From a8bcd57ebe290978809572144b261a78ca12633b Mon Sep 17 00:00:00 2001 From: serb Date: Wed, 15 Nov 2017 07:07:16 -0800 Subject: [PATCH 001/196] 8189989: Improve container portability Reviewed-by: prr, azvegint, rhalade, skoivu --- src/java.desktop/share/classes/java/awt/Container.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/java.desktop/share/classes/java/awt/Container.java b/src/java.desktop/share/classes/java/awt/Container.java index 5b3d404ff4f..88b07fe9b6e 100644 --- a/src/java.desktop/share/classes/java/awt/Container.java +++ b/src/java.desktop/share/classes/java/awt/Container.java @@ -35,6 +35,7 @@ import java.beans.PropertyChangeListener; import java.io.IOException; +import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamField; @@ -3720,8 +3721,15 @@ private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { ObjectInputStream.GetField f = s.readFields(); - Component [] tmpComponent = (Component[])f.get("component", EMPTY_ARRAY); + // array of components may not be present in the stream or may be null + Component [] tmpComponent = (Component[])f.get("component", null); + if (tmpComponent == null) { + tmpComponent = EMPTY_ARRAY; + } int ncomponents = (Integer) f.get("ncomponents", 0); + if (ncomponents < 0 || ncomponents > tmpComponent.length) { + throw new InvalidObjectException("Incorrect number of components"); + } component = new java.util.ArrayList(ncomponents); for (int i = 0; i < ncomponents; ++i) { component.add(tmpComponent[i]); From a2b7e2919333e3239c619f30e464f02026cdfcb5 Mon Sep 17 00:00:00 2001 From: weijun Date: Wed, 6 Dec 2017 21:17:19 +0800 Subject: [PATCH 002/196] 8189977: Improve permission portability Reviewed-by: rriggs --- .../share/classes/java/util/Hashtable.java | 4 +++ .../share/classes/java/util/Vector.java | 26 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/java.base/share/classes/java/util/Hashtable.java b/src/java.base/share/classes/java/util/Hashtable.java index 172343c02bf..4123718baf7 100644 --- a/src/java.base/share/classes/java/util/Hashtable.java +++ b/src/java.base/share/classes/java/util/Hashtable.java @@ -1293,6 +1293,10 @@ void readHashtable(java.io.ObjectInputStream s) length--; length = Math.min(length, origlength); + if (length < 0) { // overflow + length = origlength; + } + // Check Map.Entry[].class since it's the nearest public type to // what we're actually creating. SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Map.Entry[].class, length); diff --git a/src/java.base/share/classes/java/util/Vector.java b/src/java.base/share/classes/java/util/Vector.java index 39a40bded72..8648f3ab5f7 100644 --- a/src/java.base/share/classes/java/util/Vector.java +++ b/src/java.base/share/classes/java/util/Vector.java @@ -25,6 +25,9 @@ package java.util; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.StreamCorruptedException; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.function.UnaryOperator; @@ -1168,6 +1171,29 @@ private void shiftTailOverGap(Object[] es, int lo, int hi) { es[i] = null; } + /** + * Loads a {@code Vector} instance from a stream + * (that is, deserializes it). + * This method performs checks to ensure the consistency + * of the fields. + * + * @param in the stream + * @throws java.io.IOException if an I/O error occurs + * @throws ClassNotFoundException if the stream contains data + * of a non-existing class + */ + private void readObject(ObjectInputStream in) + throws IOException, ClassNotFoundException { + ObjectInputStream.GetField gfields = in.readFields(); + int count = gfields.get("elementCount", 0); + Object[] data = (Object[])gfields.get("elementData", null); + if (count < 0 || data == null || count > data.length) { + throw new StreamCorruptedException("Inconsistent vector internals"); + } + elementCount = count; + elementData = data.clone(); + } + /** * Saves the state of the {@code Vector} instance to a stream * (that is, serializes it). From 0b45a14b8e59a27f952139d30f7e510484b0f024 Mon Sep 17 00:00:00 2001 From: prr Date: Wed, 6 Dec 2017 14:35:58 -0800 Subject: [PATCH 003/196] 8183032: Upgrade to LittleCMS 2.9 Reviewed-by: serb, psadhukhan, mschoene, rhalade --- src/java.desktop/share/native/liblcms/LCMS.c | 6 +- .../share/native/liblcms/cmsalpha.c | 107 ++-- .../share/native/liblcms/cmscam02.c | 2 +- .../share/native/liblcms/cmscgats.c | 295 +++++----- .../share/native/liblcms/cmscnvrt.c | 15 +- .../share/native/liblcms/cmserr.c | 10 +- .../share/native/liblcms/cmsgamma.c | 458 ++++++++++----- .../share/native/liblcms/cmsgmt.c | 4 +- .../share/native/liblcms/cmshalf.c | 6 +- .../share/native/liblcms/cmsintrp.c | 62 +- .../share/native/liblcms/cmsio0.c | 71 ++- .../share/native/liblcms/cmsio1.c | 38 +- .../share/native/liblcms/cmslut.c | 129 +++-- .../share/native/liblcms/cmsmd5.c | 2 +- .../share/native/liblcms/cmsmtrx.c | 2 +- .../share/native/liblcms/cmsnamed.c | 49 +- .../share/native/liblcms/cmsopt.c | 176 +++--- .../share/native/liblcms/cmspack.c | 539 ++++++++++-------- .../share/native/liblcms/cmspcs.c | 10 +- .../share/native/liblcms/cmsplugin.c | 72 ++- .../share/native/liblcms/cmsps2.c | 63 +- .../share/native/liblcms/cmssamp.c | 2 +- src/java.desktop/share/native/liblcms/cmssm.c | 2 +- .../share/native/liblcms/cmstypes.c | 231 +++++--- .../share/native/liblcms/cmsvirt.c | 56 +- .../share/native/liblcms/cmswtpnt.c | 7 +- .../share/native/liblcms/cmsxform.c | 33 +- src/java.desktop/share/native/liblcms/lcms2.h | 68 ++- .../share/native/liblcms/lcms2_internal.h | 128 +++-- .../share/native/liblcms/lcms2_plugin.h | 6 +- 30 files changed, 1595 insertions(+), 1054 deletions(-) diff --git a/src/java.desktop/share/native/liblcms/LCMS.c b/src/java.desktop/share/native/liblcms/LCMS.c index 17c49ad826c..329801b07f4 100644 --- a/src/java.desktop/share/native/liblcms/LCMS.c +++ b/src/java.desktop/share/native/liblcms/LCMS.c @@ -391,12 +391,12 @@ JNIEXPORT jbyteArray JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagNative { lcmsProfile_p sProf = (lcmsProfile_p)jlong_to_ptr(id); TagSignature_t sig; - cmsInt32Number tagSize; + cmsUInt32Number tagSize; jbyte* dataArray = NULL; jbyteArray data = NULL; - jint bufSize; + cmsUInt32Number bufSize; sig.j = tagSig; @@ -839,7 +839,7 @@ static cmsHPROFILE _writeCookedTag(const cmsHPROFILE pfTarget, for (i = 0; i < tagCount; i++) { cmsBool isTagReady = FALSE; const cmsTagSignature s = cmsGetTagSignature(pfTarget, i); - const cmsInt32Number tagSize = cmsReadRawTag(pfTarget, s, NULL, 0); + const cmsUInt32Number tagSize = cmsReadRawTag(pfTarget, s, NULL, 0); if (s == sig) { // skip the user supplied tag diff --git a/src/java.desktop/share/native/liblcms/cmsalpha.c b/src/java.desktop/share/native/liblcms/cmsalpha.c index 277ed5598c3..d1ad61ab48d 100644 --- a/src/java.desktop/share/native/liblcms/cmsalpha.c +++ b/src/java.desktop/share/native/liblcms/cmsalpha.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -55,7 +55,6 @@ #include "lcms2_internal.h" - // Alpha copy ------------------------------------------------------------------------------------------------------------------ // Floor to byte, taking care of saturation @@ -71,16 +70,16 @@ cmsINLINE cmsUInt8Number _cmsQuickSaturateByte(cmsFloat64Number d) // Return the size in bytes of a given formatter static -int trueBytesSize(cmsUInt32Number Format) +cmsUInt32Number trueBytesSize(cmsUInt32Number Format) { - int fmt_bytes = T_BYTES(Format); + cmsUInt32Number fmt_bytes = T_BYTES(Format); - // For double, the T_BYTES field returns zero - if (fmt_bytes == 0) - return sizeof(double); + // For double, the T_BYTES field returns zero + if (fmt_bytes == 0) + return sizeof(double); - // Otherwise, it is already correct for all formats - return fmt_bytes; + // Otherwise, it is already correct for all formats + return fmt_bytes; } @@ -119,8 +118,13 @@ void from8toDBL(void* dst, const void* src) static void from8toHLF(void* dst, const void* src) { +#ifndef CMS_NO_HALF_SUPPORT cmsFloat32Number n = (*(cmsUInt8Number*)src) / 255.0f; *(cmsUInt16Number*)dst = _cmsFloat2Half(n); +#else + cmsUNUSED_PARAMETER(dst); + cmsUNUSED_PARAMETER(src); +#endif } // From 16 @@ -151,8 +155,13 @@ void from16toDBL(void* dst, const void* src) static void from16toHLF(void* dst, const void* src) { +#ifndef CMS_NO_HALF_SUPPORT cmsFloat32Number n = (*(cmsUInt16Number*)src) / 65535.0f; *(cmsUInt16Number*)dst = _cmsFloat2Half(n); +#else + cmsUNUSED_PARAMETER(dst); + cmsUNUSED_PARAMETER(src); +#endif } // From Float @@ -187,8 +196,13 @@ void fromFLTtoDBL(void* dst, const void* src) static void fromFLTtoHLF(void* dst, const void* src) { +#ifndef CMS_NO_HALF_SUPPORT cmsFloat32Number n = *(cmsFloat32Number*)src; *(cmsUInt16Number*)dst = _cmsFloat2Half(n); +#else + cmsUNUSED_PARAMETER(dst); + cmsUNUSED_PARAMETER(src); +#endif } @@ -197,27 +211,48 @@ void fromFLTtoHLF(void* dst, const void* src) static void fromHLFto8(void* dst, const void* src) { +#ifndef CMS_NO_HALF_SUPPORT cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src); *(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0f); +#else + cmsUNUSED_PARAMETER(dst); + cmsUNUSED_PARAMETER(src); +#endif + } static void fromHLFto16(void* dst, const void* src) { +#ifndef CMS_NO_HALF_SUPPORT cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src); *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f); +#else + cmsUNUSED_PARAMETER(dst); + cmsUNUSED_PARAMETER(src); +#endif } static void fromHLFtoFLT(void* dst, const void* src) { +#ifndef CMS_NO_HALF_SUPPORT *(cmsFloat32Number*)dst = _cmsHalf2Float(*(cmsUInt16Number*)src); +#else + cmsUNUSED_PARAMETER(dst); + cmsUNUSED_PARAMETER(src); +#endif } static void fromHLFtoDBL(void* dst, const void* src) { +#ifndef CMS_NO_HALF_SUPPORT *(cmsFloat64Number*)dst = (cmsFloat64Number)_cmsHalf2Float(*(cmsUInt16Number*)src); +#else + cmsUNUSED_PARAMETER(dst); + cmsUNUSED_PARAMETER(src); +#endif } // From double @@ -245,8 +280,13 @@ void fromDBLtoFLT(void* dst, const void* src) static void fromDBLtoHLF(void* dst, const void* src) { +#ifndef CMS_NO_HALF_SUPPORT cmsFloat32Number n = (cmsFloat32Number) *(cmsFloat64Number*)src; *(cmsUInt16Number*)dst = _cmsFloat2Half(n); +#else + cmsUNUSED_PARAMETER(dst); + cmsUNUSED_PARAMETER(src); +#endif } static @@ -260,21 +300,22 @@ void copy64(void* dst, const void* src) static int FormatterPos(cmsUInt32Number frm) { - int b = T_BYTES(frm); - - if (b == 0 && T_FLOAT(frm)) - return 4; // DBL - if (b == 2 && T_FLOAT(frm)) - return 2; // HLF - if (b == 4 && T_FLOAT(frm)) - return 3; // FLT - if (b == 2 && !T_FLOAT(frm)) - return 1; // 16 - if (b == 1 && !T_FLOAT(frm)) - return 0; // 8 + cmsUInt32Number b = T_BYTES(frm); - return -1; // not recognized + if (b == 0 && T_FLOAT(frm)) + return 4; // DBL +#ifndef CMS_NO_HALF_SUPPORT + if (b == 2 && T_FLOAT(frm)) + return 2; // HLF +#endif + if (b == 4 && T_FLOAT(frm)) + return 3; // FLT + if (b == 2 && !T_FLOAT(frm)) + return 1; // 16 + if (b == 1 && !T_FLOAT(frm)) + return 0; // 8 + return -1; // not recognized } // Obtains a alpha-to-alpha funmction formatter @@ -310,12 +351,12 @@ void ComputeIncrementsForChunky(cmsUInt32Number Format, cmsUInt32Number ComponentPointerIncrements[]) { cmsUInt32Number channels[cmsMAXCHANNELS]; - int extra = T_EXTRA(Format); - int nchannels = T_CHANNELS(Format); - int total_chans = nchannels + extra; - int i; - int channelSize = trueBytesSize(Format); - int pixelSize = channelSize * total_chans; + cmsUInt32Number extra = T_EXTRA(Format); + cmsUInt32Number nchannels = T_CHANNELS(Format); + cmsUInt32Number total_chans = nchannels + extra; + cmsUInt32Number i; + cmsUInt32Number channelSize = trueBytesSize(Format); + cmsUInt32Number pixelSize = channelSize * total_chans; // Sanity check if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS) @@ -368,11 +409,11 @@ void ComputeIncrementsForPlanar(cmsUInt32Number Format, cmsUInt32Number ComponentPointerIncrements[]) { cmsUInt32Number channels[cmsMAXCHANNELS]; - int extra = T_EXTRA(Format); - int nchannels = T_CHANNELS(Format); - int total_chans = nchannels + extra; - int i; - int channelSize = trueBytesSize(Format); + cmsUInt32Number extra = T_EXTRA(Format); + cmsUInt32Number nchannels = T_CHANNELS(Format); + cmsUInt32Number total_chans = nchannels + extra; + cmsUInt32Number i; + cmsUInt32Number channelSize = trueBytesSize(Format); // Sanity check if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS) diff --git a/src/java.desktop/share/native/liblcms/cmscam02.c b/src/java.desktop/share/native/liblcms/cmscam02.c index ae7038c5ea9..268677fd6f4 100644 --- a/src/java.desktop/share/native/liblcms/cmscam02.c +++ b/src/java.desktop/share/native/liblcms/cmscam02.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), diff --git a/src/java.desktop/share/native/liblcms/cmscgats.c b/src/java.desktop/share/native/liblcms/cmscgats.c index c4f4fb5d31a..ff88ffb1367 100644 --- a/src/java.desktop/share/native/liblcms/cmscgats.c +++ b/src/java.desktop/share/native/liblcms/cmscgats.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -176,23 +176,24 @@ typedef struct { SUBALLOCATOR Allocator; // String suballocator -- just to keep it fast // Parser state machine - SYMBOL sy; // Current symbol - int ch; // Current character + SYMBOL sy; // Current symbol + int ch; // Current character + + cmsInt32Number inum; // integer value + cmsFloat64Number dnum; // real value - int inum; // integer value - cmsFloat64Number dnum; // real value char id[MAXID]; // identifier char str[MAXSTR]; // string // Allowed keywords & datasets. They have visibility on whole stream - KEYVALUE* ValidKeywords; - KEYVALUE* ValidSampleID; + KEYVALUE* ValidKeywords; + KEYVALUE* ValidSampleID; char* Source; // Points to loc. being parsed - int lineno; // line counter for error reporting + cmsInt32Number lineno; // line counter for error reporting FILECTX* FileStack[MAXINCLUDE]; // Stack of files being parsed - int IncludeSP; // Include Stack Pointer + cmsInt32Number IncludeSP; // Include Stack Pointer char* MemoryBlock; // The stream if holded in memory @@ -265,65 +266,64 @@ static PROPERTY PredefinedProperties[] = { {"PROD_DATE", WRITE_STRINGIFY}, // Identifies year and month of production of the target in the form yyyy:mm. {"SERIAL", WRITE_STRINGIFY}, // Uniquely identifies individual physical target. - {"MATERIAL", WRITE_STRINGIFY}, // Identifies the material on which the target was produced using a code - // uniquely identifying th e material. This is intend ed to be used for IT8.7 - // physical targets only (i.e . IT8.7/1 a nd IT8.7/2). - - {"INSTRUMENTATION", WRITE_STRINGIFY}, // Used to report the specific instrumentation used (manufacturer and - // model number) to generate the data reported. This data will often - // provide more information about the particular data collected than an - // extensive list of specific details. This is particularly important for - // spectral data or data derived from spectrophotometry. + {"MATERIAL", WRITE_STRINGIFY}, // Identifies the material on which the target was produced using a code + // uniquely identifying th e material. This is intend ed to be used for IT8.7 + // physical targets only (i.e . IT8.7/1 a nd IT8.7/2). - {"MEASUREMENT_SOURCE", WRITE_STRINGIFY}, // Illumination used for spectral measurements. This data helps provide - // a guide to the potential for issues of paper fluorescence, etc. + {"INSTRUMENTATION", WRITE_STRINGIFY}, // Used to report the specific instrumentation used (manufacturer and + // model number) to generate the data reported. This data will often + // provide more information about the particular data collected than an + // extensive list of specific details. This is particularly important for + // spectral data or data derived from spectrophotometry. - {"PRINT_CONDITIONS", WRITE_STRINGIFY}, // Used to define the characteristics of the printed sheet being reported. - // Where standard conditions have been defined (e.g., SWOP at nominal) - // named conditions may suffice. Otherwise, detailed information is - // needed. + {"MEASUREMENT_SOURCE", WRITE_STRINGIFY}, // Illumination used for spectral measurements. This data helps provide + // a guide to the potential for issues of paper fluorescence, etc. - {"SAMPLE_BACKING", WRITE_STRINGIFY}, // Identifies the backing material used behind the sample during - // measurement. Allowed values are “black”, “white”, or {"na". + {"PRINT_CONDITIONS", WRITE_STRINGIFY}, // Used to define the characteristics of the printed sheet being reported. + // Where standard conditions have been defined (e.g., SWOP at nominal) + // named conditions may suffice. Otherwise, detailed information is + // needed. - {"CHISQ_DOF", WRITE_STRINGIFY}, // Degrees of freedom associated with the Chi squared statistic + {"SAMPLE_BACKING", WRITE_STRINGIFY}, // Identifies the backing material used behind the sample during + // measurement. Allowed values are “black”, “white”, or {"na". - // below properties are new in recent specs: + {"CHISQ_DOF", WRITE_STRINGIFY}, // Degrees of freedom associated with the Chi squared statistic + // below properties are new in recent specs: {"MEASUREMENT_GEOMETRY", WRITE_STRINGIFY}, // The type of measurement, either reflection or transmission, should be indicated - // along with details of the geometry and the aperture size and shape. For example, - // for transmission measurements it is important to identify 0/diffuse, diffuse/0, - // opal or integrating sphere, etc. For reflection it is important to identify 0/45, - // 45/0, sphere (specular included or excluded), etc. + // along with details of the geometry and the aperture size and shape. For example, + // for transmission measurements it is important to identify 0/diffuse, diffuse/0, + // opal or integrating sphere, etc. For reflection it is important to identify 0/45, + // 45/0, sphere (specular included or excluded), etc. - {"FILTER", WRITE_STRINGIFY}, // Identifies the use of physical filter(s) during measurement. Typically used to - // denote the use of filters such as none, D65, Red, Green or Blue. + {"FILTER", WRITE_STRINGIFY}, // Identifies the use of physical filter(s) during measurement. Typically used to + // denote the use of filters such as none, D65, Red, Green or Blue. - {"POLARIZATION", WRITE_STRINGIFY}, // Identifies the use of a physical polarization filter during measurement. Allowed - // values are {"yes”, “white”, “none” or “na”. + {"POLARIZATION", WRITE_STRINGIFY}, // Identifies the use of a physical polarization filter during measurement. Allowed + // values are {"yes”, “white”, “none” or “na”. - {"WEIGHTING_FUNCTION", WRITE_PAIR}, // Indicates such functions as: the CIE standard observer functions used in the - // calculation of various data parameters (2 degree and 10 degree), CIE standard - // illuminant functions used in the calculation of various data parameters (e.g., D50, - // D65, etc.), density status response, etc. If used there shall be at least one - // name-value pair following the WEIGHTING_FUNCTION tag/keyword. The first attribute - // in the set shall be {"name" and shall identify the particular parameter used. - // The second shall be {"value" and shall provide the value associated with that name. - // For ASCII data, a string containing the Name and Value attribute pairs shall follow - // the weighting function keyword. A semi-colon separates attribute pairs from each - // other and within the attribute the name and value are separated by a comma. + {"WEIGHTING_FUNCTION", WRITE_PAIR}, // Indicates such functions as: the CIE standard observer functions used in the + // calculation of various data parameters (2 degree and 10 degree), CIE standard + // illuminant functions used in the calculation of various data parameters (e.g., D50, + // D65, etc.), density status response, etc. If used there shall be at least one + // name-value pair following the WEIGHTING_FUNCTION tag/keyword. The first attribute + // in the set shall be {"name" and shall identify the particular parameter used. + // The second shall be {"value" and shall provide the value associated with that name. + // For ASCII data, a string containing the Name and Value attribute pairs shall follow + // the weighting function keyword. A semi-colon separates attribute pairs from each + // other and within the attribute the name and value are separated by a comma. - {"COMPUTATIONAL_PARAMETER", WRITE_PAIR}, // Parameter that is used in computing a value from measured data. Name is the name - // of the calculation, parameter is the name of the parameter used in the calculation - // and value is the value of the parameter. + {"COMPUTATIONAL_PARAMETER", WRITE_PAIR}, // Parameter that is used in computing a value from measured data. Name is the name + // of the calculation, parameter is the name of the parameter used in the calculation + // and value is the value of the parameter. - {"TARGET_TYPE", WRITE_STRINGIFY}, // The type of target being measured, e.g. IT8.7/1, IT8.7/3, user defined, etc. + {"TARGET_TYPE", WRITE_STRINGIFY}, // The type of target being measured, e.g. IT8.7/1, IT8.7/3, user defined, etc. - {"COLORANT", WRITE_STRINGIFY}, // Identifies the colorant(s) used in creating the target. + {"COLORANT", WRITE_STRINGIFY}, // Identifies the colorant(s) used in creating the target. - {"TABLE_DESCRIPTOR", WRITE_STRINGIFY}, // Describes the purpose or contents of a data table. + {"TABLE_DESCRIPTOR", WRITE_STRINGIFY}, // Describes the purpose or contents of a data table. - {"TABLE_NAME", WRITE_STRINGIFY} // Provides a short name for a data table. + {"TABLE_NAME", WRITE_STRINGIFY} // Provides a short name for a data table. }; #define NUMPREDEFINEDPROPS (sizeof(PredefinedProperties)/sizeof(PROPERTY)) @@ -564,13 +564,13 @@ cmsFloat64Number xpow10(int n) // Reads a Real number, tries to follow from integer number static -void ReadReal(cmsIT8* it8, int inum) +void ReadReal(cmsIT8* it8, cmsInt32Number inum) { - it8->dnum = (cmsFloat64Number) inum; + it8->dnum = (cmsFloat64Number)inum; while (isdigit(it8->ch)) { - it8->dnum = it8->dnum * 10.0 + (it8->ch - '0'); + it8->dnum = (cmsFloat64Number)it8->dnum * 10.0 + (cmsFloat64Number)(it8->ch - '0'); NextCh(it8); } @@ -583,7 +583,7 @@ void ReadReal(cmsIT8* it8, int inum) while (isdigit(it8->ch)) { - frac = frac * 10.0 + (it8->ch - '0'); + frac = frac * 10.0 + (cmsFloat64Number)(it8->ch - '0'); prec++; NextCh(it8); } @@ -594,8 +594,8 @@ void ReadReal(cmsIT8* it8, int inum) // Exponent, example 34.00E+20 if (toupper(it8->ch) == 'E') { - int e; - int sgn; + cmsInt32Number e; + cmsInt32Number sgn; NextCh(it8); sgn = 1; @@ -610,17 +610,19 @@ void ReadReal(cmsIT8* it8, int inum) NextCh(it8); } - e = 0; - while (isdigit(it8->ch)) { + e = 0; + while (isdigit(it8->ch)) { - if ((cmsFloat64Number) e * 10L < INT_MAX) - e = e * 10 + (it8->ch - '0'); + cmsInt32Number digit = (it8->ch - '0'); - NextCh(it8); - } + if ((cmsFloat64Number)e * 10.0 + (cmsFloat64Number)digit < (cmsFloat64Number)+2147483647.0) + e = e * 10 + digit; + + NextCh(it8); + } - e = sgn*e; - it8 -> dnum = it8 -> dnum * xpow10(e); + e = sgn*e; + it8->dnum = it8->dnum * xpow10(e); } } @@ -638,12 +640,12 @@ cmsFloat64Number ParseFloatNumber(const char *Buffer) if (*Buffer == '-' || *Buffer == '+') { - sign = (*Buffer == '-') ? -1 : 1; - Buffer++; + sign = (*Buffer == '-') ? -1 : 1; + Buffer++; } - while (*Buffer && isdigit((int) *Buffer)) { + while (*Buffer && isdigit((int)*Buffer)) { dnum = dnum * 10.0 + (*Buffer - '0'); if (*Buffer) Buffer++; @@ -652,11 +654,11 @@ cmsFloat64Number ParseFloatNumber(const char *Buffer) if (*Buffer == '.') { cmsFloat64Number frac = 0.0; // fraction - int prec = 0; // precission + int prec = 0; // precision if (*Buffer) Buffer++; - while (*Buffer && isdigit((int) *Buffer)) { + while (*Buffer && isdigit((int)*Buffer)) { frac = frac * 10.0 + (*Buffer - '0'); prec++; @@ -687,17 +689,19 @@ cmsFloat64Number ParseFloatNumber(const char *Buffer) if (*Buffer) Buffer++; } - e = 0; - while (*Buffer && isdigit((int) *Buffer)) { + e = 0; + while (*Buffer && isdigit((int)*Buffer)) { - if ((cmsFloat64Number) e * 10L < INT_MAX) - e = e * 10 + (*Buffer - '0'); + cmsInt32Number digit = (*Buffer - '0'); - if (*Buffer) Buffer++; - } + if ((cmsFloat64Number)e * 10.0 + digit < (cmsFloat64Number)+2147483647.0) + e = e * 10 + digit; + + if (*Buffer) Buffer++; + } - e = sgn*e; - dnum = dnum * xpow10(e); + e = sgn*e; + dnum = dnum * xpow10(e); } return sign * dnum; @@ -766,7 +770,7 @@ void InSymbol(cmsIT8* it8) if (it8->ch >= 'A' && it8->ch <= 'F') j = it8->ch -'A'+10; else j = it8->ch - '0'; - if ((long) it8->inum * 16L > (long) INT_MAX) + if ((cmsFloat64Number) it8->inum * 16.0 + (cmsFloat64Number) j > (cmsFloat64Number)+2147483647.0) { SynError(it8, "Invalid hexadecimal number"); return; @@ -787,7 +791,7 @@ void InSymbol(cmsIT8* it8) { j = it8->ch - '0'; - if ((long) it8->inum * 2L > (long) INT_MAX) + if ((cmsFloat64Number) it8->inum * 2.0 + j > (cmsFloat64Number)+2147483647.0) { SynError(it8, "Invalid binary number"); return; @@ -803,14 +807,16 @@ void InSymbol(cmsIT8* it8) while (isdigit(it8->ch)) { - if ((long) it8->inum * 10L > (long) INT_MAX) { + cmsInt32Number digit = (it8->ch - '0'); + + if ((cmsFloat64Number) it8->inum * 10.0 + (cmsFloat64Number) digit > (cmsFloat64Number) +2147483647.0) { ReadReal(it8, it8->inum); it8->sy = SDNUM; it8->dnum *= sign; return; } - it8->inum = it8->inum * 10 + (it8->ch - '0'); + it8->inum = it8->inum * 10 + digit; NextCh(it8); } @@ -1515,8 +1521,8 @@ cmsBool SetDataFormat(cmsIT8* it8, int n, const char *label) cmsBool CMSEXPORT cmsIT8SetDataFormat(cmsHANDLE h, int n, const char *Sample) { - cmsIT8* it8 = (cmsIT8*) h; - return SetDataFormat(it8, n, Sample); + cmsIT8* it8 = (cmsIT8*)h; + return SetDataFormat(it8, n, Sample); } static @@ -1541,8 +1547,8 @@ static char* GetData(cmsIT8* it8, int nSet, int nField) { TABLE* t = GetTable(it8); - int nSamples = t -> nSamples; - int nPatches = t -> nPatches; + int nSamples = t -> nSamples; + int nPatches = t -> nPatches; if (nSet >= nPatches || nField >= nSamples) return NULL; @@ -1973,67 +1979,67 @@ cmsBool HeaderSection(cmsIT8* it8) case SIDENT: - strncpy(VarName, it8->id, MAXID-1); - VarName[MAXID-1] = 0; + strncpy(VarName, it8->id, MAXID - 1); + VarName[MAXID - 1] = 0; - if (!IsAvailableOnList(it8-> ValidKeywords, VarName, NULL, &Key)) { + if (!IsAvailableOnList(it8->ValidKeywords, VarName, NULL, &Key)) { #ifdef CMS_STRICT_CGATS - return SynError(it8, "Undefined keyword '%s'", VarName); + return SynError(it8, "Undefined keyword '%s'", VarName); #else - Key = AddAvailableProperty(it8, VarName, WRITE_UNCOOKED); - if (Key == NULL) return FALSE; + Key = AddAvailableProperty(it8, VarName, WRITE_UNCOOKED); + if (Key == NULL) return FALSE; #endif - } + } - InSymbol(it8); - if (!GetVal(it8, Buffer, MAXSTR-1, "Property data expected")) return FALSE; + InSymbol(it8); + if (!GetVal(it8, Buffer, MAXSTR - 1, "Property data expected")) return FALSE; - if(Key->WriteAs != WRITE_PAIR) { - AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer, - (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED); - } - else { - const char *Subkey; - char *Nextkey; - if (it8->sy != SSTRING) - return SynError(it8, "Invalid value '%s' for property '%s'.", Buffer, VarName); - - // chop the string as a list of "subkey, value" pairs, using ';' as a separator - for (Subkey = Buffer; Subkey != NULL; Subkey = Nextkey) - { - char *Value, *temp; - - // identify token pair boundary - Nextkey = (char*) strchr(Subkey, ';'); - if(Nextkey) - *Nextkey++ = '\0'; - - // for each pair, split the subkey and the value - Value = (char*) strrchr(Subkey, ','); - if(Value == NULL) - return SynError(it8, "Invalid value for property '%s'.", VarName); - - // gobble the spaces before the coma, and the coma itself - temp = Value++; - do *temp-- = '\0'; while(temp >= Subkey && *temp == ' '); - - // gobble any space at the right - temp = Value + strlen(Value) - 1; - while(*temp == ' ') *temp-- = '\0'; - - // trim the strings from the left - Subkey += strspn(Subkey, " "); - Value += strspn(Value, " "); - - if(Subkey[0] == 0 || Value[0] == 0) - return SynError(it8, "Invalid value for property '%s'.", VarName); - AddToList(it8, &GetTable(it8)->HeaderList, VarName, Subkey, Value, WRITE_PAIR); - } + if (Key->WriteAs != WRITE_PAIR) { + AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer, + (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED); + } + else { + const char *Subkey; + char *Nextkey; + if (it8->sy != SSTRING) + return SynError(it8, "Invalid value '%s' for property '%s'.", Buffer, VarName); + + // chop the string as a list of "subkey, value" pairs, using ';' as a separator + for (Subkey = Buffer; Subkey != NULL; Subkey = Nextkey) + { + char *Value, *temp; + + // identify token pair boundary + Nextkey = (char*)strchr(Subkey, ';'); + if (Nextkey) + *Nextkey++ = '\0'; + + // for each pair, split the subkey and the value + Value = (char*)strrchr(Subkey, ','); + if (Value == NULL) + return SynError(it8, "Invalid value for property '%s'.", VarName); + + // gobble the spaces before the coma, and the coma itself + temp = Value++; + do *temp-- = '\0'; while (temp >= Subkey && *temp == ' '); + + // gobble any space at the right + temp = Value + strlen(Value) - 1; + while (*temp == ' ') *temp-- = '\0'; + + // trim the strings from the left + Subkey += strspn(Subkey, " "); + Value += strspn(Value, " "); + + if (Subkey[0] == 0 || Value[0] == 0) + return SynError(it8, "Invalid value for property '%s'.", VarName); + AddToList(it8, &GetTable(it8)->HeaderList, VarName, Subkey, Value, WRITE_PAIR); } + } - InSymbol(it8); - break; + InSymbol(it8); + break; case SEOLN: break; @@ -2062,7 +2068,6 @@ void ReadType(cmsIT8* it8, char* SheetTypePtr) while (it8->ch != '\r' && it8 ->ch != '\n' && it8->ch != '\t' && it8 -> ch != 0) { - *SheetTypePtr++= (char) it8 ->ch; if (cnt++ < MAXSTR) *SheetTypePtr++= (char) it8 ->ch; NextCh(it8); @@ -2257,10 +2262,10 @@ void CookPointers(cmsIT8* it8) // that should be something like some printable characters plus a \n // returns 0 if this is not like a CGATS, or an integer otherwise. This integer is the number of words in first line? static -int IsMyBlock(const cmsUInt8Number* Buffer, int n) +int IsMyBlock(const cmsUInt8Number* Buffer, cmsUInt32Number n) { int words = 1, space = 0, quot = 0; - int i; + cmsUInt32Number i; if (n < 10) return 0; // Too small @@ -2748,7 +2753,7 @@ int CMSEXPORT cmsIT8SetTableByLabel(cmsHANDLE hIT8, const char* cSet, const char { const char* cLabelFld; char Type[256], Label[256]; - int nTable; + cmsUInt32Number nTable; _cmsAssert(hIT8 != NULL); @@ -2761,7 +2766,7 @@ int CMSEXPORT cmsIT8SetTableByLabel(cmsHANDLE hIT8, const char* cSet, const char cLabelFld = cmsIT8GetData(hIT8, cSet, cField); if (!cLabelFld) return -1; - if (sscanf(cLabelFld, "%255s %d %255s", Label, &nTable, Type) != 3) + if (sscanf(cLabelFld, "%255s %u %255s", Label, &nTable, Type) != 3) return -1; if (ExpectedType != NULL && *ExpectedType == 0) diff --git a/src/java.desktop/share/native/liblcms/cmscnvrt.c b/src/java.desktop/share/native/liblcms/cmscnvrt.c index 2ac99be19e4..04c6419fc15 100644 --- a/src/java.desktop/share/native/liblcms/cmscnvrt.c +++ b/src/java.desktop/share/native/liblcms/cmscnvrt.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -392,11 +392,12 @@ cmsBool IsEmptyLayer(cmsMAT3* m, cmsVEC3* off) // Compute the conversion layer static -cmsBool ComputeConversion(int i, cmsHPROFILE hProfiles[], - cmsUInt32Number Intent, - cmsBool BPC, - cmsFloat64Number AdaptationState, - cmsMAT3* m, cmsVEC3* off) +cmsBool ComputeConversion(cmsUInt32Number i, + cmsHPROFILE hProfiles[], + cmsUInt32Number Intent, + cmsBool BPC, + cmsFloat64Number AdaptationState, + cmsMAT3* m, cmsVEC3* off) { int k; @@ -708,7 +709,7 @@ cmsPipeline* CMSEXPORT _cmsDefaultICCintents(cmsContext ContextID, // Translate black-preserving intents to ICC ones static -int TranslateNonICCIntents(int Intent) +cmsUInt32Number TranslateNonICCIntents(cmsUInt32Number Intent) { switch (Intent) { case INTENT_PRESERVE_K_ONLY_PERCEPTUAL: diff --git a/src/java.desktop/share/native/liblcms/cmserr.c b/src/java.desktop/share/native/liblcms/cmserr.c index fc74aa7fa01..8e1e7566e0a 100644 --- a/src/java.desktop/share/native/liblcms/cmserr.c +++ b/src/java.desktop/share/native/liblcms/cmserr.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -83,9 +83,11 @@ long int CMSEXPORT cmsfilelength(FILE* f) long int p , n; p = ftell(f); // register current file position + if (p == -1L) + return -1L; if (fseek(f, 0, SEEK_END) != 0) { - return -1; + return -1L; } n = ftell(f); @@ -115,7 +117,7 @@ cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plug // ********************************************************************************* // This is the default memory allocation function. It does a very coarse -// check of amout of memory, just to prevent exploits +// check of amount of memory, just to prevent exploits static void* _cmsMallocDefaultFn(cmsContext ContextID, cmsUInt32Number size) { @@ -222,7 +224,7 @@ void _cmsAllocMemPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsCo } else { - // To reset it, we use the default allocators, which cannot be overriden + // To reset it, we use the default allocators, which cannot be overridden ctx ->chunks[MemPlugin] = &ctx ->DefaultMemoryManager; } } diff --git a/src/java.desktop/share/native/liblcms/cmsgamma.c b/src/java.desktop/share/native/liblcms/cmsgamma.c index e940fe28feb..9f0645fb8bc 100644 --- a/src/java.desktop/share/native/liblcms/cmsgamma.c +++ b/src/java.desktop/share/native/liblcms/cmsgamma.c @@ -73,10 +73,11 @@ // The list of supported parametric curves typedef struct _cmsParametricCurvesCollection_st { - int nFunctions; // Number of supported functions in this chunk - int FunctionTypes[MAX_TYPES_IN_LCMS_PLUGIN]; // The identification types - int ParameterCount[MAX_TYPES_IN_LCMS_PLUGIN]; // Number of parameters for each function - cmsParametricCurveEvaluator Evaluator; // The evaluator + cmsUInt32Number nFunctions; // Number of supported functions in this chunk + cmsInt32Number FunctionTypes[MAX_TYPES_IN_LCMS_PLUGIN]; // The identification types + cmsUInt32Number ParameterCount[MAX_TYPES_IN_LCMS_PLUGIN]; // Number of parameters for each function + + cmsParametricCurveEvaluator Evaluator; // The evaluator struct _cmsParametricCurvesCollection_st* Next; // Next in list @@ -194,7 +195,7 @@ int IsInSet(int Type, _cmsParametricCurvesCollection* c) { int i; - for (i=0; i < c ->nFunctions; i++) + for (i=0; i < (int) c ->nFunctions; i++) if (abs(Type) == c ->FunctionTypes[i]) return i; return -1; @@ -238,20 +239,20 @@ _cmsParametricCurvesCollection *GetParametricCurveByType(cmsContext ContextID, i // no optimation curve is computed. nSegments may also be zero in the inverse case, where only the // optimization curve is given. Both features simultaneously is an error static -cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsInt32Number nEntries, - cmsInt32Number nSegments, const cmsCurveSegment* Segments, +cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsUInt32Number nEntries, + cmsUInt32Number nSegments, const cmsCurveSegment* Segments, const cmsUInt16Number* Values) { cmsToneCurve* p; - int i; + cmsUInt32Number i; // We allow huge tables, which are then restricted for smoothing operations - if (nEntries > 65530 || nEntries < 0) { + if (nEntries > 65530) { cmsSignalError(ContextID, cmsERROR_RANGE, "Couldn't create tone curve of more than 65530 entries"); return NULL; } - if (nEntries <= 0 && nSegments <= 0) { + if (nEntries == 0 && nSegments == 0) { cmsSignalError(ContextID, cmsERROR_RANGE, "Couldn't create tone curve with zero segments and no table"); return NULL; } @@ -261,7 +262,7 @@ cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsInt32Number nEntr if (!p) return NULL; // In this case, there are no segments - if (nSegments <= 0) { + if (nSegments == 0) { p ->Segments = NULL; p ->Evals = NULL; } @@ -277,7 +278,7 @@ cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsInt32Number nEntr // This 16-bit table contains a limited precision representation of the whole curve and is kept for // increasing xput on certain operations. - if (nEntries <= 0) { + if (nEntries == 0) { p ->Table16 = NULL; } else { @@ -303,7 +304,7 @@ cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsInt32Number nEntr p ->SegInterp = (cmsInterpParams**) _cmsCalloc(ContextID, nSegments, sizeof(cmsInterpParams*)); if (p ->SegInterp == NULL) goto Error; - for (i=0; i< nSegments; i++) { + for (i=0; i < nSegments; i++) { // Type 0 is a special marker for table-based curves if (Segments[i].Type == 0) @@ -359,7 +360,7 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu // Type 1 Reversed: X = Y ^1/gamma case -1: - if (R < 0) { + if (R < 0) { if (fabs(Params[0] - 1.0) < MATRIX_DET_TOLERANCE) Val = R; @@ -367,80 +368,123 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu Val = 0; } else - Val = pow(R, 1/Params[0]); + { + if (fabs(Params[0]) < MATRIX_DET_TOLERANCE) + Val = PLUS_INF; + else + Val = pow(R, 1 / Params[0]); + } break; // CIE 122-1966 // Y = (aX + b)^Gamma | X >= -b/a // Y = 0 | else case 2: - disc = -Params[2] / Params[1]; + { - if (R >= disc ) { + if (fabs(Params[1]) < MATRIX_DET_TOLERANCE) + { + Val = 0; + } + else + { + disc = -Params[2] / Params[1]; - e = Params[1]*R + Params[2]; + if (R >= disc) { - if (e > 0) - Val = pow(e, Params[0]); + e = Params[1] * R + Params[2]; + + if (e > 0) + Val = pow(e, Params[0]); + else + Val = 0; + } else Val = 0; } - else - Val = 0; - break; + } + break; // Type 2 Reversed // X = (Y ^1/g - b) / a case -2: - if (R < 0) + { + if (fabs(Params[0]) < MATRIX_DET_TOLERANCE || + fabs(Params[1]) < MATRIX_DET_TOLERANCE) + { Val = 0; + } else - Val = (pow(R, 1.0/Params[0]) - Params[2]) / Params[1]; + { + if (R < 0) + Val = 0; + else + Val = (pow(R, 1.0 / Params[0]) - Params[2]) / Params[1]; - if (Val < 0) - Val = 0; - break; + if (Val < 0) + Val = 0; + } + } + break; // IEC 61966-3 // Y = (aX + b)^Gamma | X <= -b/a // Y = c | else case 3: - disc = -Params[2] / Params[1]; - if (disc < 0) - disc = 0; + { + if (fabs(Params[1]) < MATRIX_DET_TOLERANCE) + { + Val = 0; + } + else + { + disc = -Params[2] / Params[1]; + if (disc < 0) + disc = 0; - if (R >= disc) { + if (R >= disc) { - e = Params[1]*R + Params[2]; + e = Params[1] * R + Params[2]; - if (e > 0) - Val = pow(e, Params[0]) + Params[3]; + if (e > 0) + Val = pow(e, Params[0]) + Params[3]; + else + Val = 0; + } else - Val = 0; + Val = Params[3]; } - else - Val = Params[3]; - break; + } + break; // Type 3 reversed // X=((Y-c)^1/g - b)/a | (Y>=c) // X=-b/a | (Y= Params[3]) { + { + if (fabs(Params[1]) < MATRIX_DET_TOLERANCE) + { + Val = 0; + } + else + { + if (R >= Params[3]) { - e = R - Params[3]; + e = R - Params[3]; - if (e > 0) - Val = (pow(e, 1/Params[0]) - Params[2]) / Params[1]; - else - Val = 0; - } - else { - Val = -Params[2] / Params[1]; + if (e > 0) + Val = (pow(e, 1 / Params[0]) - Params[2]) / Params[1]; + else + Val = 0; + } + else { + Val = -Params[2] / Params[1]; + } } - break; + } + break; // IEC 61966-2.1 (sRGB) @@ -464,20 +508,31 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu // X=((Y^1/g-b)/a) | Y >= (ad+b)^g // X=Y/c | Y< (ad+b)^g case -4: - e = Params[1] * Params[4] + Params[2]; - if (e < 0) - disc = 0; + { + if (fabs(Params[0]) < MATRIX_DET_TOLERANCE || + fabs(Params[1]) < MATRIX_DET_TOLERANCE || + fabs(Params[3]) < MATRIX_DET_TOLERANCE) + { + Val = 0; + } else - disc = pow(e, Params[0]); + { + e = Params[1] * Params[4] + Params[2]; + if (e < 0) + disc = 0; + else + disc = pow(e, Params[0]); - if (R >= disc) { + if (R >= disc) { - Val = (pow(R, 1.0/Params[0]) - Params[2]) / Params[1]; - } - else { - Val = R / Params[3]; + Val = (pow(R, 1.0 / Params[0]) - Params[2]) / Params[1]; + } + else { + Val = R / Params[3]; + } } - break; + } + break; // Y = (aX + b)^Gamma + e | X >= d @@ -501,20 +556,29 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu // X=((Y-e)1/g-b)/a | Y >=(ad+b)^g+e), cd+f // X=(Y-f)/c | else case -5: - - disc = Params[3] * Params[4] + Params[6]; - if (R >= disc) { - - e = R - Params[5]; - if (e < 0) - Val = 0; - else - Val = (pow(e, 1.0/Params[0]) - Params[2]) / Params[1]; + { + if (fabs(Params[1]) < MATRIX_DET_TOLERANCE || + fabs(Params[3]) < MATRIX_DET_TOLERANCE) + { + Val = 0; } - else { - Val = (R - Params[6]) / Params[3]; + else + { + disc = Params[3] * Params[4] + Params[6]; + if (R >= disc) { + + e = R - Params[5]; + if (e < 0) + Val = 0; + else + Val = (pow(e, 1.0 / Params[0]) - Params[2]) / Params[1]; + } + else { + Val = (R - Params[6]) / Params[3]; + } } - break; + } + break; // Types 6,7,8 comes from segmented curves as described in ICCSpecRevision_02_11_06_Float.pdf @@ -532,12 +596,21 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu // ((Y - c) ^1/Gamma - b) / a case -6: - e = R - Params[3]; - if (e < 0) + { + if (fabs(Params[1]) < MATRIX_DET_TOLERANCE) + { Val = 0; + } else - Val = (pow(e, 1.0/Params[0]) - Params[2]) / Params[1]; - break; + { + e = R - Params[3]; + if (e < 0) + Val = 0; + else + Val = (pow(e, 1.0 / Params[0]) - Params[2]) / Params[1]; + } + } + break; // Y = a * log (b * X^Gamma + c) + d @@ -554,8 +627,19 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu // pow(10, (Y-d) / a) = b * X ^Gamma + c // pow((pow(10, (Y-d) / a) - c) / b, 1/g) = X case -7: - Val = pow((pow(10.0, (R-Params[4]) / Params[1]) - Params[3]) / Params[2], 1.0 / Params[0]); - break; + { + if (fabs(Params[0]) < MATRIX_DET_TOLERANCE || + fabs(Params[1]) < MATRIX_DET_TOLERANCE || + fabs(Params[2]) < MATRIX_DET_TOLERANCE) + { + Val = 0; + } + else + { + Val = pow((pow(10.0, (R - Params[4]) / Params[1]) - Params[3]) / Params[2], 1.0 / Params[0]); + } + } + break; //Y = a * b^(c*X+d) + e @@ -571,12 +655,25 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu disc = R - Params[4]; if (disc < 0) Val = 0; else - Val = (log(disc / Params[0]) / log(Params[1]) - Params[3]) / Params[2]; + { + if (fabs(Params[0]) < MATRIX_DET_TOLERANCE || + fabs(Params[2]) < MATRIX_DET_TOLERANCE) + { + Val = 0; + } + else + { + Val = (log(disc / Params[0]) / log(Params[1]) - Params[3]) / Params[2]; + } + } break; // S-Shaped: (1 - (1-x)^1/g)^1/g case 108: - Val = pow(1.0 - pow(1 - R, 1/Params[0]), 1/Params[0]); + if (fabs(Params[0]) < MATRIX_DET_TOLERANCE) + Val = 0; + else + Val = pow(1.0 - pow(1 - R, 1/Params[0]), 1/Params[0]); break; // y = (1 - (1-x)^1/g)^1/g @@ -596,33 +693,45 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu return Val; } -// Evaluate a segmented function for a single value. Return -1 if no valid segment found . +// Evaluate a segmented function for a single value. Return -Inf if no valid segment found . // If fn type is 0, perform an interpolation on the table static cmsFloat64Number EvalSegmentedFn(const cmsToneCurve *g, cmsFloat64Number R) { int i; + cmsFloat32Number Out32; + cmsFloat64Number Out; - for (i = g ->nSegments-1; i >= 0 ; --i) { + for (i = (int) g->nSegments - 1; i >= 0; --i) { // Check for domain - if ((R > g ->Segments[i].x0) && (R <= g ->Segments[i].x1)) { + if ((R > g->Segments[i].x0) && (R <= g->Segments[i].x1)) { // Type == 0 means segment is sampled - if (g ->Segments[i].Type == 0) { + if (g->Segments[i].Type == 0) { - cmsFloat32Number R1 = (cmsFloat32Number) (R - g ->Segments[i].x0) / (g ->Segments[i].x1 - g ->Segments[i].x0); - cmsFloat32Number Out; + cmsFloat32Number R1 = (cmsFloat32Number)(R - g->Segments[i].x0) / (g->Segments[i].x1 - g->Segments[i].x0); // Setup the table (TODO: clean that) - g ->SegInterp[i]-> Table = g ->Segments[i].SampledPoints; + g->SegInterp[i]->Table = g->Segments[i].SampledPoints; - g ->SegInterp[i] -> Interpolation.LerpFloat(&R1, &Out, g ->SegInterp[i]); + g->SegInterp[i]->Interpolation.LerpFloat(&R1, &Out32, g->SegInterp[i]); + Out = (cmsFloat64Number) Out32; - return Out; } + else { + Out = g->Evals[i](g->Segments[i].Type, g->Segments[i].Params, R); + } + + if (isinf(Out)) + return PLUS_INF; else - return g ->Evals[i](g->Segments[i].Type, g ->Segments[i].Params, R); + { + if (isinf(-Out)) + return MINUS_INF; + } + + return Out; } } @@ -645,13 +754,13 @@ const cmsUInt16Number* CMSEXPORT cmsGetToneCurveEstimatedTable(const cmsToneCurv // Create an empty gamma curve, by using tables. This specifies only the limited-precision part, and leaves the // floating point description empty. -cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurve16(cmsContext ContextID, cmsInt32Number nEntries, const cmsUInt16Number Values[]) +cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurve16(cmsContext ContextID, cmsUInt32Number nEntries, const cmsUInt16Number Values[]) { return AllocateToneCurveStruct(ContextID, nEntries, 0, NULL, Values); } static -int EntriesByGamma(cmsFloat64Number Gamma) +cmsUInt32Number EntriesByGamma(cmsFloat64Number Gamma) { if (fabs(Gamma - 1.0) < 0.001) return 2; return 4096; @@ -660,12 +769,12 @@ int EntriesByGamma(cmsFloat64Number Gamma) // Create a segmented gamma, fill the table cmsToneCurve* CMSEXPORT cmsBuildSegmentedToneCurve(cmsContext ContextID, - cmsInt32Number nSegments, const cmsCurveSegment Segments[]) + cmsUInt32Number nSegments, const cmsCurveSegment Segments[]) { - int i; + cmsUInt32Number i; cmsFloat64Number R, Val; cmsToneCurve* g; - int nGridPoints = 4096; + cmsUInt32Number nGridPoints = 4096; _cmsAssert(Segments != NULL); @@ -680,7 +789,7 @@ cmsToneCurve* CMSEXPORT cmsBuildSegmentedToneCurve(cmsContext ContextID, // Once we have the floating point version, we can approximate a 16 bit table of 4096 entries // for performance reasons. This table would normally not be used except on 8/16 bits transforms. - for (i=0; i < nGridPoints; i++) { + for (i = 0; i < nGridPoints; i++) { R = (cmsFloat64Number) i / (nGridPoints-1); @@ -893,7 +1002,7 @@ int GetInterval(cmsFloat64Number In, const cmsUInt16Number LutTable[], const str if (LutTable[0] < LutTable[p ->Domain[0]]) { // Table is overall ascending - for (i=p->Domain[0]-1; i >=0; --i) { + for (i = (int) p->Domain[0] - 1; i >= 0; --i) { y0 = LutTable[i]; y1 = LutTable[i+1]; @@ -928,7 +1037,7 @@ int GetInterval(cmsFloat64Number In, const cmsUInt16Number LutTable[], const str } // Reverse a gamma table -cmsToneCurve* CMSEXPORT cmsReverseToneCurveEx(cmsInt32Number nResultSamples, const cmsToneCurve* InCurve) +cmsToneCurve* CMSEXPORT cmsReverseToneCurveEx(cmsUInt32Number nResultSamples, const cmsToneCurve* InCurve) { cmsToneCurve *out; cmsFloat64Number a = 0, b = 0, y, x1, y1, x2, y2; @@ -957,7 +1066,7 @@ cmsToneCurve* CMSEXPORT cmsReverseToneCurveEx(cmsInt32Number nResultSamples, con Ascending = !cmsIsToneCurveDescending(InCurve); // Iterate across Y axis - for (i=0; i < nResultSamples; i++) { + for (i=0; i < (int) nResultSamples; i++) { y = (cmsFloat64Number) i * 65535.0 / (nResultSamples - 1); @@ -1012,7 +1121,8 @@ cmsToneCurve* CMSEXPORT cmsReverseToneCurve(const cmsToneCurve* InGamma) // Output: smoothed vector (z): vector from 1 to m. static -cmsBool smooth2(cmsContext ContextID, cmsFloat32Number w[], cmsFloat32Number y[], cmsFloat32Number z[], cmsFloat32Number lambda, int m) +cmsBool smooth2(cmsContext ContextID, cmsFloat32Number w[], cmsFloat32Number y[], + cmsFloat32Number z[], cmsFloat32Number lambda, int m) { int i, i1, i2; cmsFloat32Number *c, *d, *e; @@ -1071,73 +1181,121 @@ cmsBool smooth2(cmsContext ContextID, cmsFloat32Number w[], cmsFloat32Number y[] // Smooths a curve sampled at regular intervals. cmsBool CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda) { - cmsFloat32Number w[MAX_NODES_IN_CURVE], y[MAX_NODES_IN_CURVE], z[MAX_NODES_IN_CURVE]; - int i, nItems, Zeros, Poles; + cmsBool SuccessStatus = TRUE; + cmsFloat32Number *w, *y, *z; + cmsUInt32Number i, nItems, Zeros, Poles; - if (Tab == NULL) return FALSE; - - if (cmsIsToneCurveLinear(Tab)) return TRUE; // Nothing to do - - nItems = Tab -> nEntries; - - if (nItems >= MAX_NODES_IN_CURVE) { - cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: too many points."); - return FALSE; - } - - memset(w, 0, nItems * sizeof(cmsFloat32Number)); - memset(y, 0, nItems * sizeof(cmsFloat32Number)); - memset(z, 0, nItems * sizeof(cmsFloat32Number)); - - for (i=0; i < nItems; i++) + if (Tab != NULL && Tab->InterpParams != NULL) { - y[i+1] = (cmsFloat32Number) Tab -> Table16[i]; - w[i+1] = 1.0; - } + cmsContext ContextID = Tab->InterpParams->ContextID; + + if (!cmsIsToneCurveLinear(Tab)) // Only non-linear curves need smoothing + { + nItems = Tab->nEntries; + if (nItems < MAX_NODES_IN_CURVE) + { + // Allocate one more item than needed + w = (cmsFloat32Number *)_cmsCalloc(ContextID, nItems + 1, sizeof(cmsFloat32Number)); + y = (cmsFloat32Number *)_cmsCalloc(ContextID, nItems + 1, sizeof(cmsFloat32Number)); + z = (cmsFloat32Number *)_cmsCalloc(ContextID, nItems + 1, sizeof(cmsFloat32Number)); + + if (w != NULL && y != NULL && z != NULL) // Ensure no memory allocation failure + { + memset(w, 0, (nItems + 1) * sizeof(cmsFloat32Number)); + memset(y, 0, (nItems + 1) * sizeof(cmsFloat32Number)); + memset(z, 0, (nItems + 1) * sizeof(cmsFloat32Number)); + + for (i = 0; i < nItems; i++) + { + y[i + 1] = (cmsFloat32Number)Tab->Table16[i]; + w[i + 1] = 1.0; + } + + if (smooth2(ContextID, w, y, z, (cmsFloat32Number)lambda, (int)nItems)) + { + // Do some reality - checking... + + Zeros = Poles = 0; + for (i = nItems; i > 1; --i) + { + if (z[i] == 0.) Zeros++; + if (z[i] >= 65535.) Poles++; + if (z[i] < z[i - 1]) + { + cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Non-Monotonic."); + SuccessStatus = FALSE; + break; + } + } + + if (SuccessStatus && Zeros > (nItems / 3)) + { + cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly zeros."); + SuccessStatus = FALSE; + } + + if (SuccessStatus && Poles > (nItems / 3)) + { + cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly poles."); + SuccessStatus = FALSE; + } + + if (SuccessStatus) // Seems ok + { + for (i = 0; i < nItems; i++) + { + // Clamp to cmsUInt16Number + Tab->Table16[i] = _cmsQuickSaturateWord(z[i + 1]); + } + } + } + else // Could not smooth + { + cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Function smooth2 failed."); + SuccessStatus = FALSE; + } + } + else // One or more buffers could not be allocated + { + cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Could not allocate memory."); + SuccessStatus = FALSE; + } - if (!smooth2(Tab ->InterpParams->ContextID, w, y, z, (cmsFloat32Number) lambda, nItems)) return FALSE; + if (z != NULL) + _cmsFree(ContextID, z); - // Do some reality - checking... - Zeros = Poles = 0; - for (i=nItems; i > 1; --i) { + if (y != NULL) + _cmsFree(ContextID, y); - if (z[i] == 0.) Zeros++; - if (z[i] >= 65535.) Poles++; - if (z[i] < z[i-1]) { - cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Non-Monotonic."); - return FALSE; + if (w != NULL) + _cmsFree(ContextID, w); + } + else // too many items in the table + { + cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Too many points."); + SuccessStatus = FALSE; + } } } - - if (Zeros > (nItems / 3)) { - cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly zeros."); - return FALSE; - } - if (Poles > (nItems / 3)) { - cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly poles."); - return FALSE; - } - - // Seems ok - for (i=0; i < nItems; i++) { - - // Clamp to cmsUInt16Number - Tab -> Table16[i] = _cmsQuickSaturateWord(z[i+1]); + else // Tab parameter or Tab->InterpParams is NULL + { + // Can't signal an error here since the ContextID is not known at this point + SuccessStatus = FALSE; } - return TRUE; + return SuccessStatus; } // Is a table linear? Do not use parametric since we cannot guarantee some weird parameters resulting // in a linear table. This way assures it is linear in 12 bits, which should be enought in most cases. cmsBool CMSEXPORT cmsIsToneCurveLinear(const cmsToneCurve* Curve) { - cmsUInt32Number i; + int i; int diff; _cmsAssert(Curve != NULL); - for (i=0; i < Curve ->nEntries; i++) { + for (i=0; i < (int) Curve ->nEntries; i++) { diff = abs((int) Curve->Table16[i] - (int) _cmsQuantizeVal(i, Curve ->nEntries)); if (diff > 0x0f) @@ -1150,7 +1308,7 @@ cmsBool CMSEXPORT cmsIsToneCurveLinear(const cmsToneCurve* Curve) // Same, but for monotonicity cmsBool CMSEXPORT cmsIsToneCurveMonotonic(const cmsToneCurve* t) { - int n; + cmsUInt32Number n; int i, last; cmsBool lDescending; @@ -1167,7 +1325,7 @@ cmsBool CMSEXPORT cmsIsToneCurveMonotonic(const cmsToneCurve* t) last = t ->Table16[0]; - for (i = 1; i < n; i++) { + for (i = 1; i < (int) n; i++) { if (t ->Table16[i] - last > 2) // We allow some ripple return FALSE; @@ -1180,7 +1338,7 @@ cmsBool CMSEXPORT cmsIsToneCurveMonotonic(const cmsToneCurve* t) last = t ->Table16[n-1]; - for (i = n-2; i >= 0; --i) { + for (i = (int) n - 2; i >= 0; --i) { if (t ->Table16[i] - last > 2) return FALSE; diff --git a/src/java.desktop/share/native/liblcms/cmsgmt.c b/src/java.desktop/share/native/liblcms/cmsgmt.c index 81254c2ad9b..1b464af0fa8 100644 --- a/src/java.desktop/share/native/liblcms/cmsgmt.c +++ b/src/java.desktop/share/native/liblcms/cmsgmt.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -326,7 +326,7 @@ cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID, cmsStage* CLUT; cmsUInt32Number dwFormat; GAMUTCHAIN Chain; - int nChannels, nGridpoints; + cmsUInt32Number nChannels, nGridpoints; cmsColorSpaceSignature ColorSpace; cmsUInt32Number i; cmsHPROFILE ProfileList[256]; diff --git a/src/java.desktop/share/native/liblcms/cmshalf.c b/src/java.desktop/share/native/liblcms/cmshalf.c index ddcaf48b8b4..287fcb5e5f1 100644 --- a/src/java.desktop/share/native/liblcms/cmshalf.c +++ b/src/java.desktop/share/native/liblcms/cmshalf.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -532,7 +532,7 @@ static cmsUInt8Number Shift[512] = { 0x18, 0x18, 0x18, 0x18, 0x0d }; -cmsFloat32Number _cmsHalf2Float(cmsUInt16Number h) +cmsFloat32Number CMSEXPORT _cmsHalf2Float(cmsUInt16Number h) { union { cmsFloat32Number flt; @@ -545,7 +545,7 @@ cmsFloat32Number _cmsHalf2Float(cmsUInt16Number h) return out.flt; } -cmsUInt16Number _cmsFloat2Half(cmsFloat32Number flt) +cmsUInt16Number CMSEXPORT _cmsFloat2Half(cmsFloat32Number flt) { union { cmsFloat32Number flt; diff --git a/src/java.desktop/share/native/liblcms/cmsintrp.c b/src/java.desktop/share/native/liblcms/cmsintrp.c index aa96cbb440b..6a3c7f85a7c 100644 --- a/src/java.desktop/share/native/liblcms/cmsintrp.c +++ b/src/java.desktop/share/native/liblcms/cmsintrp.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -58,6 +58,13 @@ // This module incorporates several interpolation routines, for 1 to 8 channels on input and // up to 65535 channels on output. The user may change those by using the interpolation plug-in +// Some people may want to compile as C++ with all warnings on, in this case make compiler silent +#ifdef _MSC_VER +# if (_MSC_VER >= 1400) +# pragma warning( disable : 4365 ) +# endif +#endif + // Interpolation routines by default static cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags); @@ -131,12 +138,12 @@ cmsBool _cmsSetInterpolationRoutine(cmsContext ContextID, cmsInterpParams* p) // This function precalculates as many parameters as possible to speed up the interpolation. cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID, const cmsUInt32Number nSamples[], - int InputChan, int OutputChan, + cmsUInt32Number InputChan, cmsUInt32Number OutputChan, const void *Table, cmsUInt32Number dwFlags) { cmsInterpParams* p; - int i; + cmsUInt32Number i; // Check for maximum inputs if (InputChan > MAX_INPUT_DIMENSIONS) { @@ -180,7 +187,8 @@ cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID, // This one is a wrapper on the anterior, but assuming all directions have same number of nodes -cmsInterpParams* _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags) +cmsInterpParams* CMSEXPORT _cmsComputeInterpParams(cmsContext ContextID, cmsUInt32Number nSamples, + cmsUInt32Number InputChan, cmsUInt32Number OutputChan, const void* Table, cmsUInt32Number dwFlags) { int i; cmsUInt32Number Samples[MAX_INPUT_DIMENSIONS]; @@ -195,7 +203,7 @@ cmsInterpParams* _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int // Free all associated memory -void _cmsFreeInterpParams(cmsInterpParams* p) +void CMSEXPORT _cmsFreeInterpParams(cmsInterpParams* p) { if (p != NULL) _cmsFree(p ->ContextID, p); } @@ -244,7 +252,7 @@ void LinLerp1D(register const cmsUInt16Number Value[], // To prevent out of bounds indexing cmsINLINE cmsFloat32Number fclamp(cmsFloat32Number v) { - return v < 0.0f || v != v ? 0.0f : (v > 1.0f ? 1.0f : v); + return ((v < 1.0e-9f) || isnan(v)) ? 0.0f : (v > 1.0f ? 1.0f : v); } // Floating-point version of 1D interpolation @@ -381,10 +389,10 @@ void BilinearInterpFloat(const cmsFloat32Number Input[], y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0; X0 = p -> opta[1] * x0; - X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[1]); + X1 = X0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[1]); Y0 = p -> opta[0] * y0; - Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[0]); + Y1 = Y0 + (fclamp(Input[1]) >= 1.0 ? 0 : p->opta[0]); for (OutChan = 0; OutChan < TotalOut; OutChan++) { @@ -493,18 +501,18 @@ void TrilinearInterpFloat(const cmsFloat32Number Input[], py = fclamp(Input[1]) * p->Domain[1]; pz = fclamp(Input[2]) * p->Domain[2]; - x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0; - y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0; - z0 = (int) _cmsQuickFloor(pz); fz = pz - (cmsFloat32Number) z0; + x0 = (int) floor(px); fx = px - (cmsFloat32Number) x0; // We need full floor funcionality here + y0 = (int) floor(py); fy = py - (cmsFloat32Number) y0; + z0 = (int) floor(pz); fz = pz - (cmsFloat32Number) z0; X0 = p -> opta[2] * x0; - X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]); + X1 = X0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[2]); Y0 = p -> opta[1] * y0; - Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]); + Y1 = Y0 + (fclamp(Input[1]) >= 1.0 ? 0 : p->opta[1]); Z0 = p -> opta[0] * z0; - Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]); + Z1 = Z0 + (fclamp(Input[2]) >= 1.0 ? 0 : p->opta[0]); for (OutChan = 0; OutChan < TotalOut; OutChan++) { @@ -637,19 +645,19 @@ void TetrahedralInterpFloat(const cmsFloat32Number Input[], py = fclamp(Input[1]) * p->Domain[1]; pz = fclamp(Input[2]) * p->Domain[2]; - x0 = (int) _cmsQuickFloor(px); rx = (px - (cmsFloat32Number) x0); - y0 = (int) _cmsQuickFloor(py); ry = (py - (cmsFloat32Number) y0); - z0 = (int) _cmsQuickFloor(pz); rz = (pz - (cmsFloat32Number) z0); + x0 = (int) floor(px); rx = (px - (cmsFloat32Number) x0); // We need full floor functionality here + y0 = (int) floor(py); ry = (py - (cmsFloat32Number) y0); + z0 = (int) floor(pz); rz = (pz - (cmsFloat32Number) z0); X0 = p -> opta[2] * x0; - X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]); + X1 = X0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[2]); Y0 = p -> opta[1] * y0; - Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]); + Y1 = Y0 + (fclamp(Input[1]) >= 1.0 ? 0 : p->opta[1]); Z0 = p -> opta[0] * z0; - Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]); + Z1 = Z0 + (fclamp(Input[2]) >= 1.0 ? 0 : p->opta[0]); for (OutChan=0; OutChan < TotalOut; OutChan++) { @@ -952,13 +960,13 @@ void Eval4Inputs(register const cmsUInt16Number Input[], c3 = DENS(X0, Y0, Z1) - c0; } - else { + else { c1 = c2 = c3 = 0; } Rest = c1 * rx + c2 * ry + c3 * rz; - Tmp1[OutChan] = (cmsUInt16Number) ( c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest))); + Tmp1[OutChan] = (cmsUInt16Number)(c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest))); } @@ -1057,7 +1065,7 @@ void Eval4InputsFloat(const cmsFloat32Number Input[], rest = pk - (cmsFloat32Number) k0; K0 = p -> opta[3] * k0; - K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[3]); + K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[3]); p1 = *p; memmove(&p1.Domain[0], &p ->Domain[1], 3*sizeof(cmsUInt32Number)); @@ -1144,7 +1152,7 @@ void Eval5InputsFloat(const cmsFloat32Number Input[], rest = pk - (cmsFloat32Number) k0; K0 = p -> opta[4] * k0; - K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[4]); + K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[4]); p1 = *p; memmove(&p1.Domain[0], &p ->Domain[1], 4*sizeof(cmsUInt32Number)); @@ -1231,7 +1239,7 @@ void Eval6InputsFloat(const cmsFloat32Number Input[], rest = pk - (cmsFloat32Number) k0; K0 = p -> opta[5] * k0; - K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[5]); + K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[5]); p1 = *p; memmove(&p1.Domain[0], &p ->Domain[1], 5*sizeof(cmsUInt32Number)); @@ -1316,7 +1324,7 @@ void Eval7InputsFloat(const cmsFloat32Number Input[], rest = pk - (cmsFloat32Number) k0; K0 = p -> opta[6] * k0; - K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[6]); + K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[6]); p1 = *p; memmove(&p1.Domain[0], &p ->Domain[1], 6*sizeof(cmsUInt32Number)); @@ -1401,7 +1409,7 @@ void Eval8InputsFloat(const cmsFloat32Number Input[], rest = pk - (cmsFloat32Number) k0; K0 = p -> opta[7] * k0; - K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[7]); + K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[7]); p1 = *p; memmove(&p1.Domain[0], &p ->Domain[1], 7*sizeof(cmsUInt32Number)); diff --git a/src/java.desktop/share/native/liblcms/cmsio0.c b/src/java.desktop/share/native/liblcms/cmsio0.c index f86f2e738d8..3dbfcb37ebf 100644 --- a/src/java.desktop/share/native/liblcms/cmsio0.c +++ b/src/java.desktop/share/native/liblcms/cmsio0.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -366,21 +366,27 @@ cmsBool FileSeek(cmsIOHANDLER* iohandler, cmsUInt32Number offset) return TRUE; } -// Returns file pointer position +// Returns file pointer position or 0 on error, which is also a valid position. static cmsUInt32Number FileTell(cmsIOHANDLER* iohandler) { - return (cmsUInt32Number) ftell((FILE*)iohandler ->stream); + long t = ftell((FILE*)iohandler ->stream); + if (t == -1L) { + cmsSignalError(iohandler->ContextID, cmsERROR_FILE, "Tell error; probably corrupted file"); + return 0; + } + + return (cmsUInt32Number)t; } // Writes data to stream, also keeps used space for further reference. Returns TRUE on success, FALSE on error static cmsBool FileWrite(cmsIOHANDLER* iohandler, cmsUInt32Number size, const void* Buffer) { - if (size == 0) return TRUE; // We allow to write 0 bytes, but nothing is written + if (size == 0) return TRUE; // We allow to write 0 bytes, but nothing is written - iohandler->UsedSpace += size; - return (fwrite(Buffer, size, 1, (FILE*) iohandler->stream) == 1); + iohandler->UsedSpace += size; + return (fwrite(Buffer, size, 1, (FILE*)iohandler->stream) == 1); } // Closes the file @@ -548,7 +554,7 @@ cmsInt32Number CMSEXPORT cmsGetTagCount(cmsHPROFILE hProfile) _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; if (Icc == NULL) return -1; - return Icc->TagCount; + return (cmsInt32Number) Icc->TagCount; } // Return the tag signature of a given tag number @@ -566,9 +572,9 @@ cmsTagSignature CMSEXPORT cmsGetTagSignature(cmsHPROFILE hProfile, cmsUInt32Numb static int SearchOneTag(_cmsICCPROFILE* Profile, cmsTagSignature sig) { - cmsUInt32Number i; + int i; - for (i=0; i < Profile -> TagCount; i++) { + for (i=0; i < (int) Profile -> TagCount; i++) { if (sig == Profile -> TagNames[i]) return i; @@ -662,7 +668,7 @@ cmsBool _cmsNewTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, int* NewPos) return FALSE; } - *NewPos = Icc ->TagCount; + *NewPos = (int) Icc ->TagCount; Icc -> TagCount++; } @@ -693,10 +699,10 @@ cmsUInt32Number _validatedVersion(cmsUInt32Number DWord) cmsUInt8Number temp2; if (*pByte > 0x09) *pByte = (cmsUInt8Number) 0x09; - temp1 = *(pByte+1) & 0xf0; - temp2 = *(pByte+1) & 0x0f; - if (temp1 > 0x90) temp1 = 0x90; - if (temp2 > 0x09) temp2 = 0x09; + temp1 = (cmsUInt8Number) (*(pByte+1) & 0xf0); + temp2 = (cmsUInt8Number) (*(pByte+1) & 0x0f); + if (temp1 > 0x90U) temp1 = 0x90U; + if (temp2 > 0x09U) temp2 = 0x09U; *(pByte+1) = (cmsUInt8Number)(temp1 | temp2); *(pByte+2) = (cmsUInt8Number)0; *(pByte+3) = (cmsUInt8Number)0; @@ -804,7 +810,7 @@ cmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace) cmsICCHeader Header; cmsUInt32Number i; cmsTagEntry Tag; - cmsInt32Number Count = 0; + cmsUInt32Number Count; Header.size = _cmsAdjustEndianess32(UsedSpace); Header.cmmId = _cmsAdjustEndianess32(lcmsSignature); @@ -835,9 +841,9 @@ cmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace) Header.renderingIntent = _cmsAdjustEndianess32(Icc -> RenderingIntent); // Illuminant is always D50 - Header.illuminant.X = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(cmsD50_XYZ()->X)); - Header.illuminant.Y = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(cmsD50_XYZ()->Y)); - Header.illuminant.Z = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(cmsD50_XYZ()->Z)); + Header.illuminant.X = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(cmsD50_XYZ()->X)); + Header.illuminant.Y = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(cmsD50_XYZ()->Y)); + Header.illuminant.Z = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(cmsD50_XYZ()->Z)); // Created by LittleCMS (that's me!) Header.creator = _cmsAdjustEndianess32(lcmsSignature); @@ -853,6 +859,7 @@ cmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace) // Saves Tag directory // Get true count + Count = 0; for (i=0; i < Icc -> TagCount; i++) { if (Icc ->TagNames[i] != (cmsTagSignature) 0) Count++; @@ -865,9 +872,9 @@ cmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace) if (Icc ->TagNames[i] == (cmsTagSignature) 0) continue; // It is just a placeholder - Tag.sig = (cmsTagSignature) _cmsAdjustEndianess32((cmsInt32Number) Icc -> TagNames[i]); - Tag.offset = _cmsAdjustEndianess32((cmsInt32Number) Icc -> TagOffsets[i]); - Tag.size = _cmsAdjustEndianess32((cmsInt32Number) Icc -> TagSizes[i]); + Tag.sig = (cmsTagSignature) _cmsAdjustEndianess32((cmsUInt32Number) Icc -> TagNames[i]); + Tag.offset = _cmsAdjustEndianess32((cmsUInt32Number) Icc -> TagOffsets[i]); + Tag.size = _cmsAdjustEndianess32((cmsUInt32Number) Icc -> TagSizes[i]); if (!Icc ->IOhandler -> Write(Icc-> IOhandler, sizeof(cmsTagEntry), &Tag)) return FALSE; } @@ -1176,7 +1183,7 @@ cmsHPROFILE CMSEXPORT cmsOpenProfileFromMemTHR(cmsContext ContextID, const void* NewIcc = (_cmsICCPROFILE*) hEmpty; // Ok, in this case const void* is casted to void* just because open IO handler - // shares read and writting modes. Don't abuse this feature! + // shares read and writing modes. Don't abuse this feature! NewIcc ->IOhandler = cmsOpenIOhandlerFromMem(ContextID, (void*) MemPtr, dwSize, "r"); if (NewIcc ->IOhandler == NULL) goto Error; @@ -1466,7 +1473,7 @@ cmsBool CMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile) // Was open in write mode? if (Icc ->IsWrite) { - Icc ->IsWrite = FALSE; // Assure no further writting + Icc ->IsWrite = FALSE; // Assure no further writing rc &= cmsSaveProfileToFile(hProfile, Icc ->IOhandler->PhysicalFile); } @@ -1543,11 +1550,15 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig) // If the element is already in memory, return the pointer if (Icc -> TagPtrs[n]) { - if (Icc -> TagTypeHandlers[n] == NULL) goto Error; - BaseType = Icc -> TagTypeHandlers[n]->Signature; + if (Icc->TagTypeHandlers[n] == NULL) goto Error; + + // Sanity check + BaseType = Icc->TagTypeHandlers[n]->Signature; if (BaseType == 0) goto Error; - TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, sig); + + TagDescriptor = _cmsGetTagDescriptor(Icc->ContextID, sig); if (TagDescriptor == NULL) goto Error; + if (!IsTypeSupported(TagDescriptor, BaseType)) goto Error; if (Icc ->TagSaveAsRaw[n]) goto Error; // We don't support read raw tags as cooked @@ -1560,6 +1571,8 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig) Offset = Icc -> TagOffsets[n]; TagSize = Icc -> TagSizes[n]; + if (TagSize < 8) goto Error; + // Seek to its location if (!io -> Seek(io, Offset)) goto Error; @@ -1583,7 +1596,7 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig) if (!IsTypeSupported(TagDescriptor, BaseType)) goto Error; - TagSize -= 8; // Alredy read by the type base logic + TagSize -= 8; // Alredy read by the type base logic // Get type handler TypeHandler = _cmsGetTagTypeHandler(Icc ->ContextID, BaseType); @@ -1772,7 +1785,7 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v // raw data written does not exactly correspond with the raw data proposed to cmsWriteRaw data, but this approach allows // to write a tag as raw data and the read it as handled. -cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, void* data, cmsUInt32Number BufferSize) +cmsUInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, void* data, cmsUInt32Number BufferSize) { _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; void *Object; @@ -1890,7 +1903,7 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig } // Similar to the anterior. This function allows to write directly to the ICC profile any data, without -// checking anything. As a rule, mixing Raw with cooked doesn't work, so writting a tag as raw and then reading +// checking anything. As a rule, mixing Raw with cooked doesn't work, so writing a tag as raw and then reading // it as cooked without serializing does result into an error. If that is what you want, you will need to dump // the profile to memry or disk and then reopen it. cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data, cmsUInt32Number Size) diff --git a/src/java.desktop/share/native/liblcms/cmsio1.c b/src/java.desktop/share/native/liblcms/cmsio1.c index c478b2ec75e..efac5abbba8 100644 --- a/src/java.desktop/share/native/liblcms/cmsio1.c +++ b/src/java.desktop/share/native/liblcms/cmsio1.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -335,8 +335,8 @@ cmsPipeline* _cmsReadFloatInputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloa // Read and create a BRAND NEW MPE LUT from a given profile. All stuff dependent of version, etc // is adjusted here in order to create a LUT that takes care of all those details. -// We add intent = -1 as a way to read matrix shaper always, no matter of other LUT -cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent) +// We add intent = 0xffffffff as a way to read matrix shaper always, no matter of other LUT +cmsPipeline* CMSEXPORT _cmsReadInputLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent) { cmsTagTypeSignature OriginalType; cmsTagSignature tag16; @@ -366,8 +366,8 @@ cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent) } // This is an attempt to reuse this function to retrieve the matrix-shaper as pipeline no - // matter other LUT are present and have precedence. Intent = -1 means just this. - if (Intent >= INTENT_PERCEPTUAL && Intent <= INTENT_ABSOLUTE_COLORIMETRIC) { + // matter other LUT are present and have precedence. Intent = 0xffffffff can be used for that. + if (Intent <= INTENT_ABSOLUTE_COLORIMETRIC) { tag16 = Device2PCS16[Intent]; tagFloat = Device2PCSFloat[Intent]; @@ -611,7 +611,7 @@ cmsPipeline* _cmsReadFloatOutputTag(cmsHPROFILE hProfile, cmsTagSignature tagFlo } // Create an output MPE LUT from agiven profile. Version mismatches are handled here -cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent) +cmsPipeline* CMSEXPORT _cmsReadOutputLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent) { cmsTagTypeSignature OriginalType; cmsTagSignature tag16; @@ -619,7 +619,7 @@ cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent) cmsContext ContextID = cmsGetProfileContextID(hProfile); - if (Intent >= INTENT_PERCEPTUAL && Intent <= INTENT_ABSOLUTE_COLORIMETRIC) { + if (Intent <= INTENT_ABSOLUTE_COLORIMETRIC) { tag16 = PCS2Device16[Intent]; tagFloat = PCS2DeviceFloat[Intent]; @@ -695,8 +695,8 @@ cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent) static cmsPipeline* _cmsReadFloatDevicelinkTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat) { - cmsContext ContextID = cmsGetProfileContextID(hProfile); - cmsPipeline* Lut = cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat)); + cmsContext ContextID = cmsGetProfileContextID(hProfile); + cmsPipeline* Lut = cmsPipelineDup((cmsPipeline*)cmsReadTag(hProfile, tagFloat)); cmsColorSpaceSignature PCS = cmsGetPCS(hProfile); cmsColorSpaceSignature spc = cmsGetColorSpace(hProfile); @@ -714,17 +714,17 @@ cmsPipeline* _cmsReadFloatDevicelinkTag(cmsHPROFILE hProfile, cmsTagSignature ta goto Error; } - if (PCS == cmsSigLabData) + if (PCS == cmsSigLabData) + { + if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID))) + goto Error; + } + else + if (PCS == cmsSigXYZData) { - if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID))) + if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID))) goto Error; } - else - if (PCS == cmsSigXYZData) - { - if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID))) - goto Error; - } return Lut; Error: @@ -734,7 +734,7 @@ cmsPipeline* _cmsReadFloatDevicelinkTag(cmsHPROFILE hProfile, cmsTagSignature ta // This one includes abstract profiles as well. Matrix-shaper cannot be obtained on that device class. The // tag name here may default to AToB0 -cmsPipeline* _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent) +cmsPipeline* CMSEXPORT _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent) { cmsPipeline* Lut; cmsTagTypeSignature OriginalType; @@ -743,7 +743,7 @@ cmsPipeline* _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent) cmsContext ContextID = cmsGetProfileContextID(hProfile); - if (Intent < INTENT_PERCEPTUAL || Intent > INTENT_ABSOLUTE_COLORIMETRIC) + if (Intent > INTENT_ABSOLUTE_COLORIMETRIC) return NULL; tag16 = Device2PCS16[Intent]; diff --git a/src/java.desktop/share/native/liblcms/cmslut.c b/src/java.desktop/share/native/liblcms/cmslut.c index 6c4b8ce4b40..495f3ef9283 100644 --- a/src/java.desktop/share/native/liblcms/cmslut.c +++ b/src/java.desktop/share/native/liblcms/cmslut.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -153,8 +153,8 @@ cmsBool CMSEXPORT cmsPipelineCheckAndRetreiveStages(const cmsPipeline* Lut, cms mpe = Lut ->Elements; for (i=0; i < n; i++) { - // Get asked type - Type = (cmsStageSignature)va_arg(args, cmsStageSignature); + // Get asked type. cmsStageSignature is promoted to int by compiler + Type = (cmsStageSignature)va_arg(args, int); if (mpe ->Type != Type) { va_end(args); // Mismatch. We are done. @@ -321,7 +321,7 @@ cmsStage* CMSEXPORT cmsStageAllocToneCurves(cmsContext ContextID, cmsUInt32Numbe // Create a bunch of identity curves -cmsStage* _cmsStageAllocIdentityCurves(cmsContext ContextID, int nChannels) +cmsStage* CMSEXPORT _cmsStageAllocIdentityCurves(cmsContext ContextID, cmsUInt32Number nChannels) { cmsStage* mpe = cmsStageAllocToneCurves(ContextID, nChannels, NULL); @@ -443,13 +443,13 @@ cmsStage* CMSEXPORT cmsStageAllocMatrix(cmsContext ContextID, cmsUInt32Number R if (Offset != NULL) { - NewElem ->Offset = (cmsFloat64Number*) _cmsCalloc(ContextID, Cols, sizeof(cmsFloat64Number)); + NewElem ->Offset = (cmsFloat64Number*) _cmsCalloc(ContextID, Rows, sizeof(cmsFloat64Number)); if (NewElem->Offset == NULL) { MatrixElemTypeFree(NewMPE); return NULL; } - for (i=0; i < Cols; i++) { + for (i=0; i < Rows; i++) { NewElem ->Offset[i] = Offset[i]; } @@ -741,7 +741,7 @@ int IdentitySampler(register const cmsUInt16Number In[], register cmsUInt16Numbe } // Creates an MPE that just copies input to output -cmsStage* _cmsStageAllocIdentityCLut(cmsContext ContextID, int nChan) +cmsStage* CMSEXPORT _cmsStageAllocIdentityCLut(cmsContext ContextID, cmsUInt32Number nChan) { cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS]; cmsStage* mpe ; @@ -765,7 +765,7 @@ cmsStage* _cmsStageAllocIdentityCLut(cmsContext ContextID, int nChan) // Quantize a value 0 <= i < MaxSamples to 0..0xffff -cmsUInt16Number _cmsQuantizeVal(cmsFloat64Number i, int MaxSamples) +cmsUInt16Number CMSEXPORT _cmsQuantizeVal(cmsFloat64Number i, cmsUInt32Number MaxSamples) { cmsFloat64Number x; @@ -778,8 +778,9 @@ cmsUInt16Number _cmsQuantizeVal(cmsFloat64Number i, int MaxSamples) // function on knots. returns TRUE if all ok, FALSE otherwise. cmsBool CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe, cmsSAMPLER16 Sampler, void * Cargo, cmsUInt32Number dwFlags) { - int i, t, nTotalPoints, index, rest; - int nInputs, nOutputs; + int i, t, index, rest; + cmsUInt32Number nTotalPoints; + cmsUInt32Number nInputs, nOutputs; cmsUInt32Number* nSamples; cmsUInt16Number In[MAX_INPUT_DIMENSIONS+1], Out[MAX_STAGE_CHANNELS]; _cmsStageCLutData* clut; @@ -799,14 +800,17 @@ cmsBool CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe, cmsSAMPLER16 Sampler, v if (nInputs > MAX_INPUT_DIMENSIONS) return FALSE; if (nOutputs >= MAX_STAGE_CHANNELS) return FALSE; + memset(In, 0, sizeof(In)); + memset(Out, 0, sizeof(Out)); + nTotalPoints = CubeSize(nSamples, nInputs); if (nTotalPoints == 0) return FALSE; index = 0; - for (i = 0; i < nTotalPoints; i++) { + for (i = 0; i < (int) nTotalPoints; i++) { rest = i; - for (t = nInputs-1; t >=0; --t) { + for (t = (int)nInputs - 1; t >= 0; --t) { cmsUInt32Number Colorant = rest % nSamples[t]; @@ -816,7 +820,7 @@ cmsBool CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe, cmsSAMPLER16 Sampler, v } if (clut ->Tab.T != NULL) { - for (t=0; t < nOutputs; t++) + for (t = 0; t < (int)nOutputs; t++) Out[t] = clut->Tab.T[index + t]; } @@ -826,7 +830,7 @@ cmsBool CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe, cmsSAMPLER16 Sampler, v if (!(dwFlags & SAMPLER_INSPECT)) { if (clut ->Tab.T != NULL) { - for (t=0; t < nOutputs; t++) + for (t=0; t < (int) nOutputs; t++) clut->Tab.T[index + t] = Out[t]; } } @@ -837,11 +841,12 @@ cmsBool CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe, cmsSAMPLER16 Sampler, v return TRUE; } -// Same as anterior, but for floting point +// Same as anterior, but for floating point cmsBool CMSEXPORT cmsStageSampleCLutFloat(cmsStage* mpe, cmsSAMPLERFLOAT Sampler, void * Cargo, cmsUInt32Number dwFlags) { - int i, t, nTotalPoints, index, rest; - int nInputs, nOutputs; + int i, t, index, rest; + cmsUInt32Number nTotalPoints; + cmsUInt32Number nInputs, nOutputs; cmsUInt32Number* nSamples; cmsFloat32Number In[MAX_INPUT_DIMENSIONS+1], Out[MAX_STAGE_CHANNELS]; _cmsStageCLutData* clut = (_cmsStageCLutData*) mpe->Data; @@ -859,10 +864,10 @@ cmsBool CMSEXPORT cmsStageSampleCLutFloat(cmsStage* mpe, cmsSAMPLERFLOAT Sampler if (nTotalPoints == 0) return FALSE; index = 0; - for (i = 0; i < nTotalPoints; i++) { + for (i = 0; i < (int)nTotalPoints; i++) { rest = i; - for (t = nInputs-1; t >=0; --t) { + for (t = (int) nInputs-1; t >=0; --t) { cmsUInt32Number Colorant = rest % nSamples[t]; @@ -872,7 +877,7 @@ cmsBool CMSEXPORT cmsStageSampleCLutFloat(cmsStage* mpe, cmsSAMPLERFLOAT Sampler } if (clut ->Tab.TFloat != NULL) { - for (t=0; t < nOutputs; t++) + for (t=0; t < (int) nOutputs; t++) Out[t] = clut->Tab.TFloat[index + t]; } @@ -882,7 +887,7 @@ cmsBool CMSEXPORT cmsStageSampleCLutFloat(cmsStage* mpe, cmsSAMPLERFLOAT Sampler if (!(dwFlags & SAMPLER_INSPECT)) { if (clut ->Tab.TFloat != NULL) { - for (t=0; t < nOutputs; t++) + for (t=0; t < (int) nOutputs; t++) clut->Tab.TFloat[index + t] = Out[t]; } } @@ -900,7 +905,8 @@ cmsBool CMSEXPORT cmsStageSampleCLutFloat(cmsStage* mpe, cmsSAMPLERFLOAT Sampler cmsBool CMSEXPORT cmsSliceSpace16(cmsUInt32Number nInputs, const cmsUInt32Number clutPoints[], cmsSAMPLER16 Sampler, void * Cargo) { - int i, t, nTotalPoints, rest; + int i, t, rest; + cmsUInt32Number nTotalPoints; cmsUInt16Number In[cmsMAXCHANNELS]; if (nInputs >= cmsMAXCHANNELS) return FALSE; @@ -908,10 +914,10 @@ cmsBool CMSEXPORT cmsSliceSpace16(cmsUInt32Number nInputs, const cmsUInt32Number nTotalPoints = CubeSize(clutPoints, nInputs); if (nTotalPoints == 0) return FALSE; - for (i = 0; i < nTotalPoints; i++) { + for (i = 0; i < (int) nTotalPoints; i++) { rest = i; - for (t = nInputs-1; t >=0; --t) { + for (t = (int) nInputs-1; t >=0; --t) { cmsUInt32Number Colorant = rest % clutPoints[t]; @@ -930,7 +936,8 @@ cmsBool CMSEXPORT cmsSliceSpace16(cmsUInt32Number nInputs, const cmsUInt32Number cmsInt32Number CMSEXPORT cmsSliceSpaceFloat(cmsUInt32Number nInputs, const cmsUInt32Number clutPoints[], cmsSAMPLERFLOAT Sampler, void * Cargo) { - int i, t, nTotalPoints, rest; + int i, t, rest; + cmsUInt32Number nTotalPoints; cmsFloat32Number In[cmsMAXCHANNELS]; if (nInputs >= cmsMAXCHANNELS) return FALSE; @@ -938,10 +945,10 @@ cmsInt32Number CMSEXPORT cmsSliceSpaceFloat(cmsUInt32Number nInputs, const cmsUI nTotalPoints = CubeSize(clutPoints, nInputs); if (nTotalPoints == 0) return FALSE; - for (i = 0; i < nTotalPoints; i++) { + for (i = 0; i < (int) nTotalPoints; i++) { rest = i; - for (t = nInputs-1; t >=0; --t) { + for (t = (int) nInputs-1; t >=0; --t) { cmsUInt32Number Colorant = rest % clutPoints[t]; @@ -991,7 +998,7 @@ void EvaluateLab2XYZ(const cmsFloat32Number In[], // No dup or free routines needed, as the structure has no pointers in it. -cmsStage* _cmsStageAllocLab2XYZ(cmsContext ContextID) +cmsStage* CMSEXPORT _cmsStageAllocLab2XYZ(cmsContext ContextID) { return _cmsStageAllocPlaceholder(ContextID, cmsSigLab2XYZElemType, 3, 3, EvaluateLab2XYZ, NULL, NULL, NULL); } @@ -1021,7 +1028,7 @@ cmsStage* _cmsStageAllocLabV2ToV4curves(cmsContext ContextID) return NULL; } - // We need to map * (0xffff / 0xff00), thats same as (257 / 256) + // We need to map * (0xffff / 0xff00), that's same as (257 / 256) // So we can use 258-entry tables to do the trick (i / 257) * (255 * 257) * (257 / 256); for (i=0; i < 257; i++) { @@ -1042,7 +1049,7 @@ cmsStage* _cmsStageAllocLabV2ToV4curves(cmsContext ContextID) // ******************************************************************************** // Matrix-based conversion, which is more accurate, but slower and cannot properly be saved in devicelink profiles -cmsStage* _cmsStageAllocLabV2ToV4(cmsContext ContextID) +cmsStage* CMSEXPORT _cmsStageAllocLabV2ToV4(cmsContext ContextID) { static const cmsFloat64Number V2ToV4[] = { 65535.0/65280.0, 0, 0, 0, 65535.0/65280.0, 0, @@ -1058,7 +1065,7 @@ cmsStage* _cmsStageAllocLabV2ToV4(cmsContext ContextID) // Reverse direction -cmsStage* _cmsStageAllocLabV4ToV2(cmsContext ContextID) +cmsStage* CMSEXPORT _cmsStageAllocLabV4ToV2(cmsContext ContextID) { static const cmsFloat64Number V4ToV2[] = { 65280.0/65535.0, 0, 0, 0, 65280.0/65535.0, 0, @@ -1166,7 +1173,7 @@ void Clipper(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage } } -cmsStage* _cmsStageClipNegatives(cmsContext ContextID, int nChannels) +cmsStage* _cmsStageClipNegatives(cmsContext ContextID, cmsUInt32Number nChannels) { return _cmsStageAllocPlaceholder(ContextID, cmsSigClipNegativesElemType, nChannels, nChannels, Clipper, NULL, NULL, NULL); @@ -1201,7 +1208,7 @@ void EvaluateXYZ2Lab(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsUNUSED_PARAMETER(mpe); } -cmsStage* _cmsStageAllocXYZ2Lab(cmsContext ContextID) +cmsStage* CMSEXPORT _cmsStageAllocXYZ2Lab(cmsContext ContextID) { return _cmsStageAllocPlaceholder(ContextID, cmsSigXYZ2LabElemType, 3, 3, EvaluateXYZ2Lab, NULL, NULL, NULL); @@ -1300,23 +1307,42 @@ cmsStage* CMSEXPORT cmsStageDup(cmsStage* mpe) // *********************************************************************************************************** // This function sets up the channel count - static -void BlessLUT(cmsPipeline* lut) +cmsBool BlessLUT(cmsPipeline* lut) { - // We can set the input/ouput channels only if we have elements. + // We can set the input/output channels only if we have elements. if (lut ->Elements != NULL) { - cmsStage *First, *Last; + cmsStage* prev; + cmsStage* next; + cmsStage* First; + cmsStage* Last; First = cmsPipelineGetPtrToFirstStage(lut); Last = cmsPipelineGetPtrToLastStage(lut); - if (First != NULL)lut ->InputChannels = First ->InputChannels; - if (Last != NULL) lut ->OutputChannels = Last ->OutputChannels; + if (First == NULL || Last == NULL) return FALSE; + + lut->InputChannels = First->InputChannels; + lut->OutputChannels = Last->OutputChannels; + + // Check chain consistency + prev = First; + next = prev->Next; + + while (next != NULL) + { + if (next->InputChannels != prev->OutputChannels) + return FALSE; + + next = next->Next; + prev = prev->Next; } } + return TRUE; +} + // Default to evaluate the LUT on 16 bit-basis. Precision is retained. static @@ -1368,21 +1394,18 @@ void _LUTevalFloat(register const cmsFloat32Number In[], register cmsFloat32Numb } - - // LUT Creation & Destruction - cmsPipeline* CMSEXPORT cmsPipelineAlloc(cmsContext ContextID, cmsUInt32Number InputChannels, cmsUInt32Number OutputChannels) { cmsPipeline* NewLUT; + // A value of zero in channels is allowed as placeholder if (InputChannels >= cmsMAXCHANNELS || OutputChannels >= cmsMAXCHANNELS) return NULL; NewLUT = (cmsPipeline*) _cmsMallocZero(ContextID, sizeof(cmsPipeline)); if (NewLUT == NULL) return NULL; - NewLUT -> InputChannels = InputChannels; NewLUT -> OutputChannels = OutputChannels; @@ -1393,7 +1416,11 @@ cmsPipeline* CMSEXPORT cmsPipelineAlloc(cmsContext ContextID, cmsUInt32Number In NewLUT ->Data = NewLUT; NewLUT ->ContextID = ContextID; - BlessLUT(NewLUT); + if (!BlessLUT(NewLUT)) + { + _cmsFree(ContextID, NewLUT); + return NULL; + } return NewLUT; } @@ -1500,7 +1527,12 @@ cmsPipeline* CMSEXPORT cmsPipelineDup(const cmsPipeline* lut) NewLUT ->SaveAs8Bits = lut ->SaveAs8Bits; - BlessLUT(NewLUT); + if (!BlessLUT(NewLUT)) + { + _cmsFree(lut->ContextID, NewLUT); + return NULL; + } + return NewLUT; } @@ -1537,8 +1569,7 @@ int CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage return FALSE; } - BlessLUT(lut); - return TRUE; + return BlessLUT(lut); } // Unlink an element and return the pointer to it @@ -1593,6 +1624,7 @@ void CMSEXPORT cmsPipelineUnlinkStage(cmsPipeline* lut, cmsStageLoc loc, cmsStag else cmsStageFree(Unlinked); + // May fail, but we ignore it BlessLUT(lut); } @@ -1619,8 +1651,7 @@ cmsBool CMSEXPORT cmsPipelineCat(cmsPipeline* l1, const cmsPipeline* l2) return FALSE; } - BlessLUT(l1); - return TRUE; + return BlessLUT(l1); } diff --git a/src/java.desktop/share/native/liblcms/cmsmd5.c b/src/java.desktop/share/native/liblcms/cmsmd5.c index 619c94edf4c..d86c9822ec8 100644 --- a/src/java.desktop/share/native/liblcms/cmsmd5.c +++ b/src/java.desktop/share/native/liblcms/cmsmd5.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), diff --git a/src/java.desktop/share/native/liblcms/cmsmtrx.c b/src/java.desktop/share/native/liblcms/cmsmtrx.c index 2bc6a497775..916a2926810 100644 --- a/src/java.desktop/share/native/liblcms/cmsmtrx.c +++ b/src/java.desktop/share/native/liblcms/cmsmtrx.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), diff --git a/src/java.desktop/share/native/liblcms/cmsnamed.c b/src/java.desktop/share/native/liblcms/cmsnamed.c index d1edeb4ce12..177ed799465 100644 --- a/src/java.desktop/share/native/liblcms/cmsnamed.c +++ b/src/java.desktop/share/native/liblcms/cmsnamed.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -156,7 +156,7 @@ int SearchMLUEntry(cmsMLU* mlu, cmsUInt16Number LanguageCode, cmsUInt16Number Co for (i=0; i < mlu ->UsedEntries; i++) { if (mlu ->Entries[i].Country == CountryCode && - mlu ->Entries[i].Language == LanguageCode) return i; + mlu ->Entries[i].Language == LanguageCode) return (int) i; } // Not found @@ -207,31 +207,24 @@ cmsBool AddMLUBlock(cmsMLU* mlu, cmsUInt32Number size, const wchar_t *Block, return TRUE; } -// Convert from a 3-char code to a cmsUInt16Number. It is done inthis way because some +// Convert from a 3-char code to a cmsUInt16Number. It is done in this way because some // compilers don't properly align beginning of strings static cmsUInt16Number strTo16(const char str[3]) { - cmsUInt16Number n = ((cmsUInt16Number) str[0] << 8) | str[1]; + const cmsUInt8Number* ptr8 = (const cmsUInt8Number*)str; + cmsUInt16Number n = (cmsUInt16Number)(((cmsUInt16Number)ptr8[0] << 8) | ptr8[1]); - return n; // Always big endian in this case + return n; } static void strFrom16(char str[3], cmsUInt16Number n) { - // Assiming this would be aligned - union { - - cmsUInt16Number n; - char str[2]; - - } c; - - c.n = n; // Always big endian in this case - - str[0] = c.str[0]; str[1] = c.str[1]; str[2] = 0; + str[0] = (char)(n >> 8); + str[1] = (char)n; + str[2] = (char)0; } @@ -354,7 +347,7 @@ const wchar_t* _cmsMLUgetWide(const cmsMLU* mlu, cmsUInt16Number* UsedLanguageCode, cmsUInt16Number* UsedCountryCode) { cmsUInt32Number i; - cmsInt32Number Best = -1; + int Best = -1; _cmsMLUentry* v; if (mlu == NULL) return NULL; @@ -367,7 +360,7 @@ const wchar_t* _cmsMLUgetWide(const cmsMLU* mlu, if (v -> Language == LanguageCode) { - if (Best == -1) Best = i; + if (Best == -1) Best = (int) i; if (v -> Country == CountryCode) { @@ -633,10 +626,10 @@ cmsBool CMSEXPORT cmsAppendNamedColor(cmsNAMEDCOLORLIST* NamedColorList, } for (i=0; i < NamedColorList ->ColorantCount; i++) - NamedColorList ->List[NamedColorList ->nColors].DeviceColorant[i] = Colorant == NULL? 0 : Colorant[i]; + NamedColorList ->List[NamedColorList ->nColors].DeviceColorant[i] = Colorant == NULL ? (cmsUInt16Number)0 : Colorant[i]; for (i=0; i < 3; i++) - NamedColorList ->List[NamedColorList ->nColors].PCS[i] = PCS == NULL ? 0 : PCS[i]; + NamedColorList ->List[NamedColorList ->nColors].PCS[i] = PCS == NULL ? (cmsUInt16Number) 0 : PCS[i]; if (Name != NULL) { @@ -671,6 +664,7 @@ cmsBool CMSEXPORT cmsNamedColorInfo(const cmsNAMEDCOLORLIST* NamedColorList, cm if (nColor >= cmsNamedColorCount(NamedColorList)) return FALSE; + // strcpy instead of strncpy because many apps are using small buffers if (Name) strcpy(Name, NamedColorList->List[nColor].Name); if (Prefix) strcpy(Prefix, NamedColorList->Prefix); if (Suffix) strcpy(Suffix, NamedColorList->Suffix); @@ -688,13 +682,14 @@ cmsBool CMSEXPORT cmsNamedColorInfo(const cmsNAMEDCOLORLIST* NamedColorList, cm // Search for a given color name (no prefix or suffix) cmsInt32Number CMSEXPORT cmsNamedColorIndex(const cmsNAMEDCOLORLIST* NamedColorList, const char* Name) { - int i, n; + cmsUInt32Number i; + cmsUInt32Number n; if (NamedColorList == NULL) return -1; n = cmsNamedColorCount(NamedColorList); for (i=0; i < n; i++) { if (cmsstrcasecmp(Name, NamedColorList->List[i].Name) == 0) - return i; + return (cmsInt32Number) i; } return -1; @@ -723,7 +718,8 @@ void EvalNamedColorPCS(const cmsFloat32Number In[], cmsFloat32Number Out[], cons cmsUInt16Number index = (cmsUInt16Number) _cmsQuickSaturateWord(In[0] * 65535.0); if (index >= NamedColorList-> nColors) { - cmsSignalError(NamedColorList ->ContextID, cmsERROR_RANGE, "Color %d out of range; ignored", index); + cmsSignalError(NamedColorList ->ContextID, cmsERROR_RANGE, "Color %d out of range", index); + Out[0] = Out[1] = Out[2] = 0.0f; } else { @@ -742,7 +738,10 @@ void EvalNamedColor(const cmsFloat32Number In[], cmsFloat32Number Out[], const c cmsUInt32Number j; if (index >= NamedColorList-> nColors) { - cmsSignalError(NamedColorList ->ContextID, cmsERROR_RANGE, "Color %d out of range; ignored", index); + cmsSignalError(NamedColorList ->ContextID, cmsERROR_RANGE, "Color %d out of range", index); + for (j = 0; j < NamedColorList->ColorantCount; j++) + Out[j] = 0.0f; + } else { for (j=0; j < NamedColorList ->ColorantCount; j++) @@ -752,7 +751,7 @@ void EvalNamedColor(const cmsFloat32Number In[], cmsFloat32Number Out[], const c // Named color lookup element -cmsStage* _cmsStageAllocNamedColor(cmsNAMEDCOLORLIST* NamedColorList, cmsBool UsePCS) +cmsStage* CMSEXPORT _cmsStageAllocNamedColor(cmsNAMEDCOLORLIST* NamedColorList, cmsBool UsePCS) { return _cmsStageAllocPlaceholder(NamedColorList ->ContextID, cmsSigNamedColorElemType, diff --git a/src/java.desktop/share/native/liblcms/cmsopt.c b/src/java.desktop/share/native/liblcms/cmsopt.c index a3ff2fc10e3..395ececad79 100644 --- a/src/java.desktop/share/native/liblcms/cmsopt.c +++ b/src/java.desktop/share/native/liblcms/cmsopt.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -78,8 +78,8 @@ typedef struct { cmsContext ContextID; // Number of channels - int nInputs; - int nOutputs; + cmsUInt32Number nInputs; + cmsUInt32Number nOutputs; _cmsInterpFn16 EvalCurveIn16[MAX_INPUT_DIMENSIONS]; // The maximum number of input channels is known in advance cmsInterpParams* ParamsCurveIn16[MAX_INPUT_DIMENSIONS]; @@ -123,8 +123,8 @@ typedef struct { cmsContext ContextID; - int nCurves; // Number of curves - int nElements; // Elements in curves + cmsUInt32Number nCurves; // Number of curves + cmsUInt32Number nElements; // Elements in curves cmsUInt16Number** Curves; // Points to a dynamically allocated array } Curves16Data; @@ -245,7 +245,7 @@ cmsBool _MultiplyMatrix(cmsPipeline* Lut) // Multiply both matrices to get the result _cmsMAT3per(&res, (cmsMAT3*)m2->Double, (cmsMAT3*)m1->Double); - // Get the next in chain afer the matrices + // Get the next in chain after the matrices chain = (*pt2)->Next; // Remove both matrices @@ -334,7 +334,7 @@ void PrelinEval16(register const cmsUInt16Number Input[], Prelin16Data* p16 = (Prelin16Data*) D; cmsUInt16Number StageABC[MAX_INPUT_DIMENSIONS]; cmsUInt16Number StageDEF[cmsMAXCHANNELS]; - int i; + cmsUInt32Number i; for (i=0; i < p16 ->nInputs; i++) { @@ -379,15 +379,15 @@ void* Prelin16dup(cmsContext ContextID, const void* ptr) static Prelin16Data* PrelinOpt16alloc(cmsContext ContextID, const cmsInterpParams* ColorMap, - int nInputs, cmsToneCurve** In, - int nOutputs, cmsToneCurve** Out ) + cmsUInt32Number nInputs, cmsToneCurve** In, + cmsUInt32Number nOutputs, cmsToneCurve** Out ) { - int i; + cmsUInt32Number i; Prelin16Data* p16 = (Prelin16Data*)_cmsMallocZero(ContextID, sizeof(Prelin16Data)); if (p16 == NULL) return NULL; p16 ->nInputs = nInputs; - p16 -> nOutputs = nOutputs; + p16 ->nOutputs = nOutputs; for (i=0; i < nInputs; i++) { @@ -435,7 +435,7 @@ Prelin16Data* PrelinOpt16alloc(cmsContext ContextID, // Sampler implemented by another LUT. This is a clean way to precalculate the devicelink 3D CLUT for // almost any transform. We use floating point precision and then convert from floating point to 16 bits. static -int XFormSampler16(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo) +cmsInt32Number XFormSampler16(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo) { cmsPipeline* Lut = (cmsPipeline*) Cargo; cmsFloat32Number InFloat[cmsMAXCHANNELS], OutFloat[cmsMAXCHANNELS]; @@ -482,7 +482,7 @@ cmsBool AllCurvesAreLinear(cmsStage* mpe) // is to fix scum dot on broken profiles/transforms. Works on 1, 3 and 4 channels static cmsBool PatchLUT(cmsStage* CLUT, cmsUInt16Number At[], cmsUInt16Number Value[], - int nChannelsOut, int nChannelsIn) + cmsUInt32Number nChannelsOut, cmsUInt32Number nChannelsIn) { _cmsStageCLutData* Grid = (_cmsStageCLutData*) CLUT ->Data; cmsInterpParams* p16 = Grid ->Params; @@ -512,10 +512,10 @@ cmsBool PatchLUT(cmsStage* CLUT, cmsUInt16Number At[], cmsUInt16Number Value[], ((pz - z0) != 0) || ((pw - w0) != 0)) return FALSE; // Not on exact node - index = p16 -> opta[3] * x0 + - p16 -> opta[2] * y0 + - p16 -> opta[1] * z0 + - p16 -> opta[0] * w0; + index = (int) p16 -> opta[3] * x0 + + (int) p16 -> opta[2] * y0 + + (int) p16 -> opta[1] * z0 + + (int) p16 -> opta[0] * w0; } else if (nChannelsIn == 3) { @@ -532,9 +532,9 @@ cmsBool PatchLUT(cmsStage* CLUT, cmsUInt16Number At[], cmsUInt16Number Value[], ((py - y0) != 0) || ((pz - z0) != 0)) return FALSE; // Not on exact node - index = p16 -> opta[2] * x0 + - p16 -> opta[1] * y0 + - p16 -> opta[0] * z0; + index = (int) p16 -> opta[2] * x0 + + (int) p16 -> opta[1] * y0 + + (int) p16 -> opta[0] * z0; } else if (nChannelsIn == 1) { @@ -545,24 +545,24 @@ cmsBool PatchLUT(cmsStage* CLUT, cmsUInt16Number At[], cmsUInt16Number Value[], if (((px - x0) != 0)) return FALSE; // Not on exact node - index = p16 -> opta[0] * x0; + index = (int) p16 -> opta[0] * x0; } else { cmsSignalError(CLUT->ContextID, cmsERROR_INTERNAL, "(internal) %d Channels are not supported on PatchLUT", nChannelsIn); return FALSE; } - for (i=0; i < nChannelsOut; i++) - Grid -> Tab.T[index + i] = Value[i]; + for (i = 0; i < (int) nChannelsOut; i++) + Grid->Tab.T[index + i] = Value[i]; return TRUE; } // Auxiliary, to see if two values are equal or very different static -cmsBool WhitesAreEqual(int n, cmsUInt16Number White1[], cmsUInt16Number White2[] ) +cmsBool WhitesAreEqual(cmsUInt32Number n, cmsUInt16Number White1[], cmsUInt16Number White2[] ) { - int i; + cmsUInt32Number i; for (i=0; i < n; i++) { @@ -664,7 +664,7 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 cmsStage* mpe; cmsStage* CLUT; cmsStage *KeepPreLin = NULL, *KeepPostLin = NULL; - int nGridPoints; + cmsUInt32Number nGridPoints; cmsColorSpaceSignature ColorSpace, OutputColorSpace; cmsStage *NewPreLin = NULL; cmsStage *NewPostLin = NULL; @@ -676,8 +676,13 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 // This is a loosy optimization! does not apply in floating-point cases if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) return FALSE; - ColorSpace = _cmsICCcolorSpace(T_COLORSPACE(*InputFormat)); - OutputColorSpace = _cmsICCcolorSpace(T_COLORSPACE(*OutputFormat)); + ColorSpace = _cmsICCcolorSpace((int) T_COLORSPACE(*InputFormat)); + OutputColorSpace = _cmsICCcolorSpace((int) T_COLORSPACE(*OutputFormat)); + + // Color space must be specified + if (ColorSpace == (cmsColorSpaceSignature)0 || + OutputColorSpace == (cmsColorSpaceSignature)0) return FALSE; + nGridPoints = _cmsReasonableGridpointsByColorspace(ColorSpace, *dwFlags); // For empty LUTs, 2 points are enough @@ -715,7 +720,7 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 goto Error; // Remove prelinearization. Since we have duplicated the curve - // in destination LUT, the sampling shoud be applied after this stage. + // in destination LUT, the sampling should be applied after this stage. cmsPipelineUnlinkStage(Src, cmsAT_BEGIN, &KeepPreLin); } } @@ -723,7 +728,7 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 // Allocate the CLUT CLUT = cmsStageAllocCLut16bit(Src ->ContextID, nGridPoints, Src ->InputChannels, Src->OutputChannels, NULL); - if (CLUT == NULL) return FALSE; + if (CLUT == NULL) goto Error; // Add the CLUT to the destination LUT if (!cmsPipelineInsertStage(Dest, cmsAT_END, CLUT)) { @@ -747,14 +752,14 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 if (!cmsPipelineInsertStage(Dest, cmsAT_END, NewPostLin)) goto Error; - // In destination LUT, the sampling shoud be applied after this stage. + // In destination LUT, the sampling should be applied after this stage. cmsPipelineUnlinkStage(Src, cmsAT_END, &KeepPostLin); } } } // Now its time to do the sampling. We have to ignore pre/post linearization - // The source LUT whithout pre/post curves is passed as parameter. + // The source LUT without pre/post curves is passed as parameter. if (!cmsStageSampleCLut16bit(CLUT, XFormSampler16, (void*) Src, 0)) { Error: // Ops, something went wrong, Restore stages @@ -834,7 +839,7 @@ void SlopeLimiting(cmsToneCurve* g) { int BeginVal, EndVal; int AtBegin = (int) floor((cmsFloat64Number) g ->nEntries * 0.02 + 0.5); // Cutoff at 2% - int AtEnd = g ->nEntries - AtBegin - 1; // And 98% + int AtEnd = (int) g ->nEntries - AtBegin - 1; // And 98% cmsFloat64Number Val, Slope, beta; int i; @@ -895,9 +900,9 @@ Prelin8Data* PrelinOpt8alloc(cmsContext ContextID, const cmsInterpParams* p, cms // Move to 0..1.0 in fixed domain - v1 = _cmsToFixedDomain(Input[0] * p -> Domain[0]); - v2 = _cmsToFixedDomain(Input[1] * p -> Domain[1]); - v3 = _cmsToFixedDomain(Input[2] * p -> Domain[2]); + v1 = _cmsToFixedDomain((int) (Input[0] * p -> Domain[0])); + v2 = _cmsToFixedDomain((int) (Input[1] * p -> Domain[1])); + v3 = _cmsToFixedDomain((int) (Input[2] * p -> Domain[2])); // Store the precalculated table of nodes p8 ->X0[i] = (p->opta[2] * FIXED_TO_INT(v1)); @@ -942,27 +947,27 @@ void PrelinEval8(register const cmsUInt16Number Input[], cmsS15Fixed16Number rx, ry, rz; cmsS15Fixed16Number c0, c1, c2, c3, Rest; int OutChan; - register cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1; + register cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1; Prelin8Data* p8 = (Prelin8Data*) D; register const cmsInterpParams* p = p8 ->p; - int TotalOut = p -> nOutputs; + int TotalOut = (int) p -> nOutputs; const cmsUInt16Number* LutTable = (const cmsUInt16Number*) p->Table; - r = Input[0] >> 8; - g = Input[1] >> 8; - b = Input[2] >> 8; + r = (cmsUInt8Number) (Input[0] >> 8); + g = (cmsUInt8Number) (Input[1] >> 8); + b = (cmsUInt8Number) (Input[2] >> 8); - X0 = X1 = p8->X0[r]; - Y0 = Y1 = p8->Y0[g]; - Z0 = Z1 = p8->Z0[b]; + X0 = X1 = (cmsS15Fixed16Number) p8->X0[r]; + Y0 = Y1 = (cmsS15Fixed16Number) p8->Y0[g]; + Z0 = Z1 = (cmsS15Fixed16Number) p8->Z0[b]; rx = p8 ->rx[r]; ry = p8 ->ry[g]; rz = p8 ->rz[b]; - X1 = X0 + ((rx == 0) ? 0 : p ->opta[2]); - Y1 = Y0 + ((ry == 0) ? 0 : p ->opta[1]); - Z1 = Z0 + ((rz == 0) ? 0 : p ->opta[0]); + X1 = X0 + (cmsS15Fixed16Number)((rx == 0) ? 0 : p ->opta[2]); + Y1 = Y0 + (cmsS15Fixed16Number)((ry == 0) ? 0 : p ->opta[1]); + Z1 = Z0 + (cmsS15Fixed16Number)((rz == 0) ? 0 : p ->opta[0]); // These are the 6 Tetrahedral @@ -1015,9 +1020,8 @@ void PrelinEval8(register const cmsUInt16Number Input[], c1 = c2 = c3 = 0; } - Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001; - Output[OutChan] = (cmsUInt16Number)c0 + ((Rest + (Rest>>16))>>16); + Output[OutChan] = (cmsUInt16Number) (c0 + ((Rest + (Rest >> 16)) >> 16)); } } @@ -1029,8 +1033,8 @@ void PrelinEval8(register const cmsUInt16Number Input[], static cmsBool IsDegenerated(const cmsToneCurve* g) { - int i, Zeros = 0, Poles = 0; - int nEntries = g ->nEntries; + cmsUInt32Number i, Zeros = 0, Poles = 0; + cmsUInt32Number nEntries = g ->nEntries; for (i=0; i < nEntries; i++) { @@ -1052,7 +1056,7 @@ static cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) { cmsPipeline* OriginalLut; - int nGridPoints; + cmsUInt32Number nGridPoints; cmsToneCurve *Trans[cmsMAXCHANNELS], *TransReverse[cmsMAXCHANNELS]; cmsUInt32Number t, i; cmsFloat32Number v, In[cmsMAXCHANNELS], Out[cmsMAXCHANNELS]; @@ -1090,8 +1094,13 @@ cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Inte if (cmsStageType(mpe) == cmsSigNamedColorElemType) return FALSE; } - ColorSpace = _cmsICCcolorSpace(T_COLORSPACE(*InputFormat)); - OutputColorSpace = _cmsICCcolorSpace(T_COLORSPACE(*OutputFormat)); + ColorSpace = _cmsICCcolorSpace((int) T_COLORSPACE(*InputFormat)); + OutputColorSpace = _cmsICCcolorSpace((int) T_COLORSPACE(*OutputFormat)); + + // Color space must be specified + if (ColorSpace == (cmsColorSpaceSignature)0 || + OutputColorSpace == (cmsColorSpaceSignature)0) return FALSE; + nGridPoints = _cmsReasonableGridpointsByColorspace(ColorSpace, *dwFlags); // Empty gamma containers @@ -1212,7 +1221,10 @@ cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Inte Prelin8Data* p8 = PrelinOpt8alloc(OptimizedLUT ->ContextID, OptimizedPrelinCLUT ->Params, OptimizedPrelinCurves); - if (p8 == NULL) return FALSE; + if (p8 == NULL) { + cmsPipelineFree(OptimizedLUT); + return FALSE; + } _cmsPipelineSetOptimizationParameters(OptimizedLUT, PrelinEval8, (void*) p8, Prelin8free, Prelin8dup); @@ -1222,7 +1234,10 @@ cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Inte Prelin16Data* p16 = PrelinOpt16alloc(OptimizedLUT ->ContextID, OptimizedPrelinCLUT ->Params, 3, OptimizedPrelinCurves, 3, NULL); - if (p16 == NULL) return FALSE; + if (p16 == NULL) { + cmsPipelineFree(OptimizedLUT); + return FALSE; + } _cmsPipelineSetOptimizationParameters(OptimizedLUT, PrelinEval16, (void*) p16, PrelinOpt16free, Prelin16dup); @@ -1260,6 +1275,7 @@ cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Inte return FALSE; cmsUNUSED_PARAMETER(Intent); + cmsUNUSED_PARAMETER(lIsLinear); } @@ -1269,7 +1285,7 @@ static void CurvesFree(cmsContext ContextID, void* ptr) { Curves16Data* Data = (Curves16Data*) ptr; - int i; + cmsUInt32Number i; for (i=0; i < Data -> nCurves; i++) { @@ -1284,7 +1300,7 @@ static void* CurvesDup(cmsContext ContextID, const void* ptr) { Curves16Data* Data = (Curves16Data*)_cmsDupMem(ContextID, ptr, sizeof(Curves16Data)); - int i; + cmsUInt32Number i; if (Data == NULL) return NULL; @@ -1299,9 +1315,9 @@ void* CurvesDup(cmsContext ContextID, const void* ptr) // Precomputes tables for 8-bit on input devicelink. static -Curves16Data* CurvesAlloc(cmsContext ContextID, int nCurves, int nElements, cmsToneCurve** G) +Curves16Data* CurvesAlloc(cmsContext ContextID, cmsUInt32Number nCurves, cmsUInt32Number nElements, cmsToneCurve** G) { - int i, j; + cmsUInt32Number i, j; Curves16Data* c16; c16 = (Curves16Data*)_cmsMallocZero(ContextID, sizeof(Curves16Data)); @@ -1311,7 +1327,10 @@ Curves16Data* CurvesAlloc(cmsContext ContextID, int nCurves, int nElements, cmsT c16 ->nElements = nElements; c16->Curves = (cmsUInt16Number**) _cmsCalloc(ContextID, nCurves, sizeof(cmsUInt16Number*)); - if (c16 ->Curves == NULL) return NULL; + if (c16->Curves == NULL) { + _cmsFree(ContextID, c16); + return NULL; + } for (i=0; i < nCurves; i++) { @@ -1327,7 +1346,7 @@ Curves16Data* CurvesAlloc(cmsContext ContextID, int nCurves, int nElements, cmsT return NULL; } - if (nElements == 256) { + if (nElements == 256U) { for (j=0; j < nElements; j++) { @@ -1351,8 +1370,8 @@ void FastEvaluateCurves8(register const cmsUInt16Number In[], register const void* D) { Curves16Data* Data = (Curves16Data*) D; - cmsUInt8Number x; - int i; + int x; + cmsUInt32Number i; for (i=0; i < Data ->nCurves; i++) { @@ -1368,7 +1387,7 @@ void FastEvaluateCurves16(register const cmsUInt16Number In[], register const void* D) { Curves16Data* Data = (Curves16Data*) D; - int i; + cmsUInt32Number i; for (i=0; i < Data ->nCurves; i++) { Out[i] = Data -> Curves[i][In[i]]; @@ -1548,9 +1567,9 @@ void MatShaperEval16(register const cmsUInt16Number In[], // In this case (and only in this case!) we can use this simplification since // In[] is assured to come from a 8 bit number. (a << 8 | a) - ri = In[0] & 0xFF; - gi = In[1] & 0xFF; - bi = In[2] & 0xFF; + ri = In[0] & 0xFFU; + gi = In[1] & 0xFFU; + bi = In[2] & 0xFFU; // Across first shaper, which also converts to 1.14 fixed point r = p->Shaper1R[ri]; @@ -1563,9 +1582,9 @@ void MatShaperEval16(register const cmsUInt16Number In[], l3 = (p->Mat[2][0] * r + p->Mat[2][1] * g + p->Mat[2][2] * b + p->Off[2] + 0x2000) >> 14; // Now we have to clip to 0..1.0 range - ri = (l1 < 0) ? 0 : ((l1 > 16384) ? 16384 : l1); - gi = (l2 < 0) ? 0 : ((l2 > 16384) ? 16384 : l2); - bi = (l3 < 0) ? 0 : ((l3 > 16384) ? 16384 : l3); + ri = (l1 < 0) ? 0 : ((l1 > 16384) ? 16384U : (cmsUInt32Number) l1); + gi = (l2 < 0) ? 0 : ((l2 > 16384) ? 16384U : (cmsUInt32Number) l2); + bi = (l3 < 0) ? 0 : ((l3 > 16384) ? 16384U : (cmsUInt32Number) l3); // And across second shaper, Out[0] = p->Shaper2R[ri]; @@ -1586,7 +1605,10 @@ void FillFirstShaper(cmsS1Fixed14Number* Table, cmsToneCurve* Curve) R = (cmsFloat32Number) (i / 255.0); y = cmsEvalToneCurveFloat(Curve, R); - Table[i] = DOUBLE_TO_1FIXED14(y); + if (y < 131072.0) + Table[i] = DOUBLE_TO_1FIXED14(y); + else + Table[i] = 0x7fffffff; } } @@ -1602,6 +1624,12 @@ void FillSecondShaper(cmsUInt16Number* Table, cmsToneCurve* Curve, cmsBool Is8Bi R = (cmsFloat32Number) (i / 16384.0); Val = cmsEvalToneCurveFloat(Curve, R); // Val comes 0..1.0 + if (Val < 0) + Val = 0; + + if (Val > 1.0) + Val = 1.0; + if (Is8BitsOutput) { // If 8 bits output, we can optimize further by computing the / 257 part. @@ -1640,7 +1668,7 @@ cmsBool SetMatShaper(cmsPipeline* Dest, cmsToneCurve* Curve1[3], cmsMAT3* Mat, c FillSecondShaper(p ->Shaper2G, Curve2[1], Is8Bits); FillSecondShaper(p ->Shaper2B, Curve2[2], Is8Bits); - // Convert matrix to nFixed14. Note that those values may take more than 16 bits as + // Convert matrix to nFixed14. Note that those values may take more than 16 bits for (i=0; i < 3; i++) { for (j=0; j < 3; j++) { p ->Mat[i][j] = DOUBLE_TO_1FIXED14(Mat->v[i].n[j]); @@ -1902,7 +1930,7 @@ cmsBool _cmsRegisterOptimizationPlugin(cmsContext ContextID, cmsPluginBase* Dat // The entry point for LUT optimization cmsBool _cmsOptimizePipeline(cmsContext ContextID, cmsPipeline** PtrLut, - int Intent, + cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) diff --git a/src/java.desktop/share/native/liblcms/cmspack.c b/src/java.desktop/share/native/liblcms/cmspack.c index a9087f6fc8a..7aabcc244ed 100644 --- a/src/java.desktop/share/native/liblcms/cmspack.c +++ b/src/java.desktop/share/native/liblcms/cmspack.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -126,21 +126,21 @@ cmsUInt8Number* UnrollChunkyBytes(register _cmsTRANSFORM* info, register cmsUInt8Number* accum, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> InputFormat); - int DoSwap = T_DOSWAP(info ->InputFormat); - int Reverse = T_FLAVOR(info ->InputFormat); - int SwapFirst = T_SWAPFIRST(info -> InputFormat); - int Extra = T_EXTRA(info -> InputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; + cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); + cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat); + cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat); + cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat); + cmsUInt32Number Extra = T_EXTRA(info -> InputFormat); + cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; cmsUInt16Number v; - int i; + cmsUInt32Number i; if (ExtraFirst) { accum += Extra; } for (i=0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; v = FROM_8_TO_16(*accum); v = Reverse ? REVERSE_FLAVOR_16(v) : v; @@ -173,11 +173,11 @@ cmsUInt8Number* UnrollPlanarBytes(register _cmsTRANSFORM* info, register cmsUInt8Number* accum, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> InputFormat); - int DoSwap = T_DOSWAP(info ->InputFormat); - int SwapFirst = T_SWAPFIRST(info ->InputFormat); - int Reverse = T_FLAVOR(info ->InputFormat); - int i; + cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); + cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat); + cmsUInt32Number SwapFirst = T_SWAPFIRST(info ->InputFormat); + cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat); + cmsUInt32Number i; cmsUInt8Number* Init = accum; if (DoSwap ^ SwapFirst) { @@ -186,7 +186,7 @@ cmsUInt8Number* UnrollPlanarBytes(register _cmsTRANSFORM* info, for (i=0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; cmsUInt16Number v = FROM_8_TO_16(*accum); wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v; @@ -503,14 +503,14 @@ cmsUInt8Number* UnrollAnyWords(register _cmsTRANSFORM* info, register cmsUInt8Number* accum, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> InputFormat); - int SwapEndian = T_ENDIAN16(info -> InputFormat); - int DoSwap = T_DOSWAP(info ->InputFormat); - int Reverse = T_FLAVOR(info ->InputFormat); - int SwapFirst = T_SWAPFIRST(info -> InputFormat); - int Extra = T_EXTRA(info -> InputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; - int i; + cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); + cmsUInt32Number SwapEndian = T_ENDIAN16(info -> InputFormat); + cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat); + cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat); + cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat); + cmsUInt32Number Extra = T_EXTRA(info -> InputFormat); + cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; + cmsUInt32Number i; if (ExtraFirst) { accum += Extra * sizeof(cmsUInt16Number); @@ -518,7 +518,7 @@ cmsUInt8Number* UnrollAnyWords(register _cmsTRANSFORM* info, for (i=0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; cmsUInt16Number v = *(cmsUInt16Number*) accum; if (SwapEndian) @@ -552,20 +552,20 @@ cmsUInt8Number* UnrollPlanarWords(register _cmsTRANSFORM* info, register cmsUInt8Number* accum, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> InputFormat); - int DoSwap= T_DOSWAP(info ->InputFormat); - int Reverse= T_FLAVOR(info ->InputFormat); - int SwapEndian = T_ENDIAN16(info -> InputFormat); - int i; + cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); + cmsUInt32Number DoSwap= T_DOSWAP(info ->InputFormat); + cmsUInt32Number Reverse= T_FLAVOR(info ->InputFormat); + cmsUInt32Number SwapEndian = T_ENDIAN16(info -> InputFormat); + cmsUInt32Number i; cmsUInt8Number* Init = accum; if (DoSwap) { - accum += T_EXTRA(info -> InputFormat) * Stride * sizeof(cmsUInt16Number); + accum += T_EXTRA(info -> InputFormat) * Stride; } for (i=0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; cmsUInt16Number v = *(cmsUInt16Number*) accum; if (SwapEndian) @@ -573,7 +573,7 @@ cmsUInt8Number* UnrollPlanarWords(register _cmsTRANSFORM* info, wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v; - accum += Stride * sizeof(cmsUInt16Number); + accum += Stride; } return (Init + sizeof(cmsUInt16Number)); @@ -801,13 +801,18 @@ cmsUInt8Number* UnrollLabDoubleTo16(register _cmsTRANSFORM* info, { if (T_PLANAR(info -> InputFormat)) { - cmsFloat64Number* Pt = (cmsFloat64Number*) accum; - cmsCIELab Lab; + cmsUInt8Number* pos_L; + cmsUInt8Number* pos_a; + cmsUInt8Number* pos_b; + + pos_L = accum; + pos_a = accum + Stride; + pos_b = accum + Stride * 2; - Lab.L = Pt[0]; - Lab.a = Pt[Stride]; - Lab.b = Pt[Stride*2]; + Lab.L = *(cmsFloat64Number*) pos_L; + Lab.a = *(cmsFloat64Number*) pos_a; + Lab.b = *(cmsFloat64Number*) pos_b; cmsFloat2LabEncoded(wIn, &Lab); return accum + sizeof(cmsFloat64Number); @@ -832,12 +837,17 @@ cmsUInt8Number* UnrollLabFloatTo16(register _cmsTRANSFORM* info, if (T_PLANAR(info -> InputFormat)) { - cmsFloat32Number* Pt = (cmsFloat32Number*) accum; + cmsUInt8Number* pos_L; + cmsUInt8Number* pos_a; + cmsUInt8Number* pos_b; + pos_L = accum; + pos_a = accum + Stride; + pos_b = accum + Stride * 2; - Lab.L = Pt[0]; - Lab.a = Pt[Stride]; - Lab.b = Pt[Stride*2]; + Lab.L = *(cmsFloat32Number*)pos_L; + Lab.a = *(cmsFloat32Number*)pos_a; + Lab.b = *(cmsFloat32Number*)pos_b; cmsFloat2LabEncoded(wIn, &Lab); return accum + sizeof(cmsFloat32Number); @@ -863,12 +873,19 @@ cmsUInt8Number* UnrollXYZDoubleTo16(register _cmsTRANSFORM* info, { if (T_PLANAR(info -> InputFormat)) { - cmsFloat64Number* Pt = (cmsFloat64Number*) accum; cmsCIEXYZ XYZ; + cmsUInt8Number* pos_X; + cmsUInt8Number* pos_Y; + cmsUInt8Number* pos_Z; + + pos_X = accum; + pos_Y = accum + Stride; + pos_Z = accum + Stride * 2; + + XYZ.X = *(cmsFloat64Number*)pos_X; + XYZ.Y = *(cmsFloat64Number*)pos_Y; + XYZ.Z = *(cmsFloat64Number*)pos_Z; - XYZ.X = Pt[0]; - XYZ.Y = Pt[Stride]; - XYZ.Z = Pt[Stride*2]; cmsFloat2XYZEncoded(wIn, &XYZ); return accum + sizeof(cmsFloat64Number); @@ -892,12 +909,19 @@ cmsUInt8Number* UnrollXYZFloatTo16(register _cmsTRANSFORM* info, { if (T_PLANAR(info -> InputFormat)) { - cmsFloat32Number* Pt = (cmsFloat32Number*) accum; cmsCIEXYZ XYZ; + cmsUInt8Number* pos_X; + cmsUInt8Number* pos_Y; + cmsUInt8Number* pos_Z; + + pos_X = accum; + pos_Y = accum + Stride; + pos_Z = accum + Stride * 2; + + XYZ.X = *(cmsFloat32Number*)pos_X; + XYZ.Y = *(cmsFloat32Number*)pos_Y; + XYZ.Z = *(cmsFloat32Number*)pos_Z; - XYZ.X = Pt[0]; - XYZ.Y = Pt[Stride]; - XYZ.Z = Pt[Stride*2]; cmsFloat2XYZEncoded(wIn, &XYZ); return accum + sizeof(cmsFloat32Number); @@ -942,6 +966,20 @@ cmsINLINE cmsBool IsInkSpace(cmsUInt32Number Type) } } +// Return the size in bytes of a given formatter +static +cmsUInt32Number PixelSize(cmsUInt32Number Format) +{ + cmsUInt32Number fmt_bytes = T_BYTES(Format); + + // For double, the T_BYTES field is zero + if (fmt_bytes == 0) + return sizeof(cmsUInt64Number); + + // Otherwise, it is already correct for all formats + return fmt_bytes; +} + // Inks does come in percentage, remaining cases are between 0..1.0, again to 16 bits static cmsUInt8Number* UnrollDoubleTo16(register _cmsTRANSFORM* info, @@ -950,25 +988,27 @@ cmsUInt8Number* UnrollDoubleTo16(register _cmsTRANSFORM* info, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> InputFormat); - int DoSwap = T_DOSWAP(info ->InputFormat); - int Reverse = T_FLAVOR(info ->InputFormat); - int SwapFirst = T_SWAPFIRST(info -> InputFormat); - int Extra = T_EXTRA(info -> InputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; - int Planar = T_PLANAR(info -> InputFormat); + cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); + cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat); + cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat); + cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat); + cmsUInt32Number Extra = T_EXTRA(info -> InputFormat); + cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; + cmsUInt32Number Planar = T_PLANAR(info -> InputFormat); cmsFloat64Number v; cmsUInt16Number vi; - int i, start = 0; - cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0; + cmsUInt32Number i, start = 0; + cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0; + + Stride /= PixelSize(info->InputFormat); if (ExtraFirst) start = Extra; for (i=0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; if (Planar) v = (cmsFloat32Number) ((cmsFloat64Number*) accum)[(i + start) * Stride]; @@ -1006,25 +1046,26 @@ cmsUInt8Number* UnrollFloatTo16(register _cmsTRANSFORM* info, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> InputFormat); - int DoSwap = T_DOSWAP(info ->InputFormat); - int Reverse = T_FLAVOR(info ->InputFormat); - int SwapFirst = T_SWAPFIRST(info -> InputFormat); - int Extra = T_EXTRA(info -> InputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; - int Planar = T_PLANAR(info -> InputFormat); + cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); + cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat); + cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat); + cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat); + cmsUInt32Number Extra = T_EXTRA(info -> InputFormat); + cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; + cmsUInt32Number Planar = T_PLANAR(info -> InputFormat); cmsFloat32Number v; cmsUInt16Number vi; - int i, start = 0; - cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0; + cmsUInt32Number i, start = 0; + cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0; + Stride /= PixelSize(info->InputFormat); if (ExtraFirst) start = Extra; for (i=0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; if (Planar) v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[(i + start) * Stride]; @@ -1083,24 +1124,25 @@ cmsUInt8Number* UnrollFloatsToFloat(_cmsTRANSFORM* info, cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> InputFormat); - int DoSwap = T_DOSWAP(info ->InputFormat); - int Reverse = T_FLAVOR(info ->InputFormat); - int SwapFirst = T_SWAPFIRST(info -> InputFormat); - int Extra = T_EXTRA(info -> InputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; - int Planar = T_PLANAR(info -> InputFormat); + cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); + cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat); + cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat); + cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat); + cmsUInt32Number Extra = T_EXTRA(info -> InputFormat); + cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; + cmsUInt32Number Planar = T_PLANAR(info -> InputFormat); cmsFloat32Number v; - int i, start = 0; + cmsUInt32Number i, start = 0; cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 100.0F : 1.0F; + Stride /= PixelSize(info->InputFormat); if (ExtraFirst) start = Extra; for (i=0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; if (Planar) v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[(i + start) * Stride]; @@ -1135,24 +1177,25 @@ cmsUInt8Number* UnrollDoublesToFloat(_cmsTRANSFORM* info, cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> InputFormat); - int DoSwap = T_DOSWAP(info ->InputFormat); - int Reverse = T_FLAVOR(info ->InputFormat); - int SwapFirst = T_SWAPFIRST(info -> InputFormat); - int Extra = T_EXTRA(info -> InputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; - int Planar = T_PLANAR(info -> InputFormat); + cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); + cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat); + cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat); + cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat); + cmsUInt32Number Extra = T_EXTRA(info -> InputFormat); + cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; + cmsUInt32Number Planar = T_PLANAR(info -> InputFormat); cmsFloat64Number v; - int i, start = 0; + cmsUInt32Number i, start = 0; cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 100.0 : 1.0; + Stride /= PixelSize(info->InputFormat); if (ExtraFirst) start = Extra; for (i=0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; if (Planar) v = (cmsFloat64Number) ((cmsFloat64Number*) accum)[(i + start) * Stride]; @@ -1191,7 +1234,9 @@ cmsUInt8Number* UnrollLabDoubleToFloat(_cmsTRANSFORM* info, if (T_PLANAR(info -> InputFormat)) { - wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..1 + Stride /= PixelSize(info->InputFormat); + + wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..1 wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0); // form -128..+127 to 0..1 wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0); @@ -1219,6 +1264,8 @@ cmsUInt8Number* UnrollLabFloatToFloat(_cmsTRANSFORM* info, if (T_PLANAR(info -> InputFormat)) { + Stride /= PixelSize(info->InputFormat); + wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..1 wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0); // form -128..+127 to 0..1 wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0); @@ -1249,6 +1296,8 @@ cmsUInt8Number* UnrollXYZDoubleToFloat(_cmsTRANSFORM* info, if (T_PLANAR(info -> InputFormat)) { + Stride /= PixelSize(info->InputFormat); + wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ); wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ); wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ); @@ -1276,6 +1325,8 @@ cmsUInt8Number* UnrollXYZFloatToFloat(_cmsTRANSFORM* info, if (T_PLANAR(info -> InputFormat)) { + Stride /= PixelSize(info->InputFormat); + wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ); wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ); wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ); @@ -1306,15 +1357,15 @@ cmsUInt8Number* PackAnyBytes(register _cmsTRANSFORM* info, register cmsUInt8Number* output, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> OutputFormat); - int DoSwap = T_DOSWAP(info ->OutputFormat); - int Reverse = T_FLAVOR(info ->OutputFormat); - int Extra = T_EXTRA(info -> OutputFormat); - int SwapFirst = T_SWAPFIRST(info -> OutputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; + cmsUInt32Number nChan = T_CHANNELS(info -> OutputFormat); + cmsUInt32Number DoSwap = T_DOSWAP(info ->OutputFormat); + cmsUInt32Number Reverse = T_FLAVOR(info ->OutputFormat); + cmsUInt32Number Extra = T_EXTRA(info -> OutputFormat); + cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> OutputFormat); + cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; cmsUInt8Number* swap1; cmsUInt8Number v = 0; - int i; + cmsUInt32Number i; swap1 = output; @@ -1324,7 +1375,7 @@ cmsUInt8Number* PackAnyBytes(register _cmsTRANSFORM* info, for (i=0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; v = FROM_16_TO_8(wOut[index]); @@ -1358,16 +1409,16 @@ cmsUInt8Number* PackAnyWords(register _cmsTRANSFORM* info, register cmsUInt8Number* output, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> OutputFormat); - int SwapEndian = T_ENDIAN16(info -> InputFormat); - int DoSwap = T_DOSWAP(info ->OutputFormat); - int Reverse = T_FLAVOR(info ->OutputFormat); - int Extra = T_EXTRA(info -> OutputFormat); - int SwapFirst = T_SWAPFIRST(info -> OutputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; + cmsUInt32Number nChan = T_CHANNELS(info -> OutputFormat); + cmsUInt32Number SwapEndian = T_ENDIAN16(info -> OutputFormat); + cmsUInt32Number DoSwap = T_DOSWAP(info ->OutputFormat); + cmsUInt32Number Reverse = T_FLAVOR(info ->OutputFormat); + cmsUInt32Number Extra = T_EXTRA(info -> OutputFormat); + cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> OutputFormat); + cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; cmsUInt16Number* swap1; cmsUInt16Number v = 0; - int i; + cmsUInt32Number i; swap1 = (cmsUInt16Number*) output; @@ -1377,7 +1428,7 @@ cmsUInt8Number* PackAnyWords(register _cmsTRANSFORM* info, for (i=0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; v = wOut[index]; @@ -1415,11 +1466,11 @@ cmsUInt8Number* PackPlanarBytes(register _cmsTRANSFORM* info, register cmsUInt8Number* output, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> OutputFormat); - int DoSwap = T_DOSWAP(info ->OutputFormat); - int SwapFirst = T_SWAPFIRST(info ->OutputFormat); - int Reverse = T_FLAVOR(info ->OutputFormat); - int i; + cmsUInt32Number nChan = T_CHANNELS(info -> OutputFormat); + cmsUInt32Number DoSwap = T_DOSWAP(info ->OutputFormat); + cmsUInt32Number SwapFirst = T_SWAPFIRST(info ->OutputFormat); + cmsUInt32Number Reverse = T_FLAVOR(info ->OutputFormat); + cmsUInt32Number i; cmsUInt8Number* Init = output; @@ -1430,7 +1481,7 @@ cmsUInt8Number* PackPlanarBytes(register _cmsTRANSFORM* info, for (i=0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; cmsUInt8Number v = FROM_16_TO_8(wOut[index]); *(cmsUInt8Number*) output = (cmsUInt8Number) (Reverse ? REVERSE_FLAVOR_8(v) : v); @@ -1449,21 +1500,21 @@ cmsUInt8Number* PackPlanarWords(register _cmsTRANSFORM* info, register cmsUInt8Number* output, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> OutputFormat); - int DoSwap = T_DOSWAP(info ->OutputFormat); - int Reverse= T_FLAVOR(info ->OutputFormat); - int SwapEndian = T_ENDIAN16(info -> OutputFormat); - int i; + cmsUInt32Number nChan = T_CHANNELS(info -> OutputFormat); + cmsUInt32Number DoSwap = T_DOSWAP(info ->OutputFormat); + cmsUInt32Number Reverse = T_FLAVOR(info ->OutputFormat); + cmsUInt32Number SwapEndian = T_ENDIAN16(info -> OutputFormat); + cmsUInt32Number i; cmsUInt8Number* Init = output; cmsUInt16Number v; if (DoSwap) { - output += T_EXTRA(info -> OutputFormat) * Stride * sizeof(cmsUInt16Number); + output += T_EXTRA(info -> OutputFormat) * Stride; } for (i=0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; v = wOut[index]; @@ -1474,7 +1525,7 @@ cmsUInt8Number* PackPlanarWords(register _cmsTRANSFORM* info, v = REVERSE_FLAVOR_16(v); *(cmsUInt16Number*) output = v; - output += (Stride * sizeof(cmsUInt16Number)); + output += Stride; } return (Init + sizeof(cmsUInt16Number)); @@ -1823,9 +1874,9 @@ cmsUInt8Number* Pack3BytesOptimized(register _cmsTRANSFORM* info, register cmsUInt8Number* output, register cmsUInt32Number Stride) { - *output++ = (wOut[0] & 0xFF); - *output++ = (wOut[1] & 0xFF); - *output++ = (wOut[2] & 0xFF); + *output++ = (wOut[0] & 0xFFU); + *output++ = (wOut[1] & 0xFFU); + *output++ = (wOut[2] & 0xFFU); return output; @@ -1855,9 +1906,9 @@ cmsUInt8Number* Pack3BytesSwapOptimized(register _cmsTRANSFORM* info, register cmsUInt8Number* output, register cmsUInt32Number Stride) { - *output++ = (wOut[2] & 0xFF); - *output++ = (wOut[1] & 0xFF); - *output++ = (wOut[0] & 0xFF); + *output++ = (wOut[2] & 0xFFU); + *output++ = (wOut[1] & 0xFFU); + *output++ = (wOut[0] & 0xFFU); return output; @@ -1946,9 +1997,9 @@ cmsUInt8Number* Pack3BytesAndSkip1Optimized(register _cmsTRANSFORM* info, register cmsUInt8Number* output, register cmsUInt32Number Stride) { - *output++ = (wOut[0] & 0xFF); - *output++ = (wOut[1] & 0xFF); - *output++ = (wOut[2] & 0xFF); + *output++ = (wOut[0] & 0xFFU); + *output++ = (wOut[1] & 0xFFU); + *output++ = (wOut[2] & 0xFFU); output++; return output; @@ -1982,9 +2033,9 @@ cmsUInt8Number* Pack3BytesAndSkip1SwapFirstOptimized(register _cmsTRANSFORM* inf register cmsUInt32Number Stride) { output++; - *output++ = (wOut[0] & 0xFF); - *output++ = (wOut[1] & 0xFF); - *output++ = (wOut[2] & 0xFF); + *output++ = (wOut[0] & 0xFFU); + *output++ = (wOut[1] & 0xFFU); + *output++ = (wOut[2] & 0xFFU); return output; @@ -2016,9 +2067,9 @@ cmsUInt8Number* Pack3BytesAndSkip1SwapOptimized(register _cmsTRANSFORM* info, register cmsUInt32Number Stride) { output++; - *output++ = (wOut[2] & 0xFF); - *output++ = (wOut[1] & 0xFF); - *output++ = (wOut[0] & 0xFF); + *output++ = (wOut[2] & 0xFFU); + *output++ = (wOut[1] & 0xFFU); + *output++ = (wOut[0] & 0xFFU); return output; @@ -2050,9 +2101,9 @@ cmsUInt8Number* Pack3BytesAndSkip1SwapSwapFirstOptimized(register _cmsTRANSFORM* register cmsUInt8Number* output, register cmsUInt32Number Stride) { - *output++ = (wOut[2] & 0xFF); - *output++ = (wOut[1] & 0xFF); - *output++ = (wOut[0] & 0xFF); + *output++ = (wOut[2] & 0xFFU); + *output++ = (wOut[1] & 0xFFU); + *output++ = (wOut[0] & 0xFFU); output++; return output; @@ -2326,6 +2377,8 @@ cmsUInt8Number* PackLabFloatFrom16(register _cmsTRANSFORM* info, cmsFloat32Number* Out = (cmsFloat32Number*) output; + Stride /= PixelSize(info->OutputFormat); + Out[0] = (cmsFloat32Number)Lab.L; Out[Stride] = (cmsFloat32Number)Lab.a; Out[Stride*2] = (cmsFloat32Number)Lab.b; @@ -2354,6 +2407,8 @@ cmsUInt8Number* PackXYZDoubleFrom16(register _cmsTRANSFORM* Info, cmsFloat64Number* Out = (cmsFloat64Number*) output; cmsXYZEncoded2Float(&XYZ, wOut); + Stride /= PixelSize(Info->OutputFormat); + Out[0] = XYZ.X; Out[Stride] = XYZ.Y; Out[Stride*2] = XYZ.Z; @@ -2381,6 +2436,8 @@ cmsUInt8Number* PackXYZFloatFrom16(register _cmsTRANSFORM* Info, cmsFloat32Number* Out = (cmsFloat32Number*) output; cmsXYZEncoded2Float(&XYZ, wOut); + Stride /= PixelSize(Info->OutputFormat); + Out[0] = (cmsFloat32Number) XYZ.X; Out[Stride] = (cmsFloat32Number) XYZ.Y; Out[Stride*2] = (cmsFloat32Number) XYZ.Z; @@ -2408,24 +2465,26 @@ cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* info, register cmsUInt8Number* output, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> OutputFormat); - int DoSwap = T_DOSWAP(info ->OutputFormat); - int Reverse = T_FLAVOR(info ->OutputFormat); - int Extra = T_EXTRA(info -> OutputFormat); - int SwapFirst = T_SWAPFIRST(info -> OutputFormat); - int Planar = T_PLANAR(info -> OutputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; + cmsUInt32Number nChan = T_CHANNELS(info -> OutputFormat); + cmsUInt32Number DoSwap = T_DOSWAP(info ->OutputFormat); + cmsUInt32Number Reverse = T_FLAVOR(info ->OutputFormat); + cmsUInt32Number Extra = T_EXTRA(info -> OutputFormat); + cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> OutputFormat); + cmsUInt32Number Planar = T_PLANAR(info -> OutputFormat); + cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35 : 65535.0; cmsFloat64Number v = 0; cmsFloat64Number* swap1 = (cmsFloat64Number*) output; - int i, start = 0; + cmsUInt32Number i, start = 0; + + Stride /= PixelSize(info->OutputFormat); if (ExtraFirst) start = Extra; for (i=0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; v = (cmsFloat64Number) wOut[index] / maximum; @@ -2459,24 +2518,26 @@ cmsUInt8Number* PackFloatFrom16(register _cmsTRANSFORM* info, register cmsUInt8Number* output, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info->OutputFormat); - int DoSwap = T_DOSWAP(info->OutputFormat); - int Reverse = T_FLAVOR(info->OutputFormat); - int Extra = T_EXTRA(info->OutputFormat); - int SwapFirst = T_SWAPFIRST(info->OutputFormat); - int Planar = T_PLANAR(info->OutputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; + cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat); + cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat); + cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat); + cmsUInt32Number Extra = T_EXTRA(info->OutputFormat); + cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat); + cmsUInt32Number Planar = T_PLANAR(info->OutputFormat); + cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 655.35 : 65535.0; cmsFloat64Number v = 0; cmsFloat32Number* swap1 = (cmsFloat32Number*)output; - int i, start = 0; + cmsUInt32Number i, start = 0; + + Stride /= PixelSize(info->OutputFormat); if (ExtraFirst) start = Extra; for (i = 0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; v = (cmsFloat64Number)wOut[index] / maximum; @@ -2512,24 +2573,26 @@ cmsUInt8Number* PackFloatsFromFloat(_cmsTRANSFORM* info, cmsUInt8Number* output, cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info->OutputFormat); - int DoSwap = T_DOSWAP(info->OutputFormat); - int Reverse = T_FLAVOR(info->OutputFormat); - int Extra = T_EXTRA(info->OutputFormat); - int SwapFirst = T_SWAPFIRST(info->OutputFormat); - int Planar = T_PLANAR(info->OutputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; + cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat); + cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat); + cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat); + cmsUInt32Number Extra = T_EXTRA(info->OutputFormat); + cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat); + cmsUInt32Number Planar = T_PLANAR(info->OutputFormat); + cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0; cmsFloat32Number* swap1 = (cmsFloat32Number*)output; cmsFloat64Number v = 0; - int i, start = 0; + cmsUInt32Number i, start = 0; + + Stride /= PixelSize(info->OutputFormat); if (ExtraFirst) start = Extra; for (i = 0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; v = wOut[index] * maximum; @@ -2561,24 +2624,26 @@ cmsUInt8Number* PackDoublesFromFloat(_cmsTRANSFORM* info, cmsUInt8Number* output, cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info->OutputFormat); - int DoSwap = T_DOSWAP(info->OutputFormat); - int Reverse = T_FLAVOR(info->OutputFormat); - int Extra = T_EXTRA(info->OutputFormat); - int SwapFirst = T_SWAPFIRST(info->OutputFormat); - int Planar = T_PLANAR(info->OutputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; + cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat); + cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat); + cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat); + cmsUInt32Number Extra = T_EXTRA(info->OutputFormat); + cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat); + cmsUInt32Number Planar = T_PLANAR(info->OutputFormat); + cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0; cmsFloat64Number v = 0; cmsFloat64Number* swap1 = (cmsFloat64Number*)output; - int i, start = 0; + cmsUInt32Number i, start = 0; + + Stride /= PixelSize(info->OutputFormat); if (ExtraFirst) start = Extra; for (i = 0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; v = wOut[index] * maximum; @@ -2619,6 +2684,8 @@ cmsUInt8Number* PackLabFloatFromFloat(_cmsTRANSFORM* Info, if (T_PLANAR(Info -> OutputFormat)) { + Stride /= PixelSize(Info->OutputFormat); + Out[0] = (cmsFloat32Number) (wOut[0] * 100.0); Out[Stride] = (cmsFloat32Number) (wOut[1] * 255.0 - 128.0); Out[Stride*2] = (cmsFloat32Number) (wOut[2] * 255.0 - 128.0); @@ -2647,6 +2714,8 @@ cmsUInt8Number* PackLabDoubleFromFloat(_cmsTRANSFORM* Info, if (T_PLANAR(Info -> OutputFormat)) { + Stride /= PixelSize(Info->OutputFormat); + Out[0] = (cmsFloat64Number) (wOut[0] * 100.0); Out[Stride] = (cmsFloat64Number) (wOut[1] * 255.0 - 128.0); Out[Stride*2] = (cmsFloat64Number) (wOut[2] * 255.0 - 128.0); @@ -2676,6 +2745,8 @@ cmsUInt8Number* PackXYZFloatFromFloat(_cmsTRANSFORM* Info, if (T_PLANAR(Info -> OutputFormat)) { + Stride /= PixelSize(Info->OutputFormat); + Out[0] = (cmsFloat32Number) (wOut[0] * MAX_ENCODEABLE_XYZ); Out[Stride] = (cmsFloat32Number) (wOut[1] * MAX_ENCODEABLE_XYZ); Out[Stride*2] = (cmsFloat32Number) (wOut[2] * MAX_ENCODEABLE_XYZ); @@ -2704,6 +2775,8 @@ cmsUInt8Number* PackXYZDoubleFromFloat(_cmsTRANSFORM* Info, if (T_PLANAR(Info -> OutputFormat)) { + Stride /= PixelSize(Info->OutputFormat); + Out[0] = (cmsFloat64Number) (wOut[0] * MAX_ENCODEABLE_XYZ); Out[Stride] = (cmsFloat64Number) (wOut[1] * MAX_ENCODEABLE_XYZ); Out[Stride*2] = (cmsFloat64Number) (wOut[2] * MAX_ENCODEABLE_XYZ); @@ -2735,24 +2808,26 @@ cmsUInt8Number* UnrollHalfTo16(register _cmsTRANSFORM* info, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> InputFormat); - int DoSwap = T_DOSWAP(info ->InputFormat); - int Reverse = T_FLAVOR(info ->InputFormat); - int SwapFirst = T_SWAPFIRST(info -> InputFormat); - int Extra = T_EXTRA(info -> InputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; - int Planar = T_PLANAR(info -> InputFormat); + cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); + cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat); + cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat); + cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat); + cmsUInt32Number Extra = T_EXTRA(info -> InputFormat); + cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; + cmsUInt32Number Planar = T_PLANAR(info -> InputFormat); cmsFloat32Number v; - int i, start = 0; + cmsUInt32Number i, start = 0; cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 655.35F : 65535.0F; + Stride /= PixelSize(info->OutputFormat); + if (ExtraFirst) start = Extra; for (i=0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; if (Planar) v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[(i + start) * Stride] ); @@ -2787,24 +2862,25 @@ cmsUInt8Number* UnrollHalfToFloat(_cmsTRANSFORM* info, cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> InputFormat); - int DoSwap = T_DOSWAP(info ->InputFormat); - int Reverse = T_FLAVOR(info ->InputFormat); - int SwapFirst = T_SWAPFIRST(info -> InputFormat); - int Extra = T_EXTRA(info -> InputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; - int Planar = T_PLANAR(info -> InputFormat); + cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); + cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat); + cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat); + cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat); + cmsUInt32Number Extra = T_EXTRA(info -> InputFormat); + cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; + cmsUInt32Number Planar = T_PLANAR(info -> InputFormat); cmsFloat32Number v; - int i, start = 0; + cmsUInt32Number i, start = 0; cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 100.0F : 1.0F; + Stride /= PixelSize(info->OutputFormat); if (ExtraFirst) start = Extra; for (i=0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; if (Planar) v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[(i + start) * Stride] ); @@ -2837,24 +2913,26 @@ cmsUInt8Number* PackHalfFrom16(register _cmsTRANSFORM* info, register cmsUInt8Number* output, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info->OutputFormat); - int DoSwap = T_DOSWAP(info->OutputFormat); - int Reverse = T_FLAVOR(info->OutputFormat); - int Extra = T_EXTRA(info->OutputFormat); - int SwapFirst = T_SWAPFIRST(info->OutputFormat); - int Planar = T_PLANAR(info->OutputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; + cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat); + cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat); + cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat); + cmsUInt32Number Extra = T_EXTRA(info->OutputFormat); + cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat); + cmsUInt32Number Planar = T_PLANAR(info->OutputFormat); + cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 655.35F : 65535.0F; cmsFloat32Number v = 0; cmsUInt16Number* swap1 = (cmsUInt16Number*)output; - int i, start = 0; + cmsUInt32Number i, start = 0; + + Stride /= PixelSize(info->OutputFormat); if (ExtraFirst) start = Extra; for (i = 0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; v = (cmsFloat32Number)wOut[index] / maximum; @@ -2888,24 +2966,26 @@ cmsUInt8Number* PackHalfFromFloat(_cmsTRANSFORM* info, cmsUInt8Number* output, cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info->OutputFormat); - int DoSwap = T_DOSWAP(info->OutputFormat); - int Reverse = T_FLAVOR(info->OutputFormat); - int Extra = T_EXTRA(info->OutputFormat); - int SwapFirst = T_SWAPFIRST(info->OutputFormat); - int Planar = T_PLANAR(info->OutputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; + cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat); + cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat); + cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat); + cmsUInt32Number Extra = T_EXTRA(info->OutputFormat); + cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat); + cmsUInt32Number Planar = T_PLANAR(info->OutputFormat); + cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 100.0F : 1.0F; cmsUInt16Number* swap1 = (cmsUInt16Number*)output; cmsFloat32Number v = 0; - int i, start = 0; + cmsUInt32Number i, start = 0; + + Stride /= PixelSize(info->OutputFormat); if (ExtraFirst) start = Extra; for (i = 0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; v = wOut[index] * maximum; @@ -2936,7 +3016,7 @@ cmsUInt8Number* PackHalfFromFloat(_cmsTRANSFORM* info, // ---------------------------------------------------------------------------------------------------------------- -static cmsFormatters16 InputFormatters16[] = { +static const cmsFormatters16 InputFormatters16[] = { // Type Mask Function // ---------------------------- ------------------------------------ ---------------------------- @@ -3007,7 +3087,7 @@ static cmsFormatters16 InputFormatters16[] = { -static cmsFormattersFloat InputFormattersFloat[] = { +static const cmsFormattersFloat InputFormattersFloat[] = { // Type Mask Function // ---------------------------- ------------------------------------ ---------------------------- @@ -3040,7 +3120,7 @@ cmsFormatter _cmsGetStockInputFormatter(cmsUInt32Number dwInput, cmsUInt32Number case CMS_PACK_FLAGS_16BITS: { for (i=0; i < sizeof(InputFormatters16) / sizeof(cmsFormatters16); i++) { - cmsFormatters16* f = InputFormatters16 + i; + const cmsFormatters16* f = InputFormatters16 + i; if ((dwInput & ~f ->Mask) == f ->Type) { fr.Fmt16 = f ->Frm; @@ -3052,7 +3132,7 @@ cmsFormatter _cmsGetStockInputFormatter(cmsUInt32Number dwInput, cmsUInt32Number case CMS_PACK_FLAGS_FLOAT: { for (i=0; i < sizeof(InputFormattersFloat) / sizeof(cmsFormattersFloat); i++) { - cmsFormattersFloat* f = InputFormattersFloat + i; + const cmsFormattersFloat* f = InputFormattersFloat + i; if ((dwInput & ~f ->Mask) == f ->Type) { fr.FmtFloat = f ->Frm; @@ -3070,7 +3150,7 @@ cmsFormatter _cmsGetStockInputFormatter(cmsUInt32Number dwInput, cmsUInt32Number return fr; } -static cmsFormatters16 OutputFormatters16[] = { +static const cmsFormatters16 OutputFormatters16[] = { // Type Mask Function // ---------------------------- ------------------------------------ ---------------------------- @@ -3158,7 +3238,7 @@ static cmsFormatters16 OutputFormatters16[] = { }; -static cmsFormattersFloat OutputFormattersFloat[] = { +static const cmsFormattersFloat OutputFormattersFloat[] = { // Type Mask Function // ---------------------------- --------------------------------------------------- ---------------------------- { TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, PackLabFloatFromFloat}, @@ -3176,8 +3256,6 @@ static cmsFormattersFloat OutputFormattersFloat[] = { ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackHalfFromFloat }, #endif - - }; @@ -3197,7 +3275,7 @@ cmsFormatter _cmsGetStockOutputFormatter(cmsUInt32Number dwInput, cmsUInt32Numbe case CMS_PACK_FLAGS_16BITS: { for (i=0; i < sizeof(OutputFormatters16) / sizeof(cmsFormatters16); i++) { - cmsFormatters16* f = OutputFormatters16 + i; + const cmsFormatters16* f = OutputFormatters16 + i; if ((dwInput & ~f ->Mask) == f ->Type) { fr.Fmt16 = f ->Frm; @@ -3210,7 +3288,7 @@ cmsFormatter _cmsGetStockOutputFormatter(cmsUInt32Number dwInput, cmsUInt32Numbe case CMS_PACK_FLAGS_FLOAT: { for (i=0; i < sizeof(OutputFormattersFloat) / sizeof(cmsFormattersFloat); i++) { - cmsFormattersFloat* f = OutputFormattersFloat + i; + const cmsFormattersFloat* f = OutputFormattersFloat + i; if ((dwInput & ~f ->Mask) == f ->Type) { fr.FmtFloat = f ->Frm; @@ -3319,10 +3397,10 @@ cmsBool _cmsRegisterFormattersPlugin(cmsContext ContextID, cmsPluginBase* Data) return TRUE; } -cmsFormatter _cmsGetFormatter(cmsContext ContextID, - cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8 - cmsFormatterDirection Dir, - cmsUInt32Number dwFlags) +cmsFormatter CMSEXPORT _cmsGetFormatter(cmsContext ContextID, + cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8 + cmsFormatterDirection Dir, + cmsUInt32Number dwFlags) { _cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin); cmsFormattersFactoryList* f; @@ -3350,7 +3428,7 @@ cmsBool _cmsFormatterIsFloat(cmsUInt32Number Type) // Return whatever given formatter refers to 8 bits cmsBool _cmsFormatterIs8bit(cmsUInt32Number Type) { - int Bytes = T_BYTES(Type); + cmsUInt32Number Bytes = T_BYTES(Type); return (Bytes == 1); } @@ -3360,9 +3438,9 @@ cmsUInt32Number CMSEXPORT cmsFormatterForColorspaceOfProfile(cmsHPROFILE hProfil { cmsColorSpaceSignature ColorSpace = cmsGetColorSpace(hProfile); - cmsUInt32Number ColorSpaceBits = _cmsLCMScolorSpace(ColorSpace); + cmsUInt32Number ColorSpaceBits = (cmsUInt32Number) _cmsLCMScolorSpace(ColorSpace); cmsUInt32Number nOutputChans = cmsChannelsOf(ColorSpace); - cmsUInt32Number Float = lIsFloat ? 1 : 0; + cmsUInt32Number Float = lIsFloat ? 1U : 0; // Create a fake formatter for result return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans); @@ -3372,10 +3450,11 @@ cmsUInt32Number CMSEXPORT cmsFormatterForColorspaceOfProfile(cmsHPROFILE hProfil cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat) { - cmsColorSpaceSignature ColorSpace = cmsGetPCS(hProfile); - int ColorSpaceBits = _cmsLCMScolorSpace(ColorSpace); - cmsUInt32Number nOutputChans = cmsChannelsOf(ColorSpace); - cmsUInt32Number Float = lIsFloat ? 1 : 0; + cmsColorSpaceSignature ColorSpace = cmsGetPCS(hProfile); + + cmsUInt32Number ColorSpaceBits = (cmsUInt32Number) _cmsLCMScolorSpace(ColorSpace); + cmsUInt32Number nOutputChans = cmsChannelsOf(ColorSpace); + cmsUInt32Number Float = lIsFloat ? 1U : 0; // Create a fake formatter for result return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans); diff --git a/src/java.desktop/share/native/liblcms/cmspcs.c b/src/java.desktop/share/native/liblcms/cmspcs.c index f2ebf53bf96..6c6773620c5 100644 --- a/src/java.desktop/share/native/liblcms/cmspcs.c +++ b/src/java.desktop/share/native/liblcms/cmspcs.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -685,9 +685,9 @@ cmsFloat64Number CMSEXPORT cmsCIE2000DeltaE(const cmsCIELab* Lab1, const cmsCIEL // This function returns a number of gridpoints to be used as LUT table. It assumes same number // of gripdpoints in all dimensions. Flags may override the choice. -int _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags) +cmsUInt32Number _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags) { - int nChannels; + cmsUInt32Number nChannels; // Already specified? if (dwFlags & 0x00FF0000) { @@ -831,7 +831,7 @@ cmsColorSpaceSignature CMSEXPORT _cmsICCcolorSpace(int OurNotation) case PT_MCH14: return cmsSigMCHEData; case PT_MCH15: return cmsSigMCHFData; - default: return (cmsColorSpaceSignature) (-1); + default: return (cmsColorSpaceSignature) 0; } } @@ -898,7 +898,7 @@ int CMSEXPORT _cmsLCMScolorSpace(cmsColorSpaceSignature ProfileSpace) case cmsSigMCHFData: case cmsSig15colorData:return PT_MCH15; - default: return (cmsColorSpaceSignature) (-1); + default: return (cmsColorSpaceSignature) 0; } } diff --git a/src/java.desktop/share/native/liblcms/cmsplugin.c b/src/java.desktop/share/native/liblcms/cmsplugin.c index 683c8305980..e7100c8ea60 100644 --- a/src/java.desktop/share/native/liblcms/cmsplugin.c +++ b/src/java.desktop/share/native/liblcms/cmsplugin.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -201,14 +201,28 @@ cmsBool CMSEXPORT _cmsReadFloat32Number(cmsIOHANDLER* io, cmsFloat32Number* n) _cmsAssert(io != NULL); - if (io -> Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1) - return FALSE; + if (io->Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1) + return FALSE; if (n != NULL) { tmp = _cmsAdjustEndianess32(tmp); - *n = *(cmsFloat32Number*) (void*) &tmp; + *n = *(cmsFloat32Number*)(void*)&tmp; + + // Safeguard which covers against absurd values + if (*n > 1E+20 || *n < -1E+20) return FALSE; + + #if defined(_MSC_VER) && _MSC_VER < 1800 + return TRUE; + #elif defined (__BORLANDC__) + return TRUE; + #else + + // fpclassify() required by C99 (only provided by MSVC >= 1800, VS2013 onwards) + return ((fpclassify(*n) == FP_ZERO) || (fpclassify(*n) == FP_NORMAL)); + #endif } + return TRUE; } @@ -222,7 +236,11 @@ cmsBool CMSEXPORT _cmsReadUInt64Number(cmsIOHANDLER* io, cmsUInt64Number* n) if (io -> Read(io, &tmp, sizeof(cmsUInt64Number), 1) != 1) return FALSE; - if (n != NULL) _cmsAdjustEndianess64(n, &tmp); + if (n != NULL) { + + _cmsAdjustEndianess64(n, &tmp); + } + return TRUE; } @@ -237,7 +255,7 @@ cmsBool CMSEXPORT _cmsRead15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number* n return FALSE; if (n != NULL) { - *n = _cms15Fixed16toDouble(_cmsAdjustEndianess32(tmp)); + *n = _cms15Fixed16toDouble((cmsS15Fixed16Number) _cmsAdjustEndianess32(tmp)); } return TRUE; @@ -254,9 +272,9 @@ cmsBool CMSEXPORT _cmsReadXYZNumber(cmsIOHANDLER* io, cmsCIEXYZ* XYZ) if (XYZ != NULL) { - XYZ->X = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.X)); - XYZ->Y = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.Y)); - XYZ->Z = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.Z)); + XYZ->X = _cms15Fixed16toDouble((cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) xyz.X)); + XYZ->Y = _cms15Fixed16toDouble((cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) xyz.Y)); + XYZ->Z = _cms15Fixed16toDouble((cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) xyz.Z)); } return TRUE; } @@ -345,7 +363,7 @@ cmsBool CMSEXPORT _cmsWrite15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number n _cmsAssert(io != NULL); - tmp = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(n)); + tmp = _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(n)); if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1) return FALSE; @@ -359,9 +377,9 @@ cmsBool CMSEXPORT _cmsWriteXYZNumber(cmsIOHANDLER* io, const cmsCIEXYZ* XYZ) _cmsAssert(io != NULL); _cmsAssert(XYZ != NULL); - xyz.X = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(XYZ->X)); - xyz.Y = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(XYZ->Y)); - xyz.Z = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(XYZ->Z)); + xyz.X = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(XYZ->X)); + xyz.Y = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(XYZ->Y)); + xyz.Z = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(XYZ->Z)); return io -> Write(io, sizeof(cmsEncodedXYZNumber), &xyz); } @@ -519,7 +537,7 @@ cmsBool CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...) return FALSE; // Truncated, which is a fatal error for us } - rc = io ->Write(io, len, Buffer); + rc = io ->Write(io, (cmsUInt32Number) len, Buffer); va_end(args); @@ -779,6 +797,30 @@ cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData) struct _cmsContext_struct* ctx; struct _cmsContext_struct fakeContext; + // See the comments regarding locking in lcms2_internal.h + // for an explanation of why we need the following code. +#ifdef CMS_IS_WINDOWS_ +#ifndef CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT + { + static HANDLE _cmsWindowsInitMutex = NULL; + static volatile HANDLE* mutex = &_cmsWindowsInitMutex; + + if (*mutex == NULL) + { + HANDLE p = CreateMutex(NULL, FALSE, NULL); + if (p && InterlockedCompareExchangePointer((void **)mutex, (void*)p, NULL) != NULL) + CloseHandle(p); + } + if (*mutex == NULL || WaitForSingleObject(*mutex, INFINITE) == WAIT_FAILED) + return NULL; + if (((void **)&_cmsContextPoolHeadMutex)[0] == NULL) + InitializeCriticalSection(&_cmsContextPoolHeadMutex); + if (*mutex == NULL || !ReleaseMutex(*mutex)) + return NULL; + } +#endif +#endif + _cmsInstallAllocFunctions(_cmsFindMemoryPlugin(Plugin), &fakeContext.DefaultMemoryManager); fakeContext.chunks[UserPtr] = UserData; @@ -805,7 +847,7 @@ cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData) ctx ->chunks[MemPlugin] = &ctx->DefaultMemoryManager; // Now we can allocate the pool by using default memory manager - ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*)); // default size about 32 pointers + ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*)); // default size about 22 pointers if (ctx ->MemPool == NULL) { cmsDeleteContext(ctx); diff --git a/src/java.desktop/share/native/liblcms/cmsps2.c b/src/java.desktop/share/native/liblcms/cmsps2.c index 03d476bc367..a3c7b49dbff 100644 --- a/src/java.desktop/share/native/liblcms/cmsps2.c +++ b/src/java.desktop/share/native/liblcms/cmsps2.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -429,7 +429,7 @@ void EmitRangeCheck(cmsIOHANDLER* m) // Does write the intent static -void EmitIntent(cmsIOHANDLER* m, int RenderingIntent) +void EmitIntent(cmsIOHANDLER* m, cmsUInt32Number RenderingIntent) { const char *intent; @@ -563,7 +563,7 @@ void Emit1Gamma(cmsIOHANDLER* m, cmsToneCurve* Table) // Compare gamma table static -cmsBool GammaTableEquals(cmsUInt16Number* g1, cmsUInt16Number* g2, int nEntries) +cmsBool GammaTableEquals(cmsUInt16Number* g1, cmsUInt16Number* g2, cmsUInt32Number nEntries) { return memcmp(g1, g2, nEntries* sizeof(cmsUInt16Number)) == 0; } @@ -572,9 +572,9 @@ cmsBool GammaTableEquals(cmsUInt16Number* g1, cmsUInt16Number* g2, int nEntries) // Does write a set of gamma curves static -void EmitNGamma(cmsIOHANDLER* m, int n, cmsToneCurve* g[]) +void EmitNGamma(cmsIOHANDLER* m, cmsUInt32Number n, cmsToneCurve* g[]) { - int i; + cmsUInt32Number i; for( i=0; i < n; i++ ) { @@ -797,7 +797,7 @@ int EmitCIEBasedABC(cmsIOHANDLER* m, cmsFloat64Number* Matrix, cmsToneCurve** Cu static -int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, int Intent, cmsCIEXYZ* BlackPoint) +int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, cmsUInt32Number Intent, cmsCIEXYZ* BlackPoint) { const char* PreMaj; const char* PostMaj; @@ -857,14 +857,14 @@ int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, int Intent, cmsCIEXY // Generates a curve from a gray profile static - cmsToneCurve* ExtractGray2Y(cmsContext ContextID, cmsHPROFILE hProfile, int Intent) +cmsToneCurve* ExtractGray2Y(cmsContext ContextID, cmsHPROFILE hProfile, cmsUInt32Number Intent) { cmsToneCurve* Out = cmsBuildTabulatedToneCurve16(ContextID, 256, NULL); cmsHPROFILE hXYZ = cmsCreateXYZProfile(); cmsHTRANSFORM xform = cmsCreateTransformTHR(ContextID, hProfile, TYPE_GRAY_8, hXYZ, TYPE_XYZ_DBL, Intent, cmsFLAGS_NOOPTIMIZE); int i; - if (Out != NULL) { + if (Out != NULL && xform != NULL) { for (i=0; i < 256; i++) { cmsUInt8Number Gray = (cmsUInt8Number) i; @@ -876,8 +876,8 @@ static } } - cmsDeleteTransform(xform); - cmsCloseProfile(hXYZ); + if (xform) cmsDeleteTransform(xform); + if (hXYZ) cmsCloseProfile(hXYZ); return Out; } @@ -887,7 +887,7 @@ static // a more perceptually uniform space... I do choose Lab. static -int WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32Number dwFlags) +int WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags) { cmsHPROFILE hLab; cmsHTRANSFORM xform; @@ -972,7 +972,6 @@ cmsFloat64Number* GetPtrToMatrix(const cmsStage* mpe) // Does create CSA based on matrix-shaper. Allowed types are gray and RGB based - static int WriteInputMatrixShaper(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsStage* Matrix, cmsStage* Shaper) { @@ -998,17 +997,17 @@ int WriteInputMatrixShaper(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsStage* Matr memmove(&Mat, GetPtrToMatrix(Matrix), sizeof(Mat)); - for (i=0; i < 3; i++) - for (j=0; j < 3; j++) + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) Mat.v[i].n[j] *= MAX_ENCODEABLE_XYZ; - rc = EmitCIEBasedABC(m, (cmsFloat64Number *) &Mat, - _cmsStageGetPtrToCurveSet(Shaper), - &BlackPointAdaptedToD50); + rc = EmitCIEBasedABC(m, (cmsFloat64Number *)&Mat, + _cmsStageGetPtrToCurveSet(Shaper), + &BlackPointAdaptedToD50); } - else { + else { - cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Profile is not suitable for CSA. Unsupported colorspace."); + cmsSignalError(m->ContextID, cmsERROR_COLORSPACE_CHECK, "Profile is not suitable for CSA. Unsupported colorspace."); return 0; } @@ -1021,12 +1020,12 @@ int WriteInputMatrixShaper(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsStage* Matr // This is a HP extension, and it works in Lab instead of XYZ static -int WriteNamedColorCSA(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, int Intent) +int WriteNamedColorCSA(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, cmsUInt32Number Intent) { cmsHTRANSFORM xform; cmsHPROFILE hLab; - int i, nColors; - char ColorName[32]; + cmsUInt32Number i, nColors; + char ColorName[cmsMAX_PATH]; cmsNAMEDCOLORLIST* NamedColorList; hLab = cmsCreateLab4ProfileTHR(m ->ContextID, NULL); @@ -1304,20 +1303,20 @@ void EmitXYZ2Lab(cmsIOHANDLER* m) // 8 bits. static -int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32Number dwFlags) +int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags) { cmsHPROFILE hLab; cmsHTRANSFORM xform; - int i, nChannels; + cmsUInt32Number i, nChannels; cmsUInt32Number OutputFormat; _cmsTRANSFORM* v; cmsPipeline* DeviceLink; cmsHPROFILE Profiles[3]; cmsCIEXYZ BlackPointAdaptedToD50; - cmsBool lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION); - cmsBool lFixWhite = !(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP); + cmsBool lDoBPC = (cmsBool) (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION); + cmsBool lFixWhite = (cmsBool) !(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP); cmsUInt32Number InFrm = TYPE_Lab_16; - int RelativeEncodingIntent; + cmsUInt32Number RelativeEncodingIntent; cmsColorSpaceSignature ColorSpace; @@ -1413,10 +1412,10 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32N // Builds a ASCII string containing colorant list in 0..1.0 range static -void BuildColorantList(char *Colorant, int nColorant, cmsUInt16Number Out[]) +void BuildColorantList(char *Colorant, cmsUInt32Number nColorant, cmsUInt16Number Out[]) { char Buff[32]; - int j; + cmsUInt32Number j; Colorant[0] = 0; if (nColorant > cmsMAXCHANNELS) @@ -1438,12 +1437,12 @@ void BuildColorantList(char *Colorant, int nColorant, cmsUInt16Number Out[]) // This is a HP extension. static -int WriteNamedColorCRD(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, int Intent, cmsUInt32Number dwFlags) +int WriteNamedColorCRD(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, cmsUInt32Number Intent, cmsUInt32Number dwFlags) { cmsHTRANSFORM xform; - int i, nColors, nColorant; + cmsUInt32Number i, nColors, nColorant; cmsUInt32Number OutputFormat; - char ColorName[32]; + char ColorName[cmsMAX_PATH]; char Colorant[128]; cmsNAMEDCOLORLIST* NamedColorList; diff --git a/src/java.desktop/share/native/liblcms/cmssamp.c b/src/java.desktop/share/native/liblcms/cmssamp.c index b22c427323e..1e38e4f3188 100644 --- a/src/java.desktop/share/native/liblcms/cmssamp.c +++ b/src/java.desktop/share/native/liblcms/cmssamp.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), diff --git a/src/java.desktop/share/native/liblcms/cmssm.c b/src/java.desktop/share/native/liblcms/cmssm.c index 1923a02841a..38e08fc9a4f 100644 --- a/src/java.desktop/share/native/liblcms/cmssm.c +++ b/src/java.desktop/share/native/liblcms/cmssm.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), diff --git a/src/java.desktop/share/native/liblcms/cmstypes.c b/src/java.desktop/share/native/liblcms/cmstypes.c index ebf81c83b39..d0d4d24829e 100644 --- a/src/java.desktop/share/native/liblcms/cmstypes.c +++ b/src/java.desktop/share/native/liblcms/cmstypes.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -89,6 +89,11 @@ typedef struct _cmsTagTypeLinkedList_st { // Helper macro to define a MPE handler. Callbacks do have a fixed naming convention #define TYPE_MPE_HANDLER(t, x) { (t), READ_FN(x), WRITE_FN(x), GenericMPEdup, GenericMPEfree, NULL, 0 } +// Infinites +#define MINUS_INF (-1E22F) +#define PLUS_INF (+1E22F) + + // Register a new type handler. This routine is shared between normal types and MPE. LinkedList points to the optional list head static cmsBool RegisterTypesPlugin(cmsContext id, cmsPluginBase* Data, _cmsMemoryClient pos) @@ -202,6 +207,13 @@ cmsBool ReadPositionTable(struct _cms_typehandler_struct* self, { cmsUInt32Number i; cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL; + cmsUInt32Number currentPosition; + + currentPosition = io->Tell(io); + + // Verify there is enough space left to read at least two cmsUInt32Number items for Count items. + if (((io->ReportedSize - currentPosition) / (2 * sizeof(cmsUInt32Number))) < Count) + return FALSE; // Let's take the offsets to each element ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number)); @@ -424,8 +436,8 @@ void *Type_Chromaticity_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* static cmsBool SaveOneChromaticity(cmsFloat64Number x, cmsFloat64Number y, cmsIOHANDLER* io) { - if (!_cmsWriteUInt32Number(io, _cmsDoubleTo15Fixed16(x))) return FALSE; - if (!_cmsWriteUInt32Number(io, _cmsDoubleTo15Fixed16(y))) return FALSE; + if (!_cmsWriteUInt32Number(io, (cmsUInt32Number) _cmsDoubleTo15Fixed16(x))) return FALSE; + if (!_cmsWriteUInt32Number(io, (cmsUInt32Number) _cmsDoubleTo15Fixed16(y))) return FALSE; return TRUE; } @@ -984,7 +996,7 @@ cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO cmsBool rc = FALSE; char Filler[68]; - // Used below for writting zeroes + // Used below for writing zeroes memset(Filler, 0, sizeof(Filler)); // Get the len of string @@ -1146,7 +1158,10 @@ void *Type_Curve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm NewGamma = cmsBuildTabulatedToneCurve16(self ->ContextID, Count, NULL); if (!NewGamma) return NULL; - if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) return NULL; + if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) { + cmsFreeToneCurve(NewGamma); + return NULL; + } *nItems = 1; return NewGamma; @@ -1206,7 +1221,7 @@ void Type_Curve_Free(struct _cms_typehandler_struct* self, void* Ptr) // ******************************************************************************** -// Decide which curve type to use on writting +// Decide which curve type to use on writing static cmsTagTypeSignature DecideCurveType(cmsFloat64Number ICCVersion, const void *Data) { @@ -1599,7 +1614,7 @@ void Type_MLU_Free(struct _cms_typehandler_struct* self, void* Ptr) // Type cmsSigLut8Type // ******************************************************************************** -// Decide which LUT type to use on writting +// Decide which LUT type to use on writing static cmsTagTypeSignature DecideLUTtypeA2B(cmsFloat64Number ICCVersion, const void *Data) { @@ -1648,10 +1663,10 @@ Byte Position Field Length (bytes) Content Encoded as... // Read 8 bit tables as gamma functions static -cmsBool Read8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels) +cmsBool Read8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, cmsUInt32Number nChannels) { cmsUInt8Number* Temp = NULL; - int i, j; + cmsUInt32Number i, j; cmsToneCurve* Tables[cmsMAXCHANNELS]; if (nChannels > cmsMAXCHANNELS) return FALSE; @@ -1784,8 +1799,8 @@ void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cms if (!_cmsReadUInt8Number(io, NULL)) goto Error; // Do some checking - if (InputChannels > cmsMAXCHANNELS) goto Error; - if (OutputChannels > cmsMAXCHANNELS) goto Error; + if (InputChannels == 0 || InputChannels > cmsMAXCHANNELS) goto Error; + if (OutputChannels == 0 || OutputChannels > cmsMAXCHANNELS) goto Error; // Allocates an empty Pipeline NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels); @@ -1842,8 +1857,10 @@ void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cms _cmsFree(self ->ContextID, Temp); Temp = NULL; - if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T))) + if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T))) { + _cmsFree(self ->ContextID, T); goto Error; + } _cmsFree(self ->ContextID, T); } @@ -1872,7 +1889,7 @@ cmsBool Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL; _cmsStageMatrixData* MatMPE = NULL; _cmsStageCLutData* clut = NULL; - int clutPoints; + cmsUInt32Number clutPoints; // Disassemble the LUT into components. mpe = NewLUT -> Elements; @@ -1992,9 +2009,10 @@ void Type_LUT8_Free(struct _cms_typehandler_struct* self, void* Ptr) // Read 16 bit tables as gamma functions static -cmsBool Read16bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels, int nEntries) +cmsBool Read16bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, + cmsUInt32Number nChannels, cmsUInt32Number nEntries) { - int i; + cmsUInt32Number i; cmsToneCurve* Tables[cmsMAXCHANNELS]; // Maybe an empty table? (this is a lcms extension) @@ -2036,10 +2054,10 @@ cmsBool Read16bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lu static cmsBool Write16bitTables(cmsContext ContextID, cmsIOHANDLER* io, _cmsStageToneCurvesData* Tables) { - int j; + cmsUInt32Number j; cmsUInt32Number i; cmsUInt16Number val; - int nEntries; + cmsUInt32Number nEntries; _cmsAssert(Tables != NULL); @@ -2077,8 +2095,8 @@ void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm if (!_cmsReadUInt8Number(io, NULL)) return NULL; // Do some checking - if (InputChannels > cmsMAXCHANNELS) goto Error; - if (OutputChannels > cmsMAXCHANNELS) goto Error; + if (InputChannels == 0 || InputChannels > cmsMAXCHANNELS) goto Error; + if (OutputChannels == 0 || OutputChannels > cmsMAXCHANNELS) goto Error; // Allocates an empty LUT NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels); @@ -2160,7 +2178,7 @@ cmsBool Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL; _cmsStageMatrixData* MatMPE = NULL; _cmsStageCLutData* clut = NULL; - int i, InputChannels, OutputChannels, clutPoints; + cmsUInt32Number i, InputChannels, OutputChannels, clutPoints; // Disassemble the LUT into components. mpe = NewLUT -> Elements; @@ -2346,7 +2364,8 @@ cmsStage* ReadMatrix(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cms // V4 stuff. Read CLUT part for LutAtoB and LutBtoA static -cmsStage* ReadCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset, int InputChannels, int OutputChannels) +cmsStage* ReadCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, + cmsUInt32Number Offset, cmsUInt32Number InputChannels, cmsUInt32Number OutputChannels) { cmsUInt8Number gridPoints8[cmsMAXCHANNELS]; // Number of grid points in each dimension. cmsUInt32Number GridPoints[cmsMAXCHANNELS], i; @@ -2382,7 +2401,10 @@ cmsStage* ReadCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUI for (i=0; i < Data ->nEntries; i++) { - if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) return NULL; + if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) { + cmsStageFree(CLUT); + return NULL; + } Data ->Tab.T[i] = FROM_8_TO_16(v); } @@ -2512,7 +2534,10 @@ void* Type_LUTA2B_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, c if (!_cmsReadUInt32Number(io, &offsetC)) return NULL; if (!_cmsReadUInt32Number(io, &offsetA)) return NULL; - // Allocates an empty LUT + if (inputChan == 0 || inputChan >= cmsMAXCHANNELS) return NULL; + if (outputChan == 0 || outputChan >= cmsMAXCHANNELS) return NULL; + + // Allocates an empty LUT NewLUT = cmsPipelineAlloc(self ->ContextID, inputChan, outputChan); if (NewLUT == NULL) return NULL; @@ -2694,7 +2719,7 @@ static cmsBool Type_LUTA2B_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) { cmsPipeline* Lut = (cmsPipeline*) Ptr; - int inputChan, outputChan; + cmsUInt32Number inputChan, outputChan; cmsStage *A = NULL, *B = NULL, *M = NULL; cmsStage * Matrix = NULL; cmsStage * CLUT = NULL; @@ -2742,7 +2767,7 @@ cmsBool Type_LUTA2B_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io if (CLUT != NULL) { offsetC = io ->Tell(io) - BaseOffset; - if (!WriteCLUT(self, io, Lut ->SaveAs8Bits ? 1 : 2, CLUT)) return FALSE; + if (!WriteCLUT(self, io, (Lut ->SaveAs8Bits ? 1U : 2U), CLUT)) return FALSE; } if (M != NULL) { @@ -2820,6 +2845,9 @@ void* Type_LUTB2A_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, c if (!_cmsReadUInt8Number(io, &inputChan)) return NULL; if (!_cmsReadUInt8Number(io, &outputChan)) return NULL; + if (inputChan == 0 || inputChan >= cmsMAXCHANNELS) return NULL; + if (outputChan == 0 || outputChan >= cmsMAXCHANNELS) return NULL; + // Padding if (!_cmsReadUInt16Number(io, NULL)) return NULL; @@ -2879,7 +2907,7 @@ static cmsBool Type_LUTB2A_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) { cmsPipeline* Lut = (cmsPipeline*) Ptr; - int inputChan, outputChan; + cmsUInt32Number inputChan, outputChan; cmsStage *A = NULL, *B = NULL, *M = NULL; cmsStage *Matrix = NULL; cmsStage *CLUT = NULL; @@ -2921,7 +2949,7 @@ cmsBool Type_LUTB2A_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* i if (CLUT != NULL) { offsetC = io ->Tell(io) - BaseOffset; - if (!WriteCLUT(self, io, Lut ->SaveAs8Bits ? 1 : 2, CLUT)) return FALSE; + if (!WriteCLUT(self, io, (Lut ->SaveAs8Bits ? 1U : 2U), CLUT)) return FALSE; } if (M != NULL) { @@ -3011,7 +3039,7 @@ void *Type_ColorantTable_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER for (i=0; i < Count; i++) { if (io ->Read(io, Name, 32, 1) != 1) goto Error; - Name[33] = 0; + Name[32] = 0; if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error; @@ -3037,7 +3065,7 @@ static cmsBool Type_ColorantTable_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) { cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr; - int i, nColors; + cmsUInt32Number i, nColors; nColors = cmsNamedColorCount(NamedColorList); @@ -3045,9 +3073,11 @@ cmsBool Type_ColorantTable_Write(struct _cms_typehandler_struct* self, cmsIOHAN for (i=0; i < nColors; i++) { - char root[33]; + char root[cmsMAX_PATH]; cmsUInt16Number PCS[3]; + memset(root, 0, sizeof(root)); + if (!cmsNamedColorInfo(NamedColorList, i, root, NULL, NULL, PCS, NULL)) return 0; root[32] = 0; @@ -3107,8 +3137,8 @@ void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i cmsUInt32Number nDeviceCoords; // Num of device coordinates char prefix[32]; // Prefix for each color name char suffix[32]; // Suffix for each color name - cmsNAMEDCOLORLIST* v; - cmsUInt32Number i; + cmsNAMEDCOLORLIST* v; + cmsUInt32Number i; *nItems = 0; @@ -3129,7 +3159,7 @@ void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i if (nDeviceCoords > cmsMAXCHANNELS) { cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many device coordinates '%d'", nDeviceCoords); - return 0; + goto Error; } for (i=0; i < count; i++) { @@ -3138,7 +3168,7 @@ void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i char Root[33]; memset(Colorant, 0, sizeof(Colorant)); - if (io -> Read(io, Root, 32, 1) != 1) return NULL; + if (io -> Read(io, Root, 32, 1) != 1) goto Error; Root[32] = 0; // To prevent exploits if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error; @@ -3165,7 +3195,7 @@ cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr; char prefix[33]; // Prefix for each color name char suffix[33]; // Suffix for each color name - int i, nColors; + cmsUInt32Number i, nColors; nColors = cmsNamedColorCount(NamedColorList); @@ -3185,7 +3215,7 @@ cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER cmsUInt16Number PCS[3]; cmsUInt16Number Colorant[cmsMAXCHANNELS]; - char Root[33]; + char Root[cmsMAX_PATH]; if (!cmsNamedColorInfo(NamedColorList, i, Root, NULL, NULL, PCS, Colorant)) return 0; Root[32] = 0; @@ -3939,7 +3969,7 @@ cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHAND cmsUInt16Number nSegments; cmsCurveSegment* Segments; cmsToneCurve* Curve; - cmsFloat32Number PrevBreak = -1E22F; // - infinite + cmsFloat32Number PrevBreak = MINUS_INF; // - infinite // Take signature and channels for each element. if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) return NULL; @@ -3964,7 +3994,7 @@ cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHAND } Segments[nSegments-1].x0 = PrevBreak; - Segments[nSegments-1].x1 = 1E22F; // A big cmsFloat32Number number + Segments[nSegments-1].x1 = PLUS_INF; // A big cmsFloat32Number number // Read segments for (i=0; i < nSegments; i++) { @@ -3998,7 +4028,7 @@ cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHAND case cmsSigSampledCurveSeg: { cmsUInt32Number Count; - if (!_cmsReadUInt32Number(io, &Count)) return NULL; + if (!_cmsReadUInt32Number(io, &Count)) goto Error; Segments[i].nGridPoints = Count; Segments[i].SampledPoints = (cmsFloat32Number*) _cmsCalloc(self ->ContextID, Count, sizeof(cmsFloat32Number)); @@ -4017,7 +4047,7 @@ cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHAND _cmsTagSignature2String(String, (cmsTagSignature) ElementSig); cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown curve element type '%s' found.", String); } - return NULL; + goto Error; } } @@ -4031,7 +4061,12 @@ cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHAND return Curve; Error: - if (Segments) _cmsFree(self ->ContextID, Segments); + if (Segments) { + for (i=0; i < nSegments; i++) { + if (Segments[i].SampledPoints) _cmsFree(self ->ContextID, Segments[i].SampledPoints); + } + _cmsFree(self ->ContextID, Segments); + } return NULL; } @@ -4085,7 +4120,7 @@ void *Type_MPEcurve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, } _cmsFree(self ->ContextID, GammaTables); - *nItems = (mpe != NULL) ? 1 : 0; + *nItems = (mpe != NULL) ? 1U : 0; return mpe; cmsUNUSED_PARAMETER(SizeOfTag); @@ -4216,9 +4251,13 @@ void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL; - nElems = InputChans * OutputChans; + // Input and output chans may be ANY (up to 0xffff), + // but we choose to limit to 16 channels for now + if (InputChans >= cmsMAXCHANNELS) return NULL; + if (OutputChans >= cmsMAXCHANNELS) return NULL; + + nElems = (cmsUInt32Number) InputChans * OutputChans; - // Input and output chans may be ANY (up to 0xffff) Matrix = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, nElems, sizeof(cmsFloat64Number)); if (Matrix == NULL) return NULL; @@ -4233,7 +4272,11 @@ void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io cmsFloat32Number v; - if (!_cmsReadFloat32Number(io, &v)) return NULL; + if (!_cmsReadFloat32Number(io, &v)) { + _cmsFree(self ->ContextID, Matrix); + _cmsFree(self ->ContextID, Offsets); + return NULL; + } Matrix[i] = v; } @@ -4242,7 +4285,11 @@ void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io cmsFloat32Number v; - if (!_cmsReadFloat32Number(io, &v)) return NULL; + if (!_cmsReadFloat32Number(io, &v)) { + _cmsFree(self ->ContextID, Matrix); + _cmsFree(self ->ContextID, Offsets); + return NULL; + } Offsets[i] = v; } @@ -4313,8 +4360,9 @@ void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, goto Error; // Copy MAX_INPUT_DIMENSIONS at most. Expand to cmsUInt32Number - nMaxGrids = InputChans > MAX_INPUT_DIMENSIONS ? MAX_INPUT_DIMENSIONS : InputChans; - for (i=0; i < nMaxGrids; i++) { + nMaxGrids = InputChans > MAX_INPUT_DIMENSIONS ? (cmsUInt32Number) MAX_INPUT_DIMENSIONS : InputChans; + + for (i = 0; i < nMaxGrids; i++) { if (Dimensions8[i] == 1) goto Error; // Impossible value, 0 for no CLUT and then 2 at least GridPoints[i] = (cmsUInt32Number)Dimensions8[i]; } @@ -4323,11 +4371,11 @@ void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, mpe = cmsStageAllocCLutFloatGranular(self ->ContextID, GridPoints, InputChans, OutputChans, NULL); if (mpe == NULL) goto Error; - // Read the data + // Read and sanitize the data clut = (_cmsStageCLutData*) mpe ->Data; for (i=0; i < clut ->nEntries; i++) { - if (!_cmsReadFloat32Number(io, &clut ->Tab.TFloat[i])) goto Error; + if (!_cmsReadFloat32Number(io, &clut->Tab.TFloat[i])) goto Error; } *nItems = 1; @@ -4457,6 +4505,9 @@ void *Type_MPE_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsU if (!_cmsReadUInt16Number(io, &InputChans)) return NULL; if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL; + if (InputChans == 0 || InputChans >= cmsMAXCHANNELS) return NULL; + if (OutputChans == 0 || OutputChans >= cmsMAXCHANNELS) return NULL; + // Allocates an empty LUT NewLUT = cmsPipelineAlloc(self ->ContextID, InputChans, OutputChans); if (NewLUT == NULL) return NULL; @@ -4464,6 +4515,10 @@ void *Type_MPE_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsU if (!_cmsReadUInt32Number(io, &ElementCount)) goto Error; if (!ReadPositionTable(self, io, ElementCount, BaseOffset, NewLUT, ReadMPEElem)) goto Error; + // Check channel count + if (InputChans != NewLUT->InputChannels || + OutputChans != NewLUT->OutputChannels) goto Error; + // Success *nItems = 1; return NewLUT; @@ -4484,7 +4539,7 @@ static cmsBool Type_MPE_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) { cmsUInt32Number i, BaseOffset, DirectoryPos, CurrentPos; - int inputChan, outputChan; + cmsUInt32Number inputChan, outputChan; cmsUInt32Number ElemCount; cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL, Before; cmsStageSignature ElementSig; @@ -4532,7 +4587,7 @@ cmsBool Type_MPE_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, v _cmsTagSignature2String(String, (cmsTagSignature) ElementSig); - // An unknow element was found. + // An unknown element was found. cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Found unknown MPE type '%s'", String); goto Error; } @@ -5267,38 +5322,38 @@ void Type_Dictionary_Free(struct _cms_typehandler_struct* self, void* Ptr) // This is the list of built-in types -static _cmsTagTypeLinkedList SupportedTagTypes[] = { - -{TYPE_HANDLER(cmsSigChromaticityType, Chromaticity), &SupportedTagTypes[1] }, -{TYPE_HANDLER(cmsSigColorantOrderType, ColorantOrderType), &SupportedTagTypes[2] }, -{TYPE_HANDLER(cmsSigS15Fixed16ArrayType, S15Fixed16), &SupportedTagTypes[3] }, -{TYPE_HANDLER(cmsSigU16Fixed16ArrayType, U16Fixed16), &SupportedTagTypes[4] }, -{TYPE_HANDLER(cmsSigTextType, Text), &SupportedTagTypes[5] }, -{TYPE_HANDLER(cmsSigTextDescriptionType, Text_Description), &SupportedTagTypes[6] }, -{TYPE_HANDLER(cmsSigCurveType, Curve), &SupportedTagTypes[7] }, -{TYPE_HANDLER(cmsSigParametricCurveType, ParametricCurve), &SupportedTagTypes[8] }, -{TYPE_HANDLER(cmsSigDateTimeType, DateTime), &SupportedTagTypes[9] }, -{TYPE_HANDLER(cmsSigLut8Type, LUT8), &SupportedTagTypes[10] }, -{TYPE_HANDLER(cmsSigLut16Type, LUT16), &SupportedTagTypes[11] }, -{TYPE_HANDLER(cmsSigColorantTableType, ColorantTable), &SupportedTagTypes[12] }, -{TYPE_HANDLER(cmsSigNamedColor2Type, NamedColor), &SupportedTagTypes[13] }, -{TYPE_HANDLER(cmsSigMultiLocalizedUnicodeType, MLU), &SupportedTagTypes[14] }, -{TYPE_HANDLER(cmsSigProfileSequenceDescType, ProfileSequenceDesc), &SupportedTagTypes[15] }, -{TYPE_HANDLER(cmsSigSignatureType, Signature), &SupportedTagTypes[16] }, -{TYPE_HANDLER(cmsSigMeasurementType, Measurement), &SupportedTagTypes[17] }, -{TYPE_HANDLER(cmsSigDataType, Data), &SupportedTagTypes[18] }, -{TYPE_HANDLER(cmsSigLutAtoBType, LUTA2B), &SupportedTagTypes[19] }, -{TYPE_HANDLER(cmsSigLutBtoAType, LUTB2A), &SupportedTagTypes[20] }, -{TYPE_HANDLER(cmsSigUcrBgType, UcrBg), &SupportedTagTypes[21] }, -{TYPE_HANDLER(cmsSigCrdInfoType, CrdInfo), &SupportedTagTypes[22] }, -{TYPE_HANDLER(cmsSigMultiProcessElementType, MPE), &SupportedTagTypes[23] }, -{TYPE_HANDLER(cmsSigScreeningType, Screening), &SupportedTagTypes[24] }, -{TYPE_HANDLER(cmsSigViewingConditionsType, ViewingConditions), &SupportedTagTypes[25] }, -{TYPE_HANDLER(cmsSigXYZType, XYZ), &SupportedTagTypes[26] }, -{TYPE_HANDLER(cmsCorbisBrokenXYZtype, XYZ), &SupportedTagTypes[27] }, -{TYPE_HANDLER(cmsMonacoBrokenCurveType, Curve), &SupportedTagTypes[28] }, -{TYPE_HANDLER(cmsSigProfileSequenceIdType, ProfileSequenceId), &SupportedTagTypes[29] }, -{TYPE_HANDLER(cmsSigDictType, Dictionary), &SupportedTagTypes[30] }, +static const _cmsTagTypeLinkedList SupportedTagTypes[] = { + +{TYPE_HANDLER(cmsSigChromaticityType, Chromaticity), (_cmsTagTypeLinkedList*) &SupportedTagTypes[1] }, +{TYPE_HANDLER(cmsSigColorantOrderType, ColorantOrderType), (_cmsTagTypeLinkedList*) &SupportedTagTypes[2] }, +{TYPE_HANDLER(cmsSigS15Fixed16ArrayType, S15Fixed16), (_cmsTagTypeLinkedList*) &SupportedTagTypes[3] }, +{TYPE_HANDLER(cmsSigU16Fixed16ArrayType, U16Fixed16), (_cmsTagTypeLinkedList*) &SupportedTagTypes[4] }, +{TYPE_HANDLER(cmsSigTextType, Text), (_cmsTagTypeLinkedList*) &SupportedTagTypes[5] }, +{TYPE_HANDLER(cmsSigTextDescriptionType, Text_Description), (_cmsTagTypeLinkedList*) &SupportedTagTypes[6] }, +{TYPE_HANDLER(cmsSigCurveType, Curve), (_cmsTagTypeLinkedList*) &SupportedTagTypes[7] }, +{TYPE_HANDLER(cmsSigParametricCurveType, ParametricCurve), (_cmsTagTypeLinkedList*) &SupportedTagTypes[8] }, +{TYPE_HANDLER(cmsSigDateTimeType, DateTime), (_cmsTagTypeLinkedList*) &SupportedTagTypes[9] }, +{TYPE_HANDLER(cmsSigLut8Type, LUT8), (_cmsTagTypeLinkedList*) &SupportedTagTypes[10] }, +{TYPE_HANDLER(cmsSigLut16Type, LUT16), (_cmsTagTypeLinkedList*) &SupportedTagTypes[11] }, +{TYPE_HANDLER(cmsSigColorantTableType, ColorantTable), (_cmsTagTypeLinkedList*) &SupportedTagTypes[12] }, +{TYPE_HANDLER(cmsSigNamedColor2Type, NamedColor), (_cmsTagTypeLinkedList*) &SupportedTagTypes[13] }, +{TYPE_HANDLER(cmsSigMultiLocalizedUnicodeType, MLU), (_cmsTagTypeLinkedList*) &SupportedTagTypes[14] }, +{TYPE_HANDLER(cmsSigProfileSequenceDescType, ProfileSequenceDesc),(_cmsTagTypeLinkedList*) &SupportedTagTypes[15] }, +{TYPE_HANDLER(cmsSigSignatureType, Signature), (_cmsTagTypeLinkedList*) &SupportedTagTypes[16] }, +{TYPE_HANDLER(cmsSigMeasurementType, Measurement), (_cmsTagTypeLinkedList*) &SupportedTagTypes[17] }, +{TYPE_HANDLER(cmsSigDataType, Data), (_cmsTagTypeLinkedList*) &SupportedTagTypes[18] }, +{TYPE_HANDLER(cmsSigLutAtoBType, LUTA2B), (_cmsTagTypeLinkedList*) &SupportedTagTypes[19] }, +{TYPE_HANDLER(cmsSigLutBtoAType, LUTB2A), (_cmsTagTypeLinkedList*) &SupportedTagTypes[20] }, +{TYPE_HANDLER(cmsSigUcrBgType, UcrBg), (_cmsTagTypeLinkedList*) &SupportedTagTypes[21] }, +{TYPE_HANDLER(cmsSigCrdInfoType, CrdInfo), (_cmsTagTypeLinkedList*) &SupportedTagTypes[22] }, +{TYPE_HANDLER(cmsSigMultiProcessElementType, MPE), (_cmsTagTypeLinkedList*) &SupportedTagTypes[23] }, +{TYPE_HANDLER(cmsSigScreeningType, Screening), (_cmsTagTypeLinkedList*) &SupportedTagTypes[24] }, +{TYPE_HANDLER(cmsSigViewingConditionsType, ViewingConditions), (_cmsTagTypeLinkedList*) &SupportedTagTypes[25] }, +{TYPE_HANDLER(cmsSigXYZType, XYZ), (_cmsTagTypeLinkedList*) &SupportedTagTypes[26] }, +{TYPE_HANDLER(cmsCorbisBrokenXYZtype, XYZ), (_cmsTagTypeLinkedList*) &SupportedTagTypes[27] }, +{TYPE_HANDLER(cmsMonacoBrokenCurveType, Curve), (_cmsTagTypeLinkedList*) &SupportedTagTypes[28] }, +{TYPE_HANDLER(cmsSigProfileSequenceIdType, ProfileSequenceId), (_cmsTagTypeLinkedList*) &SupportedTagTypes[29] }, +{TYPE_HANDLER(cmsSigDictType, Dictionary), (_cmsTagTypeLinkedList*) &SupportedTagTypes[30] }, {TYPE_HANDLER(cmsSigVcgtType, vcgt), NULL } }; @@ -5390,7 +5445,7 @@ cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsContext ContextID, cmsTagTypeSignatu { _cmsTagTypePluginChunkType* ctx = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(ContextID, TagTypePlugin); - return GetHandler(sig, ctx->TagTypes, SupportedTagTypes); + return GetHandler(sig, ctx->TagTypes, (_cmsTagTypeLinkedList*) SupportedTagTypes); } // ******************************************************************************** @@ -5405,7 +5460,7 @@ typedef struct _cmsTagLinkedList_st { } _cmsTagLinkedList; -// This is the list of built-in tags +// This is the list of built-in tags. The data of this list can be modified by plug-ins static _cmsTagLinkedList SupportedTags[] = { { cmsSigAToB0Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutAtoBType, cmsSigLut8Type}, DecideLUTtypeA2B}, &SupportedTags[1]}, @@ -5454,7 +5509,7 @@ static _cmsTagLinkedList SupportedTags[] = { { cmsSigPreview2Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[32]}, { cmsSigProfileDescriptionTag, { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[33]}, - { cmsSigProfileSequenceDescTag, { 1, 1, { cmsSigProfileSequenceDescType }, NULL}, &SupportedTags[34]}, + { cmsSigProfileSequenceDescTag, { 1, 1, { cmsSigProfileSequenceDescType }, NULL}, &SupportedTags[34]}, { cmsSigTechnologyTag, { 1, 1, { cmsSigSignatureType }, NULL}, &SupportedTags[35]}, { cmsSigColorimetricIntentImageStateTag, { 1, 1, { cmsSigSignatureType }, NULL}, &SupportedTags[36]}, @@ -5491,10 +5546,10 @@ static _cmsTagLinkedList SupportedTags[] = { { cmsSigVcgtTag, { 1, 1, { cmsSigVcgtType}, NULL }, &SupportedTags[60]}, { cmsSigMetaTag, { 1, 1, { cmsSigDictType}, NULL }, &SupportedTags[61]}, { cmsSigProfileSequenceIdTag, { 1, 1, { cmsSigProfileSequenceIdType}, NULL }, &SupportedTags[62]}, + { cmsSigProfileDescriptionMLTag,{ 1, 1, { cmsSigMultiLocalizedUnicodeType}, NULL}, &SupportedTags[63]}, { cmsSigArgyllArtsTag, { 9, 1, { cmsSigS15Fixed16ArrayType}, NULL}, NULL} - }; /* diff --git a/src/java.desktop/share/native/liblcms/cmsvirt.c b/src/java.desktop/share/native/liblcms/cmsvirt.c index 8d353b369d7..89e55e4e439 100644 --- a/src/java.desktop/share/native/liblcms/cmsvirt.c +++ b/src/java.desktop/share/native/liblcms/cmsvirt.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -320,7 +320,7 @@ cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLinkTHR(cmsContext ContextID, { cmsHPROFILE hICC; cmsPipeline* Pipeline; - int nChannels; + cmsUInt32Number nChannels; hICC = cmsCreateProfilePlaceholder(ContextID); if (!hICC) @@ -426,7 +426,7 @@ cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID, cmsHPROFILE hICC; cmsPipeline* LUT; cmsStage* CLUT; - int nChannels; + cmsUInt32Number nChannels; if (ColorSpace != cmsSigCmykData) { cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "InkLimiting: Only CMYK currently supported"); @@ -755,13 +755,13 @@ int bchswSampler(register const cmsUInt16Number In[], register cmsUInt16Number O // contrast, Saturation and white point displacement cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID, - int nLUTPoints, - cmsFloat64Number Bright, - cmsFloat64Number Contrast, - cmsFloat64Number Hue, - cmsFloat64Number Saturation, - int TempSrc, - int TempDest) + cmsUInt32Number nLUTPoints, + cmsFloat64Number Bright, + cmsFloat64Number Contrast, + cmsFloat64Number Hue, + cmsFloat64Number Saturation, + cmsUInt32Number TempSrc, + cmsUInt32Number TempDest) { cmsHPROFILE hICC; cmsPipeline* Pipeline; @@ -769,7 +769,7 @@ cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID, cmsCIExyY WhitePnt; cmsStage* CLUT; cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS]; - int i; + cmsUInt32Number i; bchsw.Brightness = Bright; bchsw.Contrast = Contrast; @@ -807,7 +807,7 @@ cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID, for (i=0; i < MAX_INPUT_DIMENSIONS; i++) Dimensions[i] = nLUTPoints; CLUT = cmsStageAllocCLut16bitGranular(ContextID, Dimensions, 3, 3, NULL); - if (CLUT == NULL) return NULL; + if (CLUT == NULL) goto Error; if (!cmsStageSampleCLut16bit(CLUT, bchswSampler, (void*) &bchsw, 0)) { @@ -840,13 +840,13 @@ cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID, } -CMSAPI cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfile(int nLUTPoints, +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfile(cmsUInt32Number nLUTPoints, cmsFloat64Number Bright, cmsFloat64Number Contrast, cmsFloat64Number Hue, cmsFloat64Number Saturation, - int TempSrc, - int TempDest) + cmsUInt32Number TempSrc, + cmsUInt32Number TempDest) { return cmsCreateBCHSWabstractProfileTHR(NULL, nLUTPoints, Bright, Contrast, Hue, Saturation, TempSrc, TempDest); } @@ -859,8 +859,10 @@ cmsHPROFILE CMSEXPORT cmsCreateNULLProfileTHR(cmsContext ContextID) cmsHPROFILE hProfile; cmsPipeline* LUT = NULL; cmsStage* PostLin; - cmsToneCurve* EmptyTab; + cmsStage* OutLin; + cmsToneCurve* EmptyTab[3]; cmsUInt16Number Zero[2] = { 0, 0 }; + const cmsFloat64Number PickLstarMatrix[] = { 1, 0, 0 }; hProfile = cmsCreateProfilePlaceholder(ContextID); if (!hProfile) // can't allocate @@ -871,22 +873,28 @@ cmsHPROFILE CMSEXPORT cmsCreateNULLProfileTHR(cmsContext ContextID) if (!SetTextTags(hProfile, L"NULL profile built-in")) goto Error; - cmsSetDeviceClass(hProfile, cmsSigOutputClass); cmsSetColorSpace(hProfile, cmsSigGrayData); cmsSetPCS(hProfile, cmsSigLabData); - // An empty LUTs is all we need - LUT = cmsPipelineAlloc(ContextID, 1, 1); + // Create a valid ICC 4 structure + LUT = cmsPipelineAlloc(ContextID, 3, 1); if (LUT == NULL) goto Error; - EmptyTab = cmsBuildTabulatedToneCurve16(ContextID, 2, Zero); - PostLin = cmsStageAllocToneCurves(ContextID, 1, &EmptyTab); - cmsFreeToneCurve(EmptyTab); + EmptyTab[0] = EmptyTab[1] = EmptyTab[2] = cmsBuildTabulatedToneCurve16(ContextID, 2, Zero); + PostLin = cmsStageAllocToneCurves(ContextID, 3, EmptyTab); + OutLin = cmsStageAllocToneCurves(ContextID, 1, EmptyTab); + cmsFreeToneCurve(EmptyTab[0]); if (!cmsPipelineInsertStage(LUT, cmsAT_END, PostLin)) goto Error; + if (!cmsPipelineInsertStage(LUT, cmsAT_END, cmsStageAllocMatrix(ContextID, 1, 3, PickLstarMatrix, NULL))) + goto Error; + + if (!cmsPipelineInsertStage(LUT, cmsAT_END, OutLin)) + goto Error; + if (!cmsWriteTag(hProfile, cmsSigBToA0Tag, (void*) LUT)) goto Error; if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, cmsD50_XYZ())) goto Error; @@ -967,7 +975,7 @@ cmsHPROFILE CreateNamedColorDevicelink(cmsHTRANSFORM xform) { _cmsTRANSFORM* v = (_cmsTRANSFORM*) xform; cmsHPROFILE hICC = NULL; - int i, nColors; + cmsUInt32Number i, nColors; cmsNAMEDCOLORLIST *nc2 = NULL, *Original = NULL; // Create an empty placeholder @@ -1084,7 +1092,7 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat { cmsHPROFILE hProfile = NULL; cmsUInt32Number FrmIn, FrmOut, ChansIn, ChansOut; - cmsUInt32Number ColorSpaceBitsIn, ColorSpaceBitsOut; + int ColorSpaceBitsIn, ColorSpaceBitsOut; _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; cmsPipeline* LUT = NULL; cmsStage* mpe; diff --git a/src/java.desktop/share/native/liblcms/cmswtpnt.c b/src/java.desktop/share/native/liblcms/cmswtpnt.c index d23b29f1b00..fddf8b5e709 100644 --- a/src/java.desktop/share/native/liblcms/cmswtpnt.c +++ b/src/java.desktop/share/native/liblcms/cmswtpnt.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -105,7 +105,6 @@ cmsBool CMSEXPORT cmsWhitePointFromTemp(cmsCIExyY* WhitePoint, cmsFloat64Number } // Obtain y(x) - y = -3.000*(x*x) + 2.870*x - 0.275; // wave factors (not used, but here for futures extensions) @@ -131,7 +130,7 @@ typedef struct { } ISOTEMPERATURE; -static ISOTEMPERATURE isotempdata[] = { +static const ISOTEMPERATURE isotempdata[] = { // {Mirek, Ut, Vt, Tt } {0, 0.18006, 0.26352, -0.24341}, {10, 0.18066, 0.26589, -0.25479}, @@ -295,7 +294,7 @@ cmsBool _cmsAdaptMatrixToD50(cmsMAT3* r, const cmsCIExyY* SourceWhitePt) // Build a White point, primary chromas transfer matrix from RGB to CIE XYZ // This is just an approximation, I am not handling all the non-linear // aspects of the RGB to XYZ process, and assumming that the gamma correction -// has transitive property in the tranformation chain. +// has transitive property in the transformation chain. // // the alghoritm: // diff --git a/src/java.desktop/share/native/liblcms/cmsxform.c b/src/java.desktop/share/native/liblcms/cmsxform.c index dfedd7f5cf9..77d54804a42 100644 --- a/src/java.desktop/share/native/liblcms/cmsxform.c +++ b/src/java.desktop/share/native/liblcms/cmsxform.c @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -284,6 +284,8 @@ void FloatXFORM(_cmsTRANSFORM* p, strideIn = 0; strideOut = 0; + memset(fIn, 0, sizeof(fIn)); + memset(fOut, 0, sizeof(fIn)); for (i = 0; i < LineCount; i++) { @@ -348,6 +350,7 @@ void NullFloatXFORM(_cmsTRANSFORM* p, strideIn = 0; strideOut = 0; + memset(fIn, 0, sizeof(fIn)); for (i = 0; i < LineCount; i++) { @@ -385,6 +388,7 @@ void NullXFORM(_cmsTRANSFORM* p, strideIn = 0; strideOut = 0; + memset(wIn, 0, sizeof(wIn)); for (i = 0; i < LineCount; i++) { @@ -422,6 +426,8 @@ void PrecalculatedXFORM(_cmsTRANSFORM* p, strideIn = 0; strideOut = 0; + memset(wIn, 0, sizeof(wIn)); + memset(wOut, 0, sizeof(wOut)); for (i = 0; i < LineCount; i++) { @@ -483,6 +489,8 @@ void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p, strideIn = 0; strideOut = 0; + memset(wIn, 0, sizeof(wIn)); + memset(wOut, 0, sizeof(wOut)); for (i = 0; i < LineCount; i++) { @@ -790,7 +798,10 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, // Allocate needed memory _cmsTRANSFORM* p = (_cmsTRANSFORM*)_cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM)); - if (!p) return NULL; + if (!p) { + cmsPipelineFree(lut); + return NULL; + } // Store the proposed pipeline p->Lut = lut; @@ -823,7 +834,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, p->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; p->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; - // Save the day? + // Save the day? (Ignore the warning) if (Plugin->OldXform) { p->OldXform = (_cmsTransformFn) p->xform; p->xform = _cmsTransform2toTransformAdaptor; @@ -848,7 +859,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) { cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); - _cmsFree(ContextID, p); + cmsDeleteTransform(p); return NULL; } @@ -870,7 +881,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, } else { - int BytesPerPixelInput; + cmsUInt32Number BytesPerPixelInput; p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; @@ -878,7 +889,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, if (p ->FromInput == NULL || p ->ToOutput == NULL) { cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); - _cmsFree(ContextID, p); + cmsDeleteTransform(p); return NULL; } @@ -920,13 +931,13 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, } static -cmsBool GetXFormColorSpaces(int nProfiles, cmsHPROFILE hProfiles[], cmsColorSpaceSignature* Input, cmsColorSpaceSignature* Output) +cmsBool GetXFormColorSpaces(cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[], cmsColorSpaceSignature* Input, cmsColorSpaceSignature* Output) { cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut; cmsColorSpaceSignature PostColorSpace; - int i; + cmsUInt32Number i; - if (nProfiles <= 0) return FALSE; + if (nProfiles == 0) return FALSE; if (hProfiles[0] == NULL) return FALSE; *Input = PostColorSpace = cmsGetColorSpace(hProfiles[0]); @@ -975,7 +986,7 @@ cmsBool GetXFormColorSpaces(int nProfiles, cmsHPROFILE hProfiles[], cmsColorSpac static cmsBool IsProperColorSpace(cmsColorSpaceSignature Check, cmsUInt32Number dwFormat) { - int Space1 = T_COLORSPACE(dwFormat); + int Space1 = (int) T_COLORSPACE(dwFormat); int Space2 = _cmsLCMScolorSpace(Check); if (Space1 == PT_ANY) return TRUE; @@ -1231,7 +1242,7 @@ cmsHTRANSFORM CMSEXPORT cmsCreateTransformTHR(cmsContext ContextID, hArray[0] = Input; hArray[1] = Output; - return cmsCreateMultiprofileTransformTHR(ContextID, hArray, Output == NULL ? 1 : 2, InputFormat, OutputFormat, Intent, dwFlags); + return cmsCreateMultiprofileTransformTHR(ContextID, hArray, Output == NULL ? 1U : 2U, InputFormat, OutputFormat, Intent, dwFlags); } CMSAPI cmsHTRANSFORM CMSEXPORT cmsCreateTransform(cmsHPROFILE Input, diff --git a/src/java.desktop/share/native/liblcms/lcms2.h b/src/java.desktop/share/native/liblcms/lcms2.h index cbca89421a5..cc5d0cf60fb 100644 --- a/src/java.desktop/share/native/liblcms/lcms2.h +++ b/src/java.desktop/share/native/liblcms/lcms2.h @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -52,7 +52,7 @@ // //--------------------------------------------------------------------------------- // -// Version 2.8 +// Version 2.9rc3 // #ifndef _lcms2_H @@ -78,7 +78,7 @@ // #define CMS_USE_CPP_API // Uncomment this line if you need strict CGATS syntax. Makes CGATS files to -// require "KEYWORD" on undefined identifiers, keep it comented out unless needed +// require "KEYWORD" on undefined identifiers, keep it commented out unless needed // #define CMS_STRICT_CGATS 1 // Uncomment to get rid of the tables for "half" float support @@ -87,6 +87,9 @@ // Uncomment to get rid of pthreads/windows dependency // #define CMS_NO_PTHREADS 1 +// Uncomment this for special windows mutex initialization (see lcms2_internal.h) +// #define CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT + // ********** End of configuration toggles ****************************** // Needed for streams @@ -104,7 +107,7 @@ extern "C" { #endif // Version/release -#define LCMS_VERSION 2080 +#define LCMS_VERSION 2090 // I will give the chance of redefining basic types for compilers that are not fully C99 compliant #ifndef CMS_BASIC_TYPES_ALREADY_DEFINED @@ -254,16 +257,21 @@ typedef int cmsBool; # define CMSAPI __declspec(dllexport) # else # define CMSAPI __declspec(dllimport) -# endif +# endif # endif # else -# define CMSEXPORT -# define CMSAPI +# define CMSEXPORT +# define CMSAPI # endif -#else -# define CMSEXPORT -# define CMSAPI -#endif +#else // not Windows +# ifdef HAVE_FUNC_ATTRIBUTE_VISIBILITY +# define CMSEXPORT +# define CMSAPI __attribute__((visibility("default"))) +# else +# define CMSEXPORT +# define CMSAPI +# endif +#endif // CMS_IS_WINDOWS_ #ifdef HasTHREADS # if HasTHREADS == 1 @@ -284,9 +292,9 @@ typedef int cmsBool; #endif // D50 XYZ normalized to Y=1.0 -#define cmsD50X 0.9642 -#define cmsD50Y 1.0 -#define cmsD50Z 0.8249 +#define cmsD50X 0.9642 +#define cmsD50Y 1.0 +#define cmsD50Z 0.8249 // V4 perceptual black #define cmsPERCEPTUAL_BLACK_X 0.00336 @@ -294,8 +302,8 @@ typedef int cmsBool; #define cmsPERCEPTUAL_BLACK_Z 0.00287 // Definitions in ICC spec -#define cmsMagicNumber 0x61637370 // 'acsp' -#define lcmsSignature 0x6c636d73 // 'lcms' +#define cmsMagicNumber 0x61637370 // 'acsp' +#define lcmsSignature 0x6c636d73 // 'lcms' // Base ICC type definitions @@ -1154,7 +1162,7 @@ typedef struct { cmsCIEXYZ whitePoint; cmsFloat64Number Yb; cmsFloat64Number La; - int surround; + cmsUInt32Number surround; cmsFloat64Number D_value; } cmsViewingConditions; @@ -1182,16 +1190,16 @@ typedef struct { // The internal representation is none of your business. typedef struct _cms_curve_struct cmsToneCurve; -CMSAPI cmsToneCurve* CMSEXPORT cmsBuildSegmentedToneCurve(cmsContext ContextID, cmsInt32Number nSegments, const cmsCurveSegment Segments[]); +CMSAPI cmsToneCurve* CMSEXPORT cmsBuildSegmentedToneCurve(cmsContext ContextID, cmsUInt32Number nSegments, const cmsCurveSegment Segments[]); CMSAPI cmsToneCurve* CMSEXPORT cmsBuildParametricToneCurve(cmsContext ContextID, cmsInt32Number Type, const cmsFloat64Number Params[]); CMSAPI cmsToneCurve* CMSEXPORT cmsBuildGamma(cmsContext ContextID, cmsFloat64Number Gamma); -CMSAPI cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurve16(cmsContext ContextID, cmsInt32Number nEntries, const cmsUInt16Number values[]); +CMSAPI cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurve16(cmsContext ContextID, cmsUInt32Number nEntries, const cmsUInt16Number values[]); CMSAPI cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurveFloat(cmsContext ContextID, cmsUInt32Number nEntries, const cmsFloat32Number values[]); CMSAPI void CMSEXPORT cmsFreeToneCurve(cmsToneCurve* Curve); CMSAPI void CMSEXPORT cmsFreeToneCurveTriple(cmsToneCurve* Curve[3]); CMSAPI cmsToneCurve* CMSEXPORT cmsDupToneCurve(const cmsToneCurve* Src); CMSAPI cmsToneCurve* CMSEXPORT cmsReverseToneCurve(const cmsToneCurve* InGamma); -CMSAPI cmsToneCurve* CMSEXPORT cmsReverseToneCurveEx(cmsInt32Number nResultSamples, const cmsToneCurve* InGamma); +CMSAPI cmsToneCurve* CMSEXPORT cmsReverseToneCurveEx(cmsUInt32Number nResultSamples, const cmsToneCurve* InGamma); CMSAPI cmsToneCurve* CMSEXPORT cmsJoinToneCurve(cmsContext ContextID, const cmsToneCurve* X, const cmsToneCurve* Y, cmsUInt32Number nPoints); CMSAPI cmsBool CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda); CMSAPI cmsFloat32Number CMSEXPORT cmsEvalToneCurveFloat(const cmsToneCurve* Curve, cmsFloat32Number v); @@ -1236,7 +1244,7 @@ CMSAPI cmsBool CMSEXPORT cmsPipelineSetSaveAs8bitsFlag(cmsPipeline* lu // Where to place/locate the stages in the pipeline chain typedef enum { cmsAT_BEGIN, cmsAT_END } cmsStageLoc; -CMSAPI int CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe); +CMSAPI cmsBool CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe); CMSAPI void CMSEXPORT cmsPipelineUnlinkStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage** mpe); // This function is quite useful to analyze the structure of a Pipeline and retrieve the Stage elements @@ -1459,7 +1467,7 @@ CMSAPI cmsBool CMSEXPORT cmsLinkTag(cmsHPROFILE hProfile, cmsTagSignat CMSAPI cmsTagSignature CMSEXPORT cmsTagLinkedTo(cmsHPROFILE hProfile, cmsTagSignature sig); // Read and write raw data -CMSAPI cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, void* Buffer, cmsUInt32Number BufferSize); +CMSAPI cmsUInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, void* Buffer, cmsUInt32Number BufferSize); CMSAPI cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data, cmsUInt32Number Size); // Access header data @@ -1550,7 +1558,7 @@ CMSAPI cmsBool CMSEXPORT cmsCloseIOhandler(cmsIOHANDLER* io); CMSAPI cmsBool CMSEXPORT cmsMD5computeID(cmsHPROFILE hProfile); -// Profile high level funtions ------------------------------------------------------------------------------------------ +// Profile high level functions ------------------------------------------------------------------------------------------ CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromFile(const char *ICCProfile, const char *sAccess); CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromFileTHR(cmsContext ContextID, const char *ICCProfile, const char *sAccess); @@ -1610,21 +1618,21 @@ CMSAPI cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID) CMSAPI cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfile(void); CMSAPI cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID, - int nLUTPoints, + cmsUInt32Number nLUTPoints, cmsFloat64Number Bright, cmsFloat64Number Contrast, cmsFloat64Number Hue, cmsFloat64Number Saturation, - int TempSrc, - int TempDest); + cmsUInt32Number TempSrc, + cmsUInt32Number TempDest); -CMSAPI cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfile(int nLUTPoints, +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfile(cmsUInt32Number nLUTPoints, cmsFloat64Number Bright, cmsFloat64Number Contrast, cmsFloat64Number Hue, cmsFloat64Number Saturation, - int TempSrc, - int TempDest); + cmsUInt32Number TempSrc, + cmsUInt32Number TempDest); CMSAPI cmsHPROFILE CMSEXPORT cmsCreateNULLProfileTHR(cmsContext ContextID); CMSAPI cmsHPROFILE CMSEXPORT cmsCreateNULLProfile(void); @@ -1666,7 +1674,7 @@ CMSAPI cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID #define cmsFLAGS_BLACKPOINTCOMPENSATION 0x2000 #define cmsFLAGS_NOWHITEONWHITEFIXUP 0x0004 // Don't fix scum dot #define cmsFLAGS_HIGHRESPRECALC 0x0400 // Use more memory to give better accurancy -#define cmsFLAGS_LOWRESPRECALC 0x0800 // Use less memory to minimize resouces +#define cmsFLAGS_LOWRESPRECALC 0x0800 // Use less memory to minimize resources // For devicelink creation #define cmsFLAGS_8BITS_DEVICELINK 0x0008 // Create 8 bits devicelinks diff --git a/src/java.desktop/share/native/liblcms/lcms2_internal.h b/src/java.desktop/share/native/liblcms/lcms2_internal.h index 90094728823..8984981e830 100644 --- a/src/java.desktop/share/native/liblcms/lcms2_internal.h +++ b/src/java.desktop/share/native/liblcms/lcms2_internal.h @@ -30,7 +30,7 @@ // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -106,7 +106,7 @@ // Maximum of channels for internal pipeline evaluation #define MAX_STAGE_CHANNELS 128 -// Unused parameter warning supression +// Unused parameter warning suppression #define cmsUNUSED_PARAMETER(x) ((void)x) // The specification for "inline" is section 6.7.4 of the C99 standard (ISO/IEC 9899:1999). @@ -125,8 +125,16 @@ # ifndef vsnprintf # define vsnprintf _vsnprintf # endif -#endif +/// Properly define some macros to accommodate +/// older MSVC versions. +# if _MSC_VER <= 1700 + #include + #define isnan _isnan + #define isinf(x) (!_finite((x))) +# endif + +#endif // A fast way to convert from/to 16 <-> 8 bits #define FROM_8_TO_16(rgb) (cmsUInt16Number) ((((cmsUInt16Number) (rgb)) << 8)|(rgb)) @@ -201,19 +209,48 @@ cmsINLINE cmsUInt16Number _cmsQuickSaturateWord(cmsFloat64Number d) return _cmsQuickFloorWord(d); } +// Test bed entry points--------------------------------------------------------------- +#define CMSCHECKPOINT CMSAPI // Pthread support -------------------------------------------------------------------- #ifndef CMS_NO_PTHREADS // This is the threading support. Unfortunately, it has to be platform-dependent because // windows does not support pthreads. - #ifdef CMS_IS_WINDOWS_ #define WIN32_LEAN_AND_MEAN 1 #include +// The locking scheme in LCMS requires a single 'top level' mutex +// to work. This is actually implemented on Windows as a +// CriticalSection, because they are lighter weight. With +// pthreads, this is statically inited. Unfortunately, windows +// can't officially statically init critical sections. +// +// We can work around this in 2 ways. +// +// 1) We can use a proper mutex purely to protect the init +// of the CriticalSection. This in turns requires us to protect +// the Mutex creation, which we can do using the snappily +// named InterlockedCompareExchangePointer API (present on +// windows XP and above). +// +// 2) In cases where we want to work on pre-Windows XP, we +// can use an even more horrible hack described below. +// +// So why wouldn't we always use 2)? Because not calling +// the init function for a critical section means it fails +// testing with ApplicationVerifier (and presumably similar +// tools). +// +// We therefore default to 1, and people who want to be able +// to run on pre-Windows XP boxes can build with: +// CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT +// defined. This is automatically set for builds using +// versions of MSVC that don't have this API available. +// // From: http://locklessinc.com/articles/pthreads_on_windows/ // The pthreads API has an initialization macro that has no correspondence to anything in // the windows API. By investigating the internal definition of the critical section type, @@ -235,14 +272,30 @@ cmsINLINE cmsUInt16Number _cmsQuickSaturateWord(cmsFloat64Number d) typedef CRITICAL_SECTION _cmsMutex; -#define CMS_MUTEX_INITIALIZER {(PRTL_CRITICAL_SECTION_DEBUG) -1,-1,0,0,0,0} - #ifdef _MSC_VER # if (_MSC_VER >= 1800) # pragma warning(disable : 26135) # endif #endif +#ifndef CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT +// If we are building with a version of MSVC smaller +// than 1400 (i.e. before VS2005) then we don't have +// the InterlockedCompareExchangePointer API, so use +// the old version. +# ifdef _MSC_VER +# if _MSC_VER < 1400 +# define CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT +# endif +# endif +#endif + +#ifdef CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT +# define CMS_MUTEX_INITIALIZER {(PRTL_CRITICAL_SECTION_DEBUG) -1,-1,0,0,0,0} +#else +# define CMS_MUTEX_INITIALIZER {(PRTL_CRITICAL_SECTION_DEBUG)NULL,-1,0,0,0,0} +#endif + cmsINLINE int _cmsLockPrimitive(_cmsMutex *m) { EnterCriticalSection(m); @@ -478,7 +531,7 @@ struct _cmsContext_struct { void* chunks[MemoryClientMax]; // array of pointers to client chunks. Memory itself is hold in the suballocator. // If NULL, then it reverts to global Context0 - _cmsMemPluginChunkType DefaultMemoryManager; // The allocators used for creating the context itself. Cannot be overriden + _cmsMemPluginChunkType DefaultMemoryManager; // The allocators used for creating the context itself. Cannot be overridden }; // Returns a pointer to a valid context structure, including the global one if id is zero. @@ -800,10 +853,10 @@ void _cmsTagSignature2String(char String[5], cmsTagSignature sig // Interpolation --------------------------------------------------------------------------------------------------------- -cmsInterpParams* _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags); -cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID, const cmsUInt32Number nSamples[], int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags); -void _cmsFreeInterpParams(cmsInterpParams* p); -cmsBool _cmsSetInterpolationRoutine(cmsContext ContextID, cmsInterpParams* p); +CMSCHECKPOINT cmsInterpParams* CMSEXPORT _cmsComputeInterpParams(cmsContext ContextID, cmsUInt32Number nSamples, cmsUInt32Number InputChan, cmsUInt32Number OutputChan, const void* Table, cmsUInt32Number dwFlags); +cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID, const cmsUInt32Number nSamples[], cmsUInt32Number InputChan, cmsUInt32Number OutputChan, const void* Table, cmsUInt32Number dwFlags); +CMSCHECKPOINT void CMSEXPORT _cmsFreeInterpParams(cmsInterpParams* p); +cmsBool _cmsSetInterpolationRoutine(cmsContext ContextID, cmsInterpParams* p); // Curves ---------------------------------------------------------------------------------------------------------------- @@ -853,20 +906,20 @@ struct _cmsStage_struct { // Special Stages (cannot be saved) -cmsStage* _cmsStageAllocLab2XYZ(cmsContext ContextID); -cmsStage* _cmsStageAllocXYZ2Lab(cmsContext ContextID); -cmsStage* _cmsStageAllocLabPrelin(cmsContext ContextID); -cmsStage* _cmsStageAllocLabV2ToV4(cmsContext ContextID); -cmsStage* _cmsStageAllocLabV2ToV4curves(cmsContext ContextID); -cmsStage* _cmsStageAllocLabV4ToV2(cmsContext ContextID); -cmsStage* _cmsStageAllocNamedColor(cmsNAMEDCOLORLIST* NamedColorList, cmsBool UsePCS); -cmsStage* _cmsStageAllocIdentityCurves(cmsContext ContextID, int nChannels); -cmsStage* _cmsStageAllocIdentityCLut(cmsContext ContextID, int nChan); -cmsStage* _cmsStageNormalizeFromLabFloat(cmsContext ContextID); -cmsStage* _cmsStageNormalizeFromXyzFloat(cmsContext ContextID); -cmsStage* _cmsStageNormalizeToLabFloat(cmsContext ContextID); -cmsStage* _cmsStageNormalizeToXyzFloat(cmsContext ContextID); -cmsStage* _cmsStageClipNegatives(cmsContext ContextID, int nChannels); +CMSCHECKPOINT cmsStage* CMSEXPORT _cmsStageAllocLab2XYZ(cmsContext ContextID); +CMSCHECKPOINT cmsStage* CMSEXPORT _cmsStageAllocXYZ2Lab(cmsContext ContextID); +cmsStage* _cmsStageAllocLabPrelin(cmsContext ContextID); +CMSCHECKPOINT cmsStage* CMSEXPORT _cmsStageAllocLabV2ToV4(cmsContext ContextID); +cmsStage* _cmsStageAllocLabV2ToV4curves(cmsContext ContextID); +CMSCHECKPOINT cmsStage* CMSEXPORT _cmsStageAllocLabV4ToV2(cmsContext ContextID); +CMSCHECKPOINT cmsStage* CMSEXPORT _cmsStageAllocNamedColor(cmsNAMEDCOLORLIST* NamedColorList, cmsBool UsePCS); +CMSCHECKPOINT cmsStage* CMSEXPORT _cmsStageAllocIdentityCurves(cmsContext ContextID, cmsUInt32Number nChannels); +CMSCHECKPOINT cmsStage* CMSEXPORT _cmsStageAllocIdentityCLut(cmsContext ContextID, cmsUInt32Number nChan); +cmsStage* _cmsStageNormalizeFromLabFloat(cmsContext ContextID); +cmsStage* _cmsStageNormalizeFromXyzFloat(cmsContext ContextID); +cmsStage* _cmsStageNormalizeToLabFloat(cmsContext ContextID); +cmsStage* _cmsStageNormalizeToXyzFloat(cmsContext ContextID); +cmsStage* _cmsStageClipNegatives(cmsContext ContextID, cmsUInt32Number nChannels); // For curve set only @@ -901,9 +954,9 @@ struct _cmsPipeline_struct { // Read tags using low-level function, provide necessary glue code to adapt versions, etc. All those return a brand new copy // of the LUTS, since ownership of original is up to the profile. The user should free allocated resources. -cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent); -cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent); -cmsPipeline* _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent); +CMSCHECKPOINT cmsPipeline* CMSEXPORT _cmsReadInputLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent); +CMSCHECKPOINT cmsPipeline* CMSEXPORT _cmsReadOutputLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent); +CMSCHECKPOINT cmsPipeline* CMSEXPORT _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent); // Special values cmsBool _cmsReadMediaWhitePoint(cmsCIEXYZ* Dest, cmsHPROFILE hProfile); @@ -928,8 +981,9 @@ cmsSEQ* _cmsCompileProfileSequence(cmsContext ContextID, cmsUInt32Number nProfil // LUT optimization ------------------------------------------------------------------------------------------------ -cmsUInt16Number _cmsQuantizeVal(cmsFloat64Number i, int MaxSamples); -int _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags); +CMSCHECKPOINT cmsUInt16Number CMSEXPORT _cmsQuantizeVal(cmsFloat64Number i, cmsUInt32Number MaxSamples); + +cmsUInt32Number _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags); cmsBool _cmsEndPointsBySpace(cmsColorSpaceSignature Space, cmsUInt16Number **White, @@ -938,7 +992,7 @@ cmsBool _cmsEndPointsBySpace(cmsColorSpaceSignature Space, cmsBool _cmsOptimizePipeline(cmsContext ContextID, cmsPipeline** Lut, - int Intent, + cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags ); @@ -962,17 +1016,17 @@ cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID, cmsBool _cmsFormatterIsFloat(cmsUInt32Number Type); cmsBool _cmsFormatterIs8bit(cmsUInt32Number Type); -cmsFormatter _cmsGetFormatter(cmsContext ContextID, - cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8 - cmsFormatterDirection Dir, - cmsUInt32Number dwFlags); +CMSCHECKPOINT cmsFormatter CMSEXPORT _cmsGetFormatter(cmsContext ContextID, + cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8 + cmsFormatterDirection Dir, + cmsUInt32Number dwFlags); #ifndef CMS_NO_HALF_SUPPORT // Half float -cmsFloat32Number _cmsHalf2Float(cmsUInt16Number h); -cmsUInt16Number _cmsFloat2Half(cmsFloat32Number flt); +CMSCHECKPOINT cmsFloat32Number CMSEXPORT _cmsHalf2Float(cmsUInt16Number h); +CMSCHECKPOINT cmsUInt16Number CMSEXPORT _cmsFloat2Half(cmsFloat32Number flt); #endif diff --git a/src/java.desktop/share/native/liblcms/lcms2_plugin.h b/src/java.desktop/share/native/liblcms/lcms2_plugin.h index aff3b48d7ec..6fe59c39665 100644 --- a/src/java.desktop/share/native/liblcms/lcms2_plugin.h +++ b/src/java.desktop/share/native/liblcms/lcms2_plugin.h @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2016 Marti Maria Saguer +// Copyright (c) 1998-2017 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -347,7 +347,7 @@ typedef struct { // Parametric curves. A negative type means same function but analytically inverted. Max. number of params is 10 -// Evaluator callback for user-suplied parametric curves. May implement more than one type +// Evaluator callback for user-supplied parametric curves. May implement more than one type typedef cmsFloat64Number (* cmsParametricCurveEvaluator)(cmsInt32Number Type, const cmsFloat64Number Params[10], cmsFloat64Number R); // Plug-in may implement an arbitrary number of parametric curves @@ -457,7 +457,7 @@ typedef struct { cmsUInt32Number nSupportedTypes; // In how many types this tag can come (MAX_TYPES_IN_LCMS_PLUGIN maximum) cmsTagTypeSignature SupportedTypes[MAX_TYPES_IN_LCMS_PLUGIN]; - // For writting + // For writing cmsTagTypeSignature (* DecideType)(cmsFloat64Number ICCVersion, const void *Data); } cmsTagDescriptor; From cbe7fedef2a61d34482ac12e6da111716fd1b3bd Mon Sep 17 00:00:00 2001 From: mullan Date: Fri, 8 Dec 2017 09:37:28 -0500 Subject: [PATCH 004/196] 8191358: Restore TSA certificate expiration check Reviewed-by: coffeys, rhalade --- .../certpath/PKIXCertPathValidator.java | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java b/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java index c65ebf03986..80497e774fd 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java @@ -31,6 +31,7 @@ import java.util.*; import sun.security.provider.certpath.PKIX.ValidatorParams; +import sun.security.validator.Validator; import sun.security.x509.X509CertImpl; import sun.security.util.Debug; @@ -189,12 +190,21 @@ private static PKIXCertPathValidatorResult validate(TrustAnchor anchor, params.policyQualifiersRejected(), rootNode); certPathCheckers.add(pc); - // default value for date is current time - BasicChecker bc; - bc = new BasicChecker(anchor, - (params.timestamp() == null ? params.date() : - params.timestamp().getTimestamp()), - params.sigProvider(), false); + + // the time that the certificate validity period should be + // checked against + Date timeToCheck = null; + // use timestamp if checking signed code that is timestamped, otherwise + // use date parameter from PKIXParameters + if ((params.variant() == Validator.VAR_CODE_SIGNING || + params.variant() == Validator.VAR_PLUGIN_CODE_SIGNING) && + params.timestamp() != null) { + timeToCheck = params.timestamp().getTimestamp(); + } else { + timeToCheck = params.date(); + } + BasicChecker bc = new BasicChecker(anchor, timeToCheck, + params.sigProvider(), false); certPathCheckers.add(bc); boolean revCheckerAdded = false; From 3b6148b10c24a8fc08d2afef663e914e52bf5208 Mon Sep 17 00:00:00 2001 From: serb Date: Sun, 10 Dec 2017 15:29:26 -0800 Subject: [PATCH 005/196] 8192030: Better MTSchema support Reviewed-by: skoivu, rhalade, prr, aghaisas --- .../classes/sun/awt/windows/ThemeReader.java | 18 ++++++++++++++++-- .../native/libawt/windows/ThemeReader.cpp | 4 ++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/java.desktop/windows/classes/sun/awt/windows/ThemeReader.java b/src/java.desktop/windows/classes/sun/awt/windows/ThemeReader.java index 26751e953ba..167d4d5b910 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/ThemeReader.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/ThemeReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2017, 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,6 +61,7 @@ public final class ThemeReader { private static final Lock readLock = readWriteLock.readLock(); private static final Lock writeLock = readWriteLock.writeLock(); private static volatile boolean valid = false; + private static volatile boolean isThemed; static volatile boolean xpStyleEnabled; @@ -70,7 +71,17 @@ static void flush() { valid = false; } - public static native boolean isThemed(); + private static native boolean initThemes(); + + public static boolean isThemed() { + writeLock.lock(); + try { + isThemed = initThemes(); + return isThemed; + } finally { + writeLock.unlock(); + } + } public static boolean isXPStyleEnabled() { return xpStyleEnabled; @@ -98,6 +109,9 @@ private static Long getThemeImpl(String widget) { // returns theme value // this method should be invoked with readLock locked private static Long getTheme(String widget) { + if (!isThemed) { + throw new IllegalStateException("Themes are not loaded"); + } if (!valid) { readLock.unlock(); writeLock.lock(); diff --git a/src/java.desktop/windows/native/libawt/windows/ThemeReader.cpp b/src/java.desktop/windows/native/libawt/windows/ThemeReader.cpp index c48ae8fbe31..99ca918a500 100644 --- a/src/java.desktop/windows/native/libawt/windows/ThemeReader.cpp +++ b/src/java.desktop/windows/native/libawt/windows/ThemeReader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -232,7 +232,7 @@ BOOL InitThemes() { return FALSE; } -JNIEXPORT jboolean JNICALL Java_sun_awt_windows_ThemeReader_isThemed +JNIEXPORT jboolean JNICALL Java_sun_awt_windows_ThemeReader_initThemes (JNIEnv *env, jclass klass) { static BOOL TryLoadingThemeLib = FALSE; static BOOL Themed = FALSE; From 36930b9f667f9fe58be2544cad3bd7f7363a09c1 Mon Sep 17 00:00:00 2001 From: weijun Date: Thu, 14 Dec 2017 08:21:36 +0800 Subject: [PATCH 006/196] 8189969: Manifest better manifest entries Reviewed-by: mullan --- .../sun/security/util/ManifestDigester.java | 84 ++++++++++++------- 1 file changed, 54 insertions(+), 30 deletions(-) diff --git a/src/java.base/share/classes/sun/security/util/ManifestDigester.java b/src/java.base/share/classes/sun/security/util/ManifestDigester.java index 913667716e0..aeff45bd21c 100644 --- a/src/java.base/share/classes/sun/security/util/ManifestDigester.java +++ b/src/java.base/share/classes/sun/security/util/ManifestDigester.java @@ -26,12 +26,17 @@ package sun.security.util; import java.security.*; +import java.util.ArrayList; import java.util.HashMap; import java.io.ByteArrayOutputStream; +import java.util.List; + import static java.nio.charset.StandardCharsets.UTF_8; /** * This class is used to compute digests on sections of the Manifest. + * Please note that multiple sections might have the same name, and they + * all belong to a single Entry. */ public class ManifestDigester { @@ -40,7 +45,7 @@ public class ManifestDigester { /** the raw bytes of the manifest */ private byte[] rawBytes; - /** the offset/length pair for a section */ + /** the entries grouped by names */ private HashMap entries; // key is a UTF-8 string /** state returned by findSection */ @@ -119,8 +124,8 @@ public ManifestDigester(byte[] bytes) return; // XXX: exception? // create an entry for main attributes - entries.put(MF_MAIN_ATTRS, - new Entry(0, pos.endOfSection + 1, pos.startOfNext, rawBytes)); + entries.put(MF_MAIN_ATTRS, new Entry().addSection( + new Section(0, pos.endOfSection + 1, pos.startOfNext, rawBytes))); int start = pos.startOfNext; while(findSection(start, pos)) { @@ -162,9 +167,10 @@ public ManifestDigester(byte[] bytes) } } - entries.put(new String(nameBuf.toByteArray(), UTF_8), - new Entry(start, sectionLen, sectionLenWithBlank, - rawBytes)); + entries.computeIfAbsent(new String(nameBuf.toByteArray(), UTF_8), + dummy -> new Entry()) + .addSection(new Section(start, sectionLen, + sectionLenWithBlank, rawBytes)); } } start = pos.startOfNext; @@ -182,13 +188,52 @@ private boolean isNameAttr(byte[] bytes, int start) } public static class Entry { + + // One Entry for one name, and one name can have multiple sections. + // According to the JAR File Specification: "If there are multiple + // individual sections for the same file entry, the attributes in + // these sections are merged." + private List
sections = new ArrayList<>(); + boolean oldStyle; + + private Entry addSection(Section sec) + { + sections.add(sec); + return this; + } + + public byte[] digest(MessageDigest md) + { + md.reset(); + for (Section sec : sections) { + if (oldStyle) { + Section.doOldStyle(md, sec.rawBytes, sec.offset, sec.lengthWithBlankLine); + } else { + md.update(sec.rawBytes, sec.offset, sec.lengthWithBlankLine); + } + } + return md.digest(); + } + + /** Netscape doesn't include the new line. Intel and JavaSoft do */ + + public byte[] digestWorkaround(MessageDigest md) + { + md.reset(); + for (Section sec : sections) { + md.update(sec.rawBytes, sec.offset, sec.length); + } + return md.digest(); + } + } + + private static class Section { int offset; int length; int lengthWithBlankLine; byte[] rawBytes; - boolean oldStyle; - public Entry(int offset, int length, + public Section(int offset, int length, int lengthWithBlankLine, byte[] rawBytes) { this.offset = offset; @@ -197,18 +242,7 @@ public Entry(int offset, int length, this.rawBytes = rawBytes; } - public byte[] digest(MessageDigest md) - { - md.reset(); - if (oldStyle) { - doOldStyle(md,rawBytes, offset, lengthWithBlankLine); - } else { - md.update(rawBytes, offset, lengthWithBlankLine); - } - return md.digest(); - } - - private void doOldStyle(MessageDigest md, + private static void doOldStyle(MessageDigest md, byte[] bytes, int offset, int length) @@ -232,16 +266,6 @@ private void doOldStyle(MessageDigest md, } md.update(bytes, start, i-start); } - - - /** Netscape doesn't include the new line. Intel and JavaSoft do */ - - public byte[] digestWorkaround(MessageDigest md) - { - md.reset(); - md.update(rawBytes, offset, length); - return md.digest(); - } } public Entry get(String name, boolean oldStyle) { From 29fbeff3b89eaafdb12506f9c91ff765589305dd Mon Sep 17 00:00:00 2001 From: mullan Date: Fri, 15 Dec 2017 10:42:25 -0500 Subject: [PATCH 007/196] 8186032: Disable XML Signatures signed with EC keys less than 224 bits Reviewed-by: weijun, rhalade --- src/java.base/share/conf/security/java.security | 1 + 1 file changed, 1 insertion(+) diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index b7766158830..deb5a2e26c2 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -881,6 +881,7 @@ jdk.xml.dsig.secureValidationPolicy=\ disallowReferenceUriSchemes file http https,\ minKeySize RSA 1024,\ minKeySize DSA 1024,\ + minKeySize EC 224,\ noDuplicateIds,\ noRetrievalMethodLoops From a81e06afa40d45a0c8c125ff2ee278e70d7b7d3a Mon Sep 17 00:00:00 2001 From: psandoz Date: Tue, 12 Dec 2017 16:37:39 -0800 Subject: [PATCH 008/196] 8193414: Improvements in MethodType lookups Reviewed-by: ahgross, jrose --- .../classes/java/lang/invoke/MethodType.java | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/java.base/share/classes/java/lang/invoke/MethodType.java b/src/java.base/share/classes/java/lang/invoke/MethodType.java index f3346bc21c6..620404c8782 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodType.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodType.java @@ -1206,33 +1206,24 @@ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOExceptio * @param s the stream to read the object from * @throws java.io.IOException if there is a problem reading the object * @throws ClassNotFoundException if one of the component classes cannot be resolved - * @see #MethodType() * @see #readResolve * @see #writeObject */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { + // Assign temporary defaults in case this object escapes + MethodType_init(void.class, NO_PTYPES); + s.defaultReadObject(); // requires serialPersistentFields to be an empty array Class returnType = (Class) s.readObject(); Class[] parameterArray = (Class[]) s.readObject(); - - // Probably this object will never escape, but let's check - // the field values now, just to be sure. - checkRtype(returnType); - checkPtypes(parameterArray); - parameterArray = parameterArray.clone(); // make sure it is unshared + + // Assign deserialized values MethodType_init(returnType, parameterArray); } - /** - * For serialization only. - * Sets the final fields to null, pending {@code Unsafe.putObject}. - */ - private MethodType() { - this.rtype = null; - this.ptypes = null; - } + // Initialization of state for deserialization only private void MethodType_init(Class rtype, Class[] ptypes) { // In order to communicate these values to readResolve, we must // store them into the implementation-specific final fields. @@ -1259,9 +1250,14 @@ private static class OffsetHolder { */ private Object readResolve() { // Do not use a trusted path for deserialization: - //return makeImpl(rtype, ptypes, true); + // return makeImpl(rtype, ptypes, true); // Verify all operands, and make sure ptypes is unshared: - return methodType(rtype, ptypes); + try { + return methodType(rtype, ptypes); + } finally { + // Re-assign defaults in case this object escapes + MethodType_init(void.class, NO_PTYPES); + } } /** From 42c7d5faab54b353102c7ba611cda626ef6afbe8 Mon Sep 17 00:00:00 2001 From: apetcher Date: Tue, 2 Jan 2018 09:23:01 -0500 Subject: [PATCH 009/196] 8182362: Update CipherOutputStream Usage Summary: Clarify spec of CipherOutputStream in Javadoc comments Reviewed-by: ascarpino --- .../classes/javax/crypto/CipherOutputStream.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/javax/crypto/CipherOutputStream.java b/src/java.base/share/classes/javax/crypto/CipherOutputStream.java index 40e7dc49a6a..30c9c53553c 100644 --- a/src/java.base/share/classes/javax/crypto/CipherOutputStream.java +++ b/src/java.base/share/classes/javax/crypto/CipherOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -42,7 +42,15 @@ * java.io.OutputStream and java.io.FilterOutputStream. This class * has exactly those methods specified in its ancestor classes, and * overrides them all. Moreover, this class catches all exceptions - * that are not thrown by its ancestor classes. + * that are not thrown by its ancestor classes. In particular, this + * class catches BadPaddingException and other exceptions thrown by + * failed integrity checks during decryption. These exceptions are not + * re-thrown, so the client will not be informed that integrity checks + * failed. Because of this behavior, this class may not be suitable + * for use with decryption in an authenticated mode of operation (e.g. GCM) + * if the application requires explicit notification when authentication + * fails. Such an application can use the Cipher API directly as an + * alternative to using this class. * *

It is crucial for a programmer using this class not to use * methods that are not defined or overriden in this class (such as a From bfc2894d7768d9024fe549f7a2a91966c0abb576 Mon Sep 17 00:00:00 2001 From: serb Date: Wed, 3 Jan 2018 09:05:11 -0800 Subject: [PATCH 010/196] 8191696: Better mouse positioning Reviewed-by: skoivu, rhalade, prr, aghaisas --- .../classes/sun/awt/X11/XMouseInfoPeer.java | 23 ++++++++++--------- .../native/libawt/windows/MouseInfo.cpp | 3 ++- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XMouseInfoPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XMouseInfoPeer.java index 09c9450a176..f4c46c2766d 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XMouseInfoPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XMouseInfoPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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,16 +25,16 @@ package sun.awt.X11; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; import java.awt.Point; import java.awt.Window; -import java.awt.GraphicsEnvironment; -import java.awt.GraphicsDevice; import java.awt.peer.MouseInfoPeer; -import sun.awt.X11GraphicsDevice; import sun.awt.AWTAccessor; +import sun.awt.X11GraphicsDevice; -public class XMouseInfoPeer implements MouseInfoPeer { +public final class XMouseInfoPeer implements MouseInfoPeer { /** * Package-private constructor to prevent instantiation. @@ -85,13 +85,14 @@ public int fillPointWithCoords(Point point) { @SuppressWarnings("deprecation") public boolean isWindowUnderMouse(Window w) { - - long display = XToolkit.getDisplay(); - - // java.awt.Component.findUnderMouseInWindow checks that - // the peer is non-null by checking that the component - // is showing. + if (w == null) { + return false; + } XWindow peer = AWTAccessor.getComponentAccessor().getPeer(w); + if (peer == null) { + return false; + } + long display = XToolkit.getDisplay(); long contentWindow = peer.getContentWindow(); long parent = XlibUtil.getParentWindow(contentWindow); diff --git a/src/java.desktop/windows/native/libawt/windows/MouseInfo.cpp b/src/java.desktop/windows/native/libawt/windows/MouseInfo.cpp index 90cef5303cf..37fbc914519 100644 --- a/src/java.desktop/windows/native/libawt/windows/MouseInfo.cpp +++ b/src/java.desktop/windows/native/libawt/windows/MouseInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -48,6 +48,7 @@ Java_sun_awt_windows_WMouseInfoPeer_isWindowUnderMouse(JNIEnv *env, jclass cls, } jobject winPeer = AwtObject::GetPeerForTarget(env, window); + CHECK_NULL_RETURN(winPeer, JNI_FALSE); PDATA pData; pData = JNI_GET_PDATA(winPeer); env->DeleteLocalRef(winPeer); From e1b46ed39293624445dc3284fe6932844124911c Mon Sep 17 00:00:00 2001 From: weijun Date: Fri, 12 Jan 2018 08:06:24 +0800 Subject: [PATCH 011/196] 8189997: Enhance keystore mechanisms 8194259: keytool error: java.io.IOException: Invalid secret key format Reviewed-by: mullan, valeriep, rriggs, ahgross --- .../com/sun/crypto/provider/JceKeyStore.java | 8 +- .../com/sun/crypto/provider/KeyProtector.java | 8 +- .../provider/SealedObjectForKeyProtector.java | 97 ++++++++++++++++++- .../classes/javax/crypto/SealedObject.java | 41 ++++---- .../misc/JavaxCryptoSealedObjectAccess.java} | 44 ++------- .../jdk/internal/misc/SharedSecrets.java | 13 +++ .../share/conf/security/java.security | 20 ++++ 7 files changed, 163 insertions(+), 68 deletions(-) rename src/java.base/share/classes/{com/sun/crypto/provider/ai.java => jdk/internal/misc/JavaxCryptoSealedObjectAccess.java} (56%) diff --git a/src/java.base/share/classes/com/sun/crypto/provider/JceKeyStore.java b/src/java.base/share/classes/com/sun/crypto/provider/JceKeyStore.java index f3190b39a29..bceb60da76d 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/JceKeyStore.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/JceKeyStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2018, 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 @@ -943,8 +943,10 @@ private static class DeserializationChecker implements ObjectInputFilter { // First run a custom filter long nestedDepth = info.depth(); if ((nestedDepth == 1 && - info.serialClass() != SealedObjectForKeyProtector.class) || - nestedDepth > MAX_NESTED_DEPTH) { + info.serialClass() != SealedObjectForKeyProtector.class) || + (nestedDepth > MAX_NESTED_DEPTH && + info.serialClass() != null && + info.serialClass() != Object.class)) { return Status.REJECTED; } diff --git a/src/java.base/share/classes/com/sun/crypto/provider/KeyProtector.java b/src/java.base/share/classes/com/sun/crypto/provider/KeyProtector.java index 823d7bdb8d1..7f9d0b2ee0f 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/KeyProtector.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/KeyProtector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2018, 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,8 +26,6 @@ package com.sun.crypto.provider; import java.io.IOException; -import java.io.Serializable; -import java.security.Security; import java.security.Key; import java.security.PrivateKey; import java.security.Provider; @@ -35,7 +33,6 @@ import java.security.MessageDigest; import java.security.GeneralSecurityException; import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; import java.security.UnrecoverableKeyException; import java.security.AlgorithmParameters; import java.security.spec.InvalidParameterSpecException; @@ -44,7 +41,6 @@ import javax.crypto.Cipher; import javax.crypto.CipherSpi; import javax.crypto.SecretKey; -import javax.crypto.IllegalBlockSizeException; import javax.crypto.SealedObject; import javax.crypto.spec.*; import sun.security.x509.AlgorithmId; @@ -347,7 +343,7 @@ Key unseal(SealedObject so) SunJCE.getInstance(), "PBEWithMD5AndTripleDES"); cipher.init(Cipher.DECRYPT_MODE, skey, params); - return (Key)soForKeyProtector.getObject(cipher); + return soForKeyProtector.getKey(cipher); } catch (NoSuchAlgorithmException ex) { // Note: this catch needed to be here because of the // later catch of GeneralSecurityException diff --git a/src/java.base/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java b/src/java.base/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java index d88e7668c20..36056896f35 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2018, 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,8 @@ package com.sun.crypto.provider; +import jdk.internal.misc.SharedSecrets; + import java.io.*; import java.security.*; import javax.crypto.*; @@ -33,6 +35,16 @@ final class SealedObjectForKeyProtector extends SealedObject { static final long serialVersionUID = -3650226485480866989L; + /** + * The InputStreamFilter for a Key object inside this SealedObject. It can + * be either provided as a {@link Security} property or a system property + * (when provided as latter, it shadows the former). If the result of this + * filter is {@link java.io.ObjectInputFilter.Status.UNDECIDED}, the system + * level filter defined by jdk.serialFilter will be consulted. The value + * of this property uses the same format of jdk.serialFilter. + */ + private static final String KEY_SERIAL_FILTER = "jceks.key.serialFilter"; + SealedObjectForKeyProtector(Serializable object, Cipher c) throws IOException, IllegalBlockSizeException { super(object, c); @@ -59,4 +71,87 @@ AlgorithmParameters getParameters() { } return params; } + + final Key getKey(Cipher c) + throws IOException, ClassNotFoundException, IllegalBlockSizeException, + BadPaddingException { + + try (ObjectInputStream ois = SharedSecrets.getJavaxCryptoSealedObjectAccess() + .getExtObjectInputStream(this, c)) { + AccessController.doPrivileged( + (PrivilegedAction) () -> { + ois.setObjectInputFilter(DeserializationChecker.ONE_FILTER); + return null; + }); + try { + @SuppressWarnings("unchecked") + Key t = (Key) ois.readObject(); + return t; + } catch (InvalidClassException ice) { + String msg = ice.getMessage(); + if (msg.contains("REJECTED")) { + throw new IOException("Rejected by the" + + " jceks.key.serialFilter or jdk.serialFilter" + + " property", ice); + } else { + throw ice; + } + } + } + } + + /** + * The filter for the content of a SealedObjectForKeyProtector. + * + * First, the jceks.key.serialFilter will be consulted. If the result + * is UNDECIDED, the system level jdk.serialFilter will be consulted. + */ + private static class DeserializationChecker implements ObjectInputFilter { + + private static final ObjectInputFilter ONE_FILTER; + + static { + String prop = AccessController.doPrivileged( + (PrivilegedAction) () -> { + String tmp = System.getProperty(KEY_SERIAL_FILTER); + if (tmp != null) { + return tmp; + } else { + return Security.getProperty(KEY_SERIAL_FILTER); + } + }); + ONE_FILTER = new DeserializationChecker(prop == null ? null + : ObjectInputFilter.Config.createFilter(prop)); + } + + private final ObjectInputFilter base; + + private DeserializationChecker(ObjectInputFilter base) { + this.base = base; + } + + @Override + public ObjectInputFilter.Status checkInput( + ObjectInputFilter.FilterInfo info) { + + if (info.serialClass() == Object.class) { + return Status.UNDECIDED; + } + + if (base != null) { + Status result = base.checkInput(info); + if (result != Status.UNDECIDED) { + return result; + } + } + + ObjectInputFilter defaultFilter = + ObjectInputFilter.Config.getSerialFilter(); + if (defaultFilter != null) { + return defaultFilter.checkInput(info); + } + + return Status.UNDECIDED; + } + } } diff --git a/src/java.base/share/classes/javax/crypto/SealedObject.java b/src/java.base/share/classes/javax/crypto/SealedObject.java index 3d657423aa4..9c31f375325 100644 --- a/src/java.base/share/classes/javax/crypto/SealedObject.java +++ b/src/java.base/share/classes/javax/crypto/SealedObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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,8 @@ package javax.crypto; +import jdk.internal.misc.SharedSecrets; + import java.io.*; import java.security.AlgorithmParameters; import java.security.Key; @@ -287,17 +289,7 @@ public final Object getObject(Cipher c) throws IOException, ClassNotFoundException, IllegalBlockSizeException, BadPaddingException { - /* - * Unseal the object - */ - byte[] content = c.doFinal(this.encryptedContent); - - /* - * De-serialize it - */ - // creating a stream pipe-line, from b to a - ByteArrayInputStream b = new ByteArrayInputStream(content); - ObjectInput a = new extObjectInputStream(b); + ObjectInput a = getExtObjectInputStream(c); try { Object obj = a.readObject(); return obj; @@ -417,17 +409,7 @@ private Object unseal(Key key, String provider) throw new RuntimeException(iape.getMessage()); } - /* - * Unseal the object - */ - byte[] content = c.doFinal(this.encryptedContent); - - /* - * De-serialize it - */ - // creating a stream pipe-line, from b to a - ByteArrayInputStream b = new ByteArrayInputStream(content); - ObjectInput a = new extObjectInputStream(b); + ObjectInput a = getExtObjectInputStream(c); try { Object obj = a.readObject(); return obj; @@ -450,6 +432,19 @@ private void readObject(java.io.ObjectInputStream s) if (encodedParams != null) encodedParams = encodedParams.clone(); } + + // This method is also called inside SealedObjectForKeyProtector.java. + private ObjectInputStream getExtObjectInputStream(Cipher c) + throws BadPaddingException, IllegalBlockSizeException, IOException { + + byte[] content = c.doFinal(this.encryptedContent); + ByteArrayInputStream b = new ByteArrayInputStream(content); + return new extObjectInputStream(b); + } + + static { + SharedSecrets.setJavaxCryptoSealedObjectAccess((obj,c) -> obj.getExtObjectInputStream(c)); + } } final class extObjectInputStream extends ObjectInputStream { diff --git a/src/java.base/share/classes/com/sun/crypto/provider/ai.java b/src/java.base/share/classes/jdk/internal/misc/JavaxCryptoSealedObjectAccess.java similarity index 56% rename from src/java.base/share/classes/com/sun/crypto/provider/ai.java rename to src/java.base/share/classes/jdk/internal/misc/JavaxCryptoSealedObjectAccess.java index 853307396ff..291ee9e3aaa 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/ai.java +++ b/src/java.base/share/classes/jdk/internal/misc/JavaxCryptoSealedObjectAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -22,43 +22,17 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +package jdk.internal.misc; -package com.sun.crypto.provider; - -import java.io.IOException; -import java.io.Serializable; -import java.io.ObjectStreamException; -import java.security.AlgorithmParameters; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; +import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.SealedObject; -import javax.crypto.spec.*; - -/** - * This class is introduced to workaround a problem in - * the SunJCE provider shipped in JCE 1.2.1: the class - * SealedObjectForKeyProtector was obfuscated due to a mistake. - * - * In order to retrieve secret keys in a JCEKS KeyStore written - * by the SunJCE provider in JCE 1.2.1, this class will be used. - * - * @author Valerie Peng - * - * - * @see JceKeyStore - */ - -final class ai extends javax.crypto.SealedObject { - - static final long serialVersionUID = -7051502576727967444L; - - ai(SealedObject so) { - super(so); - } +import java.io.IOException; +import java.io.ObjectInputStream; - Object readResolve() throws ObjectStreamException { - return new SealedObjectForKeyProtector(this); - } +public interface JavaxCryptoSealedObjectAccess { + ObjectInputStream getExtObjectInputStream( + SealedObject sealed, Cipher cipher) + throws BadPaddingException, IllegalBlockSizeException, IOException; } diff --git a/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java b/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java index fd792cd847f..04439fba710 100644 --- a/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java +++ b/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java @@ -25,6 +25,7 @@ package jdk.internal.misc; +import javax.crypto.SealedObject; import java.io.ObjectInputFilter; import java.lang.module.ModuleDescriptor; import java.util.ResourceBundle; @@ -71,6 +72,7 @@ public class SharedSecrets { private static JavaObjectInputStreamAccess javaObjectInputStreamAccess; private static JavaObjectInputFilterAccess javaObjectInputFilterAccess; private static JavaIORandomAccessFileAccess javaIORandomAccessFileAccess; + private static JavaxCryptoSealedObjectAccess javaxCryptoSealedObjectAccess; public static JavaUtilJarAccess javaUtilJarAccess() { if (javaUtilJarAccess == null) { @@ -324,4 +326,15 @@ public static JavaIORandomAccessFileAccess getJavaIORandomAccessFileAccess() { } return javaIORandomAccessFileAccess; } + + public static void setJavaxCryptoSealedObjectAccess(JavaxCryptoSealedObjectAccess jcsoa) { + javaxCryptoSealedObjectAccess = jcsoa; + } + + public static JavaxCryptoSealedObjectAccess getJavaxCryptoSealedObjectAccess() { + if (javaxCryptoSealedObjectAccess == null) { + unsafe.ensureClassInitialized(SealedObject.class); + } + return javaxCryptoSealedObjectAccess; + } } diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index deb5a2e26c2..12cb112819f 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -895,6 +895,9 @@ jdk.xml.dsig.secureValidationPolicy=\ # Patterns are separated by ";" (semicolon). # Whitespace is significant and is considered part of the pattern. # +# If the system property jdk.serialFilter is also specified, it supersedes +# the security property value defined here. +# # If a pattern includes a "=", it sets a limit. # If a limit appears more than once the last value is used. # Limits are checked before classes regardless of the order in the @@ -1005,3 +1008,20 @@ jdk.xml.dsig.secureValidationPolicy=\ # It is not guaranteed to be examined and used by other implementations. # #com.sun.CORBA.ORBIorTypeCheckRegistryFilter=binary_class_name;binary_class_name + +# +# JCEKS Encrypted Key Serial Filter +# +# This filter, if configured, is used by the JCEKS KeyStore during the +# deserialization of the encrypted Key object stored inside a key entry. +# If not configured or the filter result is UNDECIDED (i.e. none of the patterns +# matches), the filter configured by jdk.serialFilter will be consulted. +# +# If the system property jceks.key.serialFilter is also specified, it supersedes +# the security property value defined here. +# +# The filter pattern uses the same format as jdk.serialFilter. The default +# pattern allows java.lang.Enum, java.security.KeyRep, java.security.KeyRep$Type, +# and javax.crypto.spec.SecretKeySpec and rejects all the others. +jceks.key.serialFilter = java.base/java.lang.Enum;java.base/java.security.KeyRep;\ + java.base/java.security.KeyRep$Type;java.base/javax.crypto.spec.SecretKeySpec;!* From 64c50226369ab2926449be859b4dde9029a961b3 Mon Sep 17 00:00:00 2001 From: weijun Date: Thu, 18 Jan 2018 11:03:30 +0800 Subject: [PATCH 012/196] 8195662: Add T6587786.java to problem list before JDK-8195589 is resolved Reviewed-by: mullan, jjg --- test/langtools/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/langtools/ProblemList.txt b/test/langtools/ProblemList.txt index f94a7f30fcc..d7896926cac 100644 --- a/test/langtools/ProblemList.txt +++ b/test/langtools/ProblemList.txt @@ -63,6 +63,7 @@ tools/javac/jvm/VerboseOutTest.java # javap tools/javap/output/RepeatingTypeAnnotations.java 8057687 generic-all emit correct byte code an attributes for type annotations +tools/javap/T6587786.java 8195589 generic-all T6587786.java failed after JDK-8189997 ########################################################################### # From f9369684021e232708b79651c1d9923af090923c Mon Sep 17 00:00:00 2001 From: joehw Date: Wed, 17 Jan 2018 22:24:46 -0800 Subject: [PATCH 013/196] 8189993: Improve document portability Reviewed-by: rriggs, lancea, dfuchs, skoivu --- .../org/apache/xerces/internal/dom/NamedNodeMapImpl.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/NamedNodeMapImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/NamedNodeMapImpl.java index 051237b2561..27086ee5bed 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/NamedNodeMapImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/NamedNodeMapImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -56,7 +56,7 @@ * @xerces.internal * * @since PR-DOM-Level-1-19980818. - * @LastModified: Oct 2017 + * @LastModified: Jan 2018 */ public class NamedNodeMapImpl implements NamedNodeMap, Serializable { @@ -595,12 +595,14 @@ public void removeAll (){ } } + @SuppressWarnings("unchecked") private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); if (nodes != null) { // nodes are written as a Vector for compatibility. - nodes = new ArrayList<>(nodes); + // cast to Vector is required + nodes = new ArrayList<>((Vector)nodes); } } From a5abe837f64b2016bc53f92f291c7886ef185168 Mon Sep 17 00:00:00 2001 From: igerasim Date: Fri, 19 Jan 2018 11:24:39 -0800 Subject: [PATCH 014/196] 8175075: Add 3DES to the default disabled algorithm security property Reviewed-by: xuelei, mullan, rhalade --- src/java.base/share/conf/security/java.security | 2 +- .../java/net/httpclient/http2/TLSConnection.java | 3 +++ test/jdk/javax/net/ssl/DTLS/CipherSuite.java | 9 +++++++-- .../https/NewImpl/ComHostnameVerifier.java | 15 ++++++++------- .../https/NewImpl/JavaxHostnameVerifier.java | 15 ++++++++------- 5 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index 12cb112819f..35e466804e2 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -676,7 +676,7 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ # Example: # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 1024, \ - EC keySize < 224, DES40_CBC, RC4_40 + EC keySize < 224, DES40_CBC, RC4_40, 3DES_EDE_CBC # # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) diff --git a/test/jdk/java/net/httpclient/http2/TLSConnection.java b/test/jdk/java/net/httpclient/http2/TLSConnection.java index 6c1cb89ed80..e0179dd16d6 100644 --- a/test/jdk/java/net/httpclient/http2/TLSConnection.java +++ b/test/jdk/java/net/httpclient/http2/TLSConnection.java @@ -27,6 +27,7 @@ import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; +import java.security.Security; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpRequest.BodyPublishers; @@ -57,6 +58,8 @@ public class TLSConnection { private static final SSLParameters USE_DEFAULT_SSL_PARAMETERS = new SSLParameters(); public static void main(String[] args) throws Exception { + // re-enable 3DES + Security.setProperty("jdk.tls.disabledAlgorithms", ""); // enable all logging System.setProperty("jdk.httpclient.HttpClient.log", "all,frames:all"); diff --git a/test/jdk/javax/net/ssl/DTLS/CipherSuite.java b/test/jdk/javax/net/ssl/DTLS/CipherSuite.java index cfca351e1cb..59639f1ea18 100644 --- a/test/jdk/javax/net/ssl/DTLS/CipherSuite.java +++ b/test/jdk/javax/net/ssl/DTLS/CipherSuite.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, 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 @@ -38,7 +38,7 @@ * @run main/othervm CipherSuite TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 * @run main/othervm CipherSuite TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA * @run main/othervm CipherSuite TLS_DHE_RSA_WITH_AES_128_CBC_SHA - * @run main/othervm CipherSuite TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * @run main/othervm CipherSuite TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA re-enable * @run main/othervm CipherSuite TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 * @run main/othervm CipherSuite TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 * @run main/othervm CipherSuite TLS_RSA_WITH_AES_128_GCM_SHA256 @@ -49,6 +49,7 @@ */ import javax.net.ssl.SSLEngine; +import java.security.Security; /** * Test common DTLS cipher suites. @@ -59,6 +60,10 @@ public class CipherSuite extends DTLSOverDatagram { volatile static String cipherSuite; public static void main(String[] args) throws Exception { + if (args.length > 1 && "re-enable".equals(args[1])) { + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + } + cipherSuite = args[0]; CipherSuite testCase = new CipherSuite(); diff --git a/test/jdk/sun/net/www/protocol/https/NewImpl/ComHostnameVerifier.java b/test/jdk/sun/net/www/protocol/https/NewImpl/ComHostnameVerifier.java index 6e9972444e5..2a1f80a4cac 100644 --- a/test/jdk/sun/net/www/protocol/https/NewImpl/ComHostnameVerifier.java +++ b/test/jdk/sun/net/www/protocol/https/NewImpl/ComHostnameVerifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,23 +21,22 @@ * questions. */ +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. + /* * @test - * @bug 4474255 - * @test 1.1 01/06/27 - * @bug 4484246 + * @bug 4474255 4484246 * @summary When an application enables anonymous SSL cipher suite, * Hostname verification is not required * @modules java.base/com.sun.net.ssl * java.base/com.sun.net.ssl.internal.www.protocol.https * @run main/othervm ComHostnameVerifier - * - * SunJSSE does not support dynamic system properties, no way to re-use - * system properties in samevm/agentvm mode. */ import java.io.*; import java.net.*; +import java.security.Security; import javax.net.ssl.*; import javax.security.cert.*; import com.sun.net.ssl.HostnameVerifier; @@ -261,6 +260,8 @@ void doClientSide() throws Exception { volatile Exception clientException = null; public static void main(String[] args) throws Exception { + // re-enable 3DES + Security.setProperty("jdk.tls.disabledAlgorithms", ""); if (debug) System.setProperty("javax.net.debug", "all"); diff --git a/test/jdk/sun/net/www/protocol/https/NewImpl/JavaxHostnameVerifier.java b/test/jdk/sun/net/www/protocol/https/NewImpl/JavaxHostnameVerifier.java index 3337871fbdf..a02d7622c8b 100644 --- a/test/jdk/sun/net/www/protocol/https/NewImpl/JavaxHostnameVerifier.java +++ b/test/jdk/sun/net/www/protocol/https/NewImpl/JavaxHostnameVerifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,21 +21,20 @@ * questions. */ +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. + /* * @test - * @bug 4474255 - * @test 1.1 01/06/27 - * @bug 4484246 + * @bug 4474255 4484246 * @summary When an application enables anonymous SSL cipher suite, * Hostname verification is not required * @run main/othervm JavaxHostnameVerifier - * - * SunJSSE does not support dynamic system properties, no way to re-use - * system properties in samevm/agentvm mode. */ import java.io.*; import java.net.*; +import java.security.Security; import java.security.cert.*; import javax.net.ssl.*; @@ -244,6 +243,8 @@ void doClientSide() throws Exception { volatile Exception clientException = null; public static void main(String[] args) throws Exception { + // re-enable 3DES + Security.setProperty("jdk.tls.disabledAlgorithms", ""); if (debug) System.setProperty("javax.net.debug", "all"); From bc53d4a59594046a66732ec93d84e9e311958788 Mon Sep 17 00:00:00 2001 From: psandoz Date: Mon, 22 Jan 2018 13:27:28 -0800 Subject: [PATCH 015/196] 8194233: Improve support for array handles Reviewed-by: jrose, vlivanov, ahgross, rhalade --- .../lang/invoke/X-VarHandle.java.template | 50 ++++++--- .../invoke/VarHandles/VarHandleBaseTest.java | 8 ++ .../VarHandleTestAccessBoolean.java | 3 +- .../VarHandles/VarHandleTestAccessByte.java | 3 +- .../VarHandles/VarHandleTestAccessChar.java | 3 +- .../VarHandles/VarHandleTestAccessDouble.java | 3 +- .../VarHandles/VarHandleTestAccessFloat.java | 3 +- .../VarHandles/VarHandleTestAccessInt.java | 3 +- .../VarHandles/VarHandleTestAccessLong.java | 3 +- .../VarHandles/VarHandleTestAccessShort.java | 3 +- .../VarHandles/VarHandleTestAccessString.java | 90 +++++++++++++++- .../X-VarHandleTestAccess.java.template | 100 +++++++++++++++++- 12 files changed, 248 insertions(+), 24 deletions(-) diff --git a/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template b/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template index 71419c36548..505a8dad470 100644 --- a/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template +++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template @@ -592,6 +592,28 @@ final class VarHandle$Type$s { return accessMode.at.accessModeType({#if[Object]?arrayType:$type$[].class}, {#if[Object]?arrayType.getComponentType():$type$.class}, int.class); } +#if[Object] + @ForceInline + static Object runtimeTypeCheck(Array handle, Object[] oarray, Object value) { + if (handle.arrayType == oarray.getClass()) { + // Fast path: static array type same as argument array type + return handle.componentType.cast(value); + } else { + // Slow path: check value against argument array component type + return reflectiveTypeCheck(oarray, value); + } + } + + @ForceInline + static Object reflectiveTypeCheck(Object[] oarray, Object value) { + try { + return oarray.getClass().getComponentType().cast(value); + } catch (ClassCastException e) { + throw new ArrayStoreException(); + } + } +#end[Object] + @ForceInline static $type$ get(Array handle, Object oarray, int index) { #if[Object] @@ -632,7 +654,7 @@ final class VarHandle$Type$s { #end[Object] UNSAFE.put$Type$Volatile(array, (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, - {#if[Object]?handle.componentType.cast(value):value}); + {#if[Object]?runtimeTypeCheck(handle, array, value):value}); } @ForceInline @@ -655,7 +677,7 @@ final class VarHandle$Type$s { #end[Object] UNSAFE.put$Type$Opaque(array, (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, - {#if[Object]?handle.componentType.cast(value):value}); + {#if[Object]?runtimeTypeCheck(handle, array, value):value}); } @ForceInline @@ -678,7 +700,7 @@ final class VarHandle$Type$s { #end[Object] UNSAFE.put$Type$Release(array, (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, - {#if[Object]?handle.componentType.cast(value):value}); + {#if[Object]?runtimeTypeCheck(handle, array, value):value}); } #if[CAS] @@ -692,7 +714,7 @@ final class VarHandle$Type$s { return UNSAFE.compareAndSet$Type$(array, (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, - {#if[Object]?handle.componentType.cast(value):value}); + {#if[Object]?runtimeTypeCheck(handle, array, value):value}); } @ForceInline @@ -705,7 +727,7 @@ final class VarHandle$Type$s { return UNSAFE.compareAndExchange$Type$(array, (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, - {#if[Object]?handle.componentType.cast(value):value}); + {#if[Object]?runtimeTypeCheck(handle, array, value):value}); } @ForceInline @@ -718,7 +740,7 @@ final class VarHandle$Type$s { return UNSAFE.compareAndExchange$Type$Acquire(array, (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, - {#if[Object]?handle.componentType.cast(value):value}); + {#if[Object]?runtimeTypeCheck(handle, array, value):value}); } @ForceInline @@ -731,7 +753,7 @@ final class VarHandle$Type$s { return UNSAFE.compareAndExchange$Type$Release(array, (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, - {#if[Object]?handle.componentType.cast(value):value}); + {#if[Object]?runtimeTypeCheck(handle, array, value):value}); } @ForceInline @@ -744,7 +766,7 @@ final class VarHandle$Type$s { return UNSAFE.weakCompareAndSet$Type$Plain(array, (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, - {#if[Object]?handle.componentType.cast(value):value}); + {#if[Object]?runtimeTypeCheck(handle, array, value):value}); } @ForceInline @@ -757,7 +779,7 @@ final class VarHandle$Type$s { return UNSAFE.weakCompareAndSet$Type$(array, (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, - {#if[Object]?handle.componentType.cast(value):value}); + {#if[Object]?runtimeTypeCheck(handle, array, value):value}); } @ForceInline @@ -770,7 +792,7 @@ final class VarHandle$Type$s { return UNSAFE.weakCompareAndSet$Type$Acquire(array, (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, - {#if[Object]?handle.componentType.cast(value):value}); + {#if[Object]?runtimeTypeCheck(handle, array, value):value}); } @ForceInline @@ -783,7 +805,7 @@ final class VarHandle$Type$s { return UNSAFE.weakCompareAndSet$Type$Release(array, (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, - {#if[Object]?handle.componentType.cast(value):value}); + {#if[Object]?runtimeTypeCheck(handle, array, value):value}); } @ForceInline @@ -795,7 +817,7 @@ final class VarHandle$Type$s { #end[Object] return UNSAFE.getAndSet$Type$(array, (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, - {#if[Object]?handle.componentType.cast(value):value}); + {#if[Object]?runtimeTypeCheck(handle, array, value):value}); } @ForceInline @@ -807,7 +829,7 @@ final class VarHandle$Type$s { #end[Object] return UNSAFE.getAndSet$Type$Acquire(array, (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, - {#if[Object]?handle.componentType.cast(value):value}); + {#if[Object]?runtimeTypeCheck(handle, array, value):value}); } @ForceInline @@ -819,7 +841,7 @@ final class VarHandle$Type$s { #end[Object] return UNSAFE.getAndSet$Type$Release(array, (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, - {#if[Object]?handle.componentType.cast(value):value}); + {#if[Object]?runtimeTypeCheck(handle, array, value):value}); } #end[CAS] #if[AtomicAdd] diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleBaseTest.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleBaseTest.java index 30469225067..7792df89155 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleBaseTest.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleBaseTest.java @@ -70,6 +70,14 @@ static void checkIOOBE(Object message, ThrowingRunnable r) { checkWithThrowable(IndexOutOfBoundsException.class, message, r); } + static void checkASE(ThrowingRunnable r) { + checkWithThrowable(ArrayStoreException.class, null, r); + } + + static void checkASE(Object message, ThrowingRunnable r) { + checkWithThrowable(ArrayStoreException.class, message, r); + } + static void checkISE(ThrowingRunnable r) { checkWithThrowable(IllegalStateException.class, null, r); } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java index a4d54635d95..ea85761a9a9 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java @@ -60,6 +60,7 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest { VarHandle vhArray; + @BeforeClass public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -210,7 +211,6 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleAccessTestCase("Array index out of bounds", vhArray, VarHandleTestAccessBoolean::testArrayIndexOutOfBounds, false)); - // Work around issue with jtreg summary reporting which truncates // the String result of Object.toString to 30 characters, hence // the first dummy argument @@ -1255,5 +1255,6 @@ static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { }); } } + } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java index be79776202b..033451a7753 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java @@ -60,6 +60,7 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest { VarHandle vhArray; + @BeforeClass public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -210,7 +211,6 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleAccessTestCase("Array index out of bounds", vhArray, VarHandleTestAccessByte::testArrayIndexOutOfBounds, false)); - // Work around issue with jtreg summary reporting which truncates // the String result of Object.toString to 30 characters, hence // the first dummy argument @@ -1292,5 +1292,6 @@ static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { }); } } + } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java index 6e2f42cee14..ecd685f073e 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java @@ -60,6 +60,7 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest { VarHandle vhArray; + @BeforeClass public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -210,7 +211,6 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleAccessTestCase("Array index out of bounds", vhArray, VarHandleTestAccessChar::testArrayIndexOutOfBounds, false)); - // Work around issue with jtreg summary reporting which truncates // the String result of Object.toString to 30 characters, hence // the first dummy argument @@ -1292,5 +1292,6 @@ static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { }); } } + } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java index e0564d5d002..3aa12aa4098 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java @@ -60,6 +60,7 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest { VarHandle vhArray; + @BeforeClass public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -210,7 +211,6 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleAccessTestCase("Array index out of bounds", vhArray, VarHandleTestAccessDouble::testArrayIndexOutOfBounds, false)); - // Work around issue with jtreg summary reporting which truncates // the String result of Object.toString to 30 characters, hence // the first dummy argument @@ -1183,5 +1183,6 @@ static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { } } + } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java index 4fa6b41fd3c..81f19fb91dd 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java @@ -60,6 +60,7 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest { VarHandle vhArray; + @BeforeClass public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -210,7 +211,6 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleAccessTestCase("Array index out of bounds", vhArray, VarHandleTestAccessFloat::testArrayIndexOutOfBounds, false)); - // Work around issue with jtreg summary reporting which truncates // the String result of Object.toString to 30 characters, hence // the first dummy argument @@ -1183,5 +1183,6 @@ static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { } } + } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java index 2fbcc9cb46d..bfa7665a8f5 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java @@ -60,6 +60,7 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest { VarHandle vhArray; + @BeforeClass public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -210,7 +211,6 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleAccessTestCase("Array index out of bounds", vhArray, VarHandleTestAccessInt::testArrayIndexOutOfBounds, false)); - // Work around issue with jtreg summary reporting which truncates // the String result of Object.toString to 30 characters, hence // the first dummy argument @@ -1292,5 +1292,6 @@ static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { }); } } + } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java index d94cdc131d2..6d948593f86 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java @@ -60,6 +60,7 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest { VarHandle vhArray; + @BeforeClass public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -210,7 +211,6 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleAccessTestCase("Array index out of bounds", vhArray, VarHandleTestAccessLong::testArrayIndexOutOfBounds, false)); - // Work around issue with jtreg summary reporting which truncates // the String result of Object.toString to 30 characters, hence // the first dummy argument @@ -1292,5 +1292,6 @@ static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { }); } } + } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java index 7ff96eb10ea..088de606734 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java @@ -60,6 +60,7 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest { VarHandle vhArray; + @BeforeClass public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -210,7 +211,6 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleAccessTestCase("Array index out of bounds", vhArray, VarHandleTestAccessShort::testArrayIndexOutOfBounds, false)); - // Work around issue with jtreg summary reporting which truncates // the String result of Object.toString to 30 characters, hence // the first dummy argument @@ -1292,5 +1292,6 @@ static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { }); } } + } diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessString.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessString.java index 0904505db40..04ed5de6c35 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessString.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessString.java @@ -60,6 +60,8 @@ public class VarHandleTestAccessString extends VarHandleBaseTest { VarHandle vhArray; + VarHandle vhArrayObject; + @BeforeClass public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -75,6 +77,7 @@ public void setup() throws Exception { VarHandleTestAccessString.class, "static_v", String.class); vhArray = MethodHandles.arrayElementVarHandle(String[].class); + vhArrayObject = MethodHandles.arrayElementVarHandle(Object[].class); } @@ -204,13 +207,17 @@ public Object[][] accessTestCaseProvider() throws Exception { cases.add(new VarHandleAccessTestCase("Array", vhArray, VarHandleTestAccessString::testArray)); + cases.add(new VarHandleAccessTestCase("Array Object[]", + vhArrayObject, VarHandleTestAccessString::testArray)); cases.add(new VarHandleAccessTestCase("Array unsupported", vhArray, VarHandleTestAccessString::testArrayUnsupported, false)); cases.add(new VarHandleAccessTestCase("Array index out of bounds", vhArray, VarHandleTestAccessString::testArrayIndexOutOfBounds, false)); - + cases.add(new VarHandleAccessTestCase("Array store exception", + vhArrayObject, VarHandleTestAccessString::testArrayStoreException, + false)); // Work around issue with jtreg summary reporting which truncates // the String result of Object.toString to 30 characters, hence // the first dummy argument @@ -1146,5 +1153,86 @@ static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { } } + + static void testArrayStoreException(VarHandle vh) throws Throwable { + Object[] array = new String[10]; + Arrays.fill(array, "foo"); + Object value = new Object(); + + // Set + checkASE(() -> { + vh.set(array, 0, value); + }); + + // SetVolatile + checkASE(() -> { + vh.setVolatile(array, 0, value); + }); + + // SetOpaque + checkASE(() -> { + vh.setOpaque(array, 0, value); + }); + + // SetRelease + checkASE(() -> { + vh.setRelease(array, 0, value); + }); + + // CompareAndSet + checkASE(() -> { // receiver reference class + boolean r = vh.compareAndSet(array, 0, "foo", value); + }); + + // WeakCompareAndSet + checkASE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetPlain(array, 0, "foo", value); + }); + + // WeakCompareAndSetVolatile + checkASE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSet(array, 0, "foo", value); + }); + + // WeakCompareAndSetAcquire + checkASE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetAcquire(array, 0, "foo", value); + }); + + // WeakCompareAndSetRelease + checkASE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetRelease(array, 0, "foo", value); + }); + + // CompareAndExchange + checkASE(() -> { // receiver reference class + String x = (String) vh.compareAndExchange(array, 0, "foo", value); + }); + + // CompareAndExchangeAcquire + checkASE(() -> { // receiver reference class + String x = (String) vh.compareAndExchangeAcquire(array, 0, "foo", value); + }); + + // CompareAndExchangeRelease + checkASE(() -> { // receiver reference class + String x = (String) vh.compareAndExchangeRelease(array, 0, "foo", value); + }); + + // GetAndSet + checkASE(() -> { // receiver reference class + String x = (String) vh.getAndSet(array, 0, value); + }); + + // GetAndSetAcquire + checkASE(() -> { // receiver reference class + String x = (String) vh.getAndSetAcquire(array, 0, value); + }); + + // GetAndSetRelease + checkASE(() -> { // receiver reference class + String x = (String) vh.getAndSetRelease(array, 0, value); + }); + } } diff --git a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template index 3d36bd35efc..5014fc1b187 100644 --- a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template +++ b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template @@ -60,6 +60,10 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { VarHandle vhArray; +#if[String] + VarHandle vhArrayObject; +#end[String] + @BeforeClass public void setup() throws Exception { vhFinalField = MethodHandles.lookup().findVarHandle( @@ -75,6 +79,9 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { VarHandleTestAccess$Type$.class, "static_v", $type$.class); vhArray = MethodHandles.arrayElementVarHandle($type$[].class); +#if[String] + vhArrayObject = MethodHandles.arrayElementVarHandle(Object[].class); +#end[String] } @@ -236,13 +243,21 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { cases.add(new VarHandleAccessTestCase("Array", vhArray, VarHandleTestAccess$Type$::testArray)); +#if[String] + cases.add(new VarHandleAccessTestCase("Array Object[]", + vhArrayObject, VarHandleTestAccess$Type$::testArray)); +#end[String] cases.add(new VarHandleAccessTestCase("Array unsupported", vhArray, VarHandleTestAccess$Type$::testArrayUnsupported, false)); cases.add(new VarHandleAccessTestCase("Array index out of bounds", vhArray, VarHandleTestAccess$Type$::testArrayIndexOutOfBounds, false)); - +#if[String] + cases.add(new VarHandleAccessTestCase("Array store exception", + vhArrayObject, VarHandleTestAccess$Type$::testArrayStoreException, + false)); +#end[String] // Work around issue with jtreg summary reporting which truncates // the String result of Object.toString to 30 characters, hence // the first dummy argument @@ -1823,5 +1838,88 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { #end[Bitwise] } } + +#if[String] + static void testArrayStoreException(VarHandle vh) throws Throwable { + Object[] array = new $type$[10]; + Arrays.fill(array, $value1$); + Object value = new Object(); + + // Set + checkASE(() -> { + vh.set(array, 0, value); + }); + + // SetVolatile + checkASE(() -> { + vh.setVolatile(array, 0, value); + }); + + // SetOpaque + checkASE(() -> { + vh.setOpaque(array, 0, value); + }); + + // SetRelease + checkASE(() -> { + vh.setRelease(array, 0, value); + }); + + // CompareAndSet + checkASE(() -> { // receiver reference class + boolean r = vh.compareAndSet(array, 0, $value1$, value); + }); + + // WeakCompareAndSet + checkASE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetPlain(array, 0, $value1$, value); + }); + + // WeakCompareAndSetVolatile + checkASE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSet(array, 0, $value1$, value); + }); + + // WeakCompareAndSetAcquire + checkASE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetAcquire(array, 0, $value1$, value); + }); + + // WeakCompareAndSetRelease + checkASE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetRelease(array, 0, $value1$, value); + }); + + // CompareAndExchange + checkASE(() -> { // receiver reference class + $type$ x = ($type$) vh.compareAndExchange(array, 0, $value1$, value); + }); + + // CompareAndExchangeAcquire + checkASE(() -> { // receiver reference class + $type$ x = ($type$) vh.compareAndExchangeAcquire(array, 0, $value1$, value); + }); + + // CompareAndExchangeRelease + checkASE(() -> { // receiver reference class + $type$ x = ($type$) vh.compareAndExchangeRelease(array, 0, $value1$, value); + }); + + // GetAndSet + checkASE(() -> { // receiver reference class + $type$ x = ($type$) vh.getAndSet(array, 0, value); + }); + + // GetAndSetAcquire + checkASE(() -> { // receiver reference class + $type$ x = ($type$) vh.getAndSetAcquire(array, 0, value); + }); + + // GetAndSetRelease + checkASE(() -> { // receiver reference class + $type$ x = ($type$) vh.getAndSetRelease(array, 0, value); + }); + } +#end[String] } From 87c8de7d5f1f36d662a5f271c525e5366acec3bd Mon Sep 17 00:00:00 2001 From: apetcher Date: Tue, 23 Jan 2018 11:18:11 -0500 Subject: [PATCH 016/196] 8193409: Improve AES supporting classes Reviewed-by: valeriep --- .../sun/crypto/provider/DESedeWrapCipher.java | 18 +- .../sun/crypto/provider/FeedbackCipher.java | 6 +- .../crypto/provider/GaloisCounterMode.java | 15 +- .../security/ucrypto/NativeGCMCipher.java | 14 +- .../security/ucrypto/UcryptoException.java | 188 ++++++++++-------- 5 files changed, 143 insertions(+), 98 deletions(-) diff --git a/src/java.base/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java b/src/java.base/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java index df00ec2736c..8c1a5a3b3af 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java @@ -470,6 +470,9 @@ protected byte[] engineWrap(Key key) } catch (InvalidKeyException ike) { // should never happen throw new RuntimeException("Internal cipher key is corrupted"); + } catch (InvalidAlgorithmParameterException iape) { + // should never happen + throw new RuntimeException("Internal cipher IV is invalid"); } byte[] out2 = new byte[out.length]; cipher.encrypt(out, 0, out.length, out2, 0); @@ -481,6 +484,9 @@ protected byte[] engineWrap(Key key) } catch (InvalidKeyException ike) { // should never happen throw new RuntimeException("Internal cipher key is corrupted"); + } catch (InvalidAlgorithmParameterException iape) { + // should never happen + throw new RuntimeException("Internal cipher IV is invalid"); } return out2; } @@ -524,8 +530,12 @@ protected Key engineUnwrap(byte[] wrappedKey, } iv = new byte[IV_LEN]; System.arraycopy(buffer, 0, iv, 0, iv.length); - cipher.init(true, cipherKey.getAlgorithm(), cipherKey.getEncoded(), + try { + cipher.init(true, cipherKey.getAlgorithm(), cipherKey.getEncoded(), iv); + } catch (InvalidAlgorithmParameterException iape) { + throw new InvalidKeyException("IV in wrapped key is invalid"); + } byte[] buffer2 = new byte[buffer.length - iv.length]; cipher.decrypt(buffer, iv.length, buffer2.length, buffer2, 0); @@ -538,8 +548,12 @@ protected Key engineUnwrap(byte[] wrappedKey, } } // restore cipher state to prior to this call - cipher.init(decrypting, cipherKey.getAlgorithm(), + try { + cipher.init(decrypting, cipherKey.getAlgorithm(), cipherKey.getEncoded(), IV2); + } catch (InvalidAlgorithmParameterException iape) { + throw new InvalidKeyException("IV in wrapped key is invalid"); + } byte[] out = new byte[keyValLen]; System.arraycopy(buffer2, 0, out, 0, keyValLen); return ConstructKeys.constructKey(out, wrappedKeyAlgorithm, diff --git a/src/java.base/share/classes/com/sun/crypto/provider/FeedbackCipher.java b/src/java.base/share/classes/com/sun/crypto/provider/FeedbackCipher.java index 8d03913e284..b21f96227a4 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/FeedbackCipher.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/FeedbackCipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package com.sun.crypto.provider; import java.security.InvalidKeyException; +import java.security.InvalidAlgorithmParameterException; import javax.crypto.*; /** @@ -99,7 +100,8 @@ final int getBlockSize() { * initializing this cipher */ abstract void init(boolean decrypting, String algorithm, byte[] key, - byte[] iv) throws InvalidKeyException; + byte[] iv) throws InvalidKeyException, + InvalidAlgorithmParameterException; /** * Gets the initialization vector. diff --git a/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java b/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java index 7dd9791f1b1..6ea2b3a66eb 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, 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 @@ -262,8 +262,9 @@ void restore() { * @exception InvalidKeyException if the given key is inappropriate for * initializing this cipher */ + @Override void init(boolean decrypting, String algorithm, byte[] key, byte[] iv) - throws InvalidKeyException { + throws InvalidKeyException, InvalidAlgorithmParameterException { init(decrypting, algorithm, key, iv, DEFAULT_TAG_LEN); } @@ -282,10 +283,16 @@ void init(boolean decrypting, String algorithm, byte[] key, byte[] iv) */ void init(boolean decrypting, String algorithm, byte[] keyValue, byte[] ivValue, int tagLenBytes) - throws InvalidKeyException { - if (keyValue == null || ivValue == null) { + throws InvalidKeyException, InvalidAlgorithmParameterException { + if (keyValue == null) { throw new InvalidKeyException("Internal error"); } + if (ivValue == null) { + throw new InvalidAlgorithmParameterException("Internal error"); + } + if (ivValue.length == 0) { + throw new InvalidAlgorithmParameterException("IV is empty"); + } // always encrypt mode for embedded cipher this.embeddedCipher.init(false, algorithm, keyValue); diff --git a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeGCMCipher.java b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeGCMCipher.java index 0d5b4325b99..6fa8ef34f2a 100644 --- a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeGCMCipher.java +++ b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeGCMCipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, 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 @@ -246,7 +246,17 @@ protected synchronized void engineInit(int opmode, Key key, requireReinit = false; ibuffer = new ByteArrayOutputStream(); } - init(doEncrypt, keyBytes, ivBytes, tagLen, null); + try { + init(doEncrypt, keyBytes, ivBytes, tagLen, null); + } catch (UcryptoException ex) { + if (ex.getError() == + UcryptoException.Error.CRYPTO_MECHANISM_PARAM_INVALID) { + + throw new InvalidAlgorithmParameterException(ex.getMessage()); + } else { + throw ex; + } + } } // see JCE spec diff --git a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoException.java b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoException.java index 0ba6c198ed3..4c1e98e1f4d 100644 --- a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoException.java +++ b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, 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,93 +40,105 @@ public final class UcryptoException extends ProviderException { private static final long serialVersionUID = -933864511110035746L; // NOTE: check /usr/include/sys/crypto/common.h for updates - private static final String[] ERROR_MSG = { - "CRYPTO_SUCCESS", - "CRYPTO_CANCEL", - "CRYPTO_HOST_MEMORY", - "CRYPTO_GENERAL_ERROR", - "CRYPTO_FAILED", - "CRYPTO_ARGUMENTS_BAD", - "CRYPTO_ATTRIBUTE_READ_ONLY", - "CRYPTO_ATTRIBUTE_SENSITIVE", - "CRYPTO_ATTRIBUTE_TYPE_INVALID", - "CRYPTO_ATTRIBUTE_VALUE_INVALID", - "CRYPTO_CANCELED", - "CRYPTO_DATA_INVALID", - "CRYPTO_DATA_LEN_RANGE", - "CRYPTO_DEVICE_ERROR", - "CRYPTO_DEVICE_MEMORY", - "CRYPTO_DEVICE_REMOVED", - "CRYPTO_ENCRYPTED_DATA_INVALID", - "CRYPTO_ENCRYPTED_DATA_LEN_RANGE", - "CRYPTO_KEY_HANDLE_INVALID", - "CRYPTO_KEY_SIZE_RANGE", - "CRYPTO_KEY_TYPE_INCONSISTENT", - "CRYPTO_KEY_NOT_NEEDED", - "CRYPTO_KEY_CHANGED", - "CRYPTO_KEY_NEEDED", - "CRYPTO_KEY_INDIGESTIBLE", - "CRYPTO_KEY_FUNCTION_NOT_PERMITTED", - "CRYPTO_KEY_NOT_WRAPPABLE", - "CRYPTO_KEY_UNEXTRACTABLE", - "CRYPTO_MECHANISM_INVALID", - "CRYPTO_MECHANISM_PARAM_INVALID", - "CRYPTO_OBJECT_HANDLE_INVALID", - "CRYPTO_OPERATION_IS_ACTIVE", - "CRYPTO_OPERATION_NOT_INITIALIZED", - "CRYPTO_PIN_INCORRECT", - "CRYPTO_PIN_INVALID", - "CRYPTO_PIN_LEN_RANGE", - "CRYPTO_PIN_EXPIRED", - "CRYPTO_PIN_LOCKED", - "CRYPTO_SESSION_CLOSED", - "CRYPTO_SESSION_COUNT", - "CRYPTO_SESSION_HANDLE_INVALID", - "CRYPTO_SESSION_READ_ONLY", - "CRYPTO_SESSION_EXISTS", - "CRYPTO_SESSION_READ_ONLY_EXISTS", - "CRYPTO_SESSION_READ_WRITE_SO_EXISTS", - "CRYPTO_SIGNATURE_INVALID", - "CRYPTO_SIGNATURE_LEN_RANGE", - "CRYPTO_TEMPLATE_INCOMPLETE", - "CRYPTO_TEMPLATE_INCONSISTENT", - "CRYPTO_UNWRAPPING_KEY_HANDLE_INVALID", - "CRYPTO_UNWRAPPING_KEY_SIZE_RANGE", - "CRYPTO_UNWRAPPING_KEY_TYPE_INCONSISTENT", - "CRYPTO_USER_ALREADY_LOGGED_IN", - "CRYPTO_USER_NOT_LOGGED_IN", - "CRYPTO_USER_PIN_NOT_INITIALIZED", - "CRYPTO_USER_TYPE_INVALID", - "CRYPTO_USER_ANOTHER_ALREADY_LOGGED_IN", - "CRYPTO_USER_TOO_MANY_TYPES", - "CRYPTO_WRAPPED_KEY_INVALID", - "CRYPTO_WRAPPED_KEY_LEN_RANGE", - "CRYPTO_WRAPPING_KEY_HANDLE_INVALID", - "CRYPTO_WRAPPING_KEY_SIZE_RANGE", - "CRYPTO_WRAPPING_KEY_TYPE_INCONSISTENT", - "CRYPTO_RANDOM_SEED_NOT_SUPPORTED", - "CRYPTO_RANDOM_NO_RNG", - "CRYPTO_DOMAIN_PARAMS_INVALID", - "CRYPTO_BUFFER_TOO_SMALL", - "CRYPTO_INFORMATION_SENSITIVE", - "CRYPTO_NOT_SUPPORTED", - "CRYPTO_QUEUED", - "CRYPTO_BUFFER_TOO_BIG", - "CRYPTO_INVALID_CONTEXT", - "CRYPTO_INVALID_MAC", - "CRYPTO_MECH_NOT_SUPPORTED", - "CRYPTO_INCONSISTENT_ATTRIBUTE", - "CRYPTO_NO_PERMISSION", - "CRYPTO_INVALID_PROVIDER_ID", - "CRYPTO_VERSION_MISMATCH", - "CRYPTO_BUSY", - "CRYPTO_UNKNOWN_PROVIDER", - "CRYPTO_MODVERIFICATION_FAILED", - "CRYPTO_OLD_CTX_TEMPLATE", - "CRYPTO_WEAK_KEY", - "CRYPTO_FIPS140_ERROR" + public enum Error { + CRYPTO_SUCCESS, + CRYPTO_CANCEL, + CRYPTO_HOST_MEMORY, + CRYPTO_GENERAL_ERROR, + CRYPTO_FAILED, + CRYPTO_ARGUMENTS_BAD, + CRYPTO_ATTRIBUTE_READ_ONLY, + CRYPTO_ATTRIBUTE_SENSITIVE, + CRYPTO_ATTRIBUTE_TYPE_INVALID, + CRYPTO_ATTRIBUTE_VALUE_INVALID, + CRYPTO_CANCELED, + CRYPTO_DATA_INVALID, + CRYPTO_DATA_LEN_RANGE, + CRYPTO_DEVICE_ERROR, + CRYPTO_DEVICE_MEMORY, + CRYPTO_DEVICE_REMOVED, + CRYPTO_ENCRYPTED_DATA_INVALID, + CRYPTO_ENCRYPTED_DATA_LEN_RANGE, + CRYPTO_KEY_HANDLE_INVALID, + CRYPTO_KEY_SIZE_RANGE, + CRYPTO_KEY_TYPE_INCONSISTENT, + CRYPTO_KEY_NOT_NEEDED, + CRYPTO_KEY_CHANGED, + CRYPTO_KEY_NEEDED, + CRYPTO_KEY_INDIGESTIBLE, + CRYPTO_KEY_FUNCTION_NOT_PERMITTED, + CRYPTO_KEY_NOT_WRAPPABLE, + CRYPTO_KEY_UNEXTRACTABLE, + CRYPTO_MECHANISM_INVALID, + CRYPTO_MECHANISM_PARAM_INVALID, + CRYPTO_OBJECT_HANDLE_INVALID, + CRYPTO_OPERATION_IS_ACTIVE, + CRYPTO_OPERATION_NOT_INITIALIZED, + CRYPTO_PIN_INCORRECT, + CRYPTO_PIN_INVALID, + CRYPTO_PIN_LEN_RANGE, + CRYPTO_PIN_EXPIRED, + CRYPTO_PIN_LOCKED, + CRYPTO_SESSION_CLOSED, + CRYPTO_SESSION_COUNT, + CRYPTO_SESSION_HANDLE_INVALID, + CRYPTO_SESSION_READ_ONLY, + CRYPTO_SESSION_EXISTS, + CRYPTO_SESSION_READ_ONLY_EXISTS, + CRYPTO_SESSION_READ_WRITE_SO_EXISTS, + CRYPTO_SIGNATURE_INVALID, + CRYPTO_SIGNATURE_LEN_RANGE, + CRYPTO_TEMPLATE_INCOMPLETE, + CRYPTO_TEMPLATE_INCONSISTENT, + CRYPTO_UNWRAPPING_KEY_HANDLE_INVALID, + CRYPTO_UNWRAPPING_KEY_SIZE_RANGE, + CRYPTO_UNWRAPPING_KEY_TYPE_INCONSISTENT, + CRYPTO_USER_ALREADY_LOGGED_IN, + CRYPTO_USER_NOT_LOGGED_IN, + CRYPTO_USER_PIN_NOT_INITIALIZED, + CRYPTO_USER_TYPE_INVALID, + CRYPTO_USER_ANOTHER_ALREADY_LOGGED_IN, + CRYPTO_USER_TOO_MANY_TYPES, + CRYPTO_WRAPPED_KEY_INVALID, + CRYPTO_WRAPPED_KEY_LEN_RANGE, + CRYPTO_WRAPPING_KEY_HANDLE_INVALID, + CRYPTO_WRAPPING_KEY_SIZE_RANGE, + CRYPTO_WRAPPING_KEY_TYPE_INCONSISTENT, + CRYPTO_RANDOM_SEED_NOT_SUPPORTED, + CRYPTO_RANDOM_NO_RNG, + CRYPTO_DOMAIN_PARAMS_INVALID, + CRYPTO_BUFFER_TOO_SMALL, + CRYPTO_INFORMATION_SENSITIVE, + CRYPTO_NOT_SUPPORTED, + CRYPTO_QUEUED, + CRYPTO_BUFFER_TOO_BIG, + CRYPTO_INVALID_CONTEXT, + CRYPTO_INVALID_MAC, + CRYPTO_MECH_NOT_SUPPORTED, + CRYPTO_INCONSISTENT_ATTRIBUTE, + CRYPTO_NO_PERMISSION, + CRYPTO_INVALID_PROVIDER_ID, + CRYPTO_VERSION_MISMATCH, + CRYPTO_BUSY, + CRYPTO_UNKNOWN_PROVIDER, + CRYPTO_MODVERIFICATION_FAILED, + CRYPTO_OLD_CTX_TEMPLATE, + CRYPTO_WEAK_KEY, + CRYPTO_FIPS140_ERROR; }; + // Array used to look up error by ordinal + private static final Error[] ALL_ERRORS = Error.values(); + + /** + * Get the error enum value (if any) associated with this exception. + */ + public Error getError() { + return errorCode < ALL_ERRORS.length ? + ALL_ERRORS[errorCode] : + null; + } + /** * The error code if this exception is triggered by a Ucrypto error. */ @@ -142,8 +154,8 @@ public final class UcryptoException extends ProviderException { */ static String getErrorMessage(int errorCode) { String message; - if (errorCode < ERROR_MSG.length) { - message = ERROR_MSG[errorCode]; + if (errorCode < ALL_ERRORS.length) { + message = ALL_ERRORS[errorCode].name(); } else { message = "0x" + Integer.toHexString(errorCode); } From 07bf504b87c407cbf74b31f692644b298dcaaabf Mon Sep 17 00:00:00 2001 From: psandoz Date: Wed, 24 Jan 2018 16:44:31 -0800 Subject: [PATCH 017/196] 8194238: Trying exceptions in MethodHandles Reviewed-by: jrose, vlivanov, ahgross --- .../java/lang/invoke/MethodHandles.java | 18 +++++++++- test/jdk/java/lang/invoke/TryFinallyTest.java | 34 +++++++++++++++++-- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index e0d078dcc1f..0277a8e24e2 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -5893,6 +5893,19 @@ private static Class iteratedLoopChecks(MethodHandle iterator, MethodHandle i * In rare cases where exceptions must be converted in that way, first wrap * the target with {@link #catchException(MethodHandle, Class, MethodHandle)} * to capture an outgoing exception, and then wrap with {@code tryFinally}. + *

+ * It is recommended that the first parameter type of {@code cleanup} be + * declared {@code Throwable} rather than a narrower subtype. This ensures + * {@code cleanup} will always be invoked with whatever exception that + * {@code target} throws. Declaring a narrower type may result in a + * {@code ClassCastException} being thrown by the {@code try-finally} + * handle if the type of the exception thrown by {@code target} is not + * assignable to the first parameter type of {@code cleanup}. Note that + * various exception types of {@code VirtualMachineError}, + * {@code LinkageError}, and {@code RuntimeException} can in principle be + * thrown by almost any kind of Java code, and a finally clause that + * catches (say) only {@code IOException} would mask any of the others + * behind a {@code ClassCastException}. * * @param target the handle whose execution is to be wrapped in a {@code try} block. * @param cleanup the handle that is invoked in the finally block. @@ -5909,7 +5922,6 @@ private static Class iteratedLoopChecks(MethodHandle iterator, MethodHandle i */ public static MethodHandle tryFinally(MethodHandle target, MethodHandle cleanup) { List> targetParamTypes = target.type().parameterList(); - List> cleanupParamTypes = cleanup.type().parameterList(); Class rtype = target.type().returnType(); tryFinallyChecks(target, cleanup); @@ -5919,6 +5931,10 @@ public static MethodHandle tryFinally(MethodHandle target, MethodHandle cleanup) // target parameter list. cleanup = dropArgumentsToMatch(cleanup, (rtype == void.class ? 1 : 2), targetParamTypes, 0); + // Ensure that the intrinsic type checks the instance thrown by the + // target against the first parameter of cleanup + cleanup = cleanup.asType(cleanup.type().changeParameterType(0, Throwable.class)); + // Use asFixedArity() to avoid unnecessary boxing of last argument for VarargsCollector case. return MethodHandleImpl.makeTryFinally(target.asFixedArity(), cleanup.asFixedArity(), rtype, targetParamTypes); } diff --git a/test/jdk/java/lang/invoke/TryFinallyTest.java b/test/jdk/java/lang/invoke/TryFinallyTest.java index abf79f38703..5e66360eedf 100644 --- a/test/jdk/java/lang/invoke/TryFinallyTest.java +++ b/test/jdk/java/lang/invoke/TryFinallyTest.java @@ -24,9 +24,7 @@ */ /* @test - * @bug 8139885 - * @bug 8150824 - * @bug 8150825 + * @bug 8139885 8150824 8150825 8194238 * @run testng/othervm -ea -esa test.java.lang.invoke.TryFinallyTest */ @@ -126,6 +124,19 @@ public static void testTryFinallyNegative(MethodHandle target, MethodHandle clea assertTrue(caught); } + @Test + public static void testTryFinallyThrowableCheck() { + MethodHandle mh = MethodHandles.tryFinally(TryFinally.MH_throwingTarget, + TryFinally.MH_catchingCleanup); + try { + mh.invoke(); + fail("ClassCastException expected"); + } catch (Throwable t) { + assertTrue("Throwable not assignable to ClassCastException: " + t, + ClassCastException.class.isAssignableFrom(t.getClass())); + } + } + static class TryFinally { static String greet(String whom) { @@ -156,6 +167,17 @@ static void voidTarget() {} static void voidCleanup(Throwable t) {} + static class T1 extends Throwable {} + + static class T2 extends Throwable {} + + static void throwingTarget() throws Throwable { + throw new T1(); + } + + static void catchingCleanup(T2 t) throws Throwable { + } + static final Class TRY_FINALLY = TryFinally.class; static final MethodType MT_greet = methodType(String.class, String.class); @@ -166,6 +188,8 @@ static void voidCleanup(Throwable t) {} static final MethodType MT_exclaimMore = methodType(String.class, Throwable.class, String.class, String.class); static final MethodType MT_voidTarget = methodType(void.class); static final MethodType MT_voidCleanup = methodType(void.class, Throwable.class); + static final MethodType MT_throwingTarget = methodType(void.class); + static final MethodType MT_catchingCleanup = methodType(void.class, T2.class); static final MethodHandle MH_greet; static final MethodHandle MH_exclaim; @@ -175,6 +199,8 @@ static void voidCleanup(Throwable t) {} static final MethodHandle MH_exclaimMore; static final MethodHandle MH_voidTarget; static final MethodHandle MH_voidCleanup; + static final MethodHandle MH_throwingTarget; + static final MethodHandle MH_catchingCleanup; static final MethodHandle MH_dummyTarget; @@ -192,6 +218,8 @@ static void voidCleanup(Throwable t) {} MH_exclaimMore = LOOKUP.findStatic(TRY_FINALLY, "exclaimMore", MT_exclaimMore); MH_voidTarget = LOOKUP.findStatic(TRY_FINALLY, "voidTarget", MT_voidTarget); MH_voidCleanup = LOOKUP.findStatic(TRY_FINALLY, "voidCleanup", MT_voidCleanup); + MH_throwingTarget = LOOKUP.findStatic(TRY_FINALLY, "throwingTarget", MT_throwingTarget); + MH_catchingCleanup = LOOKUP.findStatic(TRY_FINALLY, "catchingCleanup", MT_catchingCleanup); MH_dummyTarget = MethodHandles.dropArguments(MH_voidTarget, 0, int.class, long.class, Object.class, int.class, long.class, Object.class); } catch (Exception e) { From b6d40e7837f48c68b65ef033b71bd45f60ef11e6 Mon Sep 17 00:00:00 2001 From: prr Date: Fri, 26 Jan 2018 12:01:08 -0800 Subject: [PATCH 018/196] 8196289: Update src/java.desktop/share/legal/lcms.md for LCMS 2.9 Reviewed-by: mchung --- src/java.desktop/share/legal/lcms.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.desktop/share/legal/lcms.md b/src/java.desktop/share/legal/lcms.md index d74475540d5..a8a06325cd0 100644 --- a/src/java.desktop/share/legal/lcms.md +++ b/src/java.desktop/share/legal/lcms.md @@ -1,10 +1,10 @@ -## Little Color Management System (LCMS) v2.8 +## Little Color Management System (LCMS) v2.9 ### LCMS License

 
 Little Color Management System
-Copyright (c) 1998-2016 Marti Maria Saguer
+Copyright (c) 1998-2011 Marti Maria Saguer
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the "Software"),

From ca32703592a1d03290aeff6d51854b27bcc396ea Mon Sep 17 00:00:00 2001
From: smarks 
Date: Fri, 2 Feb 2018 10:56:12 -0800
Subject: [PATCH 019/196] 8189981: Improve queuing portability Reviewed-by:
 skoivu, rhalade, chegar, igerasim

---
 .../classes/java/util/concurrent/PriorityBlockingQueue.java  | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java b/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java
index 8a362274749..7b19c13bb0d 100644
--- a/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java
+++ b/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java
@@ -51,6 +51,7 @@
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.function.Consumer;
+import jdk.internal.misc.SharedSecrets;
 
 /**
  * An unbounded {@linkplain BlockingQueue blocking queue} that uses
@@ -921,7 +922,9 @@ private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
         try {
             s.defaultReadObject();
-            this.queue = new Object[q.size()];
+            int sz = q.size();
+            SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, sz);
+            this.queue = new Object[sz];
             comparator = q.comparator();
             addAll(q);
         } finally {

From d81fd882b90d5294475a68d15f8dea70aa4fc8f2 Mon Sep 17 00:00:00 2001
From: apetcher 
Date: Mon, 12 Feb 2018 11:38:35 -0500
Subject: [PATCH 020/196] 8197443: ArrayIndexOutOfBoundsException in
 UcryptoException.getError Reviewed-by: mullan

---
 .../classes/com/oracle/security/ucrypto/UcryptoException.java | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoException.java b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoException.java
index 4c1e98e1f4d..34dbe8ae5bb 100644
--- a/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoException.java
+++ b/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoException.java
@@ -134,7 +134,7 @@ public enum Error {
      * Get the error enum value (if any) associated with this exception.
      */
     public Error getError() {
-        return errorCode < ALL_ERRORS.length ?
+        return (errorCode >= 0 && errorCode < ALL_ERRORS.length) ?
             ALL_ERRORS[errorCode] :
             null;
     }
@@ -154,7 +154,7 @@ public Error getError() {
      */
     static String getErrorMessage(int errorCode) {
         String message;
-        if (errorCode < ALL_ERRORS.length) {
+        if (errorCode >= 0 && errorCode < ALL_ERRORS.length) {
             message = ALL_ERRORS[errorCode].name();
         } else {
             message = "0x" + Integer.toHexString(errorCode);

From 236fdea8ae5c0dd4246519b437e7371926ccda30 Mon Sep 17 00:00:00 2001
From: asapre 
Date: Wed, 14 Feb 2018 15:36:59 +0530
Subject: [PATCH 021/196] 8189985: Improve tabular data portability
 Reviewed-by: dfuchs, mchung, skoivu

---
 .../javax/management/openmbean/TabularDataSupport.java     | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/java.management/share/classes/javax/management/openmbean/TabularDataSupport.java b/src/java.management/share/classes/javax/management/openmbean/TabularDataSupport.java
index bcbd176266e..c46e0edfd83 100644
--- a/src/java.management/share/classes/javax/management/openmbean/TabularDataSupport.java
+++ b/src/java.management/share/classes/javax/management/openmbean/TabularDataSupport.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, 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
@@ -45,6 +45,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import jdk.internal.misc.SharedSecrets;
 
 // jmx import
 //
@@ -922,6 +923,8 @@ private void readObject(ObjectInputStream in)
             throws IOException, ClassNotFoundException {
       in.defaultReadObject();
       List tmpNames = tabularType.getIndexNames();
-      indexNamesArray = tmpNames.toArray(new String[tmpNames.size()]);
+      int size = tmpNames.size();
+      SharedSecrets.getJavaObjectInputStreamAccess().checkArray(in, String[].class, size);
+      indexNamesArray = tmpNames.toArray(new String[size]);
     }
 }

From 63b4f04aa603ca763909f582edb08243ff26e227 Mon Sep 17 00:00:00 2001
From: cjplummer 
Date: Sat, 24 Mar 2018 13:39:07 -0700
Subject: [PATCH 022/196] 8198655: test/lib/jdk/test/lib/apps/LingeredApp
 shouldn't inherit cout/cerr Summary: no longer force stderr to console. Copy
 app's output to Sytem.err. Reviewed-by: sspitsyn, dholmes, iignatyev, clanger

---
 .../jtreg/serviceability/sa/ClhsdbSymbol.java |   4 +-
 test/lib/jdk/test/lib/apps/LingeredApp.java   | 128 ++++++++++--------
 2 files changed, 76 insertions(+), 56 deletions(-)

diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbSymbol.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbSymbol.java
index e03610e0e89..6435e5d0eb7 100644
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbSymbol.java
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbSymbol.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -55,7 +55,7 @@ public static void main(String[] args) throws Exception {
                     "Ljava/io/InputStream", "LambdaMetafactory", "PerfCounter",
                     "isAnonymousClass", "JVMTI_THREAD_STATE_TERMINATED", "jdi",
                     "checkGetClassLoaderPermission", "lockCreationTime",
-                    "storedAppOutput", "storedAppOutput", "getProcess",
+                    "stderrBuffer", "stdoutBuffer", "getProcess",
                     "LingeredApp"));
 
             test.run(theApp.getPid(), cmds, expStrMap, null);
diff --git a/test/lib/jdk/test/lib/apps/LingeredApp.java b/test/lib/jdk/test/lib/apps/LingeredApp.java
index 22a123ccbb5..7bff8b5c60f 100644
--- a/test/lib/jdk/test/lib/apps/LingeredApp.java
+++ b/test/lib/jdk/test/lib/apps/LingeredApp.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,9 +24,12 @@
 package jdk.test.lib.apps;
 
 import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.StringReader;
 import java.nio.file.Files;
 import java.nio.file.NoSuchFileException;
 import java.nio.file.Path;
@@ -37,7 +40,11 @@
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 import java.util.UUID;
+import jdk.test.lib.process.OutputBuffer;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.StreamPumper;
 
 /**
  * This is a framework to launch an app that could be synchronized with caller
@@ -69,39 +76,16 @@ public class LingeredApp {
     private static final long spinDelay = 1000;
 
     private long lockCreationTime;
-    private final ArrayList storedAppOutput;
+    private ByteArrayOutputStream stderrBuffer;
+    private ByteArrayOutputStream stdoutBuffer;
+    private Thread outPumperThread;
+    private Thread errPumperThread;
 
     protected Process appProcess;
+    protected OutputBuffer output;
     protected static final int appWaitTime = 100;
     protected final String lockFileName;
 
-    /*
-     * Drain child process output, store it into string array
-     */
-    class InputGobbler extends Thread {
-
-        InputStream is;
-        List astr;
-
-        InputGobbler(InputStream is, List astr) {
-            this.is = is;
-            this.astr = astr;
-        }
-
-        public void run() {
-            try {
-                InputStreamReader isr = new InputStreamReader(is);
-                BufferedReader br = new BufferedReader(isr);
-                String line = null;
-                while ((line = br.readLine()) != null) {
-                    astr.add(line);
-                }
-            } catch (IOException ex) {
-                // pass
-            }
-        }
-    }
-
     /**
      * Create LingeredApp object on caller side. Lock file have be a valid filename
      * at writable location
@@ -110,13 +94,11 @@ public void run() {
      */
     public LingeredApp(String lockFileName) {
         this.lockFileName = lockFileName;
-        this.storedAppOutput = new ArrayList();
     }
 
     public LingeredApp() {
         final String lockName = UUID.randomUUID().toString() + ".lck";
         this.lockFileName = lockName;
-        this.storedAppOutput = new ArrayList();
     }
 
     /**
@@ -156,13 +138,48 @@ public Process getProcess() {
 
     /**
      *
-     * @return application output as string array. Empty array if application produced no output
+     * @return OutputBuffer object for the LingeredApp's output. Can only be called
+     * after LingeredApp has exited.
+     */
+    public OutputBuffer getOutput() {
+        if (appProcess.isAlive()) {
+            throw new RuntimeException("Process is still alive. Can't get its output.");
+        }
+        if (output == null) {
+            output = new OutputBuffer(stdoutBuffer.toString(), stderrBuffer.toString());
+        }
+        return output;
+    }
+
+    /*
+     * Capture all stdout and stderr output from the LingeredApp so it can be returned
+     * to the driver app later. This code is modeled after ProcessTools.getOutput().
+     */
+    private void startOutputPumpers() {
+        stderrBuffer = new ByteArrayOutputStream();
+        stdoutBuffer = new ByteArrayOutputStream();
+        StreamPumper outPumper = new StreamPumper(appProcess.getInputStream(), stdoutBuffer);
+        StreamPumper errPumper = new StreamPumper(appProcess.getErrorStream(), stderrBuffer);
+        outPumperThread = new Thread(outPumper);
+        errPumperThread = new Thread(errPumper);
+
+        outPumperThread.setDaemon(true);
+        errPumperThread.setDaemon(true);
+
+        outPumperThread.start();
+        errPumperThread.start();
+    }
+
+    /**
+     *
+     * @return application output as List. Empty List if application produced no output
      */
     public List getAppOutput() {
         if (appProcess.isAlive()) {
             throw new RuntimeException("Process is still alive. Can't get its output.");
         }
-        return storedAppOutput;
+        BufferedReader bufReader = new BufferedReader(new StringReader(output.getStdout()));
+        return bufReader.lines().collect(Collectors.toList());
     }
 
     /* Make sure all part of the app use the same method to get dates,
@@ -211,13 +228,14 @@ public void deleteLock() throws IOException {
     }
 
     public void waitAppTerminate() {
-        while (true) {
-            try {
-                appProcess.waitFor();
-                break;
-            } catch (InterruptedException ex) {
-                // pass
-            }
+        // This code is modeled after tail end of ProcessTools.getOutput().
+        try {
+            appProcess.waitFor();
+            outPumperThread.join();
+            errPumperThread.join();
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            // pass
         }
     }
 
@@ -280,7 +298,6 @@ public List runAppPrepare(List vmArguments) {
         List cmd = new ArrayList();
         cmd.add(javapath);
 
-
         if (vmArguments == null) {
             // Propagate test.vm.options to LingeredApp, filter out possible empty options
             String testVmOpts[] = System.getProperty("test.vm.opts","").split("\\s+");
@@ -289,8 +306,7 @@ public List runAppPrepare(List vmArguments) {
                     cmd.add(s);
                 }
             }
-        }
-        else{
+        } else {
             // Lets user manage LingeredApp options
             cmd.addAll(vmArguments);
         }
@@ -313,13 +329,7 @@ public void printCommandLine(List cmd) {
             cmdLine.append("'").append(strCmd).append("' ");
         }
 
-        System.out.println("Command line: [" + cmdLine.toString() + "]");
-    }
-
-    public void startGobblerPipe() {
-      // Create pipe reader for process, and read stdin and stderr to array of strings
-      InputGobbler gb = new InputGobbler(appProcess.getInputStream(), storedAppOutput);
-      gb.start();
+        System.err.println("Command line: [" + cmdLine.toString() + "]");
     }
 
     /**
@@ -339,13 +349,20 @@ public void runApp(List vmArguments)
         printCommandLine(cmd);
 
         ProcessBuilder pb = new ProcessBuilder(cmd);
-        // we don't expect any error output but make sure we are not stuck on pipe
-        // pb.redirectErrorStream(false);
         // ProcessBuilder.start can throw IOException
-        pb.redirectError(ProcessBuilder.Redirect.INHERIT);
         appProcess = pb.start();
 
-        startGobblerPipe();
+        startOutputPumpers();
+    }
+
+    private void finishApp() {
+        OutputBuffer output = getOutput();
+        String msg =
+            " LingeredApp stdout: [" + output.getStdout() + "];\n" +
+            " LingeredApp stderr: [" + output.getStderr() + "]\n" +
+            " LingeredApp exitValue = " + appProcess.exitValue();
+
+        System.err.println(msg);
     }
 
     /**
@@ -364,6 +381,7 @@ public void stopApp() throws IOException {
                 throw new IOException("LingeredApp terminated with non-zero exit code " + exitcode);
             }
         }
+        finishApp();
     }
 
     /**
@@ -384,6 +402,8 @@ public static LingeredApp startApp(List cmd) throws IOException {
             a.waitAppReady(appWaitTime);
         } catch (Exception ex) {
             a.deleteLock();
+            System.err.println("LingeredApp failed to start: " + ex);
+            a.finishApp();
             throw ex;
         }
 

From e9c10043078c405eaec2dee1a67b032f55f43ecd Mon Sep 17 00:00:00 2001
From: glaubitz 
Date: Mon, 26 Mar 2018 10:03:31 +0200
Subject: [PATCH 023/196] 8200203: Missing platform definitions for ia64
 Reviewed-by: ihse, stuefe

---
 make/autoconf/platform.m4 | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/make/autoconf/platform.m4 b/make/autoconf/platform.m4
index 9de0f01d789..a6a1ba1a36a 100644
--- a/make/autoconf/platform.m4
+++ b/make/autoconf/platform.m4
@@ -60,6 +60,12 @@ AC_DEFUN([PLATFORM_EXTRACT_VARS_FROM_CPU],
       VAR_CPU_BITS=64
       VAR_CPU_ENDIAN=little
       ;;
+    ia64)
+      VAR_CPU=ia64
+      VAR_CPU_ARCH=ia64
+      VAR_CPU_BITS=64
+      VAR_CPU_ENDIAN=little
+      ;;
     m68k)
       VAR_CPU=m68k
       VAR_CPU_ARCH=m68k

From fab4977150a38dfbdb9ff46051315627ec8a63f4 Mon Sep 17 00:00:00 2001
From: pliden 
Date: Mon, 26 Mar 2018 12:44:39 +0200
Subject: [PATCH 024/196] 8199850: Move parsing of VerifyGCType to G1
 Reviewed-by: sjohanss, tschatzl

---
 .../gtest/gc/g1/test_g1HeapVerifier.cpp       | 65 +++++++++----------
 .../hotspot/jtreg/gc/g1/TestVerifyGCType.java | 22 +------
 2 files changed, 33 insertions(+), 54 deletions(-)

diff --git a/test/hotspot/gtest/gc/g1/test_g1HeapVerifier.cpp b/test/hotspot/gtest/gc/g1/test_g1HeapVerifier.cpp
index 76a5e235344..9e44321b1a9 100644
--- a/test/hotspot/gtest/gc/g1/test_g1HeapVerifier.cpp
+++ b/test/hotspot/gtest/gc/g1/test_g1HeapVerifier.cpp
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/g1/g1Arguments.hpp"
 #include "gc/g1/g1HeapVerifier.hpp"
 #include "logging/logConfiguration.hpp"
 #include "logging/logTestFixture.hpp"
@@ -32,50 +33,48 @@ class G1HeapVerifierTest : public LogTestFixture {
 };
 
 TEST_F(G1HeapVerifierTest, parse) {
-  G1HeapVerifier verifier(NULL);
-
   LogConfiguration::configure_stdout(LogLevel::Off, true, LOG_TAGS(gc, verify));
 
   // Default is to verify everything.
-  ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyAll));
-  ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyYoungOnly));
-  ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyInitialMark));
-  ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyMixed));
-  ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyRemark));
-  ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyCleanup));
-  ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyFull));
+  ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyAll));
+  ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyYoungOnly));
+  ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyInitialMark));
+  ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyMixed));
+  ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyRemark));
+  ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyCleanup));
+  ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyFull));
 
   // Setting one will disable all other.
-  verifier.parse_verification_type("full");
-  ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyAll));
-  ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyYoungOnly));
-  ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyInitialMark));
-  ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyMixed));
-  ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyRemark));
-  ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyCleanup));
-  ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyFull));
+  G1Arguments::parse_verification_type("full");
+  ASSERT_FALSE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyAll));
+  ASSERT_FALSE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyYoungOnly));
+  ASSERT_FALSE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyInitialMark));
+  ASSERT_FALSE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyMixed));
+  ASSERT_FALSE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyRemark));
+  ASSERT_FALSE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyCleanup));
+  ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyFull));
 
   // Verify case sensitivity.
-  verifier.parse_verification_type("YOUNG-ONLY");
-  ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyYoungOnly));
-  verifier.parse_verification_type("young-only");
-  ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyYoungOnly));
+  G1Arguments::parse_verification_type("YOUNG-ONLY");
+  ASSERT_FALSE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyYoungOnly));
+  G1Arguments::parse_verification_type("young-only");
+  ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyYoungOnly));
 
   // Verify perfect match
-  verifier.parse_verification_type("mixedgc");
-  ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyMixed));
-  verifier.parse_verification_type("mixe");
-  ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyMixed));
-  verifier.parse_verification_type("mixed");
-  ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyMixed));
+  G1Arguments::parse_verification_type("mixedgc");
+  ASSERT_FALSE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyMixed));
+  G1Arguments::parse_verification_type("mixe");
+  ASSERT_FALSE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyMixed));
+  G1Arguments::parse_verification_type("mixed");
+  ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyMixed));
 
   // Verify the last three
-  verifier.parse_verification_type("initial-mark");
-  verifier.parse_verification_type("remark");
-  verifier.parse_verification_type("cleanup");
-  ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyRemark));
-  ASSERT_TRUE(verifier.should_verify(G1HeapVerifier::G1VerifyCleanup));
+  G1Arguments::parse_verification_type("initial-mark");
+  G1Arguments::parse_verification_type("remark");
+  G1Arguments::parse_verification_type("cleanup");
+  ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyRemark));
+  ASSERT_TRUE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyCleanup));
 
   // Enabling all is not the same as G1VerifyAll
-  ASSERT_FALSE(verifier.should_verify(G1HeapVerifier::G1VerifyAll));
+  ASSERT_FALSE(G1HeapVerifier::should_verify(G1HeapVerifier::G1VerifyAll));
 }
diff --git a/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java b/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java
index c227be9f54e..84ae43ae2b4 100644
--- a/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java
+++ b/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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,7 +53,6 @@ public static void main(String args[]) throws Exception {
         testFullAndRemark();
         testConcurrentMark();
         testBadVerificationType();
-        testUnsupportedCollector();
     }
 
     private static void testAllVerificationEnabled() throws Exception {
@@ -127,14 +126,6 @@ private static void testBadVerificationType() throws Exception {
         verifyCollection("Pause Full", true, true, true, output.getStdout());
     }
 
-    private static void testUnsupportedCollector() throws Exception {
-        OutputAnalyzer output;
-        // Test bad gc
-        output = testWithBadGC();
-        output.shouldHaveExitValue(0);
-        output.shouldMatch("VerifyGCType is not supported by this collector.");
-    }
-
     private static OutputAnalyzer testWithVerificationType(String[] types) throws Exception {
         ArrayList basicOpts = new ArrayList<>();
         Collections.addAll(basicOpts, new String[] {
@@ -161,17 +152,6 @@ private static OutputAnalyzer testWithVerificationType(String[] types) throws Ex
         return analyzer;
     }
 
-    private static OutputAnalyzer testWithBadGC() throws Exception {
-        ProcessBuilder procBuilder =  ProcessTools.createJavaProcessBuilder(new String[] {
-                "-XX:+UseParallelGC",
-                "-XX:+UnlockDiagnosticVMOptions",
-                "-XX:VerifyGCType=full",
-                "-version"});
-
-        OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start());
-        return analyzer;
-    }
-
     private static void verifyCollection(String name, boolean expectBefore, boolean expectDuring, boolean expectAfter, String data) {
         CollectionInfo ci = CollectionInfo.parseFirst(name, data);
         Asserts.assertTrue(ci != null, "Expected GC not found: " + name + "\n" + data);

From 7dc307b1ea07555733288784a7cff742219c6089 Mon Sep 17 00:00:00 2001
From: tschatzl 
Date: Mon, 26 Mar 2018 16:51:43 +0200
Subject: [PATCH 025/196] 8180415: Rebuild remembered sets during the
 concurrent cycle Summary: In general maintain remembered sets of old regions
 only from the start of the concurrent cycle to the mixed gc they are used, at
 most until the end of the mixed phase. Reviewed-by: sjohanss, sangheki

---
 .../TestConcurrentPhaseControlG1.java                         | 4 ++--
 .../TestConcurrentPhaseControlG1Basics.java                   | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlG1.java b/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlG1.java
index 8c3775b927b..48c5b5212b5 100644
--- a/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlG1.java
+++ b/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlG1.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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,7 +53,7 @@ public class TestConcurrentPhaseControlG1 {
         {"MARK_FROM_ROOTS", "Concurrent Mark From Roots"},
         {"BEFORE_REMARK", null},
         {"REMARK", "Pause Remark"},
-        {"CREATE_LIVE_DATA", "Concurrent Create Live Data"},
+        {"REBUILD_REMEMBERED_SETS", "Concurrent Rebuild Remembered Sets"},
         // "COMPLETE_CLEANUP",  -- optional phase, not reached by this test
         {"CLEANUP_FOR_NEXT_MARK", "Concurrent Cleanup for Next Mark"},
         // Clear request
diff --git a/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlG1Basics.java b/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlG1Basics.java
index 8097bb412a0..7b8d662579e 100644
--- a/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlG1Basics.java
+++ b/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlG1Basics.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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,7 +53,7 @@ public class TestConcurrentPhaseControlG1Basics {
         "MARK_FROM_ROOTS",
         "BEFORE_REMARK",
         "REMARK",
-        "CREATE_LIVE_DATA",
+        "REBUILD_REMEMBERED_SETS",
         "COMPLETE_CLEANUP",
         "CLEANUP_FOR_NEXT_MARK",
     };

From c98ea5dfbde99d71de90297eca66bd1dc96c7ead Mon Sep 17 00:00:00 2001
From: tschatzl 
Date: Mon, 26 Mar 2018 16:51:43 +0200
Subject: [PATCH 026/196] 8196485: FromCardCache default card index can cause
 crashes Summary: The default value of -1 for 32 bit card indices is a regular
 card value at the border of 2TB heap addresses in the from card cache, so G1
 may loose remembered set entries. Extend from card cache entries to 64 bits.
 Reviewed-by: shade, sjohanss Contributed-by: Thomas Schatzl
 , Jarkko Miettinen 

---
 .../jtreg/gc/g1/TestFromCardCacheIndex.java   | 120 ++++++++++++++++++
 1 file changed, 120 insertions(+)
 create mode 100644 test/hotspot/jtreg/gc/g1/TestFromCardCacheIndex.java

diff --git a/test/hotspot/jtreg/gc/g1/TestFromCardCacheIndex.java b/test/hotspot/jtreg/gc/g1/TestFromCardCacheIndex.java
new file mode 100644
index 00000000000..f2332306dae
--- /dev/null
+++ b/test/hotspot/jtreg/gc/g1/TestFromCardCacheIndex.java
@@ -0,0 +1,120 @@
+/*
+ * @test TestFromCardCacheIndex.java
+ * @bug 8196485
+ * @summary Ensure that G1 does not miss a remembered set entry due to from card cache default value indices.
+ * @key gc
+ * @requires vm.gc.G1
+ * @requires vm.debug
+ * @requires vm.bits != "32"
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. -Xms20M -Xmx20M -XX:+UseCompressedOops -XX:G1HeapRegionSize=1M -XX:HeapBaseMinAddress=2199011721216 -XX:+UseG1GC -verbose:gc TestFromCardCacheIndex
+ */
+
+import sun.hotspot.WhiteBox;
+
+/**
+ * Repeatedly tries to generate references from objects that contained a card with the same index
+ * of the from card cache default value.
+ */
+public class TestFromCardCacheIndex {
+    private static WhiteBox WB;
+
+    // Shift value to calculate card indices from addresses.
+    private static final int CardSizeShift = 9;
+
+    /**
+     * Returns the last address on the heap within the object.
+     *
+     * @param The Object array to get the last address from.
+     */
+    private static long getObjectLastAddress(Object[] o) {
+        return WB.getObjectAddress(o) + WB.getObjectSize(o) - 1;
+    }
+
+    /**
+     * Returns the (truncated) 32 bit card index for the given address.
+     *
+     * @param The address to get the 32 bit card index from.
+     */
+    private static int getCardIndex32bit(long address) {
+        return (int)(address >> CardSizeShift);
+    }
+
+    // The source arrays that are placed on the heap in old gen.
+    private static int numArrays = 7000;
+    private static int arraySize = 508;
+    // Size of a humongous byte array, a bit less than a 1M region. This makes sure
+    // that we always create a cross-region reference when referencing it.
+    private static int byteArraySize = 1024*1023;
+
+    public static void main(String[] args) {
+        WB = sun.hotspot.WhiteBox.getWhiteBox();
+        for (int i = 0; i < 5; i++) {
+          runTest();
+          WB.fullGC();
+        }
+    }
+
+    public static void runTest() {
+        System.out.println("Starting test");
+
+        // Spray the heap with random object arrays in the hope that we get one
+        // at the proper place.
+        Object[][] arrays = new Object[numArrays][];
+        for (int i = 0; i < numArrays; i++) {
+            arrays[i] = new Object[arraySize];
+        }
+
+        // Make sure that everything is in old gen.
+        WB.fullGC();
+
+        // Find if we got an allocation at the right spot.
+        Object[] arrayWithCardMinus1 = findArray(arrays);
+
+        if (arrayWithCardMinus1 == null) {
+            System.out.println("Array with card -1 not found. Trying again.");
+            return;
+        } else {
+            System.out.println("Array with card -1 found.");
+        }
+
+        System.out.println("Modifying the last card in the array with a new object in a different region...");
+        // Create a target object that is guaranteed to be in a different region.
+        byte[] target = new byte[byteArraySize];
+
+        // Modify the last entry of the object we found.
+        arrayWithCardMinus1[arraySize - 1] = target;
+
+        target = null;
+        // Make sure that the dirty cards are flushed by doing a GC.
+        System.out.println("Doing a GC.");
+        WB.youngGC();
+
+        System.out.println("The crash didn't reproduce. Trying again.");
+    }
+
+    /**
+     * Finds an returns an array that contains a (32 bit truncated) card with value -1.
+     */
+    private static Object[] findArray(Object[][] arrays) {
+        for (int i = 0; i < arrays.length; i++) {
+            Object[] target = arrays[i];
+            if (target == null) {
+                continue;
+            }
+            final long startAddress = WB.getObjectAddress(target);
+            final long lastAddress = getObjectLastAddress(target);
+            final int card = getCardIndex32bit(lastAddress);
+            if (card == -1) {
+                Object[] foundArray = target;
+                return foundArray;
+            }
+        }
+        return null;
+    }
+}
+

From b6075a97c9c9823d9a23a4db78301b1bec3f7061 Mon Sep 17 00:00:00 2001
From: amenkov 
Date: Mon, 26 Mar 2018 09:27:24 -0700
Subject: [PATCH 027/196] 8049695: nsk/jdb/options/connect/connect003 fails
 with "Launched jdb could not attach to debuggee during 300000 milliseconds"
 Reviewed-by: dholmes, sspitsyn, cjplummer

---
 .../share/native/libdt_shmem/shmemBase.c      |  46 ++++---
 .../serviceability/attach/ShMemLongName.java  | 124 ++++++++++++++++++
 2 files changed, 146 insertions(+), 24 deletions(-)
 create mode 100644 test/hotspot/jtreg/serviceability/attach/ShMemLongName.java

diff --git a/src/jdk.jdi/share/native/libdt_shmem/shmemBase.c b/src/jdk.jdi/share/native/libdt_shmem/shmemBase.c
index 1001ef3a912..77266af3627 100644
--- a/src/jdk.jdi/share/native/libdt_shmem/shmemBase.c
+++ b/src/jdk.jdi/share/native/libdt_shmem/shmemBase.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, 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
@@ -404,25 +404,25 @@ static int
 createStream(char *name, Stream *stream)
 {
     jint error;
-    char prefix[MAX_IPC_PREFIX];
+    char objectName[MAX_IPC_NAME];
 
-    sprintf(prefix, "%s.mutex", name);
-    error = createWithGeneratedName(prefix, stream->shared->mutexName,
+    sprintf(objectName, "%s.mutex", name);
+    error = createWithGeneratedName(objectName, stream->shared->mutexName,
                                     createMutex, &stream->mutex);
     if (error != SYS_OK) {
         return error;
     }
 
-    sprintf(prefix, "%s.hasData", name);
-    error = createWithGeneratedName(prefix, stream->shared->hasDataEventName,
+    sprintf(objectName, "%s.hasData", name);
+    error = createWithGeneratedName(objectName, stream->shared->hasDataEventName,
                                     createEvent, &stream->hasData);
     if (error != SYS_OK) {
         (void)closeStream(stream, JNI_FALSE);
         return error;
     }
 
-    sprintf(prefix, "%s.hasSpace", name);
-    error = createWithGeneratedName(prefix, stream->shared->hasSpaceEventName,
+    sprintf(objectName, "%s.hasSpace", name);
+    error = createWithGeneratedName(objectName, stream->shared->hasSpaceEventName,
                                     createEvent, &stream->hasSpace);
     if (error != SYS_OK) {
         (void)closeStream(stream, JNI_FALSE);
@@ -598,7 +598,7 @@ createConnection(SharedMemoryTransport *transport, jlong otherPID,
                  SharedMemoryConnection **connectionPtr)
 {
     jint error;
-    char streamPrefix[MAX_IPC_NAME];
+    char streamName[MAX_IPC_NAME];
 
     SharedMemoryConnection *connection = allocConnection();
     if (connection == NULL) {
@@ -619,17 +619,17 @@ createConnection(SharedMemoryTransport *transport, jlong otherPID,
     connection->incoming.shared = &connection->shared->toServer;
     connection->outgoing.shared = &connection->shared->toClient;
 
-    strcpy(streamPrefix, connection->name);
-    strcat(streamPrefix, ".ctos");
-    error = createStream(streamPrefix, &connection->incoming);
+    strcpy(streamName, connection->name);
+    strcat(streamName, ".ctos");
+    error = createStream(streamName, &connection->incoming);
     if (error != SYS_OK) {
         closeConnection(connection);
         return error;
     }
 
-    strcpy(streamPrefix, connection->name);
-    strcat(streamPrefix, ".stoc");
-    error = createStream(streamPrefix, &connection->outgoing);
+    strcpy(streamName, connection->name);
+    strcat(streamName, ".stoc");
+    error = createStream(streamName, &connection->outgoing);
     if (error != SYS_OK) {
         closeConnection(connection);
         return error;
@@ -746,9 +746,7 @@ createTransport(const char *address, SharedMemoryTransport **transportPtr)
 {
     SharedMemoryTransport *transport;
     jint error;
-    char prefix[MAX_IPC_PREFIX];
-
-
+    char objectName[MAX_IPC_NAME];
 
     transport = allocTransport();
     if (transport == NULL) {
@@ -784,24 +782,24 @@ createTransport(const char *address, SharedMemoryTransport **transportPtr)
     memset(transport->shared, 0, sizeof(SharedListener));
     transport->shared->acceptingPID = sysProcessGetID();
 
-    sprintf(prefix, "%s.mutex", transport->name);
-    error = createWithGeneratedName(prefix, transport->shared->mutexName,
+    sprintf(objectName, "%s.mutex", transport->name);
+    error = createWithGeneratedName(objectName, transport->shared->mutexName,
                                     createMutex, &transport->mutex);
     if (error != SYS_OK) {
         closeTransport(transport);
         return error;
     }
 
-    sprintf(prefix, "%s.accept", transport->name);
-    error = createWithGeneratedName(prefix, transport->shared->acceptEventName,
+    sprintf(objectName, "%s.accept", transport->name);
+    error = createWithGeneratedName(objectName, transport->shared->acceptEventName,
                                     createEvent, &transport->acceptEvent);
     if (error != SYS_OK) {
         closeTransport(transport);
         return error;
     }
 
-    sprintf(prefix, "%s.attach", transport->name);
-    error = createWithGeneratedName(prefix, transport->shared->attachEventName,
+    sprintf(objectName, "%s.attach", transport->name);
+    error = createWithGeneratedName(objectName, transport->shared->attachEventName,
                                     createEvent, &transport->attachEvent);
     if (error != SYS_OK) {
         closeTransport(transport);
diff --git a/test/hotspot/jtreg/serviceability/attach/ShMemLongName.java b/test/hotspot/jtreg/serviceability/attach/ShMemLongName.java
new file mode 100644
index 00000000000..bd491a1628b
--- /dev/null
+++ b/test/hotspot/jtreg/serviceability/attach/ShMemLongName.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2018, 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 8049695
+ * @summary Ensure shmem transport works with long names
+ * @requires os.family == "windows"
+ * @library /test/lib
+ * @run main/othervm ShMemLongName
+ */
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Map;
+
+import com.sun.jdi.Bootstrap;
+import com.sun.jdi.VirtualMachine;
+import com.sun.jdi.connect.AttachingConnector;
+import com.sun.jdi.connect.Connector;
+import jdk.test.lib.process.ProcessTools;
+
+
+public class ShMemLongName {
+
+    private static final int maxShMemLength = 49;
+
+    private static final String transport = "dt_shmem";
+
+    public static void main(String[] args) throws Exception {
+        // test with the maximum supported shmem name length
+        String shmemName = ("ShMemLongName" + ProcessHandle.current().pid()
+                                    + String.join("", Collections.nCopies(maxShMemLength, "x"))
+                                 ).substring(0, maxShMemLength);
+        Process target = getTarget(shmemName).start();
+        try {
+            waitForReady(target);
+
+            log("attaching to the VM...");
+            AttachingConnector ac = Bootstrap.virtualMachineManager().attachingConnectors()
+                    .stream()
+                    .filter(c -> transport.equals(c.transport().name()))
+                    .findFirst()
+                    .orElseThrow(() -> new RuntimeException("Failed to find transport " + transport));
+            Map acArgs = ac.defaultArguments();
+            acArgs.get("name").setValue(shmemName);
+
+            VirtualMachine vm = ac.attach(acArgs);
+
+            log("attached. test(1) PASSED.");
+
+            vm.dispose();
+        } finally {
+            target.destroy();
+            target.waitFor();
+        }
+
+        // extra test: ensure using of too-long name fails gracefully
+        // (shmemName + "X") is expected to be "too long".
+        ProcessTools.executeProcess(getTarget(shmemName + "X"))
+                .shouldContain("address strings longer than")
+                .shouldHaveExitValue(2);
+        log("test(2) PASSED.");
+    }
+
+    private static void log(String s) {
+        System.out.println(s);
+        System.out.flush();
+    }
+
+    // creates target process builder for the specified shmem transport name
+    private static ProcessBuilder getTarget(String shmemName) throws IOException {
+        log("starting target with shmem name: '" + shmemName + "'...");
+        return ProcessTools.createJavaProcessBuilder(
+                "-Xdebug",
+                "-Xrunjdwp:transport=" + transport + ",server=y,suspend=n,address=" + shmemName,
+                "ShMemLongName$Target");
+    }
+
+    private static void waitForReady(Process target) throws Exception {
+        InputStream os = target.getInputStream();
+        try (BufferedReader reader = new BufferedReader(new InputStreamReader(os))) {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                if (line.equals(Target.readyString)) {
+                    return;
+                }
+            }
+        }
+    }
+
+    public static class Target {
+        public static final String readyString = "Ready";
+        public static void main(String[] args) throws Exception {
+            log(readyString);
+            while (true) {
+                Thread.sleep(1000);
+            }
+        }
+    }
+}

From dc4db1f0d49edd2241fec17a2ad3734429d14161 Mon Sep 17 00:00:00 2001
From: gadams 
Date: Mon, 26 Mar 2018 08:17:56 -0400
Subject: [PATCH 028/196] 8057732:
 sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java: Invalid
 PerfMemory size Reviewed-by: cjplummer

---
 .../sun/tools/attach/VirtualMachineImpl.java   | 18 ++++++++++++++----
 test/jdk/ProblemList.txt                       |  1 -
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java b/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java
index bf2a3dc081d..a6f2279ecfc 100644
--- a/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java
+++ b/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, 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
@@ -80,9 +80,19 @@ InputStream execute(String cmd, Object ... args)
         assert args.length <= 3;        // includes null
 
         // create a pipe using a random name
-        int r = (new Random()).nextInt();
-        String pipename = "\\\\.\\pipe\\javatool" + r;
-        long hPipe = createPipe(pipename);
+        Random rnd = new Random();
+        int r = rnd.nextInt();
+        String pipeprefix = "\\\\.\\pipe\\javatool";
+        String pipename = pipeprefix + r;
+        long hPipe;
+        try {
+            hPipe = createPipe(pipename);
+        } catch (IOException ce) {
+            // Retry with another random pipe name.
+            r = rnd.nextInt();
+            pipename = pipeprefix + r;
+            hPipe = createPipe(pipename);
+        }
 
         // check if we are detached - in theory it's possible that detach is invoked
         // after this check but before we enqueue the command.
diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt
index 94c3610b7b3..6c24e2a6d3b 100644
--- a/test/jdk/ProblemList.txt
+++ b/test/jdk/ProblemList.txt
@@ -768,7 +768,6 @@ com/sun/jdi/NashornPopFrameTest.java                            8187143 generic-
 
 sun/tools/jstat/jstatClassloadOutput1.sh                        8173942 generic-all
 
-sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java    8057732 generic-all
 
 ############################################################################
 

From 1446052a25a8ab20af9cb05791db1aaa1dc40bbc Mon Sep 17 00:00:00 2001
From: tschatzl 
Date: Tue, 27 Mar 2018 11:05:01 +0200
Subject: [PATCH 029/196] 8193067: gc/g1/TestVerifyGCType.java still unstable
 Summary: Fix number of gc threads and heap waste percentage to trigger mixed
 gcs reproducibly Reviewed-by: sjohanss, pliden

---
 test/hotspot/jtreg/ProblemList.txt             | 1 -
 test/hotspot/jtreg/gc/g1/TestVerifyGCType.java | 2 ++
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt
index f67ec676dbd..87ee16063c9 100644
--- a/test/hotspot/jtreg/ProblemList.txt
+++ b/test/hotspot/jtreg/ProblemList.txt
@@ -63,7 +63,6 @@ gc/g1/humongousObjects/objectGraphTest/TestObjectGraphAfterGC.java 8156755 gener
 gc/survivorAlignment/TestPromotionToSurvivor.java 8129886 generic-all
 gc/g1/logging/TestG1LoggingFailure.java 8169634 generic-all
 gc/g1/humongousObjects/TestHeapCounters.java 8178918 generic-all
-gc/g1/TestVerifyGCType.java 8193067 generic-all
 gc/stress/gclocker/TestGCLockerWithParallel.java 8180622 generic-all
 gc/stress/gclocker/TestGCLockerWithG1.java 8180622 generic-all
 gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java 8177765 generic-all
diff --git a/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java b/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java
index 84ae43ae2b4..f5450c7cfa7 100644
--- a/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java
+++ b/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java
@@ -136,6 +136,8 @@ private static OutputAnalyzer testWithVerificationType(String[] types) throws Ex
                                        "-Xlog:gc,gc+start,gc+verify=info",
                                        "-Xms16m",
                                        "-Xmx16m",
+                                       "-XX:ParallelGCThreads=1",
+                                       "-XX:G1HeapWastePercent=1",
                                        "-XX:+VerifyBeforeGC",
                                        "-XX:+VerifyAfterGC",
                                        "-XX:+VerifyDuringGC"});

From 82f6545399fc8abecb5011ca09a3ef321610e08c Mon Sep 17 00:00:00 2001
From: thartmann 
Date: Tue, 27 Mar 2018 11:13:11 +0200
Subject: [PATCH 030/196] 8200227: [Graal] Test times out with Graal due to low
 compile threshold Summary: Removed unnecessary VM options from test to avoid
 timeouts with Graal. Reviewed-by: kvn

---
 .../intrinsics/string/TestStringIntrinsicRangeChecks.java       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/hotspot/jtreg/compiler/intrinsics/string/TestStringIntrinsicRangeChecks.java b/test/hotspot/jtreg/compiler/intrinsics/string/TestStringIntrinsicRangeChecks.java
index 3486950413e..5f37c54f97a 100644
--- a/test/hotspot/jtreg/compiler/intrinsics/string/TestStringIntrinsicRangeChecks.java
+++ b/test/hotspot/jtreg/compiler/intrinsics/string/TestStringIntrinsicRangeChecks.java
@@ -29,7 +29,7 @@
  * @summary Verifies that string intrinsics throw array out of bounds exceptions.
  * @library /compiler/patches /test/lib
  * @build java.base/java.lang.Helper
- * @run main/othervm -Xbatch -XX:CompileThreshold=100 -XX:-TieredCompilation compiler.intrinsics.string.TestStringIntrinsicRangeChecks
+ * @run main/othervm -Xbatch -XX:CompileThreshold=100 compiler.intrinsics.string.TestStringIntrinsicRangeChecks
  */
 package compiler.intrinsics.string;
 

From 71ff7276f8e01feaeddcb46ea8a070d3b424f750 Mon Sep 17 00:00:00 2001
From: simonis 
Date: Wed, 28 Mar 2018 11:27:35 +0200
Subject: [PATCH 031/196] 8198915: [Graal] 3rd testcase of
 compiler/types/TestMeetIncompatibleInterfaceArrays.java takes more than 10
 mins Reviewed-by: kvn, thartmann

---
 .../TestMeetIncompatibleInterfaceArrays.java  | 59 ++++++++++++-------
 1 file changed, 39 insertions(+), 20 deletions(-)

diff --git a/test/hotspot/jtreg/compiler/types/TestMeetIncompatibleInterfaceArrays.java b/test/hotspot/jtreg/compiler/types/TestMeetIncompatibleInterfaceArrays.java
index 180508664ce..8df5b0e4832 100644
--- a/test/hotspot/jtreg/compiler/types/TestMeetIncompatibleInterfaceArrays.java
+++ b/test/hotspot/jtreg/compiler/types/TestMeetIncompatibleInterfaceArrays.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 SAP SE. All rights reserved.
+ * Copyright (c) 2018 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
@@ -27,7 +27,7 @@
  * @summary C2 can not handle returns with inccompatible interface arrays
  * @modules java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.misc
- * @library /test/lib
+ * @library /test/lib /
  *
  * @build sun.hotspot.WhiteBox
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
@@ -37,7 +37,6 @@
  *        -XX:+UnlockDiagnosticVMOptions
  *        -XX:+WhiteBoxAPI
  *        -Xbatch
- *        -XX:CompileThreshold=1
  *        -XX:-TieredCompilation
  *        -XX:CICompilerCount=1
  *        -XX:+PrintCompilation
@@ -51,7 +50,6 @@
  *        -XX:+UnlockDiagnosticVMOptions
  *        -XX:+WhiteBoxAPI
  *        -Xbatch
- *        -XX:CompileThreshold=1
  *        -XX:-TieredCompilation
  *        -XX:CICompilerCount=1
  *        -XX:+PrintCompilation
@@ -65,11 +63,6 @@
  *        -XX:+UnlockDiagnosticVMOptions
  *        -XX:+WhiteBoxAPI
  *        -Xbatch
- *        -XX:CompileThreshold=1
- *        -XX:Tier0InvokeNotifyFreqLog=0 -XX:Tier2InvokeNotifyFreqLog=0 -XX:Tier3InvokeNotifyFreqLog=0 -XX:Tier23InlineeNotifyFreqLog=0
- *        -XX:Tier3InvocationThreshold=2 -XX:Tier3MinInvocationThreshold=2 -XX:Tier3CompileThreshold=2
- *        -XX:Tier4InvocationThreshold=1 -XX:Tier4MinInvocationThreshold=1 -XX:Tier4CompileThreshold=1
- *        -XX:+TieredCompilation
  *        -XX:CICompilerCount=2
  *        -XX:+PrintCompilation
  *        -XX:+PrintInlining
@@ -84,6 +77,7 @@
 
 package compiler.types;
 
+import compiler.whitebox.CompilerWhiteBoxTest;
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import sun.hotspot.WhiteBox;
@@ -190,8 +184,8 @@ public static I2[][][][][] createI21Array5() {
      *     return Helper.createI2Array3(); // returns I1[][][] which gives a verifier error because return expects I1[][][][]
      *   }
      *   public static void test() {
-     *     I1[][][][][] i1 = run();
-     *     System.out.println(i1[0][0][0][0][0].getName());
+     *     I1[][][][] i1 = run();
+     *     System.out.println(i1[0][0][0][0].getName());
      *   }
      * ...
      * public class MeetIncompatibleInterfaceArrays5ASM {
@@ -306,9 +300,25 @@ static void generateTestClass(int dim, boolean good) throws Exception {
 
     }
 
-    public static String[][] tier = { { "interpreted", "C2 (tier 4) without inlining", "C2 (tier4) without inlining" },
-            { "interpreted", "C2 (tier 4) with inlining", "C2 (tier4) with inlining" },
-            { "interpreted", "C1 (tier 3) with inlining", "C2 (tier4) with inlining" } };
+    public static String[][] tier = { { "interpreted (tier 0)",
+                                        "C2 (tier 4) without inlining",
+                                        "C2 (tier 4) without inlining" },
+                                      { "interpreted (tier 0)",
+                                        "C2 (tier 4) with inlining",
+                                        "C2 (tier 4) with inlining" },
+                                      { "interpreted (tier 0)",
+                                        "C1 (tier 3) with inlining",
+                                        "C2 (tier 4) with inlining" } };
+
+    public static int[][] level = { { CompilerWhiteBoxTest.COMP_LEVEL_NONE,
+                                      CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION,
+                                      CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION },
+                                    { CompilerWhiteBoxTest.COMP_LEVEL_NONE,
+                                      CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION,
+                                      CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION },
+                                    { CompilerWhiteBoxTest.COMP_LEVEL_NONE,
+                                      CompilerWhiteBoxTest.COMP_LEVEL_FULL_PROFILE,
+                                      CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION } };
 
     public static void main(String[] args) throws Exception {
         final int pass = Integer.parseInt(args.length > 0 ? args[0] : "0");
@@ -344,8 +354,11 @@ public static void main(String[] args) throws Exception {
                 Method m = c.getMethod("test");
                 Method r = c.getMethod("run");
                 for (int j = 0; j < 3; j++) {
-                    System.out.println((j + 1) + ". invokation of " + baseClassName + i + "ASM.test() [should be "
-                            + tier[pass][j] + "]");
+                    System.out.println((j + 1) + ". invokation of " + baseClassName + i + "ASM.test() [::" +
+                                       r.getName() + "() should be '" + tier[pass][j] + "' compiled]");
+
+                    WB.enqueueMethodForCompilation(r, level[pass][j]);
+
                     try {
                         m.invoke(null);
                     } catch (InvocationTargetException ite) {
@@ -360,10 +373,16 @@ public static void main(String[] args) throws Exception {
                             }
                         }
                     }
-                }
-                System.out.println("Method " + r + (WB.isMethodCompiled(r) ? " has" : " has not") + " been compiled.");
-                if (!WB.isMethodCompiled(r)) {
-                    throw new Exception("Method " + r + " must be compiled!");
+
+                    int r_comp_level = WB.getMethodCompilationLevel(r);
+                    System.out.println("   invokation of " + baseClassName + i + "ASM.test() [::" +
+                                       r.getName() + "() was compiled at tier " + r_comp_level + "]");
+
+                    if (r_comp_level != level[pass][j]) {
+                      throw new Exception("Method " + r + " must be compiled at tier " + r_comp_level + " !");
+                    }
+
+                    WB.deoptimizeMethod(r);
                 }
             }
         }

From 912b8cf2b57048048647c0f1584dbedba6bd4db0 Mon Sep 17 00:00:00 2001
From: pliden 
Date: Wed, 28 Mar 2018 11:38:47 +0200
Subject: [PATCH 032/196] 8199918: Shorten names of CollectedHeap::Name members
 Reviewed-by: shade, eosterlund

---
 test/hotspot/jtreg/serviceability/sa/TestIntConstant.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/hotspot/jtreg/serviceability/sa/TestIntConstant.java b/test/hotspot/jtreg/serviceability/sa/TestIntConstant.java
index 67209cda743..58b637cd68b 100644
--- a/test/hotspot/jtreg/serviceability/sa/TestIntConstant.java
+++ b/test/hotspot/jtreg/serviceability/sa/TestIntConstant.java
@@ -110,7 +110,7 @@ public static void testIntConstant() throws Exception {
             // with names and the values derived from enums and #define preprocessor
             // macros in hotspot.
             String[] defaultOutputStrings =
-                {"CollectedHeap::G1CollectedHeap 2",
+                {"CollectedHeap::G1 3",
                  "RUNNABLE 2",
                  "Deoptimization::Reason_class_check 4",
                  "InstanceKlass::_misc_is_anonymous 32",

From 71c836788e8e1665010e1d934ec48797a582e9d3 Mon Sep 17 00:00:00 2001
From: pliden 
Date: Wed, 28 Mar 2018 11:38:47 +0200
Subject: [PATCH 033/196] 8199925: Break out GC selection logic from
 GCArguments to GCConfig Reviewed-by: eosterlund, rkennke

---
 test/hotspot/jtreg/serviceability/sa/TestIntConstant.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/hotspot/jtreg/serviceability/sa/TestIntConstant.java b/test/hotspot/jtreg/serviceability/sa/TestIntConstant.java
index 58b637cd68b..a73884770ea 100644
--- a/test/hotspot/jtreg/serviceability/sa/TestIntConstant.java
+++ b/test/hotspot/jtreg/serviceability/sa/TestIntConstant.java
@@ -110,7 +110,7 @@ public static void testIntConstant() throws Exception {
             // with names and the values derived from enums and #define preprocessor
             // macros in hotspot.
             String[] defaultOutputStrings =
-                {"CollectedHeap::G1 3",
+                {"CollectedHeap::G1 4",
                  "RUNNABLE 2",
                  "Deoptimization::Reason_class_check 4",
                  "InstanceKlass::_misc_is_anonymous 32",

From 4073142cf08e0a9611f5c03755a5e1ba43e023fc Mon Sep 17 00:00:00 2001
From: pliden 
Date: Wed, 28 Mar 2018 11:38:47 +0200
Subject: [PATCH 034/196] 8199927: Make WhiteBox more GC agnostic Reviewed-by:
 shade, eosterlund

---
 test/jtreg-ext/requires/VMProps.java |  8 +---
 test/lib/sun/hotspot/WhiteBox.java   |  6 +--
 test/lib/sun/hotspot/gc/GC.java      | 71 ++++++++--------------------
 3 files changed, 24 insertions(+), 61 deletions(-)

diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java
index 8b0e41a5239..8b7e6f41d8a 100644
--- a/test/jtreg-ext/requires/VMProps.java
+++ b/test/jtreg-ext/requires/VMProps.java
@@ -228,13 +228,9 @@ protected String cpuFeatures() {
      *    User either set G1 explicitely (-XX:+UseG1GC) or did not set any GC
      * @param map - property-value pairs
      */
-    protected void vmGC(Map map){
-        GC currentGC = GC.current();
-        boolean isByErgo = GC.currentSetByErgo();
-        List supportedGC = GC.allSupported();
+    protected void vmGC(Map map) {
         for (GC gc: GC.values()) {
-            boolean isSupported = supportedGC.contains(gc);
-            boolean isAcceptable = isSupported && (gc == currentGC || isByErgo);
+            boolean isAcceptable = gc.isSupported() && (gc.isSelected() || GC.isSelectedErgonomically());
             map.put("vm.gc." + gc.name(), "" + isAcceptable);
         }
     }
diff --git a/test/lib/sun/hotspot/WhiteBox.java b/test/lib/sun/hotspot/WhiteBox.java
index 79674649dac..6e906c9dcab 100644
--- a/test/lib/sun/hotspot/WhiteBox.java
+++ b/test/lib/sun/hotspot/WhiteBox.java
@@ -382,9 +382,9 @@ public void clearInlineCaches(boolean preserve_static_stubs) {
 
   // Don't use these methods directly
   // Use sun.hotspot.gc.GC class instead.
-  public native int currentGC();
-  public native int allSupportedGC();
-  public native boolean gcSelectedByErgo();
+  public native boolean isGCSupported(int name);
+  public native boolean isGCSelected(int name);
+  public native boolean isGCSelectedErgonomically();
 
   // Force Young GC
   public native void youngGC();
diff --git a/test/lib/sun/hotspot/gc/GC.java b/test/lib/sun/hotspot/gc/GC.java
index 0fcc3222eea..900346a6ac4 100644
--- a/test/lib/sun/hotspot/gc/GC.java
+++ b/test/lib/sun/hotspot/gc/GC.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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,8 +23,6 @@
 
 package sun.hotspot.gc;
 
-import java.util.ArrayList;
-import java.util.List;
 import sun.hotspot.WhiteBox;
 
 /**
@@ -32,72 +30,41 @@
  * retrieved from the VM with the WhiteBox API.
  */
 public enum GC {
+    /*
+     * Enum values much match CollectedHeap::Name
+     */
     Serial(1),
     Parallel(2),
-    ConcMarkSweep(4),
-    G1(8);
+    ConcMarkSweep(3),
+    G1(4);
 
-    private static final GC CURRENT_GC;
-    private static final int ALL_GC_CODES;
-    private static final boolean IS_BY_ERGO;
-    static {
-        WhiteBox WB = WhiteBox.getWhiteBox();
-        ALL_GC_CODES = WB.allSupportedGC();
-        IS_BY_ERGO = WB.gcSelectedByErgo();
+    private static final WhiteBox WB = WhiteBox.getWhiteBox();
 
-        int currentCode = WB.currentGC();
-        GC tmp = null;
-        for (GC gc: GC.values()) {
-            if (gc.code == currentCode) {
-                tmp = gc;
-                break;
-            }
-        }
-        if (tmp == null) {
-            throw new Error("Unknown current GC code " + currentCode);
-        }
-        CURRENT_GC = tmp;
-    }
+    private final int name;
 
-    private final int code;
-    private GC(int code) {
-        this.code = code;
+    private GC(int name) {
+        this.name = name;
     }
 
     /**
-     * @return true if the collector is supported by the VM, false otherwise.
+     * @return true if this GC is supported by the VM
      */
     public boolean isSupported() {
-        return (ALL_GC_CODES & code) != 0;
-    }
-
-
-    /**
-     * @return the current collector used by VM.
-     */
-    public static GC current() {
-        return CURRENT_GC;
+        return WB.isGCSupported(name);
     }
 
     /**
-     * @return true if GC was selected by ergonomic, false if specified
-     * explicitly by the command line flag.
+     * @return true if this GC is currently selected/used
      */
-    public static boolean currentSetByErgo() {
-        return IS_BY_ERGO;
+    public boolean isSelected() {
+        return WB.isGCSelected(name);
     }
 
     /**
-     * @return List of collectors supported by the VM.
+     * @return true if GC was selected ergonomically, as opposed
+     *         to being explicitly specified on the command line
      */
-    public static List allSupported() {
-        List list = new ArrayList<>();
-        for (GC gc: GC.values()) {
-            if (gc.isSupported()) {
-                list.add(gc);
-            }
-        }
-        return list;
+    public static boolean isSelectedErgonomically() {
+        return WB.isGCSelectedErgonomically();
     }
 }
-

From 6b94c8bfc3520724ef83fc5496a4a6ad3737b637 Mon Sep 17 00:00:00 2001
From: mseledtsov 
Date: Tue, 3 Apr 2018 08:56:46 -0700
Subject: [PATCH 035/196] 8200126: [TESTBUG] Open source VM runtime signal
 tests Summary: Open sourced the signal tests, updated make files and test
 groups accordingly Reviewed-by: dholmes, ctornqvi, ihse

---
 make/test/JtregNativeHotspot.gmk              |   3 +
 test/hotspot/jtreg/TEST.groups                |   6 +-
 test/hotspot/jtreg/runtime/signal/README      |  59 +++
 .../jtreg/runtime/signal/SigTestDriver.java   | 178 +++++++
 .../jtreg/runtime/signal/TestSigalrm.java     |  35 ++
 .../jtreg/runtime/signal/TestSigbus.java      |  35 ++
 .../jtreg/runtime/signal/TestSigcld.java      |  35 ++
 .../jtreg/runtime/signal/TestSigcont.java     |  35 ++
 .../jtreg/runtime/signal/TestSigemt.java      |  35 ++
 .../jtreg/runtime/signal/TestSigfpe.java      |  35 ++
 .../jtreg/runtime/signal/TestSigfreeze.java   |  35 ++
 .../jtreg/runtime/signal/TestSighup.java      |  35 ++
 .../jtreg/runtime/signal/TestSigill.java      |  35 ++
 .../jtreg/runtime/signal/TestSigint.java      |  35 ++
 .../jtreg/runtime/signal/TestSigiot.java      |  35 ++
 .../jtreg/runtime/signal/TestSiglost.java     |  35 ++
 .../jtreg/runtime/signal/TestSiglwp.java      |  35 ++
 .../jtreg/runtime/signal/TestSigpipe.java     |  35 ++
 .../jtreg/runtime/signal/TestSigpoll.java     |  35 ++
 .../jtreg/runtime/signal/TestSigprof.java     |  35 ++
 .../jtreg/runtime/signal/TestSigpwr.java      |  35 ++
 .../jtreg/runtime/signal/TestSigquit.java     |  35 ++
 .../jtreg/runtime/signal/TestSigsegv.java     |  35 ++
 .../jtreg/runtime/signal/TestSigstop.java     |  35 ++
 .../jtreg/runtime/signal/TestSigsys.java      |  35 ++
 .../jtreg/runtime/signal/TestSigterm.java     |  35 ++
 .../jtreg/runtime/signal/TestSigthaw.java     |  35 ++
 .../jtreg/runtime/signal/TestSigtrap.java     |  35 ++
 .../jtreg/runtime/signal/TestSigtstp.java     |  35 ++
 .../jtreg/runtime/signal/TestSigttin.java     |  35 ++
 .../jtreg/runtime/signal/TestSigttou.java     |  35 ++
 .../jtreg/runtime/signal/TestSigurg.java      |  35 ++
 .../jtreg/runtime/signal/TestSigusr1.java     |  35 ++
 .../jtreg/runtime/signal/TestSigusr2.java     |  35 ++
 .../jtreg/runtime/signal/TestSigvtalrm.java   |  35 ++
 .../jtreg/runtime/signal/TestSigwinch.java    |  35 ++
 .../jtreg/runtime/signal/TestSigxcpu.java     |  35 ++
 .../jtreg/runtime/signal/TestSigxfsz.java     |  35 ++
 .../jtreg/runtime/signal/TestSigxres.java     |  35 ++
 .../hotspot/jtreg/runtime/signal/exesigtest.c | 462 ++++++++++++++++++
 40 files changed, 1931 insertions(+), 2 deletions(-)
 create mode 100644 test/hotspot/jtreg/runtime/signal/README
 create mode 100644 test/hotspot/jtreg/runtime/signal/SigTestDriver.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigalrm.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigbus.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigcld.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigcont.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigemt.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigfpe.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigfreeze.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSighup.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigill.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigint.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigiot.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSiglost.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSiglwp.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigpipe.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigpoll.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigprof.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigpwr.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigquit.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigsegv.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigstop.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigsys.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigterm.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigthaw.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigtrap.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigtstp.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigttin.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigttou.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigurg.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigusr1.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigusr2.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigvtalrm.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigwinch.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigxcpu.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigxfsz.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/TestSigxres.java
 create mode 100644 test/hotspot/jtreg/runtime/signal/exesigtest.c

diff --git a/make/test/JtregNativeHotspot.gmk b/make/test/JtregNativeHotspot.gmk
index 2c3cd31395c..1e5fc8b4a49 100644
--- a/make/test/JtregNativeHotspot.gmk
+++ b/make/test/JtregNativeHotspot.gmk
@@ -65,8 +65,11 @@ else
       exeinvoke.c exestack-gap.c
 endif
 
+BUILD_HOTSPOT_JTREG_EXECUTABLES_LIBS_exesigtest := -ljvm
+
 ifeq ($(OPENJDK_TARGET_OS), windows)
     BUILD_HOTSPOT_JTREG_EXECUTABLES_CFLAGS_exeFPRegs := -MT
+    BUILD_HOTSPOT_JTREG_EXCLUDE += exesigtest.c
 endif
 
 $(eval $(call SetupTestFilesCompilation, BUILD_HOTSPOT_JTREG_LIBRARIES, \
diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups
index dc8afeb73e7..b4b06329530 100644
--- a/test/hotspot/jtreg/TEST.groups
+++ b/test/hotspot/jtreg/TEST.groups
@@ -220,7 +220,8 @@ tier1_runtime = \
  -runtime/containers/ \
   sanity/ \
   testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java \
- -:tier1_runtime_appcds_exclude
+ -:tier1_runtime_appcds_exclude \
+ -runtime/signal
 
 hotspot_cds = \
   runtime/SharedArchiveFile/ \
@@ -263,7 +264,8 @@ hotspot_tier2_runtime = \
  -runtime/containers/ \
  -:tier1_runtime \
  -:tier1_serviceability \
- -:hotspot_tier2_runtime_platform_agnostic
+ -:hotspot_tier2_runtime_platform_agnostic \
+ -runtime/signal
 
 hotspot_tier2_runtime_platform_agnostic = \
   runtime/SelectionResolution \
diff --git a/test/hotspot/jtreg/runtime/signal/README b/test/hotspot/jtreg/runtime/signal/README
new file mode 100644
index 00000000000..4a83fb5a911
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/README
@@ -0,0 +1,59 @@
+Copyright (c) 2008, 2018, 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.
+
+
+Briefly, the tests cover the following scenarios:
+1. prepre
+   set signal handlers -> create JVM -> send signals -> destroy JVM -> check signal handlers were called
+
+2. prepost
+   set signal handlers -> create JVM -> destroy JVM -> send signals  -> check signal handlers were called
+
+3. postpre
+   create JVM ->set signal handlers -> send signals -> destroy JVM -> check signal handlers were called
+
+4. postpost
+   create JVM -> set signal handlers -> destroy JVM -> send signals  -> check signal handlers were called
+
+There is one more scenario called 'nojvm'.
+In this case no jvm is created, so pure signal testing is done.
+
+Signal handlers don't do anything, so the only fact that signal handler was called is checked.
+Also 2 different ways of setting signal handlers are tested: sigaction, sigset.
+
+For 'postpre' and 'postpro' libjsig.so is used to chain signal handlers behind VM installed ones.
+
+=> Current tests cover the following cases (don't count 'nojvm' scenario):
+1. Support for pre-installed signal handlers when the HotSpot VM is created.
+2. Support for signal handler installation after the HotSpot VM is created inside JNI code
+
+
+Notes:
+
+SIGQUIT, SIGTERM, SIGINT, and SIGHUP signals cannot be chained.
+If the application needs to handle these signals, the -Xrs option needs
+to be specified. So, test these signals only with -Xrs flag.
+
+On Linux and Mac OS X, SIGUSR2 is used to implement suspend and resume. So,
+don't test SIGUSR2 on Linux and Mac OS X.
+
+SIGJVM1 and SIGJVM2 exist only on Solaris and are reserved for exclusive use
+by the JVM. So don't test SIGJVM1 and SIGJVM2.
diff --git a/test/hotspot/jtreg/runtime/signal/SigTestDriver.java b/test/hotspot/jtreg/runtime/signal/SigTestDriver.java
new file mode 100644
index 00000000000..ea548f3b97c
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/SigTestDriver.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2007, 2018, 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 jdk.test.lib.Platform;
+import jdk.test.lib.Utils;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class SigTestDriver {
+    public static void main(String[] args) {
+        // No signal tests on Windows yet; so setting to no-op
+        if (Platform.isWindows()) {
+            System.out.println("SKIPPED: no signal tests on Windows, ignore.");
+            return;
+        }
+
+        // At least one argument should be specified
+        if ( (args == null) || (args.length < 1) ) {
+            throw new IllegalArgumentException("At lease one argument should be specified, the signal name");
+        }
+
+        String signame = args[0];
+        switch (signame) {
+            case "SIGWAITING":
+            case "SIGKILL":
+            case "SIGSTOP": {
+                System.out.println("SKIPPED: signals SIGWAITING, SIGKILL and SIGSTOP can't be tested, ignore.");
+                return;
+            }
+            case "SIGUSR2": {
+                if (Platform.isLinux()) {
+                    System.out.println("SKIPPED: SIGUSR2 can't be tested on Linux, ignore.");
+                    return;
+                } else if (Platform.isOSX()) {
+                    System.out.println("SKIPPED: SIGUSR2 can't be tested on OS X, ignore.");
+                    return;
+                }
+            }
+        }
+
+        Path test = Paths.get(System.getProperty("test.nativepath"))
+                         .resolve("sigtest")
+                         .toAbsolutePath();
+        String envVar = Platform.isWindows() ? "PATH" :
+                (Platform.isOSX() ? "DYLD_LIBRARY_PATH" : "LD_LIBRARY_PATH");
+
+        List cmd = new ArrayList<>();
+        Collections.addAll(cmd,
+                test.toString(),
+                "-sig",
+                signame,
+                "-mode",
+                null, // modeIdx
+                "-scenario",
+                null // scenarioIdx
+        );
+        int modeIdx = 4;
+        int scenarioIdx = 6;
+
+        // add external flags
+        cmd.addAll(vmargs());
+
+        // add test specific arguments w/o signame
+        cmd.addAll(Arrays.asList(args)
+                         .subList(1, args.length));
+
+        boolean passed = true;
+
+        for (String mode : new String[]{"sigset", "sigaction"}) {
+            for (String scenario : new String[] {"nojvm", "prepre", "prepost", "postpre", "postpost"}) {
+                cmd.set(modeIdx, mode);
+                cmd.set(scenarioIdx, scenario);
+                System.out.printf("START TESTING: SIGNAL = %s, MODE = %s, SCENARIO=%s%n",signame, mode, scenario);
+                System.out.printf("Do execute: %s%n", cmd.toString());
+
+                ProcessBuilder pb = new ProcessBuilder(cmd);
+                pb.environment().merge(envVar, jvmLibDir().toString(),
+                        (x, y) -> y + File.pathSeparator + x);
+                pb.environment().put("CLASSPATH", Utils.TEST_CLASS_PATH);
+
+                switch (scenario) {
+                    case "postpre":
+                    case "postpost": {
+                        pb.environment().merge("LD_PRELOAD", libjsig().toString(),
+                                (x, y) -> y + File.pathSeparator + x);
+                    }
+                }
+
+                try {
+                    OutputAnalyzer oa = ProcessTools.executeProcess(pb);
+                    oa.reportDiagnosticSummary();
+                    int exitCode = oa.getExitValue();
+                    if (exitCode == 0) {
+                       System.out.println("PASSED with exit code 0");
+                    } else {
+                        System.out.println("FAILED with exit code " + exitCode);
+                        passed = false;
+                    }
+                } catch (Exception e) {
+                    throw new Error("execution failed", e);
+                }
+            }
+        }
+
+        if (!passed) {
+            throw new Error("test failed");
+        }
+    }
+
+    private static List vmargs() {
+        return Stream.concat(Arrays.stream(Utils.VM_OPTIONS.split(" ")),
+                             Arrays.stream(Utils.JAVA_OPTIONS.split(" ")))
+                     .filter(s -> !s.isEmpty())
+                     .filter(s -> s.startsWith("-X"))
+                     .flatMap(arg -> Stream.of("-vmopt", arg))
+                     .collect(Collectors.toList());
+    }
+
+    private static Path libjsig() {
+        return jvmLibDir().resolve((Platform.isWindows() ? "" : "lib")
+                + "jsig." + Platform.sharedLibraryExt());
+    }
+
+    private static Path jvmLibDir() {
+        Path dir = Paths.get(Utils.TEST_JDK);
+        if (Platform.isWindows()) {
+            return dir.resolve("bin")
+                      .resolve(variant())
+                      .toAbsolutePath();
+        } else {
+            return dir.resolve("lib")
+                      .resolve(variant())
+                      .toAbsolutePath();
+        }
+    }
+
+    private static String variant() {
+        if (Platform.isServer()) {
+            return "server";
+        } else if (Platform.isClient()) {
+            return "client";
+        } else if (Platform.isMinimal()) {
+            return "minimal";
+        } else {
+            throw new Error("TESTBUG: unsupported vm variant");
+        }
+    }
+}
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigalrm.java b/test/hotspot/jtreg/runtime/signal/TestSigalrm.java
new file mode 100644
index 00000000000..337a97e0706
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigalrm.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigalrm01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGALRM
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigbus.java b/test/hotspot/jtreg/runtime/signal/TestSigbus.java
new file mode 100644
index 00000000000..ce1c04e50ea
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigbus.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigbus01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGBUS
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigcld.java b/test/hotspot/jtreg/runtime/signal/TestSigcld.java
new file mode 100644
index 00000000000..8b84ed97951
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigcld.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigcld01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGCLD
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigcont.java b/test/hotspot/jtreg/runtime/signal/TestSigcont.java
new file mode 100644
index 00000000000..d0e3106f251
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigcont.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigcont01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGCONT
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigemt.java b/test/hotspot/jtreg/runtime/signal/TestSigemt.java
new file mode 100644
index 00000000000..0614f87fbcc
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigemt.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigemt01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGEMT
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigfpe.java b/test/hotspot/jtreg/runtime/signal/TestSigfpe.java
new file mode 100644
index 00000000000..bd9977f3855
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigfpe.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigfpe01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+  * @library /test/lib
+ * @run main/native SigTestDriver SIGFPE
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigfreeze.java b/test/hotspot/jtreg/runtime/signal/TestSigfreeze.java
new file mode 100644
index 00000000000..d335fd7b129
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigfreeze.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigfreeze01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGFREEZE
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSighup.java b/test/hotspot/jtreg/runtime/signal/TestSighup.java
new file mode 100644
index 00000000000..6ac820d4a1f
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSighup.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sighup01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGHUP   -vmopt -XX:+PrintCommandLineFlags -vmopt -Xrs
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigill.java b/test/hotspot/jtreg/runtime/signal/TestSigill.java
new file mode 100644
index 00000000000..f24d9a024d5
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigill.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigill01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGILL
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigint.java b/test/hotspot/jtreg/runtime/signal/TestSigint.java
new file mode 100644
index 00000000000..4c6f8eafb52
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigint.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigint01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGINT   -vmopt -XX:+PrintCommandLineFlags -vmopt -Xrs
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigiot.java b/test/hotspot/jtreg/runtime/signal/TestSigiot.java
new file mode 100644
index 00000000000..107c04422bf
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigiot.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigiot01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGIOT
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSiglost.java b/test/hotspot/jtreg/runtime/signal/TestSiglost.java
new file mode 100644
index 00000000000..0b2582a61ea
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSiglost.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/siglost01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGLOST
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSiglwp.java b/test/hotspot/jtreg/runtime/signal/TestSiglwp.java
new file mode 100644
index 00000000000..3641c827785
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSiglwp.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/siglwp01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGLWP
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigpipe.java b/test/hotspot/jtreg/runtime/signal/TestSigpipe.java
new file mode 100644
index 00000000000..98476b71912
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigpipe.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigpipe01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGPIPE
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigpoll.java b/test/hotspot/jtreg/runtime/signal/TestSigpoll.java
new file mode 100644
index 00000000000..777ea2d97ad
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigpoll.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigpoll01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGPOLL
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigprof.java b/test/hotspot/jtreg/runtime/signal/TestSigprof.java
new file mode 100644
index 00000000000..e9185146c4d
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigprof.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigprof01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGPROF
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigpwr.java b/test/hotspot/jtreg/runtime/signal/TestSigpwr.java
new file mode 100644
index 00000000000..50c670d468e
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigpwr.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigpwr01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGPWR
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigquit.java b/test/hotspot/jtreg/runtime/signal/TestSigquit.java
new file mode 100644
index 00000000000..f83b9f64a20
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigquit.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigquit01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGQUIT   -vmopt -XX:+PrintCommandLineFlags -vmopt -Xrs
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigsegv.java b/test/hotspot/jtreg/runtime/signal/TestSigsegv.java
new file mode 100644
index 00000000000..2524e6d6dff
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigsegv.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigsegv01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGSEGV
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigstop.java b/test/hotspot/jtreg/runtime/signal/TestSigstop.java
new file mode 100644
index 00000000000..a6ce690da0f
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigstop.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigstop01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGSTOP
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigsys.java b/test/hotspot/jtreg/runtime/signal/TestSigsys.java
new file mode 100644
index 00000000000..32fc4dcc07f
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigsys.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigsys01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGSYS
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigterm.java b/test/hotspot/jtreg/runtime/signal/TestSigterm.java
new file mode 100644
index 00000000000..b61897dc210
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigterm.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigterm01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGTERM   -vmopt -XX:+PrintCommandLineFlags -vmopt -Xrs
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigthaw.java b/test/hotspot/jtreg/runtime/signal/TestSigthaw.java
new file mode 100644
index 00000000000..01e163c4083
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigthaw.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigthaw01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGTHAW
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigtrap.java b/test/hotspot/jtreg/runtime/signal/TestSigtrap.java
new file mode 100644
index 00000000000..46ead06c6b0
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigtrap.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigtrap01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGTRAP
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigtstp.java b/test/hotspot/jtreg/runtime/signal/TestSigtstp.java
new file mode 100644
index 00000000000..fcb5e6a0ce9
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigtstp.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigtstp01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGTSTP
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigttin.java b/test/hotspot/jtreg/runtime/signal/TestSigttin.java
new file mode 100644
index 00000000000..48e35345546
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigttin.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigttin01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGTTIN
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigttou.java b/test/hotspot/jtreg/runtime/signal/TestSigttou.java
new file mode 100644
index 00000000000..1a3ffd60d52
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigttou.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigttou01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGTTOU
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigurg.java b/test/hotspot/jtreg/runtime/signal/TestSigurg.java
new file mode 100644
index 00000000000..05fb609a06a
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigurg.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigurg01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGURG
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigusr1.java b/test/hotspot/jtreg/runtime/signal/TestSigusr1.java
new file mode 100644
index 00000000000..9f1fadc1968
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigusr1.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigusr101.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGUSR1
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigusr2.java b/test/hotspot/jtreg/runtime/signal/TestSigusr2.java
new file mode 100644
index 00000000000..915c2e97aa8
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigusr2.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigusr201.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGUSR2
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigvtalrm.java b/test/hotspot/jtreg/runtime/signal/TestSigvtalrm.java
new file mode 100644
index 00000000000..031e3c679ca
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigvtalrm.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigvtalrm01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGVTALRM
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigwinch.java b/test/hotspot/jtreg/runtime/signal/TestSigwinch.java
new file mode 100644
index 00000000000..de169ffea24
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigwinch.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigwinch01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGWINCH
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigxcpu.java b/test/hotspot/jtreg/runtime/signal/TestSigxcpu.java
new file mode 100644
index 00000000000..c63c68922b6
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigxcpu.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigxcpu01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGXCPU
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigxfsz.java b/test/hotspot/jtreg/runtime/signal/TestSigxfsz.java
new file mode 100644
index 00000000000..1aecbfdd040
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigxfsz.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigxfsz01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGXFSZ
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/TestSigxres.java b/test/hotspot/jtreg/runtime/signal/TestSigxres.java
new file mode 100644
index 00000000000..7d099e4e8b6
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/TestSigxres.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @requires os.family != "windows"
+ *
+ * @summary converted from VM testbase runtime/signal/sigxres01.
+ * VM testbase keywords: [signal, runtime, linux, solaris, macosx]
+ *
+ * @library /test/lib
+ * @run main/native SigTestDriver SIGXRES
+ */
+
diff --git a/test/hotspot/jtreg/runtime/signal/exesigtest.c b/test/hotspot/jtreg/runtime/signal/exesigtest.c
new file mode 100644
index 00000000000..02dd7625599
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/signal/exesigtest.c
@@ -0,0 +1,462 @@
+/*
+ * Copyright (c) 2007, 2018, 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * This is the main program to test the signal chaining/ handling functionality
+ * See bugs 6277077 and 6414402
+ */
+
+#define TRUE  1
+#define FALSE 0
+typedef int boolean;
+
+static JNIEnv *env;
+static JavaVM *vm;
+
+// static int sigid = 0;
+
+// Define the test pass/ fail codes, may be we can use
+// nsk/share/native/native_consts.h in future
+static int TEST_PASSED=0;
+static int TEST_FAILED=1;
+
+// This variable is used to notify whether signal has been received or not.
+static volatile sig_atomic_t sig_received = 0;
+
+static char *mode = 0;
+static char *scenario = 0;
+static char *signal_name;
+static int signal_num = -1;
+
+static JavaVMOption *options = 0;
+static int numOptions = 0;
+
+typedef struct
+{
+    int sigNum;
+    const char* sigName;
+} signalDefinition;
+
+static signalDefinition signals[] =
+{
+    {SIGINT, "SIGINT"},
+    {SIGQUIT, "SIGQUIT"},
+    {SIGILL, "SIGILL"},
+    {SIGTRAP, "SIGTRAP"},
+    {SIGIOT, "SIGIOT"},
+#ifdef SIGEMT
+    {SIGEMT, "SIGEMT"},
+#endif
+    {SIGFPE, "SIGFPE"},
+    {SIGBUS, "SIGBUS"},
+    {SIGSEGV, "SIGSEGV"},
+    {SIGSYS, "SIGSYS"},
+    {SIGPIPE, "SIGPIPE"},
+    {SIGALRM, "SIGALRM"},
+    {SIGTERM, "SIGTERM"},
+    {SIGUSR1, "SIGUSR1"},
+    {SIGUSR2, "SIGUSR2"},
+#ifdef SIGCLD
+    {SIGCLD, "SIGCLD"},
+#endif
+#ifdef SIGPWR
+    {SIGPWR, "SIGPWR"},
+#endif
+    {SIGWINCH, "SIGWINCH"},
+    {SIGURG, "SIGURG"},
+#ifdef SIGPOLL
+    {SIGPOLL, "SIGPOLL"},
+#endif
+    {SIGSTOP, "SIGSTOP"},
+    {SIGTSTP, "SIGTSTP"},
+    {SIGCONT, "SIGCONT"},
+    {SIGTTIN, "SIGTTIN"},
+    {SIGTTOU, "SIGTTOU"},
+    {SIGVTALRM, "SIGVTALRM"},
+    {SIGPROF, "SIGPROF"},
+    {SIGXCPU, "SIGXCPU"},
+    {SIGXFSZ, "SIGXFSZ"},
+#ifdef SIGWAITING
+    {SIGWAITING, "SIGWAITING"},
+#endif
+#ifdef SIGLWP
+    {SIGLWP, "SIGLWP"},
+#endif
+#ifdef SIGFREEZE
+    {SIGFREEZE, "SIGFREEZE"},
+#endif
+#ifdef SIGTHAW
+    {SIGTHAW, "SIGTHAW"},
+#endif
+#ifdef SIGLOST
+    {SIGLOST, "SIGLOST"},
+#endif
+#ifdef SIGXRES
+    {SIGXRES, "SIGXRES"},
+#endif
+    {SIGHUP, "SIGHUP"}
+};
+
+boolean isSupportedSigScenario ()
+{
+    if ( (!strcmp(scenario, "nojvm")) || (!strcmp(scenario, "prepre")) || (!strcmp(scenario, "prepost")) ||
+                (!strcmp(scenario, "postpost")) || (!strcmp(scenario, "postpre")) )
+    {
+        // printf("%s is a supported scenario\n", scenario);
+        return TRUE;
+    }
+    else
+    {
+        printf("ERROR: %s is not a supported scenario\n", scenario);
+        return FALSE;
+    }
+}
+
+boolean isSupportedSigMode ()
+{
+    if ( (!strcmp(mode, "sigset")) || (!strcmp(mode, "sigaction")) )
+    {
+        // printf("%s is a supported mode\n", mode);
+        return TRUE;
+    }
+    else
+    {
+        printf("ERROR: %s is not a supported mode\n", mode);
+        return FALSE;
+    }
+}
+
+int getSigNumBySigName(const char* sigName)
+{
+    int signals_len, sigdef_len, total_sigs, i=0;
+
+    if (sigName == NULL) return -1;
+
+    signals_len = sizeof(signals);
+    sigdef_len = sizeof(signalDefinition);
+    total_sigs = signals_len / sigdef_len;
+    for (i = 0; i < total_sigs; i++)
+    {
+        // printf("Inside for loop, i = %d\n", i);
+        if (!strcmp(sigName, signals[i].sigName))
+            return signals[i].sigNum;
+    }
+
+    return -1;
+}
+
+// signal handler
+void handler(int sig)
+{
+    printf("%s: signal handler for signal %d has been processed\n", signal_name, signal_num);
+    sig_received = 1;
+}
+
+// Initialize VM with given options
+void initVM()
+{
+    JavaVMInitArgs vm_args;
+    int i =0;
+    jint result;
+
+    vm_args.nOptions = numOptions;
+    vm_args.version = JNI_VERSION_1_2;
+    vm_args.ignoreUnrecognized = JNI_FALSE;
+    vm_args.options = options;
+
+/* try hardcoding options
+    JavaVMOption option1[2];
+    option1[0].optionString="-XX:+PrintCommandLineFlags";
+    option1[1].optionString="-Xrs";
+*/
+    vm_args.options=options;
+    vm_args.nOptions=numOptions;
+
+    // Print the VM options in use
+    printf("initVM: numOptions = %d\n", vm_args.nOptions);
+    for (i = 0; i < vm_args.nOptions; i++)
+    {
+        printf("\tvm_args.options[%d].optionString = %s\n", i, vm_args.options[i].optionString);
+    }
+
+    // Initialize VM with given options
+    result = JNI_CreateJavaVM( &vm, (void **) &env, &vm_args );
+
+    // Did the VM initialize successfully ?
+    if (result != 0)
+    {
+        printf("ERROR: cannot create Java VM.\n");
+        exit(TEST_FAILED);
+    }
+
+    (*vm)->AttachCurrentThread(vm, (void **) &env,  (void *) 0);
+    printf("initVM: JVM started and attached\n");
+}
+
+// Function to set up signal handler
+void setSignalHandler()
+{
+    int retval = 0 ;
+
+    if (!strcmp(mode, "sigaction"))
+    {
+        struct sigaction act;
+        act.sa_handler = handler;
+        sigemptyset(&act.sa_mask);
+        act.sa_flags = 0;
+        retval = sigaction(signal_num, &act, 0);
+        if (retval != 0) {
+           printf("ERROR: failed to set signal handler using function %s, error=%s\n", mode, strerror(errno));
+           exit(TEST_FAILED);
+        }
+    } // end - dealing with sigaction
+    else if (!strcmp(mode, "sigset"))
+    {
+        sigset(signal_num, handler);
+    } // end dealing with sigset
+    printf("%s: signal handler using function '%s' has been set\n", signal_name, mode);
+}
+
+// Function to invoke given signal
+void invokeSignal()
+{
+    int pid, retval;
+    sigset_t new_set, old_set;
+
+    pid = getpid();
+    retval = 0;
+
+    // we need to unblock the signal in case it was previously blocked by JVM
+    // and as result inherited by child process
+    // (this is at least the case for SIGQUIT in case -Xrs flag is not used).
+    // Otherwise the test will timeout.
+    sigemptyset(&new_set);
+    sigaddset(&new_set, signal_num);
+    sigprocmask(SIG_UNBLOCK, &new_set, &old_set);
+    if (retval != 0) {
+        printf("ERROR: failed to unblock signal, error=%s\n", strerror(errno));
+        exit(TEST_FAILED);
+    }
+
+    // send the signal
+    retval = kill(pid, signal_num);
+    if (retval != 0)
+    {
+        printf("ERROR: failed to send signal %s, error=%s\n", signal_name, strerror(errno));
+        exit(TEST_FAILED);
+    }
+
+    // set original mask for the signal
+    retval = sigprocmask(SIG_SETMASK, &old_set, NULL);
+    if (retval != 0) {
+        printf("ERROR: failed to set original mask for signal, error=%s\n", strerror(errno));
+        exit(TEST_FAILED);
+    }
+
+    printf("%s: signal has been sent successfully\n", signal_name);
+}
+
+// Usage function
+void printUsage()
+{
+    printf("Usage: sigtest -sig {signal_name} -mode {signal | sigset | sigaction } -scenario {nojvm | postpre | postpost | prepre | prepost}> [-vmopt jvm_option] \n");
+    printf("\n");
+    exit(TEST_FAILED);
+}
+
+// signal handler BEFORE VM initialization AND
+// Invoke signal BEFORE VM exits
+void scen_prepre()
+{
+    setSignalHandler();
+    initVM();
+    invokeSignal();
+    (*vm)->DestroyJavaVM(vm);
+}
+
+// signal handler BEFORE VM initialization AND
+// Invoke signal AFTER VM exits
+void scen_prepost()
+{
+    setSignalHandler();
+    initVM();
+    (*vm)->DestroyJavaVM(vm);
+    invokeSignal();
+}
+
+// signal handler AFTER VM initialization AND
+// Invoke signal BEFORE VM exits
+void scen_postpre()
+{
+    initVM();
+    setSignalHandler();
+    invokeSignal();
+    (*vm)->DestroyJavaVM(vm);
+}
+
+// signal handler AFTER VM initializationAND
+// Invoke signal AFTER VM exits
+void scen_postpost()
+{
+    initVM();
+    setSignalHandler();
+    (*vm)->DestroyJavaVM(vm);
+    invokeSignal();
+}
+
+// signal handler with no JVM in picture
+void scen_nojvm()
+{
+    setSignalHandler();
+    invokeSignal();
+}
+
+void run()
+{
+    // print the current scenario
+    if (!strcmp(scenario, "postpre"))
+        scen_postpre();
+    else if (!strcmp(scenario, "postpost"))
+        scen_postpost();
+    else if (!strcmp(scenario, "prepre"))
+        scen_prepre();
+    else if (!strcmp(scenario, "prepost"))
+        scen_prepost();
+    else if (!strcmp(scenario, "nojvm"))
+        scen_nojvm();
+}
+
+// main main
+int main(int argc, char **argv)
+{
+    int i=0, j;
+
+    signal_num = -1;
+    signal_name = NULL;
+
+    // Parse the arguments and find out how many vm args we have
+    for (i=1; i= argc )
+            {
+                printUsage();
+            }
+            signal_name = argv[i];
+
+        }
+        else if (!strcmp(argv[i], "-mode"))
+        {
+            i++;
+            if ( i >= argc )
+            {
+                printUsage();
+            }
+            mode = argv[i];
+        }
+        else if (!strcmp(argv[i], "-scenario"))
+        {
+            i++;
+            if ( i >= argc )
+            {
+                printUsage();
+            }
+            scenario = argv[i];
+        }
+        else if (!strcmp(argv[i], "-vmopt"))
+        {
+            i++;
+            if ( i >= argc )
+            {
+                printUsage();
+            }
+            numOptions++;
+        }
+        else
+        {
+            printUsage();
+        }
+    }
+
+    if ( !isSupportedSigScenario() || !isSupportedSigMode() )
+    {
+        printUsage();
+    }
+
+    // get signal number by it's name
+    signal_num = getSigNumBySigName(signal_name);
+    if (signal_num == -1)
+    {
+      printf("%s: unknown signal, perhaps is not supported on this platform, ignore\n",
+            signal_name);
+      exit(TEST_PASSED);
+    }
+
+    j = 0;
+    // Initialize given number of VM options
+    if (numOptions > 0)
+    {
+        options = (JavaVMOption *) malloc(numOptions * sizeof(JavaVMOption));
+        for (i=0; i= argc )
+                {
+                    printUsage();
+                }
+                options[j].optionString = argv[i];
+                j++;
+            }
+        }
+    }
+
+    // do signal invocation
+    printf("%s: start testing: signal_num=%d,  mode=%s, scenario=%s\n", signal_name, signal_num, mode, scenario);
+    run();
+
+    while (!sig_received) {
+      sleep(1);
+      printf("%s: waiting for getting signal 1sec ...\n", signal_name);
+    }
+
+    printf("%s: signal has been received\n", signal_name);
+
+    free(options);
+
+    return (sig_received ? TEST_PASSED : TEST_FAILED);
+}

From eff34e0937cae317a6c8f54bbf64128c4b8577ce Mon Sep 17 00:00:00 2001
From: rwestberg 
Date: Wed, 28 Mar 2018 15:30:43 +0200
Subject: [PATCH 036/196] 8199619: Building HotSpot on Windows should define
 NOMINMAX Reviewed-by: erikj, kbarrett, ihse

---
 make/autoconf/flags-cflags.m4 | 1 +
 1 file changed, 1 insertion(+)

diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4
index 8e8d0b5eb0c..8bdb3c76ad3 100644
--- a/make/autoconf/flags-cflags.m4
+++ b/make/autoconf/flags-cflags.m4
@@ -455,6 +455,7 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER],
   elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
     ALWAYS_DEFINES_JDK="-DWIN32_LEAN_AND_MEAN -D_CRT_SECURE_NO_DEPRECATE \
         -D_CRT_NONSTDC_NO_DEPRECATE -DWIN32 -DIAL"
+    ALWAYS_DEFINES_JVM="-DNOMINMAX"
   fi
 
   ###############################################################################

From c9ad5485818805f06737a96a2b389a262ec4ac46 Mon Sep 17 00:00:00 2001
From: tschatzl 
Date: Wed, 28 Mar 2018 16:39:32 +0200
Subject: [PATCH 037/196] 8197573: Remove concurrent cleanup and secondary free
 list handling Summary: Remove secondary free list and all associated
 functionality, moving the cleanup work into the Cleanup pause instead.
 Reviewed-by: sangheki, sjohanss

---
 .../concurrent_phase_control/TestConcurrentPhaseControlG1.java  | 2 --
 .../TestConcurrentPhaseControlG1Basics.java                     | 1 -
 2 files changed, 3 deletions(-)

diff --git a/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlG1.java b/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlG1.java
index 48c5b5212b5..e339f57fcab 100644
--- a/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlG1.java
+++ b/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlG1.java
@@ -54,8 +54,6 @@ public class TestConcurrentPhaseControlG1 {
         {"BEFORE_REMARK", null},
         {"REMARK", "Pause Remark"},
         {"REBUILD_REMEMBERED_SETS", "Concurrent Rebuild Remembered Sets"},
-        // "COMPLETE_CLEANUP",  -- optional phase, not reached by this test
-        {"CLEANUP_FOR_NEXT_MARK", "Concurrent Cleanup for Next Mark"},
         // Clear request
         {"IDLE", null},
         {"ANY", null},
diff --git a/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlG1Basics.java b/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlG1Basics.java
index 7b8d662579e..2adec2aacfa 100644
--- a/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlG1Basics.java
+++ b/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlG1Basics.java
@@ -54,7 +54,6 @@ public class TestConcurrentPhaseControlG1Basics {
         "BEFORE_REMARK",
         "REMARK",
         "REBUILD_REMEMBERED_SETS",
-        "COMPLETE_CLEANUP",
         "CLEANUP_FOR_NEXT_MARK",
     };
 

From a1e9dfc449b4adcd8ef51498dedf0f0e92972fee Mon Sep 17 00:00:00 2001
From: amenkov 
Date: Wed, 28 Mar 2018 12:10:24 -0700
Subject: [PATCH 038/196] 8198393: Instrumentation.retransformClasses() throws
 NullPointerException when handling a zero-length array Reviewed-by: sspitsyn,
 cjplummer

---
 .../sun/instrument/InstrumentationImpl.java   |  5 +-
 .../jvmti/RetransformClassesZeroLength.java   | 95 +++++++++++++++++++
 2 files changed, 99 insertions(+), 1 deletion(-)
 create mode 100644 test/hotspot/jtreg/serviceability/jvmti/RetransformClassesZeroLength.java

diff --git a/src/java.instrument/share/classes/sun/instrument/InstrumentationImpl.java b/src/java.instrument/share/classes/sun/instrument/InstrumentationImpl.java
index 5cf0c21361f..3241c086d90 100644
--- a/src/java.instrument/share/classes/sun/instrument/InstrumentationImpl.java
+++ b/src/java.instrument/share/classes/sun/instrument/InstrumentationImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -161,6 +161,9 @@ public boolean isModifiableModule(Module module) {
             throw new UnsupportedOperationException(
               "retransformClasses is not supported in this environment");
         }
+        if (classes.length == 0) {
+            return; // no-op
+        }
         retransformClasses0(mNativeAgent, classes);
     }
 
diff --git a/test/hotspot/jtreg/serviceability/jvmti/RetransformClassesZeroLength.java b/test/hotspot/jtreg/serviceability/jvmti/RetransformClassesZeroLength.java
new file mode 100644
index 00000000000..3d546556f1b
--- /dev/null
+++ b/test/hotspot/jtreg/serviceability/jvmti/RetransformClassesZeroLength.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2018, 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 8198393
+ * @summary Instrumentation.retransformClasses(new Class[0]) should be NOP
+ * @library /test/lib
+ * @modules java.instrument
+ * @compile RetransformClassesZeroLength.java
+ * @run main RetransformClassesZeroLength
+ */
+
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.lang.instrument.UnmodifiableClassException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.ProtectionDomain;
+
+import jdk.test.lib.process.ProcessTools;
+
+
+public class RetransformClassesZeroLength {
+
+    private static String manifest =
+            "Premain-Class: " + RetransformClassesZeroLength.Agent.class.getName() + "\n"
+            + "Can-Retransform-Classes: true\n";
+
+    private static String CP = System.getProperty("test.classes");
+
+    public static void main(String args[]) throws Throwable {
+        String agentJar = buildAgent();
+        ProcessTools.executeProcess(
+                ProcessTools.createJavaProcessBuilder(
+                        "-javaagent:" + agentJar,
+                        "-version")
+        ).shouldHaveExitValue(0);
+    }
+
+    private static String buildAgent() throws Exception {
+        Path jar = Files.createTempFile(Paths.get("."), null, ".jar");
+        String jarPath = jar.toAbsolutePath().toString();
+        ClassFileInstaller.writeJar(jarPath,
+                ClassFileInstaller.Manifest.fromString(manifest),
+                RetransformClassesZeroLength.class.getName());
+        return jarPath;
+    }
+
+
+    public static class Agent implements ClassFileTransformer {
+        public static void premain(String args, Instrumentation inst) {
+            inst.addTransformer(new NoOpTransformer());
+            try {
+                inst.retransformClasses(new Class[0]);
+            } catch (UnmodifiableClassException ex) {
+                throw new AssertionError(ex);
+            }
+        }
+    }
+
+    private static class NoOpTransformer implements ClassFileTransformer {
+        @Override
+        public byte[] transform(ClassLoader loader,
+                                String className,
+                                Class classBeingRedefined,
+                                ProtectionDomain protectionDomain,
+                                byte[] classfileBuffer
+                                ) throws IllegalClassFormatException {
+            return null;    // no transform
+        }
+    }
+}

From a2605d930175b316dfca5b9677ce0dd3273b04e9 Mon Sep 17 00:00:00 2001
From: lmesnik 
Date: Wed, 28 Mar 2018 13:38:08 -0700
Subject: [PATCH 039/196] 8200091: [TESTBUG] Update jittester for jdk11
 Reviewed-by: iignatyev

---
 test/hotspot/jtreg/testlibrary/jittester/Makefile | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/test/hotspot/jtreg/testlibrary/jittester/Makefile b/test/hotspot/jtreg/testlibrary/jittester/Makefile
index e4dd97cff23..a5786a50201 100644
--- a/test/hotspot/jtreg/testlibrary/jittester/Makefile
+++ b/test/hotspot/jtreg/testlibrary/jittester/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 2018, 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
@@ -69,7 +69,7 @@ DIST_DIR = dist
 DIST_JAR = $(DIST_DIR)/JITtester.jar
 
 SRC_FILES = $(shell find $(SRC_DIR) -name '*.java')
-TESTLIBRARY_SRC_DIR = ../../../../test/lib/jdk/test/lib
+TESTLIBRARY_SRC_DIR = ../../../../lib/jdk/test/lib
 TESTLIBRARY_SRC_FILES = $(TESTLIBRARY_SRC_DIR)/Asserts.java \
                         $(TESTLIBRARY_SRC_DIR)/JDKToolFinder.java \
                         $(TESTLIBRARY_SRC_DIR)/JDKToolLauncher.java \
@@ -125,13 +125,20 @@ copyaot: $(TESTBASE_DIR)/compiler/aot
 	@cp ../../compiler/aot/AotCompiler.java $(TESTBASE_DIR)/compiler/aot
 
 testgroup: $(TESTBASE_DIR)
-	@echo 'jittester_all = \\' > $(TESTGROUP_FILE)
+	@echo 'jittester_all = \' > $(TESTGROUP_FILE)
 	@echo '	/' >> $(TESTGROUP_FILE)
 	@echo '' >> $(TESTGROUP_FILE)
+	@echo 'jit_tests = \' >> $(TESTGROUP_FILE)
+	@echo ' java_tests \' >> $(TESTGROUP_FILE)
+	@echo ' bytecode_tests' >> $(TESTGROUP_FILE)
+	@echo '' >> $(TESTGROUP_FILE)
+	@echo 'aot_tests = \' >> $(TESTGROUP_FILE)
+	@echo ' aot_bytecode_tests \' >> $(TESTGROUP_FILE)
+	@echo ' aot_java_tests' >> $(TESTGROUP_FILE)
+	@echo '' >> $(TESTGROUP_FILE)
 
 testroot: $(TESTBASE_DIR)
 	@echo 'groups=TEST.groups' > $(TESTROOT_FILE)
 
 $(TESTBASE_DIR) $(DIST_DIR) $(TESTBASE_DIR)/jdk/test/lib/jittester/jtreg $(TESTBASE_DIR)/compiler/aot:
 	$(shell if [ ! -d $@ ]; then mkdir -p $@; fi)
-

From da2714aa56d980349c3d6b77ccacf346e1da7f29 Mon Sep 17 00:00:00 2001
From: lmesnik 
Date: Wed, 28 Mar 2018 13:25:15 -0700
Subject: [PATCH 040/196] 8200187: Exclude 3 long-running tests from tier1
 Reviewed-by: dholmes, cjplummer

---
 test/hotspot/jtreg/TEST.groups | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups
index abf48e48c3c..dc8afeb73e7 100644
--- a/test/hotspot/jtreg/TEST.groups
+++ b/test/hotspot/jtreg/TEST.groups
@@ -143,14 +143,15 @@ tier1_gc = \
   :tier1_gc_1 \
   :tier1_gc_2 \
   :tier1_gc_gcold \
-  :tier1_gc_gcbasher 
+  :tier1_gc_gcbasher
 
 hotspot_not_fast_gc = \
   :hotspot_gc \
   -:tier1_gc
 
 tier1_gc_1 = \
-  gc/g1/
+  gc/g1/ \
+  -gc/g1/ihop/TestIHOPErgo.java
 
 tier1_gc_2 = \
   sanity/ExecuteInternalVMTests.java \
@@ -243,7 +244,9 @@ tier1_runtime_appcds_exclude = \
 tier1_serviceability = \
   serviceability/dcmd/compiler \
   serviceability/logging \
-  serviceability/sa
+  serviceability/sa \
+  -serviceability/sa/ClhsdbScanOops.java \
+  -serviceability/sa/TestHeapDumpForLargeArray.java
 
 tier1 = \
   :tier1_common \
@@ -289,4 +292,3 @@ hotspot_rest_runtime = \
   -:tier1_runtime_appcds_exclude \
   -:hotspot_nmt \
   -:hotspot_tier2_runtime_platform_agnostic
-

From b977a0a10e81a2142ddacdbe7707b4b07b04d145 Mon Sep 17 00:00:00 2001
From: kvn 
Date: Wed, 28 Mar 2018 17:20:06 -0700
Subject: [PATCH 041/196] 8200383: Can't build on SPARC Hotspot with code which
 use math functions Summary: remove old hack which supports Solaris 8 and 9
 Reviewed-by: erikj, ihse

---
 make/autoconf/libraries.m4  | 12 +-----------
 make/lib/Awt2dLibraries.gmk |  6 +-----
 2 files changed, 2 insertions(+), 16 deletions(-)

diff --git a/make/autoconf/libraries.m4 b/make/autoconf/libraries.m4
index c40a55589be..1d33778e2ad 100644
--- a/make/autoconf/libraries.m4
+++ b/make/autoconf/libraries.m4
@@ -114,17 +114,7 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES],
   fi
 
   # Math library
-  if test "x$OPENJDK_TARGET_OS" != xsolaris; then
-    BASIC_JVM_LIBS="$LIBM"
-  else
-    # FIXME: This hard-coded path is not really proper.
-    if test "x$OPENJDK_TARGET_CPU" = xx86_64; then
-      BASIC_SOLARIS_LIBM_LIBS="/usr/lib/amd64/libm.so.1"
-    elif test "x$OPENJDK_TARGET_CPU" = xsparcv9; then
-      BASIC_SOLARIS_LIBM_LIBS="/usr/lib/sparcv9/libm.so.1"
-    fi
-    BASIC_JVM_LIBS="$BASIC_SOLARIS_LIBM_LIBS"
-  fi
+  BASIC_JVM_LIBS="$LIBM"
 
   # Dynamic loading library
   if test "x$OPENJDK_TARGET_OS" = xlinux || test "x$OPENJDK_TARGET_OS" = xsolaris || test "x$OPENJDK_TARGET_OS" = xaix; then
diff --git a/make/lib/Awt2dLibraries.gmk b/make/lib/Awt2dLibraries.gmk
index e77c5f2a34e..f2d14e5de08 100644
--- a/make/lib/Awt2dLibraries.gmk
+++ b/make/lib/Awt2dLibraries.gmk
@@ -409,11 +409,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBLCMS, \
     LDFLAGS := $(LDFLAGS_JDKLIB) \
         $(call SET_SHARED_LIBRARY_ORIGIN), \
     LDFLAGS_unix := -L$(INSTALL_LIBRARIES_HERE), \
-    LDFLAGS_solaris := /usr/lib$(OPENJDK_TARGET_CPU_ISADIR)/libm.so.2, \
-    LIBS_unix := -lawt -ljvm -ljava $(LCMS_LIBS), \
-    LIBS_linux := $(LIBM), \
-    LIBS_macosx := $(LIBM), \
-    LIBS_aix := $(LIBM),\
+    LIBS_unix := -lawt -ljvm -ljava $(LCMS_LIBS) $(LIBM), \
     LIBS_windows := $(WIN_AWT_LIB) $(WIN_JAVA_LIB), \
 ))
 

From c7aa4f20655364f460b77326e06b35fb3485d121 Mon Sep 17 00:00:00 2001
From: redestad 
Date: Thu, 29 Mar 2018 10:38:29 +0200
Subject: [PATCH 042/196] 8200238: Reduce number of exceptions created when
 calling MemberName$Factory::resolveOrNull Reviewed-by: lfoltan, acorn,
 dholmes

---
 .../share/classes/java/lang/invoke/MemberName.java | 14 +++++++++-----
 .../java/lang/invoke/MethodHandleNatives.java      |  3 ++-
 2 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/src/java.base/share/classes/java/lang/invoke/MemberName.java b/src/java.base/share/classes/java/lang/invoke/MemberName.java
index 8471adea570..ed25dca7c81 100644
--- a/src/java.base/share/classes/java/lang/invoke/MemberName.java
+++ b/src/java.base/share/classes/java/lang/invoke/MemberName.java
@@ -1047,7 +1047,8 @@ List getMembers(Class defc,
          *  If lookup fails or access is not permitted, null is returned.
          *  Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
          */
-        private MemberName resolve(byte refKind, MemberName ref, Class lookupClass) {
+        private MemberName resolve(byte refKind, MemberName ref, Class lookupClass,
+                                   boolean speculativeResolve) {
             MemberName m = ref.clone();  // JVM will side-effect the ref
             assert(refKind == m.getReferenceKind());
             try {
@@ -1066,7 +1067,10 @@ private MemberName resolve(byte refKind, MemberName ref, Class lookupClass) {
                 //
                 // REFC view on PTYPES doesn't matter, since it is used only as a starting point for resolution and doesn't
                 // participate in method selection.
-                m = MethodHandleNatives.resolve(m, lookupClass);
+                m = MethodHandleNatives.resolve(m, lookupClass, speculativeResolve);
+                if (m == null && speculativeResolve) {
+                    return null;
+                }
                 m.checkForTypeAlias(m.getDeclaringClass());
                 m.resolution = null;
             } catch (ClassNotFoundException | LinkageError ex) {
@@ -1091,7 +1095,7 @@ private MemberName resolve(byte refKind, MemberName ref, Class lookupClass) {
         MemberName resolveOrFail(byte refKind, MemberName m, Class lookupClass,
                                  Class nsmClass)
                 throws IllegalAccessException, NoSuchMemberException {
-            MemberName result = resolve(refKind, m, lookupClass);
+            MemberName result = resolve(refKind, m, lookupClass, false);
             if (result.isResolved())
                 return result;
             ReflectiveOperationException ex = result.makeAccessException();
@@ -1106,8 +1110,8 @@ MemberName resolveOrFail(byte refKind, MemberName m, Class lookupClass,
          */
         public
         MemberName resolveOrNull(byte refKind, MemberName m, Class lookupClass) {
-            MemberName result = resolve(refKind, m, lookupClass);
-            if (result.isResolved())
+            MemberName result = resolve(refKind, m, lookupClass, true);
+            if (result != null && result.isResolved())
                 return result;
             return null;
         }
diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java
index c288f6d7a57..3e872414b6c 100644
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java
@@ -49,7 +49,8 @@ private MethodHandleNatives() { } // static only
 
     static native void init(MemberName self, Object ref);
     static native void expand(MemberName self);
-    static native MemberName resolve(MemberName self, Class caller) throws LinkageError, ClassNotFoundException;
+    static native MemberName resolve(MemberName self, Class caller,
+            boolean speculativeResolve) throws LinkageError, ClassNotFoundException;
     static native int getMembers(Class defc, String matchName, String matchSig,
             int matchFlags, Class caller, int skip, MemberName[] results);
 

From 7b2082b4840f25858fc4311a76db6c697e8b4231 Mon Sep 17 00:00:00 2001
From: simonis 
Date: Thu, 29 Mar 2018 14:50:25 +0200
Subject: [PATCH 043/196] 8200360: MeetIncompatibleInterfaceArrays fails with
 "MeetIncompatibleInterfaceArrays0ASM.run() must be compiled at tier 0 !"
 Reviewed-by: kvn, thartmann

---
 .../types/TestMeetIncompatibleInterfaceArrays.java         | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/test/hotspot/jtreg/compiler/types/TestMeetIncompatibleInterfaceArrays.java b/test/hotspot/jtreg/compiler/types/TestMeetIncompatibleInterfaceArrays.java
index 8df5b0e4832..dd01fba95e6 100644
--- a/test/hotspot/jtreg/compiler/types/TestMeetIncompatibleInterfaceArrays.java
+++ b/test/hotspot/jtreg/compiler/types/TestMeetIncompatibleInterfaceArrays.java
@@ -38,6 +38,7 @@
  *        -XX:+WhiteBoxAPI
  *        -Xbatch
  *        -XX:-TieredCompilation
+ *        -XX:TieredStopAtLevel=4
  *        -XX:CICompilerCount=1
  *        -XX:+PrintCompilation
  *        -XX:+PrintInlining
@@ -51,6 +52,7 @@
  *        -XX:+WhiteBoxAPI
  *        -Xbatch
  *        -XX:-TieredCompilation
+ *        -XX:TieredStopAtLevel=4
  *        -XX:CICompilerCount=1
  *        -XX:+PrintCompilation
  *        -XX:+PrintInlining
@@ -63,6 +65,8 @@
  *        -XX:+UnlockDiagnosticVMOptions
  *        -XX:+WhiteBoxAPI
  *        -Xbatch
+ *        -XX:+TieredCompilation
+ *        -XX:TieredStopAtLevel=4
  *        -XX:CICompilerCount=2
  *        -XX:+PrintCompilation
  *        -XX:+PrintInlining
@@ -379,7 +383,8 @@ public static void main(String[] args) throws Exception {
                                        r.getName() + "() was compiled at tier " + r_comp_level + "]");
 
                     if (r_comp_level != level[pass][j]) {
-                      throw new Exception("Method " + r + " must be compiled at tier " + r_comp_level + " !");
+                      throw new Exception("Method " + r + " must be compiled at tier " + level[pass][j] +
+                                          " but was compiled at " + r_comp_level + " instead!");
                     }
 
                     WB.deoptimizeMethod(r);

From d2c8b8af55a5c5bd9435eb335d84f714abf81fa8 Mon Sep 17 00:00:00 2001
From: kvn 
Date: Thu, 29 Mar 2018 09:52:53 -0700
Subject: [PATCH 044/196] 8200391: clean up test/hotspot/jtreg/ProblemList.txt
 (compiler related) Reviewed-by: mseledtsov

---
 test/hotspot/jtreg/ProblemList-graal.txt | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/test/hotspot/jtreg/ProblemList-graal.txt b/test/hotspot/jtreg/ProblemList-graal.txt
index 469144946c1..4de9eb0503d 100644
--- a/test/hotspot/jtreg/ProblemList-graal.txt
+++ b/test/hotspot/jtreg/ProblemList-graal.txt
@@ -47,10 +47,6 @@ compiler/jvmci/SecurityRestrictionsTest.java                    8181837   generi
 compiler/jvmci/TestValidateModules.java                         8194942   generic-all
 gc/arguments/TestVerifyBeforeAndAfterGCFlags.java               8194942   generic-all
 
-compiler/rangechecks/TestRangeCheckSmearing.java                8195632   generic-all
-compiler/uncommontrap/Test8009761.java                          8195632   generic-all
-compiler/whitebox/ForceNMethodSweepTest.java                    8195632   generic-all
-
 compiler/unsafe/UnsafeGetConstantField.java                     8181833   generic-all
 compiler/unsafe/UnsafeGetStableArrayElement.java                8181833   generic-all
 compiler/unsafe/UnsafeOffHeapBooleanTest.java                   8181833   generic-all
@@ -70,12 +66,10 @@ gc/g1/plab/TestPLABResize.java                                  8191048   generi
 
 gc/TestNUMAPageSize.java                                        8194949   generic-all
 
-runtime/appcds/UseAppCDS.java                                   8196626   generic-all
-
 runtime/ReservedStack/ReservedStackTestCompiler.java            8181855   generic-all
 
 serviceability/jvmti/GetModulesInfo/JvmtiGetAllModulesTest.java 8195156   generic-all
 
-compiler/compilercontrol/directives/LogTest.java                8197446   generic-all
+compiler/compilercontrol/directives/LogTest.java                8181753   generic-all
 
 gc/g1/ihop/TestIHOPStatic.java                                  8199486   generic-all

From bca1d40d8c533d055daac3624b3f890ef9cc7b34 Mon Sep 17 00:00:00 2001
From: iklam 
Date: Thu, 29 Mar 2018 20:15:23 -0700
Subject: [PATCH 045/196] 8183238: Obsolete CheckEndorsedAndExtDirs and remove
 checks for lib/endorsed and lib/ext Reviewed-by: dholmes, mchung, alanb

---
 src/bsd/doc/man/java.1              | 61 +----------------------------
 src/linux/doc/man/java.1            | 61 +----------------------------
 src/solaris/doc/sun/man/man1/java.1 | 61 +----------------------------
 3 files changed, 3 insertions(+), 180 deletions(-)

diff --git a/src/bsd/doc/man/java.1 b/src/bsd/doc/man/java.1
index 4615bad506a..b75bcf1a6e2 100644
--- a/src/bsd/doc/man/java.1
+++ b/src/bsd/doc/man/java.1
@@ -1,5 +1,5 @@
 '\" t
-.\" Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved.
+.\" Copyright (c) 1994, 2018, 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
@@ -1178,65 +1178,6 @@ Verify all classes\&.
 .PP
 These options control the runtime behavior of the Java HotSpot VM\&.
 .PP
-\-XX:+CheckEndorsedAndExtDirs
-.RS 4
-Enables the option to prevent the
-\fBjava\fR
-command from running a Java application if it uses the endorsed\-standards override mechanism or the extension mechanism\&. This option checks if an application is using one of these mechanisms by checking the following:
-.sp
-.RS 4
-.ie n \{\
-\h'-04'\(bu\h'+03'\c
-.\}
-.el \{\
-.sp -1
-.IP \(bu 2.3
-.\}
-The
-\fBjava\&.ext\&.dirs\fR
-or
-\fBjava\&.endorsed\&.dirs\fR
-system property is set\&.
-.RE
-.sp
-.RS 4
-.ie n \{\
-\h'-04'\(bu\h'+03'\c
-.\}
-.el \{\
-.sp -1
-.IP \(bu 2.3
-.\}
-The
-\fBlib/endorsed\fR
-directory exists and is not empty\&.
-.RE
-.sp
-.RS 4
-.ie n \{\
-\h'-04'\(bu\h'+03'\c
-.\}
-.el \{\
-.sp -1
-.IP \(bu 2.3
-.\}
-The
-\fBlib/ext\fR
-directory contains any JAR files other than those of the JDK\&.
-.RE
-.sp
-.RS 4
-.ie n \{\
-\h'-04'\(bu\h'+03'\c
-.\}
-.el \{\
-.sp -1
-.IP \(bu 2.3
-.\}
-The system\-wide platform\-specific extension directory contains any JAR files\&.
-.RE
-.RE
-.PP
 \-XX:+DisableAttachMechanism
 .RS 4
 Enables the option that disables the mechanism that lets tools attach to the JVM\&. By default, this option is disabled, meaning that the attach mechanism is enabled and you can use tools such as
diff --git a/src/linux/doc/man/java.1 b/src/linux/doc/man/java.1
index afa5693cf7d..bec6bf80210 100644
--- a/src/linux/doc/man/java.1
+++ b/src/linux/doc/man/java.1
@@ -1,5 +1,5 @@
 '\" t
-.\" Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved.
+.\" Copyright (c) 1994, 2018, 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
@@ -1173,65 +1173,6 @@ Verify all classes\&.
 .PP
 These options control the runtime behavior of the Java HotSpot VM\&.
 .PP
-\-XX:+CheckEndorsedAndExtDirs
-.RS 4
-Enables the option to prevent the
-\fBjava\fR
-command from running a Java application if it uses the endorsed\-standards override mechanism or the extension mechanism\&. This option checks if an application is using one of these mechanisms by checking the following:
-.sp
-.RS 4
-.ie n \{\
-\h'-04'\(bu\h'+03'\c
-.\}
-.el \{\
-.sp -1
-.IP \(bu 2.3
-.\}
-The
-\fBjava\&.ext\&.dirs\fR
-or
-\fBjava\&.endorsed\&.dirs\fR
-system property is set\&.
-.RE
-.sp
-.RS 4
-.ie n \{\
-\h'-04'\(bu\h'+03'\c
-.\}
-.el \{\
-.sp -1
-.IP \(bu 2.3
-.\}
-The
-\fBlib/endorsed\fR
-directory exists and is not empty\&.
-.RE
-.sp
-.RS 4
-.ie n \{\
-\h'-04'\(bu\h'+03'\c
-.\}
-.el \{\
-.sp -1
-.IP \(bu 2.3
-.\}
-The
-\fBlib/ext\fR
-directory contains any JAR files other than those of the JDK\&.
-.RE
-.sp
-.RS 4
-.ie n \{\
-\h'-04'\(bu\h'+03'\c
-.\}
-.el \{\
-.sp -1
-.IP \(bu 2.3
-.\}
-The system\-wide platform\-specific extension directory contains any JAR files\&.
-.RE
-.RE
-.PP
 \-XX:+DisableAttachMechanism
 .RS 4
 Enables the option that disables the mechanism that lets tools attach to the JVM\&. By default, this option is disabled, meaning that the attach mechanism is enabled and you can use tools such as
diff --git a/src/solaris/doc/sun/man/man1/java.1 b/src/solaris/doc/sun/man/man1/java.1
index afa5693cf7d..bec6bf80210 100644
--- a/src/solaris/doc/sun/man/man1/java.1
+++ b/src/solaris/doc/sun/man/man1/java.1
@@ -1,5 +1,5 @@
 '\" t
-.\" Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved.
+.\" Copyright (c) 1994, 2018, 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
@@ -1173,65 +1173,6 @@ Verify all classes\&.
 .PP
 These options control the runtime behavior of the Java HotSpot VM\&.
 .PP
-\-XX:+CheckEndorsedAndExtDirs
-.RS 4
-Enables the option to prevent the
-\fBjava\fR
-command from running a Java application if it uses the endorsed\-standards override mechanism or the extension mechanism\&. This option checks if an application is using one of these mechanisms by checking the following:
-.sp
-.RS 4
-.ie n \{\
-\h'-04'\(bu\h'+03'\c
-.\}
-.el \{\
-.sp -1
-.IP \(bu 2.3
-.\}
-The
-\fBjava\&.ext\&.dirs\fR
-or
-\fBjava\&.endorsed\&.dirs\fR
-system property is set\&.
-.RE
-.sp
-.RS 4
-.ie n \{\
-\h'-04'\(bu\h'+03'\c
-.\}
-.el \{\
-.sp -1
-.IP \(bu 2.3
-.\}
-The
-\fBlib/endorsed\fR
-directory exists and is not empty\&.
-.RE
-.sp
-.RS 4
-.ie n \{\
-\h'-04'\(bu\h'+03'\c
-.\}
-.el \{\
-.sp -1
-.IP \(bu 2.3
-.\}
-The
-\fBlib/ext\fR
-directory contains any JAR files other than those of the JDK\&.
-.RE
-.sp
-.RS 4
-.ie n \{\
-\h'-04'\(bu\h'+03'\c
-.\}
-.el \{\
-.sp -1
-.IP \(bu 2.3
-.\}
-The system\-wide platform\-specific extension directory contains any JAR files\&.
-.RE
-.RE
-.PP
 \-XX:+DisableAttachMechanism
 .RS 4
 Enables the option that disables the mechanism that lets tools attach to the JVM\&. By default, this option is disabled, meaning that the attach mechanism is enabled and you can use tools such as

From 7a19dda33fcbf4c6de6d064d97269a12023528b4 Mon Sep 17 00:00:00 2001
From: ccheung 
Date: Thu, 29 Mar 2018 21:48:38 -0700
Subject: [PATCH 046/196] 8200078: [Graal]
 runtime/appcds/GraalWithLimitedMetaspace.java crashes in visit_all_interfaces
 Summary: stop CDS dumping right away when an OOM due to insufficient
 metaspace is encountered Reviewed-by: iklam, mseledtsov

---
 .../runtime/SharedArchiveFile/MaxMetaspaceSize.java  |  6 +++---
 .../runtime/appcds/GraalWithLimitedMetaspace.java    | 12 +++++++++---
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/test/hotspot/jtreg/runtime/SharedArchiveFile/MaxMetaspaceSize.java b/test/hotspot/jtreg/runtime/SharedArchiveFile/MaxMetaspaceSize.java
index f8799b3843d..020c3219c64 100644
--- a/test/hotspot/jtreg/runtime/SharedArchiveFile/MaxMetaspaceSize.java
+++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/MaxMetaspaceSize.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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,7 +24,7 @@
 /**
  * @test
  * @requires vm.cds
- * @bug 8067187
+ * @bug 8067187 8200078
  * @summary Testing CDS dumping with the -XX:MaxMetaspaceSize= option
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
@@ -50,7 +50,7 @@ public static void main(String[] args) throws Exception {
       processArgs.add("-XX:MaxMetaspaceSize=1m");
     }
 
-    String msg = "OutOfMemoryError: Metaspace";
+    String msg = "Failed allocating metaspace object";
     ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(processArgs.toArray(new String[0]));
     CDSTestUtils.executeAndLog(pb, "dump").shouldContain(msg).shouldHaveExitValue(1);
   }
diff --git a/test/hotspot/jtreg/runtime/appcds/GraalWithLimitedMetaspace.java b/test/hotspot/jtreg/runtime/appcds/GraalWithLimitedMetaspace.java
index 91d8aa8ec9d..1cc230f33fa 100644
--- a/test/hotspot/jtreg/runtime/appcds/GraalWithLimitedMetaspace.java
+++ b/test/hotspot/jtreg/runtime/appcds/GraalWithLimitedMetaspace.java
@@ -125,8 +125,14 @@ static void dumpArchive() throws Exception {
             "-XX:MetaspaceSize=12M",
             "-XX:MaxMetaspaceSize=12M"));
 
-        OutputAnalyzer output = TestCommon.executeAndLog(pb, "dump-archive")
-            .shouldHaveExitValue(1)
-            .shouldContain("Failed allocating metaspace object type");
+        OutputAnalyzer output = TestCommon.executeAndLog(pb, "dump-archive");
+        int exitValue = output.getExitValue();
+        if (exitValue == 1) {
+            output.shouldContain("Failed allocating metaspace object type");
+        } else if (exitValue == 0) {
+            output.shouldContain("Loading classes to share");
+        } else {
+            throw new RuntimeException("Unexpected exit value " + exitValue);
+        }
     }
 }

From 453f0650fe1efd83d219e2457940beab678c383f Mon Sep 17 00:00:00 2001
From: stuefe 
Date: Fri, 30 Mar 2018 06:31:16 +0200
Subject: [PATCH 047/196] 8191101: Show register content in hs-err file on
 assert Reviewed-by: adinn, clanger, simonis

---
 .../ShowRegistersOnAssertTest.java            | 91 +++++++++++++++++++
 1 file changed, 91 insertions(+)
 create mode 100644 test/hotspot/jtreg/runtime/ErrorHandling/ShowRegistersOnAssertTest.java

diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/ShowRegistersOnAssertTest.java b/test/hotspot/jtreg/runtime/ErrorHandling/ShowRegistersOnAssertTest.java
new file mode 100644
index 00000000000..732729f8ed4
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/ErrorHandling/ShowRegistersOnAssertTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2018, 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 8191101
+ * @summary Show Registers on assert/guarantee
+ * @library /test/lib
+ * @requires (vm.debug == true) & (os.family == "linux")
+ * @author Thomas Stuefe (SAP)
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ */
+
+// Note: this test can only run on debug since it relies on VMError::controlled_crash() which
+// only exists in debug builds.
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.util.regex.Pattern;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.Platform;
+import jdk.test.lib.process.ProcessTools;
+
+public class ShowRegistersOnAssertTest {
+
+    private static void do_test(boolean do_assert, // true - assert, false - guarantee
+        boolean suppress_assert,
+        boolean show_registers_on_assert) throws Exception
+    {
+        System.out.println("Testing " + (suppress_assert ? "suppressed" : "normal") + " " + (do_assert ? "assert" : "guarantee") +
+                           " with " + (show_registers_on_assert ? "-XX:+ShowRegistersOnAssert" : "-XX:-ShowRegistersOnAssert") + "...");
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+            "-XX:+UnlockDiagnosticVMOptions", "-Xmx100M", "-XX:-CreateCoredumpOnCrash",
+            "-XX:ErrorHandlerTest=" + (do_assert ? "1" : "3"),
+            (suppress_assert ? "-XX:SuppressErrorAt=/vmError.cpp" : ""),
+            (show_registers_on_assert ? "-XX:+ShowRegistersOnAssert" : "-XX:-ShowRegistersOnAssert"),
+            "-version");
+
+        OutputAnalyzer output_detail = new OutputAnalyzer(pb.start());
+
+        if (suppress_assert) {
+            // we should have not have crashed. See VMError::controlled_crash().
+            output_detail.shouldMatch(".*survived intentional crash.*");
+        } else {
+            // we should have crashed with an internal error. We should definitly NOT have crashed with a segfault
+            // (which would be a sign that the assert poison page mechanism does not work).
+            output_detail.shouldMatch("# A fatal error has been detected by the Java Runtime Environment:.*");
+            output_detail.shouldMatch("# +Internal Error.*");
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        // Note: for now, this is only a regression test testing that the addition of ShowRegistersOnAssert does
+        // not break normal assert/guarantee handling. The feature is not implemented on all platforms and really testing
+        // it requires more effort.
+        do_test(false, false, false);
+        do_test(false, false, true);
+        do_test(false, true, false);
+        do_test(false, true, true);
+        do_test(true, false, false);
+        do_test(true, false, true);
+        do_test(true, true, false);
+        do_test(true, true, true);
+    }
+
+}
+

From 69dfd0f3dc12e6a1eb7e8bed51c133207565098c Mon Sep 17 00:00:00 2001
From: kvn 
Date: Fri, 30 Mar 2018 07:47:20 -0700
Subject: [PATCH 048/196] 8200461: MeetIncompatibleInterfaceArrays test fails
 with -Xcomp Summary: Add requires to run test only in Xmixed mode.
 Reviewed-by: simonis

---
 .../compiler/types/TestMeetIncompatibleInterfaceArrays.java      | 1 +
 1 file changed, 1 insertion(+)

diff --git a/test/hotspot/jtreg/compiler/types/TestMeetIncompatibleInterfaceArrays.java b/test/hotspot/jtreg/compiler/types/TestMeetIncompatibleInterfaceArrays.java
index dd01fba95e6..f64253db950 100644
--- a/test/hotspot/jtreg/compiler/types/TestMeetIncompatibleInterfaceArrays.java
+++ b/test/hotspot/jtreg/compiler/types/TestMeetIncompatibleInterfaceArrays.java
@@ -25,6 +25,7 @@
  * @test
  * @bug 8141551
  * @summary C2 can not handle returns with inccompatible interface arrays
+ * @requires vm.compMode == "Xmixed" & vm.flavor == "server"
  * @modules java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.misc
  * @library /test/lib /

From 3eb39e1c02389f641708bdf4872495b4de443fce Mon Sep 17 00:00:00 2001
From: serb 
Date: Fri, 30 Mar 2018 13:57:19 -0700
Subject: [PATCH 049/196] 8198335:
 java/awt/FullScreen/UninitializedDisplayModeChangeTest/UninitializedDisplayModeChangeTest.java
 fails in headless mode Reviewed-by: prr

---
 .../classes/sun/awt/windows/WToolkit.java       | 17 ++++++++++-------
 test/jdk/ProblemList.txt                        |  1 -
 .../UninitializedDisplayModeChangeTest.java     |  3 ++-
 3 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java b/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java
index 82ea9d709b9..812ea7a2985 100644
--- a/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java
+++ b/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2018, 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,6 +47,7 @@
 import sun.awt.AWTAutoShutdown;
 import sun.awt.AWTPermissions;
 import sun.awt.AppContext;
+import sun.awt.DisplayChangedListener;
 import sun.awt.LightweightFrame;
 import sun.awt.SunToolkit;
 import sun.awt.util.ThreadGroupUtils;
@@ -802,9 +803,10 @@ public Dimension getBestCursorSize(int preferredWidth, int preferredHeight) {
     public native int getMaximumCursorColors();
 
     static void paletteChanged() {
-        ((Win32GraphicsEnvironment)GraphicsEnvironment
-        .getLocalGraphicsEnvironment())
-        .paletteChanged();
+        Object lge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+        if (lge instanceof DisplayChangedListener) {
+            ((DisplayChangedListener) lge).paletteChanged();
+        }
     }
 
     /*
@@ -816,9 +818,10 @@ public static void displayChanged() {
         EventQueue.invokeLater(new Runnable() {
             @Override
             public void run() {
-                ((Win32GraphicsEnvironment)GraphicsEnvironment
-                .getLocalGraphicsEnvironment())
-                .displayChanged();
+                Object lge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+                if (lge instanceof DisplayChangedListener) {
+                    ((DisplayChangedListener) lge).displayChanged();
+                }
             }
         });
     }
diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt
index 94c3610b7b3..4b8039d098f 100644
--- a/test/jdk/ProblemList.txt
+++ b/test/jdk/ProblemList.txt
@@ -171,7 +171,6 @@ java/awt/LightweightComponent/LightweightEventTest/LightweightEventTest.java 815
 java/awt/EventDispatchThread/HandleExceptionOnEDT/HandleExceptionOnEDT.java 6990210 generic-all
 java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.html 4931413 windows-all
 java/awt/FullScreen/FullScreenInsets/FullScreenInsets.java 7019055 windows-all
-java/awt/FullScreen/UninitializedDisplayModeChangeTest/UninitializedDisplayModeChangeTest.java 8198335 windows-all
 java/awt/Focus/8013611/JDK8013611.java 8175366 windows-all,macosx-all
 java/awt/Focus/6378278/InputVerifierTest.java 8198616 macosx-all
 java/awt/Focus/6382144/EndlessLoopTest.java 8198617 macosx-all
diff --git a/test/jdk/java/awt/FullScreen/UninitializedDisplayModeChangeTest/UninitializedDisplayModeChangeTest.java b/test/jdk/java/awt/FullScreen/UninitializedDisplayModeChangeTest/UninitializedDisplayModeChangeTest.java
index 11b0b941b6c..c9ee4991421 100644
--- a/test/jdk/java/awt/FullScreen/UninitializedDisplayModeChangeTest/UninitializedDisplayModeChangeTest.java
+++ b/test/jdk/java/awt/FullScreen/UninitializedDisplayModeChangeTest/UninitializedDisplayModeChangeTest.java
@@ -23,12 +23,13 @@
 
 /**
  * @test
- * @bug 6358034 6568560 8198613
+ * @bug 6358034 6568560 8198613 8198335
  * @key headful
  * @summary Tests that no exception is thrown when display mode is changed
  *          externally
  * @compile UninitializedDisplayModeChangeTest.java DisplayModeChanger.java
  * @run main/othervm UninitializedDisplayModeChangeTest
+ * @run main/othervm -Djava.awt.headless=true UninitializedDisplayModeChangeTest
  */
 
 import java.awt.EventQueue;

From 7acc5d00510697e1b39d6ad949c66affc3410d79 Mon Sep 17 00:00:00 2001
From: kaddepalli 
Date: Mon, 2 Apr 2018 16:52:11 +0530
Subject: [PATCH 050/196] 8200525: test
 java/awt/event/SequencedEvent/SequencedEventTest.java fails to compile
 Reviewed-by: prr, serb

---
 .../java/awt/event/SequencedEvent/SequencedEventTest.java | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/test/jdk/java/awt/event/SequencedEvent/SequencedEventTest.java b/test/jdk/java/awt/event/SequencedEvent/SequencedEventTest.java
index 12e849f074e..b8df72e187c 100644
--- a/test/jdk/java/awt/event/SequencedEvent/SequencedEventTest.java
+++ b/test/jdk/java/awt/event/SequencedEvent/SequencedEventTest.java
@@ -25,7 +25,8 @@
  * @test
  * @bug 8152974
  * @key headful
- * @summary AWT hang occurrs when sequenced events arrive out of sequence
+ * @modules java.desktop/sun.awt
+ * @summary AWT hang occurs when sequenced events arrive out of sequence
  * @run main SequencedEventTest
  */
 import sun.awt.AppContext;
@@ -84,7 +85,8 @@ public static void main(String[] args) throws Exception {
                     peekEvent(java.awt.event.FocusEvent.FOCUS_LAST + 1);
 
             if (ev != null)
-                throw new RuntimeException("Test case failed!");
+                throw new RuntimeException("Test case failed, since all the sequenced events" +
+                "are not flushed!" + ev);
         } catch (InterruptedException e) {
             throw new RuntimeException("Test case failed." + e.getMessage());
         }
@@ -163,7 +165,7 @@ private AWTEvent getSequencedEvent()
              */
             Class seqClass = (Class) Class.forName("java.awt.SequencedEvent");
             Constructor seqConst = seqClass.getConstructor(AWTEvent.class);
-            seqConst.setAccessible(true);;
+            seqConst.setAccessible(true);
             return seqConst.newInstance(wrapMe);
         } catch (Throwable err) {
             throw new RuntimeException("Unable to instantiate SequencedEvent",err);

From fefcc5244858822a7f643bbf65a7192f4a385cd9 Mon Sep 17 00:00:00 2001
From: kaddepalli 
Date: Mon, 2 Apr 2018 16:56:58 +0530
Subject: [PATCH 051/196] 8200343: Minor JViewport documentation typo
 Reviewed-by: serb, pkbalakr

---
 src/java.desktop/share/classes/javax/swing/JViewport.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/java.desktop/share/classes/javax/swing/JViewport.java b/src/java.desktop/share/classes/javax/swing/JViewport.java
index 44576585435..3fb3b6d76ec 100644
--- a/src/java.desktop/share/classes/javax/swing/JViewport.java
+++ b/src/java.desktop/share/classes/javax/swing/JViewport.java
@@ -61,7 +61,7 @@
  * 

* NOTE:We have implemented a faster scrolling algorithm that * does not require a buffer to draw in. The algorithm works as follows: - *

  1. The view and parent view and checked to see if they are + *
    1. The view and parent view are checked to see if they are * JComponents, * if they aren't, stop and repaint the whole viewport. *
    2. If the viewport is obscured by an ancestor, stop and repaint the whole From 3e9764ae7d145637489b1fc509c6658e38d488e3 Mon Sep 17 00:00:00 2001 From: iignatyev Date: Tue, 3 Apr 2018 10:01:04 -0700 Subject: [PATCH 052/196] 8200538: cl : Command line warning D9014 : invalid value '2220' for '/wd' Reviewed-by: ihse --- make/lib/Awt2dLibraries.gmk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/lib/Awt2dLibraries.gmk b/make/lib/Awt2dLibraries.gmk index b5391fd2643..5edc62a8ff2 100644 --- a/make/lib/Awt2dLibraries.gmk +++ b/make/lib/Awt2dLibraries.gmk @@ -543,7 +543,7 @@ else DISABLED_WARNINGS_solstudio := \ E_STATEMENT_NOT_REACHED \ E_END_OF_LOOP_CODE_NOT_REACHED, \ - DISABLED_WARNINGS_microsoft := 4267 2220 4244, \ + DISABLED_WARNINGS_microsoft := 4267 4244, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ )) From 6e2a4c163c6f701b269ba876ba8b9268dfdd6873 Mon Sep 17 00:00:00 2001 From: ihse Date: Tue, 3 Apr 2018 21:50:35 +0200 Subject: [PATCH 053/196] 8200267: a.out created at top dir by Solaris build Reviewed-by: erikj --- make/autoconf/toolchain.m4 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/make/autoconf/toolchain.m4 b/make/autoconf/toolchain.m4 index ea03071f3e3..a95759f4768 100644 --- a/make/autoconf/toolchain.m4 +++ b/make/autoconf/toolchain.m4 @@ -597,8 +597,9 @@ AC_DEFUN([TOOLCHAIN_EXTRACT_LD_VERSION], # solstudio cc requires us to have an existing file to pass as argument, # but it need not be a syntactically correct C file, so just use - # ourself. :) - LINKER_VERSION_STRING=`$LD -Wl,-V $TOPDIR/configure 2>&1 | $HEAD -n 1 | $SED -e 's/ld: //'` + # ourself. :) The intermediate 'cat' is needed to stop ld from leaving + # a lingering a.out (!). + LINKER_VERSION_STRING=`$LD -Wl,-V $TOPDIR/configure 2>&1 | $CAT | $HEAD -n 1 | $SED -e 's/ld: //'` # Extract version number [ LINKER_VERSION_NUMBER=`$ECHO $LINKER_VERSION_STRING | \ $SED -e 's/.* \([0-9][0-9]*\.[0-9][0-9]*\)-\([0-9][0-9]*\.[0-9][0-9]*\)/\1.\2/'` ] From 8556dda8dab87231884fb52615b7fab6a6ece76e Mon Sep 17 00:00:00 2001 From: rfield Date: Tue, 3 Apr 2018 13:27:58 -0700 Subject: [PATCH 054/196] 8198801: JShell: user exception chained cause not retained Reviewed-by: jlahoda --- .../jdk/internal/jshell/tool/JShellTool.java | 83 +++++++--- .../jshell/tool/resources/l10n.properties | 5 + .../share/classes/jdk/jshell/Eval.java | 38 ++++- .../classes/jdk/jshell/EvalException.java | 25 ++- .../classes/jdk/jshell/JShellException.java | 6 +- .../jshell/UnresolvedReferenceException.java | 2 +- .../execution/DirectExecutionControl.java | 19 ++- .../execution/ExecutionControlForwarder.java | 45 ++++-- .../jdk/jshell/execution/RemoteCodes.java | 10 +- .../execution/StreamingExecutionControl.java | 61 ++++++-- test/langtools/jdk/jshell/ExceptionsTest.java | 142 +++++++++++++++--- test/langtools/jdk/jshell/ToolSimpleTest.java | 28 +++- 12 files changed, 382 insertions(+), 82 deletions(-) diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index b123782bf92..0bdd37afe6a 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -81,6 +81,7 @@ import jdk.jshell.ImportSnippet; import jdk.jshell.JShell; import jdk.jshell.JShell.Subscription; +import jdk.jshell.JShellException; import jdk.jshell.MethodSnippet; import jdk.jshell.Snippet; import jdk.jshell.Snippet.Kind; @@ -3357,21 +3358,61 @@ List errorsOnly(List diagnostics) { /** * Print out a snippet exception. * - * @param exception the exception to print + * @param exception the throwable to print * @return true on fatal exception */ - private boolean displayException(Exception exception) { + private boolean displayException(Throwable exception) { + Throwable rootCause = exception; + while (rootCause instanceof EvalException) { + rootCause = rootCause.getCause(); + } + if (rootCause != exception && rootCause instanceof UnresolvedReferenceException) { + // An unresolved reference caused a chained exception, just show the unresolved + return displayException(rootCause, null); + } else { + return displayException(exception, null); + } + } + //where + private boolean displayException(Throwable exception, StackTraceElement[] caused) { if (exception instanceof EvalException) { - printEvalException((EvalException) exception); - return true; + // User exception + return displayEvalException((EvalException) exception, caused); } else if (exception instanceof UnresolvedReferenceException) { - printUnresolvedException((UnresolvedReferenceException) exception); - return false; + // Reference to an undefined snippet + return displayUnresolvedException((UnresolvedReferenceException) exception); } else { + // Should never occur error("Unexpected execution exception: %s", exception); return true; } } + //where + private boolean displayUnresolvedException(UnresolvedReferenceException ex) { + // Display the resolution issue + printSnippetStatus(ex.getSnippet(), false); + return false; + } + + //where + private boolean displayEvalException(EvalException ex, StackTraceElement[] caused) { + // The message for the user exception is configured based on the + // existance of an exception message and if this is a recursive + // invocation for a chained exception. + String msg = ex.getMessage(); + String key = "jshell.err.exception" + + (caused == null? ".thrown" : ".cause") + + (msg == null? "" : ".message"); + errormsg(key, ex.getExceptionClassName(), msg); + // The caused trace is sent to truncate duplicate elements in the cause trace + printStackTrace(ex.getStackTrace(), caused); + JShellException cause = ex.getCause(); + if (cause != null) { + // Display the cause (recursively) + displayException(cause, ex.getStackTrace()); + } + return true; + } /** * Display a list of diagnostics. @@ -3518,9 +3559,19 @@ private boolean handleEvent(SnippetEvent ste) { } return false; } - //where - void printStackTrace(StackTraceElement[] stes) { - for (StackTraceElement ste : stes) { + + // Print a stack trace, elide frames displayed for the caused exception + void printStackTrace(StackTraceElement[] stes, StackTraceElement[] caused) { + int overlap = 0; + if (caused != null) { + int maxOverlap = Math.min(stes.length, caused.length); + while (overlap < maxOverlap + && stes[stes.length - (overlap + 1)].equals(caused[caused.length - (overlap + 1)])) { + ++overlap; + } + } + for (int i = 0; i < stes.length - overlap; ++i) { + StackTraceElement ste = stes[i]; StringBuilder sb = new StringBuilder(); String cn = ste.getClassName(); if (!cn.isEmpty()) { @@ -3548,19 +3599,9 @@ void printStackTrace(StackTraceElement[] stes) { error(" at %s(%s)", sb, loc); } - } - //where - void printUnresolvedException(UnresolvedReferenceException ex) { - printSnippetStatus(ex.getSnippet(), false); - } - //where - void printEvalException(EvalException ex) { - if (ex.getMessage() == null) { - error("%s thrown", ex.getExceptionClassName()); - } else { - error("%s thrown: %s", ex.getExceptionClassName(), ex.getMessage()); + if (overlap != 0) { + error(" ..."); } - printStackTrace(ex.getStackTrace()); } private FormatAction toAction(Status status, Status previousStatus, boolean isSignatureChange) { diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties index 6b526691571..0bc471c9630 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties @@ -163,6 +163,11 @@ jshell.err.retained.mode.failure = Failure in retained modes (modes cleared) -- jshell.err.corrupted.stored.startup = Corrupted stored startup, using default -- {0} +jshell.err.exception.thrown = Exception {0} +jshell.err.exception.thrown.message = Exception {0}: {1} +jshell.err.exception.cause = Caused by: {0} +jshell.err.exception.cause.message = Caused by: {0}: {1} + jshell.console.see.synopsis = jshell.console.see.full.documentation = jshell.console.see.documentation = diff --git a/src/jdk.jshell/share/classes/jdk/jshell/Eval.java b/src/jdk.jshell/share/classes/jdk/jshell/Eval.java index f2f40aa04dc..9f64a9326da 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/Eval.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/Eval.java @@ -850,17 +850,15 @@ private List declare(Snippet si, DiagList generatedDiagnostics) { ? expunge(value) : ""; } catch (ResolutionException ex) { - DeclarationSnippet sn = (DeclarationSnippet) state.maps.getSnippetDeadOrAlive(ex.id()); - exception = new UnresolvedReferenceException(sn, translateExceptionStack(ex)); + exception = asUnresolvedReferenceException(ex); } catch (UserException ex) { - exception = new EvalException(ex.getMessage(), - ex.causeExceptionClass(), - translateExceptionStack(ex)); + exception = asEvalException(ex); } catch (RunException ex) { // StopException - no-op } catch (InternalException ex) { state.debug(ex, "invoke"); } catch (EngineTerminationException ex) { + state.debug(ex, "termination"); state.closeDown(); } } else if (si.subKind() == SubKind.VAR_DECLARATION_SUBKIND) { @@ -890,6 +888,36 @@ private List declare(Snippet si, DiagList generatedDiagnostics) { return events(c, outs, value, exception); } + // Convert an internal UserException to an API EvalException, translating + // the stack to snippet form. Convert any chained exceptions + private EvalException asEvalException(UserException ue) { + return new EvalException(ue.getMessage(), + ue.causeExceptionClass(), + translateExceptionStack(ue), + asJShellException(ue.getCause())); + } + + // Convert an internal ResolutionException to an API UnresolvedReferenceException, + // translating the snippet id to snipper and the stack to snippet form + private UnresolvedReferenceException asUnresolvedReferenceException(ResolutionException re) { + DeclarationSnippet sn = (DeclarationSnippet) state.maps.getSnippetDeadOrAlive(re.id()); + return new UnresolvedReferenceException(sn, translateExceptionStack(re)); + } + + // Convert an internal UserException/ResolutionException to an API + // EvalException/UnresolvedReferenceException + private JShellException asJShellException(Throwable e) { + if (e == null) { + return null; + } else if (e instanceof UserException) { + return asEvalException((UserException) e); + } else if (e instanceof ResolutionException) { + return asUnresolvedReferenceException((ResolutionException) e); + } else { + throw new AssertionError(e); + } + } + private boolean interestingEvent(SnippetEvent e) { return e.isSignatureChange() || e.causeSnippet() == null diff --git a/src/jdk.jshell/share/classes/jdk/jshell/EvalException.java b/src/jdk.jshell/share/classes/jdk/jshell/EvalException.java index 70883742d59..01721db3fa6 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/EvalException.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/EvalException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, 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,10 +26,10 @@ package jdk.jshell; /** - * Wraps an exception thrown in the remotely executing client. + * Wraps an throwable thrown in the executing client. * An instance of EvalException can be returned in the * {@link jdk.jshell.SnippetEvent#exception()} query. - * The name of the exception thrown is available from + * The name of the throwable thrown is available from * {@link jdk.jshell.EvalException#getExceptionClassName()}. * Message and stack can be queried by methods on Exception. *

      @@ -45,8 +45,9 @@ public class EvalException extends JShellException { private final String exceptionClass; - EvalException(String message, String exceptionClass, StackTraceElement[] stackElements) { - super(message); + EvalException(String message, String exceptionClass, + StackTraceElement[] stackElements, JShellException cause) { + super(message, cause); this.exceptionClass = exceptionClass; this.setStackTrace(stackElements); } @@ -63,4 +64,18 @@ public String getExceptionClassName() { return exceptionClass; } + /** + * Returns the wrapped cause of the throwable in the executing client + * represented by this {@code EvalException} or {@code null} if the cause is + * nonexistent or unknown. + * + * @return the cause wrapped in a {@code EvalException} or + * {@link UnresolvedReferenceException} or return {@code null} if the cause + * is nonexistent or unknown. + * @since 11 + */ + @Override + public JShellException getCause() { + return (JShellException) super.getCause(); + } } diff --git a/src/jdk.jshell/share/classes/jdk/jshell/JShellException.java b/src/jdk.jshell/share/classes/jdk/jshell/JShellException.java index a9fe6a0caf8..637b50d2b9b 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/JShellException.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/JShellException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, 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 @@ -36,4 +36,8 @@ public class JShellException extends Exception { JShellException(String message) { super(message); } + + JShellException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java b/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java index 0bc2918d75f..44c33e6a074 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java @@ -45,7 +45,7 @@ public class UnresolvedReferenceException extends JShellException { final DeclarationSnippet snippet; UnresolvedReferenceException(DeclarationSnippet snippet, StackTraceElement[] stackElements) { - super("Attempt to use definition snippet with unresolved references"); + super("Attempt to use definition snippet with unresolved references in " + snippet); this.snippet = snippet; this.setStackTrace(stackElements); } diff --git a/src/jdk.jshell/share/classes/jdk/jshell/execution/DirectExecutionControl.java b/src/jdk.jshell/share/classes/jdk/jshell/execution/DirectExecutionControl.java index a1e9d1f2273..67255823adb 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/execution/DirectExecutionControl.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/execution/DirectExecutionControl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, 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 @@ -288,11 +288,20 @@ protected static String valueString(Object value) { * @throws ExecutionControl.InternalException for internal problems */ protected String throwConvertedInvocationException(Throwable cause) throws RunException, InternalException { - if (cause instanceof SPIResolutionException) { - SPIResolutionException spire = (SPIResolutionException) cause; - throw new ResolutionException(spire.id(), spire.getStackTrace()); + throw asRunException(cause); + } + + private RunException asRunException(Throwable ex) { + if (ex instanceof SPIResolutionException) { + SPIResolutionException spire = (SPIResolutionException) ex; + return new ResolutionException(spire.id(), spire.getStackTrace()); } else { - throw new UserException(cause.getMessage(), cause.getClass().getName(), cause.getStackTrace()); + UserException ue = new UserException(ex.getMessage(), + ex.getClass().getName(), + ex.getStackTrace()); + Throwable cause = ex.getCause(); + ue.initCause(cause == null ? null : asRunException(cause)); + return ue; } } diff --git a/src/jdk.jshell/share/classes/jdk/jshell/execution/ExecutionControlForwarder.java b/src/jdk.jshell/share/classes/jdk/jshell/execution/ExecutionControlForwarder.java index ff1cdd5cb50..061e548878b 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/execution/ExecutionControlForwarder.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/execution/ExecutionControlForwarder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, 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 @@ -195,8 +195,7 @@ private boolean processCommand() throws IOException { flush(); return true; } catch (InternalException ex) { - writeStatus(RESULT_INTERNAL_PROBLEM); - writeUTF(ex.getMessage()); + writeInternalException(ex); flush(); return true; } catch (ClassInstallException ex) { @@ -206,16 +205,24 @@ private boolean processCommand() throws IOException { flush(); return true; } catch (UserException ex) { - writeStatus(RESULT_USER_EXCEPTION); - writeNullOrUTF(ex.getMessage()); - writeUTF(ex.causeExceptionClass()); - writeObject(ex.getStackTrace()); + writeStatus(RESULT_USER_EXCEPTION_CHAINED); + for (Throwable e = ex; e != null; ) { + if (e instanceof UserException) { + writeUserException((UserException) e); + e = e.getCause(); + } else if (e instanceof ResolutionException) { + writeResolutionException((ResolutionException) e); + e = null; + } else { + writeInternalException(e); + e = null; + } + } + writeStatus(RESULT_SUCCESS); flush(); return true; } catch (ResolutionException ex) { - writeStatus(RESULT_CORRALLED); - writeInt(ex.id()); - writeObject(ex.getStackTrace()); + writeResolutionException(ex); flush(); return true; } catch (StoppedException ex) { @@ -232,6 +239,24 @@ private boolean processCommand() throws IOException { } } + void writeInternalException(Throwable ex) throws IOException { + writeStatus(RESULT_INTERNAL_PROBLEM); + writeUTF(ex.getMessage()); + } + + void writeUserException(UserException ex) throws IOException { + writeStatus(RESULT_USER_EXCEPTION); + writeNullOrUTF(ex.getMessage()); + writeUTF(ex.causeExceptionClass()); + writeObject(ex.getStackTrace()); + } + + void writeResolutionException(ResolutionException ex) throws IOException { + writeStatus(RESULT_CORRALLED); + writeInt(ex.id()); + writeObject(ex.getStackTrace()); + } + void commandLoop() { try { while (processCommand()) { diff --git a/src/jdk.jshell/share/classes/jdk/jshell/execution/RemoteCodes.java b/src/jdk.jshell/share/classes/jdk/jshell/execution/RemoteCodes.java index c841adb253b..e7b3f2c65cd 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/execution/RemoteCodes.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/execution/RemoteCodes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, 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 @@ -89,7 +89,7 @@ class RemoteCodes { */ static final int RESULT_INTERNAL_PROBLEM = 103; /** - * User exception encountered. + * User exception encountered. Legacy and used within RESULT_USER_EXCEPTION_CHAINED */ static final int RESULT_USER_EXCEPTION = 104; /** @@ -104,5 +104,9 @@ class RemoteCodes { * The invoke has been stopped. */ static final int RESULT_STOPPED = 107; - + /** + * User exception encountered. + * @since 11 + */ + static final int RESULT_USER_EXCEPTION_CHAINED = 108; } diff --git a/src/jdk.jshell/share/classes/jdk/jshell/execution/StreamingExecutionControl.java b/src/jdk.jshell/share/classes/jdk/jshell/execution/StreamingExecutionControl.java index 8c8f2f00821..a2c70a1bdaa 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/execution/StreamingExecutionControl.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/execution/StreamingExecutionControl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, 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 @@ -283,18 +283,46 @@ private void readAndReportExecutionResult() throws RunException, throw new NotImplementedException(message); } case RESULT_USER_EXCEPTION: { - // A user exception was encountered. - String message = readNullOrUTF(); - String exceptionClassName = in.readUTF(); - StackTraceElement[] elems = (StackTraceElement[]) in.readObject(); - throw new UserException(message, exceptionClassName, elems); + // A user exception was encountered. Handle pre JDK 11 back-ends + throw readUserException(); } case RESULT_CORRALLED: { // An unresolved reference was encountered. - int id = in.readInt(); - StackTraceElement[] elems = (StackTraceElement[]) in.readObject(); - ResolutionException re = new ResolutionException(id, elems); - throw re; + throw readResolutionException(); + } + case RESULT_USER_EXCEPTION_CHAINED: { + // A user exception was encountered -- transmit chained. + in.readInt(); // always RESULT_USER_EXCEPTION + UserException result = readUserException(); + RunException caused = result; + // Loop through the chained causes (if any) building a chained exception + loop: while (true) { + RunException ex; + int cstatus = in.readInt(); + switch (cstatus) { + case RESULT_USER_EXCEPTION: { + // A user exception was the proximal cause. + ex = readUserException(); + break; + } + case RESULT_CORRALLED: { + // An unresolved reference was the underlying cause. + ex = readResolutionException(); + break; + } + case RESULT_SUCCESS: { + // End of chained exceptions + break loop; + } + default: { + throw new EngineTerminationException("Bad chained remote result code: " + cstatus); + } + } + caused.initCause(ex); + caused = ex; + } + caused.initCause(null); // root cause has no cause + throw result; } case RESULT_STOPPED: { // Execution was aborted by the stop() @@ -314,8 +342,21 @@ private void readAndReportExecutionResult() throws RunException, } } } catch (IOException | ClassNotFoundException ex) { + ex.printStackTrace(); throw new EngineTerminationException(ex.toString()); } } + private UserException readUserException() throws IOException, ClassNotFoundException { + String message = readNullOrUTF(); + String exceptionClassName = in.readUTF(); + StackTraceElement[] elems = (StackTraceElement[]) in.readObject(); + return new UserException(message, exceptionClassName, elems); + } + + private ResolutionException readResolutionException() throws IOException, ClassNotFoundException { + int id = in.readInt(); + StackTraceElement[] elems = (StackTraceElement[]) in.readObject(); + return new ResolutionException(id, elems); + } } diff --git a/test/langtools/jdk/jshell/ExceptionsTest.java b/test/langtools/jdk/jshell/ExceptionsTest.java index a5dde23cb19..b9ff29bd63c 100644 --- a/test/langtools/jdk/jshell/ExceptionsTest.java +++ b/test/langtools/jdk/jshell/ExceptionsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, 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,16 +24,20 @@ /* * @test * @summary Tests for exceptions + * @bug 8198801 * @build KullaTesting TestingInputStream * @run testng ExceptionsTest */ -import jdk.jshell.SnippetEvent; -import jdk.jshell.EvalException; +import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; - +import jdk.jshell.EvalException; +import jdk.jshell.JShellException; import jdk.jshell.Snippet; +import jdk.jshell.SnippetEvent; +import jdk.jshell.UnresolvedReferenceException; + import org.testng.annotations.Test; import static org.testng.Assert.*; @@ -81,6 +85,54 @@ public void throwFromStaticMethodOfInterface() { newStackTraceElement("", "", cr3.snippet(), 1))); } + public void throwChained() { + String message1 = "error_message1"; + String message2 = "error_message2"; + Snippet s1 = methodKey(assertEval("void p() throws Exception { ((String) null).toString(); }")); + Snippet s2 = methodKey(assertEval("void n() throws Exception { try { p(); } catch (Exception ex) { throw new java.io.IOException(\"" + message2 + "\", ex); }}")); + Snippet s3 = methodKey(assertEval("void m() {\n" + + "try { n(); }\n" + + "catch (Exception ex) {\n" + + " throw new RuntimeException(\"" + message1 + "\", ex);\n" + + "}}")); + SnippetEvent cr4 = assertEvalException("m();"); + assertExceptionMatch(cr4, + new ExceptionInfo(RuntimeException.class, message1, + new ExceptionInfo(IOException.class, message2, + new ExceptionInfo(NullPointerException.class, null, + newStackTraceElement("", "p", s1, 1), + newStackTraceElement("", "n", s2, 1), + newStackTraceElement("", "m", s3, 2), + newStackTraceElement("", "", cr4.snippet(), 1)), + newStackTraceElement("", "n", s2, 1), + newStackTraceElement("", "m", s3, 2), + newStackTraceElement("", "", cr4.snippet(), 1)), + newStackTraceElement("", "m", s3, 4), + newStackTraceElement("", "", cr4.snippet(), 1))); + } + + public void throwChainedUnresolved() { + String message1 = "error_message1"; + String message2 = "error_message2"; + Snippet s1 = methodKey(assertEval("void p() throws Exception { ((String) null).toString(); }")); + Snippet s2 = methodKey(assertEval("void n() throws Exception { try { p(); } catch (Exception ex) { throw new java.io.IOException(\"" + message2 + "\", ex); }}")); + Snippet s3 = methodKey(assertEval("void m() {\n" + + "try { n(); }\n" + + "catch (Exception ex) {\n" + + " throw new RuntimeException(\"" + message1 + "\", ex);\n" + + "}}")); + getState().drop(s1); + SnippetEvent cr4 = assertEvalException("m();"); + assertExceptionMatch(cr4, + new ExceptionInfo(RuntimeException.class, message1, + new UnresolvedExceptionInfo(s2, + newStackTraceElement("", "n", s2, 1), + newStackTraceElement("", "m", s3, 2), + newStackTraceElement("", "", cr4.snippet(), 1)), + newStackTraceElement("", "m", s3, 4), + newStackTraceElement("", "", cr4.snippet(), 1))); + } + public void throwFromConstructor() { String message = "error_message"; Snippet s1 = methodKey(assertEval("void f() { throw new RuntimeException(\"" + message + "\"); }")); @@ -171,15 +223,42 @@ private StackTraceElement newStackTraceElement(String className, String methodNa return new StackTraceElement(className, methodName, "#" + key.id(), lineNumber); } - private static class ExceptionInfo { + private static class AnyExceptionInfo { + + public final StackTraceElement[] stackTraceElements; + + public AnyExceptionInfo(StackTraceElement... stackTraceElements) { + this.stackTraceElements = stackTraceElements.length == 0 ? null : stackTraceElements; + } + } + + private static class UnresolvedExceptionInfo extends AnyExceptionInfo { + + public final Snippet sn; + + public UnresolvedExceptionInfo(Snippet sn, StackTraceElement... stackTraceElements) { + super(stackTraceElements); + this.sn = sn; + } + } + + private static class ExceptionInfo extends AnyExceptionInfo { + public final Class exception; public final String message; - public final StackTraceElement[] stackTraceElements; + public final AnyExceptionInfo cause; + + public ExceptionInfo(Class exception, String message, + StackTraceElement... stackTraceElements) { + this(exception, message, null, stackTraceElements); + } - public ExceptionInfo(Class exception, String message, StackTraceElement...stackTraceElements) { + public ExceptionInfo(Class exception, String message, + AnyExceptionInfo cause, StackTraceElement... stackTraceElements) { + super(stackTraceElements); this.exception = exception; this.message = message; - this.stackTraceElements = stackTraceElements.length == 0 ? null : stackTraceElements; + this.cause = cause; } } @@ -188,28 +267,51 @@ private void assertExecuteException(String input, Class exc } private void assertExceptionMatch(SnippetEvent cr, ExceptionInfo exceptionInfo) { - assertNotNull(cr.exception(), "Expected exception was not thrown: " + exceptionInfo.exception); - if (cr.exception() instanceof EvalException) { - EvalException ex = (EvalException) cr.exception(); + assertExceptionMatch(cr.exception(), cr.snippet().source(), exceptionInfo); + } + + private void assertExceptionMatch(Throwable exception, String source, ExceptionInfo exceptionInfo) { + assertNotNull(exception, "Expected exception was not thrown: " + exceptionInfo.exception); + if (exception instanceof EvalException) { + EvalException ex = (EvalException) exception; String actualException = ex.getExceptionClassName(); String expectedException = exceptionInfo.exception.getCanonicalName(); - String stackTrace = getStackTrace(ex); - String source = cr.snippet().source(); assertEquals(actualException, expectedException, String.format("Given \"%s\" expected exception: %s, got: %s%nStack trace:%n%s", - source, expectedException, actualException, stackTrace)); + source, expectedException, actualException, getStackTrace(ex))); if (exceptionInfo.message != null) { assertEquals(ex.getMessage(), exceptionInfo.message, String.format("Given \"%s\" expected message: %s, got: %s", source, exceptionInfo.message, ex.getMessage())); } - if (exceptionInfo.stackTraceElements != null) { - assertStackTrace(ex.getStackTrace(), exceptionInfo.stackTraceElements, - String.format("Given \"%s\"%nStack trace:%n%s%n", - source, stackTrace)); + assertStackMatch(ex, source, exceptionInfo); + if (exceptionInfo.cause != null) { + assertAnyExceptionMatch(exception.getCause(), exceptionInfo.cause); } } else { - fail("Unexpected execution exceptionInfo: " + cr.exception()); + fail("Unexpected exception: " + exception + " or exceptionInfo: " + exceptionInfo); + } + } + + private void assertStackMatch(JShellException exception, String source, AnyExceptionInfo exceptionInfo) { + if (exceptionInfo.stackTraceElements != null) { + assertStackTrace(exception.getStackTrace(), exceptionInfo.stackTraceElements, + String.format("Given \"%s\"%nStack trace:%n%s%n", + source, getStackTrace(exception))); + } + } + + private void assertAnyExceptionMatch(Throwable exception, AnyExceptionInfo exceptionInfo) { + if (exceptionInfo instanceof ExceptionInfo) { + assertExceptionMatch(exception, "", (ExceptionInfo) exceptionInfo); + } else { + assertTrue(exceptionInfo instanceof UnresolvedExceptionInfo, "Bad exceptionInfo: " + exceptionInfo); + assertTrue(exception instanceof UnresolvedReferenceException, + "Expected UnresolvedReferenceException: " + exception); + UnresolvedExceptionInfo uei = (UnresolvedExceptionInfo) exceptionInfo; + UnresolvedReferenceException ure = (UnresolvedReferenceException) exception; + assertEquals(ure.getSnippet(), uei.sn); + assertStackMatch(ure, "", exceptionInfo); } } @@ -236,7 +338,7 @@ private void assertStackTrace(StackTraceElement[] actual, StackTraceElement[] ex } } - private String getStackTrace(EvalException ex) { + private String getStackTrace(Throwable ex) { StringWriter st = new StringWriter(); ex.printStackTrace(new PrintWriter(st)); return st.toString(); diff --git a/test/langtools/jdk/jshell/ToolSimpleTest.java b/test/langtools/jdk/jshell/ToolSimpleTest.java index 0393d5b26b6..dfe5009e29e 100644 --- a/test/langtools/jdk/jshell/ToolSimpleTest.java +++ b/test/langtools/jdk/jshell/ToolSimpleTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103 8165405 8173073 8173848 8174041 8173916 8174028 8174262 8174797 8177079 8180508 8177466 8172154 8192979 8191842 8198573 + * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103 8165405 8173073 8173848 8174041 8173916 8174028 8174262 8174797 8177079 8180508 8177466 8172154 8192979 8191842 8198573 8198801 * @summary Simple jshell tool tests * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main @@ -86,6 +86,32 @@ public void testLessThan() { ); } + @Test + public void testChainedThrow() { + test( + (a) -> assertCommand(a, "void p() throws Exception { ((String) null).toString(); }", + "| created method p()"), + (a) -> assertCommand(a, "void n() throws Exception { try { p(); } catch (Exception ex) { throw new IOException(\"bar\", ex); }}", + "| created method n()"), + (a) -> assertCommand(a, "void m() { try { n(); } catch (Exception ex) { throw new RuntimeException(\"foo\", ex); }}", + "| created method m()"), + (a) -> assertCommand(a, "m()", + "| Exception java.lang.RuntimeException: foo\n" + + "| at m (#3:1)\n" + + "| at (#4:1)\n" + + "| Caused by: java.io.IOException: bar\n" + + "| at n (#2:1)\n" + + "| ...\n" + + "| Caused by: java.lang.NullPointerException\n" + + "| at p (#1:1)\n" + + "| ..."), + (a) -> assertCommand(a, "/drop p", + "| dropped method p()"), + (a) -> assertCommand(a, "m()", + "| attempted to call method n() which cannot be invoked until method p() is declared") + ); + } + @Test public void oneLineOfError() { test( From 4e67fb8218fee8d9e8568a26794aee9e35655c27 Mon Sep 17 00:00:00 2001 From: erikj Date: Tue, 3 Apr 2018 22:33:58 +0200 Subject: [PATCH 055/196] 8200375: Change to GCC 7.3.0 for building Linux at Oracle Reviewed-by: ihse, tbell --- make/conf/jib-profiles.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index c97abaf8a16..6a7b51df644 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -816,7 +816,7 @@ var getJibProfilesProfiles = function (input, common, data) { var getJibProfilesDependencies = function (input, common) { var devkit_platform_revisions = { - linux_x64: "gcc4.9.2-OEL6.4+1.3", + linux_x64: "gcc7.3.0-OEL6.4+1.0", macosx_x64: "Xcode6.3-MacOSX10.9+1.0", solaris_x64: "SS12u4-Solaris11u1+1.0", solaris_sparcv9: "SS12u4-Solaris11u1+1.1", From 31c4e18c3fca7a051e33a5366f219795bf1166fc Mon Sep 17 00:00:00 2001 From: ihse Date: Tue, 3 Apr 2018 22:37:43 +0200 Subject: [PATCH 056/196] 8200658: Fix incremental builds of hotspot on solaris Reviewed-by: erikj --- make/common/NativeCompilation.gmk | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index 36697776aee..569ee1321b0 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -292,8 +292,7 @@ define SetupCompileNativeFileBody endif ifneq ($$(strip $$($1_CFLAGS) $$($1_CXXFLAGS) $$($1_OPTIMIZATION)), ) - $1_VARDEPS := $$($1_CFLAGS) $$($1_CXXFLAGS) $$($1_OPT_CFLAGS) \ - $$($1_OPT_CXXFLAGS) + $1_VARDEPS := $$($1_CFLAGS) $$($1_CXXFLAGS) $$($1_OPTIMIZATION) $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$($1_OBJ).vardeps) endif From 29f7467ce0d896b929e3055a78f8f795cf3c371d Mon Sep 17 00:00:00 2001 From: vromero Date: Tue, 3 Apr 2018 23:58:52 -0400 Subject: [PATCH 057/196] 8198314: javac hidden options violate standard syntax for options Reviewed-by: jjg --- .../com/sun/tools/javac/main/Option.java | 37 +++++++++---------- .../com/sun/tools/sjavac/options/Options.java | 4 +- .../share/classes/jdk/jshell/TaskFactory.java | 2 +- .../ClassFileModifiers/ClassModifiers.java | 4 +- .../ClassFileModifiers/MemberModifiers.java | 4 +- .../javac/Diagnostics/6722234/T6722234a.java | 4 +- .../javac/Diagnostics/6722234/T6722234b.java | 4 +- .../javac/Diagnostics/6722234/T6722234c.java | 2 +- .../javac/Diagnostics/6722234/T6722234d.java | 4 +- .../javac/Diagnostics/6862608/T6862608a.java | 2 +- .../javac/Diagnostics/6862608/T6862608b.java | 2 +- .../tools/javac/Diagnostics/7010608/Test.java | 6 +-- .../javac/Diagnostics/8010387/T8010387.java | 2 +- .../javac/InterfaceMemberClassModifiers.java | 2 +- test/langtools/tools/javac/T6214885.java | 4 +- ...AnnotationsCrashWithErroneousTreeTest.java | 2 +- .../VerifyErroneousAnnotationsAttributed.java | 4 +- .../newlocations/AfterMethodTypeParams.java | 4 +- .../tools/javac/api/6731573/T6731573.java | 6 +-- .../api/taskListeners/EventsBalancedTest.java | 10 ++--- .../javac/completionDeps/DepsAndAnno.java | 4 +- .../javac/completionDeps/DepsAndDocLint.java | 4 +- .../diags/examples/ApplicableMethodFound.java | 4 +- .../examples/ApplicableMethodFound1.java | 4 +- .../diags/examples/DeferredMethodInst.java | 4 +- .../diags/examples/LambdaDeduplicate.java | 2 +- .../javac/diags/examples/LambdaStat.java | 4 +- .../tools/javac/diags/examples/MrefStat.java | 4 +- .../tools/javac/diags/examples/MrefStat1.java | 4 +- .../examples/NotApplicableMethodFound.java | 4 +- .../javac/diags/examples/PartialInstSig.java | 4 +- .../diags/examples/VerboseResolveMulti.java | 4 +- .../diags/examples/VerboseResolveMulti1.java | 4 +- .../javac/diags/examples/WhereCaptured.java | 4 +- .../javac/diags/examples/WhereCaptured1.java | 4 +- .../javac/diags/examples/WhereFreshTvar.java | 4 +- .../diags/examples/WhereIntersection.java | 4 +- .../diags/examples/WhereIntersection2.java | 4 +- .../javac/diags/examples/WhereTypeVar.java | 4 +- .../javac/diags/examples/WhereTypeVar2.java | 4 +- .../javac/failover/CheckAttributedTree.java | 4 +- .../tools/javac/failover/FailOver01.java | 2 +- .../tools/javac/failover/FailOver02.java | 2 +- .../tools/javac/failover/FailOver03.java | 2 +- .../tools/javac/failover/FailOver04.java | 2 +- .../tools/javac/failover/FailOver05.java | 2 +- .../tools/javac/failover/FailOver06.java | 2 +- .../tools/javac/failover/FailOver07.java | 2 +- .../tools/javac/failover/FailOver08.java | 2 +- .../tools/javac/failover/FailOver09.java | 2 +- .../tools/javac/failover/FailOver10.java | 2 +- .../tools/javac/failover/FailOver11.java | 2 +- .../tools/javac/failover/FailOver12.java | 2 +- .../tools/javac/failover/FailOver13.java | 2 +- .../tools/javac/failover/FailOver14.java | 2 +- .../tools/javac/failover/FailOver15.java | 2 +- .../generics/inference/8158355/T8158355.java | 4 +- .../tools/javac/lambda/MostSpecific09.java | 2 +- .../javac/lambda/TestLambdaToMethodStats.java | 4 +- .../lambda/XDdumpLambdaToMethodStats.java | 4 +- .../lambda/bridge/TestMetafactoryBridges.java | 4 +- .../StructuralMostSpecificTest.java | 4 +- .../MissingSuperRecovery.java | 2 +- .../tools/javac/modules/AddLimitMods.java | 14 +++---- .../javac/options/IsSupportedOptionTest.java | 4 +- .../tools/javac/policy/test3/Test.java | 6 +-- .../tools/javac/positions/TreeEndPosTest.java | 4 +- .../ProtectedMemberAccess2.java | 2 +- .../ProtectedMemberAccess3.java | 2 +- .../ProtectedMemberAccess4.java | 2 +- .../tools/javac/resolve/ResolveHarness.java | 6 +-- test/langtools/tools/javac/tree/VarTree.java | 4 +- .../tools/javac/unicode/UnicodeNewline.java | 2 +- .../tools/sjavac/JavacOptionPrep.java | 4 +- 74 files changed, 146 insertions(+), 149 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java index 65cf5dffea3..23bfdec575e 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java @@ -520,24 +520,24 @@ public void process(OptionHelper helper, String option, String p) { XDIAGS("-Xdiags:", "opt.diags", EXTENDED, BASIC, ONEOF, "compact", "verbose"), - DEBUG("--debug:", null, HIDDEN, BASIC) { + DEBUG("--debug", null, HIDDEN, BASIC, ArgKind.REQUIRED) { @Override - public void process(OptionHelper helper, String option) throws InvalidValueException { - HiddenGroup.DEBUG.process(helper, option); + public void process(OptionHelper helper, String option, String arg) throws InvalidValueException { + HiddenGroup.DEBUG.process(helper, option, arg); } }, - SHOULDSTOP("--should-stop:", null, HIDDEN, BASIC) { + SHOULDSTOP("--should-stop", null, HIDDEN, BASIC, ArgKind.REQUIRED) { @Override - public void process(OptionHelper helper, String option) throws InvalidValueException { - HiddenGroup.SHOULDSTOP.process(helper, option); + public void process(OptionHelper helper, String option, String arg) throws InvalidValueException { + HiddenGroup.SHOULDSTOP.process(helper, option, arg); } }, - DIAGS("--diags:", null, HIDDEN, BASIC) { + DIAGS("--diags", null, HIDDEN, BASIC, ArgKind.REQUIRED) { @Override - public void process(OptionHelper helper, String option) throws InvalidValueException { - HiddenGroup.DIAGS.process(helper, option); + public void process(OptionHelper helper, String option, String arg) throws InvalidValueException { + HiddenGroup.DIAGS.process(helper, option, arg); } }, @@ -846,27 +846,19 @@ enum HiddenGroup { DEBUG("debug"), SHOULDSTOP("should-stop"); - static final Set skipSet = new java.util.HashSet<>( - Arrays.asList("--diags:", "--debug:", "--should-stop:")); - final String text; HiddenGroup(String text) { this.text = text; } - public void process(OptionHelper helper, String option) throws InvalidValueException { - String p = option.substring(option.indexOf(':') + 1).trim(); - String[] subOptions = p.split(";"); + public void process(OptionHelper helper, String option, String arg) throws InvalidValueException { + String[] subOptions = arg.split(";"); for (String subOption : subOptions) { subOption = text + "." + subOption.trim(); XD.process(helper, subOption, subOption); } } - - static boolean skip(String name) { - return skipSet.contains(name); - } } /** @@ -957,6 +949,11 @@ public int compare(Option o1, Option o2) { this(text, null, descrKey, kind, group, null, null, ArgKind.NONE); } + Option(String text, String descrKey, + OptionKind kind, OptionGroup group, ArgKind argKind) { + this(text, null, descrKey, kind, group, null, null, argKind); + } + Option(String text, String argsNameKey, String descrKey, OptionKind kind, OptionGroup group) { this(text, argsNameKey, descrKey, kind, group, null, null, ArgKind.REQUIRED); @@ -1025,7 +1022,7 @@ public boolean matches(String option) { } private boolean matches(String option, String name) { - if (name.startsWith("--") && !HiddenGroup.skip(name)) { + if (name.startsWith("--")) { return option.equals(name) || hasArg() && option.startsWith(name + "="); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Options.java b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Options.java index 4f212a86a19..b06e209816f 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Options.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Options.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, 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 @@ -313,7 +313,7 @@ public String[] prepJavacArgs() { } // Enable dependency generation - args.add("--debug:completionDeps=source,class"); + args.add("--debug=completionDeps=source,class"); // This can't be anything but 'none'. Enforced by sjavac main method. args.add("-implicit:" + implicitPolicy); diff --git a/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java b/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java index d9f09db6418..18f9eb300a8 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java @@ -167,7 +167,7 @@ public Z analyze(Collection wraps, WrapSourceHandler sh = new WrapSourceHandler(); List allOptions = new ArrayList<>(); - allOptions.add("--should-stop:at=FLOW"); + allOptions.add("--should-stop=at=FLOW"); allOptions.add("-Xlint:unchecked"); allOptions.add("-proc:none"); allOptions.addAll(extraArgs); diff --git a/test/langtools/tools/javac/ClassFileModifiers/ClassModifiers.java b/test/langtools/tools/javac/ClassFileModifiers/ClassModifiers.java index 77bf387f7e7..3663f2f11aa 100644 --- a/test/langtools/tools/javac/ClassFileModifiers/ClassModifiers.java +++ b/test/langtools/tools/javac/ClassFileModifiers/ClassModifiers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2018, 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,7 +28,7 @@ * file are correct, including those within InnerClasses attributes. * @author John Rose (jrose). Entered as a regression test by Bill Maddox (maddox). * - * @compile/ref=ClassModifiers.out --debug:dumpmodifiers=ci ClassModifiers.java + * @compile/ref=ClassModifiers.out --debug=dumpmodifiers=ci ClassModifiers.java * */ diff --git a/test/langtools/tools/javac/ClassFileModifiers/MemberModifiers.java b/test/langtools/tools/javac/ClassFileModifiers/MemberModifiers.java index fa134f816ae..7ff3a80cf7c 100644 --- a/test/langtools/tools/javac/ClassFileModifiers/MemberModifiers.java +++ b/test/langtools/tools/javac/ClassFileModifiers/MemberModifiers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ * @bug 4249112 4785453 * @summary Verify that implicit member modifiers are set correctly. * - * @compile/ref=MemberModifiers.out --debug:dumpmodifiers=cfm MemberModifiers.java + * @compile/ref=MemberModifiers.out --debug=dumpmodifiers=cfm MemberModifiers.java */ // Currently, we check only that members of final classes are not final. diff --git a/test/langtools/tools/javac/Diagnostics/6722234/T6722234a.java b/test/langtools/tools/javac/Diagnostics/6722234/T6722234a.java index 04008efcfb3..3bce9308254 100644 --- a/test/langtools/tools/javac/Diagnostics/6722234/T6722234a.java +++ b/test/langtools/tools/javac/Diagnostics/6722234/T6722234a.java @@ -3,8 +3,8 @@ * @bug 6722234 * @summary javac diagnostics need better integration with the type-system * @author mcimadamore - * @compile/fail/ref=T6722234a_1.out -XDrawDiagnostics --diags:formatterOptions=disambiguateTvars T6722234a.java - * @compile/fail/ref=T6722234a_2.out -XDrawDiagnostics --diags:formatterOptions=disambiguateTvars,where T6722234a.java + * @compile/fail/ref=T6722234a_1.out -XDrawDiagnostics --diags=formatterOptions=disambiguateTvars T6722234a.java + * @compile/fail/ref=T6722234a_2.out -XDrawDiagnostics --diags=formatterOptions=disambiguateTvars,where T6722234a.java */ class T6722234a { diff --git a/test/langtools/tools/javac/Diagnostics/6722234/T6722234b.java b/test/langtools/tools/javac/Diagnostics/6722234/T6722234b.java index 47a1716cf2a..6b8fb798228 100644 --- a/test/langtools/tools/javac/Diagnostics/6722234/T6722234b.java +++ b/test/langtools/tools/javac/Diagnostics/6722234/T6722234b.java @@ -3,8 +3,8 @@ * @bug 6722234 8078024 * @summary javac diagnostics need better integration with the type-system * @author mcimadamore - * @compile/fail/ref=T6722234b_1.out -XDrawDiagnostics --diags:formatterOptions=simpleNames T6722234b.java - * @compile/fail/ref=T6722234b_2.out -XDrawDiagnostics --diags:formatterOptions=simpleNames,where T6722234b.java + * @compile/fail/ref=T6722234b_1.out -XDrawDiagnostics --diags=formatterOptions=simpleNames T6722234b.java + * @compile/fail/ref=T6722234b_2.out -XDrawDiagnostics --diags=formatterOptions=simpleNames,where T6722234b.java */ import java.util.*; diff --git a/test/langtools/tools/javac/Diagnostics/6722234/T6722234c.java b/test/langtools/tools/javac/Diagnostics/6722234/T6722234c.java index 4b12953003d..8884d788f9e 100644 --- a/test/langtools/tools/javac/Diagnostics/6722234/T6722234c.java +++ b/test/langtools/tools/javac/Diagnostics/6722234/T6722234c.java @@ -3,7 +3,7 @@ * @bug 6722234 * @summary javac diagnostics need better integration with the type-system * @author mcimadamore - * @compile/fail/ref=T6722234c.out -XDrawDiagnostics --diags:formatterOptions=simpleNames T6722234c.java + * @compile/fail/ref=T6722234c.out -XDrawDiagnostics --diags=formatterOptions=simpleNames T6722234c.java */ class T6722234c { diff --git a/test/langtools/tools/javac/Diagnostics/6722234/T6722234d.java b/test/langtools/tools/javac/Diagnostics/6722234/T6722234d.java index 95fa4fb24ab..4dc9fe7a3da 100644 --- a/test/langtools/tools/javac/Diagnostics/6722234/T6722234d.java +++ b/test/langtools/tools/javac/Diagnostics/6722234/T6722234d.java @@ -3,8 +3,8 @@ * @bug 6722234 8078024 * @summary javac diagnostics need better integration with the type-system * @author mcimadamore - * @compile/fail/ref=T6722234d_1.out -XDrawDiagnostics --diags:formatterOptions=where T6722234d.java - * @compile/fail/ref=T6722234d_2.out -XDrawDiagnostics --diags:formatterOptions=where,simpleNames T6722234d.java + * @compile/fail/ref=T6722234d_1.out -XDrawDiagnostics --diags=formatterOptions=where T6722234d.java + * @compile/fail/ref=T6722234d_2.out -XDrawDiagnostics --diags=formatterOptions=where,simpleNames T6722234d.java */ class T6722234d { diff --git a/test/langtools/tools/javac/Diagnostics/6862608/T6862608a.java b/test/langtools/tools/javac/Diagnostics/6862608/T6862608a.java index 1713c05e202..90b7953f1bd 100644 --- a/test/langtools/tools/javac/Diagnostics/6862608/T6862608a.java +++ b/test/langtools/tools/javac/Diagnostics/6862608/T6862608a.java @@ -3,7 +3,7 @@ * @bug 6862608 * @summary rich diagnostic sometimes contain wrong type variable numbering * @author mcimadamore - * @compile/fail/ref=T6862608a.out -XDrawDiagnostics --diags:formatterOptions=disambiguateTvars,where T6862608a.java + * @compile/fail/ref=T6862608a.out -XDrawDiagnostics --diags=formatterOptions=disambiguateTvars,where T6862608a.java */ diff --git a/test/langtools/tools/javac/Diagnostics/6862608/T6862608b.java b/test/langtools/tools/javac/Diagnostics/6862608/T6862608b.java index 14c61a33142..6946728abb5 100644 --- a/test/langtools/tools/javac/Diagnostics/6862608/T6862608b.java +++ b/test/langtools/tools/javac/Diagnostics/6862608/T6862608b.java @@ -3,7 +3,7 @@ * @bug 6862608 * @summary rich diagnostic sometimes contain wrong type variable numbering * @author mcimadamore - * @compile/fail/ref=T6862608b.out -XDrawDiagnostics --diags:formatterOptions=disambiguateTvars,where T6862608b.java + * @compile/fail/ref=T6862608b.out -XDrawDiagnostics --diags=formatterOptions=disambiguateTvars,where T6862608b.java */ class T66862608b { diff --git a/test/langtools/tools/javac/Diagnostics/7010608/Test.java b/test/langtools/tools/javac/Diagnostics/7010608/Test.java index 332d26a0d9d..7b8ae31ba52 100644 --- a/test/langtools/tools/javac/Diagnostics/7010608/Test.java +++ b/test/langtools/tools/javac/Diagnostics/7010608/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2018, 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,9 +46,9 @@ void run() throws Exception { try { test(Arrays.asList(), "myfo://test:1: error: cannot find symbol"); - test(Arrays.asList("--diags:layout=OLD"), + test(Arrays.asList("--diags=layout=OLD"), "myfo://test:1: cannot find symbol"); - test(Arrays.asList("--diags:legacy"), + test(Arrays.asList("--diags=legacy"), "myfo://test:1: cannot find symbol"); } finally { Locale.setDefault(prev); diff --git a/test/langtools/tools/javac/Diagnostics/8010387/T8010387.java b/test/langtools/tools/javac/Diagnostics/8010387/T8010387.java index 74a664cd160..b6cfc7c4830 100644 --- a/test/langtools/tools/javac/Diagnostics/8010387/T8010387.java +++ b/test/langtools/tools/javac/Diagnostics/8010387/T8010387.java @@ -2,7 +2,7 @@ * @test /nodynamiccopyright/ * @bug 8010387 * @summary rich diagnostic sometimes contain wrong type variable numbering - * @compile/fail/ref=T8010387.out -XDrawDiagnostics --diags:formatterOptions=disambiguateTvars,where T8010387.java + * @compile/fail/ref=T8010387.out -XDrawDiagnostics --diags=formatterOptions=disambiguateTvars,where T8010387.java */ abstract class T8010387 { diff --git a/test/langtools/tools/javac/InterfaceMemberClassModifiers.java b/test/langtools/tools/javac/InterfaceMemberClassModifiers.java index bb5fd1367e6..995653fccef 100644 --- a/test/langtools/tools/javac/InterfaceMemberClassModifiers.java +++ b/test/langtools/tools/javac/InterfaceMemberClassModifiers.java @@ -4,7 +4,7 @@ * @summary Verify that invalid access modifiers on interface members don't cause crash. * @author maddox * - * @compile/fail/ref=InterfaceMemberClassModifiers.out --diags:layout=%b:%l:%_%m InterfaceMemberClassModifiers.java + * @compile/fail/ref=InterfaceMemberClassModifiers.out --diags=layout=%b:%l:%_%m InterfaceMemberClassModifiers.java */ public interface InterfaceMemberClassModifiers { diff --git a/test/langtools/tools/javac/T6214885.java b/test/langtools/tools/javac/T6214885.java index f79b752ecbc..c667bc3e897 100644 --- a/test/langtools/tools/javac/T6214885.java +++ b/test/langtools/tools/javac/T6214885.java @@ -2,8 +2,8 @@ * @test /nodynamiccopyright/ * @bug 6214885 * @summary This test exercises features provided by the new internal Diagnostics API - * @compile/fail/ref=T6214885a.out --diags:layout=%b:%l%_%t%m|%p%m T6214885.java - * @compile/fail/ref=T6214885b.out --diags:layout=%b:%l:%c%_%t%m|%p%m T6214885.java + * @compile/fail/ref=T6214885a.out --diags=layout=%b:%l%_%t%m|%p%m T6214885.java + * @compile/fail/ref=T6214885b.out --diags=layout=%b:%l:%c%_%t%m|%p%m T6214885.java */ class T6214885 { diff --git a/test/langtools/tools/javac/T8026963/TypeAnnotationsCrashWithErroneousTreeTest.java b/test/langtools/tools/javac/T8026963/TypeAnnotationsCrashWithErroneousTreeTest.java index 49fd4d46cf7..0a940797039 100644 --- a/test/langtools/tools/javac/T8026963/TypeAnnotationsCrashWithErroneousTreeTest.java +++ b/test/langtools/tools/javac/T8026963/TypeAnnotationsCrashWithErroneousTreeTest.java @@ -2,7 +2,7 @@ * @test /nodynamiccopyright/ * @bug 8026963 * @summary type annotations code crashes for lambdas with void argument - * @compile/fail/ref=TypeAnnotationsCrashWithErroneousTreeTest.out -XDrawDiagnostics --should-stop:at=FLOW TypeAnnotationsCrashWithErroneousTreeTest.java + * @compile/fail/ref=TypeAnnotationsCrashWithErroneousTreeTest.out -XDrawDiagnostics --should-stop=at=FLOW TypeAnnotationsCrashWithErroneousTreeTest.java */ public class TypeAnnotationsCrashWithErroneousTreeTest { diff --git a/test/langtools/tools/javac/annotations/neg/8022765/VerifyErroneousAnnotationsAttributed.java b/test/langtools/tools/javac/annotations/neg/8022765/VerifyErroneousAnnotationsAttributed.java index 263a145af38..bbb296d2df7 100644 --- a/test/langtools/tools/javac/annotations/neg/8022765/VerifyErroneousAnnotationsAttributed.java +++ b/test/langtools/tools/javac/annotations/neg/8022765/VerifyErroneousAnnotationsAttributed.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, 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 @@ -237,7 +237,7 @@ void validate(String code) throws IOException, URISyntaxException { JavacTask task = tool.getTask(null, fm, devNull, - Arrays.asList("--should-stop:at=FLOW"), + Arrays.asList("--should-stop=at=FLOW"), null, Arrays.asList(new MyFileObject(code))); diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/newlocations/AfterMethodTypeParams.java b/test/langtools/tools/javac/annotations/typeAnnotations/newlocations/AfterMethodTypeParams.java index bea25e934c8..cc4d7eaf056 100644 --- a/test/langtools/tools/javac/annotations/typeAnnotations/newlocations/AfterMethodTypeParams.java +++ b/test/langtools/tools/javac/annotations/typeAnnotations/newlocations/AfterMethodTypeParams.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, 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 @@ -54,7 +54,7 @@ void run() throws IOException { String test = TEMPLATE.replace("CONTENT", tc.snippet); List files = Arrays.asList(new MyFileObject(test)); StringWriter out = new StringWriter(); - List options = Arrays.asList("-XDrawDiagnostics", "--should-stop:at=FLOW"); + List options = Arrays.asList("-XDrawDiagnostics", "--should-stop=at=FLOW"); JavacTask task = (JavacTask) compiler.getTask(out, null, null, options, null, files); new TreePathScanner() { diff --git a/test/langtools/tools/javac/api/6731573/T6731573.java b/test/langtools/tools/javac/api/6731573/T6731573.java index 435e2b26f98..0d7ceb8fd2f 100644 --- a/test/langtools/tools/javac/api/6731573/T6731573.java +++ b/test/langtools/tools/javac/api/6731573/T6731573.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2018, 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 @@ -62,8 +62,8 @@ boolean shouldDisplaySource(SourceLine sourceLine) { enum SourceLine { STANDARD(null), - ENABLED("--diags:showSource=true"), - DISABLED("--diags:showSource=false"); + ENABLED("--diags=showSource=true"), + DISABLED("--diags=showSource=false"); String optValue; diff --git a/test/langtools/tools/javac/api/taskListeners/EventsBalancedTest.java b/test/langtools/tools/javac/api/taskListeners/EventsBalancedTest.java index b55053c7a81..bd01d192b6e 100644 --- a/test/langtools/tools/javac/api/taskListeners/EventsBalancedTest.java +++ b/test/langtools/tools/javac/api/taskListeners/EventsBalancedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, 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 @@ -63,11 +63,11 @@ void test() throws IOException { test(null, Arrays.asList(b, a)); for (CompileState stop : CompileState.values()) { - test(Arrays.asList("--should-stop:ifNoError=" + stop, - "--should-stop:ifError=" + stop), + test(Arrays.asList("--should-stop=ifNoError=" + stop, + "--should-stop=ifError=" + stop), Arrays.asList(a, b)); - test(Arrays.asList("--should-stop:ifNoError=" + stop, - "--should-stop:ifError=" + stop), + test(Arrays.asList("--should-stop=ifNoError=" + stop, + "--should-stop=ifError=" + stop), Arrays.asList(b, a)); } } diff --git a/test/langtools/tools/javac/completionDeps/DepsAndAnno.java b/test/langtools/tools/javac/completionDeps/DepsAndAnno.java index 8ba7f54e183..07e70210392 100644 --- a/test/langtools/tools/javac/completionDeps/DepsAndAnno.java +++ b/test/langtools/tools/javac/completionDeps/DepsAndAnno.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, 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,7 @@ public class DepsAndAnno { public static void main(String[] args) { ToolBox toolBox = new ToolBox(); new JavacTask(toolBox, Task.Mode.CMDLINE) - .options("--debug:completionDeps") + .options("--debug=completionDeps") .outdir(".") .files(ToolBox.testSrc + "/DepsAndAnno.java") .run(); diff --git a/test/langtools/tools/javac/completionDeps/DepsAndDocLint.java b/test/langtools/tools/javac/completionDeps/DepsAndDocLint.java index b9df5e72b3d..b2fcf8c130d 100644 --- a/test/langtools/tools/javac/completionDeps/DepsAndDocLint.java +++ b/test/langtools/tools/javac/completionDeps/DepsAndDocLint.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, 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,7 +25,7 @@ * @test * @bug 8078389 * @summary Make sure there is no interference between completionDeps and doclint - * @compile --debug:completionDeps -Xdoclint DepsAndDocLint.java + * @compile --debug=completionDeps -Xdoclint DepsAndDocLint.java */ public class DepsAndDocLint { diff --git a/test/langtools/tools/javac/diags/examples/ApplicableMethodFound.java b/test/langtools/tools/javac/diags/examples/ApplicableMethodFound.java index bb324afa790..70d53c67fdf 100644 --- a/test/langtools/tools/javac/diags/examples/ApplicableMethodFound.java +++ b/test/langtools/tools/javac/diags/examples/ApplicableMethodFound.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2018, 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,7 +23,7 @@ // key: compiler.misc.applicable.method.found // key: compiler.note.verbose.resolve.multi -// options: --debug:verboseResolution=applicable,success +// options: --debug=verboseResolution=applicable,success class ApplicableMethodFound { diff --git a/test/langtools/tools/javac/diags/examples/ApplicableMethodFound1.java b/test/langtools/tools/javac/diags/examples/ApplicableMethodFound1.java index 5ecca3a329f..21f5f49cc59 100644 --- a/test/langtools/tools/javac/diags/examples/ApplicableMethodFound1.java +++ b/test/langtools/tools/javac/diags/examples/ApplicableMethodFound1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2018, 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,7 +24,7 @@ // key: compiler.misc.applicable.method.found.1 // key: compiler.note.verbose.resolve.multi // key: compiler.misc.partial.inst.sig -// options: --debug:verboseResolution=applicable,success +// options: --debug=verboseResolution=applicable,success class ApplicableMethodFound1 { diff --git a/test/langtools/tools/javac/diags/examples/DeferredMethodInst.java b/test/langtools/tools/javac/diags/examples/DeferredMethodInst.java index 59bfd4c37f8..d641d41946f 100644 --- a/test/langtools/tools/javac/diags/examples/DeferredMethodInst.java +++ b/test/langtools/tools/javac/diags/examples/DeferredMethodInst.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2018, 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,7 +25,7 @@ // key: compiler.note.verbose.resolve.multi // key: compiler.note.deferred.method.inst // key: compiler.misc.partial.inst.sig -// options: --debug:verboseResolution=applicable,success,deferred-inference +// options: --debug=verboseResolution=applicable,success,deferred-inference class DeferredMethodInst { diff --git a/test/langtools/tools/javac/diags/examples/LambdaDeduplicate.java b/test/langtools/tools/javac/diags/examples/LambdaDeduplicate.java index da6c4e3f720..8dda7bb2dd9 100644 --- a/test/langtools/tools/javac/diags/examples/LambdaDeduplicate.java +++ b/test/langtools/tools/javac/diags/examples/LambdaDeduplicate.java @@ -23,7 +23,7 @@ // key: compiler.note.verbose.l2m.deduplicate -// options: --debug:dumpLambdaToMethodDeduplication +// options: --debug=dumpLambdaToMethodDeduplication import java.util.function.Function; diff --git a/test/langtools/tools/javac/diags/examples/LambdaStat.java b/test/langtools/tools/javac/diags/examples/LambdaStat.java index c3ee38d6f8e..23b5809ea2c 100644 --- a/test/langtools/tools/javac/diags/examples/LambdaStat.java +++ b/test/langtools/tools/javac/diags/examples/LambdaStat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, 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 @@ -22,7 +22,7 @@ */ // key: compiler.note.lambda.stat -// options: --debug:dumpLambdaToMethodStats +// options: --debug=dumpLambdaToMethodStats class LambdaStat { Runnable r = ()->{}; diff --git a/test/langtools/tools/javac/diags/examples/MrefStat.java b/test/langtools/tools/javac/diags/examples/MrefStat.java index 7f84baa8ca0..ef11f97b82f 100644 --- a/test/langtools/tools/javac/diags/examples/MrefStat.java +++ b/test/langtools/tools/javac/diags/examples/MrefStat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, 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 @@ -22,7 +22,7 @@ */ // key: compiler.note.mref.stat -// options: --debug:dumpLambdaToMethodStats +// options: --debug=dumpLambdaToMethodStats class MrefStat { Runnable r = MrefStat::m; diff --git a/test/langtools/tools/javac/diags/examples/MrefStat1.java b/test/langtools/tools/javac/diags/examples/MrefStat1.java index c4bdf4cff2d..6250fd7f33f 100644 --- a/test/langtools/tools/javac/diags/examples/MrefStat1.java +++ b/test/langtools/tools/javac/diags/examples/MrefStat1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, 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 @@ -22,7 +22,7 @@ */ // key: compiler.note.mref.stat.1 -// options: --debug:dumpLambdaToMethodStats +// options: --debug=dumpLambdaToMethodStats class MrefStat1 { diff --git a/test/langtools/tools/javac/diags/examples/NotApplicableMethodFound.java b/test/langtools/tools/javac/diags/examples/NotApplicableMethodFound.java index dc199bc3e38..ef23a3d8f10 100644 --- a/test/langtools/tools/javac/diags/examples/NotApplicableMethodFound.java +++ b/test/langtools/tools/javac/diags/examples/NotApplicableMethodFound.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ // key: compiler.err.cant.apply.symbol // key: compiler.misc.no.conforming.assignment.exists // key: compiler.misc.inconvertible.types -// options: --debug:verboseResolution=inapplicable,failure +// options: --debug=verboseResolution=inapplicable,failure class NotApplicableMethodFound { diff --git a/test/langtools/tools/javac/diags/examples/PartialInstSig.java b/test/langtools/tools/javac/diags/examples/PartialInstSig.java index 4a56058856f..41d8355742c 100644 --- a/test/langtools/tools/javac/diags/examples/PartialInstSig.java +++ b/test/langtools/tools/javac/diags/examples/PartialInstSig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2018, 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,7 +24,7 @@ // key: compiler.misc.applicable.method.found.1 // key: compiler.note.verbose.resolve.multi // key: compiler.misc.partial.inst.sig -// options: --debug:verboseResolution=applicable,success +// options: --debug=verboseResolution=applicable,success class PartialInstSig { diff --git a/test/langtools/tools/javac/diags/examples/VerboseResolveMulti.java b/test/langtools/tools/javac/diags/examples/VerboseResolveMulti.java index c097c74085a..107cd2fbd25 100644 --- a/test/langtools/tools/javac/diags/examples/VerboseResolveMulti.java +++ b/test/langtools/tools/javac/diags/examples/VerboseResolveMulti.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2018, 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,7 +23,7 @@ // key: compiler.misc.applicable.method.found // key: compiler.note.verbose.resolve.multi -// options: --debug:verboseResolution=applicable,success +// options: --debug=verboseResolution=applicable,success class VerboseResolveMulti { diff --git a/test/langtools/tools/javac/diags/examples/VerboseResolveMulti1.java b/test/langtools/tools/javac/diags/examples/VerboseResolveMulti1.java index 33e7a2deef4..152bbe54d7d 100644 --- a/test/langtools/tools/javac/diags/examples/VerboseResolveMulti1.java +++ b/test/langtools/tools/javac/diags/examples/VerboseResolveMulti1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ // key: compiler.err.cant.apply.symbol // key: compiler.misc.no.conforming.assignment.exists // key: compiler.misc.inconvertible.types -// options: --debug:verboseResolution=inapplicable,failure +// options: --debug=verboseResolution=inapplicable,failure class VerboseResolveMulti1 { diff --git a/test/langtools/tools/javac/diags/examples/WhereCaptured.java b/test/langtools/tools/javac/diags/examples/WhereCaptured.java index 22fc86530dd..532be002234 100644 --- a/test/langtools/tools/javac/diags/examples/WhereCaptured.java +++ b/test/langtools/tools/javac/diags/examples/WhereCaptured.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2018, 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,7 +28,7 @@ // key: compiler.err.cant.apply.symbol // key: compiler.misc.incompatible.eq.bounds // key: compiler.misc.captured.type -// options: --diags:formatterOptions=where,simpleNames +// options: --diags=formatterOptions=where,simpleNames // run: simple import java.util.*; diff --git a/test/langtools/tools/javac/diags/examples/WhereCaptured1.java b/test/langtools/tools/javac/diags/examples/WhereCaptured1.java index 26fdf3e8f5b..7a71e52432f 100644 --- a/test/langtools/tools/javac/diags/examples/WhereCaptured1.java +++ b/test/langtools/tools/javac/diags/examples/WhereCaptured1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2018, 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,7 +29,7 @@ // key: compiler.misc.incompatible.eq.bounds // key: compiler.misc.captured.type // key: compiler.misc.type.null -// options: --diags:formatterOptions=where,simpleNames +// options: --diags=formatterOptions=where,simpleNames // run: simple import java.util.*; diff --git a/test/langtools/tools/javac/diags/examples/WhereFreshTvar.java b/test/langtools/tools/javac/diags/examples/WhereFreshTvar.java index fb060c89c1e..5d796c6108d 100644 --- a/test/langtools/tools/javac/diags/examples/WhereFreshTvar.java +++ b/test/langtools/tools/javac/diags/examples/WhereFreshTvar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, 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,7 +25,7 @@ // key: compiler.misc.where.description.typevar // key: compiler.err.prob.found.req // key: compiler.misc.inconvertible.types -// options: --diags:formatterOptions=where,simpleNames +// options: --diags=formatterOptions=where,simpleNames // run: simple import java.util.*; diff --git a/test/langtools/tools/javac/diags/examples/WhereIntersection.java b/test/langtools/tools/javac/diags/examples/WhereIntersection.java index beec1d7cd6e..65c959136e0 100644 --- a/test/langtools/tools/javac/diags/examples/WhereIntersection.java +++ b/test/langtools/tools/javac/diags/examples/WhereIntersection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ // key: compiler.misc.where.description.intersection.1 // key: compiler.misc.where.intersection // key: compiler.err.prob.found.req -// options: --diags:formatterOptions=where +// options: --diags=formatterOptions=where // run: simple class WhereIntersection { diff --git a/test/langtools/tools/javac/diags/examples/WhereIntersection2.java b/test/langtools/tools/javac/diags/examples/WhereIntersection2.java index 91cab029c46..5732a822e3c 100644 --- a/test/langtools/tools/javac/diags/examples/WhereIntersection2.java +++ b/test/langtools/tools/javac/diags/examples/WhereIntersection2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2018, 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,7 +29,7 @@ // key: compiler.misc.where.description.intersection // key: compiler.misc.where.intersection // key: compiler.err.prob.found.req -// options: --diags:formatterOptions=where +// options: --diags=formatterOptions=where // run: simple class WhereIntersection2 { diff --git a/test/langtools/tools/javac/diags/examples/WhereTypeVar.java b/test/langtools/tools/javac/diags/examples/WhereTypeVar.java index 55097a8ce6a..69aee4bf738 100644 --- a/test/langtools/tools/javac/diags/examples/WhereTypeVar.java +++ b/test/langtools/tools/javac/diags/examples/WhereTypeVar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2018, 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,7 @@ // key: compiler.err.cant.apply.symbol // key: compiler.misc.no.conforming.assignment.exists // key: compiler.misc.inconvertible.types -// options: --diags:formatterOptions=where,disambiguateTvars +// options: --diags=formatterOptions=where,disambiguateTvars // run: simple class WhereTypeVar { diff --git a/test/langtools/tools/javac/diags/examples/WhereTypeVar2.java b/test/langtools/tools/javac/diags/examples/WhereTypeVar2.java index 1f6f51b9431..38d160f0e12 100644 --- a/test/langtools/tools/javac/diags/examples/WhereTypeVar2.java +++ b/test/langtools/tools/javac/diags/examples/WhereTypeVar2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2018, 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,7 +25,7 @@ // key: compiler.misc.where.description.typevar // key: compiler.misc.where.typevar // key: compiler.err.prob.found.req -// options: --diags:formatterOptions=where +// options: --diags=formatterOptions=where // run: simple class WhereTypeVar2 { diff --git a/test/langtools/tools/javac/failover/CheckAttributedTree.java b/test/langtools/tools/javac/failover/CheckAttributedTree.java index 88d8e974fae..91b80eef0dd 100644 --- a/test/langtools/tools/javac/failover/CheckAttributedTree.java +++ b/test/langtools/tools/javac/failover/CheckAttributedTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2018, 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 @@ -315,7 +315,7 @@ void readAndCheck(File file, BiConsumer c) throws IOE totalNumberOfCompilations++; newCompilationTask() .withWriter(pw) - .withOption("--should-stop:at=ATTR") + .withOption("--should-stop=at=ATTR") .withOption("-XDverboseCompilePolicy") .withOption("-Xdoclint:none") .withSource(files.iterator().next()) diff --git a/test/langtools/tools/javac/failover/FailOver01.java b/test/langtools/tools/javac/failover/FailOver01.java index e8d4da79272..79181e10a8c 100644 --- a/test/langtools/tools/javac/failover/FailOver01.java +++ b/test/langtools/tools/javac/failover/FailOver01.java @@ -4,7 +4,7 @@ * @summary Flow.java should be more error-friendly * @author mcimadamore * - * @compile/fail/ref=FailOver01.out -XDrawDiagnostics --should-stop:at=FLOW -XDdev FailOver01.java + * @compile/fail/ref=FailOver01.out -XDrawDiagnostics --should-stop=at=FLOW -XDdev FailOver01.java */ class Test { { x = "" } } diff --git a/test/langtools/tools/javac/failover/FailOver02.java b/test/langtools/tools/javac/failover/FailOver02.java index 0aac6fa4546..0835ae2d155 100644 --- a/test/langtools/tools/javac/failover/FailOver02.java +++ b/test/langtools/tools/javac/failover/FailOver02.java @@ -4,7 +4,7 @@ * @summary Flow.java should be more error-friendly * @author mcimadamore * - * @compile/fail/ref=FailOver02.out -XDrawDiagnostics --should-stop:at=FLOW -XDdev FailOver02.java + * @compile/fail/ref=FailOver02.out -XDrawDiagnostics --should-stop=at=FLOW -XDdev FailOver02.java */ class Test implements AutoCloseable { diff --git a/test/langtools/tools/javac/failover/FailOver03.java b/test/langtools/tools/javac/failover/FailOver03.java index cdfe3a8d81c..6638480f54f 100644 --- a/test/langtools/tools/javac/failover/FailOver03.java +++ b/test/langtools/tools/javac/failover/FailOver03.java @@ -4,7 +4,7 @@ * @summary Flow.java should be more error-friendly * @author mcimadamore * - * @compile/fail/ref=FailOver03.out -XDrawDiagnostics --should-stop:at=FLOW -XDdev FailOver03.java + * @compile/fail/ref=FailOver03.out -XDrawDiagnostics --should-stop=at=FLOW -XDdev FailOver03.java */ class Test extends Test { diff --git a/test/langtools/tools/javac/failover/FailOver04.java b/test/langtools/tools/javac/failover/FailOver04.java index e9a723d1a19..893f2aaa3fb 100644 --- a/test/langtools/tools/javac/failover/FailOver04.java +++ b/test/langtools/tools/javac/failover/FailOver04.java @@ -4,7 +4,7 @@ * @summary Flow.java should be more error-friendly * @author mcimadamore * - * @compile/fail/ref=FailOver04.out -XDrawDiagnostics --should-stop:at=FLOW -XDdev FailOver04.java + * @compile/fail/ref=FailOver04.out -XDrawDiagnostics --should-stop=at=FLOW -XDdev FailOver04.java */ class Test { diff --git a/test/langtools/tools/javac/failover/FailOver05.java b/test/langtools/tools/javac/failover/FailOver05.java index cbbbc222b7c..cfd8d49da6b 100644 --- a/test/langtools/tools/javac/failover/FailOver05.java +++ b/test/langtools/tools/javac/failover/FailOver05.java @@ -4,7 +4,7 @@ * @summary Flow.java should be more error-friendly * @author mcimadamore * - * @compile/fail/ref=FailOver05.out -XDrawDiagnostics --should-stop:at=FLOW -XDdev FailOver05.java + * @compile/fail/ref=FailOver05.out -XDrawDiagnostics --should-stop=at=FLOW -XDdev FailOver05.java */ class Test extends Test { diff --git a/test/langtools/tools/javac/failover/FailOver06.java b/test/langtools/tools/javac/failover/FailOver06.java index 14f7fa34f97..cde419c3d98 100644 --- a/test/langtools/tools/javac/failover/FailOver06.java +++ b/test/langtools/tools/javac/failover/FailOver06.java @@ -4,7 +4,7 @@ * @summary Flow.java should be more error-friendly * @author mcimadamore * - * @compile/fail/ref=FailOver06.out -XDrawDiagnostics --should-stop:at=FLOW -XDdev FailOver06.java + * @compile/fail/ref=FailOver06.out -XDrawDiagnostics --should-stop=at=FLOW -XDdev FailOver06.java */ class Test extends Test { diff --git a/test/langtools/tools/javac/failover/FailOver07.java b/test/langtools/tools/javac/failover/FailOver07.java index a73037a0e99..21b1688e13f 100644 --- a/test/langtools/tools/javac/failover/FailOver07.java +++ b/test/langtools/tools/javac/failover/FailOver07.java @@ -4,7 +4,7 @@ * @summary Flow.java should be more error-friendly * @author mcimadamore * - * @compile/fail/ref=FailOver07.out -XDrawDiagnostics --should-stop:at=FLOW -XDdev FailOver07.java + * @compile/fail/ref=FailOver07.out -XDrawDiagnostics --should-stop=at=FLOW -XDdev FailOver07.java */ class Test extends Test { diff --git a/test/langtools/tools/javac/failover/FailOver08.java b/test/langtools/tools/javac/failover/FailOver08.java index d2446ae59af..59eea3414b1 100644 --- a/test/langtools/tools/javac/failover/FailOver08.java +++ b/test/langtools/tools/javac/failover/FailOver08.java @@ -4,7 +4,7 @@ * @summary Flow.java should be more error-friendly * @author mcimadamore * - * @compile/fail/ref=FailOver08.out -XDrawDiagnostics --should-stop:at=FLOW -XDdev FailOver08.java + * @compile/fail/ref=FailOver08.out -XDrawDiagnostics --should-stop=at=FLOW -XDdev FailOver08.java */ class Test extends Test { diff --git a/test/langtools/tools/javac/failover/FailOver09.java b/test/langtools/tools/javac/failover/FailOver09.java index bc126e140f6..67b83e527a5 100644 --- a/test/langtools/tools/javac/failover/FailOver09.java +++ b/test/langtools/tools/javac/failover/FailOver09.java @@ -4,7 +4,7 @@ * @summary Flow.java should be more error-friendly * @author mcimadamore * - * @compile/fail/ref=FailOver09.out -XDrawDiagnostics --should-stop:at=FLOW -XDdev FailOver09.java + * @compile/fail/ref=FailOver09.out -XDrawDiagnostics --should-stop=at=FLOW -XDdev FailOver09.java */ class Test extends Test { diff --git a/test/langtools/tools/javac/failover/FailOver10.java b/test/langtools/tools/javac/failover/FailOver10.java index 5d32c85437d..288337f16f2 100644 --- a/test/langtools/tools/javac/failover/FailOver10.java +++ b/test/langtools/tools/javac/failover/FailOver10.java @@ -4,7 +4,7 @@ * @summary Flow.java should be more error-friendly * @author mcimadamore * - * @compile/fail/ref=FailOver10.out -XDrawDiagnostics --should-stop:at=FLOW -XDdev FailOver10.java + * @compile/fail/ref=FailOver10.out -XDrawDiagnostics --should-stop=at=FLOW -XDdev FailOver10.java */ class Test extends Test { diff --git a/test/langtools/tools/javac/failover/FailOver11.java b/test/langtools/tools/javac/failover/FailOver11.java index 863053982bc..13fe3a83b45 100644 --- a/test/langtools/tools/javac/failover/FailOver11.java +++ b/test/langtools/tools/javac/failover/FailOver11.java @@ -4,7 +4,7 @@ * @summary Flow.java should be more error-friendly * @author mcimadamore * - * @compile/fail/ref=FailOver11.out -XDrawDiagnostics --should-stop:at=FLOW -XDdev FailOver11.java + * @compile/fail/ref=FailOver11.out -XDrawDiagnostics --should-stop=at=FLOW -XDdev FailOver11.java */ class Test extends Test { diff --git a/test/langtools/tools/javac/failover/FailOver12.java b/test/langtools/tools/javac/failover/FailOver12.java index ed8699e039c..99ad97445a7 100644 --- a/test/langtools/tools/javac/failover/FailOver12.java +++ b/test/langtools/tools/javac/failover/FailOver12.java @@ -4,7 +4,7 @@ * @summary Flow.java should be more error-friendly * @author mcimadamore * - * @compile/fail/ref=FailOver12.out -XDrawDiagnostics --should-stop:at=FLOW -XDdev FailOver12.java + * @compile/fail/ref=FailOver12.out -XDrawDiagnostics --should-stop=at=FLOW -XDdev FailOver12.java */ class Test extends Test { diff --git a/test/langtools/tools/javac/failover/FailOver13.java b/test/langtools/tools/javac/failover/FailOver13.java index f85249d0833..02606b4d7b0 100644 --- a/test/langtools/tools/javac/failover/FailOver13.java +++ b/test/langtools/tools/javac/failover/FailOver13.java @@ -4,7 +4,7 @@ * @summary Flow.java should be more error-friendly * @author mcimadamore * - * @compile/fail/ref=FailOver13.out -XDrawDiagnostics --should-stop:at=FLOW -XDdev FailOver13.java + * @compile/fail/ref=FailOver13.out -XDrawDiagnostics --should-stop=at=FLOW -XDdev FailOver13.java */ class Test extends Test { diff --git a/test/langtools/tools/javac/failover/FailOver14.java b/test/langtools/tools/javac/failover/FailOver14.java index c0d3ab78abd..fc9e0fe3df8 100644 --- a/test/langtools/tools/javac/failover/FailOver14.java +++ b/test/langtools/tools/javac/failover/FailOver14.java @@ -4,7 +4,7 @@ * @summary Flow.java should be more error-friendly * @author mcimadamore * - * @compile/fail/ref=FailOver14.out -XDrawDiagnostics --should-stop:at=FLOW -XDdev FailOver14.java + * @compile/fail/ref=FailOver14.out -XDrawDiagnostics --should-stop=at=FLOW -XDdev FailOver14.java */ class Test extends Test { diff --git a/test/langtools/tools/javac/failover/FailOver15.java b/test/langtools/tools/javac/failover/FailOver15.java index 619cfd3a5ac..de64f4fb386 100644 --- a/test/langtools/tools/javac/failover/FailOver15.java +++ b/test/langtools/tools/javac/failover/FailOver15.java @@ -3,7 +3,7 @@ * @bug 6970584 7060926 * @summary Attr.PostAttrAnalyzer misses a case * - * @compile/fail/ref=FailOver15.out -XDrawDiagnostics --should-stop:at=FLOW -XDdev FailOver15.java + * @compile/fail/ref=FailOver15.out -XDrawDiagnostics --should-stop=at=FLOW -XDdev FailOver15.java */ class Test { diff --git a/test/langtools/tools/javac/generics/inference/8158355/T8158355.java b/test/langtools/tools/javac/generics/inference/8158355/T8158355.java index edc6fe95254..08c7ae280a3 100644 --- a/test/langtools/tools/javac/generics/inference/8158355/T8158355.java +++ b/test/langtools/tools/javac/generics/inference/8158355/T8158355.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, 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,7 @@ * @test * @bug 8158355 * @summary Inference graph dot support broken - * @compile --debug:dumpInferenceGraphsTo=. T8158355.java + * @compile --debug=dumpInferenceGraphsTo=. T8158355.java */ import java.util.List; diff --git a/test/langtools/tools/javac/lambda/MostSpecific09.java b/test/langtools/tools/javac/lambda/MostSpecific09.java index d7883a45c55..ef685ab541e 100644 --- a/test/langtools/tools/javac/lambda/MostSpecific09.java +++ b/test/langtools/tools/javac/lambda/MostSpecific09.java @@ -2,7 +2,7 @@ * @test /nodynamiccopyright/ * @bug 8029718 8065800 * @summary Should always use lambda body structure to disambiguate overload resolution - * @compile/fail/ref=MostSpecific09.out -XDrawDiagnostics --should-stop:at=ATTR --debug:verboseResolution=applicable,success MostSpecific09.java + * @compile/fail/ref=MostSpecific09.out -XDrawDiagnostics --should-stop=at=ATTR --debug=verboseResolution=applicable,success MostSpecific09.java */ class MostSpecific09 { diff --git a/test/langtools/tools/javac/lambda/TestLambdaToMethodStats.java b/test/langtools/tools/javac/lambda/TestLambdaToMethodStats.java index bd8f219fcfb..dad07d1b2d4 100644 --- a/test/langtools/tools/javac/lambda/TestLambdaToMethodStats.java +++ b/test/langtools/tools/javac/lambda/TestLambdaToMethodStats.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, 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 @@ -122,7 +122,7 @@ public static void main(String... args) throws Exception { @Override public void doWork() throws IOException { newCompilationTask() - .withOption("--debug:dumpLambdaToMethodStats") + .withOption("--debug=dumpLambdaToMethodStats") .withSourceFromTemplate(template) .generate(this::check); } diff --git a/test/langtools/tools/javac/lambda/XDdumpLambdaToMethodStats.java b/test/langtools/tools/javac/lambda/XDdumpLambdaToMethodStats.java index 53b42d9d14a..e1b399ee6b0 100644 --- a/test/langtools/tools/javac/lambda/XDdumpLambdaToMethodStats.java +++ b/test/langtools/tools/javac/lambda/XDdumpLambdaToMethodStats.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, 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,7 +25,7 @@ * @test * @bug 8143217 * @summary javac throws NPE when printing diagnostics for Lambda expressions - * @compile XDdumpLambdaToMethodStats.java --debug:dumpLambdaToMethodStats + * @compile XDdumpLambdaToMethodStats.java --debug=dumpLambdaToMethodStats * */ diff --git a/test/langtools/tools/javac/lambda/bridge/TestMetafactoryBridges.java b/test/langtools/tools/javac/lambda/bridge/TestMetafactoryBridges.java index a61c9d4b344..6542d83b582 100644 --- a/test/langtools/tools/javac/lambda/bridge/TestMetafactoryBridges.java +++ b/test/langtools/tools/javac/lambda/bridge/TestMetafactoryBridges.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, 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 @@ -274,7 +274,7 @@ void run(JavaCompiler tool) throws Exception { sourcefiles.add(new JavaSource(ck)); } JavacTask ct = (JavacTask)tool.getTask(debugWriter, null, diagChecker, - Arrays.asList("--debug:dumpLambdaToMethodStats", "-d", outDir.getAbsolutePath(), + Arrays.asList("--debug=dumpLambdaToMethodStats", "-d", outDir.getAbsolutePath(), "-sourcepath", srcDir.getAbsolutePath(), "-classpath", classesDir.getAbsolutePath(), pp.preferOpt), null, sourcefiles); diff --git a/test/langtools/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java b/test/langtools/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java index 5a016c9c08c..1234e6bdd8c 100644 --- a/test/langtools/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java +++ b/test/langtools/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018, 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 @@ -210,7 +210,7 @@ boolean hasSameOverloadPhase() { public void doWork() throws Throwable { newCompilationTask() .withSourceFromTemplate(sourceTemplate) - .withOption("--debug:verboseResolution=all,-predef,-internal,-object-init") + .withOption("--debug=verboseResolution=all,-predef,-internal,-object-init") .analyze(this::check); } diff --git a/test/langtools/tools/javac/missingSuperRecovery/MissingSuperRecovery.java b/test/langtools/tools/javac/missingSuperRecovery/MissingSuperRecovery.java index 5e58732f04c..e5ef4725a0f 100644 --- a/test/langtools/tools/javac/missingSuperRecovery/MissingSuperRecovery.java +++ b/test/langtools/tools/javac/missingSuperRecovery/MissingSuperRecovery.java @@ -5,7 +5,7 @@ * class is no longer available during a subsequent compilation. * @author maddox * @build impl - * @compile/fail/ref=MissingSuperRecovery.out --diags:layout=%b:%l:%_%m MissingSuperRecovery.java + * @compile/fail/ref=MissingSuperRecovery.out --diags=layout=%b:%l:%_%m MissingSuperRecovery.java */ // Requires "golden" class file 'impl.class', which contains diff --git a/test/langtools/tools/javac/modules/AddLimitMods.java b/test/langtools/tools/javac/modules/AddLimitMods.java index 0b87acd6fe6..e1f6b884b00 100644 --- a/test/langtools/tools/javac/modules/AddLimitMods.java +++ b/test/langtools/tools/javac/modules/AddLimitMods.java @@ -120,7 +120,7 @@ public void testManual(Path base) throws Exception { //real test new JavacTask(tb) .options("--module-path", modulePath.toString(), - "--should-stop:ifNoError=FLOW", + "--should-stop=ifNoError=FLOW", "--limit-modules", "java.base") .outdir(modulePath) .files(findJavaFiles(m1)) @@ -129,7 +129,7 @@ public void testManual(Path base) throws Exception { new JavacTask(tb) .options("--module-path", modulePath.toString(), - "--should-stop:ifNoError=FLOW", + "--should-stop=ifNoError=FLOW", "--limit-modules", "java.base", "--add-modules", "m2x") .outdir(modulePath) @@ -139,7 +139,7 @@ public void testManual(Path base) throws Exception { new JavacTask(tb) .options("--module-path", modulePath.toString(), - "--should-stop:ifNoError=FLOW", + "--should-stop=ifNoError=FLOW", "--limit-modules", "java.base", "--add-modules", "m2x,m3x") .outdir(modulePath) @@ -149,7 +149,7 @@ public void testManual(Path base) throws Exception { new JavacTask(tb) .options("--module-path", modulePath.toString(), - "--should-stop:ifNoError=FLOW", + "--should-stop=ifNoError=FLOW", "--limit-modules", "m2x") .outdir(modulePath) .files(findJavaFiles(m1)) @@ -158,7 +158,7 @@ public void testManual(Path base) throws Exception { new JavacTask(tb) .options("--module-path", modulePath.toString(), - "--should-stop:ifNoError=FLOW", + "--should-stop=ifNoError=FLOW", "--limit-modules", "m3x") .outdir(modulePath) .files(findJavaFiles(m1)) @@ -167,7 +167,7 @@ public void testManual(Path base) throws Exception { new JavacTask(tb) .options("--module-path", modulePath.toString(), - "--should-stop:ifNoError=FLOW", + "--should-stop=ifNoError=FLOW", "--limit-modules", "m3x", "--add-modules", "m2x") .outdir(modulePath) @@ -430,7 +430,7 @@ public void testRuntime2Compile(Path base) throws Exception { auxOptions, "--module-path", modulePath.toString(), "--class-path", classpathOut.toString(), - "--should-stop:ifNoError=FLOW")) + "--should-stop=ifNoError=FLOW")) .outdir(modulePath) .files(findJavaFiles(m2)) .run(success ? Task.Expect.SUCCESS : Task.Expect.FAIL) diff --git a/test/langtools/tools/javac/options/IsSupportedOptionTest.java b/test/langtools/tools/javac/options/IsSupportedOptionTest.java index 1dbf52d52d5..b70230e34dc 100644 --- a/test/langtools/tools/javac/options/IsSupportedOptionTest.java +++ b/test/langtools/tools/javac/options/IsSupportedOptionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -52,7 +52,7 @@ public void run() throws Exception { check(tool, "-Xdoclint", 0); check(tool, "-Xdoclint:stats", 0); check(tool, "-Xdoclint/package:foo", 0); - check(tool, "--debug:any", 0); + check(tool, "--debug=any", 1); check(tool, "-g", 0); check(tool, "-g:vars", 0); check(tool, "-g:none", 0); diff --git a/test/langtools/tools/javac/policy/test3/Test.java b/test/langtools/tools/javac/policy/test3/Test.java index 8f620a700b7..4b3352eb842 100644 --- a/test/langtools/tools/javac/policy/test3/Test.java +++ b/test/langtools/tools/javac/policy/test3/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ import java.io.*; import java.util.*; -// Simple test of --should-stop:at. +// Simple test of --should-stop=at. // For each of the permissable values, we compile a file with an error in it, // then using -XDverboseCompilePolicy we check that the compilation gets as // far as expected, but no further. @@ -83,7 +83,7 @@ public void test(CompilePolicy cp, ShouldStopPolicy ssp) { args.add("-d"); args.add("."); if (ssp.needOption) - args.add("--should-stop:at=" + ssp); + args.add("--should-stop=at=" + ssp); args.add(new File(System.getProperty("test.src", "."), "A.java").getPath()); StringWriter sw = new StringWriter(); diff --git a/test/langtools/tools/javac/positions/TreeEndPosTest.java b/test/langtools/tools/javac/positions/TreeEndPosTest.java index 523ec5dcf3c..007a71db55c 100644 --- a/test/langtools/tools/javac/positions/TreeEndPosTest.java +++ b/test/langtools/tools/javac/positions/TreeEndPosTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, 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 @@ -145,7 +145,7 @@ static void compile(JavaSource src) throws IOException { options.add(tempDir.getPath()); options.add("-d"); options.add(tempDir.getPath()); - options.add("--should-stop:at=GENERATE"); + options.add("--should-stop=at=GENERATE"); List sources = new ArrayList<>(); sources.add(src); diff --git a/test/langtools/tools/javac/protectedAccess/ProtectedMemberAccess2.java b/test/langtools/tools/javac/protectedAccess/ProtectedMemberAccess2.java index 5910eaa73c4..b90e6dee6ff 100644 --- a/test/langtools/tools/javac/protectedAccess/ProtectedMemberAccess2.java +++ b/test/langtools/tools/javac/protectedAccess/ProtectedMemberAccess2.java @@ -4,7 +4,7 @@ * @summary Verify correct implementation of JLS2e 6.6.2.1 * @author maddox * - * @compile/fail/ref=ProtectedMemberAccess2.out --diags:formatterOptions=-simpleNames;layout=%b:%l:%_%m ProtectedMemberAccess2.java + * @compile/fail/ref=ProtectedMemberAccess2.out --diags=formatterOptions=-simpleNames;layout=%b:%l:%_%m ProtectedMemberAccess2.java */ // 71 errors expected. diff --git a/test/langtools/tools/javac/protectedAccess/ProtectedMemberAccess3.java b/test/langtools/tools/javac/protectedAccess/ProtectedMemberAccess3.java index 82b8d1b51a1..814f50e9dc1 100644 --- a/test/langtools/tools/javac/protectedAccess/ProtectedMemberAccess3.java +++ b/test/langtools/tools/javac/protectedAccess/ProtectedMemberAccess3.java @@ -4,7 +4,7 @@ * @summary Verify correct implementation of JLS2e 6.6.2.1 * @author maddox * - * @compile/fail/ref=ProtectedMemberAccess3.out --diags:formatterOptions=-simpleNames;layout=%b:%l:%_%m ProtectedMemberAccess3.java + * @compile/fail/ref=ProtectedMemberAccess3.out --diags=formatterOptions=-simpleNames;layout=%b:%l:%_%m ProtectedMemberAccess3.java */ // 46 errors expected. diff --git a/test/langtools/tools/javac/protectedAccess/ProtectedMemberAccess4.java b/test/langtools/tools/javac/protectedAccess/ProtectedMemberAccess4.java index d8a55813524..bd3ce83b0fe 100644 --- a/test/langtools/tools/javac/protectedAccess/ProtectedMemberAccess4.java +++ b/test/langtools/tools/javac/protectedAccess/ProtectedMemberAccess4.java @@ -4,7 +4,7 @@ * @summary Verify correct implementation of JLS2e 6.6.2.1 * @author maddox * - * @compile/fail/ref=ProtectedMemberAccess4.out --diags:formatterOptions=-simpleNames;layout=%b:%l:%_%m ProtectedMemberAccess4.java + * @compile/fail/ref=ProtectedMemberAccess4.out --diags=formatterOptions=-simpleNames;layout=%b:%l:%_%m ProtectedMemberAccess4.java */ // 33 errors expected. diff --git a/test/langtools/tools/javac/resolve/ResolveHarness.java b/test/langtools/tools/javac/resolve/ResolveHarness.java index 8de0a6b2432..23cfa776b3b 100644 --- a/test/langtools/tools/javac/resolve/ResolveHarness.java +++ b/test/langtools/tools/javac/resolve/ResolveHarness.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2018, 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 @@ -132,8 +132,8 @@ protected ResolveHarness(JavaFileObject jfo) { protected void check() throws Exception { String[] options = { - "--should-stop:at=ATTR", - "--debug:verboseResolution=success,failure,applicable,inapplicable,deferred-inference,predef" + "--should-stop=at=ATTR", + "--debug=verboseResolution=success,failure,applicable,inapplicable,deferred-inference,predef" }; AbstractProcessor[] processors = { new ResolveCandidateFinder(), null }; diff --git a/test/langtools/tools/javac/tree/VarTree.java b/test/langtools/tools/javac/tree/VarTree.java index 99bfdb35ddd..7d1f9f2204c 100644 --- a/test/langtools/tools/javac/tree/VarTree.java +++ b/test/langtools/tools/javac/tree/VarTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -77,7 +77,7 @@ void run(String code, String expected) throws IOException { String src = prefix + parts[0] + parts[1] + parts[2] + " } }"; JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, d -> {}, - List.of("--should-stop:at=FLOW"), + List.of("--should-stop=at=FLOW"), null, Arrays.asList(new MyFileObject(src))); Iterable units = ct.parse(); diff --git a/test/langtools/tools/javac/unicode/UnicodeNewline.java b/test/langtools/tools/javac/unicode/UnicodeNewline.java index 535be3f8bd9..847b1fcc661 100644 --- a/test/langtools/tools/javac/unicode/UnicodeNewline.java +++ b/test/langtools/tools/javac/unicode/UnicodeNewline.java @@ -3,7 +3,7 @@ * @bug 4739428 4785453 * @summary when \u000a is used, diagnostics are reported on the wrong line. * - * @compile/fail/ref=UnicodeNewline.out --diags:layout=%b:%l:%_%m UnicodeNewline.java + * @compile/fail/ref=UnicodeNewline.out --diags=layout=%b:%l:%_%m UnicodeNewline.java */ class UnicodeNewline { diff --git a/test/langtools/tools/sjavac/JavacOptionPrep.java b/test/langtools/tools/sjavac/JavacOptionPrep.java index 9e3bb21b1e0..c5023c890d6 100644 --- a/test/langtools/tools/sjavac/JavacOptionPrep.java +++ b/test/langtools/tools/sjavac/JavacOptionPrep.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, 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 @@ -96,7 +96,7 @@ public static void main(String[] unused) throws IOException { // Ignore this option for now. When the file=... requirement goes // away, this will be easier to handle. - if (option.startsWith("--debug:completionDeps")) + if (option.startsWith("--debug=completionDeps")) continue; switch (option) { From 8ade45dcb454a101cd35c730f7b2a25bd9073f2b Mon Sep 17 00:00:00 2001 From: amlu Date: Wed, 4 Apr 2018 16:57:01 +0800 Subject: [PATCH 058/196] 8200703: Problem list jdk/jshell/ExceptionsTest.java fails on windows Reviewed-by: jlahoda --- test/langtools/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/langtools/ProblemList.txt b/test/langtools/ProblemList.txt index 265dbca45ff..f94a7f30fcc 100644 --- a/test/langtools/ProblemList.txt +++ b/test/langtools/ProblemList.txt @@ -38,6 +38,7 @@ jdk/javadoc/doclet/testIOException/TestIOException.java jdk/jshell/UserJdiUserRemoteTest.java 8173079 linux-all jdk/jshell/UserInputTest.java 8169536 generic-all +jdk/jshell/ExceptionsTest.java 8200701 windows-all ########################################################################### # From 1eff00e94580337c58fb7a1617a126820260f9bf Mon Sep 17 00:00:00 2001 From: mullan Date: Wed, 4 Apr 2018 11:26:10 -0400 Subject: [PATCH 059/196] 8193032: Remove terminally deprecated SecurityManager APIs Summary: Remove the checkTopLevelWindow, checkSystemClipboardAccess, checkAwtEventQueueAccess, and checkMemberAccess methods. Reviewed-by: alanb, mchung, kcr --- .../classes/java/lang/SecurityManager.java | 104 +----------------- .../classes/sun/applet/AppletSecurity.java | 26 +---- .../sun/applet/resources/MsgAppletViewer.java | 5 +- .../RedefineObject/WalkThroughInvoke.java | 4 +- .../DepMethodsRequireAllPerm.java | 82 -------------- 5 files changed, 5 insertions(+), 216 deletions(-) delete mode 100644 test/jdk/java/lang/SecurityManager/DepMethodsRequireAllPerm.java diff --git a/src/java.base/share/classes/java/lang/SecurityManager.java b/src/java.base/share/classes/java/lang/SecurityManager.java index 35e30c06cb1..74da4daeda5 100644 --- a/src/java.base/share/classes/java/lang/SecurityManager.java +++ b/src/java.base/share/classes/java/lang/SecurityManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2018, 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 @@ -235,19 +235,6 @@ public class SecurityManager { */ private boolean initialized = false; - - /** - * returns true if the current context has been granted AllPermission - */ - private boolean hasAllPermission() { - try { - checkPermission(SecurityConstants.ALL_PERMISSION); - return true; - } catch (SecurityException se) { - return false; - } - } - /** * Constructs a new SecurityManager. * @@ -1080,28 +1067,6 @@ public void checkPropertyAccess(String key) { SecurityConstants.PROPERTY_READ_ACTION)); } - /** - * Returns {@code true} if the calling thread has {@code AllPermission}. - * - * @param window not used except to check if it is {@code null}. - * @return {@code true} if the calling thread has {@code AllPermission}. - * @exception NullPointerException if the {@code window} argument is - * {@code null}. - * @deprecated This method was originally used to check if the calling thread - * was trusted to bring up a top-level window. The method has been - * obsoleted and code should instead use {@link #checkPermission} - * to check {@code AWTPermission("showWindowWithoutWarningBanner")}. - * This method is subject to removal in a future version of Java SE. - * @see #checkPermission(java.security.Permission) checkPermission - */ - @Deprecated(since="1.8", forRemoval=true) - public boolean checkTopLevelWindow(Object window) { - if (window == null) { - throw new NullPointerException("window can't be null"); - } - return hasAllPermission(); - } - /** * Throws a SecurityException if the * calling thread is not allowed to initiate a print job request. @@ -1124,44 +1089,6 @@ public void checkPrintJobAccess() { checkPermission(new RuntimePermission("queuePrintJob")); } - /** - * Throws {@code SecurityException} if the calling thread does - * not have {@code AllPermission}. - * - * @since 1.1 - * @exception SecurityException if the calling thread does not have - * {@code AllPermission} - * @deprecated This method was originally used to check if the calling - * thread could access the system clipboard. The method has been - * obsoleted and code should instead use {@link #checkPermission} - * to check {@code AWTPermission("accessClipboard")}. - * This method is subject to removal in a future version of Java SE. - * @see #checkPermission(java.security.Permission) checkPermission - */ - @Deprecated(since="1.8", forRemoval=true) - public void checkSystemClipboardAccess() { - checkPermission(SecurityConstants.ALL_PERMISSION); - } - - /** - * Throws {@code SecurityException} if the calling thread does - * not have {@code AllPermission}. - * - * @since 1.1 - * @exception SecurityException if the calling thread does not have - * {@code AllPermission} - * @deprecated This method was originally used to check if the calling - * thread could access the AWT event queue. The method has been - * obsoleted and code should instead use {@link #checkPermission} - * to check {@code AWTPermission("accessEventQueue")}. - * This method is subject to removal in a future version of Java SE. - * @see #checkPermission(java.security.Permission) checkPermission - */ - @Deprecated(since="1.8", forRemoval=true) - public void checkAwtEventQueueAccess() { - checkPermission(SecurityConstants.ALL_PERMISSION); - } - /* * We have an initial invalid bit (initially false) for the class * variables which tell if the cache is valid. If the underlying @@ -1474,35 +1401,6 @@ public void checkSetFactory() { checkPermission(new RuntimePermission("setFactory")); } - /** - * Throws a {@code SecurityException} if the calling thread does - * not have {@code AllPermission}. - * - * @param clazz the class that reflection is to be performed on. - * @param which type of access, PUBLIC or DECLARED. - * @throws SecurityException if the caller does not have - * {@code AllPermission} - * @throws NullPointerException if the {@code clazz} argument is - * {@code null} - * @deprecated This method was originally used to check if the calling - * thread was allowed to access members. It relied on the - * caller being at a stack depth of 4 which is error-prone and - * cannot be enforced by the runtime. The method has been - * obsoleted and code should instead use - * {@link #checkPermission} to check - * {@code RuntimePermission("accessDeclaredMembers")}. This - * method is subject to removal in a future version of Java SE. - * @since 1.1 - * @see #checkPermission(java.security.Permission) checkPermission - */ - @Deprecated(since="1.8", forRemoval=true) - public void checkMemberAccess(Class clazz, int which) { - if (clazz == null) { - throw new NullPointerException("class can't be null"); - } - checkPermission(SecurityConstants.ALL_PERMISSION); - } - /** * Determines whether the permission with the specified permission target * name should be granted or denied. diff --git a/src/java.desktop/share/classes/sun/applet/AppletSecurity.java b/src/java.desktop/share/classes/sun/applet/AppletSecurity.java index b9155e81072..2d4c7fce90a 100644 --- a/src/java.desktop/share/classes/sun/applet/AppletSecurity.java +++ b/src/java.desktop/share/classes/sun/applet/AppletSecurity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2018, 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 @@ -370,30 +370,6 @@ public void checkPackageAccess(final String pkgname) { } } - /** - * Tests if a client can get access to the AWT event queue. - *

      - * This method calls {@code checkPermission} with the - * {@code AWTPermission("accessEventQueue")} permission. - * - * @since 1.1 - * @exception SecurityException if the caller does not have - * permission to access the AWT event queue. - */ - @SuppressWarnings({"deprecation", - "removal"}) // SecurityManager.checkAwtEventQueueAccess - public void checkAwtEventQueueAccess() { - AppContext appContext = AppContext.getAppContext(); - AppletClassLoader appletClassLoader = currentAppletClassLoader(); - - if (AppContext.isMainContext(appContext) && (appletClassLoader != null)) { - // If we're about to allow access to the main EventQueue, - // and anything untrusted is on the class context stack, - // disallow access. - super.checkPermission(AWTPermissions.CHECK_AWT_EVENTQUEUE_PERMISSION); - } - } // checkAwtEventQueueAccess() - /** * Returns the thread group of the applet. We consult the classloader * if there is one. diff --git a/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer.java b/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer.java index d9ba0253213..70e87bd0353 100644 --- a/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer.java +++ b/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2018, 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 @@ -188,10 +188,7 @@ public Object[][] getContents() { {"appletsecurityexception.checkpackageaccess", "Security Exception: cannot access package: {0}"}, {"appletsecurityexception.checkpackagedefinition", "Security Exception: cannot define package: {0}"}, {"appletsecurityexception.cannotsetfactory", "Security Exception: cannot set factory"}, - {"appletsecurityexception.checkmemberaccess", "Security Exception: check member access"}, {"appletsecurityexception.checkgetprintjob", "Security Exception: getPrintJob"}, - {"appletsecurityexception.checksystemclipboardaccess", "Security Exception: getSystemClipboard"}, - {"appletsecurityexception.checkawteventqueueaccess", "Security Exception: getEventQueue"}, {"appletsecurityexception.checksecurityaccess", "Security Exception: security operation: {0}"}, {"appletsecurityexception.getsecuritycontext.unknown", "unknown class loader type. unable to check for getContext"}, {"appletsecurityexception.checkread.unknown", "unknown class loader type. unable to check for checking read {0}"}, diff --git a/test/hotspot/jtreg/runtime/RedefineObject/WalkThroughInvoke.java b/test/hotspot/jtreg/runtime/RedefineObject/WalkThroughInvoke.java index 51f0e635bca..3738dfd3c99 100644 --- a/test/hotspot/jtreg/runtime/RedefineObject/WalkThroughInvoke.java +++ b/test/hotspot/jtreg/runtime/RedefineObject/WalkThroughInvoke.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, 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,7 +29,7 @@ public void stackWalk() { SecurityManager sm = new SecurityManager(); // Walks the stack with Method.invoke in the stack (which is the // purpose of the test) before it gets an AccessControlException. - sm.checkMemberAccess(b, Member.DECLARED); + sm.checkPermission(new RuntimePermission("accessDeclaredMembers")); } catch (java.security.AccessControlException e) { // Ignoring an 'AccessControlException' exception since // it is expected as part of this test. diff --git a/test/jdk/java/lang/SecurityManager/DepMethodsRequireAllPerm.java b/test/jdk/java/lang/SecurityManager/DepMethodsRequireAllPerm.java deleted file mode 100644 index 77cda7e8fe1..00000000000 --- a/test/jdk/java/lang/SecurityManager/DepMethodsRequireAllPerm.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2013, 2017, 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 8004502 8008793 8029886 8186535 - * @summary Sanity check that the SecurityManager checkMemberAccess method and - * methods that used to check AWTPermission now check for AllPermission - */ - -import java.security.AllPermission; -import java.security.Permission; - -public class DepMethodsRequireAllPerm { - - static class MySecurityManager extends SecurityManager { - final Class expectedClass; - - MySecurityManager(Class c) { - expectedClass = c; - } - - @Override - public void checkPermission(Permission perm) { - if (perm.getClass() != expectedClass) - throw new RuntimeException("Got: " + perm.getClass() + ", expected: " + expectedClass); - super.checkPermission(perm); - } - } - - public static void main(String[] args) { - MySecurityManager sm = new MySecurityManager(AllPermission.class); - - try { - sm.checkAwtEventQueueAccess(); - throw new RuntimeException("SecurityException expected"); - } catch (SecurityException expected) { } - - try { - sm.checkSystemClipboardAccess(); - throw new RuntimeException("SecurityException expected"); - } catch (SecurityException expected) { } - - try { - sm.checkTopLevelWindow(null); - throw new RuntimeException("NullPointException expected"); - } catch (NullPointerException expected) { } - - if (sm.checkTopLevelWindow(new Object())) { - throw new RuntimeException("checkTopLevelWindow expected to return false"); - } - - try { - sm.checkMemberAccess(Object.class, java.lang.reflect.Member.DECLARED); - throw new RuntimeException("SecurityException expected"); - } catch (SecurityException expected) { } - - try { - sm.checkMemberAccess(null, java.lang.reflect.Member.DECLARED); - throw new RuntimeException("NullPointerException expected"); - } catch (NullPointerException expected) { } - } -} From 402baca35f138e2c211ce6fe42e0f9f2b07edda2 Mon Sep 17 00:00:00 2001 From: lbourges Date: Wed, 4 Apr 2018 21:36:02 +0200 Subject: [PATCH 060/196] 8200526: Test sun/java2d/marlin/ClipShapeTest.java times out Summary: increased timeout to 300s per test Reviewed-by: jdv, prr, serb --- test/jdk/sun/java2d/marlin/ClipShapeTest.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/jdk/sun/java2d/marlin/ClipShapeTest.java b/test/jdk/sun/java2d/marlin/ClipShapeTest.java index c219987a169..add7e7c1348 100644 --- a/test/jdk/sun/java2d/marlin/ClipShapeTest.java +++ b/test/jdk/sun/java2d/marlin/ClipShapeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, 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 @@ -58,14 +58,14 @@ * for paths made of either 9 lines, 4 quads, 2 cubics (random) * Note: Use the argument -slow to run more intensive tests (too much time) * - * @run main/othervm/timeout=120 -Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine ClipShapeTest -poly - * @run main/othervm/timeout=240 -Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine ClipShapeTest -poly -doDash - * @run main/othervm/timeout=120 -Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine ClipShapeTest -cubic - * @run main/othervm/timeout=240 -Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine ClipShapeTest -cubic -doDash - * @run main/othervm/timeout=120 -Dsun.java2d.renderer=sun.java2d.marlin.DMarlinRenderingEngine ClipShapeTest -poly - * @run main/othervm/timeout=240 -Dsun.java2d.renderer=sun.java2d.marlin.DMarlinRenderingEngine ClipShapeTest -poly -doDash - * @run main/othervm/timeout=120 -Dsun.java2d.renderer=sun.java2d.marlin.DMarlinRenderingEngine ClipShapeTest -cubic - * @run main/othervm/timeout=240 -Dsun.java2d.renderer=sun.java2d.marlin.DMarlinRenderingEngine ClipShapeTest -cubic -doDash + * @run main/othervm/timeout=300 -Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine ClipShapeTest -poly + * @run main/othervm/timeout=300 -Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine ClipShapeTest -poly -doDash + * @run main/othervm/timeout=300 -Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine ClipShapeTest -cubic + * @run main/othervm/timeout=300 -Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine ClipShapeTest -cubic -doDash + * @run main/othervm/timeout=300 -Dsun.java2d.renderer=sun.java2d.marlin.DMarlinRenderingEngine ClipShapeTest -poly + * @run main/othervm/timeout=300 -Dsun.java2d.renderer=sun.java2d.marlin.DMarlinRenderingEngine ClipShapeTest -poly -doDash + * @run main/othervm/timeout=300 -Dsun.java2d.renderer=sun.java2d.marlin.DMarlinRenderingEngine ClipShapeTest -cubic + * @run main/othervm/timeout=300 -Dsun.java2d.renderer=sun.java2d.marlin.DMarlinRenderingEngine ClipShapeTest -cubic -doDash */ public final class ClipShapeTest { From 20bdde4ee99a960cc9ed040e9548e09a7095153f Mon Sep 17 00:00:00 2001 From: igerasim Date: Wed, 4 Apr 2018 14:09:31 -0700 Subject: [PATCH 061/196] 8200696: Optimal initial capacity of java.lang.Class.enumConstantDirectory Reviewed-by: dholmes, redestad --- .../share/classes/java/lang/Class.java | 4 +- .../ConstantDirectoryOptimalCapacity.java | 113 ++++++++++++++++++ .../jdk/testlibrary/OptimalCapacity.java | 28 ++++- 3 files changed, 141 insertions(+), 4 deletions(-) create mode 100644 test/jdk/java/lang/Enum/ConstantDirectoryOptimalCapacity.java diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index cf34ff2d86e..ef959d6a97d 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2018, 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 @@ -3529,7 +3529,7 @@ Map enumConstantDirectory() { if (universe == null) throw new IllegalArgumentException( getName() + " is not an enum type"); - directory = new HashMap<>(2 * universe.length); + directory = new HashMap<>((int)(universe.length / 0.75f) + 1); for (T constant : universe) { directory.put(((Enum)constant).name(), constant); } diff --git a/test/jdk/java/lang/Enum/ConstantDirectoryOptimalCapacity.java b/test/jdk/java/lang/Enum/ConstantDirectoryOptimalCapacity.java new file mode 100644 index 00000000000..de9a235b723 --- /dev/null +++ b/test/jdk/java/lang/Enum/ConstantDirectoryOptimalCapacity.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2018, 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 8200696 + * @summary Initial capacity of Class.enumConstantDirectory is not optimal + * @library /lib/testlibrary + * @modules java.base/java.lang:open + * @build jdk.testlibrary.OptimalCapacity + * @run main ConstantDirectoryOptimalCapacity + */ + +import jdk.testlibrary.OptimalCapacity; + +public class ConstantDirectoryOptimalCapacity { + + public static void main(String[] args) throws Throwable { + test(E1.class); + test(E2.class); + test(E3.class); + test(E4.class); + test(E5.class); + test(E6.class); + test(E7.class); + test(E8.class); + test(E9.class); + test(E10.class); + test(E11.class); + test(E12.class); + test(E13.class); + test(E14.class); + test(E15.class); + test(E16.class); + test(E17.class); + test(E18.class); + test(E19.class); + test(E20.class); + test(E21.class); + test(E22.class); + test(E23.class); + test(E24.class); + test(E25.class); + test(E26.class); + } + + private static void test(Class e) { + Enum.valueOf(e, "V0"); // trigger init of enumConstantDirectory + + int initialCapacity = (int)(e.getEnumConstants().length / 0.75f) + 1; + OptimalCapacity.ofHashMap(e.getClass(), e, "enumConstantDirectory", + initialCapacity); + } + + enum E1 { V0 } + enum E2 { V0, V1 } + enum E3 { V0, V1, V2 } + enum E4 { V0, V1, V2, V3 } + enum E5 { V0, V1, V2, V3, V4 } + enum E6 { V0, V1, V2, V3, V4, V5 } + enum E7 { V0, V1, V2, V3, V4, V5, V6 } + enum E8 { V0, V1, V2, V3, V4, V5, V6, V7 } + enum E9 { V0, V1, V2, V3, V4, V5, V6, V7, V8 } + enum E10 { V0, V1, V2, V3, V4, V5, V6, V7, V8, V9 } + enum E11 { V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10 } + enum E12 { V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11 } + enum E13 { V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12 } + enum E14 { V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13 } + enum E15 { V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, + V14 } + enum E16 { V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, + V14, V15 } + enum E17 { V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, + V14, V15, V16 } + enum E18 { V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, + V14, V15, V16, V17 } + enum E19 { V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, + V14, V15, V16, V17, V18 } + enum E20 { V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, + V14, V15, V16, V17, V18, V19 } + enum E21 { V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, + V14, V15, V16, V17, V18, V19, V20 } + enum E22 { V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, + V14, V15, V16, V17, V18, V19, V20, V21 } + enum E23 { V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, + V14, V15, V16, V17, V18, V19, V20, V21, V22 } + enum E24 { V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, + V14, V15, V16, V17, V18, V19, V20, V21, V22, V23 } + enum E25 { V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, + V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24 } + enum E26 { V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, + V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25 } +} diff --git a/test/jdk/lib/testlibrary/jdk/testlibrary/OptimalCapacity.java b/test/jdk/lib/testlibrary/jdk/testlibrary/OptimalCapacity.java index 2d1ada3842a..ab74cc26dda 100644 --- a/test/jdk/lib/testlibrary/jdk/testlibrary/OptimalCapacity.java +++ b/test/jdk/lib/testlibrary/jdk/testlibrary/OptimalCapacity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, 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 @@ -101,11 +101,35 @@ public static void ofArrayList(Class clazz, String fieldName, */ public static void ofHashMap(Class clazz, String fieldName, int initialCapacity) + { + ofHashMap(clazz, null, fieldName, initialCapacity); + } + + /** + * Checks adequacy of the initial capacity of a non-static field + * of type {@code HashMap}. + * + * Having + *

      +     * class XClass {
      +     *     HashMap theMap = new HashMap(N);
      +     * }
      +     * XClass instance = ...
      +     * 
      + * + * you should call from the test + * + *
      +     * OptimalCapacity.ofHashMap(XClass.class, instance, "theMap", N);
      +     * 
      + */ + public static void ofHashMap(Class clazz, Object instance, + String fieldName, int initialCapacity) { try { Field field = clazz.getDeclaredField(fieldName); field.setAccessible(true); - Object obj = field.get(null); + Object obj = field.get(instance); if (!HashMap.class.equals(obj.getClass())) { throw new RuntimeException(field + " expected to be of type HashMap"); From 12bfb4b91fa064a70f0db576f5b83cd501522de1 Mon Sep 17 00:00:00 2001 From: jjg Date: Wed, 4 Apr 2018 14:42:53 -0700 Subject: [PATCH 062/196] 8200664: fix broken links in java.base docs Reviewed-by: alanb, joehw --- .../java/net/doc-files/net-properties.html | 4 +- .../java/util/doc-files/coll-designfaq.html | 4 +- .../java/util/doc-files/coll-overview.html | 4 +- .../java/util/doc-files/coll-reference.html | 62 +++++++++---------- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/java.base/share/classes/java/net/doc-files/net-properties.html b/src/java.base/share/classes/java/net/doc-files/net-properties.html index acf653ebaed..f6f87b8edc3 100644 --- a/src/java.base/share/classes/java/net/doc-files/net-properties.html +++ b/src/java.base/share/classes/java/net/doc-files/net-properties.html @@ -1,6 +1,6 @@ \n"); - tree.addContent(script.asContent()); - } else { - subDiv.addContent(links.createAnchor(SectionName.SKIP_NAVBAR_BOTTOM)); - tree.addContent(subDiv); - tree.addContent(HtmlConstants.END_OF_BOTTOM_NAVBAR); - } - if (configuration.allowTag(HtmlTag.NAV)) { - htmlTree.addContent(tree); - } - } - } - - /** - * Do nothing. This is the default method. - */ - protected void addSummaryDetailLinks(Content navDiv) { - } - - /** - * Get link to the "overview-summary.html" page. - * - * @return a content tree for the link - */ - protected Content getNavLinkContents() { - Content linkContent = links.createLink(pathToRoot.resolve(DocPaths.overviewSummary(configuration.frames)), - contents.overviewLabel, "", ""); - Content li = HtmlTree.LI(linkContent); - return li; - } - - /** - * Get link to the module summary page for the module passed. - * - * @param mdle Module to which link will be generated - * @return a content tree for the link - */ - protected Content getNavLinkModule(ModuleElement mdle) { - Content linkContent = getModuleLink(mdle, contents.moduleLabel); - Content li = HtmlTree.LI(linkContent); - return li; - } - - /** - * Get the word "Module", to indicate that link is not available here. - * - * @return a content tree for the link - */ - protected Content getNavLinkModule() { - Content li = HtmlTree.LI(contents.moduleLabel); - return li; - } - - /** - * Get link to the "package-summary.html" page for the package passed. - * - * @param pkg Package to which link will be generated - * @return a content tree for the link - */ - protected Content getNavLinkPackage(PackageElement pkg) { - Content linkContent = getPackageLink(pkg, contents.packageLabel); - Content li = HtmlTree.LI(linkContent); - return li; - } - - /** - * Get the word "Package" , to indicate that link is not available here. - * - * @return a content tree for the link - */ - protected Content getNavLinkPackage() { - Content li = HtmlTree.LI(contents.packageLabel); - return li; - } - - /** - * Get the word "Use", to indicate that link is not available. - * - * @return a content tree for the link - */ - protected Content getNavLinkClassUse() { - Content li = HtmlTree.LI(contents.useLabel); - return li; - } - - /** - * Get "FRAMES" link, to switch to the frame version of the output. - * - * @param link File to be linked, "index.html" - * @return a content tree for the link - */ - protected Content getNavShowLists(DocPath link) { - DocLink dl = new DocLink(link, path.getPath(), null); - Content framesContent = links.createLink(dl, contents.framesLabel, "", "_top"); - Content li = HtmlTree.LI(framesContent); - return li; - } - - /** - * Get "FRAMES" link, to switch to the frame version of the output. - * - * @return a content tree for the link - */ - protected Content getNavShowLists() { - return getNavShowLists(pathToRoot.resolve(DocPaths.INDEX)); - } - - /** - * Get "NO FRAMES" link, to switch to the non-frame version of the output. - * - * @param link File to be linked - * @return a content tree for the link - */ - protected Content getNavHideLists(DocPath link) { - Content noFramesContent = links.createLink(link, contents.noFramesLabel, "", "_top"); - Content li = HtmlTree.LI(noFramesContent); - return li; - } - - /** - * Get "Tree" link in the navigation bar. If there is only one package - * specified on the command line, then the "Tree" link will be to the - * only "package-tree.html" file otherwise it will be to the - * "overview-tree.html" file. - * - * @return a content tree for the link - */ - protected Content getNavLinkTree() { - List packages = new ArrayList<>(configuration.getSpecifiedPackageElements()); - DocPath docPath = packages.size() == 1 && configuration.getSpecifiedTypeElements().isEmpty() - ? pathString(packages.get(0), DocPaths.PACKAGE_TREE) - : pathToRoot.resolve(DocPaths.OVERVIEW_TREE); - return HtmlTree.LI(links.createLink(docPath, contents.treeLabel, "", "")); - } - /** * Get the overview tree link for the main tree. * @@ -758,91 +503,6 @@ protected Content getNavLinkMainTree(String label) { return li; } - /** - * Get the word "Class", to indicate that class link is not available. - * - * @return a content tree for the link - */ - protected Content getNavLinkClass() { - Content li = HtmlTree.LI(contents.classLabel); - return li; - } - - /** - * Get "Deprecated" API link in the navigation bar. - * - * @return a content tree for the link - */ - protected Content getNavLinkDeprecated() { - Content linkContent = links.createLink(pathToRoot.resolve(DocPaths.DEPRECATED_LIST), - contents.deprecatedLabel, "", ""); - Content li = HtmlTree.LI(linkContent); - return li; - } - - /** - * Get link for generated index. If the user has used "-splitindex" - * command line option, then link to file "index-files/index-1.html" is - * generated otherwise link to file "index-all.html" is generated. - * - * @return a content tree for the link - */ - protected Content getNavLinkClassIndex() { - Content allClassesContent = links.createLink(pathToRoot.resolve( - DocPaths.AllClasses(configuration.frames)), - contents.allClassesLabel, "", ""); - Content li = HtmlTree.LI(allClassesContent); - return li; - } - - /** - * Get link for generated class index. - * - * @return a content tree for the link - */ - protected Content getNavLinkIndex() { - Content linkContent = links.createLink(pathToRoot.resolve( - (configuration.splitindex - ? DocPaths.INDEX_FILES.resolve(DocPaths.indexN(1)) - : DocPaths.INDEX_ALL)), - contents.indexLabel, "", ""); - Content li = HtmlTree.LI(linkContent); - return li; - } - - /** - * Get help file link. If user has provided a help file, then generate a - * link to the user given file, which is already copied to current or - * destination directory. - * - * @return a content tree for the link - */ - protected Content getNavLinkHelp() { - String helpfile = configuration.helpfile; - DocPath helpfilenm; - if (helpfile.isEmpty()) { - helpfilenm = DocPaths.HELP_DOC; - } else { - DocFile file = DocFile.createFileForInput(configuration, helpfile); - helpfilenm = DocPath.create(file.getName()); - } - Content linkContent = links.createLink(pathToRoot.resolve(helpfilenm), - contents.helpLabel, "", ""); - Content li = HtmlTree.LI(linkContent); - return li; - } - - /** - * Add gap between navigation bar elements. - * - * @param liNav the content tree to which the gap will be added - */ - protected void addNavGap(Content liNav) { - liNav.addContent(Contents.SPACE); - liNav.addContent("|"); - liNav.addContent(Contents.SPACE); - } - /** * Get table caption. * diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java index 4090c3ddde4..00f8784b963 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java @@ -40,7 +40,7 @@ import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; -import jdk.javadoc.internal.doclets.formats.html.markup.Links; +import jdk.javadoc.internal.doclets.formats.html.markup.Navigation; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; @@ -424,37 +424,4 @@ protected void addReturnType(ExecutableElement method, Content htmltree) { htmltree.addContent(Contents.SPACE); } } - - /** - * {@inheritDoc} - */ - @Override - protected Content getNavSummaryLink(TypeElement typeElement, boolean link) { - if (link) { - if (typeElement == null) { - return links.createLink( - SectionName.METHOD_SUMMARY, - contents.navMethod); - } else { - return links.createLink( - SectionName.METHODS_INHERITANCE, - configuration.getClassName(typeElement), contents.navMethod); - } - } else { - return contents.navMethod; - } - } - - /** - * {@inheritDoc} - */ - @Override - protected void addNavDetailLink(boolean link, Content liNav) { - if (link) { - liNav.addContent(links.createLink( - SectionName.METHOD_DETAIL, contents.navMethod)); - } else { - liNav.addContent(contents.navMethod); - } - } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java index cd249871e96..910e8b69ec0 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java @@ -227,7 +227,8 @@ protected void addNavigationBarHeader(Content body) { ? HtmlTree.HEADER() : body; addTop(tree); - addNavLinks(true, tree); + navBar.setUserHeader(getUserHeaderFooter(true)); + tree.addContent(navBar.getContent(true)); if (configuration.allowTag(HtmlTag.HEADER)) { body.addContent(tree); } @@ -244,7 +245,8 @@ protected void addNavigationBarFooter(Content body) { Content htmltree = (configuration.allowTag(HtmlTag.FOOTER)) ? HtmlTree.FOOTER() : body; - addNavLinks(false, htmltree); + navBar.setUserFooter(getUserHeaderFooter(false)); + htmltree.addContent(navBar.getContent(false)); addBottom(htmltree); if (configuration.allowTag(HtmlTag.FOOTER)) { body.addContent(htmltree); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java index 221edc126cd..10e4fcd048b 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java @@ -50,13 +50,14 @@ import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.Navigation; +import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode; import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.ModuleSummaryWriter; import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper; import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException; -import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; /** * Class to generate file for each module contents in the right-hand frame. This will list all the @@ -171,6 +172,8 @@ class PackageEntry { */ protected HtmlTree sectionTree = HtmlTree.SECTION(); + private final Navigation navBar; + /** * Constructor to construct ModuleWriter object and to generate "moduleName-summary.html" file. * @@ -181,6 +184,7 @@ public ModuleWriterImpl(HtmlConfiguration configuration, ModuleElement mdle) { super(configuration, configuration.docPaths.moduleSummary(mdle)); this.mdle = mdle; this.moduleMode = configuration.docEnv.getModuleMode(); + this.navBar = new Navigation(mdle, configuration, fixedNavDiv, PageMode.MODULE, path); computeModulesData(); } @@ -196,7 +200,13 @@ public Content getModuleHeader(String heading) { ? HtmlTree.HEADER() : bodyTree; addTop(htmlTree); - addNavLinks(true, htmlTree); + navBar.setDisplaySummaryModuleDescLink(!utils.getFullBody(mdle).isEmpty() && !configuration.nocomment); + navBar.setDisplaySummaryModulesLink(display(requires) || display(indirectModules)); + navBar.setDisplaySummaryPackagesLink(display(packages) || display(indirectPackages) + || display(indirectOpenPackages)); + navBar.setDisplaySummaryServicesLink(displayServices(uses, usesTrees) || displayServices(provides.keySet(), providesTrees)); + navBar.setUserHeader(getUserHeaderFooter(true)); + htmlTree.addContent(navBar.getContent(true)); if (configuration.allowTag(HtmlTag.HEADER)) { bodyTree.addContent(htmlTree); } @@ -913,47 +923,6 @@ public void addModuleTags(Content moduleContentTree) { } } - /** - * Add summary details to the navigation bar. - * - * @param subDiv the content tree to which the summary detail links will be added - */ - @Override - protected void addSummaryDetailLinks(Content subDiv) { - Content div = HtmlTree.DIV(getNavSummaryLinks()); - subDiv.addContent(div); - } - - /** - * Get summary links for navigation bar. - * - * @return the content tree for the navigation summary links - */ - protected Content getNavSummaryLinks() { - Content li = HtmlTree.LI(contents.moduleSubNavLabel); - li.addContent(Contents.SPACE); - Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li); - Content liNav = new HtmlTree(HtmlTag.LI); - liNav.addContent(!utils.getFullBody(mdle).isEmpty() && !configuration.nocomment - ? links.createLink(SectionName.MODULE_DESCRIPTION, contents.navModuleDescription) - : contents.navModuleDescription); - addNavGap(liNav); - liNav.addContent((display(requires) || display(indirectModules)) - ? links.createLink(SectionName.MODULES, contents.navModules) - : contents.navModules); - addNavGap(liNav); - liNav.addContent((display(packages) - || display(indirectPackages) || display(indirectOpenPackages)) - ? links.createLink(SectionName.PACKAGES, contents.navPackages) - : contents.navPackages); - addNavGap(liNav); - liNav.addContent((displayServices(uses, usesTrees) || displayServices(provides.keySet(), providesTrees)) - ? links.createLink(SectionName.SERVICES, contents.navServices) - : contents.navServices); - ulNav.addContent(liNav); - return ulNav; - } - /** * {@inheritDoc} */ @@ -975,7 +944,8 @@ public void addModuleFooter(Content contentTree) { Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER)) ? HtmlTree.FOOTER() : contentTree; - addNavLinks(false, htmlTree); + navBar.setUserFooter(getUserHeaderFooter(false)); + htmlTree.addContent(navBar.getContent(false)); addBottom(htmlTree); if (configuration.allowTag(HtmlTag.FOOTER)) { contentTree.addContent(htmlTree); @@ -1017,15 +987,4 @@ public void addPackageDeprecationInfo(Content li, PackageElement pkg) { li.addContent(deprDiv); } } - - /** - * Get this module link. - * - * @return a content tree for the module link - */ - @Override - protected Content getNavLinkModule() { - Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, contents.moduleLabel); - return li; - } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java index 31af5c7308e..bb38b687027 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java @@ -37,7 +37,7 @@ import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; -import jdk.javadoc.internal.doclets.formats.html.markup.Links; +import jdk.javadoc.internal.doclets.formats.html.markup.Navigation; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; @@ -205,31 +205,4 @@ protected void addSummaryType(Element member, Content tdSummaryType) { protected Content getDeprecatedLink(Element member) { return writer.getQualifiedClassLink(LinkInfoImpl.Kind.MEMBER, member); } - - /** - * {@inheritDoc} - */ - @Override - protected Content getNavSummaryLink(TypeElement typeElement, boolean link) { - if (link) { - if (typeElement == null) { - return links.createLink( - SectionName.NESTED_CLASS_SUMMARY, - contents.navNested); - } else { - return links.createLink( - SectionName.NESTED_CLASSES_INHERITANCE, - utils.getFullyQualifiedName(typeElement), contents.navNested); - } - } else { - return contents.navNested; - } - } - - /** - * {@inheritDoc} - */ - @Override - protected void addNavDetailLink(boolean link, Content liNav) { - } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java index 73a238595cc..9cc858ea82b 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java @@ -209,7 +209,8 @@ protected void addNavigationBarHeader(Content body) { ? HtmlTree.HEADER() : body; addTop(tree); - addNavLinks(true, tree); + navBar.setUserHeader(getUserHeaderFooter(true)); + tree.addContent(navBar.getContent(true)); if (configuration.allowTag(HtmlTag.HEADER)) { body.addContent(tree); } @@ -226,7 +227,8 @@ protected void addNavigationBarFooter(Content body) { Content tree = (configuration.allowTag(HtmlTag.FOOTER)) ? HtmlTree.FOOTER() : body; - addNavLinks(false, tree); + navBar.setUserFooter(getUserHeaderFooter(false)); + tree.addContent(navBar.getContent(false)); addBottom(tree); if (configuration.allowTag(HtmlTag.FOOTER)) { body.addContent(tree); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java index 7e54b2e905c..063ac738b07 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java @@ -31,6 +31,8 @@ import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.Navigation; +import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.util.ClassTree; import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException; @@ -57,6 +59,8 @@ public class PackageTreeWriter extends AbstractTreeWriter { */ protected PackageElement packageElement; + private final Navigation navBar; + /** * Constructor. * @param configuration the configuration @@ -67,6 +71,7 @@ public PackageTreeWriter(HtmlConfiguration configuration, DocPath path, PackageE super(configuration, path, new ClassTree(configuration.typeElementCatalog.allClasses(packageElement), configuration)); this.packageElement = packageElement; + this.navBar = new Navigation(packageElement, configuration, fixedNavDiv, PageMode.TREE, path); } /** @@ -118,7 +123,8 @@ protected void generatePackageTreeFile() throws DocFileIOException { HtmlTree tree = (configuration.allowTag(HtmlTag.FOOTER)) ? HtmlTree.FOOTER() : body; - addNavLinks(false, tree); + navBar.setUserFooter(getUserHeaderFooter(false)); + tree.addContent(navBar.getContent(false)); addBottom(tree); if (configuration.allowTag(HtmlTag.FOOTER)) { body.addContent(tree); @@ -139,7 +145,11 @@ protected HtmlTree getPackageTreeHeader() { ? HtmlTree.HEADER() : bodyTree; addTop(htmlTree); - addNavLinks(true, htmlTree); + Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(packageElement), + contents.moduleLabel); + navBar.setNavLinkModule(linkContent); + navBar.setUserHeader(getUserHeaderFooter(true)); + htmlTree.addContent(navBar.getContent(true)); if (configuration.allowTag(HtmlTag.HEADER)) { bodyTree.addContent(htmlTree); } @@ -160,30 +170,4 @@ protected void addLinkToMainTree(Content div) { ul.addContent(getNavLinkMainTree(configuration.getText("doclet.All_Packages"))); div.addContent(ul); } - - /** - * Get the module link. - * - * @return a content tree for the module link - */ - @Override - protected Content getNavLinkModule() { - Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(packageElement), - contents.moduleLabel); - Content li = HtmlTree.LI(linkContent); - return li; - } - - /** - * Get link to the package summary page for the package of this tree. - * - * @return a content tree for the package link - */ - @Override - protected Content getNavLinkPackage() { - Content linkContent = links.createLink(DocPaths.PACKAGE_SUMMARY, - contents.packageLabel); - Content li = HtmlTree.LI(linkContent); - return li; - } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java index 2233d8549e3..ebed4a15e10 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java @@ -38,7 +38,8 @@ import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; -import jdk.javadoc.internal.doclets.formats.html.markup.Links; +import jdk.javadoc.internal.doclets.formats.html.markup.Navigation; +import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.util.ClassUseMapper; @@ -63,6 +64,7 @@ public class PackageUseWriter extends SubWriterHolderWriter { final SortedMap> usingPackageToUsedClasses = new TreeMap<>(); protected HtmlTree mainTree = HtmlTree.MAIN(); final String packageUseTableSummary; + private final Navigation navBar; /** * Constructor. @@ -100,6 +102,7 @@ public PackageUseWriter(HtmlConfiguration configuration, packageUseTableSummary = resources.getText("doclet.Use_Table_Summary", resources.getText("doclet.packages")); + this.navBar = new Navigation(packageElement, configuration, fixedNavDiv, PageMode.USE, path); } /** @@ -140,7 +143,8 @@ protected void generatePackageUseFile() throws DocFileIOException { HtmlTree tree = (configuration.allowTag(HtmlTag.FOOTER)) ? HtmlTree.FOOTER() : body; - addNavLinks(false, tree); + navBar.setUserFooter(getUserHeaderFooter(false)); + tree.addContent(navBar.getContent(false)); addBottom(tree); if (configuration.allowTag(HtmlTag.FOOTER)) { body.addContent(tree); @@ -249,7 +253,11 @@ private HtmlTree getPackageUseHeader() { ? HtmlTree.HEADER() : bodyTree; addTop(htmlTree); - addNavLinks(true, htmlTree); + Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(packageElement), + contents.moduleLabel); + navBar.setNavLinkModule(linkContent); + navBar.setUserHeader(getUserHeaderFooter(true)); + htmlTree.addContent(navBar.getContent(true)); if (configuration.allowTag(HtmlTag.HEADER)) { bodyTree.addContent(htmlTree); } @@ -267,54 +275,4 @@ private HtmlTree getPackageUseHeader() { } return bodyTree; } - - /** - * Get the module link. - * - * @return a content tree for the module link - */ - @Override - protected Content getNavLinkModule() { - Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(packageElement), - contents.moduleLabel); - Content li = HtmlTree.LI(linkContent); - return li; - } - - /** - * Get this package link. - * - * @return a content tree for the package link - */ - @Override - protected Content getNavLinkPackage() { - Content linkContent = links.createLink(DocPaths.PACKAGE_SUMMARY, - contents.packageLabel); - Content li = HtmlTree.LI(linkContent); - return li; - } - - /** - * Get the use link. - * - * @return a content tree for the use link - */ - @Override - protected Content getNavLinkClassUse() { - Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, contents.useLabel); - return li; - } - - /** - * Get the tree link. - * - * @return a content tree for the tree link - */ - @Override - protected Content getNavLinkTree() { - Content linkContent = links.createLink(DocPaths.PACKAGE_TREE, - contents.treeLabel); - Content li = HtmlTree.LI(linkContent); - return li; - } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java index cb09a5b7b94..1beb5a7f992 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java @@ -40,12 +40,13 @@ import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.Navigation; +import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.PackageSummaryWriter; import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper; import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException; -import jdk.javadoc.internal.doclets.toolkit.util.DocPath; import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; /** @@ -79,6 +80,8 @@ public class PackageWriterImpl extends HtmlDocletWriter */ protected HtmlTree sectionTree = HtmlTree.SECTION(); + private final Navigation navBar; + /** * Constructor to construct PackageWriter object and to generate * "package-summary.html" file in the respective package directory. @@ -95,6 +98,7 @@ public PackageWriterImpl(HtmlConfiguration configuration, PackageElement package configuration.docPaths.forPackage(packageElement) .resolve(DocPaths.PACKAGE_SUMMARY)); this.packageElement = packageElement; + this.navBar = new Navigation(packageElement, configuration, fixedNavDiv, PageMode.PACKAGE, path); } /** @@ -107,7 +111,11 @@ public Content getPackageHeader(String heading) { ? HtmlTree.HEADER() : bodyTree; addTop(htmlTree); - addNavLinks(true, htmlTree); + Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(packageElement), + contents.moduleLabel); + navBar.setNavLinkModule(linkContent); + navBar.setUserHeader(getUserHeaderFooter(true)); + htmlTree.addContent(navBar.getContent(true)); if (configuration.allowTag(HtmlTag.HEADER)) { bodyTree.addContent(htmlTree); } @@ -346,7 +354,8 @@ public void addPackageFooter(Content contentTree) { Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER)) ? HtmlTree.FOOTER() : contentTree; - addNavLinks(false, htmlTree); + navBar.setUserFooter(getUserHeaderFooter(false)); + htmlTree.addContent(navBar.getContent(false)); addBottom(htmlTree); if (configuration.allowTag(HtmlTag.FOOTER)) { contentTree.addContent(htmlTree); @@ -361,55 +370,4 @@ public void printDocument(Content contentTree) throws DocFileIOException { printHtmlDocument(configuration.metakeywords.getMetaKeywords(packageElement), true, contentTree); } - - /** - * Get "Use" link for this pacakge in the navigation bar. - * - * @return a content tree for the class use link - */ - @Override - protected Content getNavLinkClassUse() { - Content useLink = links.createLink(DocPaths.PACKAGE_USE, - contents.useLabel, "", ""); - Content li = HtmlTree.LI(useLink); - return li; - } - - /** - * Get "Tree" link in the navigation bar. This will be link to the package - * tree file. - * - * @return a content tree for the tree link - */ - @Override - protected Content getNavLinkTree() { - Content useLink = links.createLink(DocPaths.PACKAGE_TREE, - contents.treeLabel, "", ""); - Content li = HtmlTree.LI(useLink); - return li; - } - - /** - * Get the module link. - * - * @return a content tree for the module link - */ - @Override - protected Content getNavLinkModule() { - Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(packageElement), - contents.moduleLabel); - Content li = HtmlTree.LI(linkContent); - return li; - } - - /** - * Highlight "Package" in the navigation bar, as this is the package page. - * - * @return a content tree for the package link - */ - @Override - protected Content getNavLinkPackage() { - Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, contents.packageLabel); - return li; - } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java index 46dc452beca..d287f2eb8fa 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java @@ -37,7 +37,7 @@ import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; -import jdk.javadoc.internal.doclets.formats.html.markup.Links; +import jdk.javadoc.internal.doclets.formats.html.markup.Navigation; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; @@ -324,38 +324,4 @@ protected Content getDeprecatedLink(Element member) { return writer.getDocLink(LinkInfoImpl.Kind.MEMBER, member, utils.getFullyQualifiedName(member)); } - - /** - * {@inheritDoc} - */ - @Override - protected Content getNavSummaryLink(TypeElement typeElement, boolean link) { - if (link) { - if (typeElement == null) { - return links.createLink( - SectionName.PROPERTY_SUMMARY, - contents.navProperty); - } else { - return links.createLink( - SectionName.PROPERTIES_INHERITANCE, - configuration.getClassName(typeElement), contents.navProperty); - } - } else { - return contents.navProperty; - } - } - - /** - * {@inheritDoc} - */ - @Override - protected void addNavDetailLink(boolean link, Content liNav) { - if (link) { - liNav.addContent(links.createLink( - SectionName.PROPERTY_DETAIL, - contents.navProperty)); - } else { - liNav.addContent(contents.navProperty); - } - } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java index 5be1a74e0a8..f76609cde4c 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java @@ -33,6 +33,8 @@ import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.Navigation; +import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.SerializedFormWriter; @@ -59,12 +61,15 @@ public class SerializedFormWriterImpl extends SubWriterHolderWriter */ private HtmlTree mainTree = HtmlTree.MAIN(); + private final Navigation navBar; + /** * @param configuration the configuration data for the doclet */ public SerializedFormWriterImpl(HtmlConfiguration configuration) { super(configuration, DocPaths.SERIALIZED_FORM); visibleClasses = configuration.getIncludedTypeElements(); + this.navBar = new Navigation(null, configuration, fixedNavDiv, PageMode.SERIALIZEDFORM, path); } /** @@ -79,7 +84,8 @@ public Content getHeader(String header) { ? HtmlTree.HEADER() : bodyTree; addTop(htmlTree); - addNavLinks(true, htmlTree); + navBar.setUserHeader(getUserHeaderFooter(true)); + htmlTree.addContent(navBar.getContent(true)); if (configuration.allowTag(HtmlTag.HEADER)) { bodyTree.addContent(htmlTree); } @@ -261,7 +267,8 @@ public void addFooter(Content serializedTree) { Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER)) ? HtmlTree.FOOTER() : serializedTree; - addNavLinks(false, htmlTree); + navBar.setUserFooter(getUserHeaderFooter(false)); + htmlTree.addContent(navBar.getContent(false)); addBottom(htmlTree); if (configuration.allowTag(HtmlTag.FOOTER)) { serializedTree.addContent(htmlTree); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java index 1f6acfde7da..ed8175d36bd 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java @@ -97,7 +97,8 @@ protected void generateIndexFile() throws DocFileIOException { ? HtmlTree.HEADER() : body; addTop(htmlTree); - addNavLinks(true, htmlTree); + navBar.setUserHeader(getUserHeaderFooter(true)); + htmlTree.addContent(navBar.getContent(true)); if (configuration.allowTag(HtmlTag.HEADER)) { body.addContent(htmlTree); } @@ -123,7 +124,8 @@ protected void generateIndexFile() throws DocFileIOException { if (configuration.allowTag(HtmlTag.FOOTER)) { htmlTree = HtmlTree.FOOTER(); } - addNavLinks(false, htmlTree); + navBar.setUserFooter(getUserHeaderFooter(false)); + htmlTree.addContent(navBar.getContent(false)); addBottom(htmlTree); if (configuration.allowTag(HtmlTag.FOOTER)) { body.addContent(htmlTree); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java index d9000fbef4d..179a50a9f67 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java @@ -125,7 +125,8 @@ protected void generateIndexFile(Character unicode) throws DocFileIOException { ? HtmlTree.HEADER() : body; addTop(htmlTree); - addNavLinks(true, htmlTree); + navBar.setUserHeader(getUserHeaderFooter(true)); + htmlTree.addContent(navBar.getContent(true)); if (configuration.allowTag(HtmlTag.HEADER)) { body.addContent(htmlTree); } @@ -145,7 +146,8 @@ protected void generateIndexFile(Character unicode) throws DocFileIOException { if (configuration.allowTag(HtmlTag.FOOTER)) { htmlTree = HtmlTree.FOOTER(); } - addNavLinks(false, htmlTree); + navBar.setUserFooter(getUserHeaderFooter(false)); + htmlTree.addContent(navBar.getContent(false)); addBottom(htmlTree); if (configuration.allowTag(HtmlTag.FOOTER)) { body.addContent(htmlTree); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java index 3691e8d9621..62fad1d47ed 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java @@ -33,7 +33,8 @@ import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; -import jdk.javadoc.internal.doclets.formats.html.markup.Links; +import jdk.javadoc.internal.doclets.formats.html.markup.Navigation; +import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode; import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.util.ClassTree; @@ -68,6 +69,8 @@ public class TreeWriter extends AbstractTreeWriter { */ private final boolean classesOnly; + private final Navigation navBar; + /** * Constructor to construct TreeWriter object. * @@ -79,6 +82,7 @@ public TreeWriter(HtmlConfiguration configuration, DocPath filename, ClassTree c super(configuration, filename, classtree); packages = configuration.packages; classesOnly = packages.isEmpty(); + this.navBar = new Navigation(null, configuration, fixedNavDiv, PageMode.TREE, path); } /** @@ -127,7 +131,8 @@ public void generateTreeFile() throws DocFileIOException { } else { htmlTree = body; } - addNavLinks(false, htmlTree); + navBar.setUserFooter(getUserHeaderFooter(false)); + htmlTree.addContent(navBar.getContent(false)); addBottom(htmlTree); if (configuration.allowTag(HtmlTag.FOOTER)) { body.addContent(htmlTree); @@ -186,7 +191,8 @@ protected HtmlTree getTreeHeader() { ? HtmlTree.HEADER() : bodyTree; addTop(htmlTree); - addNavLinks(true, htmlTree); + navBar.setUserHeader(getUserHeaderFooter(true)); + htmlTree.addContent(navBar.getContent(true)); if (configuration.allowTag(HtmlTag.HEADER)) { bodyTree.addContent(htmlTree); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Navigation.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Navigation.java new file mode 100644 index 00000000000..244a9eb1346 --- /dev/null +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Navigation.java @@ -0,0 +1,1089 @@ +/* + * Copyright (c) 2018, 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 jdk.javadoc.internal.doclets.formats.html.markup; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Deque; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.SortedSet; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ModuleElement; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; + +import jdk.javadoc.internal.doclets.formats.html.AbstractMemberWriter; +import jdk.javadoc.internal.doclets.formats.html.Contents; +import jdk.javadoc.internal.doclets.formats.html.HtmlConfiguration; +import jdk.javadoc.internal.doclets.formats.html.SectionName; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.builders.MemberSummaryBuilder; +import jdk.javadoc.internal.doclets.toolkit.util.DocFile; +import jdk.javadoc.internal.doclets.toolkit.util.DocLink; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap; + +/** + * Factory for navigation bar. + * + *

      + * This is NOT part of any supported API. If you write code that depends on this, you do so at + * your own risk. This code and its internal interfaces are subject to change or deletion without + * notice. + */ +public class Navigation { + + private final HtmlConfiguration configuration; + private final Element element; + private final Contents contents; + private final DocPath path; + private final DocPath pathToRoot; + private final Links links; + private final HtmlTree fixedNavDiv; + private final PageMode documentedPage; + private Content navLinkModule; + private Content navLinkPackage; + private Content navLinkClass; + private MemberSummaryBuilder memberSummaryBuilder; + private boolean displaySummaryModuleDescLink; + private boolean displaySummaryModulesLink; + private boolean displaySummaryPackagesLink; + private boolean displaySummaryServicesLink; + private final Map> topBottomNavContents; + private Content userHeader; + private Content userFooter; + private final String rowListTitle; + private final Content searchLabel; + private static final Script FIXED_NAV_SCRIPT = new Script("\n"); + + public enum PageMode { + CLASS, + CONSTANTVALUES, + DEPRECATED, + DOCFILE, + HELP, + INDEX, + MODULE, + OVERVIEW, + PACKAGE, + SERIALIZEDFORM, + TREE, + USE; + } + + enum Position { + BOTTOM("allclasses_navbar_bottom", HtmlConstants.START_OF_BOTTOM_NAVBAR, HtmlConstants.END_OF_BOTTOM_NAVBAR), + TOP("allclasses_navbar_top", HtmlConstants.START_OF_TOP_NAVBAR, HtmlConstants.END_OF_TOP_NAVBAR); + + final String allClassesLinkId; + final Content startOfNav; + final Content endOfNav; + + Position(String allClassesLinkId, Content startOfNav, Content endOfNav) { + this.allClassesLinkId = allClassesLinkId; + this.startOfNav = startOfNav; + this.endOfNav = endOfNav; + } + + String allClassesLinkId() { + return allClassesLinkId; + } + + Content startOfNav() { + return startOfNav; + } + + Content endOfNav() { + return endOfNav; + } + + Script allClassesLinkScript() { + return new Script("\n"); + } + } + + /** + * Creates a {@code Navigation} object for a specific file, to be written in a specific HTML + * version. + * + * @param element element being documented. null if its not an element documentation page + * @param configuration the configuration object + * @param fixedNavDiv the fixed navigation for the header navigation + * @param page the kind of page being documented + * @param path the DocPath object + */ + public Navigation(Element element, HtmlConfiguration configuration, HtmlTree fixedNavDiv, + PageMode page, DocPath path) { + this.configuration = configuration; + this.element = element; + this.fixedNavDiv = fixedNavDiv; + this.contents = configuration.contents; + this.documentedPage = page; + this.path = path; + this.pathToRoot = path.parent().invert(); + this.links = new Links(path, configuration.htmlVersion); + this.topBottomNavContents = new HashMap<>(); + this.rowListTitle = configuration.getText("doclet.Navigation"); + this.searchLabel = configuration.getContent("doclet.search"); + populateNavContents(Position.TOP); + populateNavContents(Position.BOTTOM); + } + + /** + * Populate the navigation contents for top and bottom navigation + * + * @param position the position of the navigation bar on the page + */ + private void populateNavContents(Position position) { + Deque queue = new ArrayDeque<>(); + Content skipNavLinks = configuration.getContent("doclet.Skip_navigation_links"); + switch (position) { + case TOP: + queue.addLast(links.createAnchor(SectionName.NAVBAR_TOP)); + queue.addLast(links.createLink(SectionName.SKIP_NAVBAR_TOP, skipNavLinks, + skipNavLinks.toString(), "")); + queue.addLast(links.createAnchor(SectionName.NAVBAR_TOP_FIRSTROW)); + queue.addLast(links.createAnchor(SectionName.SKIP_NAVBAR_TOP)); + topBottomNavContents.put(position, queue); + break; + case BOTTOM: + queue.addLast(links.createAnchor(SectionName.NAVBAR_BOTTOM)); + queue.addLast(links.createLink(SectionName.SKIP_NAVBAR_BOTTOM, skipNavLinks, + skipNavLinks.toString(), "")); + queue.addLast(links.createAnchor(SectionName.NAVBAR_BOTTOM_FIRSTROW)); + queue.addLast(links.createAnchor(SectionName.SKIP_NAVBAR_BOTTOM)); + topBottomNavContents.put(position, queue); + break; + default: + break; + } + } + + public Navigation setNavLinkModule(Content navLinkModule) { + this.navLinkModule = navLinkModule; + return this; + } + + public Navigation setNavLinkPackage(Content navLinkPackage) { + this.navLinkPackage = navLinkPackage; + return this; + } + + public Navigation setNavLinkClass(Content navLinkClass) { + this.navLinkClass = navLinkClass; + return this; + } + + public Navigation setMemberSummaryBuilder(MemberSummaryBuilder memberSummaryBuilder) { + this.memberSummaryBuilder = memberSummaryBuilder; + return this; + } + + public Navigation setDisplaySummaryModuleDescLink(boolean displaySummaryModuleDescLink) { + this.displaySummaryModuleDescLink = displaySummaryModuleDescLink; + return this; + } + + public Navigation setDisplaySummaryModulesLink(boolean displaySummaryModulesLink) { + this.displaySummaryModulesLink = displaySummaryModulesLink; + return this; + } + + public Navigation setDisplaySummaryPackagesLink(boolean displaySummaryPackagesLink) { + this.displaySummaryPackagesLink = displaySummaryPackagesLink; + return this; + } + + public Navigation setDisplaySummaryServicesLink(boolean displaySummaryServicesLink) { + this.displaySummaryServicesLink = displaySummaryServicesLink; + return this; + } + + public Navigation setUserHeader(Content userHeader) { + this.userHeader = userHeader; + return this; + } + + public Navigation setUserFooter(Content userFooter) { + this.userFooter = userFooter; + return this; + } + + /** + * Add the links for the main navigation. + * + * @param tree the content tree to which the main navigation will added + */ + private void addMainNavLinks(Content tree) { + switch (documentedPage) { + case OVERVIEW: + addActivePageLink(tree, contents.overviewLabel, configuration.createoverview); + addModuleLink(tree); + addPackageLink(tree); + addPageLabel(tree, contents.classLabel, true); + addPageLabel(tree, contents.useLabel, configuration.classuse); + addTreeLink(tree); + addDeprecatedLink(tree); + addIndexLink(tree); + addHelpLink(tree); + break; + case MODULE: + addOverviewLink(tree); + addActivePageLink(tree, contents.moduleLabel, configuration.showModules); + addPackageLink(tree); + addPageLabel(tree, contents.classLabel, true); + addPageLabel(tree, contents.useLabel, configuration.classuse); + addTreeLink(tree); + addDeprecatedLink(tree); + addIndexLink(tree); + addHelpLink(tree); + break; + case PACKAGE: + addOverviewLink(tree); + addModuleOfElementLink(tree); + addActivePageLink(tree, contents.packageLabel, true); + addPageLabel(tree, contents.classLabel, true); + if (configuration.classuse) { + addContentToTree(tree, links.createLink(DocPaths.PACKAGE_USE, + contents.useLabel, "", "")); + } + if (configuration.createtree) { + addContentToTree(tree, links.createLink(DocPaths.PACKAGE_TREE, + contents.treeLabel, "", "")); + } + addDeprecatedLink(tree); + addIndexLink(tree); + addHelpLink(tree); + break; + case CLASS: + addOverviewLink(tree); + addModuleOfElementLink(tree); + addPackageSummaryLink(tree); + addActivePageLink(tree, contents.classLabel, true); + if (configuration.classuse) { + addContentToTree(tree, links.createLink(DocPaths.CLASS_USE.resolve(path.basename()), + contents.useLabel)); + } + if (configuration.createtree) { + addContentToTree(tree, links.createLink(DocPaths.PACKAGE_TREE, + contents.treeLabel, "", "")); + } + addDeprecatedLink(tree); + addIndexLink(tree); + addHelpLink(tree); + break; + case USE: + addOverviewLink(tree); + addModuleOfElementLink(tree); + if (element instanceof PackageElement) { + addPackageSummaryLink(tree); + addPageLabel(tree, contents.classLabel, true); + } else { + addPackageOfElementLink(tree); + addContentToTree(tree, navLinkClass); + } + addActivePageLink(tree, contents.useLabel, configuration.classuse); + if (element instanceof PackageElement) { + addContentToTree(tree, links.createLink(DocPaths.PACKAGE_TREE, contents.treeLabel)); + } else { + addContentToTree(tree, configuration.utils.isEnclosingPackageIncluded((TypeElement) element) + ? links.createLink(DocPath.parent.resolve(DocPaths.PACKAGE_TREE), contents.treeLabel) + : links.createLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE), contents.treeLabel)); + } + addDeprecatedLink(tree); + addIndexLink(tree); + addHelpLink(tree); + break; + case TREE: + addOverviewLink(tree); + if (element == null) { + addPageLabel(tree, contents.moduleLabel, configuration.showModules); + addPageLabel(tree, contents.packageLabel, true); + } else { + addModuleOfElementLink(tree); + addPackageSummaryLink(tree); + } + addPageLabel(tree, contents.classLabel, true); + addPageLabel(tree, contents.useLabel, configuration.classuse); + addActivePageLink(tree, contents.treeLabel, configuration.createtree); + addDeprecatedLink(tree); + addIndexLink(tree); + addHelpLink(tree); + break; + case DEPRECATED: + case INDEX: + case HELP: + addOverviewLink(tree); + addModuleLink(tree); + addPackageLink(tree); + addPageLabel(tree, contents.classLabel, true); + addPageLabel(tree, contents.useLabel, configuration.classuse); + addTreeLink(tree); + if (documentedPage == PageMode.DEPRECATED) { + addActivePageLink(tree, contents.deprecatedLabel, !(configuration.nodeprecated + || configuration.nodeprecatedlist)); + } else { + addDeprecatedLink(tree); + } + if (documentedPage == PageMode.INDEX) { + addActivePageLink(tree, contents.indexLabel, configuration.createindex); + } else { + addIndexLink(tree); + } + if (documentedPage == PageMode.HELP) { + addActivePageLink(tree, contents.helpLabel, !configuration.nohelp); + } else { + addHelpLink(tree); + } + break; + case CONSTANTVALUES: + case SERIALIZEDFORM: + addOverviewLink(tree); + addModuleLink(tree); + addPackageLink(tree); + addPageLabel(tree, contents.classLabel, true); + addPageLabel(tree, contents.useLabel, configuration.classuse); + addTreeLink(tree); + addDeprecatedLink(tree); + addIndexLink(tree); + addHelpLink(tree); + break; + case DOCFILE: + addOverviewLink(tree); + addModuleOfElementLink(tree); + addContentToTree(tree, navLinkPackage); + addPageLabel(tree, contents.classLabel, true); + addPageLabel(tree, contents.useLabel, configuration.classuse); + addTreeLink(tree); + addDeprecatedLink(tree); + addIndexLink(tree); + addHelpLink(tree); + break; + default: + break; + } + } + + /** + * Add the summary links to the sub-navigation. + * + * @param tree the content tree to which the sub-navigation will added + */ + private void addSummaryLinks(Content tree) { + List listContents = new ArrayList<>(); + switch (documentedPage) { + case CLASS: + if (element.getKind() == ElementKind.ANNOTATION_TYPE) { + addAnnotationTypeSummaryLink("doclet.navField", + VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS, listContents); + addAnnotationTypeSummaryLink("doclet.navAnnotationTypeRequiredMember", + VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED, listContents); + addAnnotationTypeSummaryLink("doclet.navAnnotationTypeOptionalMember", + VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL, listContents); + } else { + TypeElement typeElement = (TypeElement) element; + for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.summarySet) { + if (kind == VisibleMemberMap.Kind.ENUM_CONSTANTS && !configuration.utils.isEnum(typeElement)) { + continue; + } + if (kind == VisibleMemberMap.Kind.CONSTRUCTORS && configuration.utils.isEnum(typeElement)) { + continue; + } + AbstractMemberWriter writer + = ((AbstractMemberWriter) memberSummaryBuilder.getMemberSummaryWriter(kind)); + if (writer == null) { + addContentToList(listContents, + contents.getContent(VisibleMemberMap.Kind.getNavLinkLabels(kind))); + } else { + addTypeSummaryLink(memberSummaryBuilder.members(kind), + memberSummaryBuilder.getVisibleMemberMap(kind), listContents); + } + } + } + if (!listContents.isEmpty()) { + Content li = HtmlTree.LI(contents.summaryLabel); + li.addContent(Contents.SPACE); + tree.addContent(li); + addListToNav(listContents, tree); + } + break; + case MODULE: + if (displaySummaryModuleDescLink) { + addContentToList(listContents, + links.createLink(SectionName.MODULE_DESCRIPTION, contents.navModuleDescription)); + } else { + addContentToList(listContents, contents.navModuleDescription); + } + if (displaySummaryModulesLink) { + addContentToList(listContents, + links.createLink(SectionName.MODULES, contents.navModules)); + } else { + addContentToList(listContents, contents.navModules); + } + if (displaySummaryPackagesLink) { + addContentToList(listContents, + links.createLink(SectionName.PACKAGES, contents.navPackages)); + } else { + addContentToList(listContents, contents.navPackages); + } + if (displaySummaryServicesLink) { + addContentToList(listContents, + links.createLink(SectionName.SERVICES, contents.navServices)); + } else { + addContentToList(listContents, contents.navServices); + } + if (!listContents.isEmpty()) { + Content li = HtmlTree.LI(contents.moduleSubNavLabel); + li.addContent(Contents.SPACE); + tree.addContent(li); + addListToNav(listContents, tree); + } + break; + default: + break; + } + } + + /** + * Add the navigation summary link. + * + * @param members members to be linked + * @param visibleMemberMap the visible inherited members map + * @param listContents the list of contents + */ + private void addTypeSummaryLink(SortedSet members, + VisibleMemberMap visibleMemberMap, List listContents) { + if (!members.isEmpty()) { + addTypeSummaryLink(null, visibleMemberMap.kind, true, listContents); + return; + } + + SortedSet visibleClasses = visibleMemberMap.getVisibleClasses(); + for (TypeElement t : visibleClasses) { + if (!configuration.getVisibleMemberMap(t, visibleMemberMap.kind).getLeafMembers().isEmpty()) { + addTypeSummaryLink(null, visibleMemberMap.kind, true, listContents); + return; + } + } + addTypeSummaryLink(null, visibleMemberMap.kind, false, listContents); + } + + /** + * Add the navigation Type summary link. + * + * @param typeElement the Type being documented + * @param kind the kind of member being documented + * @param link true if the members are listed and need to be linked + * @param listContents the list of contents to which the summary will be added + */ + private void addTypeSummaryLink(TypeElement typeElement, VisibleMemberMap.Kind kind, boolean link, + List listContents) { + switch (kind) { + case CONSTRUCTORS: + if (link) { + addContentToList(listContents, links.createLink(SectionName.CONSTRUCTOR_SUMMARY, + contents.navConstructor)); + } else { + addContentToList(listContents, contents.navConstructor); + } + break; + case ENUM_CONSTANTS: + if (link) { + if (typeElement == null) { + addContentToList(listContents, links.createLink(SectionName.ENUM_CONSTANT_SUMMARY, + contents.navEnum)); + } else { + addContentToList(listContents, links.createLink( + SectionName.ENUM_CONSTANTS_INHERITANCE, + configuration.getClassName(typeElement), contents.navEnum)); + } + } else { + addContentToList(listContents, contents.navEnum); + } + break; + case FIELDS: + if (link) { + if (typeElement == null) { + addContentToList(listContents, + links.createLink(SectionName.FIELD_SUMMARY, contents.navField)); + } else { + addContentToList(listContents, links.createLink(SectionName.FIELDS_INHERITANCE, + configuration.getClassName(typeElement), contents.navField)); + } + } else { + addContentToList(listContents, contents.navField); + } + break; + case METHODS: + if (link) { + if (typeElement == null) { + addContentToList(listContents, + links.createLink(SectionName.METHOD_SUMMARY, contents.navMethod)); + } else { + addContentToList(listContents, links.createLink(SectionName.METHODS_INHERITANCE, + configuration.getClassName(typeElement), contents.navMethod)); + } + } else { + addContentToList(listContents, contents.navMethod); + } + break; + case INNER_CLASSES: + if (link) { + if (typeElement == null) { + addContentToList(listContents, + links.createLink(SectionName.NESTED_CLASS_SUMMARY, contents.navNested)); + } else { + addContentToList(listContents, links.createLink(SectionName.NESTED_CLASSES_INHERITANCE, + configuration.utils.getFullyQualifiedName(typeElement), contents.navNested)); + } + } else { + addContentToList(listContents, contents.navNested); + } + break; + case PROPERTIES: + if (link) { + if (typeElement == null) { + addContentToList(listContents, + links.createLink(SectionName.PROPERTY_SUMMARY, contents.navProperty)); + } else { + addContentToList(listContents, links.createLink(SectionName.PROPERTIES_INHERITANCE, + configuration.getClassName(typeElement), contents.navProperty)); + } + } else { + addContentToList(listContents, contents.navProperty); + } + break; + default: + break; + } + } + + /** + * Add the navigation Type summary link. + * + * @param label the label to be added + * @param type the kind of member being documented + * @param listContents the list of contents to which the summary will be added + */ + private void addAnnotationTypeSummaryLink(String label, VisibleMemberMap.Kind type, List listContents) { + AbstractMemberWriter writer = ((AbstractMemberWriter) memberSummaryBuilder. + getMemberSummaryWriter(type)); + if (writer == null) { + addContentToList(listContents, contents.getContent(label)); + } else { + boolean link = !memberSummaryBuilder.getVisibleMemberMap(type).noVisibleMembers(); + switch (type) { + case ANNOTATION_TYPE_FIELDS: + if (link) { + addContentToList(listContents, links.createLink(SectionName.ANNOTATION_TYPE_FIELD_SUMMARY, + contents.navField)); + } else { + addContentToList(listContents, contents.navField); + } + break; + case ANNOTATION_TYPE_MEMBER_REQUIRED: + if (link) { + addContentToList(listContents, links.createLink( + SectionName.ANNOTATION_TYPE_REQUIRED_ELEMENT_SUMMARY, + contents.navAnnotationTypeRequiredMember)); + } else { + addContentToList(listContents, contents.navAnnotationTypeRequiredMember); + } + break; + case ANNOTATION_TYPE_MEMBER_OPTIONAL: + if (link) { + addContentToList(listContents, links.createLink( + SectionName.ANNOTATION_TYPE_OPTIONAL_ELEMENT_SUMMARY, + contents.navAnnotationTypeOptionalMember)); + } else { + addContentToList(listContents, contents.navAnnotationTypeOptionalMember); + } + break; + default: + break; + } + } + } + + /** + * Add the detail links to sub-navigation. + * + * @param tree the content tree to which the links will be added + */ + private void addDetailLinks(Content tree) { + switch (documentedPage) { + case CLASS: + List listContents = new ArrayList<>(); + if (element.getKind() == ElementKind.ANNOTATION_TYPE) { + addAnnotationTypeDetailLink(listContents); + } else { + TypeElement typeElement = (TypeElement) element; + for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.detailSet) { + AbstractMemberWriter writer + = ((AbstractMemberWriter) memberSummaryBuilder. + getMemberSummaryWriter(kind)); + if (kind == VisibleMemberMap.Kind.ENUM_CONSTANTS && !configuration.utils.isEnum(typeElement)) { + continue; + } + if (kind == VisibleMemberMap.Kind.CONSTRUCTORS && configuration.utils.isEnum(typeElement)) { + continue; + } + if (writer == null) { + addContentToList(listContents, contents.getContent(VisibleMemberMap.Kind.getNavLinkLabels(kind))); + } else { + addTypeDetailLink(kind, !memberSummaryBuilder.members(kind).isEmpty(), listContents); + } + } + } + if (!listContents.isEmpty()) { + Content li = HtmlTree.LI(contents.detailLabel); + li.addContent(Contents.SPACE); + tree.addContent(li); + addListToNav(listContents, tree); + } + break; + default: + break; + } + } + + /** + * Add the navigation Type detail link. + * + * @param kind the kind of member being documented + * @param link true if the members are listed and need to be linked + * @param listContents the list of contents to which the detail will be added. + */ + protected void addTypeDetailLink(VisibleMemberMap.Kind kind, boolean link, List listContents) { + switch (kind) { + case CONSTRUCTORS: + if (link) { + addContentToList(listContents, links.createLink(SectionName.CONSTRUCTOR_DETAIL, contents.navConstructor)); + } else { + addContentToList(listContents, contents.navConstructor); + } + break; + case ENUM_CONSTANTS: + if (link) { + addContentToList(listContents, links.createLink(SectionName.ENUM_CONSTANT_DETAIL, contents.navEnum)); + } else { + addContentToList(listContents, contents.navEnum); + } + break; + case FIELDS: + if (link) { + addContentToList(listContents, links.createLink(SectionName.FIELD_DETAIL, contents.navField)); + } else { + addContentToList(listContents, contents.navField); + } + break; + case METHODS: + if (link) { + addContentToList(listContents, links.createLink(SectionName.METHOD_DETAIL, contents.navMethod)); + } else { + addContentToList(listContents, contents.navMethod); + } + break; + case PROPERTIES: + if (link) { + addContentToList(listContents, links.createLink(SectionName.PROPERTY_DETAIL, contents.navProperty)); + } else { + addContentToList(listContents, contents.navProperty); + } + break; + default: + break; + } + } + + /** + * Add the navigation Annotation Type detail link. + * + * @param listContents the list of contents to which the annotation detail will be added. + */ + protected void addAnnotationTypeDetailLink(List listContents) { + TypeElement annotationType = (TypeElement) element; + AbstractMemberWriter writerField + = ((AbstractMemberWriter) memberSummaryBuilder. + getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS)); + AbstractMemberWriter writerOptional + = ((AbstractMemberWriter) memberSummaryBuilder. + getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL)); + AbstractMemberWriter writerRequired + = ((AbstractMemberWriter) memberSummaryBuilder. + getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED)); + if (writerField != null) { + addAnnotationTypeDetailLink(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS, + !configuration.utils.getAnnotationFields(annotationType).isEmpty(), + listContents); + } else { + addContentToList(listContents, contents.navField); + } + if (writerOptional != null) { + addAnnotationTypeDetailLink(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL, + !annotationType.getAnnotationMirrors().isEmpty(), listContents); + } else if (writerRequired != null) { + addAnnotationTypeDetailLink(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED, + !annotationType.getAnnotationMirrors().isEmpty(), listContents); + } else { + addContentToList(listContents, contents.navAnnotationTypeMember); + } + } + + /** + * Add the navigation Annotation Type detail link. + * + * @param type the kind of member being documented + * @param link true if the member details need to be linked + * @param listContents the list of contents to which the annotation detail will be added. + */ + protected void addAnnotationTypeDetailLink(VisibleMemberMap.Kind type, boolean link, List listContents) { + switch (type) { + case ANNOTATION_TYPE_FIELDS: + if (link) { + addContentToList(listContents, links.createLink(SectionName.ANNOTATION_TYPE_FIELD_DETAIL, + contents.navField)); + } else { + addContentToList(listContents, contents.navField); + } + break; + case ANNOTATION_TYPE_MEMBER_REQUIRED: + case ANNOTATION_TYPE_MEMBER_OPTIONAL: + if (link) { + addContentToList(listContents, links.createLink(SectionName.ANNOTATION_TYPE_ELEMENT_DETAIL, + contents.navAnnotationTypeMember)); + } else { + addContentToList(listContents, contents.navAnnotationTypeMember); + } + break; + default: + break; + } + } + + private void addContentToList(List listContents, Content tree) { + listContents.add(HtmlTree.LI(tree)); + } + + private void addContentToTree(Content tree, Content content) { + tree.addContent(HtmlTree.LI(content)); + } + + private void addListToNav(List listContents, Content tree) { + int count = 0; + for (Content liContent : listContents) { + if (count < listContents.size() - 1) { + liContent.addContent(Contents.SPACE); + liContent.addContent("|"); + liContent.addContent(Contents.SPACE); + } + tree.addContent(liContent); + count++; + } + } + + private void addActivePageLink(Content tree, Content label, boolean display) { + if (display) { + tree.addContent(HtmlTree.LI(HtmlStyle.navBarCell1Rev, label)); + } + } + + private void addPageLabel(Content tree, Content label, boolean display) { + if (display) { + tree.addContent(HtmlTree.LI(label)); + } + } + + private void addOverviewLink(Content tree) { + if (configuration.createoverview) { + tree.addContent(HtmlTree.LI(links.createLink(pathToRoot.resolve(DocPaths.overviewSummary(configuration.frames)), + contents.overviewLabel, "", ""))); + } + } + + private void addModuleLink(Content tree) { + if (configuration.showModules) { + if (configuration.modules.size() == 1) { + ModuleElement mdle = configuration.modules.first(); + boolean included = configuration.utils.isIncluded(mdle); + tree.addContent(HtmlTree.LI((included) + ? links.createLink(pathToRoot.resolve(configuration.docPaths.moduleSummary(mdle)), contents.moduleLabel, "", "") + : contents.moduleLabel)); + } else if (!configuration.modules.isEmpty()) { + addPageLabel(tree, contents.moduleLabel, true); + } + } + } + + private void addModuleOfElementLink(Content tree) { + if (configuration.showModules) { + tree.addContent(HtmlTree.LI(navLinkModule)); + } + } + + private void addPackageLink(Content tree) { + if (configuration.packages.size() == 1) { + PackageElement packageElement = configuration.packages.first(); + boolean included = packageElement != null && configuration.utils.isIncluded(packageElement); + if (!included) { + for (PackageElement p : configuration.packages) { + if (p.equals(packageElement)) { + included = true; + break; + } + } + } + if (included || packageElement == null) { + tree.addContent(HtmlTree.LI(links.createLink( + pathToRoot.resolve(configuration.docPaths.forPackage(packageElement).resolve(DocPaths.PACKAGE_SUMMARY)), + contents.packageLabel))); + } else { + DocLink crossPkgLink = configuration.extern.getExternalLink( + configuration.utils.getPackageName(packageElement), pathToRoot, + DocPaths.PACKAGE_SUMMARY.getPath()); + if (crossPkgLink != null) { + tree.addContent(HtmlTree.LI(links.createLink(crossPkgLink, contents.packageLabel))); + } else { + tree.addContent(HtmlTree.LI(contents.packageLabel)); + } + } + } else if (!configuration.packages.isEmpty()) { + addPageLabel(tree, contents.packageLabel, true); + } + } + + private void addPackageOfElementLink(Content tree) { + tree.addContent(HtmlTree.LI(links.createLink(DocPath.parent.resolve(DocPaths.PACKAGE_SUMMARY), + contents.packageLabel))); + } + + private void addPackageSummaryLink(Content tree) { + tree.addContent(HtmlTree.LI(links.createLink(DocPaths.PACKAGE_SUMMARY, contents.packageLabel))); + } + + private void addTreeLink(Content tree) { + if (configuration.createtree) { + List packages = new ArrayList<>(configuration.getSpecifiedPackageElements()); + DocPath docPath = packages.size() == 1 && configuration.getSpecifiedTypeElements().isEmpty() + ? pathToRoot.resolve(configuration.docPaths.forPackage(packages.get(0)).resolve(DocPaths.PACKAGE_TREE)) + : pathToRoot.resolve(DocPaths.OVERVIEW_TREE); + tree.addContent(HtmlTree.LI(links.createLink(docPath, contents.treeLabel, "", ""))); + } + } + + private void addDeprecatedLink(Content tree) { + if (!(configuration.nodeprecated || configuration.nodeprecatedlist)) { + tree.addContent(HtmlTree.LI(links.createLink(pathToRoot.resolve(DocPaths.DEPRECATED_LIST), + contents.deprecatedLabel, "", ""))); + } + } + + private void addIndexLink(Content tree) { + if (configuration.createindex) { + tree.addContent(HtmlTree.LI(links.createLink(pathToRoot.resolve( + (configuration.splitindex + ? DocPaths.INDEX_FILES.resolve(DocPaths.indexN(1)) + : DocPaths.INDEX_ALL)), + contents.indexLabel, "", ""))); + } + } + + private void addHelpLink(Content tree) { + if (!configuration.nohelp) { + String helpfile = configuration.helpfile; + DocPath helpfilenm; + if (helpfile.isEmpty()) { + helpfilenm = DocPaths.HELP_DOC; + } else { + DocFile file = DocFile.createFileForInput(configuration, helpfile); + helpfilenm = DocPath.create(file.getName()); + } + tree.addContent(HtmlTree.LI(links.createLink(pathToRoot.resolve(helpfilenm), + contents.helpLabel, "", ""))); + } + } + + /** + * Add "FRAMES" link, to switch to the frame version of the output. + * + * @param tree the content tree to which the link will be added + */ + private void addNavShowLists(Content tree) { + DocLink dl = new DocLink(pathToRoot.resolve(DocPaths.INDEX), path.getPath(), null); + Content framesContent = links.createLink(dl, contents.framesLabel, "", "_top"); + tree.addContent(HtmlTree.LI(framesContent)); + } + + /** + * Add "NO FRAMES" link, to switch to the non-frame version of the output. + * + * @param tree the content tree to which the link will be added + */ + private void addNavHideLists(Content tree) { + Content noFramesContent = links.createLink(path.basename(), contents.noFramesLabel, "", "_top"); + tree.addContent(HtmlTree.LI(noFramesContent)); + } + + private void addNavLinkClassIndex(Content tree) { + Content allClassesContent = links.createLink(pathToRoot.resolve( + DocPaths.AllClasses(configuration.frames)), + contents.allClassesLabel, "", ""); + tree.addContent(HtmlTree.LI(allClassesContent)); + } + + private void addSearch(Content tree) { + String searchValueId = "search"; + String reset = "reset"; + HtmlTree inputText = HtmlTree.INPUT("text", searchValueId, searchValueId); + HtmlTree inputReset = HtmlTree.INPUT(reset, reset, reset); + HtmlTree liInput = HtmlTree.LI(HtmlTree.LABEL(searchValueId, searchLabel)); + liInput.addContent(inputText); + liInput.addContent(inputReset); + HtmlTree ulSearch = HtmlTree.UL(HtmlStyle.navListSearch, liInput); + tree.addContent(ulSearch); + } + + private void addAllClassesLinkScript(Content tree, boolean top) { + Content div = HtmlTree.DIV(top + ? Position.TOP.allClassesLinkScript().asContent() + : Position.BOTTOM.allClassesLinkScript().asContent()); + Content div_noscript = HtmlTree.DIV(contents.noScriptMessage); + Content noScript = HtmlTree.NOSCRIPT(div_noscript); + div.addContent(noScript); + tree.addContent(div); + } + + private void addFixedNavScript(Content tree) { + tree.addContent(FIXED_NAV_SCRIPT.asContent()); + } + + /** + * Get the navigation content. + * + * @param top true if the top navigation bar is to be printed + * @return the navigation contents + */ + public Content getContent(boolean top) { + Content contentTree = new ContentBuilder(); + if (!configuration.nonavbar) { + Deque queue; + Content tree = (configuration.htmlVersion == HtmlVersion.HTML5) + ? HtmlTree.NAV() + : contentTree; + HtmlTree navDiv = new HtmlTree(HtmlTag.DIV); + if (top) { + queue = topBottomNavContents.get(Position.TOP); + fixedNavDiv.addContent(Position.TOP.startOfNav()); + navDiv.setStyle(HtmlStyle.topNav); + } else { + queue = topBottomNavContents.get(Position.BOTTOM); + tree.addContent(Position.BOTTOM.startOfNav()); + navDiv.setStyle(HtmlStyle.bottomNav); + } + navDiv.addContent(queue.poll()); + HtmlTree skipLinkDiv = HtmlTree.DIV(HtmlStyle.skipNav, queue.poll()); + navDiv.addContent(skipLinkDiv); + navDiv.addContent(queue.poll()); + HtmlTree navList = new HtmlTree(HtmlTag.UL); + navList.setStyle(HtmlStyle.navList); + navList.addAttr(HtmlAttr.TITLE, rowListTitle); + fixedNavDiv.setStyle(HtmlStyle.fixedNav); + addMainNavLinks(navList); + navDiv.addContent(navList); + Content aboutDiv = HtmlTree.DIV(HtmlStyle.aboutLanguage, top ? userHeader : userFooter); + navDiv.addContent(aboutDiv); + if (top) { + fixedNavDiv.addContent(navDiv); + } else { + tree.addContent(navDiv); + } + HtmlTree subDiv = new HtmlTree(HtmlTag.DIV); + subDiv.setStyle(HtmlStyle.subNav); + HtmlTree ulFrames = new HtmlTree(HtmlTag.UL); + ulFrames.setStyle(HtmlStyle.navList); + if (!configuration.nonavbar) { + if (configuration.frames) { + addNavShowLists(ulFrames); + addNavHideLists(ulFrames); + } + } + subDiv.addContent(ulFrames); + HtmlTree ulAllClasses = new HtmlTree(HtmlTag.UL); + ulAllClasses.setStyle(HtmlStyle.navList); + ulAllClasses.addAttr(HtmlAttr.ID, top + ? Position.TOP.allClassesLinkId() + : Position.BOTTOM.allClassesLinkId()); + addNavLinkClassIndex(ulAllClasses); + subDiv.addContent(ulAllClasses); + if (top && configuration.createindex) { + addSearch(subDiv); + } + addAllClassesLinkScript(subDiv, top); + HtmlTree div = new HtmlTree(HtmlTag.DIV); + // Add the summary links if present. + HtmlTree ulNavSummary = new HtmlTree(HtmlTag.UL); + ulNavSummary.setStyle(HtmlStyle.subNavList); + addSummaryLinks(ulNavSummary); + div.addContent(ulNavSummary); + // Add the detail links if present. + HtmlTree ulNavDetail = new HtmlTree(HtmlTag.UL); + ulNavDetail.setStyle(HtmlStyle.subNavList); + addDetailLinks(ulNavDetail); + div.addContent(ulNavDetail); + subDiv.addContent(div); + subDiv.addContent(queue.poll()); + if (top) { + fixedNavDiv.addContent(subDiv); + fixedNavDiv.addContent(Position.TOP.endOfNav()); + tree.addContent(fixedNavDiv); + HtmlTree paddingDiv = HtmlTree.DIV(HtmlStyle.navPadding, Contents.SPACE); + tree.addContent(paddingDiv); + addFixedNavScript(tree); + } else { + tree.addContent(subDiv); + tree.addContent(Position.BOTTOM.endOfNav()); + } + return tree; + } + return contentTree; + } +} diff --git a/test/langtools/jdk/javadoc/doclet/testModules/TestModuleServicesLink.java b/test/langtools/jdk/javadoc/doclet/testModules/TestModuleServicesLink.java index 5c5fdc60ebf..a8977f3a41b 100644 --- a/test/langtools/jdk/javadoc/doclet/testModules/TestModuleServicesLink.java +++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModuleServicesLink.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8185151 + * @bug 8185151 8196200 * @summary test that navigation summary links are not linked when there are no dependencies * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main @@ -69,10 +69,10 @@ public void checkNavbarWithServices1(Path base) throws Exception { checkExit(Exit.OK); checkOutput("m/module-summary.html", true, - "Description |" - + " Modules |" - + " Packages |" - + " Services"); + "

    3. Description | 
    4. \n" + + "
    5. Modules | 
    6. \n" + + "
    7. Packages | 
    8. \n" + + "
    9. Services
    10. "); } @@ -93,10 +93,10 @@ public void checkNavbarWithServices2(Path base) throws Exception { checkExit(Exit.OK); checkOutput("m/module-summary.html", true, - "Description |" - + " Modules |" - + " Packages |" - + " Services"); + "
    11. Description | 
    12. \n" + + "
    13. Modules | 
    14. \n" + + "
    15. Packages | 
    16. \n" + + "
    17. Services
    18. "); } @@ -115,9 +115,10 @@ public void checkNavbarWithoutServices(Path base) throws Exception { checkExit(Exit.OK); checkOutput("m/module-summary.html", true, - "Description | Modules |" - + " Packages |" - + " Services"); + "
    19. Description | 
    20. \n" + + "
    21. Modules | 
    22. \n" + + "
    23. Packages | 
    24. \n" + + "
    25. Services
    26. "); } } diff --git a/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java b/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java index f127af8756c..d557b1c4dc2 100644 --- a/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java +++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java @@ -26,7 +26,7 @@ * @bug 8154119 8154262 8156077 8157987 8154261 8154817 8135291 8155995 8162363 * 8168766 8168688 8162674 8160196 8175799 8174974 8176778 8177562 8175218 * 8175823 8166306 8178043 8181622 8183511 8169819 8074407 8183037 8191464 - 8164407 8192007 8182765 + 8164407 8192007 8182765 8196200 * @summary Test modules support in javadoc. * @author bpatel * @library ../lib @@ -940,9 +940,10 @@ void checkModuleSummary() { checkOutput("moduleA/module-summary.html", true, "", "\n" + "\n" @@ -964,9 +965,10 @@ void checkModuleSummary() { + "\n" + ""); checkOutput("moduleB/module-summary.html", true, - "
    27. Description | Modules | " - + "Packages | " - + "Services
    28. ", + "
    29. Description | 
    30. \n" + + "
    31. Modules | 
    32. \n" + + "
    33. Packages | 
    34. \n" + + "
    35. Services
    36. ", "\n" + "\n" + "\n" @@ -1180,8 +1182,10 @@ void checkModuleModeCommon() { + " Package Link: testpkgmdltags.
      \n" + ""); checkOutput("moduleA/module-summary.html", true, - "
    37. Description | " - + "Modules | Packages | Services
    38. ", + "
    39. Description | 
    40. \n" + + "
    41. Modules | 
    42. \n" + + "
    43. Packages | 
    44. \n" + + "
    45. Services
    46. ", "moduleB\n" + "testpkgmdlB\n"); checkOutput("moduleB/module-summary.html", true, @@ -1189,8 +1193,10 @@ void checkModuleModeCommon() { + "\n" + "
      With a test description for uses.
      \n\n"); checkOutput("moduletags/module-summary.html", true, - "
    47. Description | Modules" - + " | Packages | Services
    48. ", + "
    49. Description | 
    50. \n" + + "
    51. Modules | 
    52. \n" + + "
    53. Packages | 
    54. \n" + + "
    55. Services
    56. ", "\n" + "", "\n" @@ -1267,8 +1273,10 @@ void checkModuleModeApi(boolean found) { "\n" + ""); checkOutput("moduleB/module-summary.html", found, - "
    57. Description | Modules | " - + "Packages | Services
    58. ", + "
    59. Description | 
    60. \n" + + "
    61. Modules | 
    62. \n" + + "
    63. Packages | 
    64. \n" + + "
    65. Services
    66. ", "\n" + "", "
      Indirect Requires 
      transitivetestpkgmdlA testpkgmdlB 
      \n" @@ -1329,8 +1337,10 @@ void checkModuleModeAll(boolean found) { + "\n" + ""); checkOutput("moduleB/module-summary.html", found, - "
    67. Description | " - + "Modules | Packages | Services
    68. ", + "
    69. Description | 
    70. \n" + + "
    71. Modules | 
    72. \n" + + "
    73. Packages | 
    74. \n" + + "
    75. Services
    76. ", "\n" + "\n" + "\n" diff --git a/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java b/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java index 95b9c308306..2bdda855a62 100644 --- a/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java +++ b/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java @@ -24,24 +24,36 @@ /* * @test * @bug 4131628 4664607 7025314 8023700 7198273 8025633 8026567 8081854 8150188 8151743 8196027 8182765 + * 8196200 * @summary Make sure the Next/Prev Class links iterate through all types. * Make sure the navagation is 2 columns, not 3. * @author jamieh - * @library ../lib + * @library /tools/lib ../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool - * @build JavadocTester + * @build toolbox.ToolBox JavadocTester * @run main TestNavigation */ +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +import toolbox.*; + public class TestNavigation extends JavadocTester { + public final ToolBox tb; public static void main(String... args) throws Exception { TestNavigation tester = new TestNavigation(); - tester.runTests(); + tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + public TestNavigation() { + tb = new ToolBox(); } @Test - void test() { + void test(Path ignore) { javadoc("-d", "out", "-overview", testSrc("overview.html"), "-sourcepath", testSrc, @@ -96,7 +108,7 @@ void test() { } @Test - void test_html4() { + void test_html4(Path ignore) { javadoc("-d", "out-html4", "-html4", "-overview", testSrc("overview.html"), @@ -135,7 +147,7 @@ void test_html4() { // Test for checking additional padding to offset the fixed navigation bar in HTML5. @Test - void test1() { + void test1(Path ignore) { javadoc("-d", "out-1", "-html5", "-sourcepath", testSrc, @@ -167,7 +179,7 @@ void test1() { // Test to make sure that no extra padding for nav bar gets generated if -nonavbar is specified for HTML4. @Test - void test2() { + void test2(Path ignore) { javadoc("-d", "out-2", "-nonavbar", "-sourcepath", testSrc, @@ -197,7 +209,7 @@ void test2() { // Test to make sure that no extra padding for nav bar gets generated if -nonavbar is specified for HTML5. @Test - void test3() { + void test3(Path ignore) { javadoc("-d", "out-3", "-html5", "-nonavbar", @@ -227,4 +239,89 @@ void test3() { + "\n" + ""); } + + @Test + void test4(Path base) throws IOException { + Path src = base.resolve("src"); + tb.writeJavaFiles(src, + "package pkg1; public class A {\n" + + " /**\n" + + " * Class with members.\n" + + " */\n" + + " public static class X {\n" + + " /**\n" + + " * A ctor\n" + + " */\n" + + " public X() {\n" + + " }\n" + + " /**\n" + + " * A field\n" + + " */\n" + + " public int field;\n" + + " /**\n" + + " * A method\n" + + " */\n" + + " public void method() {\n" + + " }\n" + + " /**\n" + + " * An inner class\n" + + " */\n" + + " public static class IC {\n" + + " }\n" + + " }\n" + + " /**\n" + + " * Class with all inherited members.\n" + + " */\n" + + " public static class Y extends X {\n" + + " }\n" + + "}"); + + tb.writeJavaFiles(src, + "package pkg1; public class C {\n" + + "}"); + + tb.writeJavaFiles(src, + "package pkg1; public interface InterfaceWithNoMembers {\n" + + "}"); + + javadoc("-d", "out-4", + "-sourcepath", src.toString(), + "pkg1"); + checkExit(Exit.OK); + + checkOrder("pkg1/A.X.html", + "Summary", + "
    77. Nested | 
    78. ", + "
    79. Field | 
    80. ", + "
    81. Constr | 
    82. ", + "
    83. Method
    84. "); + + checkOrder("pkg1/A.Y.html", + "Summary", + "
    85. Nested | 
    86. ", + "
    87. Field | 
    88. ", + "
    89. Constr | 
    90. ", + "
    91. Method
    92. "); + + checkOrder("pkg1/A.X.IC.html", + "Summary", + "
    93. Nested | 
    94. ", + "
    95. Field | 
    96. ", + "
    97. Constr | 
    98. ", + "
    99. Method
    100. "); + + checkOrder("pkg1/C.html", + "Summary", + "
    101. Nested | 
    102. ", + "
    103. Field | 
    104. ", + "
    105. Constr | 
    106. ", + "
    107. Method
    108. "); + + checkOrder("pkg1/InterfaceWithNoMembers.html", + "Summary", + "
    109. Nested | 
    110. ", + "
    111. Field | 
    112. ", + "
    113. Constr | 
    114. ", + "
    115. Method
    116. "); + } } From be8bccfaa836e033adfc98a4c63aaee27bc8bc17 Mon Sep 17 00:00:00 2001 From: mikael Date: Mon, 9 Apr 2018 10:19:33 -0700 Subject: [PATCH 102/196] 8201263: Trailing backslash in VS120COMNTOOLS leads to ugly error message when running tests Reviewed-by: erikj --- test/TestCommon.gmk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/TestCommon.gmk b/test/TestCommon.gmk index f039288b1a4..73db6f22642 100644 --- a/test/TestCommon.gmk +++ b/test/TestCommon.gmk @@ -446,7 +446,7 @@ JTREG_BASIC_OPTIONS += -e:JIB_DATA_DIR JTREG_BASIC_OPTIONS += -e:JDK8_HOME=${JT_JAVA} # Give aot tests access to Visual Studio installation ifneq ($(VS120COMNTOOLS), ) - JTREG_BASIC_OPTIONS += -e:VS120COMNTOOLS=$(shell $(GETMIXEDPATH) "$(VS120COMNTOOLS)") + JTREG_BASIC_OPTIONS += -e:VS120COMNTOOLS="$(shell $(GETMIXEDPATH) "$(patsubst %\,%,$(VS120COMNTOOLS))")" endif # Set other vm and test options JTREG_TEST_OPTIONS += $(JAVA_ARGS:%=-javaoptions:%) $(JAVA_VM_ARGS:%=-vmoption:%) From 7d91e74b924936f10984504b96679752308ac0d2 Mon Sep 17 00:00:00 2001 From: ihse Date: Mon, 9 Apr 2018 19:23:01 +0200 Subject: [PATCH 103/196] 8201236: Straighten out dtrace build logic Reviewed-by: erikj --- make/common/NativeCompilation.gmk | 3 +- make/hotspot/gensrc/GensrcDtrace.gmk | 52 ++++++++ make/hotspot/lib/CompileDtraceLibraries.gmk | 60 ++++++++++ make/hotspot/lib/CompileDtracePreJvm.gmk | 39 ------ make/hotspot/lib/CompileJvm.gmk | 77 +----------- make/hotspot/lib/CompileLibraries.gmk | 7 +- ...DtracePostJvm.gmk => JvmDtraceObjects.gmk} | 111 ++++-------------- make/hotspot/lib/JvmFlags.gmk | 97 +++++++++++++++ .../src/native/dtrace/generateJvmOffsets.cpp | 24 ++-- .../src/native/dtrace/generateJvmOffsets.h | 43 ------- 10 files changed, 247 insertions(+), 266 deletions(-) create mode 100644 make/hotspot/lib/CompileDtraceLibraries.gmk delete mode 100644 make/hotspot/lib/CompileDtracePreJvm.gmk rename make/hotspot/lib/{CompileDtracePostJvm.gmk => JvmDtraceObjects.gmk} (52%) create mode 100644 make/hotspot/lib/JvmFlags.gmk delete mode 100644 make/hotspot/src/native/dtrace/generateJvmOffsets.h diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index da4d24d1c4c..9533493fd5c 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -297,7 +297,7 @@ define SetupCompileNativeFileBody endif $$($1_OBJ): $$($1_SRC_FILE) $$($$($1_BASE)_COMPILE_VARDEPS_FILE) \ - $$($1_VARDEPS_FILE) | $$($$($1_BASE)_BUILD_INFO) + $$($$($1_BASE)_EXTRA_DEPS) $$($1_VARDEPS_FILE) | $$($$($1_BASE)_BUILD_INFO) $$(call LogInfo, Compiling $$($1_FILENAME) (for $$($$($1_BASE)_BASENAME))) $$(call MakeDir, $$(@D)) ifneq ($(TOOLCHAIN_TYPE), microsoft) @@ -366,6 +366,7 @@ endef # EXCLUDE_PATTERN exclude files matching any of these substrings # EXTRA_FILES List of extra files not in any of the SRC dirs # EXTRA_OBJECT_FILES List of extra object files to include when linking +# EXTRA_DEPS List of extra dependencies to be added to each compiled file # VERSIONINFO_RESOURCE Input file for RC. Setting this implies that RC will be run # RC_FLAGS flags for RC. # EMBED_MANIFEST if true, embed manifest on Windows. diff --git a/make/hotspot/gensrc/GensrcDtrace.gmk b/make/hotspot/gensrc/GensrcDtrace.gmk index e8a5bdb3ef4..3a013c71808 100644 --- a/make/hotspot/gensrc/GensrcDtrace.gmk +++ b/make/hotspot/gensrc/GensrcDtrace.gmk @@ -54,4 +54,56 @@ ifeq ($(call check-jvm-feature, dtrace), true) TARGETS += $(patsubst $(DTRACE_SOURCE_DIR)/%.d, \ $(DTRACE_GENSRC_DIR)/%.h, $(wildcard $(DTRACE_SOURCE_DIR)/*.d)) + ifeq ($(OPENJDK_TARGET_OS), solaris) + ############################################################################ + # First we need to generate the dtraceGenOffsets tool. When run, this will + # produce two header files and a C++ file. Note that generateJvmOffsets.cpp + # is using the same JVM_CFLAGS as libjvm.so. + + # Include support files that will setup JVM compiler flags. + include lib/JvmFeatures.gmk + include lib/JvmFlags.gmk + + # We cannot compile until the JVMTI gensrc has finished + JVMTI_H := $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles/jvmti.h + + $(eval $(call SetupNativeCompilation, BUILD_DTRACE_GEN_OFFSETS, \ + NAME := dtraceGenOffsets, \ + TYPE := EXECUTABLE, \ + SRC := $(TOPDIR)/make/hotspot/src/native/dtrace, \ + TOOLCHAIN := $(TOOLCHAIN_BUILD), \ + LDFLAGS := -m64, \ + CFLAGS := -m64 $(JVM_CFLAGS), \ + EXTRA_DEPS := $(JVMTI_H), \ + OBJECT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets/objs, \ + OUTPUT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets, \ + )) + + DTRACE_GEN_OFFSETS_TOOL := $(BUILD_DTRACE_GEN_OFFSETS_TARGET) + + # Argument 1: Output filename + # Argument 2: dtrace-gen-offset tool command line option + define SetupDtraceOffsetsGeneration + $1: $$(BUILD_DTRACE_GEN_OFFSETS) + $$(call LogInfo, Generating dtrace $2 file $$(@F)) + $$(call MakeDir, $$(@D)) + $$(call ExecuteWithLog, $$@, ( $$(DTRACE_GEN_OFFSETS_TOOL) -$$(strip $2) > $$@ ) ) + + TARGETS += $1 + endef + + JVM_OFFSETS_H := $(DTRACE_GENSRC_DIR)/JvmOffsets.h + JVM_OFFSETS_CPP := $(DTRACE_GENSRC_DIR)/JvmOffsets.cpp + JVM_OFFSETS_INDEX_H := $(DTRACE_GENSRC_DIR)/JvmOffsetsIndex.h + + ############################################################################ + # Run the dtrace-gen-offset tool to generate these three files. + # The generated JvmOffsets.cpp is compiled with the rest of libjvm. + # The header files are used by libjvm_db and jhelper.d, respectively. + + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_H), header)) + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_INDEX_H), index)) + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_CPP), table)) + endif + endif diff --git a/make/hotspot/lib/CompileDtraceLibraries.gmk b/make/hotspot/lib/CompileDtraceLibraries.gmk new file mode 100644 index 00000000000..391f1355472 --- /dev/null +++ b/make/hotspot/lib/CompileDtraceLibraries.gmk @@ -0,0 +1,60 @@ +# +# Copyright (c) 2013, 2018, 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. +# + +ifeq ($(call check-jvm-feature, dtrace), true) + ifeq ($(OPENJDK_TARGET_OS), solaris) + + ############################################################################ + # Build the stand-alone dtrace libraries. + + LIBJVM_DTRACE_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm_dtrace + $(eval $(call SetupNativeCompilation, BUILD_LIBJVM_DTRACE, \ + NAME := jvm_dtrace, \ + OUTPUT_DIR := $(JVM_LIB_OUTPUTDIR), \ + SRC := $(TOPDIR)/src/java.base/solaris/native/libjvm_dtrace, \ + CFLAGS := -m64 -G -mt -KPIC, \ + LDFLAGS := -m64 -mt -xnolib $(SHARED_LIBRARY_FLAGS), \ + LIBS := $(LIBDL) -lthread -ldoor, \ + MAPFILE := $(TOPDIR)/make/mapfiles/libjvm_dtrace/mapfile-vers, \ + OBJECT_DIR := $(LIBJVM_DTRACE_OUTPUTDIR)/objs, \ + )) + + # Note that libjvm_db.c has tests for COMPILER2, but this was never set by + # the old build. + LIBJVM_DB_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm_db + $(eval $(call SetupNativeCompilation, BUILD_LIBJVM_DB, \ + NAME := jvm_db, \ + OUTPUT_DIR := $(JVM_LIB_OUTPUTDIR), \ + SRC := $(TOPDIR)/src/java.base/solaris/native/libjvm_db, \ + CFLAGS := -I$(DTRACE_GENSRC_DIR) -m64 -G -mt -KPIC, \ + LDFLAGS := -m64 -mt -xnolib $(SHARED_LIBRARY_FLAGS), \ + MAPFILE := $(TOPDIR)/make/mapfiles/libjvm_db/mapfile-vers, \ + OBJECT_DIR := $(LIBJVM_DB_OUTPUTDIR)/objs, \ + )) + + TARGETS += $(BUILD_LIBJVM_DTRACE) $(BUILD_LIBJVM_DB) + + endif +endif diff --git a/make/hotspot/lib/CompileDtracePreJvm.gmk b/make/hotspot/lib/CompileDtracePreJvm.gmk deleted file mode 100644 index 66031394af8..00000000000 --- a/make/hotspot/lib/CompileDtracePreJvm.gmk +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright (c) 2016, 2018, 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. -# - -ifeq ($(call check-jvm-feature, dtrace), true) - ifeq ($(OPENJDK_TARGET_OS), solaris) - # These files are are generated by CompileDtrace.gmk but consumed by - # CompileJvm.gmk - DTRACE_OBJ := $(JVM_OUTPUTDIR)/objs/dtrace.o - DTRACE_JHELPER_OBJ := $(JVM_OUTPUTDIR)/objs/dtrace_jhelper.o - DTRACE_EXTRA_OBJECT_FILES := $(DTRACE_OBJ) $(DTRACE_JHELPER_OBJ) - - # Since we cannot generate JvmOffsets.cpp as part of the gensrc step, - # we need this special hook to get it to compile with the rest of libjvm. - JVM_OFFSETS_CPP := $(DTRACE_SUPPORT_DIR)/JvmOffsets.cpp - DTRACE_EXTRA_SOURCE_FILES := $(JVM_OFFSETS_CPP) - endif -endif diff --git a/make/hotspot/lib/CompileJvm.gmk b/make/hotspot/lib/CompileJvm.gmk index 49d24a80700..61f84a145af 100644 --- a/make/hotspot/lib/CompileJvm.gmk +++ b/make/hotspot/lib/CompileJvm.gmk @@ -24,11 +24,13 @@ # # Include support files that will setup compiler flags due to the selected -# jvm feature set, and specific file overrides. +# jvm feature set, specific file overrides, and general flags. include lib/JvmFeatures.gmk include lib/JvmOverrideFiles.gmk +include lib/JvmFlags.gmk -$(eval $(call IncludeCustomExtension, hotspot/lib/CompileJvm.gmk)) +# Include support files that will setup DTRACE_EXTRA_OBJECT_FILES. +include lib/JvmDtraceObjects.gmk ################################################################################ # Setup compilation of the main Hotspot native library (libjvm). @@ -39,71 +41,6 @@ JVM_MAPFILE := $(JVM_OUTPUTDIR)/mapfile ################################################################################ # Platform independent setup -# This variable may be added to by a custom extension -JVM_SRC_ROOTS += $(TOPDIR)/src/hotspot - -JVM_SRC_DIRS += $(call uniq, $(wildcard $(foreach d, $(JVM_SRC_ROOTS), \ - $d/share \ - $d/os/$(HOTSPOT_TARGET_OS) \ - $d/os/$(HOTSPOT_TARGET_OS_TYPE) \ - $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH) \ - $d/os_cpu/$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH) \ - ))) \ - $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles \ - $(JVM_VARIANT_OUTPUTDIR)/gensrc/tracefiles \ - # - -JVM_CFLAGS_INCLUDES += \ - $(patsubst %,-I%,$(filter-out $(JVM_VARIANT_OUTPUTDIR)/gensrc/%, $(JVM_SRC_DIRS))) \ - -I$(JVM_VARIANT_OUTPUTDIR)/gensrc \ - -I$(TOPDIR)/src/hotspot/share/precompiled \ - -I$(TOPDIR)/src/hotspot/share/include \ - -I$(TOPDIR)/src/hotspot/os/$(HOTSPOT_TARGET_OS_TYPE)/include \ - -I$(SUPPORT_OUTPUTDIR)/modules_include/java.base \ - -I$(SUPPORT_OUTPUTDIR)/modules_include/java.base/$(OPENJDK_TARGET_OS_INCLUDE_SUBDIR) \ - -I$(TOPDIR)/src/java.base/share/native/libjimage \ - # - -# INCLUDE_SUFFIX_* is only meant for including the proper -# platform files. Don't use it to guard code. Use the value of -# HOTSPOT_TARGET_CPU_DEFINE etc. instead. -# Remaining TARGET_ARCH_* is needed to select the cpu specific -# sources for 64-bit ARM ports (arm versus aarch64). -JVM_CFLAGS_TARGET_DEFINES += \ - -DTARGET_ARCH_$(HOTSPOT_TARGET_CPU_ARCH) \ - -DINCLUDE_SUFFIX_OS=_$(HOTSPOT_TARGET_OS) \ - -DINCLUDE_SUFFIX_CPU=_$(HOTSPOT_TARGET_CPU_ARCH) \ - -DINCLUDE_SUFFIX_COMPILER=_$(HOTSPOT_TOOLCHAIN_TYPE) \ - -DTARGET_COMPILER_$(HOTSPOT_TOOLCHAIN_TYPE) \ - -D$(HOTSPOT_TARGET_CPU_DEFINE) \ - -DHOTSPOT_LIB_ARCH='"$(OPENJDK_TARGET_CPU_LEGACY_LIB)"' \ - # - -ifeq ($(DEBUG_LEVEL), release) - # For hotspot, release builds differ internally between "optimized" and "product" - # in that "optimize" does not define PRODUCT. - ifneq ($(HOTSPOT_DEBUG_LEVEL), optimized) - JVM_CFLAGS_DEBUGLEVEL := -DPRODUCT - endif -else ifeq ($(DEBUG_LEVEL), fastdebug) - JVM_CFLAGS_DEBUGLEVEL := -DASSERT - ifeq ($(filter $(OPENJDK_TARGET_OS), windows aix), ) - # NOTE: Old build did not define CHECK_UNHANDLED_OOPS on Windows and AIX. - JVM_CFLAGS_DEBUGLEVEL += -DCHECK_UNHANDLED_OOPS - endif -else ifeq ($(DEBUG_LEVEL), slowdebug) - # _NMT_NOINLINE_ informs NMT that no inlining is done by the compiler - JVM_CFLAGS_DEBUGLEVEL := -DASSERT -D_NMT_NOINLINE_ -endif - -JVM_CFLAGS += \ - $(JVM_CFLAGS_DEBUGLEVEL) \ - $(JVM_CFLAGS_TARGET_DEFINES) \ - $(JVM_CFLAGS_FEATURES) \ - $(JVM_CFLAGS_INCLUDES) \ - $(EXTRA_CFLAGS) \ - # - JVM_LDFLAGS += \ $(SHARED_LIBRARY_FLAGS) \ $(JVM_LDFLAGS_FEATURES) \ @@ -142,11 +79,6 @@ CFLAGS_VM_VERSION := \ -DCPU='"$(OPENJDK_TARGET_CPU_VM_VERSION)"' \ # -# -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp. -ifeq ($(USE_PRECOMPILED_HEADER), false) - JVM_CFLAGS += -DDONT_USE_PRECOMPILED_HEADER -endif - ################################################################################ # Platform specific setup @@ -214,7 +146,6 @@ $(eval $(call SetupNativeCompilation, BUILD_LIBJVM, \ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ OUTPUT_DIR := $(JVM_LIB_OUTPUTDIR), \ SRC := $(JVM_SRC_DIRS), \ - EXTRA_FILES := $(DTRACE_EXTRA_SOURCE_FILES), \ EXCLUDES := $(JVM_EXCLUDES), \ EXCLUDE_FILES := $(JVM_EXCLUDE_FILES), \ EXCLUDE_PATTERNS := $(JVM_EXCLUDE_PATTERNS), \ diff --git a/make/hotspot/lib/CompileLibraries.gmk b/make/hotspot/lib/CompileLibraries.gmk index 5224de78534..9b04c406421 100644 --- a/make/hotspot/lib/CompileLibraries.gmk +++ b/make/hotspot/lib/CompileLibraries.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2018, 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,11 +31,8 @@ include NativeCompilation.gmk include HotspotCommon.gmk -# The dtrace setup must be done both before and after CompileJvm.gmk, due to -# intricate dependencies. -include lib/CompileDtracePreJvm.gmk include lib/CompileJvm.gmk -include lib/CompileDtracePostJvm.gmk +include lib/CompileDtraceLibraries.gmk ifeq ($(BUILD_GTEST), true) include lib/CompileGtest.gmk diff --git a/make/hotspot/lib/CompileDtracePostJvm.gmk b/make/hotspot/lib/JvmDtraceObjects.gmk similarity index 52% rename from make/hotspot/lib/CompileDtracePostJvm.gmk rename to make/hotspot/lib/JvmDtraceObjects.gmk index ad0b23ef9b9..6f7f4059645 100644 --- a/make/hotspot/lib/CompileDtracePostJvm.gmk +++ b/make/hotspot/lib/JvmDtraceObjects.gmk @@ -23,64 +23,26 @@ # questions. # -################################################################################ -# Support for dtrace integration with libjvm, and stand-alone dtrace library -# compilation. - ifeq ($(call check-jvm-feature, dtrace), true) - ############################################################################## - ifeq ($(OPENJDK_TARGET_OS), solaris) + ############################################################################ - # Integrate with libjvm. Here we generate three object files which are + # Integrate with libjvm. Here we generate two object files which are # linked with libjvm.so. This step is complicated from a dependency - # perspective, since it needs the rest of the compiled object files from the - # libjvm compilation, but the output is object files that are to be included - # when linking libjvm.so. So this generation must happen as a part of the - # libjvm compilation. - - # First we need to generate the dtraceGenOffsets tool. When run, this will - # produce more header files and a C++ file. - - # Note that generateJvmOffsets.cpp must be compiled as if it were a file - # in the libjvm.so, using JVM_CFLAGS as setup in CompileJvm.gmk. Otherwise - # this would preferrably have been done as a part of GensrcDtrace.gmk. - $(eval $(call SetupNativeCompilation, BUILD_DTRACE_GEN_OFFSETS, \ - NAME := dtraceGenOffsets, \ - TYPE := EXECUTABLE, \ - SRC := $(TOPDIR)/make/hotspot/src/native/dtrace, \ - TOOLCHAIN := $(TOOLCHAIN_BUILD), \ - LDFLAGS := -m64, \ - CFLAGS := -m64 $(JVM_CFLAGS), \ - OBJECT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets/objs, \ - OUTPUT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets, \ - )) - - DTRACE_GEN_OFFSETS_TOOL := $(BUILD_DTRACE_GEN_OFFSETS_TARGET) - - # Argument 1: Output filename - # Argument 2: dtrace-gen-offset tool command line option - define SetupDtraceOffsetsGeneration - $1: $$(BUILD_DTRACE_GEN_OFFSETS) - $$(call LogInfo, Generating dtrace $2 file $$(@F)) - $$(call MakeDir, $$(@D)) - $$(call ExecuteWithLog, $$@, ( $$(DTRACE_GEN_OFFSETS_TOOL) -$$(strip $2) > $$@ ) ) - - TARGETS += $1 - endef - - JVM_OFFSETS_H := $(DTRACE_SUPPORT_DIR)/JvmOffsets.h - JVM_OFFSETS_CPP := $(DTRACE_SUPPORT_DIR)/JvmOffsets.cpp - JVM_OFFSETS_INDEX_H := $(DTRACE_SUPPORT_DIR)/JvmOffsetsIndex.h - - # Run the dtrace-gen-offset tool to generate these three files. - # The generated JvmOffsets.cpp is compiled with the rest of libjvm. - $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_H), header)) - $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_INDEX_H), index)) - $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_CPP), table)) + # perspective. We add these two files to the linking of libjvm using + # EXTRA_OBJECT_FILES, but they need to be created outside the call to + # SetupNativeCompilation. Also, one of the files is dependent on compiled + # object files from the libjvm compilation, so this generation must happen + # as a part of the libjvm compilation. + + DTRACE_OBJ := $(JVM_OUTPUTDIR)/objs/dtrace.o + DTRACE_JHELPER_OBJ := $(JVM_OUTPUTDIR)/objs/dtrace_jhelper.o + + DTRACE_EXTRA_OBJECT_FILES := $(DTRACE_OBJ) $(DTRACE_JHELPER_OBJ) ############################################################################ - # Generate DTRACE_OBJ which is linked with libjvm.so. + # Generate DTRACE_OBJ which is linked with libjvm.so. It depends on a set of + # object files from the compilation. # Concatenate all *.d files into a single file DTRACE_SOURCE_FILES := $(addprefix $(TOPDIR)/src/hotspot/os/posix/dtrace/, \ @@ -138,13 +100,17 @@ ifeq ($(call check-jvm-feature, dtrace), true) ############################################################################ # Generate DTRACE_JHELPER_OBJ which is linked with libjvm.so. + JHELPER_DTRACE_SRC := $(TOPDIR)/src/hotspot/os/solaris/dtrace/jhelper.d + + # jhelper.d includes JvmOffsetsIndex.h which was created by the gensrc step. + DTRACE_GENSRC_DIR := $(JVM_VARIANT_OUTPUTDIR)/gensrc/dtracefiles + JVM_OFFSETS_INDEX_H := $(DTRACE_GENSRC_DIR)/JvmOffsetsIndex.h + # Unfortunately dtrace generates incorrect types for some symbols in # dtrace_jhelper.o, resulting in "warning: symbol X has differing types" # See JDK-6890703 for details. # We work around this by fixing the types for these symbols using elfedit, # after dtrace has generated the .o file. - JHELPER_DTRACE_SRC := $(TOPDIR)/src/hotspot/os/solaris/dtrace/jhelper.d - GetElfeditCommands = \ $(foreach symbol, \ $(shell $(GREP) ^extern $(JHELPER_DTRACE_SRC) | $(AWK) '{ gsub(";","") ; print $$3 }'), \ @@ -156,7 +122,7 @@ ifeq ($(call check-jvm-feature, dtrace), true) $(call LogInfo, Running dtrace for $( $(DTRACE_SUPPORT_DIR)/$(@F).d)) $(call ExecuteWithLog, $@, $(DTRACE) $(DTRACE_FLAGS) -o $@ \ -s $(DTRACE_SUPPORT_DIR)/$(@F).d) @@ -164,40 +130,5 @@ ifeq ($(call check-jvm-feature, dtrace), true) $(call ExecuteWithLog, $@.elfedit, $(ELFEDIT) $(call GetElfeditCommands) $@) endif - ############################################################################ - # Build the stand-alone dtrace libraries - - LIBJVM_DTRACE_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm_dtrace - - $(eval $(call SetupNativeCompilation, BUILD_LIBJVM_DTRACE, \ - NAME := jvm_dtrace, \ - OUTPUT_DIR := $(JVM_LIB_OUTPUTDIR), \ - SRC := $(TOPDIR)/src/java.base/solaris/native/libjvm_dtrace, \ - CFLAGS := -m64 -G -mt -KPIC, \ - LDFLAGS := -m64 -mt -xnolib $(SHARED_LIBRARY_FLAGS), \ - LIBS := $(LIBDL) -lthread -ldoor, \ - MAPFILE := $(TOPDIR)/make/mapfiles/libjvm_dtrace/mapfile-vers, \ - OBJECT_DIR := $(LIBJVM_DTRACE_OUTPUTDIR)/objs, \ - )) - - LIBJVM_DB_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm_db - - # Note that libjvm_db.c has tests for COMPILER2, but this was never set by - # the old build. - $(eval $(call SetupNativeCompilation, BUILD_LIBJVM_DB, \ - NAME := jvm_db, \ - OUTPUT_DIR := $(JVM_LIB_OUTPUTDIR), \ - SRC := $(TOPDIR)/src/java.base/solaris/native/libjvm_db, \ - CFLAGS := -I$(JVM_VARIANT_OUTPUTDIR)/gensrc -I$(DTRACE_SUPPORT_DIR) \ - -m64 -G -mt -KPIC, \ - LDFLAGS := -m64 -mt -xnolib $(SHARED_LIBRARY_FLAGS), \ - MAPFILE := $(TOPDIR)/make/mapfiles/libjvm_db/mapfile-vers, \ - OBJECT_DIR := $(LIBJVM_DB_OUTPUTDIR)/objs, \ - )) - - # We need the generated JvmOffsets.h before we can compile the libjvm_db source code. - $(BUILD_LIBJVM_DB_ALL_OBJS): $(JVM_OFFSETS_H) - - TARGETS += $(BUILD_LIBJVM_DTRACE) $(BUILD_LIBJVM_DB) endif endif diff --git a/make/hotspot/lib/JvmFlags.gmk b/make/hotspot/lib/JvmFlags.gmk new file mode 100644 index 00000000000..9e62c37091d --- /dev/null +++ b/make/hotspot/lib/JvmFlags.gmk @@ -0,0 +1,97 @@ +# +# Copyright (c) 2013, 2018, 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. +# + +$(eval $(call IncludeCustomExtension, hotspot/lib/JvmFlags.gmk)) + +################################################################################ +# Setup JVM_CFLAGS. These are shared between GensrcDtrace.gmk and CompileJvm.gmk. + +# This variable may be added to by a custom extension +JVM_SRC_ROOTS += $(TOPDIR)/src/hotspot + +JVM_SRC_DIRS += $(call uniq, $(wildcard $(foreach d, $(JVM_SRC_ROOTS), \ + $d/share \ + $d/os/$(HOTSPOT_TARGET_OS) \ + $d/os/$(HOTSPOT_TARGET_OS_TYPE) \ + $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH) \ + $d/os_cpu/$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH) \ + ))) \ + $(JVM_VARIANT_OUTPUTDIR)/gensrc + # + +JVM_CFLAGS_INCLUDES += \ + $(patsubst %,-I%,$(JVM_SRC_DIRS)) \ + -I$(TOPDIR)/src/hotspot/share/precompiled \ + -I$(TOPDIR)/src/hotspot/share/include \ + -I$(TOPDIR)/src/hotspot/os/$(HOTSPOT_TARGET_OS_TYPE)/include \ + -I$(SUPPORT_OUTPUTDIR)/modules_include/java.base \ + -I$(SUPPORT_OUTPUTDIR)/modules_include/java.base/$(OPENJDK_TARGET_OS_INCLUDE_SUBDIR) \ + -I$(TOPDIR)/src/java.base/share/native/libjimage \ + # + +# INCLUDE_SUFFIX_* is only meant for including the proper +# platform files. Don't use it to guard code. Use the value of +# HOTSPOT_TARGET_CPU_DEFINE etc. instead. +# Remaining TARGET_ARCH_* is needed to select the cpu specific +# sources for 64-bit ARM ports (arm versus aarch64). +JVM_CFLAGS_TARGET_DEFINES += \ + -DTARGET_ARCH_$(HOTSPOT_TARGET_CPU_ARCH) \ + -DINCLUDE_SUFFIX_OS=_$(HOTSPOT_TARGET_OS) \ + -DINCLUDE_SUFFIX_CPU=_$(HOTSPOT_TARGET_CPU_ARCH) \ + -DINCLUDE_SUFFIX_COMPILER=_$(HOTSPOT_TOOLCHAIN_TYPE) \ + -DTARGET_COMPILER_$(HOTSPOT_TOOLCHAIN_TYPE) \ + -D$(HOTSPOT_TARGET_CPU_DEFINE) \ + -DHOTSPOT_LIB_ARCH='"$(OPENJDK_TARGET_CPU_LEGACY_LIB)"' \ + # + +ifeq ($(DEBUG_LEVEL), release) + # For hotspot, release builds differ internally between "optimized" and "product" + # in that "optimize" does not define PRODUCT. + ifneq ($(HOTSPOT_DEBUG_LEVEL), optimized) + JVM_CFLAGS_DEBUGLEVEL := -DPRODUCT + endif +else ifeq ($(DEBUG_LEVEL), fastdebug) + JVM_CFLAGS_DEBUGLEVEL := -DASSERT + ifeq ($(filter $(OPENJDK_TARGET_OS), windows aix), ) + # NOTE: Old build did not define CHECK_UNHANDLED_OOPS on Windows and AIX. + JVM_CFLAGS_DEBUGLEVEL += -DCHECK_UNHANDLED_OOPS + endif +else ifeq ($(DEBUG_LEVEL), slowdebug) + # _NMT_NOINLINE_ informs NMT that no inlining is done by the compiler + JVM_CFLAGS_DEBUGLEVEL := -DASSERT -D_NMT_NOINLINE_ +endif + +JVM_CFLAGS += \ + $(JVM_CFLAGS_DEBUGLEVEL) \ + $(JVM_CFLAGS_TARGET_DEFINES) \ + $(JVM_CFLAGS_FEATURES) \ + $(JVM_CFLAGS_INCLUDES) \ + $(EXTRA_CFLAGS) \ + # + +# -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp. +ifeq ($(USE_PRECOMPILED_HEADER), false) + JVM_CFLAGS += -DDONT_USE_PRECOMPILED_HEADER +endif diff --git a/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp b/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp index 417286e9777..259b881ef2c 100644 --- a/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp +++ b/make/hotspot/src/native/dtrace/generateJvmOffsets.cpp @@ -31,29 +31,23 @@ * GENOFFS_SCCS_VER 34 */ -#include "generateJvmOffsets.h" +#include +#include /* A workaround for private and protected fields */ #define private public #define protected public #include -#include "code/codeBlob.hpp" -#include "code/nmethod.hpp" -#include "code/pcDesc.hpp" #include "gc/shared/collectedHeap.hpp" -#include "memory/heap.hpp" -#include "memory/memRegion.hpp" -#include "memory/universe.hpp" -#include "memory/virtualspace.hpp" -#include "oops/constMethod.hpp" -#include "oops/klass.hpp" -#include "oops/method.hpp" -#include "oops/oop.hpp" -#include "oops/symbol.hpp" #include "runtime/vmStructs.hpp" -#include "utilities/accessFlags.hpp" -#include "utilities/globalDefinitions.hpp" + +typedef enum GEN_variant { + GEN_OFFSET = 0, + GEN_INDEX = 1, + GEN_TABLE = 2 +} GEN_variant; + #ifdef COMPILER1 #ifdef ASSERT diff --git a/make/hotspot/src/native/dtrace/generateJvmOffsets.h b/make/hotspot/src/native/dtrace/generateJvmOffsets.h deleted file mode 100644 index 99146f12c3b..00000000000 --- a/make/hotspot/src/native/dtrace/generateJvmOffsets.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2003, 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. - * - */ - -#ifndef OS_SOLARIS_DTRACE_GENERATEJVMOFFSETS_H -#define OS_SOLARIS_DTRACE_GENERATEJVMOFFSETS_H - -#include -#include - -typedef enum GEN_variant { - GEN_OFFSET = 0, - GEN_INDEX = 1, - GEN_TABLE = 2 -} GEN_variant; - -extern "C" { - int generateJvmOffsets(GEN_variant gen_var); - void gen_prologue(GEN_variant gen_var); - void gen_epilogue(GEN_variant gen_var); -} - -#endif // OS_SOLARIS_DTRACE_GENERATEJVMOFFSETS_H From bb388bb1db599e13b4e1075d4bfdd86ae8f13f31 Mon Sep 17 00:00:00 2001 From: vtheeyarath Date: Mon, 9 Apr 2018 10:39:29 -0700 Subject: [PATCH 104/196] 8164781: Pattern.asPredicate specification is incomplete Summary: Updated specification to reflect usage of find() Reviewed-by: psandoz --- .../share/classes/java/util/regex/Pattern.java | 15 +++++++++++++-- test/jdk/java/util/regex/RegExTest.java | 3 +++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/util/regex/Pattern.java b/src/java.base/share/classes/java/util/regex/Pattern.java index 898cfb2135c..4c5b1cc6634 100644 --- a/src/java.base/share/classes/java/util/regex/Pattern.java +++ b/src/java.base/share/classes/java/util/regex/Pattern.java @@ -5809,10 +5809,21 @@ static CharPredicate CIRangeU(int lower, int upper) { static final Node lastAccept = new LastNode(); /** - * Creates a predicate which can be used to match a string. + * Creates a predicate that tests if this pattern is found in a given input + * string. * - * @return The predicate which can be used for matching on a string + * @apiNote + * This method creates a predicate that behaves as if it creates a matcher + * from the input sequence and then calls {@code find}, for example a + * predicate of the form: + *
      {@code
      +     *   s -> matcher(s).find();
      +     * }
      + * + * @return The predicate which can be used for finding a match on a + * subsequence of a string * @since 1.8 + * @see Matcher#find */ public Predicate asPredicate() { return s -> matcher(s).find(); diff --git a/test/jdk/java/util/regex/RegExTest.java b/test/jdk/java/util/regex/RegExTest.java index d2cc74d6880..d4f1815828f 100644 --- a/test/jdk/java/util/regex/RegExTest.java +++ b/test/jdk/java/util/regex/RegExTest.java @@ -4683,6 +4683,9 @@ private static void patternAsPredicate() throws Exception { if (p.test("1234")) { failCount++; } + if (!p.test("word1234")) { + failCount++; + } report("Pattern.asPredicate"); } From b3d61351185efb56d60ed6a742d33ba5753c5a94 Mon Sep 17 00:00:00 2001 From: weijun Date: Tue, 10 Apr 2018 11:02:09 +0800 Subject: [PATCH 105/196] 8200152: KerberosString should use UTF-8 by default Reviewed-by: xuelei --- .../krb5/internal/util/KerberosString.java | 27 ++++++----- test/jdk/sun/security/krb5/auto/NonAscii.java | 47 +++++++++++++++++++ 2 files changed, 63 insertions(+), 11 deletions(-) create mode 100644 test/jdk/sun/security/krb5/auto/NonAscii.java diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/util/KerberosString.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/util/KerberosString.java index bdca3cf7d76..f4a6dc4dd3d 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/util/KerberosString.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/util/KerberosString.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2018, 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,8 +26,7 @@ package sun.security.krb5.internal.util; import java.io.IOException; -import java.security.AccessController; -import sun.security.action.GetBooleanAction; +import sun.security.action.GetPropertyAction; import sun.security.util.DerValue; /** @@ -45,15 +44,21 @@ public final class KerberosString { /** * RFC 4120 defines KerberosString as GeneralString (IA5String), which - * only includes ASCII characters. However, other implementations have been - * known to use GeneralString to contain UTF-8 encoding. To interop - * with these implementations, the following system property is defined. - * When set as true, KerberosString is encoded as UTF-8. Note that this - * only affects the byte encoding, the tag of the ASN.1 type is still - * GeneralString. + * only includes ASCII characters. However, most implementations have been + * known to use GeneralString to contain UTF-8 encoding. The following + * system property is defined. When set as true, KerberosString is encoded + * as UTF-8. Otherwise, it's ASCII. The default is true. + * + * Note that this only affects the byte encoding, the tag of the ASN.1 + * type is still GeneralString. */ - public static final boolean MSNAME = AccessController.doPrivileged( - new GetBooleanAction("sun.security.krb5.msinterop.kstring")); + public static final boolean MSNAME; + + static { + String prop = GetPropertyAction.privilegedGetProperty( + "sun.security.krb5.msinterop.kstring", "true"); + MSNAME = Boolean.parseBoolean(prop); + } private final String s; diff --git a/test/jdk/sun/security/krb5/auto/NonAscii.java b/test/jdk/sun/security/krb5/auto/NonAscii.java new file mode 100644 index 00000000000..f4716b91f10 --- /dev/null +++ b/test/jdk/sun/security/krb5/auto/NonAscii.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018, 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 8200152 + * @summary KerberosString should use UTF-8 by default + * @library /test/lib + * @compile -XDignore.symbol.file NonAscii.java + * @run main jdk.test.lib.FileInstaller TestHosts TestHosts + * @run main/othervm -Djdk.net.hosts.file=TestHosts NonAscii + * @run main/othervm/fail -Djdk.net.hosts.file=TestHosts + * -Dsun.security.krb5.msinterop.kstring=false + * NonAscii + * @run main/othervm/fail -Djdk.net.hosts.file=TestHosts + * -Dsun.security.krb5.msinterop.kstring=no + * NonAscii + */ + +public class NonAscii { + public static void main(String[] args) throws Exception { + String name = "ab\u00e7"; + char[] password = "password".toCharArray(); + new OneKDC(null).addPrincipal(name, password); + Context.fromUserPass(name, password, false); + } +} From 0037a19968ce2afdde7669426c5f07e66d913db6 Mon Sep 17 00:00:00 2001 From: iignatyev Date: Thu, 19 Apr 2018 15:31:06 -0700 Subject: [PATCH 106/196] 8202037: Split slow ctw_1 tests Reviewed-by: kvn --- test/hotspot/jtreg/TEST.groups | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index 9406782a18a..5cd46140424 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -70,7 +70,13 @@ tier1_compiler = \ hotspot_not_fast_compiler = \ :hotspot_compiler \ - -:tier1_compiler + -:tier1_compiler \ + -:hotspot_slow_compiler + +hotspot_slow_compiler = \ + compiler/codegen/aes \ + compiler/codecache/stress \ + compiler/gcbarriers/PreserveFPRegistersTest.java tier1_compiler_1 = \ compiler/arraycopy/ \ @@ -102,9 +108,7 @@ tier1_compiler_2 = \ compiler/integerArithmetic/ \ compiler/interpreter/ \ compiler/jvmci/ \ - -compiler/codegen/aes \ - -compiler/codecache/stress \ - -compiler/gcbarriers/PreserveFPRegistersTest.java + -:hotspot_slow_compiler tier1_compiler_3 = \ compiler/intrinsics/ \ @@ -133,12 +137,21 @@ tier1_compiler_not_xcomp = \ ctw_1 = \ applications/ctw/modules/ \ - -:ctw_2 + -:ctw_2 \ + -:ctw_3 ctw_2 = \ applications/ctw/modules/java_base.java \ applications/ctw/modules/java_desktop.java +ctw_3 = \ + applications/ctw/modules/javafx_graphics.java \ + applications/ctw/modules/java_xml.java \ + applications/ctw/modules/jdk_compiler.java \ + applications/ctw/modules/jdk_internal_vm_compiler.java \ + applications/ctw/modules/jdk_localedata.java \ + applications/ctw/modules/jdk_scripting_nashorn.java \ + tier1_gc = \ :tier1_gc_1 \ :tier1_gc_2 \ From de5c0cb09600e176ba4facab6ae5fe75f238b835 Mon Sep 17 00:00:00 2001 From: mikael Date: Thu, 19 Apr 2018 17:13:19 -0700 Subject: [PATCH 107/196] 8202052: Disable warnings when building libawt with VS2017 Reviewed-by: erikj, prr --- make/lib/Awt2dLibraries.gmk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/lib/Awt2dLibraries.gmk b/make/lib/Awt2dLibraries.gmk index 1229274869e..ce30a65af98 100644 --- a/make/lib/Awt2dLibraries.gmk +++ b/make/lib/Awt2dLibraries.gmk @@ -224,7 +224,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBAWT, \ format-nonliteral parentheses, \ DISABLED_WARNINGS_clang := logical-op-parentheses extern-initializer, \ DISABLED_WARNINGS_solstudio := E_DECLARATION_IN_CODE, \ - DISABLED_WARNINGS_microsoft := 4297 4244 4267 4996, \ + DISABLED_WARNINGS_microsoft := 4297 4244 4267 4291 4302 4311 4996, \ ASFLAGS := $(LIBAWT_ASFLAGS), \ LDFLAGS := $(LDFLAGS_JDKLIB) $(call SET_SHARED_LIBRARY_ORIGIN), \ LDFLAGS_macosx := -L$(INSTALL_LIBRARIES_HERE), \ From 1f3bfe725e40f7db487fef72496967cdae1e71eb Mon Sep 17 00:00:00 2001 From: mli Date: Fri, 20 Apr 2018 15:16:36 +0800 Subject: [PATCH 108/196] 8161991: java/nio/channels/AsynchronousSocketChannel/Basic.java failed due to RuntimeException: WritePendingException expected 8171404: java/nio/channels/AsynchronousSocketChannel/Basic.java failed with "AsynchronousCloseException expected" 8201520: AsynchronousSocketChannel/Basic.java timeout intermitently Reviewed-by: alanb --- .../AsynchronousSocketChannel/Basic.java | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/test/jdk/java/nio/channels/AsynchronousSocketChannel/Basic.java b/test/jdk/java/nio/channels/AsynchronousSocketChannel/Basic.java index 0dc0318ab68..2b67f4ee7d9 100644 --- a/test/jdk/java/nio/channels/AsynchronousSocketChannel/Basic.java +++ b/test/jdk/java/nio/channels/AsynchronousSocketChannel/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2018, 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,8 +25,8 @@ * @bug 4607272 6842687 6878369 6944810 7023403 * @summary Unit test for AsynchronousSocketChannel(use -Dseed=X to set PRNG seed) * @library /test/lib - * @build jdk.test.lib.RandomFactory - * @run main Basic -skipSlowConnectTest + * @build jdk.test.lib.RandomFactory jdk.test.lib.Utils + * @run main/othervm/timeout=600 Basic -skipSlowConnectTest * @key randomness intermittent */ @@ -79,11 +79,16 @@ static class Server implements Closeable { private final InetSocketAddress address; Server() throws IOException { - ssc = ServerSocketChannel.open().bind(new InetSocketAddress(0)); + this(0); + } - InetAddress lh = InetAddress.getLocalHost(); - int port = ((InetSocketAddress)(ssc.getLocalAddress())).getPort(); - address = new InetSocketAddress(lh, port); + Server(int recvBufSize) throws IOException { + ssc = ServerSocketChannel.open(); + if (recvBufSize > 0) { + ssc.setOption(SO_RCVBUF, recvBufSize); + } + ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + address = (InetSocketAddress)ssc.getLocalAddress(); } InetSocketAddress address() { @@ -293,7 +298,7 @@ static void testCloseWhenPending() throws Exception { System.out.println("-- asynchronous close when reading --"); - try (Server server = new Server()) { + try (Server server = new Server(1)) { ch = AsynchronousSocketChannel.open(); ch.connect(server.address()).get(); @@ -325,6 +330,8 @@ static void testCloseWhenPending() throws Exception { ch = AsynchronousSocketChannel.open(); ch.connect(server.address()).get(); + SocketChannel peer = server.accept(); + peer.setOption(SO_RCVBUF, 1); final AtomicReference writeException = new AtomicReference(); @@ -333,10 +340,13 @@ static void testCloseWhenPending() throws Exception { final AtomicInteger numCompleted = new AtomicInteger(); ch.write(genBuffer(), ch, new CompletionHandler() { public void completed(Integer result, AsynchronousSocketChannel ch) { + System.out.println("completed write to async channel: " + result); numCompleted.incrementAndGet(); ch.write(genBuffer(), ch, this); + System.out.println("started another write to async channel: " + result); } public void failed(Throwable x, AsynchronousSocketChannel ch) { + System.out.println("failed write to async channel"); writeException.set(x); } }); @@ -347,7 +357,8 @@ public void failed(Throwable x, AsynchronousSocketChannel ch) { // the internal channel state indicates it is writing int prevNumCompleted = numCompleted.get(); do { - Thread.sleep(1000); + Thread.sleep((long)(1000 * jdk.test.lib.Utils.TIMEOUT_FACTOR)); + System.out.println("check if buffer is filled up"); if (numCompleted.get() == prevNumCompleted) { break; } @@ -357,14 +368,19 @@ public void failed(Throwable x, AsynchronousSocketChannel ch) { // attempt a concurrent write - // should fail with WritePendingException try { + System.out.println("concurrent write to async channel"); ch.write(genBuffer()); + System.out.format("prevNumCompleted: %d, numCompleted: %d%n", + prevNumCompleted, numCompleted.get()); throw new RuntimeException("WritePendingException expected"); } catch (WritePendingException x) { } // close channel - should cause initial write to complete + System.out.println("closing async channel..."); ch.close(); - server.accept().close(); + System.out.println("closed async channel"); + peer.close(); // wait for exception while (writeException.get() == null) { From 69856d6458782a63953fe9f056d45e19b3f46c95 Mon Sep 17 00:00:00 2001 From: sgehwolf Date: Thu, 19 Apr 2018 17:43:26 +0200 Subject: [PATCH 109/196] 8201788: Number of make jobs wrong for bootcycle-images target Reviewed-by: erikj, ihse --- make/Init.gmk | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/make/Init.gmk b/make/Init.gmk index 6de559e2c60..fa1c5e6fdaf 100644 --- a/make/Init.gmk +++ b/make/Init.gmk @@ -310,9 +310,13 @@ else # HAS_SPEC=true ifneq ($(PARALLEL_TARGETS), ) $(call StartGlobalTimer) $(call PrepareSmartJavac) + # JOBS will only be empty for a bootcycle-images recursive call + # or if specified via a make argument directly. In those cases + # treat it as NOT using jobs at all. ( cd $(TOPDIR) && \ $(NICE) $(MAKE) $(MAKE_ARGS) $(OUTPUT_SYNC_FLAG) \ - -j $(JOBS) -f make/Main.gmk $(USER_MAKE_VARS) \ + $(if $(JOBS), -j $(JOBS)) \ + -f make/Main.gmk $(USER_MAKE_VARS) \ $(PARALLEL_TARGETS) $(COMPARE_BUILD_MAKE) $(BUILD_LOG_PIPE) || \ ( exitcode=$$? && \ $(PRINTF) "\nERROR: Build failed for $(TARGET_DESCRIPTION) (exit code $$exitcode) \n" \ From 0b0dbd8e7abd3d51ad4879e848eb2208f1cefd01 Mon Sep 17 00:00:00 2001 From: mbaesken Date: Tue, 10 Apr 2018 08:38:56 +0200 Subject: [PATCH 110/196] 8201226: missing JNIEXPORT / JNICALL at some places in function declarations/implementations Reviewed-by: ihse, mdoerr Contributed-by: matthias.baesken@sap.com, alexey.ivanov@oracle.com --- src/java.base/share/native/launcher/main.c | 2 +- src/java.base/share/native/libjimage/jimage.cpp | 14 +++++++------- src/java.base/share/native/libjimage/jimage.hpp | 12 ++++++------ src/java.base/share/native/libzip/CRC32.c | 2 +- src/java.base/share/native/libzip/zip_util.c | 14 +++++++------- src/java.base/share/native/libzip/zip_util.h | 14 +++++++------- .../native/common/awt/medialib/mlib_ImageCreate.c | 6 +++--- .../share/native/libmlib_image/mlib_ImageAffine.c | 2 +- .../libmlib_image/mlib_ImageConvKernelConvert.c | 2 +- .../share/native/libmlib_image/mlib_ImageConvMxN.c | 2 +- .../native/libmlib_image/mlib_c_ImageLookUp.c | 2 +- .../native/libsplashscreen/splashscreen_impl.h | 6 +----- .../native/libsplashscreen/splashscreen_sys.c | 2 +- src/jdk.pack/share/native/unpack200/main.cpp | 2 +- 14 files changed, 39 insertions(+), 43 deletions(-) diff --git a/src/java.base/share/native/launcher/main.c b/src/java.base/share/native/launcher/main.c index 58ed4702e12..a477c80784b 100644 --- a/src/java.base/share/native/launcher/main.c +++ b/src/java.base/share/native/launcher/main.c @@ -93,7 +93,7 @@ WinMain(HINSTANCE inst, HINSTANCE previnst, LPSTR cmdline, int cmdshow) __initenv = _environ; #else /* JAVAW */ -JNIEXPORT int JNICALL +JNIEXPORT int main(int argc, char **argv) { int margc; diff --git a/src/java.base/share/native/libjimage/jimage.cpp b/src/java.base/share/native/libjimage/jimage.cpp index e6d5b9707b0..2d8fc02c9d1 100644 --- a/src/java.base/share/native/libjimage/jimage.cpp +++ b/src/java.base/share/native/libjimage/jimage.cpp @@ -55,7 +55,7 @@ * } * ... */ -extern "C" JNIEXPORT JImageFile* JNICALL +extern "C" JNIEXPORT JImageFile* JIMAGE_Open(const char *name, jint* error) { // TODO - return a meaningful error code *error = 0; @@ -72,7 +72,7 @@ JIMAGE_Open(const char *name, jint* error) { * Ex. * (*JImageClose)(image); */ -extern "C" JNIEXPORT void JNICALL +extern "C" JNIEXPORT void JIMAGE_Close(JImageFile* image) { ImageFileReader::close((ImageFileReader*) image); } @@ -89,7 +89,7 @@ JIMAGE_Close(JImageFile* image) { * tty->print_cr(package); * -> java.base */ -extern "C" JNIEXPORT const char* JNICALL +extern "C" JNIEXPORT const char* JIMAGE_PackageToModule(JImageFile* image, const char* package_name) { return ((ImageFileReader*) image)->get_image_module_data()->package_to_module(package_name); } @@ -108,7 +108,7 @@ JIMAGE_PackageToModule(JImageFile* image, const char* package_name) { * JImageLocationRef location = (*JImageFindResource)(image, * "java.base", "9.0", "java/lang/String.class", &size); */ -extern "C" JNIEXPORT JImageLocationRef JNICALL +extern "C" JNIEXPORT JImageLocationRef JIMAGE_FindResource(JImageFile* image, const char* module_name, const char* version, const char* name, jlong* size) { @@ -155,7 +155,7 @@ JIMAGE_FindResource(JImageFile* image, * char* buffer = new char[size]; * (*JImageGetResource)(image, location, buffer, size); */ -extern "C" JNIEXPORT jlong JNICALL +extern "C" JNIEXPORT jlong JIMAGE_GetResource(JImageFile* image, JImageLocationRef location, char* buffer, jlong size) { ((ImageFileReader*) image)->get_resource((u4) location, (u1*) buffer); @@ -184,7 +184,7 @@ JIMAGE_GetResource(JImageFile* image, JImageLocationRef location, * } * (*JImageResourceIterator)(image, ctw_visitor, loader); */ -extern "C" JNIEXPORT void JNICALL +extern "C" JNIEXPORT void JIMAGE_ResourceIterator(JImageFile* image, JImageResourceVisitor_t visitor, void* arg) { ImageFileReader* imageFile = (ImageFileReader*) image; @@ -226,7 +226,7 @@ JIMAGE_ResourceIterator(JImageFile* image, * char path[JIMAGE_MAX_PATH]; * (*JImageResourcePath)(image, location, path, JIMAGE_MAX_PATH); */ -extern "C" JNIEXPORT bool JNICALL +extern "C" JNIEXPORT bool JIMAGE_ResourcePath(JImageFile* image, JImageLocationRef locationRef, char* path, size_t max) { ImageFileReader* imageFile = (ImageFileReader*) image; diff --git a/src/java.base/share/native/libjimage/jimage.hpp b/src/java.base/share/native/libjimage/jimage.hpp index a7a35dc1f74..37dfb5de344 100644 --- a/src/java.base/share/native/libjimage/jimage.hpp +++ b/src/java.base/share/native/libjimage/jimage.hpp @@ -72,7 +72,7 @@ typedef jlong JImageLocationRef; * ... */ -extern "C" JNIEXPORT JImageFile* JNICALL +extern "C" JNIEXPORT JImageFile* JIMAGE_Open(const char *name, jint* error); typedef JImageFile* (*JImageOpen_t)(const char *name, jint* error); @@ -87,7 +87,7 @@ typedef JImageFile* (*JImageOpen_t)(const char *name, jint* error); * (*JImageClose)(image); */ -extern "C" JNIEXPORT void JNICALL +extern "C" JNIEXPORT void JIMAGE_Close(JImageFile* jimage); typedef void (*JImageClose_t)(JImageFile* jimage); @@ -106,7 +106,7 @@ typedef void (*JImageClose_t)(JImageFile* jimage); * -> java.base */ -extern "C" JNIEXPORT const char * JNICALL +extern "C" JNIEXPORT const char * JIMAGE_PackageToModule(JImageFile* jimage, const char* package_name); typedef const char* (*JImagePackageToModule_t)(JImageFile* jimage, const char* package_name); @@ -150,7 +150,7 @@ typedef JImageLocationRef(*JImageFindResource_t)(JImageFile* jimage, * char* buffer = new char[size]; * (*JImageGetResource)(image, location, buffer, size); */ -extern "C" JNIEXPORT jlong JNICALL +extern "C" JNIEXPORT jlong JIMAGE_GetResource(JImageFile* jimage, JImageLocationRef location, char* buffer, jlong size); @@ -185,7 +185,7 @@ typedef bool (*JImageResourceVisitor_t)(JImageFile* jimage, const char* module_name, const char* version, const char* package, const char* name, const char* extension, void* arg); -extern "C" JNIEXPORT void JNICALL +extern "C" JNIEXPORT void JIMAGE_ResourceIterator(JImageFile* jimage, JImageResourceVisitor_t visitor, void *arg); @@ -202,7 +202,7 @@ typedef void (*JImageResourceIterator_t)(JImageFile* jimage, * char path[JIMAGE_MAX_PATH]; * (*JImageResourcePath)(image, location, path, JIMAGE_MAX_PATH); */ -extern "C" JNIEXPORT bool JNICALL +extern "C" JNIEXPORT bool JIMAGE_ResourcePath(JImageFile* image, JImageLocationRef locationRef, char* path, size_t max); diff --git a/src/java.base/share/native/libzip/CRC32.c b/src/java.base/share/native/libzip/CRC32.c index 3715baae569..13cd3f1d3c4 100644 --- a/src/java.base/share/native/libzip/CRC32.c +++ b/src/java.base/share/native/libzip/CRC32.c @@ -54,7 +54,7 @@ Java_java_util_zip_CRC32_updateBytes0(JNIEnv *env, jclass cls, jint crc, return crc; } -JNIEXPORT jint JNICALL +JNIEXPORT jint ZIP_CRC32(jint crc, const jbyte *buf, jint len) { return crc32(crc, (Bytef*)buf, len); diff --git a/src/java.base/share/native/libzip/zip_util.c b/src/java.base/share/native/libzip/zip_util.c index 5c6b3ffa40e..597c3498d74 100644 --- a/src/java.base/share/native/libzip/zip_util.c +++ b/src/java.base/share/native/libzip/zip_util.c @@ -881,7 +881,7 @@ ZIP_Put_In_Cache0(const char *name, ZFILE zfd, char **pmsg, jlong lastModified, * set to the error message text if msg != 0. Otherwise, *msg will be * set to NULL. Caller doesn't need to free the error message. */ -JNIEXPORT jzfile * JNICALL +JNIEXPORT jzfile * ZIP_Open(const char *name, char **pmsg) { jzfile *file = ZIP_Open_Generic(name, pmsg, O_RDONLY, 0); @@ -895,7 +895,7 @@ ZIP_Open(const char *name, char **pmsg) /* * Closes the specified zip file object. */ -JNIEXPORT void JNICALL +JNIEXPORT void ZIP_Close(jzfile *zip) { MLOCK(zfiles_lock); @@ -1115,7 +1115,7 @@ ZIP_FreeEntry(jzfile *jz, jzentry *ze) * Returns the zip entry corresponding to the specified name, or * NULL if not found. */ -JNIEXPORT jzentry * JNICALL +JNIEXPORT jzentry * ZIP_GetEntry(jzfile *zip, char *name, jint ulen) { if (ulen == 0) { @@ -1238,7 +1238,7 @@ ZIP_GetEntry2(jzfile *zip, char *name, jint ulen, jboolean addSlash) * Returns the n'th (starting at zero) zip file entry, or NULL if the * specified index was out of range. */ -JNIEXPORT jzentry * JNICALL +JNIEXPORT jzentry * ZIP_GetNextEntry(jzfile *zip, jint n) { jzentry *result; @@ -1439,7 +1439,7 @@ InflateFully(jzfile *zip, jzentry *entry, void *buf, char **msg) * The current implementation does not support reading an entry that * has the size bigger than 2**32 bytes in ONE invocation. */ -JNIEXPORT jzentry * JNICALL +JNIEXPORT jzentry * ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP) { jzentry *entry = ZIP_GetEntry(zip, name, 0); @@ -1456,7 +1456,7 @@ ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP) * Note: this is called from the separately delivered VM (hotspot/classic) * so we have to be careful to maintain the expected behaviour. */ -JNIEXPORT jboolean JNICALL +JNIEXPORT jboolean ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entryname) { char *msg; @@ -1515,7 +1515,7 @@ ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entryname) return JNI_TRUE; } -JNIEXPORT jboolean JNICALL +JNIEXPORT jboolean ZIP_InflateFully(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg) { z_stream strm; diff --git a/src/java.base/share/native/libzip/zip_util.h b/src/java.base/share/native/libzip/zip_util.h index 663913edafa..41c48a8508c 100644 --- a/src/java.base/share/native/libzip/zip_util.h +++ b/src/java.base/share/native/libzip/zip_util.h @@ -241,16 +241,16 @@ typedef struct jzfile { /* Zip file */ */ #define ZIP_ENDCHAIN ((jint)-1) -JNIEXPORT jzentry * JNICALL +JNIEXPORT jzentry * ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP); -JNIEXPORT jboolean JNICALL +JNIEXPORT jboolean ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entrynm); -JNIEXPORT jzentry * JNICALL +JNIEXPORT jzentry * ZIP_GetNextEntry(jzfile *zip, jint n); -JNIEXPORT jzfile * JNICALL +JNIEXPORT jzfile * ZIP_Open(const char *name, char **pmsg); jzfile * @@ -265,10 +265,10 @@ ZIP_Put_In_Cache(const char *name, ZFILE zfd, char **pmsg, jlong lastModified); jzfile * ZIP_Put_In_Cache0(const char *name, ZFILE zfd, char **pmsg, jlong lastModified, jboolean usemmap); -JNIEXPORT void JNICALL +JNIEXPORT void ZIP_Close(jzfile *zip); -JNIEXPORT jzentry * JNICALL +JNIEXPORT jzentry * ZIP_GetEntry(jzfile *zip, char *name, jint ulen); JNIEXPORT void JNICALL ZIP_Lock(jzfile *zip); @@ -281,7 +281,7 @@ ZIP_FreeEntry(jzfile *zip, jzentry *ze); jlong ZIP_GetEntryDataOffset(jzfile *zip, jzentry *entry); jzentry * ZIP_GetEntry2(jzfile *zip, char *name, jint ulen, jboolean addSlash); -JNIEXPORT jboolean JNICALL +JNIEXPORT jboolean ZIP_InflateFully(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg); #endif /* !_ZIP_H_ */ diff --git a/src/java.desktop/share/native/common/awt/medialib/mlib_ImageCreate.c b/src/java.desktop/share/native/common/awt/medialib/mlib_ImageCreate.c index b91bf8891c9..da65a9f433d 100644 --- a/src/java.desktop/share/native/common/awt/medialib/mlib_ImageCreate.c +++ b/src/java.desktop/share/native/common/awt/medialib/mlib_ImageCreate.c @@ -227,7 +227,7 @@ mlib_image* mlib_ImageSet(mlib_image *image, } /***************************************************************/ -mlib_image *mlib_ImageCreateStruct(mlib_type type, +JNIEXPORT mlib_image* JNICALL mlib_ImageCreateStruct(mlib_type type, mlib_s32 channels, mlib_s32 width, mlib_s32 height, @@ -253,7 +253,7 @@ mlib_image *mlib_ImageCreateStruct(mlib_type type, } /***************************************************************/ -mlib_image *mlib_ImageCreate(mlib_type type, +JNIEXPORT mlib_image* JNICALL mlib_ImageCreate(mlib_type type, mlib_s32 channels, mlib_s32 width, mlib_s32 height) @@ -352,7 +352,7 @@ mlib_image *mlib_ImageCreate(mlib_type type, } /***************************************************************/ -void mlib_ImageDelete(mlib_image *img) +JNIEXPORT void JNICALL mlib_ImageDelete(mlib_image *img) { if (img == NULL) return; if ((img -> flags & MLIB_IMAGE_USERALLOCATED) == 0) { diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageAffine.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageAffine.c index 84d8a147aa3..e614d5e3410 100644 --- a/src/java.desktop/share/native/libmlib_image/mlib_ImageAffine.c +++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageAffine.c @@ -299,7 +299,7 @@ mlib_status mlib_ImageAffine_alltypes(mlib_image *dst, } /***************************************************************/ -mlib_status mlib_ImageAffine(mlib_image *dst, +JNIEXPORT mlib_status JNICALL mlib_ImageAffine(mlib_image *dst, const mlib_image *src, const mlib_d64 *mtx, mlib_filter filter, diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageConvKernelConvert.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageConvKernelConvert.c index 6e4fdbdca5b..ff62e7b788e 100644 --- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConvKernelConvert.c +++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConvKernelConvert.c @@ -78,7 +78,7 @@ #endif /* __sparc */ /***************************************************************/ -mlib_status mlib_ImageConvKernelConvert(mlib_s32 *ikernel, +JNIEXPORT mlib_status JNICALL mlib_ImageConvKernelConvert(mlib_s32 *ikernel, mlib_s32 *iscale, const mlib_d64 *fkernel, mlib_s32 m, diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageConvMxN.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageConvMxN.c index 3c7e835cf62..2206ad11faf 100644 --- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConvMxN.c +++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConvMxN.c @@ -90,7 +90,7 @@ #include "mlib_ImageConvEdge.h" /***************************************************************/ -mlib_status mlib_ImageConvMxN(mlib_image *dst, +JNIEXPORT mlib_status JNICALL mlib_ImageConvMxN(mlib_image *dst, const mlib_image *src, const mlib_s32 *kernel, mlib_s32 m, diff --git a/src/java.desktop/share/native/libmlib_image/mlib_c_ImageLookUp.c b/src/java.desktop/share/native/libmlib_image/mlib_c_ImageLookUp.c index d86d0b17e9f..c98c3ed5407 100644 --- a/src/java.desktop/share/native/libmlib_image/mlib_c_ImageLookUp.c +++ b/src/java.desktop/share/native/libmlib_image/mlib_c_ImageLookUp.c @@ -78,7 +78,7 @@ #include "mlib_c_ImageLookUp.h" /***************************************************************/ -mlib_status mlib_ImageLookUp(mlib_image *dst, +JNIEXPORT mlib_status JNICALL mlib_ImageLookUp(mlib_image *dst, const mlib_image *src, const void **table) { diff --git a/src/java.desktop/share/native/libsplashscreen/splashscreen_impl.h b/src/java.desktop/share/native/libsplashscreen/splashscreen_impl.h index a10ade1b8cd..b6743af1e65 100644 --- a/src/java.desktop/share/native/libsplashscreen/splashscreen_impl.h +++ b/src/java.desktop/share/native/libsplashscreen/splashscreen_impl.h @@ -132,9 +132,6 @@ void SplashDonePlatform(Splash * splash); unsigned SplashTime(); char* SplashConvertStringAlloc(const char* in, int *size); -jboolean SplashGetScaledImageName(const char* jarName, - const char* fileName, float *scaleFactor, - char *scaleImageName, const size_t scaledImageNameLength); void SplashLock(Splash * splash); void SplashUnlock(Splash * splash); @@ -157,8 +154,7 @@ void SplashDone(Splash * splash); void SplashUpdateScreenData(Splash * splash); void SplashCleanup(Splash * splash); -void SplashSetScaleFactor(float scaleFactor); -int SplashGetScaledImgNameMaxPstfixLen(const char *fileName); + void cleanUp(char *fName, char *xName, char *pctName, float *scaleFactor); jboolean GetScaledImageName(const char *fileName, char *scaledImgName, float *scaleFactor, const size_t scaledImageLength); diff --git a/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c b/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c index bf516068f8d..83a7fb36e3b 100644 --- a/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c +++ b/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c @@ -574,7 +574,7 @@ SplashReconfigure(Splash * splash) PostMessage(splash->hWnd, WM_SPLASHRECONFIGURE, 0, 0); } -jboolean +JNIEXPORT jboolean JNICALL SplashGetScaledImageName(const char* jarName, const char* fileName, float *scaleFactor, char *scaleImageName, const size_t scaledImageLength) diff --git a/src/jdk.pack/share/native/unpack200/main.cpp b/src/jdk.pack/share/native/unpack200/main.cpp index 8ff25d1b476..e16314e3665 100644 --- a/src/jdk.pack/share/native/unpack200/main.cpp +++ b/src/jdk.pack/share/native/unpack200/main.cpp @@ -59,7 +59,7 @@ #include "unpack.h" -JNIEXPORT int JNICALL +JNIEXPORT int main(int argc, char **argv) { return unpacker::run(argc, argv); } From d64742359e14fdff2f7c896bf58524dc37abd315 Mon Sep 17 00:00:00 2001 From: ctornqvi Date: Tue, 10 Apr 2018 08:13:06 -0400 Subject: [PATCH 111/196] 8201334: Move runtime/NMT/MallocStressTest.java to hotspot_tier3_runtime Reviewed-by: lfoltan, mseledtsov, mikael --- test/hotspot/jtreg/TEST.groups | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index b4b06329530..666ad5f9751 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -265,7 +265,8 @@ hotspot_tier2_runtime = \ -:tier1_runtime \ -:tier1_serviceability \ -:hotspot_tier2_runtime_platform_agnostic \ - -runtime/signal + -runtime/signal \ + -runtime/NMT/MallocStressTest.java hotspot_tier2_runtime_platform_agnostic = \ runtime/SelectionResolution \ From 59123da37637595b6fdc4851bcf173304f33a506 Mon Sep 17 00:00:00 2001 From: Andrew Leonard Date: Tue, 10 Apr 2018 15:16:20 +0100 Subject: [PATCH 112/196] Add missing jdk9 patches... Signed-off-by: Andrew Leonard --- closed/OpenJ9.gmk | 10 +- closed/autoconf/custom-hook.m4 | 96 +++++++++++++------ closed/autoconf/custom-spec.gmk.in | 4 + .../jdk/internal/module/ModuleBootstrap.java | 13 ++- 4 files changed, 85 insertions(+), 38 deletions(-) diff --git a/closed/OpenJ9.gmk b/closed/OpenJ9.gmk index 0a1c585923c..bc7538eb9af 100644 --- a/closed/OpenJ9.gmk +++ b/closed/OpenJ9.gmk @@ -369,6 +369,7 @@ run-preprocessors-j9 : stage-j9 \ && cd $(OUTPUTDIR)/vm \ && $(MAKE) $(MAKEFLAGS) -f buildtools.mk \ BUILD_ID=$(BUILD_ID) \ + CMAKE=$(CMAKE) $(if $(findstring true,$(OPENJ9_ENABLE_CMAKE)),ENABLE_CMAKE=true CALLED_BY_SOURCE_ZIP=yes) \ EXTRA_CONFIGURE_ARGS=$(OMR_EXTRA_CONFIGURE_ARGS) \ FREEMARKER_JAR="$(FREEMARKER_JAR)" \ J9VM_SHA=$(OPENJ9_SHA) \ @@ -382,10 +383,17 @@ run-preprocessors-j9 : stage-j9 \ build-j9 : run-preprocessors-j9 @$(ECHO) Compiling OpenJ9 in $(OUTPUTDIR)/vm - (export OPENJ9_BUILD=true $(EXPORT_NO_USE_MINGW) \ +ifeq (true,$(OPENJ9_ENABLE_CMAKE)) + (export OPENJ9_BUILD=true $(EXPORT_MSVS_ENV_VARS) \ + && cd $(OUTPUTDIR)/vm/build \ + && $(MAKE) $(MAKEFLAGS) install \ + ) +else + (export OPENJ9_BUILD=true $(EXPORT_NO_USE_MINGW) $(EXPORT_MSVS_ENV_VARS) \ && cd $(OUTPUTDIR)/vm \ && $(MAKE) $(MAKEFLAGS) all \ ) +endif @$(ECHO) OpenJ9 compile complete @$(MKDIR) -p $(MODULES_LIBS_DIR)/java.base diff --git a/closed/autoconf/custom-hook.m4 b/closed/autoconf/custom-hook.m4 index cf77e3bd0d2..37521e18292 100644 --- a/closed/autoconf/custom-hook.m4 +++ b/closed/autoconf/custom-hook.m4 @@ -38,12 +38,35 @@ AC_DEFUN_ONCE([CUSTOM_EARLY_HOOK], OPENJ9_BASIC_SETUP_FUNDAMENTAL_TOOLS OPENJ9_PLATFORM_SETUP OPENJDK_VERSION_DETAILS + OPENJ9_CONFIGURE_CMAKE OPENJ9_CONFIGURE_CUDA OPENJ9_CONFIGURE_DDR OPENJ9_CONFIGURE_NUMA OPENJ9_THIRD_PARTY_REQUIREMENTS ]) +AC_DEFUN([OPENJ9_CONFIGURE_CMAKE], +[ + AC_ARG_WITH(cmake, [AS_HELP_STRING([--with-cmake], [enable building openJ9 with CMake])], + [ + if test "x$with_cmake" != "x"; then + CMAKE=$with_cmake + fi + with_cmake=yes + ], + [with_cmake=no]) + if test "$with_cmake" == "yes"; then + AC_PATH_PROG([CMAKE], [cmake]) + if test "x$CMAKE" == x; then + AC_MSG_ERROR([Could not find CMake]) + fi + OPENJ9_ENABLE_CMAKE=true + else + OPENJ9_ENABLE_CMAKE=false + fi + AC_SUBST(OPENJ9_ENABLE_CMAKE) +]) + AC_DEFUN([OPENJ9_BASIC_SETUP_FUNDAMENTAL_TOOLS], [ BASIC_REQUIRE_PROGS(M4, m4) @@ -151,6 +174,9 @@ AC_DEFUN([OPENJ9_PLATFORM_EXTRACT_VARS_FROM_CPU], powerpc64) OPENJ9_CPU=ppc-64 ;; + arm) + OPENJ9_CPU=arm + ;; *) AC_MSG_ERROR([unsupported OpenJ9 cpu $1]) ;; @@ -158,35 +184,45 @@ AC_DEFUN([OPENJ9_PLATFORM_EXTRACT_VARS_FROM_CPU], ]) AC_DEFUN_ONCE([OPENJ9_PLATFORM_SETUP], -[ - OPENJ9_PLATFORM_EXTRACT_VARS_FROM_CPU($host_cpu) - OPENJ9_BUILDSPEC="${OPENJDK_BUILD_OS}_${OPENJ9_CPU}_cmprssptrs" - OPENJ9_LIBS_SUBDIR=compressedrefs - - if test "x$OPENJ9_CPU" = xx86-64; then - if test "x$OPENJDK_BUILD_OS" = xlinux; then - OPENJ9_PLATFORM_CODE=xa64 - elif test "x$OPENJDK_BUILD_OS" = xwindows; then - OPENJ9_PLATFORM_CODE=wa64 - OPENJ9_BUILDSPEC="win_x86-64_cmprssptrs" - else - AC_MSG_ERROR([Unsupported OpenJ9 platform ${OPENJDK_BUILD_OS}, contact support team!]) - fi - elif test "x$OPENJ9_CPU" = xppc-64_le; then - OPENJ9_PLATFORM_CODE=xl64 - OPENJ9_BUILDSPEC="${OPENJDK_BUILD_OS}_ppc-64_cmprssptrs_le_gcc" - elif test "x$OPENJ9_CPU" = x390-64; then - OPENJ9_PLATFORM_CODE=xz64 - elif test "x$OPENJ9_CPU" = xppc-64; then - OPENJ9_PLATFORM_CODE=ap64 - else - AC_MSG_ERROR([Unsupported OpenJ9 cpu ${OPENJ9_CPU}, contact support team!]) - fi - - AC_SUBST(OPENJ9_BUILDSPEC) - AC_SUBST(OPENJ9_PLATFORM_CODE) - AC_SUBST(COMPILER_VERSION_STRING) - AC_SUBST(OPENJ9_LIBS_SUBDIR) + [ + # When compiling natively host_cpu and build_cpu are the same. But when + # cross compiling we need to work with the host_cpu (which is where the final + # JVM will run). + OPENJ9_PLATFORM_EXTRACT_VARS_FROM_CPU($host_cpu) + OPENJ9_BUILDSPEC="${OPENJDK_BUILD_OS}_${OPENJ9_CPU}_cmprssptrs" + OPENJ9_LIBS_SUBDIR=compressedrefs + + if test "x$OPENJ9_CPU" = xx86-64; then + if test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJ9_PLATFORM_CODE=xa64 + elif test "x$OPENJDK_BUILD_OS" = xwindows; then + OPENJ9_PLATFORM_CODE=wa64 + OPENJ9_BUILDSPEC="win_x86-64_cmprssptrs" + elif test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJ9_PLATFORM_CODE=oa64 + OPENJ9_BUILDSPEC="osx_x86-64" + else + AC_MSG_ERROR([Unsupported OpenJ9 platform ${OPENJDK_BUILD_OS}, contact support team!]) + fi + elif test "x$OPENJ9_CPU" = xppc-64_le; then + OPENJ9_PLATFORM_CODE=xl64 + OPENJ9_BUILDSPEC="${OPENJDK_BUILD_OS}_ppc-64_cmprssptrs_le_gcc" + elif test "x$OPENJ9_CPU" = x390-64; then + OPENJ9_PLATFORM_CODE=xz64 + elif test "x$OPENJ9_CPU" = xppc-64; then + OPENJ9_PLATFORM_CODE=ap64 + elif test "x$OPENJ9_CPU" = xarm; then + OPENJ9_PLATFORM_CODE=xr32 + OPENJ9_BUILDSPEC=linux_arm_linaro + OPENJ9_LIBS_SUBDIR=default + else + AC_MSG_ERROR([Unsupported OpenJ9 cpu ${OPENJ9_CPU}, contact support team!]) + fi + + AC_SUBST(OPENJ9_BUILDSPEC) + AC_SUBST(OPENJ9_PLATFORM_CODE) + AC_SUBST(COMPILER_VERSION_STRING) + AC_SUBST(OPENJ9_LIBS_SUBDIR) ]) AC_DEFUN_ONCE([OPENJDK_VERSION_DETAILS], @@ -194,7 +230,7 @@ AC_DEFUN_ONCE([OPENJDK_VERSION_DETAILS], OPENJDK_SHA=`git -C $TOPDIR rev-parse --short HEAD` LAST_TAGGED_SHA=`git -C $TOPDIR rev-list --tags="jdk-11*" --max-count=1 2>/dev/null` if test "x$LAST_TAGGED_SHA" != x; then - OPENJDK_TAG=`git -C $TOPDIR describe --abbrev=0 --tags "$LAST_TAGGED_SHA"` + OPENJDK_TAG=`git -C $TOPDIR describe --tags "$LAST_TAGGED_SHA"` else OPENJDK_TAG= fi diff --git a/closed/autoconf/custom-spec.gmk.in b/closed/autoconf/custom-spec.gmk.in index 8169e334b3e..2800a4e1b88 100644 --- a/closed/autoconf/custom-spec.gmk.in +++ b/closed/autoconf/custom-spec.gmk.in @@ -54,6 +54,10 @@ OPENJDK_TAG := @OPENJDK_TAG@ J9JDK_EXT_VERSION := ${VERSION_NUMBER_FOUR_POSITIONS} J9JDK_EXT_NAME := Extensions for OpenJDK for Eclipse OpenJ9 +# required by CMake +CMAKE := @CMAKE@ +OPENJ9_ENABLE_CMAKE := @OPENJ9_ENABLE_CMAKE@ + # required by UMA FREEMARKER_JAR := @FREEMARKER_JAR@ OPENJ9_BUILDSPEC := @OPENJ9_BUILDSPEC@ diff --git a/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java b/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java index 9176455af18..06c06d6dee0 100644 --- a/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java +++ b/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java @@ -1,6 +1,6 @@ /* * =========================================================================== - * (c) Copyright IBM Corp. 2014, 2017 All Rights Reserved + * (c) Copyright IBM Corp. 2014, 2018 All Rights Reserved * =========================================================================== */ @@ -350,12 +350,6 @@ public static ModuleLayer boot() throws Exception { Counters.add("jdk.module.boot.4.resolveTime", t4); - ClassLoader appLoader = ClassLoaders.appClassLoader(); //IBM-shared_classes_misc - ClassLoader platformLoader = ClassLoaders.platformClassLoader(); //IBM-shared_classes_misc - ((BuiltinClassLoader)platformLoader).initializeSharedClassesSupport(); //IBM-shared_classes_misc - ((BuiltinClassLoader)appLoader).initializeSharedClassesSupport(); //IBM-shared_classes_misc - - // Step 5: Map the modules in the configuration to class loaders. // The static configuration provides the mapping of standard and JDK // modules to the boot and platform loaders. All other modules (JDK @@ -424,6 +418,11 @@ public static ModuleLayer boot() throws Exception { limitedFinder = new SafeModuleFinder(finder); } + ClassLoader appLoader = ClassLoaders.appClassLoader(); //IBM-shared_classes_misc + ClassLoader platformLoader = ClassLoaders.platformClassLoader(); //IBM-shared_classes_misc + ((BuiltinClassLoader)platformLoader).initializeSharedClassesSupport(); //IBM-shared_classes_misc + ((BuiltinClassLoader)appLoader).initializeSharedClassesSupport(); //IBM-shared_classes_misc + // total time to initialize Counters.add("jdk.module.boot.totalTime", t0); Counters.publish(); From d606bd0a24e2f8601d0d7a5ebf00a14db9928cc7 Mon Sep 17 00:00:00 2001 From: redestad Date: Tue, 10 Apr 2018 16:16:34 +0200 Subject: [PATCH 113/196] 8201179: Regression due loading java.nio.charset.StandardCharsets during bootstrap Reviewed-by: sherman, martin --- .../share/classes/java/lang/StringCoding.java | 8 ++++---- .../classes/java/nio/charset/Charset.java | 2 +- .../java/nio/charset/StandardCharsets.java | 12 ++++++++--- .../share/classes/sun/nio/cs/ISO_8859_1.java | 2 ++ .../sun/nio/cs/StandardCharsets.java.template | 20 +++++++++++-------- .../share/classes/sun/nio/cs/US_ASCII.java | 2 ++ .../share/classes/sun/nio/cs/UTF_8.java | 3 +++ 7 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/java.base/share/classes/java/lang/StringCoding.java b/src/java.base/share/classes/java/lang/StringCoding.java index 32af7076752..77e142dbffd 100644 --- a/src/java.base/share/classes/java/lang/StringCoding.java +++ b/src/java.base/share/classes/java/lang/StringCoding.java @@ -42,7 +42,6 @@ import sun.nio.cs.HistoricallyNamedCharset; import sun.nio.cs.ArrayDecoder; import sun.nio.cs.ArrayEncoder; -import sun.nio.cs.StandardCharsets; import static java.lang.String.LATIN1; import static java.lang.String.UTF16; @@ -52,9 +51,6 @@ import static java.lang.Character.lowSurrogate; import static java.lang.Character.isSupplementaryCodePoint; import static java.lang.StringUTF16.putChar; -import static java.nio.charset.StandardCharsets.ISO_8859_1; -import static java.nio.charset.StandardCharsets.US_ASCII; -import static java.nio.charset.StandardCharsets.UTF_8; /** * Utility class for string encoding and decoding. @@ -70,6 +66,10 @@ private StringCoding() { } private static final ThreadLocal> encoder = new ThreadLocal<>(); + private static final Charset ISO_8859_1 = sun.nio.cs.ISO_8859_1.INSTANCE; + private static final Charset US_ASCII = sun.nio.cs.US_ASCII.INSTANCE; + private static final Charset UTF_8 = sun.nio.cs.UTF_8.INSTANCE; + private static T deref(ThreadLocal> tl) { SoftReference sr = tl.get(); if (sr == null) diff --git a/src/java.base/share/classes/java/nio/charset/Charset.java b/src/java.base/share/classes/java/nio/charset/Charset.java index f77650e1c08..eacaae5024a 100644 --- a/src/java.base/share/classes/java/nio/charset/Charset.java +++ b/src/java.base/share/classes/java/nio/charset/Charset.java @@ -609,7 +609,7 @@ public static Charset defaultCharset() { if (cs != null) defaultCharset = cs; else - defaultCharset = StandardCharsets.UTF_8; + defaultCharset = sun.nio.cs.UTF_8.INSTANCE; } } return defaultCharset; diff --git a/src/java.base/share/classes/java/nio/charset/StandardCharsets.java b/src/java.base/share/classes/java/nio/charset/StandardCharsets.java index 47f1236c893..e67f839e29f 100644 --- a/src/java.base/share/classes/java/nio/charset/StandardCharsets.java +++ b/src/java.base/share/classes/java/nio/charset/StandardCharsets.java @@ -34,22 +34,28 @@ */ public final class StandardCharsets { + // To avoid accidental eager initialization of often unused Charsets + // from happening while the VM is booting up, which may delay + // initialization of VM components, we should generally avoid depending + // on this class from elsewhere in java.base. + private StandardCharsets() { throw new AssertionError("No java.nio.charset.StandardCharsets instances for you!"); } + /** * Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the * Unicode character set */ - public static final Charset US_ASCII = new sun.nio.cs.US_ASCII(); + public static final Charset US_ASCII = sun.nio.cs.US_ASCII.INSTANCE; /** * ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1 */ - public static final Charset ISO_8859_1 = new sun.nio.cs.ISO_8859_1(); + public static final Charset ISO_8859_1 = sun.nio.cs.ISO_8859_1.INSTANCE; /** * Eight-bit UCS Transformation Format */ - public static final Charset UTF_8 = new sun.nio.cs.UTF_8(); + public static final Charset UTF_8 = sun.nio.cs.UTF_8.INSTANCE; /** * Sixteen-bit UCS Transformation Format, big-endian byte order */ diff --git a/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java b/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java index 2ef76f37a01..9aa0d5c6204 100644 --- a/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java +++ b/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java @@ -39,6 +39,8 @@ public class ISO_8859_1 extends Charset implements HistoricallyNamedCharset { + public static final ISO_8859_1 INSTANCE = new ISO_8859_1(); + public ISO_8859_1() { super("ISO-8859-1", StandardCharsets.aliases_ISO_8859_1()); } diff --git a/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template b/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template index 55d43212aab..8f673f9ea2e 100644 --- a/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template +++ b/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template @@ -83,9 +83,9 @@ public class StandardCharsets extends CharsetProvider { Map map = cache; if (map == null) { map = new Cache(); - map.put("utf-8", java.nio.charset.StandardCharsets.UTF_8); - map.put("iso-8859-1", java.nio.charset.StandardCharsets.ISO_8859_1); - map.put("us-ascii", java.nio.charset.StandardCharsets.US_ASCII); + map.put("utf-8", UTF_8.INSTANCE); + map.put("iso-8859-1", ISO_8859_1.INSTANCE); + map.put("us-ascii", US_ASCII.INSTANCE); map.put("utf-16", java.nio.charset.StandardCharsets.UTF_16); map.put("utf-16be", java.nio.charset.StandardCharsets.UTF_16BE); map.put("utf-16le", java.nio.charset.StandardCharsets.UTF_16LE); @@ -122,15 +122,19 @@ public class StandardCharsets extends CharsetProvider { private Charset lookup(String charsetName) { init(); - // By checking these built-ins we can avoid initializing Aliases and - // Classes eagerly during bootstrap + // By checking these built-ins we can avoid initializing Aliases, + // Classes and Cache eagerly during bootstrap. + // + // Initialization of java.nio.charset.StandardCharsets should be + // avoided here to minimize time spent in System.initPhase1, as it + // may delay initialization of performance critical VM subsystems. String csn; if (charsetName.equals("UTF-8")) { - return java.nio.charset.StandardCharsets.UTF_8; + return UTF_8.INSTANCE; } else if (charsetName.equals("US-ASCII")) { - return java.nio.charset.StandardCharsets.US_ASCII; + return US_ASCII.INSTANCE; } else if (charsetName.equals("ISO-8859-1")) { - return java.nio.charset.StandardCharsets.ISO_8859_1; + return ISO_8859_1.INSTANCE; } else { csn = canonicalize(toLower(charsetName)); } diff --git a/src/java.base/share/classes/sun/nio/cs/US_ASCII.java b/src/java.base/share/classes/sun/nio/cs/US_ASCII.java index c40c61bfbdf..100748aa695 100644 --- a/src/java.base/share/classes/sun/nio/cs/US_ASCII.java +++ b/src/java.base/share/classes/sun/nio/cs/US_ASCII.java @@ -36,6 +36,8 @@ public class US_ASCII extends Charset implements HistoricallyNamedCharset { + public static final US_ASCII INSTANCE = new US_ASCII(); + public US_ASCII() { super("US-ASCII", StandardCharsets.aliases_US_ASCII()); } diff --git a/src/java.base/share/classes/sun/nio/cs/UTF_8.java b/src/java.base/share/classes/sun/nio/cs/UTF_8.java index 6f4dee867db..5561fc30065 100644 --- a/src/java.base/share/classes/sun/nio/cs/UTF_8.java +++ b/src/java.base/share/classes/sun/nio/cs/UTF_8.java @@ -55,6 +55,9 @@ */ public final class UTF_8 extends Unicode { + + public static final UTF_8 INSTANCE = new UTF_8(); + public UTF_8() { super("UTF-8", StandardCharsets.aliases_UTF_8()); } From 1c10e1ab15f5d5b1b0bfa02f21d941b8893be6f9 Mon Sep 17 00:00:00 2001 From: "Keith W. Campbell" Date: Tue, 10 Apr 2018 10:42:51 -0400 Subject: [PATCH 114/196] Make indentation consistent * no tabs, two spaces per level Signed-off-by: Keith W. Campbell --- closed/autoconf/custom-hook.m4 | 114 ++++++++++++++++----------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/closed/autoconf/custom-hook.m4 b/closed/autoconf/custom-hook.m4 index 37521e18292..f21dcdb7cda 100644 --- a/closed/autoconf/custom-hook.m4 +++ b/closed/autoconf/custom-hook.m4 @@ -47,24 +47,24 @@ AC_DEFUN_ONCE([CUSTOM_EARLY_HOOK], AC_DEFUN([OPENJ9_CONFIGURE_CMAKE], [ - AC_ARG_WITH(cmake, [AS_HELP_STRING([--with-cmake], [enable building openJ9 with CMake])], - [ - if test "x$with_cmake" != "x"; then - CMAKE=$with_cmake - fi - with_cmake=yes - ], - [with_cmake=no]) - if test "$with_cmake" == "yes"; then - AC_PATH_PROG([CMAKE], [cmake]) - if test "x$CMAKE" == x; then - AC_MSG_ERROR([Could not find CMake]) - fi - OPENJ9_ENABLE_CMAKE=true - else - OPENJ9_ENABLE_CMAKE=false - fi - AC_SUBST(OPENJ9_ENABLE_CMAKE) + AC_ARG_WITH(cmake, [AS_HELP_STRING([--with-cmake], [enable building openJ9 with CMake])], + [ + if test "x$with_cmake" != "x"; then + CMAKE=$with_cmake + fi + with_cmake=yes + ], + [with_cmake=no]) + if test "$with_cmake" == "yes"; then + AC_PATH_PROG([CMAKE], [cmake]) + if test "x$CMAKE" == x; then + AC_MSG_ERROR([Could not find CMake]) + fi + OPENJ9_ENABLE_CMAKE=true + else + OPENJ9_ENABLE_CMAKE=false + fi + AC_SUBST(OPENJ9_ENABLE_CMAKE) ]) AC_DEFUN([OPENJ9_BASIC_SETUP_FUNDAMENTAL_TOOLS], @@ -184,45 +184,45 @@ AC_DEFUN([OPENJ9_PLATFORM_EXTRACT_VARS_FROM_CPU], ]) AC_DEFUN_ONCE([OPENJ9_PLATFORM_SETUP], - [ - # When compiling natively host_cpu and build_cpu are the same. But when - # cross compiling we need to work with the host_cpu (which is where the final - # JVM will run). - OPENJ9_PLATFORM_EXTRACT_VARS_FROM_CPU($host_cpu) - OPENJ9_BUILDSPEC="${OPENJDK_BUILD_OS}_${OPENJ9_CPU}_cmprssptrs" - OPENJ9_LIBS_SUBDIR=compressedrefs - - if test "x$OPENJ9_CPU" = xx86-64; then - if test "x$OPENJDK_BUILD_OS" = xlinux; then - OPENJ9_PLATFORM_CODE=xa64 - elif test "x$OPENJDK_BUILD_OS" = xwindows; then - OPENJ9_PLATFORM_CODE=wa64 - OPENJ9_BUILDSPEC="win_x86-64_cmprssptrs" - elif test "x$OPENJDK_BUILD_OS" = xmacosx; then - OPENJ9_PLATFORM_CODE=oa64 - OPENJ9_BUILDSPEC="osx_x86-64" - else - AC_MSG_ERROR([Unsupported OpenJ9 platform ${OPENJDK_BUILD_OS}, contact support team!]) - fi - elif test "x$OPENJ9_CPU" = xppc-64_le; then - OPENJ9_PLATFORM_CODE=xl64 - OPENJ9_BUILDSPEC="${OPENJDK_BUILD_OS}_ppc-64_cmprssptrs_le_gcc" - elif test "x$OPENJ9_CPU" = x390-64; then - OPENJ9_PLATFORM_CODE=xz64 - elif test "x$OPENJ9_CPU" = xppc-64; then - OPENJ9_PLATFORM_CODE=ap64 - elif test "x$OPENJ9_CPU" = xarm; then - OPENJ9_PLATFORM_CODE=xr32 - OPENJ9_BUILDSPEC=linux_arm_linaro - OPENJ9_LIBS_SUBDIR=default - else - AC_MSG_ERROR([Unsupported OpenJ9 cpu ${OPENJ9_CPU}, contact support team!]) - fi - - AC_SUBST(OPENJ9_BUILDSPEC) - AC_SUBST(OPENJ9_PLATFORM_CODE) - AC_SUBST(COMPILER_VERSION_STRING) - AC_SUBST(OPENJ9_LIBS_SUBDIR) +[ + # When compiling natively host_cpu and build_cpu are the same. But when + # cross compiling we need to work with the host_cpu (which is where the final + # JVM will run). + OPENJ9_PLATFORM_EXTRACT_VARS_FROM_CPU($host_cpu) + OPENJ9_BUILDSPEC="${OPENJDK_BUILD_OS}_${OPENJ9_CPU}_cmprssptrs" + OPENJ9_LIBS_SUBDIR=compressedrefs + + if test "x$OPENJ9_CPU" = xx86-64; then + if test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJ9_PLATFORM_CODE=xa64 + elif test "x$OPENJDK_BUILD_OS" = xwindows; then + OPENJ9_PLATFORM_CODE=wa64 + OPENJ9_BUILDSPEC="win_x86-64_cmprssptrs" + elif test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJ9_PLATFORM_CODE=oa64 + OPENJ9_BUILDSPEC="osx_x86-64" + else + AC_MSG_ERROR([Unsupported OpenJ9 platform ${OPENJDK_BUILD_OS}, contact support team!]) + fi + elif test "x$OPENJ9_CPU" = xppc-64_le; then + OPENJ9_PLATFORM_CODE=xl64 + OPENJ9_BUILDSPEC="${OPENJDK_BUILD_OS}_ppc-64_cmprssptrs_le_gcc" + elif test "x$OPENJ9_CPU" = x390-64; then + OPENJ9_PLATFORM_CODE=xz64 + elif test "x$OPENJ9_CPU" = xppc-64; then + OPENJ9_PLATFORM_CODE=ap64 + elif test "x$OPENJ9_CPU" = xarm; then + OPENJ9_PLATFORM_CODE=xr32 + OPENJ9_BUILDSPEC=linux_arm_linaro + OPENJ9_LIBS_SUBDIR=default + else + AC_MSG_ERROR([Unsupported OpenJ9 cpu ${OPENJ9_CPU}, contact support team!]) + fi + + AC_SUBST(OPENJ9_BUILDSPEC) + AC_SUBST(OPENJ9_PLATFORM_CODE) + AC_SUBST(COMPILER_VERSION_STRING) + AC_SUBST(OPENJ9_LIBS_SUBDIR) ]) AC_DEFUN_ONCE([OPENJDK_VERSION_DETAILS], From 451e9409a35b4279f9bccb469e72665b4894ed12 Mon Sep 17 00:00:00 2001 From: rriggs Date: Tue, 10 Apr 2018 10:49:17 -0400 Subject: [PATCH 115/196] 8201246: Export native function to set platform encoding Reviewed-by: rriggs Contributed-by: andrew_m_leonard@uk.ibm.com --- src/java.base/share/native/libjava/jni_util.c | 6 ++++-- src/java.base/share/native/libjava/jni_util.h | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/native/libjava/jni_util.c b/src/java.base/share/native/libjava/jni_util.c index e42a1c32b38..fa4e39b8a43 100644 --- a/src/java.base/share/native/libjava/jni_util.c +++ b/src/java.base/share/native/libjava/jni_util.c @@ -774,8 +774,10 @@ newStringUTF8(JNIEnv *env, const char *str) return newSizedStringJava(env, str, len); } -/* Initialize the fast encoding from the encoding name. */ -void +/* Initialize the fast encoding from the encoding name. + * Export InitializeEncoding so that the VM can initialize it if required. + */ +JNIEXPORT void InitializeEncoding(JNIEnv *env, const char *encname) { jclass strClazz = NULL; diff --git a/src/java.base/share/native/libjava/jni_util.h b/src/java.base/share/native/libjava/jni_util.h index f043d2f2c57..4be49acf698 100644 --- a/src/java.base/share/native/libjava/jni_util.h +++ b/src/java.base/share/native/libjava/jni_util.h @@ -388,7 +388,7 @@ enum { int getFastEncoding(); -void InitializeEncoding(JNIEnv *env, const char *name); +JNIEXPORT void InitializeEncoding(JNIEnv *env, const char *name); void* getProcessHandle(); From 5fca31668dd913fb363ee6bbab03901e0475eca0 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 10 Apr 2018 10:17:35 -0700 Subject: [PATCH 116/196] 8201327: Make Sensor deeply immutably thread safe Reviewed-by: alanb, chegar, asmundak --- .../classes/sun/management/MemoryPoolImpl.java | 16 +++++++--------- .../share/classes/sun/management/Sensor.java | 11 ++++------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/java.management/share/classes/sun/management/MemoryPoolImpl.java b/src/java.management/share/classes/sun/management/MemoryPoolImpl.java index 881207ae63e..227d19947db 100644 --- a/src/java.management/share/classes/sun/management/MemoryPoolImpl.java +++ b/src/java.management/share/classes/sun/management/MemoryPoolImpl.java @@ -55,10 +55,10 @@ class MemoryPoolImpl implements MemoryPoolMXBean { private long usageThreshold; private long collectionThreshold; - private boolean usageSensorRegistered; - private boolean gcSensorRegistered; - private Sensor usageSensor; - private Sensor gcSensor; + private boolean usageSensorRegistered; // VM-initialized to false + private boolean gcSensorRegistered; // VM-initialized to false + private final Sensor usageSensor; + private final Sensor gcSensor; MemoryPoolImpl(String name, boolean isHeap, long usageThreshold, long gcThreshold) { @@ -72,8 +72,6 @@ class MemoryPoolImpl implements MemoryPoolMXBean { this.collectionThresholdSupported = (gcThreshold >= 0); this.usageSensor = new PoolSensor(this, name + " usage sensor"); this.gcSensor = new CollectionSensor(this, name + " collection sensor"); - this.usageSensorRegistered = false; - this.gcSensorRegistered = false; } public String getName() { @@ -290,7 +288,7 @@ public boolean isCollectionUsageThresholdSupported() { * unless the memory usage has returned below the threshold. */ class PoolSensor extends Sensor { - MemoryPoolImpl pool; + final MemoryPoolImpl pool; PoolSensor(MemoryPoolImpl pool, String name) { super(name); @@ -316,10 +314,10 @@ void clearAction() { * when the memory usage of a memory pool after GC is crossing * the collection threshold. * The VM will trigger this sensor in subsequent crossing - * regardless if the memory usage has changed siince the previous GC. + * regardless if the memory usage has changed since the previous GC. */ class CollectionSensor extends Sensor { - MemoryPoolImpl pool; + final MemoryPoolImpl pool; CollectionSensor(MemoryPoolImpl pool, String name) { super(name); this.pool = pool; diff --git a/src/java.management/share/classes/sun/management/Sensor.java b/src/java.management/share/classes/sun/management/Sensor.java index c2da61d174c..58a7e5142df 100644 --- a/src/java.management/share/classes/sun/management/Sensor.java +++ b/src/java.management/share/classes/sun/management/Sensor.java @@ -48,10 +48,10 @@ */ public abstract class Sensor { - private Object lock; - private String name; - private long count; - private boolean on; + private final Object lock = new Object(); + private final String name; + private long count; // VM-initialized to 0 + private boolean on; // VM-initialized to false /** * Constructs a {@code Sensor} object. @@ -60,9 +60,6 @@ public abstract class Sensor { */ public Sensor(String name) { this.name = name; - this.count = 0; - this.on = false; - this.lock = new Object(); } /** From d0deb78922d9a62589abcd9b6bd760fa9eaccb8f Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 10 Apr 2018 10:18:01 -0700 Subject: [PATCH 117/196] 8201328: SynthParser should use Boolean.parseBoolean Reviewed-by: serb --- .../classes/javax/swing/plaf/synth/SynthParser.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthParser.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthParser.java index d590b3f2317..8bebd502302 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthParser.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthParser.java @@ -746,12 +746,7 @@ else if (aName.equals(ATTRIBUTE_KEY)) { value = lookup(aValue, Object.class); break; case 1: // boolean - if (aValue.toUpperCase().equals("TRUE")) { - value = Boolean.TRUE; - } - else { - value = Boolean.FALSE; - } + value = Boolean.parseBoolean(aValue); break; case 2: // dimension StringTokenizer tok = new StringTokenizer(aValue); @@ -939,11 +934,11 @@ else if (key.equals(ATTRIBUTE_DEST_INSETS)) { ": destinationInsets must be top left bottom right"); } else if (key.equals(ATTRIBUTE_PAINT_CENTER)) { - paintCenter = value.toLowerCase().equals("true"); + paintCenter = Boolean.parseBoolean(value); paintCenterSpecified = true; } else if (key.equals(ATTRIBUTE_STRETCH)) { - stretch = value.toLowerCase().equals("true"); + stretch = Boolean.parseBoolean(value); stretchSpecified = true; } else if (key.equals(ATTRIBUTE_DIRECTION)) { @@ -989,7 +984,7 @@ else if (value == "VERTICAL_SPLIT") { } } else if (key.equals(ATTRIBUTE_CENTER)) { - center = value.toLowerCase().equals("true"); + center = Boolean.parseBoolean(value); } } if (painter == null) { From 2b43a0c501a33b49f7c4d5f45e46fe5f6550486a Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 10 Apr 2018 10:18:55 -0700 Subject: [PATCH 118/196] 8201357: ALSA_CFLAGS is needed; was dropped in JDK-8071469 Reviewed-by: ihse, asmundak --- make/lib/Lib-java.desktop.gmk | 1 + 1 file changed, 1 insertion(+) diff --git a/make/lib/Lib-java.desktop.gmk b/make/lib/Lib-java.desktop.gmk index 0c682a46070..5a2f77f878b 100644 --- a/make/lib/Lib-java.desktop.gmk +++ b/make/lib/Lib-java.desktop.gmk @@ -50,6 +50,7 @@ ifneq ($(OPENJDK_TARGET_OS), aix) LIBJSOUND_CFLAGS := \ -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ + $(ALSA_CFLAGS) \ $(LIBJAVA_HEADER_FLAGS) \ $(foreach dir, $(LIBJSOUND_SRC_DIRS), -I$(dir)) \ -DX_PLATFORM=X_$(OPENJDK_TARGET_OS_UPPERCASE) \ From a3220dae8abbe82e83574e6725f9a3eb62d005e6 Mon Sep 17 00:00:00 2001 From: ihse Date: Tue, 10 Apr 2018 19:46:02 +0200 Subject: [PATCH 119/196] 8200298: Unify all unix versions of libjsig/jsig.c Reviewed-by: dholmes, stuefe --- make/lib/Lib-java.base.gmk | 4 +- make/mapfiles/libjsig/mapfile-vers-solaris | 3 +- src/java.base/linux/native/libjsig/jsig.c | 230 ----------------- src/java.base/macosx/native/libjsig/jsig.c | 237 ------------------ .../{solaris => unix}/native/libjsig/jsig.c | 186 +++++++++----- 5 files changed, 120 insertions(+), 540 deletions(-) delete mode 100644 src/java.base/linux/native/libjsig/jsig.c delete mode 100644 src/java.base/macosx/native/libjsig/jsig.c rename src/java.base/{solaris => unix}/native/libjsig/jsig.c (66%) diff --git a/make/lib/Lib-java.base.gmk b/make/lib/Lib-java.base.gmk index 714e8d74fc9..1d29fb9e820 100644 --- a/make/lib/Lib-java.base.gmk +++ b/make/lib/Lib-java.base.gmk @@ -155,10 +155,10 @@ endif ################################################################################ # Create the jsig library -ifneq ($(OPENJDK_TARGET_OS), windows) +ifeq ($(OPENJDK_TARGET_OS_TYPE), unix) ifeq ($(STATIC_BUILD), false) - LIBJSIG_SRC_DIR := $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libjsig + LIBJSIG_SRC_DIR := $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjsig LIBJSIG_MAPFILE := $(wildcard $(TOPDIR)/make/mapfiles/libjsig/mapfile-vers-$(OPENJDK_TARGET_OS)) ifeq ($(OPENJDK_TARGET_OS), linux) diff --git a/make/mapfiles/libjsig/mapfile-vers-solaris b/make/mapfiles/libjsig/mapfile-vers-solaris index ddb46c050ec..f8f130d3d5b 100644 --- a/make/mapfiles/libjsig/mapfile-vers-solaris +++ b/make/mapfiles/libjsig/mapfile-vers-solaris @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2018, 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,7 +28,6 @@ SUNWprivate_1.1 { global: JVM_begin_signal_setting; JVM_end_signal_setting; - JVM_get_libjsig_version; JVM_get_signal_action; sigaction; signal; diff --git a/src/java.base/linux/native/libjsig/jsig.c b/src/java.base/linux/native/libjsig/jsig.c deleted file mode 100644 index f4221355ca0..00000000000 --- a/src/java.base/linux/native/libjsig/jsig.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2001, 2013, 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. - * - */ - -/* CopyrightVersion 1.2 */ - -/* This is a special library that should be loaded before libc & - * libthread to interpose the signal handler installation functions: - * sigaction(), signal(), sigset(). - * Used for signal-chaining. See RFE 4381843. - */ - -#include -#include -#include -#include -#include -#include - -#define bool int -#define true 1 -#define false 0 - -#define MASK(sig) ((uint64_t)1 << (sig-1)) // 0 is not a signal. -// Check whether all signals fit into jvmsigs. -1 as MASK shifts by -1. -#if (64 < NSIG-1) -#error "Not all signals can be encoded in jvmsigs. Adapt its type!" -#endif -static struct sigaction sact[NSIG]; /* saved signal handlers */ -static uint64_t jvmsigs = 0; /* signals used by jvm */ - -/* used to synchronize the installation of signal handlers */ -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; -static pthread_t tid = 0; - -typedef void (*sa_handler_t)(int); -typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); -typedef sa_handler_t (*signal_t)(int, sa_handler_t); -typedef int (*sigaction_t)(int, const struct sigaction *, struct sigaction *); - -static signal_t os_signal = 0; /* os's version of signal()/sigset() */ -static sigaction_t os_sigaction = 0; /* os's version of sigaction() */ - -static bool jvm_signal_installing = false; -static bool jvm_signal_installed = false; - -static void signal_lock() { - pthread_mutex_lock(&mutex); - /* When the jvm is installing its set of signal handlers, threads - * other than the jvm thread should wait */ - if (jvm_signal_installing) { - if (tid != pthread_self()) { - pthread_cond_wait(&cond, &mutex); - } - } -} - -static void signal_unlock() { - pthread_mutex_unlock(&mutex); -} - -static sa_handler_t call_os_signal(int sig, sa_handler_t disp, - bool is_sigset) { - if (os_signal == NULL) { - if (!is_sigset) { - os_signal = (signal_t)dlsym(RTLD_NEXT, "signal"); - } else { - os_signal = (signal_t)dlsym(RTLD_NEXT, "sigset"); - } - if (os_signal == NULL) { - printf("%s\n", dlerror()); - exit(0); - } - } - return (*os_signal)(sig, disp); -} - -static void save_signal_handler(int sig, sa_handler_t disp) { - sigset_t set; - sact[sig].sa_handler = disp; - sigemptyset(&set); - sact[sig].sa_mask = set; - sact[sig].sa_flags = 0; -} - -static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) { - sa_handler_t oldhandler; - bool sigused; - - signal_lock(); - - sigused = (sig < NSIG) && ((MASK(sig) & jvmsigs) != 0); - if (jvm_signal_installed && sigused) { - /* jvm has installed its signal handler for this signal. */ - /* Save the handler. Don't really install it. */ - oldhandler = sact[sig].sa_handler; - save_signal_handler(sig, disp); - - signal_unlock(); - return oldhandler; - } else if (sig < NSIG && jvm_signal_installing) { - /* jvm is installing its signal handlers. Install the new - * handlers and save the old ones. jvm uses sigaction(). - * Leave the piece here just in case. */ - oldhandler = call_os_signal(sig, disp, is_sigset); - save_signal_handler(sig, oldhandler); - - /* Record the signals used by jvm */ - jvmsigs |= MASK(sig); - - signal_unlock(); - return oldhandler; - } else { - /* jvm has no relation with this signal (yet). Install the - * the handler. */ - oldhandler = call_os_signal(sig, disp, is_sigset); - - signal_unlock(); - return oldhandler; - } -} - -sa_handler_t signal(int sig, sa_handler_t disp) { - return set_signal(sig, disp, false); -} - -sa_handler_t sigset(int sig, sa_handler_t disp) { - return set_signal(sig, disp, true); - } - -static int call_os_sigaction(int sig, const struct sigaction *act, - struct sigaction *oact) { - if (os_sigaction == NULL) { - os_sigaction = (sigaction_t)dlsym(RTLD_NEXT, "sigaction"); - if (os_sigaction == NULL) { - printf("%s\n", dlerror()); - exit(0); - } - } - return (*os_sigaction)(sig, act, oact); -} - -int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { - int res; - bool sigused; - struct sigaction oldAct; - - signal_lock(); - - sigused = (sig < NSIG) && ((MASK(sig) & jvmsigs) != 0); - if (jvm_signal_installed && sigused) { - /* jvm has installed its signal handler for this signal. */ - /* Save the handler. Don't really install it. */ - if (oact != NULL) { - *oact = sact[sig]; - } - if (act != NULL) { - sact[sig] = *act; - } - - signal_unlock(); - return 0; - } else if (sig < NSIG && jvm_signal_installing) { - /* jvm is installing its signal handlers. Install the new - * handlers and save the old ones. */ - res = call_os_sigaction(sig, act, &oldAct); - sact[sig] = oldAct; - if (oact != NULL) { - *oact = oldAct; - } - - /* Record the signals used by jvm */ - jvmsigs |= MASK(sig); - - signal_unlock(); - return res; - } else { - /* jvm has no relation with this signal (yet). Install the - * the handler. */ - res = call_os_sigaction(sig, act, oact); - - signal_unlock(); - return res; - } -} - -/* The three functions for the jvm to call into */ -void JVM_begin_signal_setting() { - signal_lock(); - jvm_signal_installing = true; - tid = pthread_self(); - signal_unlock(); -} - -void JVM_end_signal_setting() { - signal_lock(); - jvm_signal_installed = true; - jvm_signal_installing = false; - pthread_cond_broadcast(&cond); - signal_unlock(); -} - -struct sigaction *JVM_get_signal_action(int sig) { - /* Does race condition make sense here? */ - if ((MASK(sig) & jvmsigs) != 0) { - return &sact[sig]; - } - return NULL; -} diff --git a/src/java.base/macosx/native/libjsig/jsig.c b/src/java.base/macosx/native/libjsig/jsig.c deleted file mode 100644 index d7b1e8be1a7..00000000000 --- a/src/java.base/macosx/native/libjsig/jsig.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (c) 2001, 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. - * - */ - -/* CopyrightVersion 1.2 */ - -/* This is a special library that should be loaded before libc & - * libthread to interpose the signal handler installation functions: - * sigaction(), signal(), sigset(). - * Used for signal-chaining. See RFE 4381843. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define MASK(sig) ((uint32_t)1 << (sig-1)) // 0 is not a signal. -#if (32 < NSIG-1) -#error "Not all signals can be encoded in jvmsigs. Adapt its type!" -#endif -static struct sigaction sact[NSIG]; /* saved signal handlers */ -static uint32_t jvmsigs = 0; /* signals used by jvm */ -static __thread bool reentry = false; /* prevent reentry deadlock (per-thread) */ - -/* used to synchronize the installation of signal handlers */ -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; -static pthread_t tid = 0; - -typedef void (*sa_handler_t)(int); -typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); -typedef sa_handler_t (*signal_t)(int, sa_handler_t); -typedef int (*sigaction_t)(int, const struct sigaction *, struct sigaction *); - -static signal_t os_signal = 0; /* os's version of signal()/sigset() */ -static sigaction_t os_sigaction = 0; /* os's version of sigaction() */ - -static bool jvm_signal_installing = false; -static bool jvm_signal_installed = false; - -static void signal_lock() { - pthread_mutex_lock(&mutex); - /* When the jvm is installing its set of signal handlers, threads - * other than the jvm thread should wait */ - if (jvm_signal_installing) { - if (tid != pthread_self()) { - pthread_cond_wait(&cond, &mutex); - } - } -} - -static void signal_unlock() { - pthread_mutex_unlock(&mutex); -} - -static sa_handler_t call_os_signal(int sig, sa_handler_t disp, - bool is_sigset) { - sa_handler_t res; - - if (os_signal == NULL) { - if (!is_sigset) { - os_signal = (signal_t)dlsym(RTLD_NEXT, "signal"); - } else { - os_signal = (signal_t)dlsym(RTLD_NEXT, "sigset"); - } - if (os_signal == NULL) { - printf("%s\n", dlerror()); - exit(0); - } - } - reentry = true; - res = (*os_signal)(sig, disp); - reentry = false; - return res; -} - -static void save_signal_handler(int sig, sa_handler_t disp) { - sigset_t set; - sact[sig].sa_handler = disp; - sigemptyset(&set); - sact[sig].sa_mask = set; - sact[sig].sa_flags = 0; -} - -static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) { - sa_handler_t oldhandler; - bool sigused; - - signal_lock(); - - sigused = (MASK(sig) & jvmsigs) != 0; - if (jvm_signal_installed && sigused) { - /* jvm has installed its signal handler for this signal. */ - /* Save the handler. Don't really install it. */ - oldhandler = sact[sig].sa_handler; - save_signal_handler(sig, disp); - - signal_unlock(); - return oldhandler; - } else if (jvm_signal_installing) { - /* jvm is installing its signal handlers. Install the new - * handlers and save the old ones. jvm uses sigaction(). - * Leave the piece here just in case. */ - oldhandler = call_os_signal(sig, disp, is_sigset); - save_signal_handler(sig, oldhandler); - - /* Record the signals used by jvm */ - jvmsigs |= MASK(sig); - - signal_unlock(); - return oldhandler; - } else { - /* jvm has no relation with this signal (yet). Install the - * the handler. */ - oldhandler = call_os_signal(sig, disp, is_sigset); - - signal_unlock(); - return oldhandler; - } -} - -sa_handler_t signal(int sig, sa_handler_t disp) { - return set_signal(sig, disp, false); -} - -sa_handler_t sigset(int sig, sa_handler_t disp) { - printf("sigset() is not supported by BSD"); - exit(0); - } - -static int call_os_sigaction(int sig, const struct sigaction *act, - struct sigaction *oact) { - if (os_sigaction == NULL) { - os_sigaction = (sigaction_t)dlsym(RTLD_NEXT, "sigaction"); - if (os_sigaction == NULL) { - printf("%s\n", dlerror()); - exit(0); - } - } - return (*os_sigaction)(sig, act, oact); -} - -int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { - int res; - bool sigused; - struct sigaction oldAct; - - if (reentry) { - return call_os_sigaction(sig, act, oact); - } - - signal_lock(); - - sigused = (MASK(sig) & jvmsigs) != 0; - if (jvm_signal_installed && sigused) { - /* jvm has installed its signal handler for this signal. */ - /* Save the handler. Don't really install it. */ - if (oact != NULL) { - *oact = sact[sig]; - } - if (act != NULL) { - sact[sig] = *act; - } - - signal_unlock(); - return 0; - } else if (jvm_signal_installing) { - /* jvm is installing its signal handlers. Install the new - * handlers and save the old ones. */ - res = call_os_sigaction(sig, act, &oldAct); - sact[sig] = oldAct; - if (oact != NULL) { - *oact = oldAct; - } - - /* Record the signals used by jvm */ - jvmsigs |= MASK(sig); - - signal_unlock(); - return res; - } else { - /* jvm has no relation with this signal (yet). Install the - * the handler. */ - res = call_os_sigaction(sig, act, oact); - - signal_unlock(); - return res; - } -} - -/* The three functions for the jvm to call into */ -void JVM_begin_signal_setting() { - signal_lock(); - jvm_signal_installing = true; - tid = pthread_self(); - signal_unlock(); -} - -void JVM_end_signal_setting() { - signal_lock(); - jvm_signal_installed = true; - jvm_signal_installing = false; - pthread_cond_broadcast(&cond); - signal_unlock(); -} - -struct sigaction *JVM_get_signal_action(int sig) { - /* Does race condition make sense here? */ - if ((MASK(sig) & jvmsigs) != 0) { - return &sact[sig]; - } - return NULL; -} diff --git a/src/java.base/solaris/native/libjsig/jsig.c b/src/java.base/unix/native/libjsig/jsig.c similarity index 66% rename from src/java.base/solaris/native/libjsig/jsig.c rename to src/java.base/unix/native/libjsig/jsig.c index ea3b5ab46ab..1ea79a6a07b 100644 --- a/src/java.base/solaris/native/libjsig/jsig.c +++ b/src/java.base/unix/native/libjsig/jsig.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015 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 @@ -22,42 +23,56 @@ * */ -/* CopyrightVersion 1.2 */ - /* This is a special library that should be loaded before libc & * libthread to interpose the signal handler installation functions: * sigaction(), signal(), sigset(). * Used for signal-chaining. See RFE 4381843. */ -#include +#include +#include +#include +#include #include +#include #include -#include -#include -#include -#include -#include "jni.h" -#include "jvm_md.h" -#define bool int -#define true 1 -#define false 0 +#if (__STDC_VERSION__ >= 199901L) + #include +#else + #define bool int + #define true 1 + #define false 0 +#endif + +#ifdef SOLARIS +#define MAX_SIGNALS (SIGRTMAX+1) +/* On solaris, MAX_SIGNALS is a macro, not a constant, so we must allocate sact dynamically. */ static struct sigaction *sact = (struct sigaction *)NULL; /* saved signal handlers */ -static sigset_t jvmsigs; +#else +#define MAX_SIGNALS NSIG + +static struct sigaction sact[MAX_SIGNALS]; /* saved signal handlers */ +#endif -/* used to synchronize the installation of signal handlers */ -static mutex_t mutex = DEFAULTMUTEX; -static cond_t cond = DEFAULTCV; -static thread_t tid = 0; +static sigset_t jvmsigs; /* Signals used by jvm. */ + +#ifdef MACOSX +static __thread bool reentry = false; /* prevent reentry deadlock (per-thread) */ +#endif + +/* Used to synchronize the installation of signal handlers. */ +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +static pthread_t tid = 0; typedef void (*sa_handler_t)(int); typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); -typedef sa_handler_t (*signal_t)(int, sa_handler_t); +typedef sa_handler_t (*signal_function_t)(int, sa_handler_t); typedef int (*sigaction_t)(int, const struct sigaction *, struct sigaction *); -static signal_t os_signal = 0; /* os's version of signal()/sigset() */ +static signal_function_t os_signal = 0; /* os's version of signal()/sigset() */ static sigaction_t os_sigaction = 0; /* os's version of sigaction() */ static bool jvm_signal_installing = false; @@ -66,65 +81,79 @@ static bool jvm_signal_installed = false; /* assume called within signal_lock */ static void allocate_sact() { - size_t maxsignum; - maxsignum = SIGRTMAX; +#ifdef SOLARIS if (sact == NULL) { - sact = (struct sigaction *)malloc((maxsignum+1) * (size_t)sizeof(struct sigaction)); - memset(sact, 0, (maxsignum+1) * (size_t)sizeof(struct sigaction)); - } - - if (sact == NULL) { - printf("%s\n", "libjsig.so unable to allocate memory"); - exit(0); + sact = (struct sigaction *)malloc((MAX_SIGNALS) * (size_t)sizeof(struct sigaction)); + if (sact == NULL) { + printf("%s\n", "libjsig.so unable to allocate memory"); + exit(0); + } + memset(sact, 0, (MAX_SIGNALS) * (size_t)sizeof(struct sigaction)); } - - sigemptyset(&jvmsigs); +#endif } static void signal_lock() { - mutex_lock(&mutex); + pthread_mutex_lock(&mutex); /* When the jvm is installing its set of signal handlers, threads - * other than the jvm thread should wait */ + * other than the jvm thread should wait. */ if (jvm_signal_installing) { - if (tid != thr_self()) { - cond_wait(&cond, &mutex); + if (tid != pthread_self()) { + pthread_cond_wait(&cond, &mutex); } } } static void signal_unlock() { - mutex_unlock(&mutex); + pthread_mutex_unlock(&mutex); } static sa_handler_t call_os_signal(int sig, sa_handler_t disp, bool is_sigset) { + sa_handler_t res; + if (os_signal == NULL) { if (!is_sigset) { - os_signal = (signal_t)dlsym(RTLD_NEXT, "signal"); + os_signal = (signal_function_t)dlsym(RTLD_NEXT, "signal"); } else { - os_signal = (signal_t)dlsym(RTLD_NEXT, "sigset"); + os_signal = (signal_function_t)dlsym(RTLD_NEXT, "sigset"); } if (os_signal == NULL) { printf("%s\n", dlerror()); exit(0); } } - return (*os_signal)(sig, disp); + +#ifdef MACOSX + /* On macosx, the OS implementation of signal calls sigaction. + * Make sure we do not deadlock with ourself. (See JDK-8072147). */ + reentry = true; +#endif + + res = (*os_signal)(sig, disp); + +#ifdef MACOSX + reentry = false; +#endif + + return res; } static void save_signal_handler(int sig, sa_handler_t disp, bool is_sigset) { sigset_t set; - if (sact == NULL) { - allocate_sact(); - } + sact[sig].sa_handler = disp; sigemptyset(&set); sact[sig].sa_mask = set; if (!is_sigset) { +#ifdef SOLARIS sact[sig].sa_flags = SA_NODEFER; if (sig != SIGILL && sig != SIGTRAP && sig != SIGPWR) { sact[sig].sa_flags |= SA_RESETHAND; } +#else + sact[sig].sa_flags = 0; +#endif } else { sact[sig].sa_flags = 0; } @@ -132,26 +161,28 @@ static void save_signal_handler(int sig, sa_handler_t disp, bool is_sigset) { static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) { sa_handler_t oldhandler; + bool sigused; bool sigblocked; signal_lock(); - if (sact == NULL) { - allocate_sact(); - } + allocate_sact(); - if (jvm_signal_installed && sigismember(&jvmsigs, sig)) { + sigused = sigismember(&jvmsigs, sig); + if (jvm_signal_installed && sigused) { /* jvm has installed its signal handler for this signal. */ /* Save the handler. Don't really install it. */ if (is_sigset) { - /* We won't honor the SIG_HOLD request to change the signal mask */ sigblocked = sigismember(&(sact[sig].sa_mask), sig); } oldhandler = sact[sig].sa_handler; save_signal_handler(sig, disp, is_sigset); +#ifdef SOLARIS if (is_sigset && sigblocked) { + /* We won't honor the SIG_HOLD request to change the signal mask */ oldhandler = SIG_HOLD; } +#endif signal_unlock(); return oldhandler; @@ -178,11 +209,26 @@ static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) { } sa_handler_t signal(int sig, sa_handler_t disp) { + if (sig < 0 || sig >= MAX_SIGNALS) { + errno = EINVAL; + return SIG_ERR; + } + return set_signal(sig, disp, false); } sa_handler_t sigset(int sig, sa_handler_t disp) { +#ifdef _ALLBSD_SOURCE + printf("sigset() is not supported by BSD"); + exit(0); +#else + if (sig < 0 || sig >= MAX_SIGNALS) { + errno = EINVAL; + return (sa_handler_t)-1; + } + return set_signal(sig, disp, true); +#endif } static int call_os_sigaction(int sig, const struct sigaction *act, @@ -199,14 +245,25 @@ static int call_os_sigaction(int sig, const struct sigaction *act, int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { int res; + bool sigused; struct sigaction oldAct; - signal_lock(); + if (sig < 0 || sig >= MAX_SIGNALS) { + errno = EINVAL; + return -1; + } - if (sact == NULL ) { - allocate_sact(); +#ifdef MACOSX + if (reentry) { + return call_os_sigaction(sig, act, oact); } - if (jvm_signal_installed && sigismember(&jvmsigs, sig)) { +#endif + + signal_lock(); + + allocate_sact(); + sigused = sigismember(&jvmsigs, sig); + if (jvm_signal_installed && sigused) { /* jvm has installed its signal handler for this signal. */ /* Save the handler. Don't really install it. */ if (oact != NULL) { @@ -227,7 +284,7 @@ int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { *oact = oldAct; } - /* Record the signals used by jvm */ + /* Record the signals used by jvm. */ sigaddset(&jvmsigs, sig); signal_unlock(); @@ -242,37 +299,28 @@ int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { } } -/* The four functions for the jvm to call into */ -JNIEXPORT void JNICALL -JVM_begin_signal_setting() { +/* The three functions for the jvm to call into. */ +void JVM_begin_signal_setting() { signal_lock(); + sigemptyset(&jvmsigs); jvm_signal_installing = true; - tid = thr_self(); + tid = pthread_self(); signal_unlock(); } -JNIEXPORT void JNICALL -JVM_end_signal_setting() { +void JVM_end_signal_setting() { signal_lock(); jvm_signal_installed = true; jvm_signal_installing = false; - cond_broadcast(&cond); + pthread_cond_broadcast(&cond); signal_unlock(); } -JNIEXPORT struct sigaction * JNICALL -JVM_get_signal_action(int sig) { - if (sact == NULL) { - allocate_sact(); - } +struct sigaction *JVM_get_signal_action(int sig) { + allocate_sact(); /* Does race condition make sense here? */ if (sigismember(&jvmsigs, sig)) { return &sact[sig]; } return NULL; } - -JNIEXPORT int JNICALL -JVM_get_libjsig_version() { - return JSIG_VERSION_1_4_1; -} From 8f5a3260329c6cf3d5fc6513340c658048180ec3 Mon Sep 17 00:00:00 2001 From: dl Date: Tue, 10 Apr 2018 11:25:46 -0700 Subject: [PATCH 120/196] 8200728: Docs (Comparison of Stack and Deque methods) for Deque is not correct Reviewed-by: martin, psandoz --- src/java.base/share/classes/java/util/Deque.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/java/util/Deque.java b/src/java.base/share/classes/java/util/Deque.java index 5147a4951c7..b5532a2b60d 100644 --- a/src/java.base/share/classes/java/util/Deque.java +++ b/src/java.base/share/classes/java/util/Deque.java @@ -141,8 +141,8 @@ *

      Deques can also be used as LIFO (Last-In-First-Out) stacks. This * interface should be used in preference to the legacy {@link Stack} class. * When a deque is used as a stack, elements are pushed and popped from the - * beginning of the deque. Stack methods are precisely equivalent to - * {@code Deque} methods as indicated in the table below: + * beginning of the deque. Stack methods are equivalent to {@code Deque} + * methods as indicated in the table below: * *

      None testpkgmdlBNoneAll Modules
      * @@ -163,7 +163,7 @@ * * * - * + * * * *
      Comparison of Stack and Deque methods
      {@link #peek() peek()}{@link #peekFirst() peekFirst()}{@link #getFirst() getFirst()}
      From 04b05d1692d81ff29484d1c66c07252f4b1e635d Mon Sep 17 00:00:00 2001 From: dl Date: Tue, 10 Apr 2018 11:29:37 -0700 Subject: [PATCH 121/196] 8200520: forkjoin tasks interrupted after shutdown Reviewed-by: martin, psandoz, chegar, dholmes --- .../java/util/concurrent/ForkJoinPool.java | 1216 ++++++++--------- 1 file changed, 581 insertions(+), 635 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java index 3d3b105ba06..d1f5e567190 100644 --- a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java +++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java @@ -184,17 +184,22 @@ public class ForkJoinPool extends AbstractExecutorService { * functionality and control for a set of worker threads: * Submissions from non-FJ threads enter into submission queues. * Workers take these tasks and typically split them into subtasks - * that may be stolen by other workers. Preference rules give - * first priority to processing tasks from their own queues (LIFO - * or FIFO, depending on mode), then to randomized FIFO steals of - * tasks in other queues. This framework began as vehicle for - * supporting tree-structured parallelism using work-stealing. - * Over time, its scalability advantages led to extensions and - * changes to better support more diverse usage contexts. Because - * most internal methods and nested classes are interrelated, - * their main rationale and descriptions are presented here; - * individual methods and nested classes contain only brief - * comments about details. + * that may be stolen by other workers. Work-stealing based on + * randomized scans generally leads to better throughput than + * "work dealing" in which producers assign tasks to idle threads, + * in part because threads that have finished other tasks before + * the signalled thread wakes up (which can be a long time) can + * take the task instead. Preference rules give first priority to + * processing tasks from their own queues (LIFO or FIFO, depending + * on mode), then to randomized FIFO steals of tasks in other + * queues. This framework began as vehicle for supporting + * tree-structured parallelism using work-stealing. Over time, + * its scalability advantages led to extensions and changes to + * better support more diverse usage contexts. Because most + * internal methods and nested classes are interrelated, their + * main rationale and descriptions are presented here; individual + * methods and nested classes contain only brief comments about + * details. * * WorkQueues * ========== @@ -227,9 +232,10 @@ public class ForkJoinPool extends AbstractExecutorService { * * (The actual code needs to null-check and size-check the array, * uses masking, not mod, for indexing a power-of-two-sized array, - * properly fences accesses, and possibly signals waiting workers - * to start scanning -- see below.) Both a successful pop and - * poll mainly entail a CAS of a slot from non-null to null. + * adds a release fence for publication, and possibly signals + * waiting workers to start scanning -- see below.) Both a + * successful pop and poll mainly entail a CAS of a slot from + * non-null to null. * * The pop operation (always performed by owner) is: * if ((the task at top slot is not null) and @@ -241,9 +247,14 @@ public class ForkJoinPool extends AbstractExecutorService { * (CAS slot to null)) * increment base and return task; * - * There are several variants of each of these. In particular, - * almost all uses of poll occur within scan operations that also - * interleave contention tracking (with associated code sprawl.) + * There are several variants of each of these. Most uses occur + * within operations that also interleave contention or emptiness + * tracking or inspection of elements before extracting them, so + * must interleave these with the above code. When performed by + * owner, getAndSet is used instead of CAS (see for example method + * nextLocalTask) which is usually more efficient, and possible + * because the top index cannot independently change during the + * operation. * * Memory ordering. See "Correct and Efficient Work-Stealing for * Weak Memory Models" by Le, Pop, Cohen, and Nardelli, PPoPP 2013 @@ -252,30 +263,37 @@ public class ForkJoinPool extends AbstractExecutorService { * algorithms similar to (but different than) the one used here. * Extracting tasks in array slots via (fully fenced) CAS provides * primary synchronization. The base and top indices imprecisely - * guide where to extract from. We do not always require strict - * orderings of array and index updates, so sometimes let them be - * subject to compiler and processor reorderings. However, the - * volatile "base" index also serves as a basis for memory - * ordering: Slot accesses are preceded by a read of base, - * ensuring happens-before ordering with respect to stealers (so - * the slots themselves can be read via plain array reads.) The - * only other memory orderings relied on are maintained in the - * course of signalling and activation (see below). A check that - * base == top indicates (momentary) emptiness, but otherwise may - * err on the side of possibly making the queue appear nonempty - * when a push, pop, or poll have not fully committed, or making - * it appear empty when an update of top has not yet been visibly - * written. (Method isEmpty() checks the case of a partially - * completed removal of the last element.) Because of this, the - * poll operation, considered individually, is not wait-free. One - * thief cannot successfully continue until another in-progress - * one (or, if previously empty, a push) visibly completes. - * However, in the aggregate, we ensure at least probabilistic + * guide where to extract from. We do not usually require strict + * orderings of array and index updates. Many index accesses use + * plain mode, with ordering constrained by surrounding context + * (usually with respect to element CASes or the two WorkQueue + * volatile fields source and phase). When not otherwise already + * constrained, reads of "base" by queue owners use acquire-mode, + * and some externally callable methods preface accesses with + * acquire fences. Additionally, to ensure that index update + * writes are not coalesced or postponed in loops etc, "opaque" + * mode is used in a few cases where timely writes are not + * otherwise ensured. The "locked" versions of push- and pop- + * based methods for shared queues differ from owned versions + * because locking already forces some of the ordering. + * + * Because indices and slot contents cannot always be consistent, + * a check that base == top indicates (momentary) emptiness, but + * otherwise may err on the side of possibly making the queue + * appear nonempty when a push, pop, or poll have not fully + * committed, or making it appear empty when an update of top has + * not yet been visibly written. (Method isEmpty() checks the + * case of a partially completed removal of the last element.) + * Because of this, the poll operation, considered individually, + * is not wait-free. One thief cannot successfully continue until + * another in-progress one (or, if previously empty, a push) + * visibly completes. This can stall threads when required to + * consume from a given queue (see method poll()). However, in + * the aggregate, we ensure at least probabilistic * non-blockingness. If an attempted steal fails, a scanning * thief chooses a different random victim target to try next. So, * in order for one thief to progress, it suffices for any - * in-progress poll or new push on any empty queue to - * complete. + * in-progress poll or new push on any empty queue to complete. * * This approach also enables support of a user mode in which * local task processing is in FIFO, not LIFO order, simply by @@ -296,7 +314,7 @@ public class ForkJoinPool extends AbstractExecutorService { * different position to use or create other queues -- they block * only when creating and registering new queues. Because it is * used only as a spinlock, unlocking requires only a "releasing" - * store (using setRelease). + * store (using setRelease) unless otherwise signalling. * * Management * ========== @@ -317,10 +335,10 @@ public class ForkJoinPool extends AbstractExecutorService { * * Field "ctl" contains 64 bits holding information needed to * atomically decide to add, enqueue (on an event queue), and - * dequeue (and release)-activate workers. To enable this - * packing, we restrict maximum parallelism to (1<<15)-1 (which is - * far in excess of normal operating range) to allow ids, counts, - * and their negations (used for thresholding) to fit into 16bit + * dequeue and release workers. To enable this packing, we + * restrict maximum parallelism to (1<<15)-1 (which is far in + * excess of normal operating range) to allow ids, counts, and + * their negations (used for thresholding) to fit into 16bit * subfields. * * Field "mode" holds configuration parameters as well as lifetime @@ -332,13 +350,14 @@ public class ForkJoinPool extends AbstractExecutorService { * lock (using field workerNamePrefix as lock), but is otherwise * concurrently readable, and accessed directly. We also ensure * that uses of the array reference itself never become too stale - * in case of resizing. To simplify index-based operations, the - * array size is always a power of two, and all readers must - * tolerate null slots. Worker queues are at odd indices. Shared - * (submission) queues are at even indices, up to a maximum of 64 - * slots, to limit growth even if array needs to expand to add - * more workers. Grouping them together in this way simplifies and - * speeds up task scanning. + * in case of resizing, by arranging that (re-)reads are separated + * by at least one acquiring read access. To simplify index-based + * operations, the array size is always a power of two, and all + * readers must tolerate null slots. Worker queues are at odd + * indices. Shared (submission) queues are at even indices, up to + * a maximum of 64 slots, to limit growth even if the array needs + * to expand to add more workers. Grouping them together in this + * way simplifies and speeds up task scanning. * * All worker thread creation is on-demand, triggered by task * submissions, replacement of terminated workers, and/or @@ -416,8 +435,8 @@ public class ForkJoinPool extends AbstractExecutorService { * releases so usage requires care -- seeing a negative phase does * not guarantee that the worker is available. When queued, the * lower 16 bits of scanState must hold its pool index. So we - * place the index there upon initialization (see registerWorker) - * and otherwise keep it there or restore it when necessary. + * place the index there upon initialization and otherwise keep it + * there or restore it when necessary. * * The ctl field also serves as the basis for memory * synchronization surrounding activation. This uses a more @@ -425,48 +444,56 @@ public class ForkJoinPool extends AbstractExecutorService { * consumers sync with each other by both writing/CASing ctl (even * if to its current value). This would be extremely costly. So * we relax it in several ways: (1) Producers only signal when - * their queue is empty. Other workers propagate this signal (in - * method scan) when they find tasks; to further reduce flailing, - * each worker signals only one other per activation. (2) Workers - * only enqueue after scanning (see below) and not finding any - * tasks. (3) Rather than CASing ctl to its current value in the - * common case where no action is required, we reduce write + * their queue is possibly empty at some point during a push + * operation (which requires conservatively checking size zero or + * one to cover races). (2) Other workers propagate this signal + * when they find tasks in a queue with size greater than one. (3) + * Workers only enqueue after scanning (see below) and not finding + * any tasks. (4) Rather than CASing ctl to its current value in + * the common case where no action is required, we reduce write * contention by equivalently prefacing signalWork when called by * an external task producer using a memory access with * full-volatile semantics or a "fullFence". * - * Almost always, too many signals are issued. A task producer - * cannot in general tell if some existing worker is in the midst - * of finishing one task (or already scanning) and ready to take - * another without being signalled. So the producer might instead - * activate a different worker that does not find any work, and - * then inactivates. This scarcely matters in steady-state - * computations involving all workers, but can create contention - * and bookkeeping bottlenecks during ramp-up, ramp-down, and small - * computations involving only a few workers. - * - * Scanning. Method runWorker performs top-level scanning for - * tasks. Each scan traverses and tries to poll from each queue - * starting at a random index and circularly stepping. Scans are - * not performed in ideal random permutation order, to reduce - * cacheline contention. The pseudorandom generator need not have + * Almost always, too many signals are issued, in part because a + * task producer cannot tell if some existing worker is in the + * midst of finishing one task (or already scanning) and ready to + * take another without being signalled. So the producer might + * instead activate a different worker that does not find any + * work, and then inactivates. This scarcely matters in + * steady-state computations involving all workers, but can create + * contention and bookkeeping bottlenecks during ramp-up, + * ramp-down, and small computations involving only a few workers. + * + * Scanning. Method scan (from runWorker) performs top-level + * scanning for tasks. (Similar scans appear in helpQuiesce and + * pollScan.) Each scan traverses and tries to poll from each + * queue starting at a random index. Scans are not performed in + * ideal random permutation order, to reduce cacheline + * contention. The pseudorandom generator need not have * high-quality statistical properties in the long term, but just * within computations; We use Marsaglia XorShifts (often via * ThreadLocalRandom.nextSecondarySeed), which are cheap and - * suffice. Scanning also employs contention reduction: When + * suffice. Scanning also includes contention reduction: When * scanning workers fail to extract an apparently existing task, - * they soon restart at a different pseudorandom index. This - * improves throughput when many threads are trying to take tasks - * from few queues, which can be common in some usages. Scans do - * not otherwise explicitly take into account core affinities, - * loads, cache localities, etc, However, they do exploit temporal - * locality (which usually approximates these) by preferring to - * re-poll (at most #workers times) from the same queue after a - * successful poll before trying others. + * they soon restart at a different pseudorandom index. This form + * of backoff improves throughput when many threads are trying to + * take tasks from few queues, which can be common in some usages. + * Scans do not otherwise explicitly take into account core + * affinities, loads, cache localities, etc, However, they do + * exploit temporal locality (which usually approximates these) by + * preferring to re-poll from the same queue after a successful + * poll before trying others (see method topLevelExec). However + * this preference is bounded (see TOP_BOUND_SHIFT) as a safeguard + * against infinitely unfair looping under unbounded user task + * recursion, and also to reduce long-term contention when many + * threads poll few queues holding many small tasks. The bound is + * high enough to avoid much impact on locality and scheduling + * overhead. * * Trimming workers. To release resources after periods of lack of * use, a worker starting to wait when the pool is quiescent will - * time out and terminate (see method scan) if the pool has + * time out and terminate (see method runWorker) if the pool has * remained quiescent for period given by field keepAlive. * * Shutdown and Termination. A call to shutdownNow invokes @@ -534,13 +561,14 @@ public class ForkJoinPool extends AbstractExecutorService { * time. Some previous versions of this class employed immediate * compensations for any blocked join. However, in practice, the * vast majority of blockages are transient byproducts of GC and - * other JVM or OS activities that are made worse by replacement. - * Rather than impose arbitrary policies, we allow users to - * override the default of only adding threads upon apparent - * starvation. The compensation mechanism may also be bounded. - * Bounds for the commonPool (see COMMON_MAX_SPARES) better enable - * JVMs to cope with programming errors and abuse before running - * out of resources to do so. + * other JVM or OS activities that are made worse by replacement + * when they cause longer-term oversubscription. Rather than + * impose arbitrary policies, we allow users to override the + * default of only adding threads upon apparent starvation. The + * compensation mechanism may also be bounded. Bounds for the + * commonPool (see COMMON_MAX_SPARES) better enable JVMs to cope + * with programming errors and abuse before running out of + * resources to do so. * * Common Pool * =========== @@ -573,6 +601,18 @@ public class ForkJoinPool extends AbstractExecutorService { * in ForkJoinWorkerThread) may be JVM-dependent and must access * particular Thread class fields to achieve this effect. * + * Memory placement + * ================ + * + * Performance can be very sensitive to placement of instances of + * ForkJoinPool and WorkQueues and their queue arrays. To reduce + * false-sharing impact, the @Contended annotation isolates + * adjacent WorkQueue instances, as well as the ForkJoinPool.ctl + * field. WorkQueue arrays are allocated (by their threads) with + * larger initial sizes than most ever need, mostly to reduce + * false sharing with current garbage collectors that use cardmark + * tables. + * * Style notes * =========== * @@ -580,13 +620,15 @@ public class ForkJoinPool extends AbstractExecutorService { * awkward and ugly, but also reflects the need to control * outcomes across the unusual cases that arise in very racy code * with very few invariants. All fields are read into locals - * before use, and null-checked if they are references. This is - * usually done in a "C"-like style of listing declarations at the - * heads of methods or blocks, and using inline assignments on - * first encounter. Nearly all explicit checks lead to - * bypass/return, not exception throws, because they may - * legitimately arise due to cancellation/revocation during - * shutdown. + * before use, and null-checked if they are references. Array + * accesses using masked indices include checks (that are always + * true) that the array length is non-zero to avoid compilers + * inserting more expensive traps. This is usually done in a + * "C"-like style of listing declarations at the heads of methods + * or blocks, and using inline assignments on first encounter. + * Nearly all explicit checks lead to bypass/return, not exception + * throws, because they may legitimately arise due to + * cancellation/revocation during shutdown. * * There is a lot of representation-level coupling among classes * ForkJoinPool, ForkJoinWorkerThread, and ForkJoinTask. The @@ -596,10 +638,11 @@ public class ForkJoinPool extends AbstractExecutorService { * representations will need to be accompanied by algorithmic * changes anyway. Several methods intrinsically sprawl because * they must accumulate sets of consistent reads of fields held in - * local variables. There are also other coding oddities - * (including several unnecessary-looking hoisted null checks) - * that help some methods perform reasonably even when interpreted - * (not compiled). + * local variables. Some others are artificially broken up to + * reduce producer/consumer imbalances due to dynamic compilation. + * There are also other coding oddities (including several + * unnecessary-looking hoisted null checks) that help some methods + * perform reasonably even when interpreted (not compiled). * * The order of declarations in this file is (with a few exceptions): * (1) Static utility functions @@ -703,54 +746,43 @@ public ForkJoinWorkerThread run() { static final int DORMANT = QUIET | UNSIGNALLED; /** - * The maximum number of local polls from the same queue before - * checking others. This is a safeguard against infinitely unfair - * looping under unbounded user task recursion, and must be larger - * than plausible cases of intentional bounded task recursion. + * Initial capacity of work-stealing queue array. + * Must be a power of two, at least 2. + */ + static final int INITIAL_QUEUE_CAPACITY = 1 << 13; + + /** + * Maximum capacity for queue arrays. Must be a power of two less + * than or equal to 1 << (31 - width of array entry) to ensure + * lack of wraparound of index calculations, but defined to a + * value a bit less than this to help users trap runaway programs + * before saturating systems. + */ + static final int MAXIMUM_QUEUE_CAPACITY = 1 << 26; // 64M + + /** + * The maximum number of top-level polls per worker before + * checking other queues, expressed as a bit shift to, in effect, + * multiply by pool size, and then use as random value mask, so + * average bound is about poolSize*(1<[] array; // the elements (initially unallocated) + ForkJoinTask[] array; // the queued tasks; power of 2 size final ForkJoinPool pool; // the containing pool (may be null) final ForkJoinWorkerThread owner; // owning thread or null if shared @@ -761,6 +793,17 @@ static final class WorkQueue { base = top = INITIAL_QUEUE_CAPACITY >>> 1; } + /** + * Tries to lock shared queue by CASing phase field. + */ + final boolean tryLockPhase() { + return PHASE.compareAndSet(this, 0, 1); + } + + final void releasePhaseLock() { + PHASE.setRelease(this, 0); + } + /** * Returns an exportable index (used by ForkJoinWorkerThread). */ @@ -772,7 +815,7 @@ final int getPoolIndex() { * Returns the approximate number of tasks in the queue. */ final int queueSize() { - int n = base - top; // read base first + int n = (int)BASE.getAcquire(this) - top; return (n >= 0) ? 0 : -n; // ignore transient negative } @@ -782,14 +825,14 @@ final int queueSize() { * near-empty queue has at least one unclaimed task. */ final boolean isEmpty() { - ForkJoinTask[] a; int n, al, b; + ForkJoinTask[] a; int n, cap, b; + VarHandle.acquireFence(); // needed by external callers return ((n = (b = base) - top) >= 0 || // possibly one task (n == -1 && ((a = array) == null || - (al = a.length) == 0 || - a[(al - 1) & b] == null))); + (cap = a.length) == 0 || + a[(cap - 1) & b] == null))); } - /** * Pushes a task. Call only by owner in unshared queues. * @@ -797,94 +840,99 @@ final boolean isEmpty() { * @throws RejectedExecutionException if array cannot be resized */ final void push(ForkJoinTask task) { - int s = top; ForkJoinTask[] a; int al, d; - if ((a = array) != null && (al = a.length) > 0) { - int index = (al - 1) & s; - ForkJoinPool p = pool; + ForkJoinTask[] a; + int s = top, d, cap, m; + ForkJoinPool p = pool; + if ((a = array) != null && (cap = a.length) > 0) { + QA.setRelease(a, (m = cap - 1) & s, task); top = s + 1; - QA.setRelease(a, index, task); - if ((d = base - s) == 0 && p != null) { + if (((d = s - (int)BASE.getAcquire(this)) & ~1) == 0 && + p != null) { // size 0 or 1 VarHandle.fullFence(); p.signalWork(); } - else if (d + al == 1) - growArray(); + else if (d == m) + growArray(false); } } /** - * Initializes or doubles the capacity of array. Call either - * by owner or with lock held -- it is OK for base, but not - * top, to move while resizings are in progress. + * Version of push for shared queues. Call only with phase lock held. + * @return true if should signal work */ - final ForkJoinTask[] growArray() { - ForkJoinTask[] oldA = array; - int oldSize = oldA != null ? oldA.length : 0; - int size = oldSize > 0 ? oldSize << 1 : INITIAL_QUEUE_CAPACITY; - if (size < INITIAL_QUEUE_CAPACITY || size > MAXIMUM_QUEUE_CAPACITY) - throw new RejectedExecutionException("Queue capacity exceeded"); - int oldMask, t, b; - ForkJoinTask[] a = array = new ForkJoinTask[size]; - if (oldA != null && (oldMask = oldSize - 1) > 0 && - (t = top) - (b = base) > 0) { - int mask = size - 1; - do { // emulate poll from old array, push to new array - int index = b & oldMask; - ForkJoinTask x = (ForkJoinTask) - QA.getAcquire(oldA, index); - if (x != null && - QA.compareAndSet(oldA, index, x, null)) - a[b & mask] = x; - } while (++b != t); - VarHandle.releaseFence(); + final boolean lockedPush(ForkJoinTask task) { + ForkJoinTask[] a; + boolean signal = false; + int s = top, b = base, cap, d; + if ((a = array) != null && (cap = a.length) > 0) { + a[(cap - 1) & s] = task; + top = s + 1; + if (b - s + cap - 1 == 0) + growArray(true); + else { + phase = 0; // full volatile unlock + if (((s - base) & ~1) == 0) // size 0 or 1 + signal = true; + } } - return a; + return signal; } /** - * Takes next task, if one exists, in LIFO order. Call only - * by owner in unshared queues. + * Doubles the capacity of array. Call either by owner or with + * lock held -- it is OK for base, but not top, to move while + * resizings are in progress. */ - final ForkJoinTask pop() { - int b = base, s = top, al, i; ForkJoinTask[] a; - if ((a = array) != null && b != s && (al = a.length) > 0) { - int index = (al - 1) & --s; - ForkJoinTask t = (ForkJoinTask) - QA.get(a, index); - if (t != null && - QA.compareAndSet(a, index, t, null)) { - top = s; - VarHandle.releaseFence(); - return t; + final void growArray(boolean locked) { + ForkJoinTask[] newA = null; + try { + ForkJoinTask[] oldA; int oldSize, newSize; + if ((oldA = array) != null && (oldSize = oldA.length) > 0 && + (newSize = oldSize << 1) <= MAXIMUM_QUEUE_CAPACITY && + newSize > 0) { + try { + newA = new ForkJoinTask[newSize]; + } catch (OutOfMemoryError ex) { + } + if (newA != null) { // poll from old array, push to new + int oldMask = oldSize - 1, newMask = newSize - 1; + for (int s = top - 1, k = oldMask; k >= 0; --k) { + ForkJoinTask x = (ForkJoinTask) + QA.getAndSet(oldA, s & oldMask, null); + if (x != null) + newA[s-- & newMask] = x; + else + break; + } + array = newA; + VarHandle.releaseFence(); + } } + } finally { + if (locked) + phase = 0; } - return null; + if (newA == null) + throw new RejectedExecutionException("Queue capacity exceeded"); } /** * Takes next task, if one exists, in FIFO order. */ final ForkJoinTask poll() { - for (;;) { - int b = base, s = top, d, al; ForkJoinTask[] a; - if ((a = array) != null && (d = b - s) < 0 && - (al = a.length) > 0) { - int index = (al - 1) & b; - ForkJoinTask t = (ForkJoinTask) - QA.getAcquire(a, index); - if (b++ == base) { - if (t != null) { - if (QA.compareAndSet(a, index, t, null)) { - base = b; - return t; - } - } - else if (d == -1) - break; // now empty + int b, k, cap; ForkJoinTask[] a; + while ((a = array) != null && (cap = a.length) > 0 && + top - (b = base) > 0) { + ForkJoinTask t = (ForkJoinTask) + QA.getAcquire(a, k = (cap - 1) & b); + if (base == b++) { + if (t == null) + Thread.yield(); // await index advance + else if (QA.compareAndSet(a, k, t, null)) { + BASE.setOpaque(this, b); + return t; } } - else - break; } return null; } @@ -893,33 +941,61 @@ else if (d == -1) * Takes next task, if one exists, in order specified by mode. */ final ForkJoinTask nextLocalTask() { - return ((id & FIFO) != 0) ? poll() : pop(); + ForkJoinTask t = null; + int md = id, b, s, d, cap; ForkJoinTask[] a; + if ((a = array) != null && (cap = a.length) > 0 && + (d = (s = top) - (b = base)) > 0) { + if ((md & FIFO) == 0 || d == 1) { + if ((t = (ForkJoinTask) + QA.getAndSet(a, (cap - 1) & --s, null)) != null) + TOP.setOpaque(this, s); + } + else if ((t = (ForkJoinTask) + QA.getAndSet(a, (cap - 1) & b++, null)) != null) { + BASE.setOpaque(this, b); + } + else // on contention in FIFO mode, use regular poll + t = poll(); + } + return t; } /** * Returns next task, if one exists, in order specified by mode. */ final ForkJoinTask peek() { - int al; ForkJoinTask[] a; - return ((a = array) != null && (al = a.length) > 0) ? - a[(al - 1) & - ((id & FIFO) != 0 ? base : top - 1)] : null; + int cap; ForkJoinTask[] a; + return ((a = array) != null && (cap = a.length) > 0) ? + a[(cap - 1) & ((id & FIFO) != 0 ? base : top - 1)] : null; } /** * Pops the given task only if it is at the current top. */ final boolean tryUnpush(ForkJoinTask task) { - int b = base, s = top, al; ForkJoinTask[] a; - if ((a = array) != null && b != s && (al = a.length) > 0) { - int index = (al - 1) & --s; - if (QA.compareAndSet(a, index, task, null)) { + boolean popped = false; + int s, cap; ForkJoinTask[] a; + if ((a = array) != null && (cap = a.length) > 0 && + (s = top) != base && + (popped = QA.compareAndSet(a, (cap - 1) & --s, task, null))) + TOP.setOpaque(this, s); + return popped; + } + + /** + * Shared version of tryUnpush. + */ + final boolean tryLockedUnpush(ForkJoinTask task) { + boolean popped = false; + int s = top - 1, k, cap; ForkJoinTask[] a; + if ((a = array) != null && (cap = a.length) > 0 && + a[k = (cap - 1) & s] == task && tryLockPhase()) { + if (top == s + 1 && array == a && + (popped = QA.compareAndSet(a, k, task, null))) top = s; - VarHandle.releaseFence(); - return true; - } + releasePhaseLock(); } - return false; + return popped; } /** @@ -933,58 +1009,29 @@ final void cancelAll() { // Specialized execution methods /** - * Pops and executes up to limit consecutive tasks or until empty. - * - * @param limit max runs, or zero for no limit + * Runs the given (stolen) task if nonnull, as well as + * remaining local tasks and others available from the given + * queue, up to bound n (to avoid infinite unfairness). */ - final void localPopAndExec(int limit) { - for (;;) { - int b = base, s = top, al; ForkJoinTask[] a; - if ((a = array) != null && b != s && (al = a.length) > 0) { - int index = (al - 1) & --s; - ForkJoinTask t = (ForkJoinTask) - QA.getAndSet(a, index, null); - if (t != null) { - top = s; - VarHandle.releaseFence(); - t.doExec(); - if (limit != 0 && --limit == 0) - break; - } - else + final void topLevelExec(ForkJoinTask t, WorkQueue q, int n) { + if (t != null && q != null) { // hoist checks + int nstolen = 1; + for (;;) { + t.doExec(); + if (n-- < 0) break; - } - else - break; - } - } - - /** - * Polls and executes up to limit consecutive tasks or until empty. - * - * @param limit, or zero for no limit - */ - final void localPollAndExec(int limit) { - for (int polls = 0;;) { - int b = base, s = top, d, al; ForkJoinTask[] a; - if ((a = array) != null && (d = b - s) < 0 && - (al = a.length) > 0) { - int index = (al - 1) & b++; - ForkJoinTask t = (ForkJoinTask) - QA.getAndSet(a, index, null); - if (t != null) { - base = b; - t.doExec(); - if (limit != 0 && ++polls == limit) + else if ((t = nextLocalTask()) == null) { + if ((t = q.poll()) == null) break; + else + ++nstolen; } - else if (d == -1) - break; // now empty - else - polls = 0; // stolen; reset } - else - break; + ForkJoinWorkerThread thread = owner; + nsteals += nstolen; + source = 0; + if (thread != null) + thread.afterTopLevelExec(); } } @@ -992,25 +1039,24 @@ else if (d == -1) * If present, removes task from queue and executes it. */ final void tryRemoveAndExec(ForkJoinTask task) { - ForkJoinTask[] wa; int s, wal; - if (base - (s = top) < 0 && // traverse from top - (wa = array) != null && (wal = wa.length) > 0) { - for (int m = wal - 1, ns = s - 1, i = ns; ; --i) { + ForkJoinTask[] a; int s, cap; + if ((a = array) != null && (cap = a.length) > 0 && + (s = top) - base > 0) { // traverse from top + for (int m = cap - 1, ns = s - 1, i = ns; ; --i) { int index = i & m; - ForkJoinTask t = (ForkJoinTask) - QA.get(wa, index); + ForkJoinTask t = (ForkJoinTask)QA.get(a, index); if (t == null) break; else if (t == task) { - if (QA.compareAndSet(wa, index, t, null)) { + if (QA.compareAndSet(a, index, t, null)) { top = ns; // safely shift down for (int j = i; j != ns; ++j) { ForkJoinTask f; int pindex = (j + 1) & m; - f = (ForkJoinTask)QA.get(wa, pindex); - QA.setVolatile(wa, pindex, null); + f = (ForkJoinTask)QA.get(a, pindex); + QA.setVolatile(a, pindex, null); int jindex = j & m; - QA.setRelease(wa, jindex, f); + QA.setRelease(a, jindex, f); } VarHandle.releaseFence(); t.doExec(); @@ -1022,43 +1068,52 @@ else if (t == task) { } /** - * Tries to steal and run tasks within the target's - * computation until done, not found, or limit exceeded. + * Tries to pop and run tasks within the target's computation + * until done, not found, or limit exceeded. * * @param task root of CountedCompleter computation * @param limit max runs, or zero for no limit + * @param shared true if must lock to extract task * @return task status on exit */ - final int localHelpCC(CountedCompleter task, int limit) { + final int helpCC(CountedCompleter task, int limit, boolean shared) { int status = 0; if (task != null && (status = task.status) >= 0) { - for (;;) { - boolean help = false; - int b = base, s = top, al; ForkJoinTask[] a; - if ((a = array) != null && b != s && (al = a.length) > 0) { - int index = (al - 1) & (s - 1); - ForkJoinTask o = (ForkJoinTask) - QA.get(a, index); - if (o instanceof CountedCompleter) { - CountedCompleter t = (CountedCompleter)o; - for (CountedCompleter f = t;;) { - if (f != task) { - if ((f = f.completer) == null) // try parent - break; - } - else { - if (QA.compareAndSet(a, index, t, null)) { + int s, k, cap; ForkJoinTask[] a; + while ((a = array) != null && (cap = a.length) > 0 && + (s = top) - base > 0) { + CountedCompleter v = null; + ForkJoinTask o = a[k = (cap - 1) & (s - 1)]; + if (o instanceof CountedCompleter) { + CountedCompleter t = (CountedCompleter)o; + for (CountedCompleter f = t;;) { + if (f != task) { + if ((f = f.completer) == null) + break; + } + else if (shared) { + if (tryLockPhase()) { + if (top == s && array == a && + QA.compareAndSet(a, k, t, null)) { top = s - 1; - VarHandle.releaseFence(); - t.doExec(); - help = true; + v = t; } - break; + releasePhaseLock(); + } + break; + } + else { + if (QA.compareAndSet(a, k, t, null)) { + top = s - 1; + v = t; } + break; } } } - if ((status = task.status) < 0 || !help || + if (v != null) + v.doExec(); + if ((status = task.status) < 0 || v == null || (limit != 0 && --limit == 0)) break; } @@ -1066,79 +1121,31 @@ final int localHelpCC(CountedCompleter task, int limit) { return status; } - // Operations on shared queues - - /** - * Tries to lock shared queue by CASing phase field. - */ - final boolean tryLockSharedQueue() { - return PHASE.compareAndSet(this, 0, QLOCK); - } - - /** - * Shared version of tryUnpush. - */ - final boolean trySharedUnpush(ForkJoinTask task) { - boolean popped = false; - int s = top - 1, al; ForkJoinTask[] a; - if ((a = array) != null && (al = a.length) > 0) { - int index = (al - 1) & s; - ForkJoinTask t = (ForkJoinTask) QA.get(a, index); - if (t == task && - PHASE.compareAndSet(this, 0, QLOCK)) { - if (top == s + 1 && array == a && - QA.compareAndSet(a, index, task, null)) { - popped = true; - top = s; - } - PHASE.setRelease(this, 0); - } - } - return popped; - } - /** - * Shared version of localHelpCC. + * Tries to poll and run AsynchronousCompletionTasks until + * none found or blocker is released + * + * @param blocker the blocker */ - final int sharedHelpCC(CountedCompleter task, int limit) { - int status = 0; - if (task != null && (status = task.status) >= 0) { - for (;;) { - boolean help = false; - int b = base, s = top, al; ForkJoinTask[] a; - if ((a = array) != null && b != s && (al = a.length) > 0) { - int index = (al - 1) & (s - 1); - ForkJoinTask o = (ForkJoinTask) - QA.get(a, index); - if (o instanceof CountedCompleter) { - CountedCompleter t = (CountedCompleter)o; - for (CountedCompleter f = t;;) { - if (f != task) { - if ((f = f.completer) == null) - break; - } - else { - if (PHASE.compareAndSet(this, 0, QLOCK)) { - if (top == s && array == a && - QA.compareAndSet(a, index, t, null)) { - help = true; - top = s - 1; - } - PHASE.setRelease(this, 0); - if (help) - t.doExec(); - } - break; - } - } + final void helpAsyncBlocker(ManagedBlocker blocker) { + if (blocker != null) { + int b, k, cap; ForkJoinTask[] a; ForkJoinTask t; + while ((a = array) != null && (cap = a.length) > 0 && + top - (b = base) > 0) { + t = (ForkJoinTask)QA.getAcquire(a, k = (cap - 1) & b); + if (blocker.isReleasable()) + break; + else if (base == b++ && t != null) { + if (!(t instanceof CompletableFuture. + AsynchronousCompletionTask)) + break; + else if (QA.compareAndSet(a, k, t, null)) { + BASE.setOpaque(this, b); + t.doExec(); } } - if ((status = task.status) < 0 || !help || - (limit != 0 && --limit == 0)) - break; } } - return status; } /** @@ -1153,13 +1160,17 @@ final boolean isApparentlyUnblocked() { } // VarHandle mechanics. - private static final VarHandle PHASE; + static final VarHandle PHASE; + static final VarHandle BASE; + static final VarHandle TOP; static { try { MethodHandles.Lookup l = MethodHandles.lookup(); PHASE = l.findVarHandle(WorkQueue.class, "phase", int.class); + BASE = l.findVarHandle(WorkQueue.class, "base", int.class); + TOP = l.findVarHandle(WorkQueue.class, "top", int.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } } @@ -1356,39 +1367,37 @@ final WorkQueue registerWorker(ForkJoinWorkerThread wt) { wt.setDaemon(true); // configure thread if ((handler = ueh) != null) wt.setUncaughtExceptionHandler(handler); - WorkQueue w = new WorkQueue(this, wt); int tid = 0; // for thread name - int fifo = mode & FIFO; + int idbits = mode & FIFO; String prefix = workerNamePrefix; + WorkQueue w = new WorkQueue(this, wt); if (prefix != null) { synchronized (prefix) { WorkQueue[] ws = workQueues; int n; int s = indexSeed += SEED_INCREMENT; + idbits |= (s & ~(SMASK | FIFO | DORMANT)); if (ws != null && (n = ws.length) > 1) { int m = n - 1; - tid = s & m; - int i = m & ((s << 1) | 1); // odd-numbered indices + tid = m & ((s << 1) | 1); // odd-numbered indices for (int probes = n >>> 1;;) { // find empty slot WorkQueue q; - if ((q = ws[i]) == null || q.phase == QUIET) + if ((q = ws[tid]) == null || q.phase == QUIET) break; else if (--probes == 0) { - i = n | 1; // resize below + tid = n | 1; // resize below break; } else - i = (i + 2) & m; + tid = (tid + 2) & m; } + w.phase = w.id = tid | idbits; // now publishable - int id = i | fifo | (s & ~(SMASK | FIFO | DORMANT)); - w.phase = w.id = id; // now publishable - - if (i < n) - ws[i] = w; + if (tid < n) + ws[tid] = w; else { // expand array int an = n << 1; WorkQueue[] as = new WorkQueue[an]; - as[i] = w; + as[tid] = w; int am = an - 1; for (int j = 0; j < n; ++j) { WorkQueue v; // copy external queue @@ -1421,14 +1430,14 @@ final void deregisterWorker(ForkJoinWorkerThread wt, Throwable ex) { int phase = 0; if (wt != null && (w = wt.workQueue) != null) { Object lock = workerNamePrefix; + int wid = w.id; long ns = (long)w.nsteals & 0xffffffffL; - int idx = w.id & SMASK; if (lock != null) { - WorkQueue[] ws; // remove index from array synchronized (lock) { - if ((ws = workQueues) != null && ws.length > idx && - ws[idx] == w) - ws[idx] = null; + WorkQueue[] ws; int n, i; // remove index from array + if ((ws = workQueues) != null && (n = ws.length) > 0 && + ws[i = wid & (n - 1)] == w) + ws[i] = null; stealCount += ns; } } @@ -1480,7 +1489,7 @@ else if ((v = ws[i]) == null) Thread vt = v.owner; if (sp == vp && CTL.compareAndSet(this, c, nc)) { v.phase = np; - if (v.source < 0) + if (vt != null && v.source < 0) LockSupport.unpark(vt); break; } @@ -1521,7 +1530,7 @@ else if ((sp = (int)c) != 0) { // replace or release long nc = ((long)v.stackPred & SP_MASK) | uc; if (vp == sp && CTL.compareAndSet(this, c, nc)) { v.phase = np; - if (v.source < 0) + if (vt != null && v.source < 0) LockSupport.unpark(vt); return (wp < 0) ? -1 : 1; } @@ -1578,98 +1587,85 @@ else if (bc < pc) { // lagging * See above for explanation. */ final void runWorker(WorkQueue w) { - WorkQueue[] ws; - w.growArray(); // allocate queue - int r = w.id ^ ThreadLocalRandom.nextSecondarySeed(); - if (r == 0) // initial nonzero seed - r = 1; - int lastSignalId = 0; // avoid unneeded signals - while ((ws = workQueues) != null) { - boolean nonempty = false; // scan - for (int n = ws.length, j = n, m = n - 1; j > 0; --j) { - WorkQueue q; int i, b, al; ForkJoinTask[] a; - if ((i = r & m) >= 0 && i < n && // always true - (q = ws[i]) != null && (b = q.base) - q.top < 0 && - (a = q.array) != null && (al = a.length) > 0) { - int qid = q.id; // (never zero) - int index = (al - 1) & b; - ForkJoinTask t = (ForkJoinTask) - QA.getAcquire(a, index); - if (t != null && b++ == q.base && - QA.compareAndSet(a, index, t, null)) { - if ((q.base = b) - q.top < 0 && qid != lastSignalId) - signalWork(); // propagate signal - w.source = lastSignalId = qid; - t.doExec(); - if ((w.id & FIFO) != 0) // run remaining locals - w.localPollAndExec(POLL_LIMIT); - else - w.localPopAndExec(POLL_LIMIT); - ForkJoinWorkerThread thread = w.owner; - ++w.nsteals; - w.source = 0; // now idle - if (thread != null) - thread.afterTopLevelExec(); + int r = (w.id ^ ThreadLocalRandom.nextSecondarySeed()) | FIFO; // rng + w.array = new ForkJoinTask[INITIAL_QUEUE_CAPACITY]; // initialize + for (;;) { + int phase; + if (scan(w, r)) { // scan until apparently empty + r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // move (xorshift) + } + else if ((phase = w.phase) >= 0) { // enqueue, then rescan + long np = (w.phase = (phase + SS_SEQ) | UNSIGNALLED) & SP_MASK; + long c, nc; + do { + w.stackPred = (int)(c = ctl); + nc = ((c - RC_UNIT) & UC_MASK) | np; + } while (!CTL.weakCompareAndSet(this, c, nc)); + } + else { // already queued + int pred = w.stackPred; + Thread.interrupted(); // clear before park + w.source = DORMANT; // enable signal + long c = ctl; + int md = mode, rc = (md & SMASK) + (int)(c >> RC_SHIFT); + if (md < 0) // terminating + break; + else if (rc <= 0 && (md & SHUTDOWN) != 0 && + tryTerminate(false, false)) + break; // quiescent shutdown + else if (rc <= 0 && pred != 0 && phase == (int)c) { + long nc = (UC_MASK & (c - TC_UNIT)) | (SP_MASK & pred); + long d = keepAlive + System.currentTimeMillis(); + LockSupport.parkUntil(this, d); + if (ctl == c && // drop on timeout if all idle + d - System.currentTimeMillis() <= TIMEOUT_SLOP && + CTL.compareAndSet(this, c, nc)) { + w.phase = QUIET; + break; } - nonempty = true; } - else if (nonempty) - break; - else - ++r; + else if (w.phase < 0) + LockSupport.park(this); // OK if spuriously woken + w.source = 0; // disable signal } + } + } - if (nonempty) { // move (xorshift) - r ^= r << 13; r ^= r >>> 17; r ^= r << 5; - } - else { - int phase; - lastSignalId = 0; // clear for next scan - if ((phase = w.phase) >= 0) { // enqueue - int np = w.phase = (phase + SS_SEQ) | UNSIGNALLED; - long c, nc; - do { - w.stackPred = (int)(c = ctl); - nc = ((c - RC_UNIT) & UC_MASK) | (SP_MASK & np); - } while (!CTL.weakCompareAndSet(this, c, nc)); - } - else { // already queued - int pred = w.stackPred; - w.source = DORMANT; // enable signal - for (int steps = 0;;) { - int md, rc; long c; - if (w.phase >= 0) { - w.source = 0; - break; - } - else if ((md = mode) < 0) // shutting down - return; - else if ((rc = ((md & SMASK) + // possibly quiescent - (int)((c = ctl) >> RC_SHIFT))) <= 0 && - (md & SHUTDOWN) != 0 && - tryTerminate(false, false)) - return; // help terminate - else if ((++steps & 1) == 0) - Thread.interrupted(); // clear between parks - else if (rc <= 0 && pred != 0 && phase == (int)c) { - long d = keepAlive + System.currentTimeMillis(); - LockSupport.parkUntil(this, d); - if (ctl == c && - d - System.currentTimeMillis() <= TIMEOUT_SLOP) { - long nc = ((UC_MASK & (c - TC_UNIT)) | - (SP_MASK & pred)); - if (CTL.compareAndSet(this, c, nc)) { - w.phase = QUIET; - return; // drop on timeout - } - } + /** + * Scans for and if found executes one or more top-level tasks from a queue. + * + * @return true if found an apparently non-empty queue, and + * possibly ran task(s). + */ + private boolean scan(WorkQueue w, int r) { + WorkQueue[] ws; int n; + if ((ws = workQueues) != null && (n = ws.length) > 0 && w != null) { + for (int m = n - 1, j = r & m;;) { + WorkQueue q; int b; + if ((q = ws[j]) != null && q.top != (b = q.base)) { + int qid = q.id; + ForkJoinTask[] a; int cap, k; ForkJoinTask t; + if ((a = q.array) != null && (cap = a.length) > 0) { + t = (ForkJoinTask)QA.getAcquire(a, k = (cap - 1) & b); + if (q.base == b++ && t != null && + QA.compareAndSet(a, k, t, null)) { + q.base = b; + w.source = qid; + if (q.top - b > 0) + signalWork(); + w.topLevelExec(t, q, // random fairness bound + r & ((n << TOP_BOUND_SHIFT) - 1)); } - else - LockSupport.park(this); } + return true; } + else if (--n > 0) + j = (j + 1) & m; + else + break; } } + return false; } /** @@ -1685,42 +1681,44 @@ else if (rc <= 0 && pred != 0 && phase == (int)c) { */ final int awaitJoin(WorkQueue w, ForkJoinTask task, long deadline) { int s = 0; + int seed = ThreadLocalRandom.nextSecondarySeed(); if (w != null && task != null && (!(task instanceof CountedCompleter) || - (s = w.localHelpCC((CountedCompleter)task, 0)) >= 0)) { + (s = w.helpCC((CountedCompleter)task, 0, false)) >= 0)) { w.tryRemoveAndExec(task); int src = w.source, id = w.id; + int r = (seed >>> 16) | 1, step = (seed & ~1) | 2; s = task.status; while (s >= 0) { WorkQueue[] ws; - boolean nonempty = false; - int r = ThreadLocalRandom.nextSecondarySeed() | 1; // odd indices - if ((ws = workQueues) != null) { // scan for matching id - for (int n = ws.length, m = n - 1, j = -n; j < n; j += 2) { - WorkQueue q; int i, b, al; ForkJoinTask[] a; - if ((i = (r + j) & m) >= 0 && i < n && - (q = ws[i]) != null && q.source == id && - (b = q.base) - q.top < 0 && - (a = q.array) != null && (al = a.length) > 0) { - int qid = q.id; - int index = (al - 1) & b; + int n = (ws = workQueues) == null ? 0 : ws.length, m = n - 1; + while (n > 0) { + WorkQueue q; int b; + if ((q = ws[r & m]) != null && q.source == id && + q.top != (b = q.base)) { + ForkJoinTask[] a; int cap, k; + int qid = q.id; + if ((a = q.array) != null && (cap = a.length) > 0) { ForkJoinTask t = (ForkJoinTask) - QA.getAcquire(a, index); - if (t != null && b++ == q.base && id == q.source && - QA.compareAndSet(a, index, t, null)) { + QA.getAcquire(a, k = (cap - 1) & b); + if (q.source == id && q.base == b++ && + t != null && QA.compareAndSet(a, k, t, null)) { q.base = b; w.source = qid; t.doExec(); w.source = src; } - nonempty = true; - break; } + break; + } + else { + r += step; + --n; } } if ((s = task.status) < 0) break; - else if (!nonempty) { + else if (n == 0) { // empty scan long ms, ns; int block; if (deadline == 0L) ms = 0L; // untimed @@ -1745,44 +1743,44 @@ else if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) <= 0L) * find tasks either. */ final void helpQuiescePool(WorkQueue w) { - int prevSrc = w.source, fifo = w.id & FIFO; + int prevSrc = w.source; + int seed = ThreadLocalRandom.nextSecondarySeed(); + int r = seed >>> 16, step = r | 1; for (int source = prevSrc, released = -1;;) { // -1 until known - WorkQueue[] ws; - if (fifo != 0) - w.localPollAndExec(0); - else - w.localPopAndExec(0); - if (released == -1 && w.phase >= 0) + ForkJoinTask localTask; WorkQueue[] ws; + while ((localTask = w.nextLocalTask()) != null) + localTask.doExec(); + if (w.phase >= 0 && released == -1) released = 1; boolean quiet = true, empty = true; - int r = ThreadLocalRandom.nextSecondarySeed(); - if ((ws = workQueues) != null) { - for (int n = ws.length, j = n, m = n - 1; j > 0; --j) { - WorkQueue q; int i, b, al; ForkJoinTask[] a; - if ((i = (r - j) & m) >= 0 && i < n && (q = ws[i]) != null) { - if ((b = q.base) - q.top < 0 && - (a = q.array) != null && (al = a.length) > 0) { - int qid = q.id; + int n = (ws = workQueues) == null ? 0 : ws.length; + for (int m = n - 1; n > 0; r += step, --n) { + WorkQueue q; int b; + if ((q = ws[r & m]) != null) { + int qs = q.source; + if (q.top != (b = q.base)) { + quiet = empty = false; + ForkJoinTask[] a; int cap, k; + int qid = q.id; + if ((a = q.array) != null && (cap = a.length) > 0) { if (released == 0) { // increment released = 1; CTL.getAndAdd(this, RC_UNIT); } - int index = (al - 1) & b; ForkJoinTask t = (ForkJoinTask) - QA.getAcquire(a, index); - if (t != null && b++ == q.base && - QA.compareAndSet(a, index, t, null)) { + QA.getAcquire(a, k = (cap - 1) & b); + if (q.base == b++ && t != null && + QA.compareAndSet(a, k, t, null)) { q.base = b; - w.source = source = q.id; + w.source = qid; t.doExec(); w.source = source = prevSrc; } - quiet = empty = false; - break; } - else if ((q.source & QUIET) == 0) - quiet = false; + break; } + else if ((qs & QUIET) == 0) + quiet = false; } } if (quiet) { @@ -1824,28 +1822,24 @@ private ForkJoinTask pollScan(boolean submissionsOnly) { origin = r & m; step = h | 1; } - for (int k = origin, oldSum = 0, checkSum = 0;;) { - WorkQueue q; int b, al; ForkJoinTask[] a; - if ((q = ws[k]) != null) { - checkSum += b = q.base; - if (b - q.top < 0 && - (a = q.array) != null && (al = a.length) > 0) { - int index = (al - 1) & b; - ForkJoinTask t = (ForkJoinTask) - QA.getAcquire(a, index); - if (t != null && b++ == q.base && - QA.compareAndSet(a, index, t, null)) { - q.base = b; + boolean nonempty = false; + for (int i = origin, oldSum = 0, checkSum = 0;;) { + WorkQueue q; + if ((q = ws[i]) != null) { + int b; ForkJoinTask t; + if (q.top - (b = q.base) > 0) { + nonempty = true; + if ((t = q.poll()) != null) return t; - } - else - break; // restart } + else + checkSum += b + q.id; } - if ((k = (k + step) & m) == origin) { - if (oldSum == (oldSum = checkSum)) + if ((i = (i + step) & m) == origin) { + if (!nonempty && oldSum == (oldSum = checkSum)) break rescan; checkSum = 0; + nonempty = false; } } } @@ -1859,11 +1853,9 @@ private ForkJoinTask pollScan(boolean submissionsOnly) { */ final ForkJoinTask nextTaskFor(WorkQueue w) { ForkJoinTask t; - if (w != null && - (t = (w.id & FIFO) != 0 ? w.poll() : w.pop()) != null) - return t; - else - return pollScan(false); + if (w == null || (t = w.nextLocalTask()) == null) + t = pollScan(false); + return t; } // External operations @@ -1881,64 +1873,35 @@ final void externalPush(ForkJoinTask task) { r = ThreadLocalRandom.getProbe(); } for (;;) { + WorkQueue q; int md = mode, n; WorkQueue[] ws = workQueues; if ((md & SHUTDOWN) != 0 || ws == null || (n = ws.length) <= 0) throw new RejectedExecutionException(); - else { - WorkQueue q; - boolean push = false, grow = false; - if ((q = ws[(n - 1) & r & SQMASK]) == null) { - Object lock = workerNamePrefix; - int qid = (r | QUIET) & ~(FIFO | OWNED); - q = new WorkQueue(this, null); - q.id = qid; - q.source = QUIET; - q.phase = QLOCK; // lock queue - if (lock != null) { - synchronized (lock) { // lock pool to install - int i; - if ((ws = workQueues) != null && - (n = ws.length) > 0 && - ws[i = qid & (n - 1) & SQMASK] == null) { - ws[i] = q; - push = grow = true; - } - } + else if ((q = ws[(n - 1) & r & SQMASK]) == null) { // add queue + int qid = (r | QUIET) & ~(FIFO | OWNED); + Object lock = workerNamePrefix; + ForkJoinTask[] qa = + new ForkJoinTask[INITIAL_QUEUE_CAPACITY]; + q = new WorkQueue(this, null); + q.array = qa; + q.id = qid; + q.source = QUIET; + if (lock != null) { // unless disabled, lock pool to install + synchronized (lock) { + WorkQueue[] vs; int i, vn; + if ((vs = workQueues) != null && (vn = vs.length) > 0 && + vs[i = qid & (vn - 1) & SQMASK] == null) + vs[i] = q; // else another thread already installed } } - else if (q.tryLockSharedQueue()) { - int b = q.base, s = q.top, al, d; ForkJoinTask[] a; - if ((a = q.array) != null && (al = a.length) > 0 && - al - 1 + (d = b - s) > 0) { - a[(al - 1) & s] = task; - q.top = s + 1; // relaxed writes OK here - q.phase = 0; - if (d < 0 && q.base - s < -1) - break; // no signal needed - } - else - grow = true; - push = true; - } - if (push) { - if (grow) { - try { - q.growArray(); - int s = q.top, al; ForkJoinTask[] a; - if ((a = q.array) != null && (al = a.length) > 0) { - a[(al - 1) & s] = task; - q.top = s + 1; - } - } finally { - q.phase = 0; - } - } + } + else if (!q.tryLockPhase()) // move if busy + r = ThreadLocalRandom.advanceProbe(r); + else { + if (q.lockedPush(task)) signalWork(); - break; - } - else // move if busy - r = ThreadLocalRandom.advanceProbe(r); + return; } } } @@ -1980,7 +1943,7 @@ final boolean tryExternalUnpush(ForkJoinTask task) { return ((ws = workQueues) != null && (n = ws.length) > 0 && (w = ws[(n - 1) & r & SQMASK]) != null && - w.trySharedUnpush(task)); + w.tryLockedUnpush(task)); } /** @@ -1991,7 +1954,7 @@ final int externalHelpComplete(CountedCompleter task, int maxTasks) { WorkQueue[] ws; WorkQueue w; int n; return ((ws = workQueues) != null && (n = ws.length) > 0 && (w = ws[(n - 1) & r & SQMASK]) != null) ? - w.sharedHelpCC(task, maxTasks) : 0; + w.helpCC(task, maxTasks, true) : 0; } /** @@ -2006,7 +1969,7 @@ final int externalHelpComplete(CountedCompleter task, int maxTasks) { */ final int helpComplete(WorkQueue w, CountedCompleter task, int maxTasks) { - return (w == null) ? 0 : w.localHelpCC(task, maxTasks); + return (w == null) ? 0 : w.helpCC(task, maxTasks, false); } /** @@ -2097,15 +2060,18 @@ private boolean tryTerminate(boolean now, boolean enable) { if ((md & SMASK) + (int)(checkSum >> RC_SHIFT) > 0) running = true; else if (ws != null) { - WorkQueue w; int b; + WorkQueue w; for (int i = 0; i < ws.length; ++i) { if ((w = ws[i]) != null) { - checkSum += (b = w.base) + w.id; + int s = w.source, p = w.phase; + int d = w.id, b = w.base; if (b != w.top || - ((i & 1) == 1 && w.source >= 0)) { + ((d & 1) == 1 && (s >= 0 || p >= 0))) { running = true; - break; + break; // working, scanning, or have work } + checkSum += (((long)s << 48) + ((long)p << 32) + + ((long)b << 16) + (long)d); } } } @@ -2136,7 +2102,7 @@ else if (workQueues == ws && oldSum == (oldSum = checkSum)) } catch (Throwable ignore) { } } - checkSum += w.base + w.id; + checkSum += ((long)w.phase << 32) + w.base; } } } @@ -2629,8 +2595,9 @@ public boolean getAsyncMode() { * @return the number of worker threads */ public int getRunningThreadCount() { - int rc = 0; WorkQueue[] ws; WorkQueue w; + VarHandle.acquireFence(); + int rc = 0; if ((ws = workQueues) != null) { for (int i = 1; i < ws.length; i += 2) { if ((w = ws[i]) != null && w.isApparentlyUnblocked()) @@ -2678,7 +2645,7 @@ else if (rc > 0) if ((ws = workQueues) != null) { for (int i = 1; i < ws.length; i += 2) { if ((v = ws[i]) != null) { - if ((v.source & QUIET) == 0) + if (v.source > 0) return false; --tc; } @@ -2724,8 +2691,9 @@ public long getStealCount() { * @return the number of queued tasks */ public long getQueuedTaskCount() { - long count = 0; WorkQueue[] ws; WorkQueue w; + VarHandle.acquireFence(); + int count = 0; if ((ws = workQueues) != null) { for (int i = 1; i < ws.length; i += 2) { if ((w = ws[i]) != null) @@ -2743,8 +2711,9 @@ public long getQueuedTaskCount() { * @return the number of queued submissions */ public int getQueuedSubmissionCount() { - int count = 0; WorkQueue[] ws; WorkQueue w; + VarHandle.acquireFence(); + int count = 0; if ((ws = workQueues) != null) { for (int i = 0; i < ws.length; i += 2) { if ((w = ws[i]) != null) @@ -2762,6 +2731,7 @@ public int getQueuedSubmissionCount() { */ public boolean hasQueuedSubmissions() { WorkQueue[] ws; WorkQueue w; + VarHandle.acquireFence(); if ((ws = workQueues) != null) { for (int i = 0; i < ws.length; i += 2) { if ((w = ws[i]) != null && !w.isEmpty()) @@ -2800,8 +2770,9 @@ protected ForkJoinTask pollSubmission() { * @return the number of elements transferred */ protected int drainTasksTo(Collection> c) { - int count = 0; WorkQueue[] ws; WorkQueue w; ForkJoinTask t; + VarHandle.acquireFence(); + int count = 0; if ((ws = workQueues) != null) { for (int i = 0; i < ws.length; ++i) { if ((w = ws[i]) != null) { @@ -2824,8 +2795,10 @@ protected int drainTasksTo(Collection> c) { */ public String toString() { // Use a single pass through workQueues to collect counts - long qt = 0L, qs = 0L; int rc = 0; + int md = mode; // read volatile fields first + long c = ctl; long st = stealCount; + long qt = 0L, qs = 0L; int rc = 0; WorkQueue[] ws; WorkQueue w; if ((ws = workQueues) != null) { for (int i = 0; i < ws.length; ++i) { @@ -2843,9 +2816,7 @@ public String toString() { } } - int md = mode; int pc = (md & SMASK); - long c = ctl; int tc = pc + (short)(c >>> TC_SHIFT); int ac = pc + (int)(c >> RC_SHIFT); if (ac < 0) // ignore transient negative @@ -3131,6 +3102,7 @@ public static interface ManagedBlocker { */ public static void managedBlock(ManagedBlocker blocker) throws InterruptedException { + if (blocker == null) throw new NullPointerException(); ForkJoinPool p; ForkJoinWorkerThread wt; WorkQueue w; @@ -3163,7 +3135,7 @@ public static void managedBlock(ManagedBlocker blocker) * available or blocker is released. */ static void helpAsyncBlocker(Executor e, ManagedBlocker blocker) { - if (blocker != null && (e instanceof ForkJoinPool)) { + if (e instanceof ForkJoinPool) { WorkQueue w; ForkJoinWorkerThread wt; WorkQueue[] ws; int r, n; ForkJoinPool p = (ForkJoinPool)e; Thread thread = Thread.currentThread(); @@ -3175,34 +3147,8 @@ else if ((r = ThreadLocalRandom.getProbe()) != 0 && w = ws[(n - 1) & r & SQMASK]; else w = null; - if (w != null) { - for (;;) { - int b = w.base, s = w.top, d, al; ForkJoinTask[] a; - if ((a = w.array) != null && (d = b - s) < 0 && - (al = a.length) > 0) { - int index = (al - 1) & b; - ForkJoinTask t = (ForkJoinTask) - QA.getAcquire(a, index); - if (blocker.isReleasable()) - break; - else if (b++ == w.base) { - if (t == null) { - if (d == -1) - break; - } - else if (!(t instanceof CompletableFuture. - AsynchronousCompletionTask)) - break; - else if (QA.compareAndSet(a, index, t, null)) { - w.base = b; - t.doExec(); - } - } - } - else - break; - } - } + if (w != null) + w.helpAsyncBlocker(blocker); } } @@ -3221,7 +3167,7 @@ protected RunnableFuture newTaskFor(Callable callable) { // VarHandle mechanics private static final VarHandle CTL; private static final VarHandle MODE; - private static final VarHandle QA; + static final VarHandle QA; static { try { @@ -3230,7 +3176,7 @@ protected RunnableFuture newTaskFor(Callable callable) { MODE = l.findVarHandle(ForkJoinPool.class, "mode", int.class); QA = MethodHandles.arrayElementVarHandle(ForkJoinTask[].class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } // Reduce the risk of rare disastrous classloading in first call to From d9527c91c8c5179976cb28be6f8882ce84a3a8df Mon Sep 17 00:00:00 2001 From: dl Date: Tue, 10 Apr 2018 11:33:29 -0700 Subject: [PATCH 122/196] 8200258: Improve CopyOnWriteArrayList subList code Reviewed-by: martin, psandoz, smarks --- .../util/concurrent/CopyOnWriteArrayList.java | 514 ++++++++------ .../Collection/IteratorMicroBenchmark.java | 160 +++-- .../util/Collection/RemoveMicroBenchmark.java | 316 ++++----- .../util/concurrent/tck/Collection8Test.java | 59 +- .../tck/CopyOnWriteArrayListTest.java | 626 ++++++++---------- .../tck/CopyOnWriteArraySetTest.java | 11 +- .../util/concurrent/tck/JSR166TestCase.java | 62 +- .../util/concurrent/tck/LinkedListTest.java | 13 +- .../java/util/concurrent/tck/VectorTest.java | 401 ++++++++++- 9 files changed, 1391 insertions(+), 771 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java index df28a5bc12e..e725b1da740 100644 --- a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java +++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java @@ -35,7 +35,6 @@ package java.util.concurrent; import java.lang.reflect.Field; -import java.util.AbstractList; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; @@ -134,17 +133,17 @@ public CopyOnWriteArrayList() { * @throws NullPointerException if the specified collection is null */ public CopyOnWriteArrayList(Collection c) { - Object[] elements; + Object[] es; if (c.getClass() == CopyOnWriteArrayList.class) - elements = ((CopyOnWriteArrayList)c).getArray(); + es = ((CopyOnWriteArrayList)c).getArray(); else { - elements = c.toArray(); + es = c.toArray(); // defend against c.toArray (incorrectly) not returning Object[] // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652) - if (elements.getClass() != Object[].class) - elements = Arrays.copyOf(elements, elements.length, Object[].class); + if (es.getClass() != Object[].class) + es = Arrays.copyOf(es, es.length, Object[].class); } - setArray(elements); + setArray(es); } /** @@ -180,20 +179,19 @@ public boolean isEmpty() { * static version of indexOf, to allow repeated calls without * needing to re-acquire array each time. * @param o element to search for - * @param elements the array - * @param index first index to search - * @param fence one past last index to search + * @param es the array + * @param from first index to search + * @param to one past last index to search * @return index of element, or -1 if absent */ - private static int indexOf(Object o, Object[] elements, - int index, int fence) { + private static int indexOfRange(Object o, Object[] es, int from, int to) { if (o == null) { - for (int i = index; i < fence; i++) - if (elements[i] == null) + for (int i = from; i < to; i++) + if (es[i] == null) return i; } else { - for (int i = index; i < fence; i++) - if (o.equals(elements[i])) + for (int i = from; i < to; i++) + if (o.equals(es[i])) return i; } return -1; @@ -202,18 +200,19 @@ private static int indexOf(Object o, Object[] elements, /** * static version of lastIndexOf. * @param o element to search for - * @param elements the array - * @param index first index to search + * @param es the array + * @param from index of first element of range, last element to search + * @param to one past last element of range, first element to search * @return index of element, or -1 if absent */ - private static int lastIndexOf(Object o, Object[] elements, int index) { + private static int lastIndexOfRange(Object o, Object[] es, int from, int to) { if (o == null) { - for (int i = index; i >= 0; i--) - if (elements[i] == null) + for (int i = to - 1; i >= from; i--) + if (es[i] == null) return i; } else { - for (int i = index; i >= 0; i--) - if (o.equals(elements[i])) + for (int i = to - 1; i >= from; i--) + if (o.equals(es[i])) return i; } return -1; @@ -228,16 +227,15 @@ private static int lastIndexOf(Object o, Object[] elements, int index) { * @return {@code true} if this list contains the specified element */ public boolean contains(Object o) { - Object[] elements = getArray(); - return indexOf(o, elements, 0, elements.length) >= 0; + return indexOf(o) >= 0; } /** * {@inheritDoc} */ public int indexOf(Object o) { - Object[] elements = getArray(); - return indexOf(o, elements, 0, elements.length); + Object[] es = getArray(); + return indexOfRange(o, es, 0, es.length); } /** @@ -256,16 +254,16 @@ public int indexOf(Object o) { * @throws IndexOutOfBoundsException if the specified index is negative */ public int indexOf(E e, int index) { - Object[] elements = getArray(); - return indexOf(e, elements, index, elements.length); + Object[] es = getArray(); + return indexOfRange(e, es, index, es.length); } /** * {@inheritDoc} */ public int lastIndexOf(Object o) { - Object[] elements = getArray(); - return lastIndexOf(o, elements, elements.length - 1); + Object[] es = getArray(); + return lastIndexOfRange(o, es, 0, es.length); } /** @@ -285,8 +283,8 @@ public int lastIndexOf(Object o) { * than or equal to the current size of this list */ public int lastIndexOf(E e, int index) { - Object[] elements = getArray(); - return lastIndexOf(e, elements, index); + Object[] es = getArray(); + return lastIndexOfRange(e, es, 0, index + 1); } /** @@ -322,8 +320,7 @@ public Object clone() { * @return an array containing all the elements in this list */ public Object[] toArray() { - Object[] elements = getArray(); - return Arrays.copyOf(elements, elements.length); + return getArray().clone(); } /** @@ -366,12 +363,12 @@ public Object[] toArray() { */ @SuppressWarnings("unchecked") public T[] toArray(T[] a) { - Object[] elements = getArray(); - int len = elements.length; + Object[] es = getArray(); + int len = es.length; if (a.length < len) - return (T[]) Arrays.copyOf(elements, len, a.getClass()); + return (T[]) Arrays.copyOf(es, len, a.getClass()); else { - System.arraycopy(elements, 0, a, 0, len); + System.arraycopy(es, 0, a, 0, len); if (a.length > len) a[len] = null; return a; @@ -406,17 +403,13 @@ public E get(int index) { */ public E set(int index, E element) { synchronized (lock) { - Object[] elements = getArray(); - E oldValue = elementAt(elements, index); + Object[] es = getArray(); + E oldValue = elementAt(es, index); if (oldValue != element) { - int len = elements.length; - Object[] newElements = Arrays.copyOf(elements, len); - newElements[index] = element; - setArray(newElements); - } else { - // Not quite a no-op; ensures volatile write semantics - setArray(elements); + es = es.clone(); + es[index] = element; + setArray(es); } return oldValue; } @@ -430,11 +423,11 @@ public E set(int index, E element) { */ public boolean add(E e) { synchronized (lock) { - Object[] elements = getArray(); - int len = elements.length; - Object[] newElements = Arrays.copyOf(elements, len + 1); - newElements[len] = e; - setArray(newElements); + Object[] es = getArray(); + int len = es.length; + es = Arrays.copyOf(es, len + 1); + es[len] = e; + setArray(es); return true; } } @@ -448,18 +441,18 @@ public boolean add(E e) { */ public void add(int index, E element) { synchronized (lock) { - Object[] elements = getArray(); - int len = elements.length; + Object[] es = getArray(); + int len = es.length; if (index > len || index < 0) throw new IndexOutOfBoundsException(outOfBounds(index, len)); Object[] newElements; int numMoved = len - index; if (numMoved == 0) - newElements = Arrays.copyOf(elements, len + 1); + newElements = Arrays.copyOf(es, len + 1); else { newElements = new Object[len + 1]; - System.arraycopy(elements, 0, newElements, 0, index); - System.arraycopy(elements, index, newElements, index + 1, + System.arraycopy(es, 0, newElements, 0, index); + System.arraycopy(es, index, newElements, index + 1, numMoved); } newElements[index] = element; @@ -476,19 +469,20 @@ public void add(int index, E element) { */ public E remove(int index) { synchronized (lock) { - Object[] elements = getArray(); - int len = elements.length; - E oldValue = elementAt(elements, index); + Object[] es = getArray(); + int len = es.length; + E oldValue = elementAt(es, index); int numMoved = len - index - 1; + Object[] newElements; if (numMoved == 0) - setArray(Arrays.copyOf(elements, len - 1)); + newElements = Arrays.copyOf(es, len - 1); else { - Object[] newElements = new Object[len - 1]; - System.arraycopy(elements, 0, newElements, 0, index); - System.arraycopy(elements, index + 1, newElements, index, + newElements = new Object[len - 1]; + System.arraycopy(es, 0, newElements, 0, index); + System.arraycopy(es, index + 1, newElements, index, numMoved); - setArray(newElements); } + setArray(newElements); return oldValue; } } @@ -507,7 +501,7 @@ public E remove(int index) { */ public boolean remove(Object o) { Object[] snapshot = getArray(); - int index = indexOf(o, snapshot, 0, snapshot.length); + int index = indexOfRange(o, snapshot, 0, snapshot.length); return index >= 0 && remove(o, snapshot, index); } @@ -532,7 +526,7 @@ private boolean remove(Object o, Object[] snapshot, int index) { return false; if (current[index] == o) break findIndex; - index = indexOf(o, current, index, len); + index = indexOfRange(o, current, index, len); if (index < 0) return false; } @@ -560,19 +554,19 @@ private boolean remove(Object o, Object[] snapshot, int index) { */ void removeRange(int fromIndex, int toIndex) { synchronized (lock) { - Object[] elements = getArray(); - int len = elements.length; + Object[] es = getArray(); + int len = es.length; if (fromIndex < 0 || toIndex > len || toIndex < fromIndex) throw new IndexOutOfBoundsException(); int newlen = len - (toIndex - fromIndex); int numMoved = len - toIndex; if (numMoved == 0) - setArray(Arrays.copyOf(elements, newlen)); + setArray(Arrays.copyOf(es, newlen)); else { Object[] newElements = new Object[newlen]; - System.arraycopy(elements, 0, newElements, 0, fromIndex); - System.arraycopy(elements, toIndex, newElements, + System.arraycopy(es, 0, newElements, 0, fromIndex); + System.arraycopy(es, toIndex, newElements, fromIndex, numMoved); setArray(newElements); } @@ -587,7 +581,7 @@ void removeRange(int fromIndex, int toIndex) { */ public boolean addIfAbsent(E e) { Object[] snapshot = getArray(); - return indexOf(e, snapshot, 0, snapshot.length) < 0 + return indexOfRange(e, snapshot, 0, snapshot.length) < 0 && addIfAbsent(e, snapshot); } @@ -606,7 +600,7 @@ private boolean addIfAbsent(E e, Object[] snapshot) { if (current[i] != snapshot[i] && Objects.equals(e, current[i])) return false; - if (indexOf(e, current, common, len) >= 0) + if (indexOfRange(e, current, common, len) >= 0) return false; } Object[] newElements = Arrays.copyOf(current, len + 1); @@ -627,10 +621,10 @@ private boolean addIfAbsent(E e, Object[] snapshot) { * @see #contains(Object) */ public boolean containsAll(Collection c) { - Object[] elements = getArray(); - int len = elements.length; + Object[] es = getArray(); + int len = es.length; for (Object e : c) { - if (indexOf(e, elements, 0, len) < 0) + if (indexOfRange(e, es, 0, len) < 0) return false; } return true; @@ -694,18 +688,18 @@ public int addAllAbsent(Collection c) { if (cs.length == 0) return 0; synchronized (lock) { - Object[] elements = getArray(); - int len = elements.length; + Object[] es = getArray(); + int len = es.length; int added = 0; // uniquify and compact elements in cs for (int i = 0; i < cs.length; ++i) { Object e = cs[i]; - if (indexOf(e, elements, 0, len) < 0 && - indexOf(e, cs, 0, added) < 0) + if (indexOfRange(e, es, 0, len) < 0 && + indexOfRange(e, cs, 0, added) < 0) cs[added++] = e; } if (added > 0) { - Object[] newElements = Arrays.copyOf(elements, len + added); + Object[] newElements = Arrays.copyOf(es, len + added); System.arraycopy(cs, 0, newElements, len, added); setArray(newElements); } @@ -739,15 +733,16 @@ public boolean addAll(Collection c) { if (cs.length == 0) return false; synchronized (lock) { - Object[] elements = getArray(); - int len = elements.length; + Object[] es = getArray(); + int len = es.length; + Object[] newElements; if (len == 0 && cs.getClass() == Object[].class) - setArray(cs); + newElements = cs; else { - Object[] newElements = Arrays.copyOf(elements, len + cs.length); + newElements = Arrays.copyOf(es, len + cs.length); System.arraycopy(cs, 0, newElements, len, cs.length); - setArray(newElements); } + setArray(newElements); return true; } } @@ -771,8 +766,8 @@ public boolean addAll(Collection c) { public boolean addAll(int index, Collection c) { Object[] cs = c.toArray(); synchronized (lock) { - Object[] elements = getArray(); - int len = elements.length; + Object[] es = getArray(); + int len = es.length; if (index > len || index < 0) throw new IndexOutOfBoundsException(outOfBounds(index, len)); if (cs.length == 0) @@ -780,11 +775,11 @@ public boolean addAll(int index, Collection c) { int numMoved = len - index; Object[] newElements; if (numMoved == 0) - newElements = Arrays.copyOf(elements, len + cs.length); + newElements = Arrays.copyOf(es, len + cs.length); else { newElements = new Object[len + cs.length]; - System.arraycopy(elements, 0, newElements, 0, index); - System.arraycopy(elements, index, + System.arraycopy(es, 0, newElements, 0, index); + System.arraycopy(es, index, newElements, index + cs.length, numMoved); } @@ -866,14 +861,14 @@ boolean bulkRemove(Predicate filter, int i, int end) { } public void replaceAll(UnaryOperator operator) { - Objects.requireNonNull(operator); synchronized (lock) { - replaceAll(operator, 0, getArray().length); + replaceAllRange(operator, 0, getArray().length); } } - void replaceAll(UnaryOperator operator, int i, int end) { + void replaceAllRange(UnaryOperator operator, int i, int end) { // assert Thread.holdsLock(lock); + Objects.requireNonNull(operator); final Object[] es = getArray().clone(); for (; i < end; i++) es[i] = operator.apply(elementAt(es, i)); @@ -882,12 +877,12 @@ void replaceAll(UnaryOperator operator, int i, int end) { public void sort(Comparator c) { synchronized (lock) { - sort(c, 0, getArray().length); + sortRange(c, 0, getArray().length); } } @SuppressWarnings("unchecked") - void sort(Comparator c, int i, int end) { + void sortRange(Comparator c, int i, int end) { // assert Thread.holdsLock(lock); final Object[] es = getArray().clone(); Arrays.sort(es, i, end, (Comparator)c); @@ -908,12 +903,12 @@ private void writeObject(java.io.ObjectOutputStream s) s.defaultWriteObject(); - Object[] elements = getArray(); + Object[] es = getArray(); // Write out array length - s.writeInt(elements.length); + s.writeInt(es.length); // Write out all elements in the proper order. - for (Object element : elements) + for (Object element : es) s.writeObject(element); } @@ -935,12 +930,12 @@ private void readObject(java.io.ObjectInputStream s) // Read in array length and allocate array int len = s.readInt(); SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, len); - Object[] elements = new Object[len]; + Object[] es = new Object[len]; // Read in all elements in the proper order. for (int i = 0; i < len; i++) - elements[i] = s.readObject(); - setArray(elements); + es[i] = s.readObject(); + setArray(es); } /** @@ -986,6 +981,15 @@ public boolean equals(Object o) { return !it.hasNext(); } + private static int hashCodeOfRange(Object[] es, int from, int to) { + int hashCode = 1; + for (int i = from; i < to; i++) { + Object x = es[i]; + hashCode = 31 * hashCode + (x == null ? 0 : x.hashCode()); + } + return hashCode; + } + /** * Returns the hash code value for this list. * @@ -994,10 +998,8 @@ public boolean equals(Object o) { * @return the hash code value for this list */ public int hashCode() { - int hashCode = 1; - for (Object x : getArray()) - hashCode = 31 * hashCode + (x == null ? 0 : x.hashCode()); - return hashCode; + Object[] es = getArray(); + return hashCodeOfRange(es, 0, es.length); } /** @@ -1037,12 +1039,12 @@ public ListIterator listIterator() { * @throws IndexOutOfBoundsException {@inheritDoc} */ public ListIterator listIterator(int index) { - Object[] elements = getArray(); - int len = elements.length; + Object[] es = getArray(); + int len = es.length; if (index < 0 || index > len) throw new IndexOutOfBoundsException(outOfBounds(index, len)); - return new COWIterator(elements, index); + return new COWIterator(es, index); } /** @@ -1070,9 +1072,9 @@ static final class COWIterator implements ListIterator { /** Index of element to be returned by subsequent call to next. */ private int cursor; - COWIterator(Object[] elements, int initialCursor) { + COWIterator(Object[] es, int initialCursor) { cursor = initialCursor; - snapshot = elements; + snapshot = es; } public boolean hasNext() { @@ -1102,7 +1104,7 @@ public int nextIndex() { } public int previousIndex() { - return cursor-1; + return cursor - 1; } /** @@ -1133,14 +1135,13 @@ public void add(E e) { } @Override - @SuppressWarnings("unchecked") public void forEachRemaining(Consumer action) { Objects.requireNonNull(action); final int size = snapshot.length; - for (int i = cursor; i < size; i++) { - action.accept((E) snapshot[i]); - } + int i = cursor; cursor = size; + for (; i < size; i++) + action.accept(elementAt(snapshot, i)); } } @@ -1161,136 +1162,264 @@ public void forEachRemaining(Consumer action) { */ public List subList(int fromIndex, int toIndex) { synchronized (lock) { - Object[] elements = getArray(); - int len = elements.length; - if (fromIndex < 0 || toIndex > len || fromIndex > toIndex) + Object[] es = getArray(); + int len = es.length; + int size = toIndex - fromIndex; + if (fromIndex < 0 || toIndex > len || size < 0) throw new IndexOutOfBoundsException(); - return new COWSubList(this, fromIndex, toIndex); + return new COWSubList(es, fromIndex, size); } } /** * Sublist for CopyOnWriteArrayList. */ - private static class COWSubList - extends AbstractList - implements RandomAccess - { - private final CopyOnWriteArrayList l; + private class COWSubList implements List, RandomAccess { private final int offset; private int size; private Object[] expectedArray; - // only call this holding l's lock - COWSubList(CopyOnWriteArrayList list, - int fromIndex, int toIndex) { - // assert Thread.holdsLock(list.lock); - l = list; - expectedArray = l.getArray(); - offset = fromIndex; - size = toIndex - fromIndex; + COWSubList(Object[] es, int offset, int size) { + // assert Thread.holdsLock(lock); + expectedArray = es; + this.offset = offset; + this.size = size; } - // only call this holding l's lock private void checkForComodification() { - // assert Thread.holdsLock(l.lock); - if (l.getArray() != expectedArray) + // assert Thread.holdsLock(lock); + if (getArray() != expectedArray) throw new ConcurrentModificationException(); } private Object[] getArrayChecked() { - // assert Thread.holdsLock(l.lock); - Object[] a = l.getArray(); + // assert Thread.holdsLock(lock); + Object[] a = getArray(); if (a != expectedArray) throw new ConcurrentModificationException(); return a; } - // only call this holding l's lock private void rangeCheck(int index) { - // assert Thread.holdsLock(l.lock); + // assert Thread.holdsLock(lock); if (index < 0 || index >= size) throw new IndexOutOfBoundsException(outOfBounds(index, size)); } + private void rangeCheckForAdd(int index) { + // assert Thread.holdsLock(lock); + if (index < 0 || index > size) + throw new IndexOutOfBoundsException(outOfBounds(index, size)); + } + + public Object[] toArray() { + final Object[] es; + final int offset; + final int size; + synchronized (lock) { + es = getArrayChecked(); + offset = this.offset; + size = this.size; + } + return Arrays.copyOfRange(es, offset, offset + size); + } + + @SuppressWarnings("unchecked") + public T[] toArray(T[] a) { + final Object[] es; + final int offset; + final int size; + synchronized (lock) { + es = getArrayChecked(); + offset = this.offset; + size = this.size; + } + if (a.length < size) + return (T[]) Arrays.copyOfRange( + es, offset, offset + size, a.getClass()); + else { + System.arraycopy(es, offset, a, 0, size); + if (a.length > size) + a[size] = null; + return a; + } + } + + public int indexOf(Object o) { + final Object[] es; + final int offset; + final int size; + synchronized (lock) { + es = getArrayChecked(); + offset = this.offset; + size = this.size; + } + int i = indexOfRange(o, es, offset, offset + size); + return (i == -1) ? -1 : i - offset; + } + + public int lastIndexOf(Object o) { + final Object[] es; + final int offset; + final int size; + synchronized (lock) { + es = getArrayChecked(); + offset = this.offset; + size = this.size; + } + int i = lastIndexOfRange(o, es, offset, offset + size); + return (i == -1) ? -1 : i - offset; + } + + public boolean contains(Object o) { + return indexOf(o) >= 0; + } + + public boolean containsAll(Collection c) { + final Object[] es; + final int offset; + final int size; + synchronized (lock) { + es = getArrayChecked(); + offset = this.offset; + size = this.size; + } + for (Object o : c) + if (indexOfRange(o, es, offset, offset + size) < 0) + return false; + return true; + } + + public boolean isEmpty() { + return size() == 0; + } + + public String toString() { + return Arrays.toString(toArray()); + } + + public int hashCode() { + final Object[] es; + final int offset; + final int size; + synchronized (lock) { + es = getArrayChecked(); + offset = this.offset; + size = this.size; + } + return hashCodeOfRange(es, offset, offset + size); + } + + public boolean equals(Object o) { + if (o == this) + return true; + if (!(o instanceof List)) + return false; + Iterator it = ((List)o).iterator(); + + final Object[] es; + final int offset; + final int size; + synchronized (lock) { + es = getArrayChecked(); + offset = this.offset; + size = this.size; + } + + for (int i = offset, end = offset + size; i < end; i++) + if (!it.hasNext() || !Objects.equals(es[i], it.next())) + return false; + return !it.hasNext(); + } + public E set(int index, E element) { - synchronized (l.lock) { + synchronized (lock) { rangeCheck(index); checkForComodification(); - E x = l.set(offset + index, element); - expectedArray = l.getArray(); + E x = CopyOnWriteArrayList.this.set(offset + index, element); + expectedArray = getArray(); return x; } } public E get(int index) { - synchronized (l.lock) { + synchronized (lock) { rangeCheck(index); checkForComodification(); - return l.get(offset + index); + return CopyOnWriteArrayList.this.get(offset + index); } } public int size() { - synchronized (l.lock) { + synchronized (lock) { checkForComodification(); return size; } } public boolean add(E element) { - synchronized (l.lock) { + synchronized (lock) { checkForComodification(); - l.add(offset + size, element); - expectedArray = l.getArray(); + CopyOnWriteArrayList.this.add(offset + size, element); + expectedArray = getArray(); size++; } return true; } public void add(int index, E element) { - synchronized (l.lock) { + synchronized (lock) { checkForComodification(); - if (index < 0 || index > size) - throw new IndexOutOfBoundsException - (outOfBounds(index, size)); - l.add(offset + index, element); - expectedArray = l.getArray(); + rangeCheckForAdd(index); + CopyOnWriteArrayList.this.add(offset + index, element); + expectedArray = getArray(); size++; } } public boolean addAll(Collection c) { - synchronized (l.lock) { + synchronized (lock) { + final Object[] oldArray = getArrayChecked(); + boolean modified = + CopyOnWriteArrayList.this.addAll(offset + size, c); + size += (expectedArray = getArray()).length - oldArray.length; + return modified; + } + } + + public boolean addAll(int index, Collection c) { + synchronized (lock) { + rangeCheckForAdd(index); final Object[] oldArray = getArrayChecked(); - boolean modified = l.addAll(offset + size, c); - size += (expectedArray = l.getArray()).length - oldArray.length; + boolean modified = + CopyOnWriteArrayList.this.addAll(offset + index, c); + size += (expectedArray = getArray()).length - oldArray.length; return modified; } } public void clear() { - synchronized (l.lock) { + synchronized (lock) { checkForComodification(); - l.removeRange(offset, offset + size); - expectedArray = l.getArray(); + removeRange(offset, offset + size); + expectedArray = getArray(); size = 0; } } public E remove(int index) { - synchronized (l.lock) { + synchronized (lock) { rangeCheck(index); checkForComodification(); - E result = l.remove(offset + index); - expectedArray = l.getArray(); + E result = CopyOnWriteArrayList.this.remove(offset + index); + expectedArray = getArray(); size--; return result; } } public boolean remove(Object o) { - synchronized (l.lock) { + synchronized (lock) { checkForComodification(); int index = indexOf(o); if (index == -1) @@ -1301,36 +1430,35 @@ public boolean remove(Object o) { } public Iterator iterator() { - synchronized (l.lock) { - checkForComodification(); - return new COWSubListIterator(l, 0, offset, size); - } + return listIterator(0); + } + + public ListIterator listIterator() { + return listIterator(0); } public ListIterator listIterator(int index) { - synchronized (l.lock) { + synchronized (lock) { checkForComodification(); - if (index < 0 || index > size) - throw new IndexOutOfBoundsException - (outOfBounds(index, size)); - return new COWSubListIterator(l, index, offset, size); + rangeCheckForAdd(index); + return new COWSubListIterator( + CopyOnWriteArrayList.this, index, offset, size); } } public List subList(int fromIndex, int toIndex) { - synchronized (l.lock) { + synchronized (lock) { checkForComodification(); if (fromIndex < 0 || toIndex > size || fromIndex > toIndex) throw new IndexOutOfBoundsException(); - return new COWSubList(l, fromIndex + offset, - toIndex + offset); + return new COWSubList(expectedArray, fromIndex + offset, toIndex - fromIndex); } } public void forEach(Consumer action) { Objects.requireNonNull(action); int i, end; final Object[] es; - synchronized (l.lock) { + synchronized (lock) { es = getArrayChecked(); i = offset; end = i + size; @@ -1340,19 +1468,18 @@ public void forEach(Consumer action) { } public void replaceAll(UnaryOperator operator) { - Objects.requireNonNull(operator); - synchronized (l.lock) { + synchronized (lock) { checkForComodification(); - l.replaceAll(operator, offset, offset + size); - expectedArray = l.getArray(); + replaceAllRange(operator, offset, offset + size); + expectedArray = getArray(); } } public void sort(Comparator c) { - synchronized (l.lock) { + synchronized (lock) { checkForComodification(); - l.sort(c, offset, offset + size); - expectedArray = l.getArray(); + sortRange(c, offset, offset + size); + expectedArray = getArray(); } } @@ -1372,16 +1499,17 @@ public boolean removeIf(Predicate filter) { } private boolean bulkRemove(Predicate filter) { - synchronized (l.lock) { + synchronized (lock) { final Object[] oldArray = getArrayChecked(); - boolean modified = l.bulkRemove(filter, offset, offset + size); - size += (expectedArray = l.getArray()).length - oldArray.length; + boolean modified = CopyOnWriteArrayList.this.bulkRemove( + filter, offset, offset + size); + size += (expectedArray = getArray()).length - oldArray.length; return modified; } } public Spliterator spliterator() { - synchronized (l.lock) { + synchronized (lock) { return Spliterators.spliterator( getArrayChecked(), offset, offset + size, Spliterator.IMMUTABLE | Spliterator.ORDERED); @@ -1398,7 +1526,7 @@ private static class COWSubListIterator implements ListIterator { COWSubListIterator(List l, int index, int offset, int size) { this.offset = offset; this.size = size; - it = l.listIterator(index+offset); + it = l.listIterator(index + offset); } public boolean hasNext() { @@ -1447,7 +1575,7 @@ public void add(E e) { @SuppressWarnings("unchecked") public void forEachRemaining(Consumer action) { Objects.requireNonNull(action); - while (nextIndex() < size) { + while (hasNext()) { action.accept(it.next()); } } diff --git a/test/jdk/java/util/Collection/IteratorMicroBenchmark.java b/test/jdk/java/util/Collection/IteratorMicroBenchmark.java index 8c9fa1c35c1..d2efdc09c99 100644 --- a/test/jdk/java/util/Collection/IteratorMicroBenchmark.java +++ b/test/jdk/java/util/Collection/IteratorMicroBenchmark.java @@ -36,6 +36,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Deque; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -55,6 +56,7 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.LongAdder; +import java.util.function.UnaryOperator; import java.util.regex.Pattern; import java.util.stream.Stream; @@ -75,6 +77,13 @@ abstract static class Job { public Job(String name) { this.name = name; } public String name() { return name; } public abstract void work() throws Throwable; + public void run() { + try { work(); } + catch (Throwable ex) { + // current job cannot always be deduced from stacktrace. + throw new RuntimeException("Job failed: " + name(), ex); + } + } } final int iterations; @@ -102,6 +111,7 @@ abstract static class Job { static void forceFullGc() { CountDownLatch finalizeDone = new CountDownLatch(1); WeakReference ref = new WeakReference(new Object() { + @SuppressWarnings("deprecation") protected void finalize() { finalizeDone.countDown(); }}); try { for (int i = 0; i < 10; i++) { @@ -123,7 +133,7 @@ static void forceFullGc() { * compiling everything worth compiling. * Returns array of average times per job per run. */ - long[] time0(List jobs) throws Throwable { + long[] time0(List jobs) { final int size = jobs.size(); long[] nanoss = new long[size]; for (int i = 0; i < size; i++) { @@ -132,7 +142,7 @@ long[] time0(List jobs) throws Throwable { long totalTime; int runs = 0; long startTime = System.nanoTime(); - do { job.work(); runs++; } + do { job.run(); runs++; } while ((totalTime = System.nanoTime() - startTime) < warmupNanos); nanoss[i] = totalTime/runs; } @@ -211,10 +221,6 @@ private static void deoptimize(int sum) { System.out.println("the answer"); } - private static List asSubList(List list) { - return list.subList(0, list.size()); - } - private static Iterable backwards(final List list) { return new Iterable() { public Iterator iterator() { @@ -241,11 +247,32 @@ public static void main(String[] args) throws Throwable { new IteratorMicroBenchmark(args).run(); } - void run() throws Throwable { -// System.out.printf( -// "iterations=%d size=%d, warmup=%1g, filter=\"%s\"%n", -// iterations, size, warmupSeconds, nameFilter); + HashMap, String> goodClassName = new HashMap<>(); + + String goodClassName(Class klazz) { + return goodClassName.computeIfAbsent( + klazz, + k -> { + String simple = k.getSimpleName(); + return (simple.equals("SubList")) // too simple! + ? k.getName().replaceFirst(".*\\.", "") + : simple; + }); + } + static List makeSubList(List list) { + final ThreadLocalRandom rnd = ThreadLocalRandom.current(); + int size = list.size(); + if (size <= 2) return list.subList(0, size); + List subList = list.subList(rnd.nextInt(0, 2), + size - rnd.nextInt(0, 2)); + List copy = new ArrayList<>(list); + subList.clear(); + subList.addAll(copy); + return subList; + } + + void run() throws Throwable { final ArrayList al = new ArrayList<>(size); // Populate collections with random data @@ -265,10 +292,14 @@ void run() throws Throwable { ArrayList jobs = Stream.>of( al, ad, abq, + makeSubList(new ArrayList<>(al)), new LinkedList<>(al), + makeSubList(new LinkedList<>(al)), new PriorityQueue<>(al), new Vector<>(al), + makeSubList(new Vector<>(al)), new CopyOnWriteArrayList<>(al), + makeSubList(new CopyOnWriteArrayList<>(al)), new ConcurrentLinkedQueue<>(al), new ConcurrentLinkedDeque<>(al), new LinkedBlockingQueue<>(al), @@ -294,16 +325,25 @@ private Stream concatStreams(Stream ... streams) { Stream jobs(Collection x) { return concatStreams( collectionJobs(x), + (x instanceof Deque) ? dequeJobs((Deque)x) : Stream.empty(), + (x instanceof List) ? listJobs((List)x) : Stream.empty()); } + Object sneakyAdder(int[] sneakySum) { + return new Object() { + public int hashCode() { throw new AssertionError(); } + public boolean equals(Object z) { + sneakySum[0] += (int) z; return false; }}; + } + Stream collectionJobs(Collection x) { - String klazz = x.getClass().getSimpleName(); + final String klazz = goodClassName(x.getClass()); return Stream.of( new Job(klazz + " iterate for loop") { public void work() throws Throwable { @@ -345,22 +385,28 @@ public void work() throws Throwable { new Job(klazz + " contains") { public void work() throws Throwable { int[] sum = new int[1]; - Object y = new Object() { - public boolean equals(Object z) { - sum[0] += (int) z; return false; }}; + Object sneakyAdder = sneakyAdder(sum); + for (int i = 0; i < iterations; i++) { + sum[0] = 0; + if (x.contains(sneakyAdder)) throw new AssertionError(); + check.sum(sum[0]);}}}, + new Job(klazz + " containsAll") { + public void work() throws Throwable { + int[] sum = new int[1]; + Collection sneakyAdderCollection = + Collections.singleton(sneakyAdder(sum)); for (int i = 0; i < iterations; i++) { sum[0] = 0; - if (x.contains(y)) throw new AssertionError(); + if (x.containsAll(sneakyAdderCollection)) + throw new AssertionError(); check.sum(sum[0]);}}}, new Job(klazz + " remove(Object)") { public void work() throws Throwable { int[] sum = new int[1]; - Object y = new Object() { - public boolean equals(Object z) { - sum[0] += (int) z; return false; }}; + Object sneakyAdder = sneakyAdder(sum); for (int i = 0; i < iterations; i++) { sum[0] = 0; - if (x.remove(y)) throw new AssertionError(); + if (x.remove(sneakyAdder)) throw new AssertionError(); check.sum(sum[0]);}}}, new Job(klazz + " forEach") { public void work() throws Throwable { @@ -446,7 +492,7 @@ public void work() throws Throwable { } Stream dequeJobs(Deque x) { - String klazz = x.getClass().getSimpleName(); + String klazz = goodClassName(x.getClass()); return Stream.of( new Job(klazz + " descendingIterator() loop") { public void work() throws Throwable { @@ -466,48 +512,50 @@ public void work() throws Throwable { } Stream listJobs(List x) { - String klazz = x.getClass().getSimpleName(); + final String klazz = goodClassName(x.getClass()); return Stream.of( - new Job(klazz + " subList toArray()") { + new Job(klazz + " listIterator forward loop") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + ListIterator it = x.listIterator(); + while (it.hasNext()) + sum += it.next(); + check.sum(sum);}}}, + new Job(klazz + " listIterator backward loop") { public void work() throws Throwable { - int size = x.size(); for (int i = 0; i < iterations; i++) { - int total = Stream.of(x.subList(0, size / 2), - x.subList(size / 2, size)) - .mapToInt(subList -> { - int sum = 0; - for (Object o : subList.toArray()) - sum += (Integer) o; - return sum; }) - .sum(); - check.sum(total);}}}, - new Job(klazz + " subList toArray(a)") { + int sum = 0; + ListIterator it = x.listIterator(x.size()); + while (it.hasPrevious()) + sum += it.previous(); + check.sum(sum);}}}, + new Job(klazz + " indexOf") { public void work() throws Throwable { - int size = x.size(); + int[] sum = new int[1]; + Object sneakyAdder = sneakyAdder(sum); for (int i = 0; i < iterations; i++) { - int total = Stream.of(x.subList(0, size / 2), - x.subList(size / 2, size)) - .mapToInt(subList -> { - int sum = 0; - Integer[] a = new Integer[subList.size()]; - for (Object o : subList.toArray(a)) - sum += (Integer) o; - return sum; }) - .sum(); - check.sum(total);}}}, - new Job(klazz + " subList toArray(empty)") { + sum[0] = 0; + if (x.indexOf(sneakyAdder) != -1) + throw new AssertionError(); + check.sum(sum[0]);}}}, + new Job(klazz + " lastIndexOf") { public void work() throws Throwable { - int size = x.size(); - Integer[] empty = new Integer[0]; + int[] sum = new int[1]; + Object sneakyAdder = sneakyAdder(sum); + for (int i = 0; i < iterations; i++) { + sum[0] = 0; + if (x.lastIndexOf(sneakyAdder) != -1) + throw new AssertionError(); + check.sum(sum[0]);}}}, + new Job(klazz + " replaceAll") { + public void work() throws Throwable { + int[] sum = new int[1]; + UnaryOperator sneakyAdder = + x -> { sum[0] += x; return x; }; for (int i = 0; i < iterations; i++) { - int total = Stream.of(x.subList(0, size / 2), - x.subList(size / 2, size)) - .mapToInt(subList -> { - int sum = 0; - for (Object o : subList.toArray(empty)) - sum += (Integer) o; - return sum; }) - .sum(); - check.sum(total);}}}); + sum[0] = 0; + x.replaceAll(sneakyAdder); + check.sum(sum[0]);}}}); } } diff --git a/test/jdk/java/util/Collection/RemoveMicroBenchmark.java b/test/jdk/java/util/Collection/RemoveMicroBenchmark.java index a9decce621a..989dd0895d3 100644 --- a/test/jdk/java/util/Collection/RemoveMicroBenchmark.java +++ b/test/jdk/java/util/Collection/RemoveMicroBenchmark.java @@ -27,7 +27,7 @@ * @run main RemoveMicroBenchmark iterations=1 size=8 warmup=0 */ -import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toCollection; import java.lang.ref.WeakReference; import java.util.ArrayDeque; @@ -35,6 +35,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Deque; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -47,6 +48,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingQueue; @@ -55,7 +57,7 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; -import java.util.function.Supplier; +import java.util.stream.Stream; /** * Usage: [iterations=N] [size=N] [filter=REGEXP] [warmup=SECONDS] @@ -72,25 +74,38 @@ abstract static class Job { public Job(String name) { this.name = name; } public String name() { return name; } public abstract void work() throws Throwable; + public void run() { + try { work(); } + catch (Throwable ex) { + // current job cannot always be deduced from stacktrace. + throw new RuntimeException("Job failed: " + name(), ex); + } + } } final int iterations; final int size; // number of elements in collections final double warmupSeconds; final long warmupNanos; - final Pattern filter; // select subset of Jobs to run + final Pattern nameFilter; // select subset of Jobs to run final boolean reverse; // reverse order of Jobs final boolean shuffle; // randomize order of Jobs + final ArrayList elements; // contains size random Integers + RemoveMicroBenchmark(String[] args) { iterations = intArg(args, "iterations", 10_000); size = intArg(args, "size", 1000); warmupSeconds = doubleArg(args, "warmup", 7.0); - filter = patternArg(args, "filter"); + nameFilter = patternArg(args, "filter"); reverse = booleanArg(args, "reverse"); shuffle = booleanArg(args, "shuffle"); warmupNanos = (long) (warmupSeconds * (1000L * 1000L * 1000L)); + + elements = ThreadLocalRandom.current().ints(size) + .mapToObj(x -> x) + .collect(toCollection(ArrayList::new)); } // --------------- GC finalization infrastructure --------------- @@ -99,6 +114,7 @@ abstract static class Job { static void forceFullGc() { CountDownLatch finalizeDone = new CountDownLatch(1); WeakReference ref = new WeakReference(new Object() { + @SuppressWarnings("deprecation") protected void finalize() { finalizeDone.countDown(); }}); try { for (int i = 0; i < 10; i++) { @@ -120,7 +136,7 @@ static void forceFullGc() { * compiling everything worth compiling. * Returns array of average times per job per run. */ - long[] time0(List jobs) throws Throwable { + long[] time0(List jobs) { final int size = jobs.size(); long[] nanoss = new long[size]; for (int i = 0; i < size; i++) { @@ -129,7 +145,7 @@ long[] time0(List jobs) throws Throwable { long totalTime; int runs = 0; long startTime = System.nanoTime(); - do { job.work(); runs++; } + do { job.run(); runs++; } while ((totalTime = System.nanoTime() - startTime) < warmupNanos); nanoss[i] = totalTime/runs; } @@ -203,22 +219,11 @@ private static boolean booleanArg(String[] args, String keyword) { throw new IllegalArgumentException(val); } - private static List filter(Pattern filter, List jobs) { - return (filter == null) ? jobs - : jobs.stream() - .filter(job -> filter.matcher(job.name()).find()) - .collect(toList()); - } - private static void deoptimize(int sum) { if (sum == 42) System.out.println("the answer"); } - private static List asSubList(List list) { - return list.subList(0, list.size()); - } - private static Iterable backwards(final List list) { return new Iterable() { public Iterator iterator() { @@ -245,66 +250,99 @@ public static void main(String[] args) throws Throwable { new RemoveMicroBenchmark(args).run(); } - void run() throws Throwable { -// System.out.printf( -// "iterations=%d size=%d, warmup=%1g, filter=\"%s\"%n", -// iterations, size, warmupSeconds, filter); - - final ArrayList al = new ArrayList<>(size); + HashMap, String> goodClassName = new HashMap<>(); + + String goodClassName(Class klazz) { + return goodClassName.computeIfAbsent( + klazz, + k -> { + String simple = k.getSimpleName(); + return (simple.equals("SubList")) // too simple! + ? k.getName().replaceFirst(".*\\.", "") + : simple; + }); + } - // Populate collections with random data + static List makeSubList(List list) { final ThreadLocalRandom rnd = ThreadLocalRandom.current(); - for (int i = 0; i < size; i++) - al.add(rnd.nextInt(size)); - - ArrayList jobs = new ArrayList<>(); - - List.>of( - new ArrayList<>(), - new LinkedList<>(), - new Vector<>(), - new ArrayDeque<>(), - new PriorityQueue<>(), - new ArrayBlockingQueue<>(al.size()), - new ConcurrentLinkedQueue<>(), - new ConcurrentLinkedDeque<>(), - new LinkedBlockingQueue<>(), - new LinkedBlockingDeque<>(), - new LinkedTransferQueue<>(), - new PriorityBlockingQueue<>()).forEach( - x -> { - String klazz = x.getClass().getSimpleName(); - jobs.addAll(collectionJobs(klazz, () -> x, al)); - if (x instanceof Queue) { - Queue queue = (Queue) x; - jobs.addAll(queueJobs(klazz, () -> queue, al)); - } - if (x instanceof Deque) { - Deque deque = (Deque) x; - jobs.addAll(dequeJobs(klazz, () -> deque, al)); - } - if (x instanceof BlockingQueue) { - BlockingQueue q = (BlockingQueue) x; - jobs.addAll(blockingQueueJobs(klazz, () -> q, al)); - } - if (x instanceof BlockingDeque) { - BlockingDeque q = (BlockingDeque) x; - jobs.addAll(blockingDequeJobs(klazz, () -> q, al)); - } - if (x instanceof List) { - List list = (List) x; - jobs.addAll( - collectionJobs( - klazz + " subList", - () -> list.subList(0, x.size()), - al)); - } - }); + int size = rnd.nextInt(4); + for (int i = size; i--> 0; ) + list.add(rnd.nextInt()); + int index = rnd.nextInt(size + 1); + return list.subList(index, index); + } + + private static List asSubList(List list) { + return list.subList(0, list.size()); + } + + @SafeVarargs @SuppressWarnings("varargs") + private Stream concatStreams(Stream ... streams) { + return Stream.of(streams).flatMap(s -> s); + } + + Class topLevelClass(Object x) { + for (Class k = x.getClass();; ) { + Class enclosing = k.getEnclosingClass(); + if (enclosing == null) + return k; + k = enclosing; + } + } + + void run() throws Throwable { + ArrayList jobs = Stream.>of( + new ArrayList<>(), + makeSubList(new ArrayList<>()), + new LinkedList<>(), + makeSubList(new LinkedList<>()), + new Vector<>(), + makeSubList(new Vector<>()), + new CopyOnWriteArrayList<>(), + makeSubList(new CopyOnWriteArrayList<>()), + new ArrayDeque<>(), + new PriorityQueue<>(), + new ArrayBlockingQueue<>(elements.size()), + new ConcurrentLinkedQueue<>(), + new ConcurrentLinkedDeque<>(), + new LinkedBlockingQueue<>(), + new LinkedBlockingDeque<>(), + new LinkedTransferQueue<>(), + new PriorityBlockingQueue<>()) + .flatMap(x -> jobs(x)) + .filter(job -> + nameFilter == null || nameFilter.matcher(job.name()).find()) + .collect(toCollection(ArrayList::new)); if (reverse) Collections.reverse(jobs); if (shuffle) Collections.shuffle(jobs); - time(filter(filter, jobs)); + time(jobs); + } + + Stream jobs(Collection x) { + return concatStreams( + collectionJobs(x), + + (CopyOnWriteArrayList.class.isAssignableFrom(topLevelClass(x))) + ? Stream.empty() + : iteratorRemoveJobs(x), + + (x instanceof Queue) + ? queueJobs((Queue)x) + : Stream.empty(), + + (x instanceof Deque) + ? dequeJobs((Deque)x) + : Stream.empty(), + + (x instanceof BlockingQueue) + ? blockingQueueJobs((BlockingQueue)x) + : Stream.empty(), + + (x instanceof BlockingDeque) + ? blockingDequeJobs((BlockingDeque)x) + : Stream.empty()); } Collection universeRecorder(int[] sum) { @@ -323,75 +361,81 @@ public boolean contains(Object x) { }}; } - List collectionJobs( - String description, - Supplier> supplier, - ArrayList al) { - return List.of( - new Job(description + " removeIf") { + Stream collectionJobs(Collection x) { + final String klazz = goodClassName(x.getClass()); + return Stream.of( + new Job(klazz + " removeIf") { public void work() throws Throwable { - Collection x = supplier.get(); int[] sum = new int[1]; for (int i = 0; i < iterations; i++) { sum[0] = 0; - x.addAll(al); + x.addAll(elements); x.removeIf(n -> { sum[0] += n; return true; }); check.sum(sum[0]);}}}, - new Job(description + " removeIf rnd-two-pass") { + new Job(klazz + " removeIf rnd-two-pass") { public void work() throws Throwable { ThreadLocalRandom rnd = ThreadLocalRandom.current(); - Collection x = supplier.get(); int[] sum = new int[1]; for (int i = 0; i < iterations; i++) { sum[0] = 0; - x.addAll(al); + x.addAll(elements); x.removeIf(n -> { boolean b = rnd.nextBoolean(); if (b) sum[0] += n; return b; }); x.removeIf(n -> { sum[0] += n; return true; }); check.sum(sum[0]);}}}, - new Job(description + " removeAll") { + new Job(klazz + " removeAll") { public void work() throws Throwable { - Collection x = supplier.get(); int[] sum = new int[1]; Collection universe = universeRecorder(sum); for (int i = 0; i < iterations; i++) { sum[0] = 0; - x.addAll(al); + x.addAll(elements); x.removeAll(universe); check.sum(sum[0]);}}}, - new Job(description + " retainAll") { + new Job(klazz + " retainAll") { public void work() throws Throwable { - Collection x = supplier.get(); int[] sum = new int[1]; Collection empty = emptyRecorder(sum); for (int i = 0; i < iterations; i++) { sum[0] = 0; - x.addAll(al); + x.addAll(elements); x.retainAll(empty); check.sum(sum[0]);}}}, - new Job(description + " Iterator.remove") { + new Job(klazz + " clear") { + public void work() throws Throwable { + int[] sum = new int[1]; + for (int i = 0; i < iterations; i++) { + sum[0] = 0; + x.addAll(elements); + x.forEach(e -> sum[0] += e); + x.clear(); + check.sum(sum[0]);}}}); + } + + Stream iteratorRemoveJobs(Collection x) { + final String klazz = goodClassName(x.getClass()); + return Stream.of( + new Job(klazz + " Iterator.remove") { public void work() throws Throwable { - Collection x = supplier.get(); int[] sum = new int[1]; for (int i = 0; i < iterations; i++) { sum[0] = 0; - x.addAll(al); + x.addAll(elements); Iterator it = x.iterator(); while (it.hasNext()) { sum[0] += it.next(); it.remove(); } check.sum(sum[0]);}}}, - new Job(description + " Iterator.remove-rnd-two-pass") { + new Job(klazz + " Iterator.remove-rnd-two-pass") { public void work() throws Throwable { ThreadLocalRandom rnd = ThreadLocalRandom.current(); - Collection x = supplier.get(); int[] sum = new int[1]; for (int i = 0; i < iterations; i++) { sum[0] = 0; - x.addAll(al); + x.addAll(elements); for (Iterator it = x.iterator(); it.hasNext(); ) { Integer e = it.next(); @@ -405,129 +449,103 @@ public void work() throws Throwable { sum[0] += it.next(); it.remove(); } - check.sum(sum[0]);}}}, - new Job(description + " clear") { - public void work() throws Throwable { - Collection x = supplier.get(); - int[] sum = new int[1]; - for (int i = 0; i < iterations; i++) { - sum[0] = 0; - x.addAll(al); - x.forEach(e -> sum[0] += e); - x.clear(); check.sum(sum[0]);}}}); } - List queueJobs( - String description, - Supplier> supplier, - ArrayList al) { - return List.of( - new Job(description + " poll()") { + Stream queueJobs(Queue x) { + final String klazz = goodClassName(x.getClass()); + return Stream.of( + new Job(klazz + " poll()") { public void work() throws Throwable { - Queue x = supplier.get(); int[] sum = new int[1]; for (int i = 0; i < iterations; i++) { sum[0] = 0; - x.addAll(al); + x.addAll(elements); for (Integer e; (e = x.poll()) != null; ) sum[0] += e; check.sum(sum[0]);}}}); } - List dequeJobs( - String description, - Supplier> supplier, - ArrayList al) { - return List.of( - new Job(description + " descendingIterator().remove") { + Stream dequeJobs(Deque x) { + final String klazz = goodClassName(x.getClass()); + return Stream.of( + new Job(klazz + " descendingIterator().remove") { public void work() throws Throwable { - Deque x = supplier.get(); int[] sum = new int[1]; for (int i = 0; i < iterations; i++) { sum[0] = 0; - x.addAll(al); + x.addAll(elements); Iterator it = x.descendingIterator(); while (it.hasNext()) { sum[0] += it.next(); it.remove(); } check.sum(sum[0]);}}}, - new Job(description + " pollFirst()") { + new Job(klazz + " pollFirst()") { public void work() throws Throwable { - Deque x = supplier.get(); int[] sum = new int[1]; for (int i = 0; i < iterations; i++) { sum[0] = 0; - x.addAll(al); + x.addAll(elements); for (Integer e; (e = x.pollFirst()) != null; ) sum[0] += e; check.sum(sum[0]);}}}, - new Job(description + " pollLast()") { + new Job(klazz + " pollLast()") { public void work() throws Throwable { - Deque x = supplier.get(); int[] sum = new int[1]; for (int i = 0; i < iterations; i++) { sum[0] = 0; - x.addAll(al); + x.addAll(elements); for (Integer e; (e = x.pollLast()) != null; ) sum[0] += e; check.sum(sum[0]);}}}); } - List blockingQueueJobs( - String description, - Supplier> supplier, - ArrayList al) { - return List.of( - new Job(description + " drainTo(sink)") { + Stream blockingQueueJobs(BlockingQueue x) { + final String klazz = goodClassName(x.getClass()); + return Stream.of( + new Job(klazz + " drainTo(sink)") { public void work() throws Throwable { - BlockingQueue x = supplier.get(); ArrayList sink = new ArrayList<>(); int[] sum = new int[1]; for (int i = 0; i < iterations; i++) { sum[0] = 0; sink.clear(); - x.addAll(al); + x.addAll(elements); x.drainTo(sink); sink.forEach(e -> sum[0] += e); check.sum(sum[0]);}}}, - new Job(description + " drainTo(sink, n)") { + new Job(klazz + " drainTo(sink, n)") { public void work() throws Throwable { - BlockingQueue x = supplier.get(); ArrayList sink = new ArrayList<>(); int[] sum = new int[1]; for (int i = 0; i < iterations; i++) { sum[0] = 0; sink.clear(); - x.addAll(al); - x.drainTo(sink, al.size()); + x.addAll(elements); + x.drainTo(sink, elements.size()); sink.forEach(e -> sum[0] += e); check.sum(sum[0]);}}}); } - List blockingDequeJobs( - String description, - Supplier> supplier, - ArrayList al) { - return List.of( - new Job(description + " timed pollFirst()") { + Stream blockingDequeJobs(BlockingDeque x) { + final String klazz = goodClassName(x.getClass()); + return Stream.of( + new Job(klazz + " timed pollFirst()") { public void work() throws Throwable { - BlockingDeque x = supplier.get(); int[] sum = new int[1]; for (int i = 0; i < iterations; i++) { sum[0] = 0; - x.addAll(al); + x.addAll(elements); for (Integer e; (e = x.pollFirst(0L, TimeUnit.DAYS)) != null; ) sum[0] += e; check.sum(sum[0]);}}}, - new Job(description + " timed pollLast()") { + new Job(klazz + " timed pollLast()") { public void work() throws Throwable { - BlockingDeque x = supplier.get(); int[] sum = new int[1]; for (int i = 0; i < iterations; i++) { sum[0] = 0; - x.addAll(al); + x.addAll(elements); for (Integer e; (e = x.pollLast(0L, TimeUnit.DAYS)) != null; ) sum[0] += e; check.sum(sum[0]);}}}); diff --git a/test/jdk/java/util/concurrent/tck/Collection8Test.java b/test/jdk/java/util/concurrent/tck/Collection8Test.java index f097b07ccca..7735a55c054 100644 --- a/test/jdk/java/util/concurrent/tck/Collection8Test.java +++ b/test/jdk/java/util/concurrent/tck/Collection8Test.java @@ -35,6 +35,7 @@ import static java.util.concurrent.TimeUnit.HOURS; import static java.util.concurrent.TimeUnit.MILLISECONDS; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -46,6 +47,7 @@ import java.util.List; import java.util.NoSuchElementException; import java.util.Queue; +import java.util.Set; import java.util.Spliterator; import java.util.concurrent.BlockingDeque; import java.util.concurrent.BlockingQueue; @@ -86,8 +88,9 @@ public static Test testSuite(CollectionImplementation impl) { Object bomb() { return new Object() { - public boolean equals(Object x) { throw new AssertionError(); } - public int hashCode() { throw new AssertionError(); } + @Override public boolean equals(Object x) { throw new AssertionError(); } + @Override public int hashCode() { throw new AssertionError(); } + @Override public String toString() { throw new AssertionError(); } }; } @@ -119,6 +122,23 @@ void emptyMeansEmpty(Collection c) throws InterruptedException { assertTrue(c.isEmpty()); assertEquals(0, c.size()); assertEquals("[]", c.toString()); + if (c instanceof List) { + List x = (List) c; + assertEquals(1, x.hashCode()); + assertEquals(x, Collections.emptyList()); + assertEquals(Collections.emptyList(), x); + assertEquals(-1, x.indexOf(impl.makeElement(86))); + assertEquals(-1, x.lastIndexOf(impl.makeElement(99))); + assertThrows( + IndexOutOfBoundsException.class, + () -> x.get(0), + () -> x.set(0, impl.makeElement(42))); + } + else if (c instanceof Set) { + assertEquals(0, c.hashCode()); + assertEquals(c, Collections.emptySet()); + assertEquals(Collections.emptySet(), c); + } { Object[] a = c.toArray(); assertEquals(0, a.length); @@ -279,6 +299,16 @@ public void testNoSuchElementExceptions() { () -> d.pop(), () -> d.descendingIterator().next()); } + if (c instanceof List) { + List x = (List) c; + assertThrows( + NoSuchElementException.class, + () -> x.iterator().next(), + () -> x.listIterator().next(), + () -> x.listIterator(0).next(), + () -> x.listIterator().previous(), + () -> x.listIterator(0).previous()); + } } public void testRemoveIf() { @@ -904,6 +934,31 @@ public void testGetComparator_IllegalStateException() { } } + public void testCollectionCopies() throws Exception { + ThreadLocalRandom rnd = ThreadLocalRandom.current(); + Collection c = impl.emptyCollection(); + for (int n = rnd.nextInt(4); n--> 0; ) + c.add(impl.makeElement(rnd.nextInt())); + assertEquals(c, c); + if (c instanceof List) + assertCollectionsEquals(c, new ArrayList(c)); + else if (c instanceof Set) + assertCollectionsEquals(c, new HashSet(c)); + else if (c instanceof Deque) + assertCollectionsEquivalent(c, new ArrayDeque(c)); + + Collection clone = cloneableClone(c); + if (clone != null) { + assertSame(c.getClass(), clone.getClass()); + assertCollectionsEquivalent(c, clone); + } + try { + Collection serialClone = serialClonePossiblyFailing(c); + assertSame(c.getClass(), serialClone.getClass()); + assertCollectionsEquivalent(c, serialClone); + } catch (java.io.NotSerializableException acceptable) {} + } + // public void testCollection8DebugFail() { // fail(impl.klazz().getSimpleName()); // } diff --git a/test/jdk/java/util/concurrent/tck/CopyOnWriteArrayListTest.java b/test/jdk/java/util/concurrent/tck/CopyOnWriteArrayListTest.java index 52995cff224..d893ba3fbc9 100644 --- a/test/jdk/java/util/concurrent/tck/CopyOnWriteArrayListTest.java +++ b/test/jdk/java/util/concurrent/tck/CopyOnWriteArrayListTest.java @@ -36,12 +36,13 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.NoSuchElementException; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ThreadLocalRandom; import junit.framework.Test; @@ -61,7 +62,12 @@ class Implementation implements CollectionImplementation { } class SubListImplementation extends Implementation { public List emptyCollection() { - return super.emptyCollection().subList(0, 0); + List list = super.emptyCollection(); + ThreadLocalRandom rnd = ThreadLocalRandom.current(); + if (rnd.nextBoolean()) + list.add(makeElement(rnd.nextInt())); + int i = rnd.nextInt(list.size() + 1); + return list.subList(i, i); } } return newTestSuite( @@ -70,67 +76,67 @@ public List emptyCollection() { CollectionTest.testSuite(new SubListImplementation())); } - static CopyOnWriteArrayList populatedArray(int n) { - CopyOnWriteArrayList a = new CopyOnWriteArrayList<>(); - assertTrue(a.isEmpty()); + static CopyOnWriteArrayList populatedList(int n) { + CopyOnWriteArrayList list = new CopyOnWriteArrayList<>(); + assertTrue(list.isEmpty()); for (int i = 0; i < n; i++) - a.add(i); - assertFalse(a.isEmpty()); - assertEquals(n, a.size()); - return a; + list.add(i); + assertEquals(n <= 0, list.isEmpty()); + assertEquals(n, list.size()); + return list; } - static CopyOnWriteArrayList populatedArray(Integer[] elements) { - CopyOnWriteArrayList a = new CopyOnWriteArrayList<>(); - assertTrue(a.isEmpty()); + static CopyOnWriteArrayList populatedList(Integer[] elements) { + CopyOnWriteArrayList list = new CopyOnWriteArrayList<>(); + assertTrue(list.isEmpty()); for (Integer element : elements) - a.add(element); - assertFalse(a.isEmpty()); - assertEquals(elements.length, a.size()); - return a; + list.add(element); + assertFalse(list.isEmpty()); + assertEquals(elements.length, list.size()); + return list; } /** * a new list is empty */ public void testConstructor() { - CopyOnWriteArrayList a = new CopyOnWriteArrayList(); - assertTrue(a.isEmpty()); + List list = new CopyOnWriteArrayList(); + assertTrue(list.isEmpty()); } /** * new list contains all elements of initializing array */ public void testConstructor2() { - Integer[] ints = new Integer[SIZE]; + Integer[] elts = new Integer[SIZE]; for (int i = 0; i < SIZE - 1; ++i) - ints[i] = new Integer(i); - CopyOnWriteArrayList a = new CopyOnWriteArrayList(ints); + elts[i] = i; + List list = new CopyOnWriteArrayList(elts); for (int i = 0; i < SIZE; ++i) - assertEquals(ints[i], a.get(i)); + assertEquals(elts[i], list.get(i)); } /** * new list contains all elements of initializing collection */ public void testConstructor3() { - Integer[] ints = new Integer[SIZE]; + Integer[] elts = new Integer[SIZE]; for (int i = 0; i < SIZE - 1; ++i) - ints[i] = new Integer(i); - CopyOnWriteArrayList a = new CopyOnWriteArrayList(Arrays.asList(ints)); + elts[i] = i; + List list = new CopyOnWriteArrayList(Arrays.asList(elts)); for (int i = 0; i < SIZE; ++i) - assertEquals(ints[i], a.get(i)); + assertEquals(elts[i], list.get(i)); } /** * addAll adds each element from the given collection, including duplicates */ public void testAddAll() { - CopyOnWriteArrayList full = populatedArray(3); - assertTrue(full.addAll(Arrays.asList(three, four, five))); - assertEquals(6, full.size()); - assertTrue(full.addAll(Arrays.asList(three, four, five))); - assertEquals(9, full.size()); + List list = populatedList(3); + assertTrue(list.addAll(Arrays.asList(three, four, five))); + assertEquals(6, list.size()); + assertTrue(list.addAll(Arrays.asList(three, four, five))); + assertEquals(9, list.size()); } /** @@ -138,46 +144,46 @@ public void testAddAll() { * already exist in the List */ public void testAddAllAbsent() { - CopyOnWriteArrayList full = populatedArray(3); + CopyOnWriteArrayList list = populatedList(3); // "one" is duplicate and will not be added - assertEquals(2, full.addAllAbsent(Arrays.asList(three, four, one))); - assertEquals(5, full.size()); - assertEquals(0, full.addAllAbsent(Arrays.asList(three, four, one))); - assertEquals(5, full.size()); + assertEquals(2, list.addAllAbsent(Arrays.asList(three, four, one))); + assertEquals(5, list.size()); + assertEquals(0, list.addAllAbsent(Arrays.asList(three, four, one))); + assertEquals(5, list.size()); } /** * addIfAbsent will not add the element if it already exists in the list */ public void testAddIfAbsent() { - CopyOnWriteArrayList full = populatedArray(SIZE); - full.addIfAbsent(one); - assertEquals(SIZE, full.size()); + CopyOnWriteArrayList list = populatedList(SIZE); + list.addIfAbsent(one); + assertEquals(SIZE, list.size()); } /** * addIfAbsent adds the element when it does not exist in the list */ public void testAddIfAbsent2() { - CopyOnWriteArrayList full = populatedArray(SIZE); - full.addIfAbsent(three); - assertTrue(full.contains(three)); + CopyOnWriteArrayList list = populatedList(SIZE); + list.addIfAbsent(three); + assertTrue(list.contains(three)); } /** * clear removes all elements from the list */ public void testClear() { - CopyOnWriteArrayList full = populatedArray(SIZE); - full.clear(); - assertEquals(0, full.size()); + List list = populatedList(SIZE); + list.clear(); + assertEquals(0, list.size()); } /** * Cloned list is equal */ public void testClone() { - CopyOnWriteArrayList l1 = populatedArray(SIZE); + CopyOnWriteArrayList l1 = populatedList(SIZE); CopyOnWriteArrayList l2 = (CopyOnWriteArrayList)(l1.clone()); assertEquals(l1, l2); l1.clear(); @@ -188,33 +194,33 @@ public void testClone() { * contains is true for added elements */ public void testContains() { - CopyOnWriteArrayList full = populatedArray(3); - assertTrue(full.contains(one)); - assertFalse(full.contains(five)); + List list = populatedList(3); + assertTrue(list.contains(one)); + assertFalse(list.contains(five)); } /** * adding at an index places it in the indicated index */ public void testAddIndex() { - CopyOnWriteArrayList full = populatedArray(3); - full.add(0, m1); - assertEquals(4, full.size()); - assertEquals(m1, full.get(0)); - assertEquals(zero, full.get(1)); + List list = populatedList(3); + list.add(0, m1); + assertEquals(4, list.size()); + assertEquals(m1, list.get(0)); + assertEquals(zero, list.get(1)); - full.add(2, m2); - assertEquals(5, full.size()); - assertEquals(m2, full.get(2)); - assertEquals(two, full.get(4)); + list.add(2, m2); + assertEquals(5, list.size()); + assertEquals(m2, list.get(2)); + assertEquals(two, list.get(4)); } /** * lists with same elements are equal and have same hashCode */ public void testEquals() { - CopyOnWriteArrayList a = populatedArray(3); - CopyOnWriteArrayList b = populatedArray(3); + List a = populatedList(3); + List b = populatedList(3); assertTrue(a.equals(b)); assertTrue(b.equals(a)); assertTrue(a.containsAll(b)); @@ -239,15 +245,15 @@ public void testEquals() { * containsAll returns true for collections with subset of elements */ public void testContainsAll() { - CopyOnWriteArrayList full = populatedArray(3); - assertTrue(full.containsAll(Arrays.asList())); - assertTrue(full.containsAll(Arrays.asList(one))); - assertTrue(full.containsAll(Arrays.asList(one, two))); - assertFalse(full.containsAll(Arrays.asList(one, two, six))); - assertFalse(full.containsAll(Arrays.asList(six))); + List list = populatedList(3); + assertTrue(list.containsAll(Arrays.asList())); + assertTrue(list.containsAll(Arrays.asList(one))); + assertTrue(list.containsAll(Arrays.asList(one, two))); + assertFalse(list.containsAll(Arrays.asList(one, two, six))); + assertFalse(list.containsAll(Arrays.asList(six))); try { - full.containsAll(null); + list.containsAll(null); shouldThrow(); } catch (NullPointerException success) {} } @@ -256,37 +262,81 @@ public void testContainsAll() { * get returns the value at the given index */ public void testGet() { - CopyOnWriteArrayList full = populatedArray(3); - assertEquals(0, full.get(0)); + List list = populatedList(3); + assertEquals(0, list.get(0)); } /** - * indexOf gives the index for the given object + * indexOf(Object) returns the index of the first occurrence of the + * specified element in this list, or -1 if this list does not + * contain the element */ public void testIndexOf() { - CopyOnWriteArrayList full = populatedArray(3); - assertEquals(1, full.indexOf(one)); - assertEquals(-1, full.indexOf("puppies")); + List list = populatedList(3); + assertEquals(-1, list.indexOf(-42)); + int size = list.size(); + for (int i = 0; i < size; i++) { + assertEquals(i, list.indexOf(i)); + assertEquals(i, list.subList(0, size).indexOf(i)); + assertEquals(i, list.subList(0, i + 1).indexOf(i)); + assertEquals(-1, list.subList(0, i).indexOf(i)); + assertEquals(0, list.subList(i, size).indexOf(i)); + assertEquals(-1, list.subList(i + 1, size).indexOf(i)); + } + + list.add(1); + assertEquals(1, list.indexOf(1)); + assertEquals(1, list.subList(0, size + 1).indexOf(1)); + assertEquals(0, list.subList(1, size + 1).indexOf(1)); + assertEquals(size - 2, list.subList(2, size + 1).indexOf(1)); + assertEquals(0, list.subList(size, size + 1).indexOf(1)); + assertEquals(-1, list.subList(size + 1, size + 1).indexOf(1)); } /** - * indexOf gives the index based on the given index - * at which to start searching + * indexOf(E, int) returns the index of the first occurrence of the + * specified element in this list, searching forwards from index, + * or returns -1 if the element is not found */ public void testIndexOf2() { - CopyOnWriteArrayList full = populatedArray(3); - assertEquals(1, full.indexOf(one, 0)); - assertEquals(-1, full.indexOf(one, 2)); + CopyOnWriteArrayList list = populatedList(3); + int size = list.size(); + assertEquals(-1, list.indexOf(-42, 0)); + + // we might expect IOOBE, but spec says otherwise + assertEquals(-1, list.indexOf(0, size)); + assertEquals(-1, list.indexOf(0, Integer.MAX_VALUE)); + + assertThrows( + IndexOutOfBoundsException.class, + () -> list.indexOf(0, -1), + () -> list.indexOf(0, Integer.MIN_VALUE)); + + for (int i = 0; i < size; i++) { + assertEquals(i, list.indexOf(i, 0)); + assertEquals(i, list.indexOf(i, i)); + assertEquals(-1, list.indexOf(i, i + 1)); + } + + list.add(1); + assertEquals(1, list.indexOf(1, 0)); + assertEquals(1, list.indexOf(1, 1)); + assertEquals(size, list.indexOf(1, 2)); + assertEquals(size, list.indexOf(1, size)); } /** * isEmpty returns true when empty, else false */ public void testIsEmpty() { - CopyOnWriteArrayList empty = new CopyOnWriteArrayList(); - CopyOnWriteArrayList full = populatedArray(SIZE); + List empty = new CopyOnWriteArrayList(); assertTrue(empty.isEmpty()); + assertTrue(empty.subList(0, 0).isEmpty()); + + List full = populatedList(SIZE); assertFalse(full.isEmpty()); + assertTrue(full.subList(0, 0).isEmpty()); + assertTrue(full.subList(SIZE, SIZE).isEmpty()); } /** @@ -305,7 +355,7 @@ public void testIterator() { for (int i = 0; i < SIZE; i++) elements[i] = i; shuffle(elements); - Collection full = populatedArray(elements); + Collection full = populatedList(elements); Iterator it = full.iterator(); for (int j = 0; j < SIZE; j++) { @@ -327,8 +377,8 @@ public void testEmptyIterator() { * iterator.remove throws UnsupportedOperationException */ public void testIteratorRemove() { - CopyOnWriteArrayList full = populatedArray(SIZE); - Iterator it = full.iterator(); + CopyOnWriteArrayList list = populatedList(SIZE); + Iterator it = list.iterator(); it.next(); try { it.remove(); @@ -341,42 +391,78 @@ public void testIteratorRemove() { */ public void testToString() { assertEquals("[]", new CopyOnWriteArrayList().toString()); - CopyOnWriteArrayList full = populatedArray(3); - String s = full.toString(); + List list = populatedList(3); + String s = list.toString(); for (int i = 0; i < 3; ++i) assertTrue(s.contains(String.valueOf(i))); - assertEquals(new ArrayList(full).toString(), - full.toString()); + assertEquals(new ArrayList(list).toString(), + list.toString()); } /** - * lastIndexOf returns the index for the given object + * lastIndexOf(Object) returns the index of the last occurrence of + * the specified element in this list, or -1 if this list does not + * contain the element */ public void testLastIndexOf1() { - CopyOnWriteArrayList full = populatedArray(3); - full.add(one); - full.add(three); - assertEquals(3, full.lastIndexOf(one)); - assertEquals(-1, full.lastIndexOf(six)); + List list = populatedList(3); + assertEquals(-1, list.lastIndexOf(-42)); + int size = list.size(); + for (int i = 0; i < size; i++) { + assertEquals(i, list.lastIndexOf(i)); + assertEquals(i, list.subList(0, size).lastIndexOf(i)); + assertEquals(i, list.subList(0, i + 1).lastIndexOf(i)); + assertEquals(-1, list.subList(0, i).lastIndexOf(i)); + assertEquals(0, list.subList(i, size).lastIndexOf(i)); + assertEquals(-1, list.subList(i + 1, size).lastIndexOf(i)); + } + + list.add(1); + assertEquals(size, list.lastIndexOf(1)); + assertEquals(size, list.subList(0, size + 1).lastIndexOf(1)); + assertEquals(1, list.subList(0, size).lastIndexOf(1)); + assertEquals(0, list.subList(1, 2).lastIndexOf(1)); + assertEquals(-1, list.subList(0, 1).indexOf(1)); } /** - * lastIndexOf returns the index from the given starting point + * lastIndexOf(E, int) returns the index of the last occurrence of the + * specified element in this list, searching backwards from index, or + * returns -1 if the element is not found */ public void testLastIndexOf2() { - CopyOnWriteArrayList full = populatedArray(3); - full.add(one); - full.add(three); - assertEquals(3, full.lastIndexOf(one, 4)); - assertEquals(-1, full.lastIndexOf(three, 3)); + CopyOnWriteArrayList list = populatedList(3); + + // we might expect IOOBE, but spec says otherwise + assertEquals(-1, list.lastIndexOf(0, -1)); + + int size = list.size(); + assertThrows( + IndexOutOfBoundsException.class, + () -> list.lastIndexOf(0, size), + () -> list.lastIndexOf(0, Integer.MAX_VALUE)); + + for (int i = 0; i < size; i++) { + assertEquals(i, list.lastIndexOf(i, i)); + assertEquals(list.indexOf(i), list.lastIndexOf(i, i)); + if (i > 0) + assertEquals(-1, list.lastIndexOf(i, i - 1)); + } + list.add(one); + list.add(three); + assertEquals(1, list.lastIndexOf(one, 1)); + assertEquals(1, list.lastIndexOf(one, 2)); + assertEquals(3, list.lastIndexOf(one, 3)); + assertEquals(3, list.lastIndexOf(one, 4)); + assertEquals(-1, list.lastIndexOf(three, 3)); } /** * listIterator traverses all elements */ public void testListIterator1() { - CopyOnWriteArrayList full = populatedArray(SIZE); - ListIterator i = full.listIterator(); + List list = populatedList(SIZE); + ListIterator i = list.listIterator(); int j; for (j = 0; i.hasNext(); j++) assertEquals(j, i.next()); @@ -387,8 +473,8 @@ public void testListIterator1() { * listIterator only returns those elements after the given index */ public void testListIterator2() { - CopyOnWriteArrayList full = populatedArray(3); - ListIterator i = full.listIterator(1); + List list = populatedList(3); + ListIterator i = list.listIterator(1); int j; for (j = 0; i.hasNext(); j++) assertEquals(j + 1, i.next()); @@ -401,10 +487,10 @@ public void testListIterator2() { public void testRemove_int() { int SIZE = 3; for (int i = 0; i < SIZE; i++) { - CopyOnWriteArrayList full = populatedArray(SIZE); - assertEquals(i, full.remove(i)); - assertEquals(SIZE - 1, full.size()); - assertFalse(full.contains(new Integer(i))); + List list = populatedList(SIZE); + assertEquals(i, list.remove(i)); + assertEquals(SIZE - 1, list.size()); + assertFalse(list.contains(new Integer(i))); } } @@ -414,11 +500,11 @@ public void testRemove_int() { public void testRemove_Object() { int SIZE = 3; for (int i = 0; i < SIZE; i++) { - CopyOnWriteArrayList full = populatedArray(SIZE); - assertFalse(full.remove(new Integer(-42))); - assertTrue(full.remove(new Integer(i))); - assertEquals(SIZE - 1, full.size()); - assertFalse(full.contains(new Integer(i))); + List list = populatedList(SIZE); + assertFalse(list.remove(new Integer(-42))); + assertTrue(list.remove(new Integer(i))); + assertEquals(SIZE - 1, list.size()); + assertFalse(list.contains(new Integer(i))); } CopyOnWriteArrayList x = new CopyOnWriteArrayList(Arrays.asList(4, 5, 6)); assertTrue(x.remove(new Integer(6))); @@ -434,30 +520,34 @@ public void testRemove_Object() { * removeAll removes all elements from the given collection */ public void testRemoveAll() { - CopyOnWriteArrayList full = populatedArray(3); - assertTrue(full.removeAll(Arrays.asList(one, two))); - assertEquals(1, full.size()); - assertFalse(full.removeAll(Arrays.asList(one, two))); - assertEquals(1, full.size()); + List list = populatedList(3); + assertTrue(list.removeAll(Arrays.asList(one, two))); + assertEquals(1, list.size()); + assertFalse(list.removeAll(Arrays.asList(one, two))); + assertEquals(1, list.size()); } /** * set changes the element at the given index */ public void testSet() { - CopyOnWriteArrayList full = populatedArray(3); - assertEquals(2, full.set(2, four)); - assertEquals(4, full.get(2)); + List list = populatedList(3); + assertEquals(2, list.set(2, four)); + assertEquals(4, list.get(2)); } /** * size returns the number of elements */ public void testSize() { - CopyOnWriteArrayList empty = new CopyOnWriteArrayList(); - CopyOnWriteArrayList full = populatedArray(SIZE); - assertEquals(SIZE, full.size()); + List empty = new CopyOnWriteArrayList(); assertEquals(0, empty.size()); + assertEquals(0, empty.subList(0, 0).size()); + + List full = populatedList(SIZE); + assertEquals(SIZE, full.size()); + assertEquals(0, full.subList(0, 0).size()); + assertEquals(0, full.subList(SIZE, SIZE).size()); } /** @@ -473,7 +563,7 @@ public void testToArray() { for (int i = 0; i < SIZE; i++) elements[i] = i; shuffle(elements); - Collection full = populatedArray(elements); + Collection full = populatedList(elements); assertTrue(Arrays.equals(elements, full.toArray())); assertSame(Object[].class, full.toArray().getClass()); @@ -501,7 +591,7 @@ public void testToArray2() { for (int i = 0; i < SIZE; i++) elements[i] = i; shuffle(elements); - Collection full = populatedArray(elements); + Collection full = populatedList(elements); Arrays.fill(a, 42); assertTrue(Arrays.equals(elements, full.toArray(a))); @@ -527,7 +617,7 @@ public void testToArray2() { * sublists contains elements at indexes offset from their base */ public void testSubList() { - CopyOnWriteArrayList a = populatedArray(10); + List a = populatedList(10); assertTrue(a.subList(1,1).isEmpty()); for (int j = 0; j < 9; ++j) { for (int i = j ; i < 10; ++i) { @@ -544,6 +634,11 @@ public void testSubList() { assertEquals(a.get(4), m1); s.clear(); assertEquals(7, a.size()); + + assertThrows( + IndexOutOfBoundsException.class, + () -> s.get(0), + () -> s.set(0, 42)); } // Exception tests @@ -553,231 +648,72 @@ public void testSubList() { * can not store the objects inside the list */ public void testToArray_ArrayStoreException() { - CopyOnWriteArrayList c = new CopyOnWriteArrayList(); - c.add("zfasdfsdf"); - c.add("asdadasd"); - try { - c.toArray(new Long[5]); - shouldThrow(); - } catch (ArrayStoreException success) {} - } - - /** - * get throws an IndexOutOfBoundsException on a negative index - */ - public void testGet1_IndexOutOfBoundsException() { - CopyOnWriteArrayList c = populatedArray(5); - List[] lists = { c, c.subList(1, c.size() - 1) }; - for (List list : lists) { - try { - list.get(-1); - shouldThrow(); - } catch (IndexOutOfBoundsException success) {} - } - } - - /** - * get throws an IndexOutOfBoundsException on a too high index - */ - public void testGet2_IndexOutOfBoundsException() { - CopyOnWriteArrayList c = populatedArray(5); - List[] lists = { c, c.subList(1, c.size() - 1) }; - for (List list : lists) { - try { - list.get(list.size()); - shouldThrow(); - } catch (IndexOutOfBoundsException success) {} - } - } - - /** - * set throws an IndexOutOfBoundsException on a negative index - */ - public void testSet1_IndexOutOfBoundsException() { - CopyOnWriteArrayList c = populatedArray(5); - List[] lists = { c, c.subList(1, c.size() - 1) }; - for (List list : lists) { - try { - list.set(-1, "qwerty"); - shouldThrow(); - } catch (IndexOutOfBoundsException success) {} - } - } - - /** - * set throws an IndexOutOfBoundsException on a too high index - */ - public void testSet2() { - CopyOnWriteArrayList c = populatedArray(5); - List[] lists = { c, c.subList(1, c.size() - 1) }; - for (List list : lists) { - try { - list.set(list.size(), "qwerty"); - shouldThrow(); - } catch (IndexOutOfBoundsException success) {} - } - } - - /** - * add throws an IndexOutOfBoundsException on a negative index - */ - public void testAdd1_IndexOutOfBoundsException() { - CopyOnWriteArrayList c = populatedArray(5); - List[] lists = { c, c.subList(1, c.size() - 1) }; - for (List list : lists) { - try { - list.add(-1, "qwerty"); - shouldThrow(); - } catch (IndexOutOfBoundsException success) {} - } - } - - /** - * add throws an IndexOutOfBoundsException on a too high index - */ - public void testAdd2_IndexOutOfBoundsException() { - CopyOnWriteArrayList c = populatedArray(5); - List[] lists = { c, c.subList(1, c.size() - 1) }; - for (List list : lists) { - try { - list.add(list.size() + 1, "qwerty"); - shouldThrow(); - } catch (IndexOutOfBoundsException success) {} - } - } - - /** - * remove throws an IndexOutOfBoundsException on a negative index - */ - public void testRemove1_IndexOutOfBounds() { - CopyOnWriteArrayList c = populatedArray(5); - List[] lists = { c, c.subList(1, c.size() - 1) }; - for (List list : lists) { - try { - list.remove(-1); - shouldThrow(); - } catch (IndexOutOfBoundsException success) {} - } - } - - /** - * remove throws an IndexOutOfBoundsException on a too high index - */ - public void testRemove2_IndexOutOfBounds() { - CopyOnWriteArrayList c = populatedArray(5); - List[] lists = { c, c.subList(1, c.size() - 1) }; - for (List list : lists) { - try { - list.remove(list.size()); - shouldThrow(); - } catch (IndexOutOfBoundsException success) {} - } - } - - /** - * addAll throws an IndexOutOfBoundsException on a negative index - */ - public void testAddAll1_IndexOutOfBoundsException() { - CopyOnWriteArrayList c = populatedArray(5); - List[] lists = { c, c.subList(1, c.size() - 1) }; - for (List list : lists) { - try { - list.addAll(-1, new LinkedList()); - shouldThrow(); - } catch (IndexOutOfBoundsException success) {} - } - } - - /** - * addAll throws an IndexOutOfBoundsException on a too high index - */ - public void testAddAll2_IndexOutOfBoundsException() { - CopyOnWriteArrayList c = populatedArray(5); - List[] lists = { c, c.subList(1, c.size() - 1) }; - for (List list : lists) { - try { - list.addAll(list.size() + 1, new LinkedList()); - shouldThrow(); - } catch (IndexOutOfBoundsException success) {} - } - } - - /** - * listIterator throws an IndexOutOfBoundsException on a negative index - */ - public void testListIterator1_IndexOutOfBoundsException() { - CopyOnWriteArrayList c = populatedArray(5); - List[] lists = { c, c.subList(1, c.size() - 1) }; - for (List list : lists) { - try { - list.listIterator(-1); - shouldThrow(); - } catch (IndexOutOfBoundsException success) {} - } - } - - /** - * listIterator throws an IndexOutOfBoundsException on a too high index - */ - public void testListIterator2_IndexOutOfBoundsException() { - CopyOnWriteArrayList c = populatedArray(5); - List[] lists = { c, c.subList(1, c.size() - 1) }; - for (List list : lists) { - try { - list.listIterator(list.size() + 1); - shouldThrow(); - } catch (IndexOutOfBoundsException success) {} - } - } - - /** - * subList throws an IndexOutOfBoundsException on a negative index - */ - public void testSubList1_IndexOutOfBoundsException() { - CopyOnWriteArrayList c = populatedArray(5); - List[] lists = { c, c.subList(1, c.size() - 1) }; - for (List list : lists) { - try { - list.subList(-1, list.size()); - shouldThrow(); - } catch (IndexOutOfBoundsException success) {} - } - } - - /** - * subList throws an IndexOutOfBoundsException on a too high index - */ - public void testSubList2_IndexOutOfBoundsException() { - CopyOnWriteArrayList c = populatedArray(5); - List[] lists = { c, c.subList(1, c.size() - 1) }; - for (List list : lists) { - try { - list.subList(0, list.size() + 1); - shouldThrow(); - } catch (IndexOutOfBoundsException success) {} - } - } - - /** - * subList throws IndexOutOfBoundsException when the second index - * is lower then the first - */ - public void testSubList3_IndexOutOfBoundsException() { - CopyOnWriteArrayList c = populatedArray(5); - List[] lists = { c, c.subList(1, c.size() - 1) }; - for (List list : lists) { - try { - list.subList(list.size() - 1, 1); - shouldThrow(); - } catch (IndexOutOfBoundsException success) {} - } + List list = new CopyOnWriteArrayList(); + // Integers are not auto-converted to Longs + list.add(86); + list.add(99); + assertThrows( + ArrayStoreException.class, + () -> list.toArray(new Long[0]), + () -> list.toArray(new Long[5])); + } + + void testIndexOutOfBoundsException(List list) { + int size = list.size(); + assertThrows( + IndexOutOfBoundsException.class, + () -> list.get(-1), + () -> list.get(size), + () -> list.set(-1, "qwerty"), + () -> list.set(size, "qwerty"), + () -> list.add(-1, "qwerty"), + () -> list.add(size + 1, "qwerty"), + () -> list.remove(-1), + () -> list.remove(size), + () -> list.addAll(-1, Collections.emptyList()), + () -> list.addAll(size + 1, Collections.emptyList()), + () -> list.listIterator(-1), + () -> list.listIterator(size + 1), + () -> list.subList(-1, size), + () -> list.subList(0, size + 1)); + + // Conversely, operations that must not throw + list.addAll(0, Collections.emptyList()); + list.addAll(size, Collections.emptyList()); + list.add(0, "qwerty"); + list.add(list.size(), "qwerty"); + list.get(0); + list.get(list.size() - 1); + list.set(0, "azerty"); + list.set(list.size() - 1, "azerty"); + list.listIterator(0); + list.listIterator(list.size()); + list.subList(0, list.size()); + list.remove(list.size() - 1); + } + + /** + * IndexOutOfBoundsException is thrown when specified + */ + public void testIndexOutOfBoundsException() { + ThreadLocalRandom rnd = ThreadLocalRandom.current(); + List x = populatedList(rnd.nextInt(5)); + testIndexOutOfBoundsException(x); + + int start = rnd.nextInt(x.size() + 1); + int end = rnd.nextInt(start, x.size() + 1); + assertThrows( + IndexOutOfBoundsException.class, + () -> x.subList(start, start - 1)); + List subList = x.subList(start, end); + testIndexOutOfBoundsException(x); } /** * a deserialized/reserialized list equals original */ public void testSerialization() throws Exception { - List x = populatedArray(SIZE); + List x = populatedList(SIZE); List y = serialClone(x); assertNotSame(x, y); diff --git a/test/jdk/java/util/concurrent/tck/CopyOnWriteArraySetTest.java b/test/jdk/java/util/concurrent/tck/CopyOnWriteArraySetTest.java index c28051a9b68..ad5c3802c69 100644 --- a/test/jdk/java/util/concurrent/tck/CopyOnWriteArraySetTest.java +++ b/test/jdk/java/util/concurrent/tck/CopyOnWriteArraySetTest.java @@ -49,7 +49,16 @@ public static void main(String[] args) { main(suite(), args); } public static Test suite() { - return new TestSuite(CopyOnWriteArraySetTest.class); + class Implementation implements CollectionImplementation { + public Class klazz() { return CopyOnWriteArraySet.class; } + public Set emptyCollection() { return new CopyOnWriteArraySet(); } + public Object makeElement(int i) { return i; } + public boolean isConcurrent() { return true; } + public boolean permitsNulls() { return true; } + } + return newTestSuite( + CopyOnWriteArraySetTest.class, + CollectionTest.testSuite(new Implementation())); } static CopyOnWriteArraySet populatedSet(int n) { diff --git a/test/jdk/java/util/concurrent/tck/JSR166TestCase.java b/test/jdk/java/util/concurrent/tck/JSR166TestCase.java index cb3a41e00ef..c936a3e9e27 100644 --- a/test/jdk/java/util/concurrent/tck/JSR166TestCase.java +++ b/test/jdk/java/util/concurrent/tck/JSR166TestCase.java @@ -93,11 +93,14 @@ import java.util.Collection; import java.util.Collections; import java.util.Date; +import java.util.Deque; import java.util.Enumeration; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.PropertyPermission; +import java.util.Set; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; @@ -475,6 +478,7 @@ public String run() { public static boolean atLeastJava8() { return JAVA_CLASS_VERSION >= 52.0; } public static boolean atLeastJava9() { return JAVA_CLASS_VERSION >= 53.0; } public static boolean atLeastJava10() { return JAVA_CLASS_VERSION >= 54.0; } + public static boolean atLeastJava11() { return JAVA_CLASS_VERSION >= 55.0; } /** * Collects all JSR166 unit tests as one suite. @@ -1473,26 +1477,6 @@ public final void run() { } } - public abstract class RunnableShouldThrow implements Runnable { - protected abstract void realRun() throws Throwable; - - final Class exceptionClass; - - RunnableShouldThrow(Class exceptionClass) { - this.exceptionClass = exceptionClass; - } - - public final void run() { - try { - realRun(); - threadShouldThrow(exceptionClass.getSimpleName()); - } catch (Throwable t) { - if (! exceptionClass.isInstance(t)) - threadUnexpectedException(t); - } - } - } - public abstract class ThreadShouldThrow extends Thread { protected abstract void realRun() throws Throwable; @@ -2098,4 +2082,42 @@ public void rejectedExecution(Runnable r, ThreadPoolExecutor p) { assertEquals(savedCompletedTaskCount, p.getCompletedTaskCount()); assertEquals(savedQueueSize, p.getQueue().size()); } + + void assertCollectionsEquals(Collection x, Collection y) { + assertEquals(x, y); + assertEquals(y, x); + assertEquals(x.isEmpty(), y.isEmpty()); + assertEquals(x.size(), y.size()); + if (x instanceof List) { + assertEquals(x.toString(), y.toString()); + } + if (x instanceof List || x instanceof Set) { + assertEquals(x.hashCode(), y.hashCode()); + } + if (x instanceof List || x instanceof Deque) { + assertTrue(Arrays.equals(x.toArray(), y.toArray())); + assertTrue(Arrays.equals(x.toArray(new Object[0]), + y.toArray(new Object[0]))); + } + } + + /** + * A weaker form of assertCollectionsEquals which does not insist + * that the two collections satisfy Object#equals(Object), since + * they may use identity semantics as Deques do. + */ + void assertCollectionsEquivalent(Collection x, Collection y) { + if (x instanceof List || x instanceof Set) + assertCollectionsEquals(x, y); + else { + assertEquals(x.isEmpty(), y.isEmpty()); + assertEquals(x.size(), y.size()); + assertEquals(new HashSet(x), new HashSet(y)); + if (x instanceof Deque) { + assertTrue(Arrays.equals(x.toArray(), y.toArray())); + assertTrue(Arrays.equals(x.toArray(new Object[0]), + y.toArray(new Object[0]))); + } + } + } } diff --git a/test/jdk/java/util/concurrent/tck/LinkedListTest.java b/test/jdk/java/util/concurrent/tck/LinkedListTest.java index 66dd8c02c7a..80eab3bb1d4 100644 --- a/test/jdk/java/util/concurrent/tck/LinkedListTest.java +++ b/test/jdk/java/util/concurrent/tck/LinkedListTest.java @@ -37,7 +37,9 @@ import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; +import java.util.List; import java.util.NoSuchElementException; +import java.util.concurrent.ThreadLocalRandom; import junit.framework.Test; @@ -49,14 +51,19 @@ public static void main(String[] args) { public static Test suite() { class Implementation implements CollectionImplementation { public Class klazz() { return LinkedList.class; } - public Collection emptyCollection() { return new LinkedList(); } + public List emptyCollection() { return new LinkedList(); } public Object makeElement(int i) { return i; } public boolean isConcurrent() { return false; } public boolean permitsNulls() { return true; } } class SubListImplementation extends Implementation { - public Collection emptyCollection() { - return new LinkedList().subList(0, 0); + public List emptyCollection() { + List list = super.emptyCollection(); + ThreadLocalRandom rnd = ThreadLocalRandom.current(); + if (rnd.nextBoolean()) + list.add(makeElement(rnd.nextInt())); + int i = rnd.nextInt(list.size() + 1); + return list.subList(i, i); } } return newTestSuite( diff --git a/test/jdk/java/util/concurrent/tck/VectorTest.java b/test/jdk/java/util/concurrent/tck/VectorTest.java index 1878a78cc93..dfc6c88c795 100644 --- a/test/jdk/java/util/concurrent/tck/VectorTest.java +++ b/test/jdk/java/util/concurrent/tck/VectorTest.java @@ -32,8 +32,13 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -import java.util.Vector; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Vector; +import java.util.concurrent.ThreadLocalRandom; import junit.framework.Test; @@ -52,7 +57,12 @@ class Implementation implements CollectionImplementation { } class SubListImplementation extends Implementation { public List emptyCollection() { - return super.emptyCollection().subList(0, 0); + List list = super.emptyCollection(); + ThreadLocalRandom rnd = ThreadLocalRandom.current(); + if (rnd.nextBoolean()) + list.add(makeElement(rnd.nextInt())); + int i = rnd.nextInt(list.size() + 1); + return list.subList(i, i); } } return newTestSuite( @@ -61,6 +71,393 @@ public List emptyCollection() { CollectionTest.testSuite(new SubListImplementation())); } + static Vector populatedList(int n) { + Vector list = new Vector<>(); + assertTrue(list.isEmpty()); + for (int i = 0; i < n; i++) + list.add(i); + assertEquals(n <= 0, list.isEmpty()); + assertEquals(n, list.size()); + return list; + } + + /** + * addAll adds each element from the given collection, including duplicates + */ + public void testAddAll() { + List list = populatedList(3); + assertTrue(list.addAll(Arrays.asList(three, four, five))); + assertEquals(6, list.size()); + assertTrue(list.addAll(Arrays.asList(three, four, five))); + assertEquals(9, list.size()); + } + + /** + * clear removes all elements from the list + */ + public void testClear() { + List list = populatedList(SIZE); + list.clear(); + assertEquals(0, list.size()); + } + + /** + * Cloned list is equal + */ + public void testClone() { + Vector l1 = populatedList(SIZE); + Vector l2 = (Vector)(l1.clone()); + assertEquals(l1, l2); + l1.clear(); + assertFalse(l1.equals(l2)); + } + + /** + * contains is true for added elements + */ + public void testContains() { + List list = populatedList(3); + assertTrue(list.contains(one)); + assertFalse(list.contains(five)); + } + + /** + * adding at an index places it in the indicated index + */ + public void testAddIndex() { + List list = populatedList(3); + list.add(0, m1); + assertEquals(4, list.size()); + assertEquals(m1, list.get(0)); + assertEquals(zero, list.get(1)); + + list.add(2, m2); + assertEquals(5, list.size()); + assertEquals(m2, list.get(2)); + assertEquals(two, list.get(4)); + } + + /** + * lists with same elements are equal and have same hashCode + */ + public void testEquals() { + List a = populatedList(3); + List b = populatedList(3); + assertTrue(a.equals(b)); + assertTrue(b.equals(a)); + assertTrue(a.containsAll(b)); + assertTrue(b.containsAll(a)); + assertEquals(a.hashCode(), b.hashCode()); + a.add(m1); + assertFalse(a.equals(b)); + assertFalse(b.equals(a)); + assertTrue(a.containsAll(b)); + assertFalse(b.containsAll(a)); + b.add(m1); + assertTrue(a.equals(b)); + assertTrue(b.equals(a)); + assertTrue(a.containsAll(b)); + assertTrue(b.containsAll(a)); + assertEquals(a.hashCode(), b.hashCode()); + + assertFalse(a.equals(null)); + } + + /** + * containsAll returns true for collections with subset of elements + */ + public void testContainsAll() { + List list = populatedList(3); + assertTrue(list.containsAll(Arrays.asList())); + assertTrue(list.containsAll(Arrays.asList(one))); + assertTrue(list.containsAll(Arrays.asList(one, two))); + assertFalse(list.containsAll(Arrays.asList(one, two, six))); + assertFalse(list.containsAll(Arrays.asList(six))); + + try { + list.containsAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * get returns the value at the given index + */ + public void testGet() { + List list = populatedList(3); + assertEquals(0, list.get(0)); + } + + /** + * indexOf(Object) returns the index of the first occurrence of the + * specified element in this list, or -1 if this list does not + * contain the element + */ + public void testIndexOf() { + List list = populatedList(3); + assertEquals(-1, list.indexOf(-42)); + int size = list.size(); + for (int i = 0; i < size; i++) { + assertEquals(i, list.indexOf(i)); + assertEquals(i, list.subList(0, size).indexOf(i)); + assertEquals(i, list.subList(0, i + 1).indexOf(i)); + assertEquals(-1, list.subList(0, i).indexOf(i)); + assertEquals(0, list.subList(i, size).indexOf(i)); + assertEquals(-1, list.subList(i + 1, size).indexOf(i)); + } + + list.add(1); + assertEquals(1, list.indexOf(1)); + assertEquals(1, list.subList(0, size + 1).indexOf(1)); + assertEquals(0, list.subList(1, size + 1).indexOf(1)); + assertEquals(size - 2, list.subList(2, size + 1).indexOf(1)); + assertEquals(0, list.subList(size, size + 1).indexOf(1)); + assertEquals(-1, list.subList(size + 1, size + 1).indexOf(1)); + } + + /** + * indexOf(E, int) returns the index of the first occurrence of the + * specified element in this list, searching forwards from index, + * or returns -1 if the element is not found + */ + public void testIndexOf2() { + Vector list = populatedList(3); + int size = list.size(); + assertEquals(-1, list.indexOf(-42, 0)); + + // we might expect IOOBE, but spec says otherwise + assertEquals(-1, list.indexOf(0, size)); + assertEquals(-1, list.indexOf(0, Integer.MAX_VALUE)); + + assertThrows( + IndexOutOfBoundsException.class, + () -> list.indexOf(0, -1), + () -> list.indexOf(0, Integer.MIN_VALUE)); + + for (int i = 0; i < size; i++) { + assertEquals(i, list.indexOf(i, 0)); + assertEquals(i, list.indexOf(i, i)); + assertEquals(-1, list.indexOf(i, i + 1)); + } + + list.add(1); + assertEquals(1, list.indexOf(1, 0)); + assertEquals(1, list.indexOf(1, 1)); + assertEquals(size, list.indexOf(1, 2)); + assertEquals(size, list.indexOf(1, size)); + } + + /** + * isEmpty returns true when empty, else false + */ + public void testIsEmpty() { + List empty = new Vector(); + assertTrue(empty.isEmpty()); + assertTrue(empty.subList(0, 0).isEmpty()); + + List full = populatedList(SIZE); + assertFalse(full.isEmpty()); + assertTrue(full.subList(0, 0).isEmpty()); + assertTrue(full.subList(SIZE, SIZE).isEmpty()); + } + + /** + * iterator of empty collection has no elements + */ + public void testEmptyIterator() { + Collection c = new Vector(); + assertIteratorExhausted(c.iterator()); + } + + /** + * lastIndexOf(Object) returns the index of the last occurrence of + * the specified element in this list, or -1 if this list does not + * contain the element + */ + public void testLastIndexOf1() { + List list = populatedList(3); + assertEquals(-1, list.lastIndexOf(-42)); + int size = list.size(); + for (int i = 0; i < size; i++) { + assertEquals(i, list.lastIndexOf(i)); + assertEquals(i, list.subList(0, size).lastIndexOf(i)); + assertEquals(i, list.subList(0, i + 1).lastIndexOf(i)); + assertEquals(-1, list.subList(0, i).lastIndexOf(i)); + assertEquals(0, list.subList(i, size).lastIndexOf(i)); + assertEquals(-1, list.subList(i + 1, size).lastIndexOf(i)); + } + + list.add(1); + assertEquals(size, list.lastIndexOf(1)); + assertEquals(size, list.subList(0, size + 1).lastIndexOf(1)); + assertEquals(1, list.subList(0, size).lastIndexOf(1)); + assertEquals(0, list.subList(1, 2).lastIndexOf(1)); + assertEquals(-1, list.subList(0, 1).indexOf(1)); + } + + /** + * lastIndexOf(E, int) returns the index of the last occurrence of the + * specified element in this list, searching backwards from index, or + * returns -1 if the element is not found + */ + public void testLastIndexOf2() { + Vector list = populatedList(3); + + // we might expect IOOBE, but spec says otherwise + assertEquals(-1, list.lastIndexOf(0, -1)); + + int size = list.size(); + assertThrows( + IndexOutOfBoundsException.class, + () -> list.lastIndexOf(0, size), + () -> list.lastIndexOf(0, Integer.MAX_VALUE)); + + for (int i = 0; i < size; i++) { + assertEquals(i, list.lastIndexOf(i, i)); + assertEquals(list.indexOf(i), list.lastIndexOf(i, i)); + if (i > 0) + assertEquals(-1, list.lastIndexOf(i, i - 1)); + } + list.add(one); + list.add(three); + assertEquals(1, list.lastIndexOf(one, 1)); + assertEquals(1, list.lastIndexOf(one, 2)); + assertEquals(3, list.lastIndexOf(one, 3)); + assertEquals(3, list.lastIndexOf(one, 4)); + assertEquals(-1, list.lastIndexOf(three, 3)); + } + + /** + * size returns the number of elements + */ + public void testSize() { + List empty = new Vector(); + assertEquals(0, empty.size()); + assertEquals(0, empty.subList(0, 0).size()); + + List full = populatedList(SIZE); + assertEquals(SIZE, full.size()); + assertEquals(0, full.subList(0, 0).size()); + assertEquals(0, full.subList(SIZE, SIZE).size()); + } + + /** + * sublists contains elements at indexes offset from their base + */ + public void testSubList() { + List a = populatedList(10); + assertTrue(a.subList(1,1).isEmpty()); + for (int j = 0; j < 9; ++j) { + for (int i = j ; i < 10; ++i) { + List b = a.subList(j,i); + for (int k = j; k < i; ++k) { + assertEquals(new Integer(k), b.get(k-j)); + } + } + } + + List s = a.subList(2, 5); + assertEquals(3, s.size()); + s.set(2, m1); + assertEquals(a.get(4), m1); + s.clear(); + assertEquals(7, a.size()); + + assertThrows( + IndexOutOfBoundsException.class, + () -> s.get(0), + () -> s.set(0, 42)); + } + + /** + * toArray throws an ArrayStoreException when the given array + * can not store the objects inside the list + */ + public void testToArray_ArrayStoreException() { + List list = new Vector(); + // Integers are not auto-converted to Longs + list.add(86); + list.add(99); + assertThrows( + ArrayStoreException.class, + () -> list.toArray(new Long[0]), + () -> list.toArray(new Long[5])); + } + + void testIndexOutOfBoundsException(List list) { + int size = list.size(); + assertThrows( + IndexOutOfBoundsException.class, + () -> list.get(-1), + () -> list.get(size), + () -> list.set(-1, "qwerty"), + () -> list.set(size, "qwerty"), + () -> list.add(-1, "qwerty"), + () -> list.add(size + 1, "qwerty"), + () -> list.remove(-1), + () -> list.remove(size), + () -> list.addAll(-1, Collections.emptyList()), + () -> list.addAll(size + 1, Collections.emptyList()), + () -> list.listIterator(-1), + () -> list.listIterator(size + 1), + () -> list.subList(-1, size), + () -> list.subList(0, size + 1)); + + // Conversely, operations that must not throw + list.addAll(0, Collections.emptyList()); + list.addAll(size, Collections.emptyList()); + list.add(0, "qwerty"); + list.add(list.size(), "qwerty"); + list.get(0); + list.get(list.size() - 1); + list.set(0, "azerty"); + list.set(list.size() - 1, "azerty"); + list.listIterator(0); + list.listIterator(list.size()); + list.subList(0, list.size()); + list.remove(list.size() - 1); + } + + /** + * IndexOutOfBoundsException is thrown when specified + */ + public void testIndexOutOfBoundsException() { + ThreadLocalRandom rnd = ThreadLocalRandom.current(); + List x = populatedList(rnd.nextInt(5)); + testIndexOutOfBoundsException(x); + + int start = rnd.nextInt(x.size() + 1); + int end = rnd.nextInt(start, x.size() + 1); + + // Vector#subList spec deviates slightly from List#subList spec + assertThrows( + IllegalArgumentException.class, + () -> x.subList(start, start - 1)); + + List subList = x.subList(start, end); + testIndexOutOfBoundsException(x); + } + + /** + * a deserialized/reserialized list equals original + */ + public void testSerialization() throws Exception { + List x = populatedList(SIZE); + List y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x.toString(), y.toString()); + assertTrue(Arrays.equals(x.toArray(), y.toArray())); + assertEquals(x, y); + assertEquals(y, x); + while (!x.isEmpty()) { + assertFalse(y.isEmpty()); + assertEquals(x.remove(0), y.remove(0)); + } + assertTrue(y.isEmpty()); + } + /** * tests for setSize() */ From 2e5767b374a2aedf7e4351bfefc8e19bb49d5238 Mon Sep 17 00:00:00 2001 From: dl Date: Tue, 10 Apr 2018 11:37:18 -0700 Subject: [PATCH 123/196] 8197531: Miscellaneous changes imported from jsr166 CVS 2018-04 Reviewed-by: martin, psandoz --- .../share/classes/java/util/ArrayDeque.java | 8 +- .../util/concurrent/CompletableFuture.java | 2 +- .../util/concurrent/ConcurrentHashMap.java | 2 +- .../concurrent/ConcurrentLinkedDeque.java | 2 +- .../concurrent/ConcurrentLinkedQueue.java | 2 +- .../concurrent/ConcurrentSkipListMap.java | 2 +- .../util/concurrent/CountedCompleter.java | 2 +- .../java/util/concurrent/Exchanger.java | 2 +- .../java/util/concurrent/ForkJoinTask.java | 2 +- .../java/util/concurrent/FutureTask.java | 2 +- .../util/concurrent/LinkedTransferQueue.java | 2 +- .../classes/java/util/concurrent/Phaser.java | 2 +- .../concurrent/PriorityBlockingQueue.java | 2 +- .../util/concurrent/SubmissionPublisher.java | 6 +- .../util/concurrent/SynchronousQueue.java | 8 +- .../util/concurrent/atomic/AtomicBoolean.java | 2 +- .../atomic/AtomicMarkableReference.java | 2 +- .../concurrent/atomic/AtomicReference.java | 2 +- .../atomic/AtomicStampedReference.java | 2 +- .../util/concurrent/atomic/Striped64.java | 6 +- .../locks/AbstractQueuedLongSynchronizer.java | 2 +- .../locks/AbstractQueuedSynchronizer.java | 4 +- .../util/concurrent/locks/StampedLock.java | 2 +- .../ConcurrentHashMap/WhiteBox.java | 155 ++++++++++++++++++ .../ConcurrentLinkedQueue/WhiteBox.java | 1 + .../Executors/PrivilegedCallables.java | 3 +- .../LinkedTransferQueue/WhiteBox.java | 1 + 27 files changed, 194 insertions(+), 34 deletions(-) create mode 100644 test/jdk/java/util/concurrent/ConcurrentHashMap/WhiteBox.java diff --git a/src/java.base/share/classes/java/util/ArrayDeque.java b/src/java.base/share/classes/java/util/ArrayDeque.java index f9dbf3fa6da..f4307f680c2 100644 --- a/src/java.base/share/classes/java/util/ArrayDeque.java +++ b/src/java.base/share/classes/java/util/ArrayDeque.java @@ -208,7 +208,7 @@ public ArrayDeque(int numElements) { */ public ArrayDeque(Collection c) { this(c.size()); - addAll(c); + copyElements(c); } /** @@ -322,10 +322,14 @@ public boolean addAll(Collection c) { final int s, needed; if ((needed = (s = size()) + c.size() + 1 - elements.length) > 0) grow(needed); - c.forEach(this::addLast); + copyElements(c); return size() > s; } + private void copyElements(Collection c) { + c.forEach(this::addLast); + } + /** * Inserts the specified element at the front of this deque. * diff --git a/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java b/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java index 66266827260..4c8e9b159fc 100644 --- a/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java +++ b/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java @@ -2883,7 +2883,7 @@ static final class MinimalStage extends CompletableFuture { STACK = l.findVarHandle(CompletableFuture.class, "stack", Completion.class); NEXT = l.findVarHandle(Completion.class, "next", Completion.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } // Reduce the risk of rare disastrous classloading in first call to diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java index 35672a7f172..0a0ac3eef5f 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java @@ -6383,7 +6383,7 @@ public final void compute() { ABASE = U.arrayBaseOffset(Node[].class); int scale = U.arrayIndexScale(Node[].class); if ((scale & (scale - 1)) != 0) - throw new Error("array index scale not a power of two"); + throw new ExceptionInInitializerError("array index scale not a power of two"); ASHIFT = 31 - Integer.numberOfLeadingZeros(scale); // Reduce the risk of rare disastrous classloading in first call to diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java index 0d7a0ebb159..91ddabde3cc 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java @@ -1671,7 +1671,7 @@ public void forEach(Consumer action) { NEXT = l.findVarHandle(Node.class, "next", Node.class); ITEM = l.findVarHandle(Node.class, "item", Object.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } } diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java index 701806e848e..eac8ee7d113 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java @@ -1069,7 +1069,7 @@ public void forEach(Consumer action) { ITEM = l.findVarHandle(Node.class, "item", Object.class); NEXT = l.findVarHandle(Node.class, "next", Node.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } } diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java index 822dde81df3..8b179db6932 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java @@ -3412,7 +3412,7 @@ final EntrySpliterator entrySpliterator() { VAL = l.findVarHandle(Node.class, "val", Object.class); RIGHT = l.findVarHandle(Index.class, "right", Index.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } } diff --git a/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java b/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java index 9321ccfbfb0..a91d12dfea0 100644 --- a/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java +++ b/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java @@ -775,7 +775,7 @@ protected void setRawResult(T t) { } PENDING = l.findVarHandle(CountedCompleter.class, "pending", int.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } } diff --git a/src/java.base/share/classes/java/util/concurrent/Exchanger.java b/src/java.base/share/classes/java/util/concurrent/Exchanger.java index e7baf4d5a9f..925bf0d2071 100644 --- a/src/java.base/share/classes/java/util/concurrent/Exchanger.java +++ b/src/java.base/share/classes/java/util/concurrent/Exchanger.java @@ -641,7 +641,7 @@ public V exchange(V x, long timeout, TimeUnit unit) MATCH = l.findVarHandle(Node.class, "match", Object.class); AA = MethodHandles.arrayElementVarHandle(Node[].class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } diff --git a/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java b/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java index e4e3aa8f934..b388992dad5 100644 --- a/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java +++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java @@ -1540,7 +1540,7 @@ private void readObject(java.io.ObjectInputStream s) MethodHandles.Lookup l = MethodHandles.lookup(); STATUS = l.findVarHandle(ForkJoinTask.class, "status", int.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } diff --git a/src/java.base/share/classes/java/util/concurrent/FutureTask.java b/src/java.base/share/classes/java/util/concurrent/FutureTask.java index ec644a7aaae..e913ef32a2d 100644 --- a/src/java.base/share/classes/java/util/concurrent/FutureTask.java +++ b/src/java.base/share/classes/java/util/concurrent/FutureTask.java @@ -526,7 +526,7 @@ public String toString() { RUNNER = l.findVarHandle(FutureTask.class, "runner", Thread.class); WAITERS = l.findVarHandle(FutureTask.class, "waiters", WaitNode.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } // Reduce the risk of rare disastrous classloading in first call to diff --git a/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java b/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java index 5522f7b401b..06d04e22e6c 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java @@ -1739,7 +1739,7 @@ public void forEach(Consumer action) { NEXT = l.findVarHandle(Node.class, "next", Node.class); WAITER = l.findVarHandle(Node.class, "waiter", Thread.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } // Reduce the risk of rare disastrous classloading in first call to diff --git a/src/java.base/share/classes/java/util/concurrent/Phaser.java b/src/java.base/share/classes/java/util/concurrent/Phaser.java index 4af4b8b6da2..d878e45c353 100644 --- a/src/java.base/share/classes/java/util/concurrent/Phaser.java +++ b/src/java.base/share/classes/java/util/concurrent/Phaser.java @@ -1137,7 +1137,7 @@ public boolean block() { MethodHandles.Lookup l = MethodHandles.lookup(); STATE = l.findVarHandle(Phaser.class, "state", long.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } // Reduce the risk of rare disastrous classloading in first call to diff --git a/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java b/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java index 388c75d36fd..8a362274749 100644 --- a/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java @@ -1014,7 +1014,7 @@ public Spliterator spliterator() { "allocationSpinLock", int.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } } diff --git a/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java b/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java index 8fd33c69d32..9efb01d1a0d 100644 --- a/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java +++ b/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java @@ -1096,7 +1096,7 @@ final int offer(T item, boolean unowned) { if (cap > 0) { boolean added; if (n >= cap && cap < maxCapacity) // resize - added = growAndoffer(item, a, t); + added = growAndOffer(item, a, t); else if (n >= cap || unowned) // need volatile CAS added = QA.compareAndSet(a, i, null, item); else { // can use release mode @@ -1115,7 +1115,7 @@ else if (n >= cap || unowned) // need volatile CAS * Tries to expand buffer and add item, returning true on * success. Currently fails only if out of memory. */ - final boolean growAndoffer(T item, Object[] a, int t) { + final boolean growAndOffer(T item, Object[] a, int t) { int cap = 0, newCap = 0; Object[] newArray = null; if (a != null && (cap = a.length) > 0 && (newCap = cap << 1) > 0) { @@ -1466,7 +1466,7 @@ else if (timed) long.class); QA = MethodHandles.arrayElementVarHandle(Object[].class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } // Reduce the risk of rare disastrous classloading in first call to diff --git a/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java b/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java index 7f9c7375495..8de28b87987 100644 --- a/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java +++ b/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java @@ -293,7 +293,7 @@ boolean isCancelled() { SMATCH = l.findVarHandle(SNode.class, "match", SNode.class); SNEXT = l.findVarHandle(SNode.class, "next", SNode.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } } @@ -516,7 +516,7 @@ void clean(SNode s) { MethodHandles.Lookup l = MethodHandles.lookup(); SHEAD = l.findVarHandle(TransferStack.class, "head", SNode.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } } @@ -583,7 +583,7 @@ boolean isOffList() { QITEM = l.findVarHandle(QNode.class, "item", Object.class); QNEXT = l.findVarHandle(QNode.class, "next", QNode.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } } @@ -830,7 +830,7 @@ void clean(QNode pred, QNode s) { QCLEANME = l.findVarHandle(TransferQueue.class, "cleanMe", QNode.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } } diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java index 1284e00afb7..9e2acf5535c 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java @@ -56,7 +56,7 @@ public class AtomicBoolean implements java.io.Serializable { MethodHandles.Lookup l = MethodHandles.lookup(); VALUE = l.findVarHandle(AtomicBoolean.class, "value", int.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java index 367808c7192..51ea84c55ae 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java @@ -199,7 +199,7 @@ public boolean attemptMark(V expectedReference, boolean newMark) { PAIR = l.findVarHandle(AtomicMarkableReference.class, "pair", Pair.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java index db1d483b5ae..70832ff4720 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java @@ -56,7 +56,7 @@ public class AtomicReference implements java.io.Serializable { MethodHandles.Lookup l = MethodHandles.lookup(); VALUE = l.findVarHandle(AtomicReference.class, "value", Object.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java index f031fe81d81..47b7c7ba2ec 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java @@ -199,7 +199,7 @@ public boolean attemptStamp(V expectedReference, int newStamp) { PAIR = l.findVarHandle(AtomicStampedReference.class, "pair", Pair.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java b/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java index ddb1e53a3d0..9c21fa36e5a 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java @@ -144,7 +144,7 @@ final long getAndSet(long val) { MethodHandles.Lookup l = MethodHandles.lookup(); VALUE = l.findVarHandle(Cell.class, "value", long.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } } @@ -396,13 +396,13 @@ public MethodHandles.Lookup run() { try { return MethodHandles.privateLookupIn(Thread.class, MethodHandles.lookup()); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } }}); THREAD_PROBE = l.findVarHandle(Thread.class, "threadLocalRandomProbe", int.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } diff --git a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java index e7aae9ce86f..5ed57718eed 100644 --- a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java +++ b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java @@ -1830,7 +1830,7 @@ protected final Collection getWaitingThreads() { HEAD = l.findVarHandle(AbstractQueuedLongSynchronizer.class, "head", Node.class); TAIL = l.findVarHandle(AbstractQueuedLongSynchronizer.class, "tail", Node.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } // Reduce the risk of rare disastrous classloading in first call to diff --git a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java index ce701cf0bb4..4ecfff00f86 100644 --- a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java +++ b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java @@ -555,7 +555,7 @@ final void setPrevRelaxed(Node p) { THREAD = l.findVarHandle(Node.class, "thread", Thread.class); WAITSTATUS = l.findVarHandle(Node.class, "waitStatus", int.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } } @@ -2308,7 +2308,7 @@ protected final Collection getWaitingThreads() { HEAD = l.findVarHandle(AbstractQueuedSynchronizer.class, "head", Node.class); TAIL = l.findVarHandle(AbstractQueuedSynchronizer.class, "tail", Node.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } // Reduce the risk of rare disastrous classloading in first call to diff --git a/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java b/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java index 36a8c5a9849..c06847fc267 100644 --- a/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java +++ b/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java @@ -1614,7 +1614,7 @@ private long cancelWaiter(WNode node, WNode group, boolean interrupted) { WNEXT = l.findVarHandle(WNode.class, "next", WNode.class); WCOWAIT = l.findVarHandle(WNode.class, "cowait", WNode.class); } catch (ReflectiveOperationException e) { - throw new Error(e); + throw new ExceptionInInitializerError(e); } } } diff --git a/test/jdk/java/util/concurrent/ConcurrentHashMap/WhiteBox.java b/test/jdk/java/util/concurrent/ConcurrentHashMap/WhiteBox.java new file mode 100644 index 00000000000..e460e835da7 --- /dev/null +++ b/test/jdk/java/util/concurrent/ConcurrentHashMap/WhiteBox.java @@ -0,0 +1,155 @@ +/* + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Martin Buchholz with assistance from members of JCP + * JSR-166 Expert Group and released to the public domain, as + * explained at http://creativecommons.org/publicdomain/zero/1.0/ + */ + +/* + * @test + * @modules java.base/java.util.concurrent:open + * @run testng WhiteBox + * @summary White box tests of implementation details + */ + +import static org.testng.Assert.*; +import org.testng.annotations.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ThreadLocalRandom; + +@Test +public class WhiteBox { + final ThreadLocalRandom rnd = ThreadLocalRandom.current(); + final VarHandle TABLE, NEXTTABLE, SIZECTL; + + WhiteBox() throws ReflectiveOperationException { + Class mClass = ConcurrentHashMap.class; + String nodeClassName = mClass.getName() + "$Node"; + Class nodeClass = Class.forName(nodeClassName); + Class nodeArrayClass = Class.forName("[L" + nodeClassName + ";"); + MethodHandles.Lookup lookup + = MethodHandles.privateLookupIn(mClass, MethodHandles.lookup()); + TABLE = lookup.findVarHandle(mClass, "table", nodeArrayClass); + NEXTTABLE = lookup.findVarHandle(mClass, "nextTable", nodeArrayClass); + SIZECTL = lookup.findVarHandle(mClass, "sizeCtl", int.class); + } + + Object[] table(ConcurrentHashMap m) { return (Object[]) TABLE.getVolatile(m); } + Object[] nextTable(ConcurrentHashMap m) { return (Object[]) NEXTTABLE.getVolatile(m); } + int sizeCtl(ConcurrentHashMap m) { return (int) SIZECTL.getVolatile(m); } + + @Test + public void defaultConstructor() { + ConcurrentHashMap m = new ConcurrentHashMap(); + assertNull(table(m)); + assertEquals(sizeCtl(m), 0); + assertResizeNotInProgress(m); + } + + @Test + public void shouldNotResizeWhenInitialCapacityProvided() { + int initialCapacity = rnd.nextInt(1, 100); + Object[] initialTable = null; + ConcurrentHashMap m = new ConcurrentHashMap(initialCapacity); + + // table is lazily initialized + assertNull(table(m)); + int expectedInitialTableLength = sizeCtl(m); + + assertInvariants(m); + for (int i = 0; i < initialCapacity; i++) { + m.put(i * 100 + rnd.nextInt(100), i); + if (i == 0) + initialTable = table(m); + else + assertSame(table(m), initialTable); + assertInvariants(m); + } + assertEquals(initialTable.length, expectedInitialTableLength); + } + + byte[] serialBytes(Object o) { + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(o); + oos.flush(); + oos.close(); + return bos.toByteArray(); + } catch (Exception fail) { + throw new AssertionError(fail); + } + } + + @SuppressWarnings("unchecked") + T serialClone(T o) { + try { + ObjectInputStream ois = new ObjectInputStream + (new ByteArrayInputStream(serialBytes(o))); + T clone = (T) ois.readObject(); + assertNotSame(o, clone); + assertSame(o.getClass(), clone.getClass()); + return clone; + } catch (Exception fail) { + throw new AssertionError(fail); + } + } + + @Test + public void testSerialization() { + assertInvariants(serialClone(new ConcurrentHashMap())); + + ConcurrentHashMap m = new ConcurrentHashMap(rnd.nextInt(100)); + m.put(1, 1); + ConcurrentHashMap clone = serialClone(m); + assertInvariants(clone); + assertNotSame(table(m), table(clone)); + assertEquals(m, clone); + assertResizeNotInProgress(m); + assertResizeNotInProgress(clone); + } + + /** Checks conditions which should always be true. */ + void assertInvariants(ConcurrentHashMap m) { + if (!m.isEmpty()) + assertNotNull(table(m)); + } + + void assertResizeNotInProgress(ConcurrentHashMap m) { + assertTrue(sizeCtl(m) >= 0); + assertNull(nextTable(m)); + } +} diff --git a/test/jdk/java/util/concurrent/ConcurrentLinkedQueue/WhiteBox.java b/test/jdk/java/util/concurrent/ConcurrentLinkedQueue/WhiteBox.java index 225bfb0297a..63fd29a8a9a 100644 --- a/test/jdk/java/util/concurrent/ConcurrentLinkedQueue/WhiteBox.java +++ b/test/jdk/java/util/concurrent/ConcurrentLinkedQueue/WhiteBox.java @@ -338,6 +338,7 @@ T serialClone(T o) { } } + @Test public void testSerialization() { ConcurrentLinkedQueue q = serialClone(new ConcurrentLinkedQueue()); assertInvariants(q); diff --git a/test/jdk/java/util/concurrent/Executors/PrivilegedCallables.java b/test/jdk/java/util/concurrent/Executors/PrivilegedCallables.java index 9119a20328f..d5a47f2877e 100644 --- a/test/jdk/java/util/concurrent/Executors/PrivilegedCallables.java +++ b/test/jdk/java/util/concurrent/Executors/PrivilegedCallables.java @@ -101,8 +101,7 @@ void test(String[] args) { final Policy policy = new Policy(); Policy.setPolicy(policy); policy.setPermissions(new RuntimePermission("getClassLoader"), - new RuntimePermission("setContextClassLoader"), - new RuntimePermission("stopThread")); + new RuntimePermission("setContextClassLoader")); System.setSecurityManager(new SecurityManager()); testPrivileged(); diff --git a/test/jdk/java/util/concurrent/LinkedTransferQueue/WhiteBox.java b/test/jdk/java/util/concurrent/LinkedTransferQueue/WhiteBox.java index a7b30b95e3a..e1e4607813d 100644 --- a/test/jdk/java/util/concurrent/LinkedTransferQueue/WhiteBox.java +++ b/test/jdk/java/util/concurrent/LinkedTransferQueue/WhiteBox.java @@ -361,6 +361,7 @@ T serialClone(T o) { } } + @Test public void testSerialization() { LinkedTransferQueue q = serialClone(new LinkedTransferQueue()); assertInvariants(q); From 5bcb2301e8e92db2797e9378ee0104fdcfe4c65a Mon Sep 17 00:00:00 2001 From: ccheung Date: Tue, 10 Apr 2018 11:43:40 -0700 Subject: [PATCH 124/196] 8194812: Extend class-data sharing to support the module path 8199360: Rework the support for the 'ignored' module options in CDS Reviewed-by: jiangli, lfoltan, iklam, mseledtsov --- .../jtreg/runtime/appcds/JarBuilder.java | 36 +++- .../jtreg/runtime/appcds/TestCommon.java | 19 +- .../CheckUnsupportedDumpingOptions.java | 37 +--- .../appcds/jigsaw/JigsawOptionsCombo.java | 45 +++-- .../jigsaw/PatchModule/AppClassInCP.java | 8 +- .../jigsaw/PatchModule/CustomPackage.java | 5 +- .../PatchModule/MismatchedPatchModule.java | 52 +---- .../appcds/jigsaw/PatchModule/PatchDir.java | 6 +- .../jigsaw/PatchModule/PatchJavaBase.java | 3 +- .../appcds/jigsaw/PatchModule/Simple.java | 7 +- .../PatchModule/SubClassOfPatchedClass.java | 7 +- .../appcds/jigsaw/PatchModule/TwoJars.java | 5 +- .../classpathtests/BootAppendTests.java | 71 +++---- .../EmptyClassInBootClassPath.java | 6 +- .../jigsaw/limitmods/LimitModsHelper.java | 23 ++- .../jigsaw/limitmods/LimitModsTests.java | 10 +- .../appcds/jigsaw/modulepath/AddModules.java | 137 +++++++++++++ .../appcds/jigsaw/modulepath/AddOpens.java | 110 +++++++++++ .../appcds/jigsaw/modulepath/AddReads.java | 143 ++++++++++++++ .../jigsaw/modulepath/ExportModule.java | 164 +++++++++++++++ .../jigsaw/modulepath/JvmtiAddPath.java | 156 +++++++++++++++ .../jigsaw/modulepath/MainModuleOnly.java | 177 +++++++++++++++++ .../jigsaw/modulepath/ModulePathAndCP.java | 186 ++++++++++++++++++ .../src/com.greetings/com/greetings/Main.java | 31 +++ .../src/com.greetings/module-info.java | 27 +++ .../src/com.hello/com/hello/Main.java | 31 +++ .../modulepath/src/com.hello/module-info.java | 27 +++ .../src/com.nomodule/com/nomodule/Main.java | 31 +++ .../com.norequires/com/norequires/Main.java | 31 +++ .../src/com.norequires/module-info.java | 25 +++ .../src/com.simple/com/simple/Main.java | 39 ++++ .../src/com.simple/module-info.java | 26 +++ .../modulepath/src/org.astro/module-info.java | 27 +++ .../src/org.astro/org/astro/World.java | 30 +++ .../runtime/appcds/test-classes/JvmtiApp.java | 41 ++-- .../modules/PatchModule/PatchModuleCDS.java | 11 +- test/lib/jdk/test/lib/cds/CDSTestUtils.java | 25 ++- 37 files changed, 1625 insertions(+), 190 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddModules.java create mode 100644 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddOpens.java create mode 100644 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddReads.java create mode 100644 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/ExportModule.java create mode 100644 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/JvmtiAddPath.java create mode 100644 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/MainModuleOnly.java create mode 100644 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/ModulePathAndCP.java create mode 100644 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.greetings/com/greetings/Main.java create mode 100644 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.greetings/module-info.java create mode 100644 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.hello/com/hello/Main.java create mode 100644 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.hello/module-info.java create mode 100644 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.nomodule/com/nomodule/Main.java create mode 100644 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.norequires/com/norequires/Main.java create mode 100644 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.norequires/module-info.java create mode 100644 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.simple/com/simple/Main.java create mode 100644 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.simple/module-info.java create mode 100644 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/org.astro/module-info.java create mode 100644 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/org.astro/org/astro/World.java diff --git a/test/hotspot/jtreg/runtime/appcds/JarBuilder.java b/test/hotspot/jtreg/runtime/appcds/JarBuilder.java index bb3921e7281..d96b6efb8be 100644 --- a/test/hotspot/jtreg/runtime/appcds/JarBuilder.java +++ b/test/hotspot/jtreg/runtime/appcds/JarBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, 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,9 +32,11 @@ */ import jdk.test.lib.JDKToolFinder; +import jdk.test.lib.compiler.CompilerUtils; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; import java.io.File; +import java.nio.file.Path; import java.util.ArrayList; import sun.tools.jar.Main; @@ -145,6 +147,21 @@ private static void addClassArgs(ArrayList args, String jarclassDir, } } + public static void createModularJar(String jarPath, + String classesDir, + String mainClass) throws Exception { + ArrayList argList = new ArrayList(); + argList.add("--create"); + argList.add("--file=" + jarPath); + if (mainClass != null) { + argList.add("--main-class=" + mainClass); + } + argList.add("-C"); + argList.add(classesDir); + argList.add("."); + createJar(argList); + } + private static void createJar(ArrayList args) { if (DEBUG) printIterable("createJar args: ", args); @@ -190,6 +207,23 @@ public static void compile(String dstPath, String source, String... extraArgs) t output.shouldHaveExitValue(0); } + public static void compileModule(Path src, + Path dest, + String modulePathArg // arg to --module-path + ) throws Exception { + boolean compiled = false; + if (modulePathArg == null) { + compiled = CompilerUtils.compile(src, dest); + } else { + compiled = CompilerUtils.compile(src, dest, + "--module-path", modulePathArg); + } + if (!compiled) { + throw new RuntimeException("module did not compile"); + } + } + + public static void signJar() throws Exception { String keyTool = JDKToolFinder.getJDKTool("keytool"); String jarSigner = JDKToolFinder.getJDKTool("jarsigner"); diff --git a/test/hotspot/jtreg/runtime/appcds/TestCommon.java b/test/hotspot/jtreg/runtime/appcds/TestCommon.java index 2c2cdb6db55..bee1e4a9c0a 100644 --- a/test/hotspot/jtreg/runtime/appcds/TestCommon.java +++ b/test/hotspot/jtreg/runtime/appcds/TestCommon.java @@ -200,13 +200,18 @@ public static Result run(String... suffix) throws Exception { return new Result(opts, runWithArchive(opts)); } - public static OutputAnalyzer exec(String appJar, String... suffix) throws Exception { AppCDSOptions opts = (new AppCDSOptions()).setAppJar(appJar); opts.addSuffix(suffix); return runWithArchive(opts); } + public static Result runWithModules(String prefix[], String upgrademodulepath, String modulepath, + String mid, String... testClassArgs) throws Exception { + AppCDSOptions opts = makeModuleOptions(prefix, upgrademodulepath, modulepath, + mid, testClassArgs); + return new Result(opts, runWithArchive(opts)); + } public static OutputAnalyzer execAuto(String... suffix) throws Exception { AppCDSOptions opts = (new AppCDSOptions()); @@ -220,10 +225,9 @@ public static OutputAnalyzer execOff(String... suffix) throws Exception { return runWithArchive(opts); } - public static OutputAnalyzer execModule(String prefix[], String upgrademodulepath, String modulepath, - String mid, String... testClassArgs) - throws Exception { + private static AppCDSOptions makeModuleOptions(String prefix[], String upgrademodulepath, String modulepath, + String mid, String testClassArgs[]) { AppCDSOptions opts = (new AppCDSOptions()); opts.addPrefix(prefix); @@ -234,7 +238,14 @@ public static OutputAnalyzer execModule(String prefix[], String upgrademodulepat "-p", modulepath, "-m", mid); } opts.addSuffix(testClassArgs); + return opts; + } + public static OutputAnalyzer execModule(String prefix[], String upgrademodulepath, String modulepath, + String mid, String... testClassArgs) + throws Exception { + AppCDSOptions opts = makeModuleOptions(prefix, upgrademodulepath, modulepath, + mid, testClassArgs); return runWithArchive(opts); } diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/CheckUnsupportedDumpingOptions.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/CheckUnsupportedDumpingOptions.java index 111c690dcad..3c15773611a 100644 --- a/test/hotspot/jtreg/runtime/appcds/jigsaw/CheckUnsupportedDumpingOptions.java +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/CheckUnsupportedDumpingOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, 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,20 +40,15 @@ public class CheckUnsupportedDumpingOptions { private static final String[] jigsawOptions = { - "-m", "--limit-modules", - "--module-path", "--upgrade-module-path", "--patch-module" }; private static final String[] optionValues = { "mymod", - "mymod", - "mydir", ".", "java.naming=javax.naming.spi.NamingManger" }; - private static final int infoIdx = 1; public static void main(String[] args) throws Exception { String source = "package javax.naming.spi; " + @@ -71,31 +66,11 @@ public static void main(String[] args) throws Exception { String appClasses[] = {"Hello"}; for (int i = 0; i < jigsawOptions.length; i++) { OutputAnalyzer output; - if (i == 5) { - // --patch-module - output = TestCommon.dump(appJar, appClasses, "-Xlog:cds,cds+hashtables", - jigsawOptions[i] + optionValues[i] + appJar); - } else { - output = TestCommon.dump(appJar, appClasses, "-Xlog:cds,cds+hashtables", - jigsawOptions[i], optionValues[i]); - } - if (i < infoIdx) { - output.shouldContain("Cannot use the following option " + - "when dumping the shared archive: " + jigsawOptions[i]) - .shouldHaveExitValue(1); - } else { - output.shouldContain("Info: the " + jigsawOptions[i] + - " option is ignored when dumping the shared archive"); - if (optionValues[i].equals("mymod")) { - // java will throw FindException for a module - // which cannot be found during init_phase2() of vm init - output.shouldHaveExitValue(1) - .shouldContain("java.lang.module.FindException: Module mymod not found"); - } else { - output.shouldHaveExitValue(0); - } - } + output = TestCommon.dump(appJar, appClasses, "-Xlog:cds,cds+hashtables", + jigsawOptions[i], optionValues[i]); + output.shouldContain("Cannot use the following option " + + "when dumping the shared archive: " + jigsawOptions[i]) + .shouldHaveExitValue(1); } } } - diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/JigsawOptionsCombo.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/JigsawOptionsCombo.java index 05da79d88cd..c7d397fc3be 100644 --- a/test/hotspot/jtreg/runtime/appcds/jigsaw/JigsawOptionsCombo.java +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/JigsawOptionsCombo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, 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 @@ -69,8 +69,7 @@ public static void main(String[] args) throws Exception { private ArrayList testCaseTable = new ArrayList(); public static String infoDuringDump(String option) { - return "Info: the " + option + - " option is ignored when dumping the shared archive"; + return "Cannot use the following option when dumping the shared archive: " + option; } public void runTests() throws Exception { @@ -78,7 +77,7 @@ public void runTests() throws Exception { testCaseTable.add(new TestCase( "basic: Basic dump and execute, to verify the test plumbing works", "", "", 0, - "", "", 0) ); + "", "", 0, true) ); String bcpArg = "-Xbootclasspath/a:" + TestCommon.getTestJar("hello_more.jar"); @@ -86,51 +85,50 @@ public void runTests() throws Exception { testCaseTable.add(new TestCase( "Xbootclasspath/a: is OK for both dump and run time", bcpArg, "", 0, - bcpArg, "", 0) ); + bcpArg, "", 0, true) ); testCaseTable.add(new TestCase( "module-path-01: --module-path is ignored for dump time", - "--module-path mods", - infoDuringDump("--module-path"), 0, - null, null, 0) ); + "--module-path mods", "", 0, + null, null, 0, true) ); testCaseTable.add(new TestCase( "module-path-02: --module-path is ok for run time", "", "", 0, - "--module-path mods", "", 0) ); + "--module-path mods", "", 0, true) ); testCaseTable.add(new TestCase( "add-modules-01: --add-modules is ok at dump time", "--add-modules java.management", "", 0, - null, null, 0) ); + null, null, 0, true) ); testCaseTable.add(new TestCase( "add-modules-02: --add-modules is ok at run time", "", "", 0, - "--add-modules java.management", "", 0) ); + "--add-modules java.management", "", 0, true) ); testCaseTable.add(new TestCase( "limit-modules-01: --limit-modules is ignored at dump time", "--limit-modules java.base", - infoDuringDump("--limit-modules"), 0, - null, null, 0) ); + infoDuringDump("--limit-modules"), 1, + null, null, 0, true) ); testCaseTable.add(new TestCase( "limit-modules-02: --limit-modules is ok at run time", "", "", 0, - "--limit-modules java.base", "", 0) ); + "--limit-modules java.base", "", 0, false) ); testCaseTable.add(new TestCase( "upgrade-module-path-01: --upgrade-module-path is ignored at dump time", "--upgrade-module-path mods", - infoDuringDump("--upgrade-module-path"), 0, - null, null, 0) ); + infoDuringDump("--upgrade-module-path"), 1, + null, null, 0, true) ); testCaseTable.add(new TestCase( "-upgrade-module-path-module-path-02: --upgrade-module-path is ok at run time", "", "", 0, - "--upgrade-module-path mods", "", 0) ); + "--upgrade-module-path mods", "", 0, false) ); for (TestCase tc : testCaseTable) tc.execute(); } @@ -145,6 +143,7 @@ public class TestCase { String runTimeArgs; String runTimeExpectedOutput; int runTimeExpectedExitValue; + boolean sharingOn; private String appJar = TestCommon.getTestJar("hello.jar"); private String appClasses[] = {"Hello"}; @@ -152,7 +151,8 @@ public class TestCase { public TestCase(String description, String dumpTimeArgs, String dumpTimeExpectedOutput, int dumpTimeExpectedExitValue, - String runTimeArgs, String runTimeExpectedOutput, int runTimeExpectedExitValue) { + String runTimeArgs, String runTimeExpectedOutput, int runTimeExpectedExitValue, + boolean sharingOn) { this.description = description; this.dumpTimeArgs = dumpTimeArgs; @@ -161,6 +161,7 @@ public TestCase(String description, this.runTimeArgs = runTimeArgs; this.runTimeExpectedOutput = runTimeExpectedOutput; this.runTimeExpectedExitValue = runTimeExpectedExitValue; + this.sharingOn = sharingOn; } @@ -183,7 +184,13 @@ public void execute() throws Exception { OutputAnalyzer execOutput = TestCommon.exec(appJar, getRunOptions()); if (runTimeExpectedExitValue == 0) { - TestCommon.checkExec(execOutput, runTimeExpectedOutput, "Hello World"); + if (sharingOn) { + TestCommon.checkExec(execOutput, runTimeExpectedOutput, "Hello World"); + } else { + execOutput.shouldHaveExitValue(0) + .shouldContain(runTimeExpectedOutput) + .shouldContain("Hello World"); + } } else { execOutput.shouldMatch(dumpTimeExpectedOutput); execOutput.shouldHaveExitValue(dumpTimeExpectedExitValue); diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/AppClassInCP.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/AppClassInCP.java index 702c678c2dc..c621b94fbd6 100644 --- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/AppClassInCP.java +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/AppClassInCP.java @@ -86,7 +86,8 @@ public static void main(String args[]) throws Throwable { "--patch-module=java.naming=" + moduleJar, "-Xlog:class+load", "PatchMain", "javax.naming.spi.NamingManager", "mypackage.Hello"); - TestCommon.checkDump(output, "Loading classes to share"); + output.shouldHaveExitValue(1) + .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module"); String classPath = appJar + File.pathSeparator + classDir; System.out.println("classPath: " + classPath); @@ -96,9 +97,6 @@ public static void main(String args[]) throws Throwable { "--patch-module=java.naming=" + moduleJar, "-Xlog:class+load", "PatchMain", "javax.naming.spi.NamingManager", "mypackage.Hello") - .assertNormalExit( - "I pass!", - "Hello!", - "Hello source: shared objects file"); + .assertSilentlyDisabledCDS(0, "I pass!", "Hello!"); } } diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/CustomPackage.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/CustomPackage.java index 83b15fb3098..1bc8a0f1dd1 100644 --- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/CustomPackage.java +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/CustomPackage.java @@ -70,7 +70,8 @@ public static void main(String args[]) throws Throwable { "-Xlog:class+load", "-Xlog:class+path=info", "PatchMain", "javax.naming.myspi.NamingManager"); - TestCommon.checkDump(output, "Preload Warning: Cannot find javax/naming/myspi/NamingManager"); + output.shouldHaveExitValue(1) + .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module"); TestCommon.run( "-XX:+UnlockDiagnosticVMOptions", @@ -78,6 +79,6 @@ public static void main(String args[]) throws Throwable { "-Xlog:class+load", "-Xlog:class+path=info", "PatchMain", "javax.naming.myspi.NamingManager") - .assertNormalExit("I pass!"); + .assertSilentlyDisabledCDS(0, "I pass!"); } } diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/MismatchedPatchModule.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/MismatchedPatchModule.java index 01cd4146727..d34385c0e85 100644 --- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/MismatchedPatchModule.java +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/MismatchedPatchModule.java @@ -62,61 +62,21 @@ public static void main(String args[]) throws Throwable { JarBuilder.build("javanaming", "javax/naming/spi/NamingManager"); moduleJar = TestCommon.getTestJar("javanaming.jar"); - // Case 1: --patch-module specified for dump time and run time + // Case 1: --patch-module specified for dump time System.out.println("Case 1: --patch-module specified for dump time and run time"); OutputAnalyzer output = TestCommon.dump(null, TestCommon.list("javax/naming/spi/NamingManager"), "--patch-module=java.naming=" + moduleJar, "PatchMain", "javax.naming.spi.NamingManager"); - TestCommon.checkDump(output, "Loading classes to share"); + output.shouldHaveExitValue(1) + .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module"); - // javax.naming.spi.NamingManager is not patched at runtime - TestCommon.run( - "-XX:+UnlockDiagnosticVMOptions", - "--patch-module=java.naming2=" + moduleJar, - "-Xlog:class+path=info", - "PatchMain", "javax.naming.spi.NamingManager") - .assertNormalExit(o -> o.shouldNotContain("I pass!")); - - // Case 2: --patch-module specified for dump time but not for run time - System.out.println("Case 2: --patch-module specified for dump time but not for run time"); + // Case 2: --patch-module specified for run time but not for dump time + System.out.println("Case 2: --patch-module specified for run time but not for dump time"); output = TestCommon.dump(null, TestCommon.list("javax/naming/spi/NamingManager"), - "--patch-module=java.naming=" + moduleJar, - "PatchMain", "javax.naming.spi.NamingManager"); - TestCommon.checkDump(output, "Loading classes to share"); - - // javax.naming.spi.NamingManager is not patched at runtime - TestCommon.run( - "-XX:+UnlockDiagnosticVMOptions", - "-Xlog:class+path=info", - "PatchMain", "javax.naming.spi.NamingManager") - .assertNormalExit(o -> o.shouldNotContain("I pass!")); - - // Case 3: --patch-module specified for run time but not for dump time - System.out.println("Case 3: --patch-module specified for run time but not for dump time"); - output = - TestCommon.dump(null, - TestCommon.list("javax/naming/spi/NamingManager"), - "PatchMain", "javax.naming.spi.NamingManager"); - TestCommon.checkDump(output, "Loading classes to share"); - - // javax.naming.spi.NamingManager is patched at runtime - TestCommon.run( - "-XX:+UnlockDiagnosticVMOptions", - "--patch-module=java.naming=" + moduleJar, - "-Xlog:class+path=info", - "PatchMain", "javax.naming.spi.NamingManager") - .assertNormalExit("I pass!"); - - // Case 4: mismatched --patch-module entry counts between dump time and run time - System.out.println("Case 4: mismatched --patch-module entry counts between dump time and run time"); - output = - TestCommon.dump(null, - TestCommon.list("javax/naming/spi/NamingManager"), - "--patch-module=java.naming=" + moduleJar, "PatchMain", "javax.naming.spi.NamingManager"); TestCommon.checkDump(output, "Loading classes to share"); @@ -127,6 +87,6 @@ public static void main(String args[]) throws Throwable { "--patch-module=java.naming2=" + moduleJar, "-Xlog:class+path=info", "PatchMain", "javax.naming.spi.NamingManager") - .assertNormalExit("I pass!"); + .assertSilentlyDisabledCDS(0, "I pass!"); } } diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchDir.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchDir.java index 2765363fb22..50478b2066d 100644 --- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchDir.java +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchDir.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, 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,7 @@ public static void main(String args[]) throws Throwable { "--patch-module=java.naming=" + moduleJar, "-Xlog:class+load", "PatchMain", "javax.naming.spi.NamingManager") - .shouldContain("Loading classes to share") - .shouldHaveExitValue(0); + .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module") + .shouldHaveExitValue(1); } } diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchJavaBase.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchJavaBase.java index 7dac826406d..2737a79373a 100644 --- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchJavaBase.java +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchJavaBase.java @@ -62,7 +62,8 @@ public static void main(String args[]) throws Throwable { TestCommon.dump(null, null, "--patch-module=java.base=" + moduleJar, "PatchMain", "java.lang.NewClass"); - TestCommon.checkDump(output, "Loading classes to share"); + output.shouldHaveExitValue(1) + .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module"); TestCommon.run( "-XX:+UnlockDiagnosticVMOptions", diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/Simple.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/Simple.java index 3c685ef04d9..b929e2a24d1 100644 --- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/Simple.java +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/Simple.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, 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 @@ -68,7 +68,8 @@ public static void main(String args[]) throws Throwable { "-Xlog:class+load", "-Xlog:class+path=info", "PatchMain", "javax.naming.spi.NamingManager"); - TestCommon.checkDump(output, "Loading classes to share"); + output.shouldHaveExitValue(1) + .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module"); TestCommon.run( "-XX:+UnlockDiagnosticVMOptions", @@ -76,6 +77,6 @@ public static void main(String args[]) throws Throwable { "-Xlog:class+load", "-Xlog:class+path=info", "PatchMain", "javax.naming.spi.NamingManager") - .assertNormalExit("I pass!"); + .assertSilentlyDisabledCDS(0, "I pass!"); } } diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/SubClassOfPatchedClass.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/SubClassOfPatchedClass.java index b5c773867d6..a7e82196437 100644 --- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/SubClassOfPatchedClass.java +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/SubClassOfPatchedClass.java @@ -88,7 +88,8 @@ public static void main(String args[]) throws Throwable { "--patch-module=java.naming=" + moduleJar, "-Xlog:class+load", "PatchMain", "javax.naming.Reference", "mypackage.MyReference"); - TestCommon.checkDump(output, "Loading classes to share"); + output.shouldHaveExitValue(1) + .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module"); String classPath = appJar + File.pathSeparator + classDir; System.out.println("classPath: " + classPath); @@ -98,8 +99,6 @@ public static void main(String args[]) throws Throwable { "--patch-module=java.naming=" + moduleJar, "-Xlog:class+load", "PatchMain", "javax.naming.Reference", "mypackage.MyReference") - .assertNormalExit( - "I pass!", - "MyReference source: file:"); + .assertSilentlyDisabledCDS(0, "MyReference source: file:", "I pass!"); } } diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/TwoJars.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/TwoJars.java index 680fbd4a875..fde8d19c24b 100644 --- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/TwoJars.java +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/TwoJars.java @@ -87,7 +87,8 @@ public static void main(String args[]) throws Throwable { "-Xlog:class+load", "-Xlog:class+path=info", "PatchMain", "javax.naming.spi.NamingManager"); - TestCommon.checkDump(output, "Loading classes to share"); + output.shouldHaveExitValue(1) + .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module"); TestCommon.run( "-XX:+UnlockDiagnosticVMOptions", @@ -95,6 +96,6 @@ public static void main(String args[]) throws Throwable { "-Xlog:class+load", "-Xlog:class+path=info", "PatchMain", "javax.naming.spi.NamingManager") - .assertNormalExit("I pass"); + .assertSilentlyDisabledCDS(0, "I pass!"); } } diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/BootAppendTests.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/BootAppendTests.java index c36152d4b48..453efd7237b 100644 --- a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/BootAppendTests.java +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/BootAppendTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, 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 @@ -145,29 +145,32 @@ public static void testBootAppendModuleClassWithAppCDS() throws Exception { // Test #3: A class in excluded package defined in boot module // - should be loaded from the -Xbootclasspath/a by the boot classloader public static void testBootAppendExcludedModuleClassWithoutAppCDS() throws Exception { - CDSOptions opts = (new CDSOptions()) - .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar, - "--limit-modules", "java.base") - .setArchiveName(testArchiveName) - .addSuffix(MAIN_CLASS, "Test #3", BOOT_APPEND_MODULE_CLASS, "true", "BOOT"); - - CDSTestUtils.runWithArchiveAndCheck(opts); + TestCommon.run( + "-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar, + "-Xlog:class+load=info", + "--limit-modules", "java.base", + MAIN_CLASS, "Test #3", BOOT_APPEND_MODULE_CLASS, "true", "BOOT") + .assertSilentlyDisabledCDS(out -> { + out.shouldHaveExitValue(0) + .shouldMatch(".class.load. sun.nio.cs.ext.MyClass source:.*bootAppend.jar"); + }); } // Test #4: A shared class in excluded package that's archived from // -Xbootclasspath/a - // - should be loaded from the archive by the bootstrap classloader + // - should be loaded from the jar since AppCDS will be disabled with + // the --limit-modules option public static void testBootAppendExcludedModuleClassWithAppCDS() throws Exception { - OutputAnalyzer output = TestCommon.exec( - appJar, - "-Xbootclasspath/a:" + bootAppendJar, + TestCommon.run( + "-cp", appJar, "-Xbootclasspath/a:" + bootAppendJar, + "-Xlog:class+load=info", "--limit-modules", "java.base", - "-XX:+TraceClassLoading", MAIN_CLASS, - "Test #4", BOOT_APPEND_MODULE_CLASS, "true", "BOOT"); - TestCommon.checkExec(output); - if (!TestCommon.isUnableToMap(output)) - output.shouldContain("[class,load] sun.nio.cs.ext.MyClass source: shared objects file"); + "Test #4", BOOT_APPEND_MODULE_CLASS, "true", "BOOT") + .assertSilentlyDisabledCDS(out -> { + out.shouldHaveExitValue(0) + .shouldMatch(".class.load. sun.nio.cs.ext.MyClass source:.*bootAppend.jar"); + }); } @@ -229,28 +232,28 @@ public static void testBootAppendAppModuleClassWithAppCDS() throws Exception { public static void testBootAppendAppExcludeModuleClassWithoutAppCDS() throws Exception { - CDSOptions opts = (new CDSOptions()) - .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar, - "--limit-modules", "java.base") - .setArchiveName(testArchiveName) - .addSuffix(MAIN_CLASS, "Test #9", APP_MODULE_CLASS, "true", "BOOT"); - - CDSTestUtils.runWithArchiveAndCheck(opts); + TestCommon.run( + "-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar, + "-Xlog:class+load=info", + "--limit-modules", "java.base", + MAIN_CLASS, "Test #9", APP_MODULE_CLASS, "true", "BOOT") + .assertSilentlyDisabledCDS(out -> { + out.shouldHaveExitValue(0) + .shouldMatch(".class.load. com.sun.tools.javac.Main2 source:.*bootAppend.jar"); + }); } // Test #10: A shared class in excluded package defined in jimage app module // - should be loaded from the -Xbootclasspath/a with AppCDS public static void testBootAppendAppExcludeModuleClassAppCDS() throws Exception { - OutputAnalyzer output = TestCommon.exec( - appJar, - "-Xbootclasspath/a:" + bootAppendJar, - "-XX:+TraceClassLoading", + TestCommon.run( + "-cp", appJar, "-Xbootclasspath/a:" + bootAppendJar, + "-Xlog:class+load=info", "--limit-modules", "java.base", - MAIN_CLASS, - "Test #10", APP_MODULE_CLASS, "true", "BOOT"); - TestCommon.checkExec(output); - - if (!TestCommon.isUnableToMap(output)) - output.shouldContain("[class,load] com.sun.tools.javac.Main2 source: shared objects file"); + MAIN_CLASS, "Test #10", APP_MODULE_CLASS, "true", "BOOT") + .assertSilentlyDisabledCDS(out -> { + out.shouldHaveExitValue(0) + .shouldMatch(".class.load. com.sun.tools.javac.Main2 source:.*bootAppend.jar"); + }); } } diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/EmptyClassInBootClassPath.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/EmptyClassInBootClassPath.java index 57939979c02..ce0319dd517 100644 --- a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/EmptyClassInBootClassPath.java +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/EmptyClassInBootClassPath.java @@ -89,13 +89,15 @@ public static void main(String[] args) throws Exception { argsList.add("useAppLoader"); opts = new String[argsList.size()]; opts = argsList.toArray(opts); - TestCommon.run(opts).assertNormalExit(EXPECTED_EXCEPTION); + TestCommon.run(opts) + .assertSilentlyDisabledCDS(0, EXPECTED_EXCEPTION); // case 4: load class in bootclasspath using boot loader with '--limit-modules java.base' argsList.remove(argsList.size() - 1); argsList.add("useBootLoader"); opts = new String[argsList.size()]; opts = argsList.toArray(opts); - TestCommon.run(opts).assertNormalExit(EXPECTED_EXCEPTION); + TestCommon.run(opts) + .assertSilentlyDisabledCDS(0, EXPECTED_EXCEPTION); } } diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsHelper.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsHelper.java index cb30412bae4..41ba077077b 100644 --- a/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsHelper.java +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, 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 @@ -65,11 +65,22 @@ public static void main(String[] args) throws Exception { // Make sure we got the expected defining ClassLoader testLoader(clazz, expectedLoaders[i]); - // Make sure the class is in the shared space - if (!wb.isSharedClass(clazz)) { - throw new RuntimeException(clazz.getName() + - ".class should be in the shared space. " + - "loader=" + clazz.getClassLoader() + " module=" + clazz.getModule().getName()); + // Make sure the class is not in the shared space + // because CDS is disabled with --limit-modules during run time. + if (excludeModIdx != -1) { + if (wb.isSharedClass(clazz)) { + throw new RuntimeException(clazz.getName() + + ".class should not be in the shared space. " + + "loader=" + clazz.getClassLoader() + " module=" + clazz.getModule().getName()); + } + } else { + // class should be in the shared space if --limit-modules + // isn't specified during run time + if (!wb.isSharedClass(clazz)) { + throw new RuntimeException(clazz.getName() + + ".class should be in the shared space. " + + "loader=" + clazz.getClassLoader() + " module=" + clazz.getModule().getName()); + } } } clazz = null; diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsTests.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsTests.java index 3dbaad0bf08..d8aacdfaf9a 100644 --- a/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsTests.java +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, 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 @@ -150,14 +150,14 @@ public void runTestLimitMods() throws Exception { } } } - output = TestCommon.exec( - appJar + File.pathSeparator + helperJar, + TestCommon.run( + "-cp", appJar + File.pathSeparator + helperJar, "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", bootClassPath, "--limit-modules", limitMods, "LimitModsHelper", BOOT_ARCHIVE_CLASS, PLATFORM_ARCHIVE_CLASS, APP_ARCHIVE_CLASS, - Integer.toString(excludeModIdx)); // last 4 args passed to test - TestCommon.checkExec(output); + Integer.toString(excludeModIdx)) // last 4 args passed to test + .assertSilentlyDisabledCDS(0); limitMods = null; } } diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddModules.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddModules.java new file mode 100644 index 00000000000..0fbc5bdf3d8 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddModules.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2018, 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 + * @requires vm.cds + * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules jdk.compiler + * jdk.jartool/sun.tools.jar + * jdk.jlink + * @run main AddModules + * @summary sanity test the --add-modules option + */ + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; + +public class AddModules { + + private static final Path USER_DIR = Paths.get(System.getProperty("user.dir")); + + private static final String TEST_SRC = System.getProperty("test.src"); + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path MODS_DIR = Paths.get("mods"); + + // the module name of the test module + private static final String MAIN_MODULE1 = "com.greetings"; + private static final String MAIN_MODULE2 = "com.hello"; + private static final String SUB_MODULE = "org.astro"; + + // the module main class + private static final String MAIN_CLASS1 = "com.greetings.Main"; + private static final String MAIN_CLASS2 = "com.hello.Main"; + private static final String APP_CLASS = "org.astro.World"; + + private static Path moduleDir = null; + private static Path subJar = null; + private static Path mainJar1 = null; + private static Path mainJar2 = null; + + public static void buildTestModule() throws Exception { + + // javac -d mods/$TESTMODULE src/$TESTMODULE/** + JarBuilder.compileModule(SRC_DIR.resolve(SUB_MODULE), + MODS_DIR.resolve(SUB_MODULE), + null); + + // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/** + JarBuilder.compileModule(SRC_DIR.resolve(MAIN_MODULE1), + MODS_DIR.resolve(MAIN_MODULE1), + MODS_DIR.toString()); + + JarBuilder.compileModule(SRC_DIR.resolve(MAIN_MODULE2), + MODS_DIR.resolve(MAIN_MODULE2), + MODS_DIR.toString()); + + moduleDir = Files.createTempDirectory(USER_DIR, "mlib"); + subJar = moduleDir.resolve(SUB_MODULE + ".jar"); + String classes = MODS_DIR.resolve(SUB_MODULE).toString(); + JarBuilder.createModularJar(subJar.toString(), classes, null); + + mainJar1 = moduleDir.resolve(MAIN_MODULE1 + ".jar"); + classes = MODS_DIR.resolve(MAIN_MODULE1).toString(); + JarBuilder.createModularJar(mainJar1.toString(), classes, MAIN_CLASS1); + + mainJar2 = moduleDir.resolve(MAIN_MODULE2 + ".jar"); + classes = MODS_DIR.resolve(MAIN_MODULE2).toString(); + JarBuilder.createModularJar(mainJar2.toString(), classes, MAIN_CLASS2); + + } + + public static void main(String... args) throws Exception { + // compile the modules and create the modular jar files + buildTestModule(); + String appClasses[] = {MAIN_CLASS1, MAIN_CLASS2, APP_CLASS}; + // create an archive with the classes in the modules built in the + // previous step + OutputAnalyzer output = TestCommon.createArchive( + null, appClasses, + "--module-path", moduleDir.toString(), + "--add-modules", + MAIN_MODULE1 + "," + MAIN_MODULE2); + TestCommon.checkDump(output); + String prefix[] = {"-cp", "\"\"", "-Xlog:class+load=trace"}; + + // run the com.greetings module with the archive with the --module-path + // the same as the one during dump time. + // The classes should be loaded from the archive. + TestCommon.runWithModules(prefix, + null, // --upgrade-module-path + moduleDir.toString(), // --module-path + MAIN_MODULE1) // -m + .assertNormalExit(out -> { + out.shouldContain("[class,load] com.greetings.Main source: shared objects file") + .shouldContain("[class,load] org.astro.World source: shared objects file"); + }); + + // run the com.hello module with the archive with the --module-path + // the same as the one during dump time. + // The classes should be loaded from the archive. + TestCommon.runWithModules(prefix, + null, // --upgrade-module-path + moduleDir.toString(), // --module-path + MAIN_MODULE2) // -m + .assertNormalExit(out -> { + out.shouldContain("[class,load] com.hello.Main source: shared objects file") + .shouldContain("[class,load] org.astro.World source: shared objects file"); + }); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddOpens.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddOpens.java new file mode 100644 index 00000000000..260794e4402 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddOpens.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2018, 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 + * @requires vm.cds + * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules jdk.compiler + * jdk.jartool/sun.tools.jar + * jdk.jlink + * @run main AddOpens + * @summary sanity test the --add-opens option + */ + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; + +public class AddOpens { + + private static final Path USER_DIR = Paths.get(System.getProperty("user.dir")); + + private static final String TEST_SRC = System.getProperty("test.src"); + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path MODS_DIR = Paths.get("mods"); + + // the module name of the test module + private static final String TEST_MODULE1 = "com.simple"; + + // the module main class + private static final String MAIN_CLASS = "com.simple.Main"; + + private static Path moduleDir = null; + private static Path moduleDir2 = null; + private static Path destJar = null; + + public static void buildTestModule() throws Exception { + + // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/** + JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE1), + MODS_DIR.resolve(TEST_MODULE1), + MODS_DIR.toString()); + + moduleDir = Files.createTempDirectory(USER_DIR, "mlib"); + moduleDir2 = Files.createTempDirectory(USER_DIR, "mlib2"); + + Path srcJar = moduleDir.resolve(TEST_MODULE1 + ".jar"); + destJar = moduleDir2.resolve(TEST_MODULE1 + ".jar"); + String classes = MODS_DIR.resolve(TEST_MODULE1).toString(); + JarBuilder.createModularJar(srcJar.toString(), classes, MAIN_CLASS); + Files.copy(srcJar, destJar); + + } + + public static void main(String... args) throws Exception { + // compile the modules and create the modular jar files + buildTestModule(); + String appClasses[] = {MAIN_CLASS}; + // create an archive with both -cp and --module-path in the command line. + // Only the class in the modular jar in the --module-path will be archived; + // the class in the modular jar in the -cp won't be archived. + OutputAnalyzer output = TestCommon.createArchive( + destJar.toString(), appClasses, + "-Xlog:class+load=trace", "-XX:+PrintSystemDictionaryAtExit", + "--module-path", moduleDir.toString(), + "-m", TEST_MODULE1); + TestCommon.checkDump(output); + + // run with the archive using the same command line as in dump time + // plus the "--add-opens java.base/java.lang=com.simple" option. + // The main class should be loaded from the archive. + // The setaccessible(true) on the ClassLoader.defineClass method should + // be successful. + TestCommon.run( "-Xlog:class+load=trace", + "-cp", destJar.toString(), + "--add-opens", "java.base/java.lang=" + TEST_MODULE1, + "--module-path", moduleDir.toString(), + "-m", TEST_MODULE1, "with_add_opens") + .assertNormalExit( + "[class,load] com.simple.Main source: shared objects file", + "method.setAccessible succeeded!"); + + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddReads.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddReads.java new file mode 100644 index 00000000000..06bb1410742 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddReads.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2018, 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 + * @requires vm.cds + * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules jdk.compiler + * jdk.jartool/sun.tools.jar + * jdk.jlink + * @run main AddReads + * @summary sanity test the --add-reads option + */ + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.Asserts; + +public class AddReads { + + private static final Path USER_DIR = Paths.get(System.getProperty("user.dir")); + + private static final String TEST_SRC = System.getProperty("test.src"); + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path MODS_DIR = Paths.get("mods"); + + // the module name of the test module + private static final String MAIN_MODULE = "com.norequires"; + private static final String SUB_MODULE = "org.astro"; + + // the module main class + private static final String MAIN_CLASS = "com.norequires.Main"; + private static final String APP_CLASS = "org.astro.World"; + + private static Path moduleDir = null; + private static Path subJar = null; + private static Path mainJar = null; + + public static void buildTestModule() throws Exception { + + // javac -d mods/$TESTMODULE src/$TESTMODULE/** + JarBuilder.compileModule(SRC_DIR.resolve(SUB_MODULE), + MODS_DIR.resolve(SUB_MODULE), + null); + + Asserts.assertTrue(CompilerUtils + .compile(SRC_DIR.resolve(MAIN_MODULE), + MODS_DIR.resolve(MAIN_MODULE), + "-cp", MODS_DIR.resolve(SUB_MODULE).toString(), + "--add-reads", "com.norequires=ALL-UNNAMED")); + + moduleDir = Files.createTempDirectory(USER_DIR, "mlib"); + subJar = moduleDir.resolve(SUB_MODULE + ".jar"); + String classes = MODS_DIR.resolve(SUB_MODULE).toString(); + JarBuilder.createModularJar(subJar.toString(), classes, null); + + mainJar = moduleDir.resolve(MAIN_MODULE + ".jar"); + classes = MODS_DIR.resolve(MAIN_MODULE).toString(); + JarBuilder.createModularJar(mainJar.toString(), classes, MAIN_CLASS); + } + + public static void main(String... args) throws Exception { + // compile the modules and create the modular jar files + buildTestModule(); + String appClasses[] = {MAIN_CLASS, APP_CLASS}; + // create an archive with the classes in the modules built in the + // previous step + OutputAnalyzer output = TestCommon.createArchive( + null, appClasses, + "--module-path", moduleDir.toString(), + "--add-modules", SUB_MODULE, + "--add-reads", "com.norequires=org.astro", + "-m", MAIN_MODULE); + TestCommon.checkDump(output); + String prefix[] = {"-cp", "\"\"", "-Xlog:class+load=trace", + "--add-modules", SUB_MODULE, + "--add-reads", "com.norequires=org.astro"}; + + // run the com.norequires module with the archive with the same args + // used during dump time. + // The classes should be loaded from the archive. + TestCommon.runWithModules(prefix, + null, // --upgrade-module-path + moduleDir.toString(), // --module-path + MAIN_MODULE) // -m + .assertNormalExit(out -> { + out.shouldContain("[class,load] com.norequires.Main source: shared objects file") + .shouldContain("[class,load] org.astro.World source: shared objects file"); + }); + + // create an archive with -cp pointing to the jar file containing the + // org.astro module and --module-path pointing to the main module + output = TestCommon.createArchive( + subJar.toString(), appClasses, + "--module-path", moduleDir.toString(), + "--add-modules", SUB_MODULE, + "--add-reads", "com.norequires=org.astro", + "-m", MAIN_MODULE); + TestCommon.checkDump(output); + // run the com.norequires module with the archive with the sub-module + // in the -cp and with -add-reads=com.norequires=ALL-UNNAMED + // The main class should be loaded from the archive. + // The org.astro.World should be loaded from the jar. + String prefix2[] = {"-cp", subJar.toString(), "-Xlog:class+load=trace", + "--add-reads", "com.norequires=ALL-UNNAMED"}; + TestCommon.runWithModules(prefix2, + null, // --upgrade-module-path + moduleDir.toString(), // --module-path + MAIN_MODULE) // -m + .assertNormalExit(out -> { + out.shouldContain("[class,load] com.norequires.Main source: shared objects file") + .shouldMatch(".class.load. org.astro.World source:.*org.astro.jar"); + }); + + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/ExportModule.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/ExportModule.java new file mode 100644 index 00000000000..e26d1c53b5e --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/ExportModule.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2018, 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 + * @requires vm.cds + * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules jdk.compiler + * jdk.jartool/sun.tools.jar + * jdk.jlink + * @run main ExportModule + * @summary Tests involve exporting a module from the module path to a jar in the -cp. + */ + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import jdk.test.lib.compiler.CompilerUtils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.Asserts; + +public class ExportModule { + + private static final Path USER_DIR = Paths.get(System.getProperty("user.dir")); + + private static final String TEST_SRC = System.getProperty("test.src"); + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path MODS_DIR = Paths.get("mods"); + + // the module name of the test module + private static final String TEST_MODULE1 = "com.greetings"; + private static final String TEST_MODULE2 = "org.astro"; + + // unnamed module package name + private static final String PKG_NAME = "com.nomodule"; + + // the module main class + private static final String MAIN_CLASS = "com.greetings.Main"; + private static final String APP_CLASS = "org.astro.World"; + + // unnamed module main class + private static final String UNNAMED_MAIN = "com.nomodule.Main"; + + private static Path moduleDir = null; + private static Path moduleDir2 = null; + private static Path appJar = null; + private static Path appJar2 = null; + + public static void buildTestModule() throws Exception { + + // javac -d mods/$TESTMODULE src/$TESTMODULE/** + JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE2), + MODS_DIR.resolve(TEST_MODULE2), + null); + + // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/** + JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE1), + MODS_DIR.resolve(TEST_MODULE1), + MODS_DIR.toString()); + + moduleDir = Files.createTempDirectory(USER_DIR, "mlib"); + Path jar = moduleDir.resolve(TEST_MODULE2 + ".jar"); + String classes = MODS_DIR.resolve(TEST_MODULE2).toString(); + JarBuilder.createModularJar(jar.toString(), classes, null); + + moduleDir2 = Files.createTempDirectory(USER_DIR, "mlib2"); + appJar = moduleDir2.resolve(TEST_MODULE1 + ".jar"); + classes = MODS_DIR.resolve(TEST_MODULE1).toString(); + JarBuilder.createModularJar(appJar.toString(), classes, MAIN_CLASS); + + // build a non-modular jar containing the main class which + // requires the org.astro package + boolean compiled + = CompilerUtils.compile(SRC_DIR.resolve(PKG_NAME), + MODS_DIR.resolve(PKG_NAME), + "--module-path", MODS_DIR.toString(), + "--add-modules", TEST_MODULE2, + "--add-exports", "org.astro/org.astro=ALL-UNNAMED"); + Asserts.assertTrue(compiled, "test package did not compile"); + + appJar2 = moduleDir2.resolve(PKG_NAME + ".jar"); + classes = MODS_DIR.resolve(PKG_NAME).toString(); + JarBuilder.createModularJar(appJar2.toString(), classes, null); + } + + public static void main(String... args) throws Exception { + // compile the modules and create the modular jar files + buildTestModule(); + String appClasses[] = {MAIN_CLASS, APP_CLASS}; + // create an archive with the class in the org.astro module built in the + // previous step and the main class from the modular jar in the -cp + // note: the main class is in the modular jar in the -cp which requires + // the module in the --module-path + OutputAnalyzer output = TestCommon.createArchive( + appJar.toString(), appClasses, + "-Xlog:class+load=trace", "-XX:+PrintSystemDictionaryAtExit", + "--module-path", moduleDir.toString(), + "--add-modules", TEST_MODULE2, MAIN_CLASS); + TestCommon.checkDump(output); + + // run it using the archive + // both the main class and the class from the org.astro module should + // be loaded from the archive + TestCommon.run("-Xlog:class+load=trace", + "-cp", appJar.toString(), + "--module-path", moduleDir.toString(), + "--add-modules", TEST_MODULE2, MAIN_CLASS) + .assertNormalExit( + "[class,load] org.astro.World source: shared objects file", + "[class,load] com.greetings.Main source: shared objects file"); + + String appClasses2[] = {UNNAMED_MAIN, APP_CLASS}; + // create an archive with the main class from a non-modular jar in the + // -cp and the class from the org.astro module + // note: the org.astro package needs to be exported to "ALL-UNNAMED" + // module since the jar in the -cp is a non-modular jar and thus it is + // unnmaed. + output = TestCommon.createArchive( + appJar2.toString(), appClasses2, + "-Xlog:class+load=trace", "-XX:+PrintSystemDictionaryAtExit", + "--module-path", moduleDir.toString(), + "--add-modules", TEST_MODULE2, + "--add-exports", "org.astro/org.astro=ALL-UNNAMED", + UNNAMED_MAIN); + TestCommon.checkDump(output); + + // both the main class and the class from the org.astro module should + // be loaded from the archive + TestCommon.run("-Xlog:class+load=trace", + "-cp", appJar2.toString(), + "--module-path", moduleDir.toString(), + "--add-modules", TEST_MODULE2, + "--add-exports", "org.astro/org.astro=ALL-UNNAMED", + UNNAMED_MAIN) + .assertNormalExit( + "[class,load] org.astro.World source: shared objects file", + "[class,load] com.nomodule.Main source: shared objects file"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/JvmtiAddPath.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/JvmtiAddPath.java new file mode 100644 index 00000000000..87e1993268a --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/JvmtiAddPath.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2018, 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 + * @summary JvmtiEnv::AddToBootstrapClassLoaderSearch and JvmtiEnv::AddToSystemClassLoaderSearch should disable AppCDS + * @requires vm.cds + * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * @compile ../../test-classes/JvmtiApp.java + * @run main JvmtiAddPath + */ + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import jdk.test.lib.process.OutputAnalyzer; +import sun.hotspot.WhiteBox; + +public class JvmtiAddPath { + static String use_whitebox_jar; + static String[] no_extra_matches = {}; + static String[] check_appcds_enabled = { + "[class,load] ExtraClass source: shared object" + }; + static String[] check_appcds_disabled = { + "[class,load] ExtraClass source: file:" + }; + + private static final Path USER_DIR = Paths.get(System.getProperty("user.dir")); + + private static final String TEST_SRC = System.getProperty("test.src"); + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path MODS_DIR = Paths.get("mods"); + + // the module name of the test module + private static final String TEST_MODULE1 = "com.simple"; + + // the module main class + private static final String MAIN_CLASS = "com.simple.Main"; + + private static Path moduleDir = null; + private static Path mainJar = null; + + public static void buildTestModule() throws Exception { + + // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/** + JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE1), + MODS_DIR.resolve(TEST_MODULE1), + MODS_DIR.toString()); + + moduleDir = Files.createTempDirectory(USER_DIR, "mlib"); + + mainJar = moduleDir.resolve(TEST_MODULE1 + ".jar"); + String classes = MODS_DIR.resolve(TEST_MODULE1).toString(); + JarBuilder.createModularJar(mainJar.toString(), classes, MAIN_CLASS); + } + + static void run(String cp, String... args) throws Exception { + run(no_extra_matches, cp, args); + } + + static void run(String[] extra_matches, String cp, String... args) throws Exception { + String[] opts = {"-cp", cp, "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", use_whitebox_jar}; + opts = TestCommon.concat(opts, args); + TestCommon.run(opts).assertNormalExit(extra_matches); + } + + public static void main(String[] args) throws Exception { + buildTestModule(); + JarBuilder.build("jvmti_app", "JvmtiApp", "ExtraClass"); + JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox"); + + // In all the test cases below, appJar does not contain Hello.class. Instead, we + // append JAR file(s) that contain Hello.class to the boot classpath, the app + // classpath, or both, and verify that Hello.class is loaded by the expected ClassLoader. + String appJar = TestCommon.getTestJar("jvmti_app.jar"); // contains JvmtiApp.class + String addappJar = mainJar.toString(); // contains Main.class + String addbootJar = mainJar.toString(); // contains Main.class + String twoAppJars = appJar + File.pathSeparator + addappJar; + String modulePath = "--module-path=" + moduleDir.toString(); + String wbJar = TestCommon.getTestJar("WhiteBox.jar"); + use_whitebox_jar = "-Xbootclasspath/a:" + wbJar; + + OutputAnalyzer output = TestCommon.createArchive( + appJar, + TestCommon.list("JvmtiApp", "ExtraClass", MAIN_CLASS), + use_whitebox_jar, + "-Xlog:class+load=trace", + modulePath); + TestCommon.checkDump(output); + + System.out.println("Test case 1: not adding module path - Hello.class should not be found"); + run(check_appcds_enabled, appJar, + "-Xlog:class+load", "JvmtiApp", "noadd", MAIN_CLASS); // appcds should be enabled + + System.out.println("Test case 2: add to boot classpath only - should find Hello.class in boot loader"); + run(check_appcds_disabled, appJar, + "-Xlog:class+load=trace", + modulePath, + "JvmtiApp", "bootonly", addbootJar, MAIN_CLASS); // appcds should be disabled + + System.out.println("Test case 3: add to app classpath only - should find Hello.class in app loader"); + run(appJar, modulePath, + "JvmtiApp", "apponly", addappJar, MAIN_CLASS); + + System.out.println("Test case 4: add to boot and app paths - should find Hello.class in boot loader"); + run(appJar, modulePath, + "JvmtiApp", "appandboot", addbootJar, addappJar, MAIN_CLASS); + + System.out.println("Test case 5: add to app using -cp, but add to boot using JVMTI - should find Hello.class in boot loader"); + run(appJar, modulePath, + "JvmtiApp", "bootonly", addappJar, MAIN_CLASS); + + System.out.println("Test case 6: add to app using AppCDS, but add to boot using JVMTI - should find Hello.class in boot loader"); + output = TestCommon.createArchive( + appJar, TestCommon.list("JvmtiApp", "ExtraClass"), + use_whitebox_jar, + "-Xlog:class+load=trace", + modulePath); + TestCommon.checkDump(output); + run(twoAppJars, modulePath, + "JvmtiApp", "bootonly", addappJar, MAIN_CLASS); + + System.out.println("Test case 7: add to app using AppCDS, no JVMTI calls - should find Hello.class in app loader"); + run(twoAppJars, modulePath, + "JvmtiApp", "noadd-appcds", MAIN_CLASS); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/MainModuleOnly.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/MainModuleOnly.java new file mode 100644 index 00000000000..3809b9459ef --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/MainModuleOnly.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2018, 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 + * @requires vm.cds + * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules jdk.compiler + * jdk.jartool/sun.tools.jar + * jdk.jlink + * @run main MainModuleOnly + * @summary Test some scenarios with a main modular jar specified in the --module-path and -cp options in the command line. + */ + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; + +public class MainModuleOnly { + + private static final Path USER_DIR = Paths.get(System.getProperty("user.dir")); + + private static final String TEST_SRC = System.getProperty("test.src"); + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path MODS_DIR = Paths.get("mods"); + + // the module name of the test module + private static final String TEST_MODULE1 = "com.simple"; + + // the module main class + private static final String MAIN_CLASS = "com.simple.Main"; + + private static Path moduleDir = null; + private static Path moduleDir2 = null; + private static Path destJar = null; + + public static void buildTestModule() throws Exception { + + // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/** + JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE1), + MODS_DIR.resolve(TEST_MODULE1), + MODS_DIR.toString()); + + + moduleDir = Files.createTempDirectory(USER_DIR, "mlib"); + moduleDir2 = Files.createTempDirectory(USER_DIR, "mlib2"); + + Path srcJar = moduleDir.resolve(TEST_MODULE1 + ".jar"); + destJar = moduleDir2.resolve(TEST_MODULE1 + ".jar"); + String classes = MODS_DIR.resolve(TEST_MODULE1).toString(); + JarBuilder.createModularJar(srcJar.toString(), classes, MAIN_CLASS); + Files.copy(srcJar, destJar); + + } + + public static void main(String... args) throws Exception { + // compile the modules and create the modular jar files + buildTestModule(); + String appClasses[] = {MAIN_CLASS}; + // create an archive with both -cp and --module-path in the command line. + // Only the class in the modular jar in the --module-path will be archived; + // the class in the modular jar in the -cp won't be archived. + OutputAnalyzer output = TestCommon.createArchive( + destJar.toString(), appClasses, + "-Xlog:class+load=trace", "-XX:+PrintSystemDictionaryAtExit", + "--module-path", moduleDir.toString(), + "-m", TEST_MODULE1); + TestCommon.checkDump(output); + + // run with the archive using the same command line as in dump time. + // The main class should be loaded from the archive. + TestCommon.run("-Xlog:class+load=trace", + "-cp", destJar.toString(), + "--module-path", moduleDir.toString(), + "-m", TEST_MODULE1) + .assertNormalExit("[class,load] com.simple.Main source: shared objects file"); + + // run with the archive with the main class name inserted before the -m. + // The main class name will be picked up before the module name. So the + // main class should be loaded from the jar in the -cp. + TestCommon.run("-Xlog:class+load=trace", + "-cp", destJar.toString(), + "--module-path", moduleDir.toString(), + MAIN_CLASS, "-m", TEST_MODULE1) + .assertNormalExit(out -> + out.shouldMatch(".class.load. com.simple.Main source:.*com.simple.jar")); + + // run with the archive with exploded module. Since during dump time, we + // only archive classes from the modular jar in the --module-path, the + // main class should be loaded from the exploded module directory. + TestCommon.run("-Xlog:class+load=trace", + "-cp", destJar.toString(), + "--module-path", MODS_DIR.toString(), + "-m", TEST_MODULE1 + "/" + MAIN_CLASS) + .assertNormalExit(out -> { + out.shouldMatch(".class.load. com.simple.Main source:.*com.simple") + .shouldContain(MODS_DIR.toString()); + }); + + // run with the archive with the --upgrade-module-path option. + // CDS will be disabled with this options and the main class will be + // loaded from the modular jar. + TestCommon.run("-Xlog:class+load=trace", + "-cp", destJar.toString(), + "--upgrade-module-path", moduleDir.toString(), + "--module-path", moduleDir.toString(), + "-m", TEST_MODULE1) + .assertSilentlyDisabledCDS(out -> { + out.shouldHaveExitValue(0) + .shouldMatch("CDS is disabled when the.*option is specified") + .shouldMatch(".class.load. com.simple.Main source:.*com.simple.jar"); + }); + // run with the archive with the --limit-modules option. + // CDS will be disabled with this options and the main class will be + // loaded from the modular jar. + TestCommon.run("-Xlog:class+load=trace", + "-cp", destJar.toString(), + "--limit-modules", "java.base," + TEST_MODULE1, + "--module-path", moduleDir.toString(), + "-m", TEST_MODULE1) + .assertSilentlyDisabledCDS(out -> { + out.shouldHaveExitValue(0) + .shouldMatch("CDS is disabled when the.*option is specified") + .shouldMatch(".class.load. com.simple.Main source:.*com.simple.jar"); + }); + // run with the archive with the --patch-module option. + // CDS will be disabled with this options and the main class will be + // loaded from the modular jar. + TestCommon.run("-Xlog:class+load=trace", + "-cp", destJar.toString(), + "--patch-module", TEST_MODULE1 + "=" + MODS_DIR.toString(), + "--module-path", moduleDir.toString(), + "-m", TEST_MODULE1) + .assertSilentlyDisabledCDS(out -> { + out.shouldHaveExitValue(0) + .shouldMatch("CDS is disabled when the.*option is specified") + .shouldMatch(".class.load. com.simple.Main source:.*com.simple.jar"); + }); + // modify the timestamp of the jar file + (new File(destJar.toString())).setLastModified(System.currentTimeMillis() + 2000); + // run with the archive and the jar with modified timestamp. + // It should fail due to timestamp of the jar doesn't match the one + // used during dump time. + TestCommon.run("-Xlog:class+load=trace", + "-cp", destJar.toString(), + "--module-path", moduleDir.toString(), + "-m", TEST_MODULE1) + .assertAbnormalExit( + "A jar/jimage file is not the one used while building the shared archive file:"); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/ModulePathAndCP.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/ModulePathAndCP.java new file mode 100644 index 00000000000..6fd7af4b350 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/ModulePathAndCP.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2018, 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 + * @requires vm.cds + * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules jdk.compiler + * jdk.jartool/sun.tools.jar + * jdk.jlink + * @run main ModulePathAndCP + * @summary 2 sets of tests: one with only --module-path in the command line; + * another with both -cp and --module-path in the command line. + */ + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; + +public class ModulePathAndCP { + + private static final Path USER_DIR = Paths.get(System.getProperty("user.dir")); + + private static final String TEST_SRC = System.getProperty("test.src"); + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path MODS_DIR = Paths.get("mods"); + + // the module name of the test module + private static final String MAIN_MODULE = "com.greetings"; + private static final String APP_MODULE = "org.astro"; + + // the module main class + private static final String MAIN_CLASS = "com.greetings.Main"; + private static final String APP_CLASS = "org.astro.World"; + + private static Path moduleDir = null; + private static Path moduleDir2 = null; + private static Path subJar = null; + private static Path mainJar = null; + private static Path destJar = null; + + public static void buildTestModule() throws Exception { + + // javac -d mods/$TESTMODULE src/$TESTMODULE/** + JarBuilder.compileModule(SRC_DIR.resolve(APP_MODULE), + MODS_DIR.resolve(APP_MODULE), + null); + + // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/** + JarBuilder.compileModule(SRC_DIR.resolve(MAIN_MODULE), + MODS_DIR.resolve(MAIN_MODULE), + MODS_DIR.toString()); + + moduleDir = Files.createTempDirectory(USER_DIR, "mlib"); + moduleDir2 = Files.createTempDirectory(USER_DIR, "mlib2"); + subJar = moduleDir.resolve(APP_MODULE + ".jar"); + destJar = moduleDir2.resolve(APP_MODULE + ".jar"); + String classes = MODS_DIR.resolve(APP_MODULE).toString(); + JarBuilder.createModularJar(subJar.toString(), classes, null); + Files.copy(subJar, destJar); + + mainJar = moduleDir.resolve(MAIN_MODULE + ".jar"); + Path mainJar2 = moduleDir2.resolve(MAIN_MODULE + ".jar"); + classes = MODS_DIR.resolve(MAIN_MODULE).toString(); + JarBuilder.createModularJar(mainJar.toString(), classes, MAIN_CLASS); + Files.copy(mainJar, mainJar2); + + } + + public static void main(String... args) throws Exception { + // compile the modules and create the modular jar files + buildTestModule(); + String appClasses[] = {MAIN_CLASS, APP_CLASS}; + // create an archive with the classes in the modules built in the + // previous step + OutputAnalyzer output = TestCommon.createArchive( + null, appClasses, + "--module-path", moduleDir.toString(), + "-m", MAIN_MODULE); + TestCommon.checkDump(output); + String prefix[] = {"-cp", "\"\"", "-Xlog:class+load=trace"}; + + // run with the archive with the --module-path the same as the one during + // dump time. The classes should be loaded from the archive. + TestCommon.runWithModules(prefix, + null, // --upgrade-module-path + moduleDir.toString(), // --module-path + MAIN_MODULE) // -m + .assertNormalExit(out -> { + out.shouldContain("[class,load] com.greetings.Main source: shared objects file") + .shouldContain("[class,load] org.astro.World source: shared objects file"); + }); + + // run with the archive with the --module-path different from the one during + // dump time. The classes should be loaded from the jar files. + TestCommon.runWithModules(prefix, + null, // --upgrade-module-path + moduleDir2.toString(), // --module-path + MAIN_MODULE) // -m + .assertNormalExit(out -> { + out.shouldMatch(".class.load. com.greetings.Main source:.*com.greetings.jar") + .shouldMatch(".class.load. org.astro.World source:.*org.astro.jar"); + }); + + // create an archive with modular jar files in both -cp and --module-path + String jars = subJar.toString() + System.getProperty("path.separator") + + mainJar.toString(); + output = TestCommon.createArchive( jars, appClasses, + "-Xlog:class+load=trace", "-XX:+PrintSystemDictionaryAtExit", + "--module-path", moduleDir.toString(), + "-m", MAIN_MODULE); + TestCommon.checkDump(output); + + // run with archive with the main class name specified before + // the module name with the -m option. Since the -m option was specified + // during dump time, the classes in the jar files after the -cp won't be + // archived. Therefore, the classes won't be loaded from the archive but + // will be loaded from the jar files. + TestCommon.run("-Xlog:class+load=trace", + "-cp", jars, + "--module-path", moduleDir.toString(), + MAIN_CLASS, "-m", MAIN_MODULE) + .assertNormalExit(out -> { + out.shouldMatch(".class.load. com.greetings.Main source:.*com.greetings.jar") + .shouldMatch(".class.load. org.astro.World source:.*org.astro.jar"); + }); + + // similar to the above case but without the main class name. The classes + // should be loaded from the archive. + TestCommon.run("-Xlog:class+load=trace", + "-cp", jars, + "--module-path", moduleDir.toString(), + "-m", MAIN_MODULE) + .assertNormalExit( + "[class,load] com.greetings.Main source: shared objects file", + "[class,load] org.astro.World source: shared objects file"); + + // create an archive with two modular jars in the --module-path + output = TestCommon.createArchive( + null, appClasses, + "--module-path", jars, + "-m", MAIN_MODULE); + TestCommon.checkDump(output); + + // run with the above archive but with the modular jar containing the + // org.astro module in a different location. + // The org.astro.World class should be loaded from the jar. + // The Main class should still be loaded from the archive. + jars = destJar.toString() + System.getProperty("path.separator") + + mainJar.toString(); + TestCommon.runWithModules(prefix, + null, // --upgrade-module-path + jars, // --module-path + MAIN_MODULE) // -m + .assertNormalExit(out -> { + out.shouldContain("[class,load] com.greetings.Main source: shared objects file") + .shouldMatch(".class.load. org.astro.World source:.*org.astro.jar"); + }); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.greetings/com/greetings/Main.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.greetings/com/greetings/Main.java new file mode 100644 index 00000000000..ccaa3b7684d --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.greetings/com/greetings/Main.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.greetings; +import org.astro.World; +public class Main { + public static void main(String[] args) { + System.out.format("Greetings %s!\n", World.name()); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.greetings/module-info.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.greetings/module-info.java new file mode 100644 index 00000000000..93345c7ea8f --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.greetings/module-info.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018, 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. + * + */ + +module com.greetings { + requires org.astro; +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.hello/com/hello/Main.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.hello/com/hello/Main.java new file mode 100644 index 00000000000..69f79a9d3ad --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.hello/com/hello/Main.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.hello; +import org.astro.World; +public class Main { + public static void main(String[] args) { + System.out.format("Hello %s!\n", World.name()); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.hello/module-info.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.hello/module-info.java new file mode 100644 index 00000000000..46c92f104e8 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.hello/module-info.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018, 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. + * + */ + +module com.hello { + requires org.astro; +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.nomodule/com/nomodule/Main.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.nomodule/com/nomodule/Main.java new file mode 100644 index 00000000000..79f2c7001de --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.nomodule/com/nomodule/Main.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.nomodule; +import org.astro.World; +public class Main { + public static void main(String[] args) { + System.out.format("Greetings %s!\n", World.name()); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.norequires/com/norequires/Main.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.norequires/com/norequires/Main.java new file mode 100644 index 00000000000..4c3ae500939 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.norequires/com/norequires/Main.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.norequires; +import org.astro.World; +public class Main { + public static void main(String[] args) { + System.out.format("Hello %s!\n", World.name()); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.norequires/module-info.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.norequires/module-info.java new file mode 100644 index 00000000000..194026c0ca3 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.norequires/module-info.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018, 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. + * + */ + +module com.norequires { } diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.simple/com/simple/Main.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.simple/com/simple/Main.java new file mode 100644 index 00000000000..06b6e352ec1 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.simple/com/simple/Main.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package com.simple; + +import java.lang.reflect.Method; + +public class Main { + public static void main(String[] args) throws Exception { + System.out.println("Hello World!"); + if (args.length > 0 && args[0].equals("with_add_opens")) { + Method method = ClassLoader.class.getDeclaredMethod("defineClass", + byte[].class, int.class, int.class); + method.setAccessible(true); + System.out.println("method.setAccessible succeeded!"); + } + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.simple/module-info.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.simple/module-info.java new file mode 100644 index 00000000000..dade1ee6399 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.simple/module-info.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018, 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. + * + */ + +module com.simple { +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/org.astro/module-info.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/org.astro/module-info.java new file mode 100644 index 00000000000..1faa33fd1e3 --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/org.astro/module-info.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018, 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. + * + */ + +module org.astro { + exports org.astro; +} diff --git a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/org.astro/org/astro/World.java b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/org.astro/org/astro/World.java new file mode 100644 index 00000000000..43f02ba1bff --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/org.astro/org/astro/World.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018, 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 org.astro; +public class World { + public static String name() { + return "world"; + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/test-classes/JvmtiApp.java b/test/hotspot/jtreg/runtime/appcds/test-classes/JvmtiApp.java index e0c0ea55fb6..fda99bb94da 100644 --- a/test/hotspot/jtreg/runtime/appcds/test-classes/JvmtiApp.java +++ b/test/hotspot/jtreg/runtime/appcds/test-classes/JvmtiApp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, 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,9 +25,9 @@ import sun.hotspot.WhiteBox; public class JvmtiApp { - static Class forname() { + static Class forname(String cn) { try { - return Class.forName("Hello"); + return Class.forName(cn); } catch (Throwable t) { return null; } @@ -40,9 +40,14 @@ static void failed(String msg) { // See ../JvmtiAddPath.java for how the classpaths are configured. public static void main(String args[]) { + String cn = "Hello"; + if (args.length >= 3) { + cn = args[args.length - 1]; + } + if (args[0].equals("noadd")) { - if (forname() != null) { - failed("Hello class was loaded unexpectedly"); + if (forname(cn) != null) { + failed(cn + " class was loaded unexpectedly"); } // We use -verbose:class to verify that Extra.class IS loaded by AppCDS if // the boot classpath HAS NOT been appended. @@ -54,39 +59,41 @@ public static void main(String args[]) { if (args[0].equals("bootonly")) { wb.addToBootstrapClassLoaderSearch(args[1]); - Class cls = forname(); + Class cls = forname(cn); if (cls == null) { - failed("Cannot find Hello class"); + failed("Cannot find " + cn + " class"); } if (cls.getClassLoader() != null) { failed("Hello class not loaded by boot classloader"); } } else if (args[0].equals("apponly")) { wb.addToSystemClassLoaderSearch(args[1]); - Class cls = forname(); + Class cls = forname(cn); if (cls == null) { - failed("Cannot find Hello class"); + failed("Cannot find " + cn + " class"); } if (cls.getClassLoader() != JvmtiApp.class.getClassLoader()) { - failed("Hello class not loaded by app classloader"); + failed(cn + " class not loaded by app classloader"); } } else if (args[0].equals("noadd-appcds")) { - Class cls = forname(); + cn = (args.length == 1) ? "Hello" : args[1]; + Class cls = forname(cn); if (cls == null) { - failed("Cannot find Hello class"); + failed("Cannot find " + cn + " class"); } if (cls.getClassLoader() != JvmtiApp.class.getClassLoader()) { - failed("Hello class not loaded by app classloader"); + failed(cn + " class not loaded by app classloader"); } } else if (args[0].equals("appandboot")) { wb.addToBootstrapClassLoaderSearch(args[1]); wb.addToSystemClassLoaderSearch(args[2]); - Class cls = forname(); + cn = (args.length == 3) ? "Hello" : args[3]; + Class cls = forname(cn); if (cls == null) { - failed("Cannot find Hello class"); + failed("Cannot find " + cn + " class"); } if (cls.getClassLoader() != null) { - failed("Hello class not loaded by boot classloader"); + failed(cn + " class not loaded by boot classloader"); } } else { failed("unknown option " + args[0]); @@ -102,4 +109,4 @@ public static void main(String args[]) { class ExtraClass { static void doit() {} -} \ No newline at end of file +} diff --git a/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleCDS.java b/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleCDS.java index 6b5d3c7e37c..200eb0b2cca 100644 --- a/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleCDS.java +++ b/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleCDS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, 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 @@ -50,7 +50,8 @@ public static void main(String args[]) throws Throwable { "-Xlog:class+path=info", "-version"); new OutputAnalyzer(pb.start()) - .shouldContain("ro space:"); // Make sure archive got created. + // --patch-module is not supported during CDS dumping + .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module"); // Case 2: Test that directory in --patch-module is supported for CDS dumping // Create a class file in the module java.base. @@ -73,7 +74,8 @@ public static void main(String args[]) throws Throwable { "-Xlog:class+path=info", "-version"); new OutputAnalyzer(pb.start()) - .shouldContain("ro space:"); // Make sure archive got created. + // --patch-module is not supported during CDS dumping + .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module"); // Case 3a: Test CDS dumping with jar file in --patch-module BasicJarBuilder.build("javanaming", "javax/naming/spi/NamingManager"); @@ -87,7 +89,8 @@ public static void main(String args[]) throws Throwable { "-Xlog:class+path=info", "PatchModuleMain", "javax.naming.spi.NamingManager"); new OutputAnalyzer(pb.start()) - .shouldContain("ro space:"); // Make sure archive got created. + // --patch-module is not supported during CDS dumping + .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module"); // Case 3b: Test CDS run with jar file in --patch-module pb = ProcessTools.createJavaProcessBuilder( diff --git a/test/lib/jdk/test/lib/cds/CDSTestUtils.java b/test/lib/jdk/test/lib/cds/CDSTestUtils.java index 3677b71f685..d16944eb8b7 100644 --- a/test/lib/jdk/test/lib/cds/CDSTestUtils.java +++ b/test/lib/jdk/test/lib/cds/CDSTestUtils.java @@ -117,6 +117,7 @@ public static class Result { private final boolean hasMappingFailure; private final boolean hasAbnormalExit; private final boolean hasNormalExit; + private final String CDS_DISABLED = "warning: CDS is disabled when the"; public Result(CDSOptions opts, OutputAnalyzer out) throws Exception { options = opts; @@ -126,7 +127,9 @@ public Result(CDSOptions opts, OutputAnalyzer out) throws Exception { hasNormalExit = (!hasMappingFailure) && (output.getExitValue() == 0); if (hasNormalExit) { - if ("on".equals(options.xShareMode) && output.getStderr().contains("java version")) { + if ("on".equals(options.xShareMode) && + output.getStderr().contains("java version") && + !output.getStderr().contains(CDS_DISABLED)) { // "-showversion" is always passed in the command-line by the execXXX methods. // During normal exit, we require that the VM to show that sharing was enabled. output.shouldContain("sharing"); @@ -150,6 +153,26 @@ public Result assertAbnormalExit(Checker checker) throws Exception { return this; } + // When {--limit-modules, --patch-module, and/or --upgrade-module-path} + // are specified, CDS is silently disabled for both -Xshare:auto and -Xshare:on. + public Result assertSilentlyDisabledCDS(Checker checker) throws Exception { + if (hasMappingFailure) { + throw new RuntimeException("Unexpected mapping failure"); + } + // this comes from a JVM warning message. + output.shouldContain(CDS_DISABLED); + + checker.check(output); + return this; + } + + public Result assertSilentlyDisabledCDS(int exitCode, String... matches) throws Exception { + return assertSilentlyDisabledCDS((out) -> { + out.shouldHaveExitValue(exitCode); + checkMatches(out, matches); + }); + } + public Result ifNormalExit(Checker checker) throws Exception { if (hasNormalExit) { checker.check(output); From 9df29bca23915d6e6346d7c38c6925b62f51d3bd Mon Sep 17 00:00:00 2001 From: erikj Date: Tue, 10 Apr 2018 22:37:01 +0200 Subject: [PATCH 125/196] 8201267: Disable warnings for VS2017 to enable building Reviewed-by: ihse, tbell --- make/CreateJmods.gmk | 26 ++++++++++++++----- make/autoconf/toolchain_windows.m4 | 1 - make/common/NativeCompilation.gmk | 22 +++++++++------- make/launcher/Launcher-jdk.pack.gmk | 1 + make/lib/Awt2dLibraries.gmk | 2 +- make/lib/Lib-jdk.accessibility.gmk | 2 ++ make/lib/Lib-jdk.pack.gmk | 1 + .../share/native/libinstrument/Reentrancy.c | 2 +- 8 files changed, 38 insertions(+), 19 deletions(-) diff --git a/make/CreateJmods.gmk b/make/CreateJmods.gmk index 9373499ace7..b1392711484 100644 --- a/make/CreateJmods.gmk +++ b/make/CreateJmods.gmk @@ -117,6 +117,17 @@ ifeq ($(MODULE), java.base) --hash-modules '^(?!$(EXCLUDE_PATTERN)$$)' endif endif +else # not java.base + ifeq ($(OPENJDK_TARGET_OS), windows) + # Only java.base needs to include the MSVC*_DLLs. Make sure no other module + # tries to include them (typically imported ones). + ifneq ($(wildcard $(LIBS_DIR)/$(notdir $(MSVCR_DLL))), ) + JMOD_FLAGS += --exclude '$(notdir $(MSVCR_DLL))' + endif + ifneq ($(wildcard $(LIBS_DIR)/$(notdir $(MSVCP_DLL))), ) + JMOD_FLAGS += --exclude '$(notdir $(MSVCP_DLL))' + endif + endif endif # Changes to the jmod tool itself should also trigger a rebuild of all jmods. @@ -133,18 +144,21 @@ ifeq ($(INTERIM_JMOD), true) DEPS := $(filter-out $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/classlist, $(DEPS)) endif +JMOD_FLAGS += --exclude '**{_the.*,_*.marker,*.diz,*.debuginfo,*.dSYM/**,*.dSYM,*.pdb,*.map}' + # Create jmods in a temp dir and then move them into place to keep the # module path in $(IMAGES_OUTPUTDIR)/jmods valid at all times. $(JMODS_DIR)/$(MODULE).jmod: $(DEPS) $(call LogWarn, Creating $(patsubst $(OUTPUTDIR)/%, %, $@)) $(call MakeDir, $(JMODS_DIR) $(JMODS_TEMPDIR)) $(RM) $@ $(JMODS_TEMPDIR)/$(notdir $@) - $(JMOD) create \ - --module-version $(VERSION_SHORT) \ - --target-platform '$(OPENJDK_MODULE_TARGET_PLATFORM)' \ - --module-path $(JMODS_DIR) \ - --exclude '**{_the.*,_*.marker,*.diz,*.debuginfo,*.dSYM/**,*.dSYM,*.pdb,*.map}' \ - $(JMOD_FLAGS) $(JMODS_TEMPDIR)/$(notdir $@) + $(call ExecuteWithLog, $(SUPPORT_OUTPUTDIR)/jmods/$(MODULE).jmod, \ + $(JMOD) create \ + --module-version $(VERSION_SHORT) \ + --target-platform '$(OPENJDK_MODULE_TARGET_PLATFORM)' \ + --module-path $(JMODS_DIR) \ + $(JMOD_FLAGS) $(JMODS_TEMPDIR)/$(notdir $@) \ + ) $(MV) $(JMODS_TEMPDIR)/$(notdir $@) $@ TARGETS += $(JMODS_DIR)/$(MODULE).jmod diff --git a/make/autoconf/toolchain_windows.m4 b/make/autoconf/toolchain_windows.m4 index 1adcc148cca..ea193b0b5eb 100644 --- a/make/autoconf/toolchain_windows.m4 +++ b/make/autoconf/toolchain_windows.m4 @@ -522,7 +522,6 @@ AC_DEFUN([TOOLCHAIN_CHECK_POSSIBLE_MSVC_DLL], if $ECHO "$MSVC_DLL_FILETYPE" | $GREP "$CORRECT_MSVCR_ARCH" 2>&1 > /dev/null; then AC_MSG_RESULT([ok]) MSVC_DLL="$POSSIBLE_MSVC_DLL" - BASIC_FIXUP_PATH(MSVC_DLL) AC_MSG_CHECKING([for $DLL_NAME]) AC_MSG_RESULT([$MSVC_DLL]) else diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index 9533493fd5c..daf56073d1d 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -905,20 +905,22 @@ define SetupNativeCompilationBody $1_IMPORT_LIBRARY := $$($1_OBJECT_DIR)/$$($1_NAME).lib $1_EXTRA_LDFLAGS += "-implib:$$($1_IMPORT_LIBRARY)" - # To properly trigger downstream dependants of the import library, just as - # for debug files, we must have a recipe in the rule. To avoid rerunning - # the recipe every time have it touch the target. If an import library - # file is deleted by something external, explicitly delete the target to - # trigger a rebuild of both. - ifneq ($$(wildcard $$($1_IMPORT_LIBRARY)), $$($1_IMPORT_LIBRARY)) - $$(call LogDebug, Deleting $$($1_BASENAME) because import library is missing) - $$(shell $(RM) $$($1_TARGET)) - endif - $$($1_IMPORT_LIBRARY): $$($1_TARGET) + ifeq ($$($1_TYPE), LIBRARY) + # To properly trigger downstream dependants of the import library, just as + # for debug files, we must have a recipe in the rule. To avoid rerunning + # the recipe every time have it touch the target. If an import library + # file is deleted by something external, explicitly delete the target to + # trigger a rebuild of both. + ifneq ($$(wildcard $$($1_IMPORT_LIBRARY)), $$($1_IMPORT_LIBRARY)) + $$(call LogDebug, Deleting $$($1_BASENAME) because import library is missing) + $$(shell $(RM) $$($1_TARGET)) + endif + $$($1_IMPORT_LIBRARY): $$($1_TARGET) $$(if $$(CORRECT_FUNCTION_IN_RECIPE_EVALUATION), \ $$(if $$(wildcard $$@), , $$(error $$@ was not created for $$<)) \ ) $(TOUCH) $$@ + endif endif $1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \ diff --git a/make/launcher/Launcher-jdk.pack.gmk b/make/launcher/Launcher-jdk.pack.gmk index 1e7debfda32..c66bed0d4e5 100644 --- a/make/launcher/Launcher-jdk.pack.gmk +++ b/make/launcher/Launcher-jdk.pack.gmk @@ -88,6 +88,7 @@ $(eval $(call SetupJdkExecutable, BUILD_UNPACKEXE, \ CFLAGS_solaris := -KPIC, \ CFLAGS_macosx := -fPIC, \ DISABLED_WARNINGS_gcc := unused-result implicit-fallthrough, \ + DISABLED_WARNINGS_microsoft := 4005, \ LDFLAGS := $(UNPACKEXE_ZIPOBJS) \ $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff --git a/make/lib/Awt2dLibraries.gmk b/make/lib/Awt2dLibraries.gmk index adc6c5826f8..f3205c1fcd8 100644 --- a/make/lib/Awt2dLibraries.gmk +++ b/make/lib/Awt2dLibraries.gmk @@ -543,7 +543,7 @@ else DISABLED_WARNINGS_solstudio := \ E_STATEMENT_NOT_REACHED \ E_END_OF_LOOP_CODE_NOT_REACHED, \ - DISABLED_WARNINGS_microsoft := 4267 4244, \ + DISABLED_WARNINGS_microsoft := 4267 4244 4312, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ )) diff --git a/make/lib/Lib-jdk.accessibility.gmk b/make/lib/Lib-jdk.accessibility.gmk index 9e899e8a773..ea35ab39293 100644 --- a/make/lib/Lib-jdk.accessibility.gmk +++ b/make/lib/Lib-jdk.accessibility.gmk @@ -45,6 +45,7 @@ ifeq ($(OPENJDK_TARGET_OS), windows) NAME := javaaccessbridge$1, \ SRC := $(JAVA_AB_SRCDIR), \ OPTIMIZATION := LOW, \ + DISABLED_WARNINGS_microsoft := 4311 4302 4312, \ CFLAGS := $(CFLAGS_JDKLIB) $(ACCESSBRIDGE_CFLAGS) \ $(addprefix -I,$(JAVA_AB_SRCDIR)) \ -I$(ROOT_SRCDIR)/include/bridge \ @@ -69,6 +70,7 @@ ifeq ($(OPENJDK_TARGET_OS), windows) NAME := windowsaccessbridge$1, \ SRC := $(WIN_AB_SRCDIR), \ OPTIMIZATION := LOW, \ + DISABLED_WARNINGS_microsoft := 4311 4302 4312, \ CFLAGS := $(filter-out -MD, $(CFLAGS_JDKLIB)) -MT $(ACCESSBRIDGE_CFLAGS) \ $(addprefix -I,$(WIN_AB_SRCDIR)) \ -I$(ROOT_SRCDIR)/include/bridge \ diff --git a/make/lib/Lib-jdk.pack.gmk b/make/lib/Lib-jdk.pack.gmk index 9884818852c..35fe7a41d4d 100644 --- a/make/lib/Lib-jdk.pack.gmk +++ b/make/lib/Lib-jdk.pack.gmk @@ -40,6 +40,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBUNPACK, \ $(LIBJAVA_HEADER_FLAGS), \ CFLAGS_release := -DPRODUCT, \ DISABLED_WARNINGS_gcc := implicit-fallthrough, \ + DISABLED_WARNINGS_microsoft := 4005, \ LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LDFLAGS_windows := -map:$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpack.map -debug, \ diff --git a/src/java.instrument/share/native/libinstrument/Reentrancy.c b/src/java.instrument/share/native/libinstrument/Reentrancy.c index 8cb69172bf7..2d923e23848 100644 --- a/src/java.instrument/share/native/libinstrument/Reentrancy.c +++ b/src/java.instrument/share/native/libinstrument/Reentrancy.c @@ -90,7 +90,7 @@ assertTLSValue( jvmtiEnv * jvmtienv, jthread thread, const void * expected) { jvmtiError error; - void * test = (void *) 0x99999999UL; + void * test = (void *) 0x99999999ULL; /* now check if we do a fetch we get what we wrote */ error = (*jvmtienv)->GetThreadLocalStorage( From 96a14f2634a35bdb7374c79fcb2e6187c79bb84c Mon Sep 17 00:00:00 2001 From: anazarov Date: Tue, 10 Apr 2018 14:16:13 -0700 Subject: [PATCH 126/196] 8178867: tools/jlink/multireleasejar/JLinkMultiReleaseJarTest.java failed to clean up files Reviewed-by: alanb, jjg, psandoz --- .../JLinkMultiReleaseJarTest.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/test/jdk/tools/jlink/multireleasejar/JLinkMultiReleaseJarTest.java b/test/jdk/tools/jlink/multireleasejar/JLinkMultiReleaseJarTest.java index c3c75783976..aafec448206 100644 --- a/test/jdk/tools/jlink/multireleasejar/JLinkMultiReleaseJarTest.java +++ b/test/jdk/tools/jlink/multireleasejar/JLinkMultiReleaseJarTest.java @@ -52,7 +52,9 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.Set; import java.util.jar.JarFile; import java.util.spi.ToolProvider; @@ -134,14 +136,15 @@ public void initialize() throws IOException { } private void javac(Path source, Path destination, String srcpath) throws IOException { - String[] args = Stream.concat( - Stream.of("-d", destination.toString(), "--module-source-path", srcpath), - Files.walk(source) - .map(Path::toString) - .filter(s -> s.endsWith(".java")) - ).toArray(String[]::new); - int rc = JAVAC_TOOL.run(System.out, System.err, args); - Assert.assertEquals(rc, 0); + var args = Stream.of("-d", destination.toString(), "--module-source-path", srcpath); + try (Stream pathStream = Files.walk(source)) { + args = Stream.concat(args, + pathStream.map(Path::toString) + .filter(s -> s.endsWith(".java"))); + + int rc = JAVAC_TOOL.run(System.out, System.err, args.toArray(String[]::new)); + Assert.assertEquals(rc, 0); + } } @Test @@ -149,7 +152,7 @@ public void basicTest() throws Throwable { if (ignoreTest()) return; // use jlink to build image from multi-release jar - jlink("m1.jar", "myimage"); + jlink("m1.jar", "myimage"); // validate image Path jimage = userdir.resolve("myimage").resolve("lib").resolve("modules"); From 244118025ea33b99c00cec5e43d53984b1e42f36 Mon Sep 17 00:00:00 2001 From: ihse Date: Tue, 10 Apr 2018 23:32:54 +0200 Subject: [PATCH 127/196] 8201320: Allow PrintFailureReports to be turned off Reviewed-by: erikj --- make/Init.gmk | 11 +- make/InitSupport.gmk | 216 ++++++++++++++++++++++--------------- make/autoconf/basics.m4 | 18 ++++ make/autoconf/configure.ac | 1 + make/autoconf/spec.gmk.in | 1 + 5 files changed, 158 insertions(+), 89 deletions(-) diff --git a/make/Init.gmk b/make/Init.gmk index 5027dd68af9..6de559e2c60 100644 --- a/make/Init.gmk +++ b/make/Init.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2018, 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 @@ -226,6 +226,15 @@ else # HAS_SPEC=true # Parse COMPARE_BUILD (for makefile development) $(eval $(call ParseCompareBuild)) + # If no LOG= was given on command line, but we have a non-standard default + # value, use that instead and re-parse log level. + ifeq ($(LOG), ) + ifneq ($(DEFAULT_LOG), ) + override LOG := $(DEFAULT_LOG) + $(eval $(call ParseLogLevel)) + endif + endif + ifeq ($(LOG_NOFILE), true) # Disable build log if LOG=[level,]nofile was given override BUILD_LOG_PIPE := diff --git a/make/InitSupport.gmk b/make/InitSupport.gmk index c63941f47ca..37bb7ebdd2f 100644 --- a/make/InitSupport.gmk +++ b/make/InitSupport.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2018, 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 @@ -131,73 +131,6 @@ ifeq ($(HAS_SPEC),) endif endef - # Look for a given option in the LOG variable, and if found, set a variable - # and remove the option from the LOG variable - # $1: The option to look for - # $2: The option to set to "true" if the option is found - define ParseLogOption - ifneq ($$(findstring $1, $$(LOG)),) - $2 := true - # COMMA is defined in spec.gmk, but that is not included yet - COMMA := , - # First try to remove ",