diff --git a/jcl/src/java.base/share/classes/com/ibm/oti/util/ExternalMessages-MasterIndex.properties b/jcl/src/java.base/share/classes/com/ibm/oti/util/ExternalMessages-MasterIndex.properties index 5aa7b6ebd88..dc784b7486f 100644 --- a/jcl/src/java.base/share/classes/com/ibm/oti/util/ExternalMessages-MasterIndex.properties +++ b/jcl/src/java.base/share/classes/com/ibm/oti/util/ExternalMessages-MasterIndex.properties @@ -1106,7 +1106,7 @@ K05cc=Cannot assign '{0}' to methodtype '{1}' K05cd=unable to resolve 'bootstrap_method_ref' in '{0}' at index {1} K05ce=Invalid method name: {0} K05cf=illegal setter on final field -K05d0=Can't apply fold of type: {0} to handle of type: {1} starting at {2} +K05d0=Can't apply preprocessor of type: {0} to handle of type: {1} starting at {2} K05d1=cannot have null spread argument unless spreadCount is 0 K05d2=expected '{0}' sized array; encountered '{1}' sized array K05d3=invalid descriptor: {0} @@ -1207,7 +1207,8 @@ K0636="No such field: {0}.{1}({2})" #java.lang.invoke.MethodHandles K0637=The value of {0}: {1} must be in a range from 0 to {2} K0638=The count of argument indices: {0} must be equal to the parameter count of the combiner: {1} -K063A=The return type of combiner: {0} is inconsistent with the argument type of fold handle: {1} at the fold position: {2} +K063A1=The return type of combiner: {0} is inconsistent with the argument type of {1} handle: {2} at the {3} position: {4} +K063A2=The return type of combiner should never be void. K063B=The return type of the try handle: {0} is inconsistent with the return type of the finally handle: {1} K063C=The 1st parameter type of the finally handle: {0} is not {1} K063D=The 2nd parameter type of the finally handle: {0} is inconsistent with the return type of the try handle: {1} diff --git a/jcl/src/java.base/share/classes/java/lang/Class.java b/jcl/src/java.base/share/classes/java/lang/Class.java index 5e7bb4b1ec4..1963dd0f3bc 100644 --- a/jcl/src/java.base/share/classes/java/lang/Class.java +++ b/jcl/src/java.base/share/classes/java/lang/Class.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar16]*/ /******************************************************************************* - * Copyright (c) 1998, 2018 IBM Corp. and others + * Copyright (c) 1998, 2019 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -27,6 +27,9 @@ import java.security.ProtectionDomain; import java.security.AllPermission; import java.security.Permissions; +/*[IF Java12]*/ +import java.lang.constant.ClassDesc; +/*[ENDIF] Java12*/ import java.lang.reflect.*; import java.net.URL; import java.lang.annotation.*; @@ -38,6 +41,9 @@ import java.util.List; import java.util.Map; import java.util.Set; +/*[IF Java12]*/ +import java.util.Optional; +/*[ENDIF] Java12 */ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import java.security.AccessController; @@ -4545,4 +4551,14 @@ public Class[] getNestMembers() throws LinkageError, SecurityException { return nestMembers; } /*[ENDIF] Java11 */ + +/*[IF Java12]*/ + public Class arrayType() { + throw new UnsupportedOperationException("Stub for Java 12 compilation"); + } + + public Optional describeConstable() { + throw new UnsupportedOperationException("Stub for Java 12 compilation"); + } +/*[ENDIF] Java12 */ } diff --git a/jcl/src/java.base/share/classes/java/lang/System.java b/jcl/src/java.base/share/classes/java/lang/System.java index e3c59aff7d9..0e3a87d3f32 100644 --- a/jcl/src/java.base/share/classes/java/lang/System.java +++ b/jcl/src/java.base/share/classes/java/lang/System.java @@ -36,7 +36,7 @@ import jdk.internal.access.SharedSecrets; /*[ELSE] import jdk.internal.misc.SharedSecrets; -/*[ENDIF]*/ +/*[ENDIF] Java12 */ import jdk.internal.misc.VM; import java.lang.StackWalker.Option; import java.lang.Module; @@ -141,16 +141,10 @@ static void afterClinitInitialization() { } // Fill in the properties from the VM information. - ensureProperties(); + ensureProperties(true); /*[PR CMVC 150472] sun.misc.SharedSecrets needs access to java.lang. */ SharedSecrets.setJavaLangAccess(new Access()); - - /*[PR CMVC 179976] System.setProperties(null) throws IllegalStateException */ - try { - VM.saveAndRemoveProperties(systemProperties); - } catch (NoSuchMethodError e) { - } /*[REM] Initialize the JITHelpers needed in J9VMInternals since the class can't do it itself */ try { @@ -362,28 +356,32 @@ private static void arraycopy(Object[] A1, int offset1, Object[] A2, int offset2 * provided by the virtual machine. */ @SuppressWarnings("nls") -private static void ensureProperties() { +private static void ensureProperties(boolean isInitialization) { /*[IF OpenJ9-RawBuild]*/ // invoke JCL native to initialize platform encoding initProperties(new Properties()); /*[ENDIF] OpenJ9-RawBuild */ - systemProperties = new Properties(); +/*[IF Java12]*/ + Map initializedProperties = new Hashtable(); +/*[ELSE] + Properties initializedProperties = new Properties(); +/*[ENDIF] Java12 */ if (osEncoding != null) { - systemProperties.put("os.encoding", osEncoding); //$NON-NLS-1$ + initializedProperties.put("os.encoding", osEncoding); //$NON-NLS-1$ } /*[PR The launcher apparently needs sun.jnu.encoding property or it does not work]*/ - systemProperties.put("ibm.system.encoding", platformEncoding); //$NON-NLS-1$ - systemProperties.put("sun.jnu.encoding", platformEncoding); //$NON-NLS-1$ - systemProperties.put("file.encoding", fileEncoding); //$NON-NLS-1$ - systemProperties.put("file.encoding.pkg", "sun.io"); //$NON-NLS-1$ //$NON-NLS-2$ + initializedProperties.put("ibm.system.encoding", platformEncoding); //$NON-NLS-1$ + initializedProperties.put("sun.jnu.encoding", platformEncoding); //$NON-NLS-1$ + initializedProperties.put("file.encoding", fileEncoding); //$NON-NLS-1$ + initializedProperties.put("file.encoding.pkg", "sun.io"); //$NON-NLS-1$ //$NON-NLS-2$ /*[IF !Java12]*/ /* System property java.specification.vendor is set via VersionProps.init(systemProperties) since JDK12 */ - systemProperties.put("java.specification.vendor", "Oracle Corporation"); //$NON-NLS-1$ //$NON-NLS-2$ + initializedProperties.put("java.specification.vendor", "Oracle Corporation"); //$NON-NLS-1$ //$NON-NLS-2$ /*[ENDIF] !Java12 */ - systemProperties.put("java.specification.name", "Java Platform API Specification"); //$NON-NLS-1$ //$NON-NLS-2$ - systemProperties.put("com.ibm.oti.configuration", "scar"); //$NON-NLS-1$ + initializedProperties.put("java.specification.name", "Java Platform API Specification"); //$NON-NLS-1$ //$NON-NLS-2$ + initializedProperties.put("com.ibm.oti.configuration", "scar"); //$NON-NLS-1$ String[] list = getPropertyList(); for (int i = 0; i < list.length; i += 2) { @@ -392,44 +390,84 @@ private static void ensureProperties() { if (key == null) { break; } - systemProperties.put(key, list[i+1]); + initializedProperties.put(key, list[i+1]); } - propertiesInitialized = true; - - /*[IF Java12]*/ /* java.lang.VersionProps.init() eventually calls into System.setProperty() where propertiesInitialized needs to be true */ - java.lang.VersionProps.init(systemProperties); + propertiesInitialized = true; + +/*[IF Java12]*/ + java.lang.VersionProps.init(initializedProperties); /* VersionProps.init(systemProperties) above sets java.specification.version value which is used to set java.vm.specification.version. */ - systemProperties.put("java.vm.specification.version", systemProperties.getProperty("java.specification.version")); //$NON-NLS-1$ //$NON-NLS-2$ - systemProperties.put("java.vm.vendor", systemProperties.getProperty("java.vendor")); //$NON-NLS-1$ //$NON-NLS-2$ - /*[ELSE] - /*[IF Sidecar19-SE]*/ - /* java.lang.VersionProps.init() eventually calls into System.setProperty() where propertiesInitialized needs to be true */ + initializedProperties.put("java.vm.specification.version", initializedProperties.get("java.specification.version")); //$NON-NLS-1$ //$NON-NLS-2$ + initializedProperties.put("java.vm.vendor", initializedProperties.get("java.vendor")); //$NON-NLS-1$ //$NON-NLS-2$ +/*[ELSE] + /* VersionProps.init requires systemProperties to be set */ + systemProperties = initializedProperties; + +/*[IF Sidecar19-SE]*/ java.lang.VersionProps.init(); - /*[ELSE]*/ +/*[ELSE] sun.misc.Version.init(); - /*[ENDIF] Sidecar19-SE */ - /*[ENDIF] Java12 */ - /*[IF !Sidecar19-SE]*/ StringBuffer.initFromSystemProperties(systemProperties); StringBuilder.initFromSystemProperties(systemProperties); - /*[ENDIF]*/ +/*[ENDIF] Sidecar19-SE */ +/*[ENDIF] Java12 */ - String javaRuntimeVersion = systemProperties.getProperty("java.runtime.version"); //$NON-NLS-1$ +/*[IF Java12]*/ + String javaRuntimeVersion = initializedProperties.get("java.runtime.version"); //$NON-NLS-1$ +/*[ELSE] + String javaRuntimeVersion = initializedProperties.getProperty("java.runtime.version"); //$NON-NLS-1$ +/*[ENDIF] Java12 */ if (null != javaRuntimeVersion) { - String fullVersion = systemProperties.getProperty("java.fullversion"); //$NON-NLS-1$ + /*[IF Java12]*/ + String fullVersion = initializedProperties.get("java.fullversion"); //$NON-NLS-1$ + /*[ELSE] + String fullVersion = initializedProperties.getProperty("java.fullversion"); //$NON-NLS-1$ + /*[ENDIF] Java12 */ if (null != fullVersion) { - systemProperties.put("java.fullversion", (javaRuntimeVersion + "\n" + fullVersion)); //$NON-NLS-1$ //$NON-NLS-2$ + initializedProperties.put("java.fullversion", (javaRuntimeVersion + "\n" + fullVersion)); //$NON-NLS-1$ //$NON-NLS-2$ } rasInitializeVersion(javaRuntimeVersion); } - lineSeparator = systemProperties.getProperty("line.separator", "\n"); //$NON-NLS-1$ +/*[IF Java12]*/ + lineSeparator = initializedProperties.getOrDefault("line.separator", "\n"); //$NON-NLS-1$ +/*[ELSE] + lineSeparator = initializedProperties.getProperty("line.separator", "\n"); //$NON-NLS-1$ +/*[ENDIF] Java12 */ /*[IF Sidecar19-SE]*/ - useLegacyVerPresents = systemProperties.containsKey("use.legacy.version"); + useLegacyVerPresents = initializedProperties.containsKey("use.legacy.version"); /*[ENDIF]*/ + + if (isInitialization) { + /*[PR CMVC 179976] System.setProperties(null) throws IllegalStateException */ + /*[IF Java12]*/ + VM.saveProperties(initializedProperties); + /*[ELSE] + VM.saveAndRemoveProperties(initializedProperties); + /*[ENDIF] Java12 */ + } + + /* create systemProperties from properties Map */ +/*[IF Java12]*/ + initializeSystemProperties(initializedProperties); +/*[ELSE] + systemProperties = initializedProperties; +/*[ENDIF] Java12 */ +} + +/* Converts a Map to a properties object. + * + * The sytem properties will be initialized as a Map type to be compatible + * with jdk.internal.misc.VM and java.lang.VersionProps APIs. + */ +private static void initializeSystemProperties(Map mapProperties) { + systemProperties = new Properties(); + for (Map.Entry property : mapProperties.entrySet()) { + systemProperties.put(property.getKey(), property.getValue()); + } } private static native void rasInitializeVersion(String javaRuntimeVersion); @@ -731,7 +769,7 @@ public static void setProperties(Properties p) { if (security != null) security.checkPropertiesAccess(); if (p == null) { - ensureProperties(); + ensureProperties(false); } else { systemProperties = p; } diff --git a/jcl/src/java.base/share/classes/java/lang/invoke/FilterArgumentsWithCombinerHandle.java b/jcl/src/java.base/share/classes/java/lang/invoke/FilterArgumentsWithCombinerHandle.java new file mode 100644 index 00000000000..32490668787 --- /dev/null +++ b/jcl/src/java.base/share/classes/java/lang/invoke/FilterArgumentsWithCombinerHandle.java @@ -0,0 +1,121 @@ +/*[INCLUDE-IF Java12]*/ +/******************************************************************************* + * Copyright (c) 2018, 2019 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be madpe available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package java.lang.invoke; + +/* + * Pseudocode example: + * handle: D original(A, B, C) + * filterPosition: 1 + * preprocessor: B filter(B, A) + * argumentIndices: {1, 0} + * + * resulting handle: + * D result(A a, B b, C c) { + * B e = filter(b, a) + * return original(a, e, c) + * } + */ +final class FilterArgumentsWithCombinerHandle extends MethodHandle { + protected final MethodHandle next; + protected final MethodHandle combiner; + private final int filterPosition; + private final int[] argumentIndices; + + FilterArgumentsWithCombinerHandle(MethodHandle next, int filterPosition, MethodHandle combiner, int... argumentIndices) { + super(next.type, KIND_FILTERARGUMENTS_WITHCOMBINER, infoAffectingThunks(combiner.type(), filterPosition, argumentIndices)); + this.next = next; + this.combiner = combiner; + this.filterPosition = filterPosition; + this.argumentIndices = argumentIndices; + } + + FilterArgumentsWithCombinerHandle(FilterArgumentsWithCombinerHandle originalHandle, MethodType newType) { + super(originalHandle, newType); + this.next = originalHandle.next; + this.combiner = originalHandle.combiner; + this.filterPosition = originalHandle.filterPosition; + this.argumentIndices = originalHandle.argumentIndices; + } + + static FilterArgumentsWithCombinerHandle get(MethodHandle next, int filterPosition, MethodHandle combiner, int... argumentIndices) { + return new FilterArgumentsWithCombinerHandle(next, filterPosition, combiner, argumentIndices); + } + + @Override + MethodHandle cloneWithNewType(MethodType newType) { + return new FilterArgumentsWithCombinerHandle(this, newType); + } + + private static Object[] infoAffectingThunks(MethodType combinerType, int filterPosition, int...argumentIndices) { + MethodType thunkableType = ThunkKey.computeThunkableType(combinerType); + Object[] result = {thunkableType, filterPosition, argumentIndices}; + return result; + } + + private static final ThunkTable _thunkTable = new ThunkTable(); + @Override + protected ThunkTable thunkTable(){ return _thunkTable; } + + @Override + protected final ThunkTuple computeThunks(Object info) { + return thunkTable().get(new ThunkKeyWithObjectArray(ThunkKey.computeThunkableType(type()), (Object[])info)); + } + + private static native int filterPosition(); + private static native int argumentIndices(); + /* create placeholder for combiner based on argumentIndices the original handle's arguments */ + private static native int argumentsForCombiner(int indice, int argPlaceholder); + /* number of arguments remaining after the filtered argument */ + private static native int numSuffixArgs(); + + @FrameIteratorSkip + private final int invokeExact_thunkArchetype_X(int argPlaceholder) { + if (ILGenMacros.isShareableThunk()) { + undoCustomizationLogic(combiner, next); + } + if (!ILGenMacros.isCustomThunk()) { + doCustomizationLogic(); + } + + return ILGenMacros.invokeExact_X(next, ILGenMacros.placeholder( + ILGenMacros.firstN(filterPosition(), argPlaceholder), + ILGenMacros.invokeExact(combiner, argumentsForCombiner(argumentIndices(), argPlaceholder)), + ILGenMacros.lastN(numSuffixArgs(), argPlaceholder))); + } + + @Override + final void compareWith(MethodHandle right, Comparator c) { + if (right instanceof FilterArgumentsWithCombinerHandle) { + ((FilterArgumentsWithCombinerHandle)right).compareWithFilterArgumentsWithCombiner(this, c); + } else { + c.fail(); + } + } + + final void compareWithFilterArgumentsWithCombiner(FilterArgumentsWithCombinerHandle left, Comparator c) { + c.compareChildHandle(left.next, this.next); + c.compareChildHandle(left.combiner, this.combiner); + c.compareStructuralParameter(left.filterPosition, this.filterPosition); + c.compareStructuralParameter(left.argumentIndices, this.argumentIndices); + } +} diff --git a/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandle.java b/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandle.java index 458a6f85ccc..078738360df 100644 --- a/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandle.java +++ b/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandle.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar17]*/ /******************************************************************************* - * Copyright (c) 2009, 2018 IBM Corp. and others + * Copyright (c) 2009, 2019 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -44,7 +44,7 @@ import jdk.internal.access.SharedSecrets; /*[ELSE] import jdk.internal.misc.SharedSecrets; -/*[ENDIF]*/ +/*[ENDIF] Java12 */ import jdk.internal.reflect.ConstantPool; /*[ELSE]*/ import sun.misc.Unsafe; @@ -119,6 +119,9 @@ public abstract class MethodHandle { /*[IF Panama]*/ static final byte KIND_NATIVE = 32; /*[ENDIF]*/ + /*[IF Java12]*/ + static final byte KIND_FILTERARGUMENTS_WITHCOMBINER = 33; + /*[ENDIF] Java12 */ /*[IF Sidecar18-SE-OpenJ9] MethodHandle asTypeCache = null; @@ -1363,6 +1366,21 @@ private MethodHandle returnFilterPlaceHolder() { return this; } + /*[IF Java12]*/ + /*[IF ]*/ + /* + * Used to preserve the MH on the stack when avoiding the call-in for + * filterArgumentsWithCombinerHandle. Must return 'this' so stackmapper will keep the MH + * alive. + */ + /*[ENDIF]*/ + @SuppressWarnings("unused") + @VMCONSTANTPOOL_METHOD + private MethodHandle filterArgumentsWithCombinerPlaceHolder() { + return this; + } + /*[ENDIF] Java12 */ + /*[IF ]*/ /* * Used to preserve the MH on the stack when avoiding the call-in for diff --git a/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index e136d29f795..92589cb351d 100644 --- a/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -63,7 +63,7 @@ /*[ELSE] import jdk.internal.misc.SharedSecrets; import jdk.internal.misc.JavaLangAccess; -/*[ENDIF]*/ +/*[ENDIF] Java12 */ import java.security.ProtectionDomain; import jdk.internal.org.objectweb.asm.ClassReader; /*[ELSE] Sidecar19-SE-OpenJ9 @@ -2791,7 +2791,118 @@ public static MethodHandle filterArguments(MethodHandle handle, int startPositio MethodHandle result = FilterArgumentsHandle.get(handle, startPosition, filters, newType); return result; } + +/*[IF Java12]*/ + /** + * Modifies a MethodHandle by applying a preprocessor handle as a filter to one of the arguments. + * The preprocessor's return type must be the same as the argument in handle at the filterPosition. + * The preprocessor handle accepts a subset of the original methods arguments, the subset and their order are + * dictated by the array argumentIndices. + * + * Pseudocode example: + * handle: D original(A, B, C) + * filterPosition: 1 + * preprocessor: B filter(B, A) + * argumentIndices: {1, 0} + * + * resulting handle: + * D result(A a, B b, C c) { + * B e = filter(b, a) + * return original(a, e, c) + * } + * + * @param handle - the handle to call after preprocessing + * @param filterPosition - the starting position to filter arguments + * @param preprocessor - a methodhandle that preprocesses some of the incoming arguments + * @param argumentIndices - an array of indices mapping the handle's arguments to the preprocessors inputs + * @return a MethodHandle that preprocesses some of the arguments to the handle + * @throws NullPointerException - if any of the arguments are null + * @throws IllegalArgumentException - if the preprocessor's return type differs from the first argument type of the handle, + * or if the arguments taken by the preprocessor isn't a subset of the arguments to the handle + * or if the element of argumentIndices is outside of the range of the handle's argument list + * or if the arguments specified by argumentIndices from the handle doesn't exactly match the the arguments taken by the preprocessor + */ + static MethodHandle filterArgumentsWithCombiner(MethodHandle handle, int filterPosition, MethodHandle preprocessor, int... argumentIndices) throws NullPointerException, IllegalArgumentException { + + /* create defensive copy of argument indices */ + int[] passedInargumentIndices = EMPTY_ARG_POSITIONS; + if (0 != argumentIndices.length) { + passedInargumentIndices = argumentIndices.clone(); + } + + MethodType handleType = handle.type; // implicit nullcheck + MethodType preprocessorType = preprocessor.type; // implicit nullcheck + Class preprocessorReturnClass = preprocessorType.returnType; + final int handleTypeParamCount = handleType.parameterCount(); + final int preprocessorTypeParamCount = preprocessorType.parameterCount(); + final int argIndexCount = passedInargumentIndices.length; + + if ((filterPosition < 0) || (filterPosition >= handleTypeParamCount)) { + /*[MSG "K0637", "The value of {0}: {1} must be in a range from 0 to {2}"]*/ + throw new IllegalArgumentException(Msg.getString("K0637", new Object[] { //$NON-NLS-1$ + "the filter position", Integer.toString(filterPosition), //$NON-NLS-1$ + Integer.toString(handleTypeParamCount)})); + } + if (preprocessorTypeParamCount != argIndexCount) { + /*[MSG "K0638", "The count of argument indices: {0} must be equal to the parameter count of the combiner: {1}"]*/ + throw new IllegalArgumentException(Msg.getString("K0638", new Object[] { //$NON-NLS-1$ + Integer.toString(argIndexCount), + Integer.toString(preprocessorTypeParamCount)})); + } + + for (int i = 0; i < argIndexCount; i++) { + if ((passedInargumentIndices[i] < 0) || (passedInargumentIndices[i] >= handleTypeParamCount)) { + /*[MSG "K0637", "The value of {0}: {1} must be in a range from 0 to {2}"]*/ + throw new IllegalArgumentException(Msg.getString("K0637", new Object[] { //$NON-NLS-1$ + "argument index", Integer.toString(passedInargumentIndices[i]), //$NON-NLS-1$ + Integer.toString(handleTypeParamCount)})); + } + } + + if (void.class == preprocessorReturnClass) { + /*[MSG "K063A2", "The return type of combiner should never be void."]*/ + throw new IllegalArgumentException(Msg.getString("K063A2")); //$NON-NLS-1$ + } + + if (preprocessorReturnClass != handleType.arguments[filterPosition]) { + /*[MSG "K063A1", "The return type of combiner: {0} is inconsistent with the argument type of {1} handle: {2} at the {3} position: {4}"]*/ + throw new IllegalArgumentException(Msg.getString("K063A1", new Object[] { //$NON-NLS-1$ + preprocessorReturnClass.getSimpleName(), "filter", + handleType.arguments[filterPosition].getSimpleName(), "filter", + Integer.toString(filterPosition)})); + } + + validateParametersOfCombiner(argIndexCount, preprocessorTypeParamCount, preprocessorType, handleType, passedInargumentIndices, filterPosition, 1); + + MethodHandle result = FilterArgumentsWithCombinerHandle.get(handle, filterPosition, preprocessor, passedInargumentIndices); + + return result; + } + + /** + * Produce a MethodHandle that preprocesses some of the arguments by calling the preprocessor handle. + * + * If the preprocessor handle has a return type, it must be the same as the argument type at foldPosition of the handle. + * If the preprocessor returns void, it does not contribute the first argument to the handle. + * In all cases, the preprocessor handle accepts a subset of the arguments for the handle. + * + * @param handle - the handle to call after preprocessing + * @param foldPosition - the starting position to fold arguments + * @param preprocessor - a methodhandle that preprocesses some of the incoming arguments + * @param argumentIndices - an array of indices of incoming arguments from the handle + * @return a MethodHandle that preprocesses some of the arguments to the handle before calling the next handle, possibly with an additional first argument + * @throws NullPointerException - if any of the arguments are null + * @throws IllegalArgumentException - if the preprocessor's return type is not void and it differs from the first argument type of the handle, + * or if the arguments taken by the preprocessor isn't a subset of the arguments to the handle + * or if the element of argumentIndices is outside of the range of the handle's argument list + * or if the arguments specified by argumentIndices from the handle doesn't exactly match the the arguments taken by the preprocessor + */ + static MethodHandle foldArgumentsWithCombiner(MethodHandle handle, int foldPosition, MethodHandle preprocessor, int... argumentIndices) throws NullPointerException, IllegalArgumentException { + return foldArguments(handle, foldPosition, preprocessor, argumentIndices); + } +/*[ENDIF] Java12 */ + /** * Produce a MethodHandle that preprocesses some of the arguments by calling the preprocessor handle. * @@ -2926,10 +3037,10 @@ private static final MethodHandle foldArgumentsCommon(MethodHandle handle, int f "<", Integer.toString(handleTypeParamCount)})); //$NON-NLS-1$ } if (preprocessorReturnClass != handleType.arguments[foldPosition]) { - /*[MSG "K063A", "The return type of combiner: {0} is inconsistent with the argument type of fold handle: {1} at the fold position: {2}"]*/ - throw new IllegalArgumentException(Msg.getString("K063A", new Object[] { //$NON-NLS-1$ - preprocessorReturnClass.getSimpleName(), - handleType.arguments[foldPosition].getSimpleName(), + /*[MSG "K063A1", "The return type of combiner: {0} is inconsistent with the argument type of {1} handle: {2} at the {3} position: {4}"]*/ + throw new IllegalArgumentException(Msg.getString("K063A1", new Object[] { //$NON-NLS-1$ + preprocessorReturnClass.getSimpleName(), "filter", + handleType.arguments[foldPosition].getSimpleName(), "filter", Integer.toString(foldPosition)})); } validateParametersOfCombiner(argIndexCount, preprocessorTypeParamCount, preprocessorType, handleType, argumentIndices, foldPosition, 1); @@ -2942,14 +3053,14 @@ private static void validateParametersOfCombiner(int argIndexCount, int preproce if (0 == argIndexCount) { for (int i = 0; i < preprocessorTypeParamCount; i++) { if (preprocessorType.arguments[i] != handleType.arguments[foldPosition + i + foldPlaceHolder]) { - /*[MSG "K05d0", "Can't apply fold of type: {0} to handle of type: {1} starting at {2} "]*/ + /*[MSG "K05d0", "Can't apply preprocessor of type: {0} to handle of type: {1} starting at {2} "]*/ throw new IllegalArgumentException(Msg.getString("K05d0", preprocessorType.toString(), handleType.toString(), Integer.toString(foldPosition))); //$NON-NLS-1$ } } } else { for (int i = 0; i < argIndexCount; i++) { if (preprocessorType.arguments[i] != handleType.arguments[argumentIndices[i]]) { - /*[MSG "K05d0", "Can't apply fold of type: {0} to handle of type: {1} starting at {2} "]*/ + /*[MSG "K05d0", "Can't apply preprocessor of type: {0} to handle of type: {1} starting at {2} "]*/ throw new IllegalArgumentException(Msg.getString("K05d0", preprocessorType.toString(), handleType.toString(), Integer.toString(foldPosition))); //$NON-NLS-1$ } } diff --git a/jcl/src/java.base/share/classes/java/lang/invoke/VarHandle.java b/jcl/src/java.base/share/classes/java/lang/invoke/VarHandle.java index 84f97e4e5e5..ab77e82e08a 100644 --- a/jcl/src/java.base/share/classes/java/lang/invoke/VarHandle.java +++ b/jcl/src/java.base/share/classes/java/lang/invoke/VarHandle.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar19-SE]*/ /******************************************************************************* - * Copyright (c) 2017, 2018 IBM Corp. and others + * Copyright (c) 2017, 2019 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -33,6 +33,13 @@ /*[ELSE]*/ import sun.misc.Unsafe; /*[ENDIF]*/ +/*[IF Java12]*/ +import java.lang.constant.ClassDesc; +import java.lang.constant.Constable; +import java.lang.constant.ConstantDesc; +import java.lang.constant.DirectMethodHandleDesc; +import java.lang.constant.DynamicConstantDesc; +/*[ENDIF] Java12 */ /** * Dynamically typed reference to a field, allowing read and write operations, @@ -921,4 +928,39 @@ static UnsupportedOperationException operationNotSupported(VarHandle varHandle) MethodHandle getFromHandleTable(int operation) { return handleTable[operation]; } + +/*[IF Java12]*/ + /* nominal descriptor of a VarHandle constant */ + public static final class VarHandleDesc extends DynamicConstantDesc { + + protected VarHandleDesc(DirectMethodHandleDesc bootstrapMethod, String constantName, ClassDesc constantType, ConstantDesc... bootstrapArgs) { + super(bootstrapMethod, constantName, constantType, bootstrapArgs); + throw OpenJDKCompileStub.OpenJDKCompileStubThrowError(); + } + + public static VarHandleDesc ofArray(ClassDesc arrayClass) { + throw OpenJDKCompileStub.OpenJDKCompileStubThrowError(); + } + + public static VarHandleDesc ofField(ClassDesc declaringClass, String name, ClassDesc fieldType) { + throw OpenJDKCompileStub.OpenJDKCompileStubThrowError(); + } + + public static VarHandleDesc ofStaticField(ClassDesc declaringClass, String name, ClassDesc fieldType) { + throw OpenJDKCompileStub.OpenJDKCompileStubThrowError(); + } + + public VarHandle resolveConstantDesc(MethodHandles.Lookup lookup) { + throw OpenJDKCompileStub.OpenJDKCompileStubThrowError(); + } + + public String toString() { + throw OpenJDKCompileStub.OpenJDKCompileStubThrowError(); + } + + public ClassDesc varType() { + throw OpenJDKCompileStub.OpenJDKCompileStubThrowError(); + } + } +/*[ENDIF] Java12 */ } diff --git a/jcl/src/java.base/share/classes/jdk/internal/misc/Unsafe.java b/jcl/src/java.base/share/classes/jdk/internal/misc/Unsafe.java index a5991c592b7..6f57cd416d6 100644 --- a/jcl/src/java.base/share/classes/jdk/internal/misc/Unsafe.java +++ b/jcl/src/java.base/share/classes/jdk/internal/misc/Unsafe.java @@ -1,6 +1,6 @@ /*[INCLUDE-IF Sidecar19-SE-OpenJ9]*/ /******************************************************************************* - * Copyright (c) 2017, 2018 IBM Corp. and others + * Copyright (c) 2017, 2019 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -30,6 +30,9 @@ import java.lang.reflect.Field; import java.security.ProtectionDomain; import java.util.Objects; +/*[IF Java12]*/ +import java.nio.ByteBuffer; +/*[ENDIF] Java12 */ public final class Unsafe { @@ -400,6 +403,28 @@ public final class Unsafe { * @param value Object to store in obj */ public native void putObject(Object obj, long offset, Object value); + +/*[IF Java12]*/ + /** + * Gets the value of the Object in the obj parameter referenced by offset. + * This is a non-volatile operation. + * + * @param obj object from which to retrieve the value + * @param offset position of the value in obj + * @return Object value stored in obj + */ + public native Object getReference(Object obj, long offset); + + /** + * Sets the value of the Object in the obj parameter at memory offset. + * This is a non-volatile operation. + * + * @param obj object into which to store the value + * @param offset position of the value in obj + * @param value Object to store in obj + */ + public native void putReference(Object obj, long offset, Object value); +/*[ENDIF] Java12 */ /** * Gets the value of the Object in memory referenced by address. @@ -571,6 +596,37 @@ public native Class defineClass0(String name, byte[] b, int offset, int bLeng public final native Object compareAndExchangeObject(Object obj, long offset, Object compareValue, Object exchangeValue); +/*[IF Java12]*/ + /** + * Atomically sets the parameter value at offset in obj if the compare value + * matches the existing value in the object. + * The get operation has memory semantics of getVolatile. + * The set operation has the memory semantics of setVolatile. + * + * @param obj object into which to store the value + * @param offset location to compare and store value in obj + * @param compareValue value that is expected to be in obj at offset + * @param setValue value that will be set in obj at offset if compare is successful + * @return boolean value indicating whether the field was updated + */ + public final native boolean compareAndSetReference(Object obj, long offset, Object compareValue, Object setValue); + + /** + * Atomically sets the parameter value at offset in obj if the compare value + * matches the existing value in the object. + * The get operation has memory semantics of getVolatile. + * The set operation has the memory semantics of setVolatile. + * + * @param obj object into which to store the value + * @param offset location to compare and store value in obj + * @param compareValue value that is expected to be in obj at offset + * @param exchangeValue value that will be set in obj at offset if compare is successful + * @return value in obj at offset before this operation. This will be compareValue if the exchange was successful + */ + public final native Object compareAndExchangeReference(Object obj, long offset, Object compareValue, + Object exchangeValue); +/*[ENDIF] Java12 */ + /** * Atomically gets the value of the byte in the obj parameter referenced by offset. * @@ -733,6 +789,26 @@ public final native Object compareAndExchangeObject(Object obj, long offset, Obj */ public native void putObjectVolatile(Object obj, long offset, Object value); +/*[IF Java12]*/ + /** + * Atomically gets the value of the Object in the obj parameter referenced by offset. + * + * @param obj object from which to retrieve the value + * @param offset position of the value in obj + * @return Object value stored in obj + */ + public native Object getReferenceVolatile(Object obj, long offset); + + /** + * Atomically sets the value of the Object in the obj parameter at memory offset. + * + * @param obj object into which to store the value + * @param offset position of the value in obj + * @param value Object to store in obj + */ + public native void putReferenceVolatile(Object obj, long offset, Object value); +/*[ENDIF] Java12 */ + /** * Makes permit available for thread parameter. * @@ -2704,6 +2780,106 @@ public final boolean weakCompareAndSetObject(Object obj, long offset, Object com return compareAndSetObject(obj, offset, compareValue, setValue); } +/*[IF Java12]*/ + /** + * Atomically sets the parameter value at offset in obj if the compare value + * matches the existing value in the object. + * The get operation has memory semantics of getAcquire. + * The set operation has the memory semantics of set. + * + * @param obj object into which to store the value + * @param offset location to compare and store value in obj + * @param compareValue value that is expected to be in obj at offset + * @param exchangeValue value that will be set in obj at offset if compare is successful + * @return value in obj at offset before this operation. This will be compareValue if the exchange was successful + */ + public final Object compareAndExchangeReferenceAcquire(Object obj, long offset, Object compareValue, + Object exchangeValue) { + return compareAndExchangeReference(obj, offset, compareValue, exchangeValue); + } + + /** + * Atomically sets the parameter value at offset in obj if the compare value + * matches the existing value in the object. + * The get operation has memory semantics of get. + * The set operation has the memory semantics of setRelease. + * + * @param obj object into which to store the value + * @param offset location to compare and store value in obj + * @param compareValue value that is expected to be in obj at offset + * @param exchangeValue value that will be set in obj at offset if compare is successful + * @return value in obj at offset before this operation. This will be compareValue if the exchange was successful + */ + public final Object compareAndExchangeReferenceRelease(Object obj, long offset, Object compareValue, + Object exchangeValue) { + return compareAndExchangeReference(obj, offset, compareValue, exchangeValue); + } + + /** + * Sets the parameter value at offset in obj if the compare value + * matches the existing value in the object. + * The get operation has memory semantics of get. + * The set operation has the memory semantics of set. + * + * @param obj object into which to store the value + * @param offset location to compare and store value in obj + * @param compareValue value that is expected to be in obj at offset + * @param setValue value that will be set in obj at offset if compare is successful + * @return boolean value indicating whether the field was updated + */ + public final boolean weakCompareAndSetReferencePlain(Object obj, long offset, Object compareValue, Object setValue) { + return compareAndSetReference(obj, offset, compareValue, setValue); + } + + /** + * Sets the parameter value at offset in obj if the compare value + * matches the existing value in the object. + * The get operation has memory semantics of getAcquire. + * The set operation has the memory semantics of set. + * + * @param obj object into which to store the value + * @param offset location to compare and store value in obj + * @param compareValue value that is expected to be in obj at offset + * @param setValue value that will be set in obj at offset if compare is successful + * @return boolean value indicating whether the field was updated + */ + public final boolean weakCompareAndSetReferenceAcquire(Object obj, long offset, Object compareValue, Object setValue) { + return compareAndSetReference(obj, offset, compareValue, setValue); + } + + /** + * Sets the parameter value at offset in obj if the compare value + * matches the existing value in the object. + * The get operation has memory semantics of get. + * The set operation has the memory semantics of setRelease. + * + * @param obj object into which to store the value + * @param offset location to compare and store value in obj + * @param compareValue value that is expected to be in obj at offset + * @param setValue value that will be set in obj at offset if compare is successful + * @return boolean value indicating whether the field was updated + */ + public final boolean weakCompareAndSetReferenceRelease(Object obj, long offset, Object compareValue, Object setValue) { + return compareAndSetReference(obj, offset, compareValue, setValue); + } + + /** + * Sets the parameter value at offset in obj if the compare value + * matches the existing value in the object. + * The get operation has memory semantics of get. + * The set operation has the memory semantics of set. + * + * @param obj object into which to store the value + * @param offset location to compare and store value in obj + * @param compareValue value that is expected to be in obj at offset + * @param setValue value that will be set in obj at offset if compare is successful + * @return boolean value indicating whether the field was updated + */ + public final boolean weakCompareAndSetReference(Object obj, long offset, Object compareValue, Object setValue) { + return compareAndSetReference(obj, offset, compareValue, setValue); + } +/*[ENDIF] Java12 */ + /** * Gets the value of the byte in the obj parameter referenced by offset using acquire semantics. * Preceding loads will not be reordered with subsequent loads/stores. @@ -2812,6 +2988,20 @@ public final Object getObjectAcquire(Object obj, long offset) { return getObjectVolatile(obj, offset); } + /*[IF Java12]*/ + /** + * Gets the value of the Object in the obj parameter referenced by offset using acquire semantics. + * Preceding loads will not be reordered with subsequent loads/stores. + * + * @param obj object from which to retrieve the value + * @param offset position of the value in obj + * @return Object value stored in obj + */ + public final Object getReferenceAcquire(Object obj, long offset) { + return getReferenceVolatile(obj, offset); + } + /*[ENDIF] Java12 */ + /** * Sets the value of the byte in the obj parameter at memory offset using acquire semantics. * Preceding stores will not be reordered with subsequent loads/stores. @@ -2919,6 +3109,20 @@ public final void putBooleanRelease(Object obj, long offset, boolean value) { public final void putObjectRelease(Object obj, long offset, Object value) { putObjectVolatile(obj, offset, value); } + +/*[IF Java12]*/ + /** + * Sets the value of the Object in the obj parameter at memory offset using acquire semantics. + * Preceding stores will not be reordered with subsequent loads/stores. + * + * @param obj object into which to store the value + * @param offset position of the value in obj + * @param value Object to store in obj + */ + public final void putReferenceRelease(Object obj, long offset, Object value) { + putReferenceVolatile(obj, offset, value); + } +/*[ENDIF] Java12 */ /** * Gets the value of the byte in the obj parameter referenced by offset. @@ -3028,6 +3232,20 @@ public final Object getObjectOpaque(Object obj, long offset) { return getObjectVolatile(obj, offset); } +/*[IF Java12]*/ + /** + * Gets the value of the Object in the obj parameter referenced by offset. + * The operation is in program order, but does enforce ordering with respect to other threads. + * + * @param obj object from which to retrieve the value + * @param offset position of the value in obj + * @return Object value stored in obj + */ + public final Object getReferenceOpaque(Object obj, long offset) { + return getReferenceVolatile(obj, offset); + } +/*[ENDIF] Java12 */ + /** * Sets the value of the byte in the obj parameter at memory offset. * The operation is in program order, but does enforce ordering with respect to other threads. @@ -3136,6 +3354,20 @@ public final void putObjectOpaque(Object obj, long offset, Object value) { putObjectVolatile(obj, offset, value); } +/*[IF Java12]*/ + /** + * Sets the value of the Object in the obj parameter at memory offset. + * The operation is in program order, but does enforce ordering with respect to other threads. + * + * @param obj object into which to store the value + * @param offset position of the value in obj + * @param value Object to store in obj + */ + public final void putReferenceOpaque(Object obj, long offset, Object value) { + putReferenceVolatile(obj, offset, value); + } +/*[ENDIF] Java12 */ + /** * Get the load average in the system. * @@ -4092,6 +4324,68 @@ public final Object getAndSetObjectAcquire(Object obj, long offset, Object value } } +/*[IF Java12]*/ + /** + * Atomically sets value at offset in obj + * and returns the value of the field prior to the update. + * The get operation has the memory semantics of getVolatile. + * The set operation has the memory semantics of setVolatile. + * + * @param obj object into which to set the value + * @param offset location to set value in obj + * @param value to set in obj memory + * @return value of field in obj at offset before update + */ + public final Object getAndSetReference(Object obj, long offset, Object value) { + for (;;) { + Object objectAtOffset = getReferenceVolatile(obj, offset); + if (compareAndSetReference(obj, offset, objectAtOffset, value)) { + return objectAtOffset; + } + } + } + + /** + * Atomically sets value at offset in obj + * and returns the value of the field prior to the update. + * The get operation has the memory semantics of get. + * The set operation has the memory semantics of setRelease. + * + * @param obj object into which to set the value + * @param offset location to set value in obj + * @param value to set in obj memory + * @return value of field in obj at offset before update + */ + public final Object getAndSetReferenceRelease(Object obj, long offset, Object value) { + for (;;) { + Object objectAtOffset = getReference(obj, offset); + if (weakCompareAndSetReferenceRelease(obj, offset, objectAtOffset, value)) { + return objectAtOffset; + } + } + } + + /** + * Atomically sets value at offset in obj + * and returns the value of the field prior to the update. + * The get operation has the memory semantics of getAcquire. + * The set operation has the memory semantics of set. + * + * @param obj object into which to set the value + * @param offset location to set value in obj + * @param value to set in obj memory + * @return value of field in obj at offset before update + */ + public final Object getAndSetReferenceAcquire(Object obj, long offset, Object value) { + for (;;) { + Object objectAtOffset = getReferenceAcquire(obj, offset); + if (weakCompareAndSetReferenceAcquire(obj, offset, objectAtOffset, value)) { + return objectAtOffset; + } + } + } +/*[ENDIF] Java12 */ + /** * Atomically OR's the given value to the current value of the * field at offset in obj and returns the value of the field prior @@ -5536,6 +5830,15 @@ public final void putCharUnaligned(Object obj, long offset, char value, boolean putCharUnaligned(obj, offset, endianValue); } +/*[IF Java12]*/ + /** + * Stub for Java 12 compilation + */ + public void invokeCleaner(ByteBuffer arg) { + throw new UnsupportedOperationException("Stub for Java 12 compilation"); //$NON-NLS-1$ + } +/*[ENDIF] Java12 */ + /* * Private methods */ diff --git a/runtime/compiler/codegen/J9RecognizedMethodsEnum.hpp b/runtime/compiler/codegen/J9RecognizedMethodsEnum.hpp index 7038538d5b9..8037086d942 100644 --- a/runtime/compiler/codegen/J9RecognizedMethodsEnum.hpp +++ b/runtime/compiler/codegen/J9RecognizedMethodsEnum.hpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corp. and others + * Copyright (c) 2000, 2019 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -956,6 +956,10 @@ java_lang_invoke_FoldHandle_argIndices, java_lang_invoke_FoldHandle_argumentsForCombiner, java_lang_invoke_FoldHandle_foldPosition, + java_lang_invoke_FilterArgumentsWithCombinerHandle_filterPosition, + java_lang_invoke_FilterArgumentsWithCombinerHandle_argumentIndices, + java_lang_invoke_FilterArgumentsWithCombinerHandle_argumentsForCombiner, + java_lang_invoke_FilterArgumentsWithCombinerHandle_numSuffixArgs, java_lang_invoke_GuardWithTestHandle_numGuardArgs, java_lang_invoke_ILGenMacros_arrayElements, java_lang_invoke_ILGenMacros_arrayLength, diff --git a/runtime/compiler/env/j9method.cpp b/runtime/compiler/env/j9method.cpp index 09a5914b83c..72f867a2977 100644 --- a/runtime/compiler/env/j9method.cpp +++ b/runtime/compiler/env/j9method.cpp @@ -3204,6 +3204,7 @@ TR_ResolvedJ9Method::TR_ResolvedJ9Method(TR_OpaqueMethodBlock * aMethod, TR_Fron {x(TR::sun_misc_Unsafe_putFloat_jlObjectJF_V, "putFloat", "(Ljava/lang/Object;JF)V")}, {x(TR::sun_misc_Unsafe_putDouble_jlObjectJD_V, "putDouble", "(Ljava/lang/Object;JD)V")}, {x(TR::sun_misc_Unsafe_putObject_jlObjectJjlObject_V, "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V")}, + {x(TR::sun_misc_Unsafe_putObject_jlObjectJjlObject_V, "putReference", "(Ljava/lang/Object;JLjava/lang/Object;)V")}, {x(TR::sun_misc_Unsafe_putBooleanVolatile_jlObjectJZ_V, "putBooleanVolatile", "(Ljava/lang/Object;JZ)V")}, {x(TR::sun_misc_Unsafe_putByteVolatile_jlObjectJB_V, "putByteVolatile", "(Ljava/lang/Object;JB)V")}, @@ -3214,6 +3215,7 @@ TR_ResolvedJ9Method::TR_ResolvedJ9Method(TR_OpaqueMethodBlock * aMethod, TR_Fron {x(TR::sun_misc_Unsafe_putFloatVolatile_jlObjectJF_V, "putFloatVolatile", "(Ljava/lang/Object;JF)V")}, {x(TR::sun_misc_Unsafe_putDoubleVolatile_jlObjectJD_V, "putDoubleVolatile", "(Ljava/lang/Object;JD)V")}, {x(TR::sun_misc_Unsafe_putObjectVolatile_jlObjectJjlObject_V, "putObjectVolatile", "(Ljava/lang/Object;JLjava/lang/Object;)V")}, + {x(TR::sun_misc_Unsafe_putObjectVolatile_jlObjectJjlObject_V, "putReferenceVolatile", "(Ljava/lang/Object;JLjava/lang/Object;)V")}, {x(TR::sun_misc_Unsafe_putBooleanVolatile_jlObjectJZ_V, "putBooleanRelease", "(Ljava/lang/Object;JZ)V")}, {x(TR::sun_misc_Unsafe_putByteVolatile_jlObjectJB_V, "putByteRelease", "(Ljava/lang/Object;JB)V")}, @@ -3236,6 +3238,7 @@ TR_ResolvedJ9Method::TR_ResolvedJ9Method(TR_OpaqueMethodBlock * aMethod, TR_Fron {x(TR::sun_misc_Unsafe_getFloat_jlObjectJ_F, "getFloat", "(Ljava/lang/Object;J)F")}, {x(TR::sun_misc_Unsafe_getDouble_jlObjectJ_D, "getDouble", "(Ljava/lang/Object;J)D")}, {x(TR::sun_misc_Unsafe_getObject_jlObjectJ_jlObject, "getObject", "(Ljava/lang/Object;J)Ljava/lang/Object;")}, + {x(TR::sun_misc_Unsafe_getObject_jlObjectJ_jlObject, "getReference", "(Ljava/lang/Object;J)Ljava/lang/Object;")}, {x(TR::sun_misc_Unsafe_getBooleanVolatile_jlObjectJ_Z, "getBooleanVolatile", "(Ljava/lang/Object;J)Z")}, {x(TR::sun_misc_Unsafe_getByteVolatile_jlObjectJ_B, "getByteVolatile", "(Ljava/lang/Object;J)B")}, @@ -3246,6 +3249,7 @@ TR_ResolvedJ9Method::TR_ResolvedJ9Method(TR_OpaqueMethodBlock * aMethod, TR_Fron {x(TR::sun_misc_Unsafe_getFloatVolatile_jlObjectJ_F, "getFloatVolatile", "(Ljava/lang/Object;J)F")}, {x(TR::sun_misc_Unsafe_getDoubleVolatile_jlObjectJ_D, "getDoubleVolatile", "(Ljava/lang/Object;J)D")}, {x(TR::sun_misc_Unsafe_getObjectVolatile_jlObjectJ_jlObject, "getObjectVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;")}, + {x(TR::sun_misc_Unsafe_getObjectVolatile_jlObjectJ_jlObject, "getReferenceVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;")}, {x(TR::sun_misc_Unsafe_getBooleanVolatile_jlObjectJ_Z, "getBooleanAcquire", "(Ljava/lang/Object;J)Z")}, {x(TR::sun_misc_Unsafe_getByteVolatile_jlObjectJ_B, "getByteAcquire", "(Ljava/lang/Object;J)B")}, @@ -3281,10 +3285,12 @@ TR_ResolvedJ9Method::TR_ResolvedJ9Method(TR_OpaqueMethodBlock * aMethod, TR_Fron {x(TR::sun_misc_Unsafe_compareAndSwapLong_jlObjectJJJ_Z, "compareAndSetLong", "(Ljava/lang/Object;JJJ)Z")}, {x(TR::sun_misc_Unsafe_compareAndSwapObject_jlObjectJjlObjectjlObject_Z, "compareAndSwapObject", "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z")}, {x(TR::sun_misc_Unsafe_compareAndSwapObject_jlObjectJjlObjectjlObject_Z, "compareAndSetObject", "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z")}, + {x(TR::sun_misc_Unsafe_compareAndSwapObject_jlObjectJjlObjectjlObject_Z, "compareAndSetReference", "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z")}, {x(TR::sun_misc_Unsafe_compareAndExchangeInt_jlObjectJII_Z, "compareAndExchangeInt", "(Ljava/lang/Object;JII)I")}, {x(TR::sun_misc_Unsafe_compareAndExchangeLong_jlObjectJJJ_Z, "compareAndExchangeLong", "(Ljava/lang/Object;JJJ)J")}, {x(TR::sun_misc_Unsafe_compareAndExchangeObject_jlObjectJjlObjectjlObject_Z, "compareAndExchangeObject", "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")}, + {x(TR::sun_misc_Unsafe_compareAndExchangeObject_jlObjectJjlObjectjlObject_Z, "compareAndExchangeReference", "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")}, {x(TR::sun_misc_Unsafe_compareAndExchangeInt_jlObjectJII_Z, "compareAndExchangeIntVolatile", "(Ljava/lang/Object;JII)I")}, {x(TR::sun_misc_Unsafe_compareAndExchangeLong_jlObjectJJJ_Z, "compareAndExchangeLongVolatile", "(Ljava/lang/Object;JJJ)J")}, @@ -3861,7 +3867,7 @@ TR_ResolvedJ9Method::TR_ResolvedJ9Method(TR_OpaqueMethodBlock * aMethod, TR_Fron static X VarHandleMethods[] = { - // Recognized method only works for resovled methods + // Recognized method only works for resolved methods // Resolved VarHandle access methods are suffixed with _impl in their names // A list for unresolved VarHandle access methods is in VarHandleTransformer.cpp, // changes in the following list need to be reflected in the other @@ -4021,6 +4027,14 @@ TR_ResolvedJ9Method::TR_ResolvedJ9Method(TR_OpaqueMethodBlock * aMethod, TR_Fron { TR::java_lang_invoke_FoldHandle_argumentsForCombiner, 20, "argumentsForCombiner", (int16_t)-1, "*"}, { TR::unknownMethod} }; + static X FilterArgumentsWithCombinerHandleMethods[] = + { + {x(TR::java_lang_invoke_FilterArgumentsWithCombinerHandle_filterPosition, "filterPosition", "()I")}, + {x(TR::java_lang_invoke_FilterArgumentsWithCombinerHandle_argumentIndices, "argumentIndices", "()I")}, + {x(TR::java_lang_invoke_FilterArgumentsWithCombinerHandle_numSuffixArgs, "numSuffixArgs", "()I")}, + { TR::java_lang_invoke_FilterArgumentsWithCombinerHandle_argumentsForCombiner, 20, "argumentsForCombiner", (int16_t)-1, "*"}, + { TR::unknownMethod} + }; static X FinallyHandleMethods[]= { @@ -4241,6 +4255,7 @@ TR_ResolvedJ9Method::TR_ResolvedJ9Method(TR_OpaqueMethodBlock * aMethod, TR_Fron struct Y { const char * _class; X * _methods; }; + /* classXX where XX is the number of characters in the class name */ static Y class13[] = { { "java/nio/Bits", BitsMethods }, @@ -4535,6 +4550,7 @@ TR_ResolvedJ9Method::TR_ResolvedJ9Method(TR_OpaqueMethodBlock * aMethod, TR_Fron static Y class50[] = { { "java/util/concurrent/atomic/AtomicLongFieldUpdater", JavaUtilConcurrentAtomicLongFieldUpdaterMethods }, + { "java/lang/invoke/FilterArgumentsWithCombinerHandle", FilterArgumentsWithCombinerHandleMethods }, { 0 } }; @@ -8135,6 +8151,29 @@ TR_J9ByteCodeIlGenerator::runFEMacro(TR::SymbolReference *symRef) } return true; } + case TR::java_lang_invoke_FilterArgumentsWithCombinerHandle_argumentIndices: + { + TR_ASSERT(archetypeParmCount == 0, "assertion failure"); // The number of arguments for argumentIndices() + J9::MethodHandleThunkDetails *thunkDetails = getMethodHandleThunkDetails(this, comp(), symRef); + if (!thunkDetails) + return false; + + uintptrj_t methodHandle; + uintptrj_t argumentIndices; + { + TR::VMAccessCriticalSection invokeFilterArgumentsWithCombinerHandle(fej9); + methodHandle = *thunkDetails->getHandleRef(); + argumentIndices = fej9->getReferenceField(methodHandle, "argumentIndices", "[I"); + int32_t arrayLength = (int32_t)fej9->getArrayLengthInElements(argumentIndices); + // Push the indices in reverse order + for (int i = arrayLength - 1; i >= 0; i--) { + int32_t index = fej9->getInt32Element(argumentIndices, i); + loadConstant(TR::iconst, index); + } + loadConstant(TR::iconst, arrayLength); // number of arguments + } + return true; + } case TR::java_lang_invoke_FoldHandle_foldPosition: { TR_ASSERT(archetypeParmCount == 0, "assertion failure"); // The number of arguments for foldPosition() @@ -8154,7 +8193,27 @@ TR_J9ByteCodeIlGenerator::runFEMacro(TR::SymbolReference *symRef) loadConstant(TR::iconst, foldPosition); return true; } + case TR::java_lang_invoke_FilterArgumentsWithCombinerHandle_filterPosition: + { + TR_ASSERT(archetypeParmCount == 0, "assertion failure"); // The number of arguments for filterPosition() + + J9::MethodHandleThunkDetails *thunkDetails = getMethodHandleThunkDetails(this, comp(), symRef); + if (!thunkDetails) + return false; + + uintptrj_t methodHandle; + int32_t filterPosition; + { + TR::VMAccessCriticalSection invokeFilterArgumentsWithCombinerHandle(fej9); + methodHandle = *thunkDetails->getHandleRef(); + filterPosition = fej9->getInt32Field(methodHandle, "filterPosition"); + } + + loadConstant(TR::iconst, filterPosition); + return true; + } case TR::java_lang_invoke_FoldHandle_argumentsForCombiner: + case TR::java_lang_invoke_FilterArgumentsWithCombinerHandle_argumentsForCombiner: { TR::Node *placeholder = genNodeAndPopChildren(TR::icall, 1, placeholderWithDummySignature()); @@ -8220,7 +8279,30 @@ TR_J9ByteCodeIlGenerator::runFEMacro(TR::SymbolReference *symRef) loadConstant(TR::iconst, numArgsPassToFinallyTarget); return true; } + case TR::java_lang_invoke_FilterArgumentsWithCombinerHandle_numSuffixArgs: + { + TR_ASSERT(archetypeParmCount == 0, "assertion failure"); + J9::MethodHandleThunkDetails *thunkDetails = getMethodHandleThunkDetails(this, comp(), symRef); + if (!thunkDetails) + return false; + + uintptrj_t methodHandle; + uintptrj_t arguments; + int32_t numArguments; + int32_t filterPos; + + { + TR::VMAccessCriticalSection invokeFilterArgumentsWithCombinerHandle(fej9); + methodHandle = *thunkDetails->getHandleRef(); + arguments = fej9->getReferenceField(fej9->methodHandle_type(methodHandle), "arguments", "[Ljava/lang/Class;"); + numArguments = (int32_t)fej9->getArrayLengthInElements(arguments); + filterPos = (int32_t)fej9->getInt32Field(methodHandle, "filterPosition"); + } + + loadConstant(TR::iconst, numArguments - (filterPos + 1)); + return true; + } case TR::java_lang_invoke_FilterArgumentsHandle_numPrefixArgs: case TR::java_lang_invoke_FilterArgumentsHandle_numSuffixArgs: case TR::java_lang_invoke_FilterArgumentsHandle_numArgsToFilter: @@ -8239,7 +8321,7 @@ TR_J9ByteCodeIlGenerator::runFEMacro(TR::SymbolReference *symRef) int32_t numFilters; { - TR::VMAccessCriticalSection invokeFilderArgumentsHandle(fej9); + TR::VMAccessCriticalSection invokeFilterArgumentsHandle(fej9); methodHandle = *thunkDetails->getHandleRef(); arguments = fej9->getReferenceField(fej9->methodHandle_type(methodHandle), "arguments", "[Ljava/lang/Class;"); numArguments = (int32_t)fej9->getArrayLengthInElements(arguments); diff --git a/runtime/oti/VM_MethodHandleKinds.h b/runtime/oti/VM_MethodHandleKinds.h index 13ae1bc0e1e..6e5eb088208 100644 --- a/runtime/oti/VM_MethodHandleKinds.h +++ b/runtime/oti/VM_MethodHandleKinds.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 1991, 2018 IBM Corp. and others + * Copyright (c) 1991, 2019 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -58,5 +58,6 @@ #ifdef J9VM_OPT_PANAMA #define J9_METHOD_HANDLE_KIND_NATIVE 0x20 #endif +#define J9_METHOD_HANDLE_KIND_FILTER_ARGUMENTS_WITH_COMBINER 0x21 #endif /* VM_METHODHANDLEKINDS_H_ */ diff --git a/runtime/oti/vmconstantpool.xml b/runtime/oti/vmconstantpool.xml index f69048a85c2..dc56ebe85e1 100644 --- a/runtime/oti/vmconstantpool.xml +++ b/runtime/oti/vmconstantpool.xml @@ -1,6 +1,6 @@