Path: blob/master/jcl/src/java.base/share/classes/java/lang/invoke/CollectHandle.java
12520 views
/*[INCLUDE-IF Sidecar17 & !OPENJDK_METHODHANDLES]*/1/*******************************************************************************2* Copyright (c) 2009, 2020 IBM Corp. and others3*4* This program and the accompanying materials are made available under5* the terms of the Eclipse Public License 2.0 which accompanies this6* distribution and is available at https://www.eclipse.org/legal/epl-2.0/7* or the Apache License, Version 2.0 which accompanies this distribution and8* is available at https://www.apache.org/licenses/LICENSE-2.0.9*10* This Source Code may also be made available under the following11* Secondary Licenses when the conditions for such availability set12* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU13* General Public License, version 2 with the GNU Classpath14* Exception [1] and GNU General Public License, version 2 with the15* OpenJDK Assembly Exception [2].16*17* [1] https://www.gnu.org/software/classpath/license.html18* [2] http://openjdk.java.net/legal/assembly-exception.html19*20* 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-exception21*******************************************************************************/22package java.lang.invoke;2324import com.ibm.oti.util.Msg;25import java.lang.reflect.Array;26/*[IF JAVA_SPEC_VERSION >= 15]*/27import java.util.List;28/*[ENDIF] JAVA_SPEC_VERSION >= 15 */2930/* CollectHandle is a MethodHandle subclass used to call another MethodHandle.31* It accepts the incoming arguments and collects the requested number32* of them into an array of type 'T'.33* <p>34* Return types can NOT be adapted by this handle.35* <p>36* Can't pre-allocate the collect array as its not thread-safe - same handle37* can be used in multiple threads or collected args array can be modified38* down the call chain.39*/40final class CollectHandle extends MethodHandle {41@VMCONSTANTPOOL_FIELD42final MethodHandle next;43@VMCONSTANTPOOL_FIELD44final int collectArraySize; /* Size of the collect array */45@VMCONSTANTPOOL_FIELD46final int collectPosition; /* The starting position of arguments to collect */47final Object emptyArray;4849CollectHandle(MethodHandle next, int collectArraySize, int collectPosition) {50super(collectMethodType(next.type(), collectArraySize, collectPosition), KIND_COLLECT, new int[]{collectArraySize, collectPosition});51this.collectPosition = collectPosition;52this.collectArraySize = collectArraySize;53this.next = next;54if (collectArraySize == 0) {55emptyArray = Array.newInstance(next.type.parameterType(collectPosition).getComponentType(), 0);56} else {57emptyArray = null;58}59}6061CollectHandle(CollectHandle original, MethodType newType) {62super(original, newType);63this.collectPosition = original.collectPosition;64this.collectArraySize = original.collectArraySize;65this.next = original.next;66this.emptyArray = original.emptyArray;67}6869private static final MethodType collectMethodType(MethodType type, int collectArraySize, int collectPosition) {70int parameterCount = type.parameterCount();71if (0 == parameterCount) {72/*[MSG "K05ca", "The argument of MethodType at '{0}' must be an array class"]*/73throw new IllegalArgumentException(Msg.getString("K05ca", collectPosition)); //$NON-NLS-1$74}75// Ensure the class at the specified position is an array76Class<?> arrayComponent = type.parameterType(collectPosition).getComponentType();77if (null == arrayComponent) {78/*[MSG "K05ca", "The argument of MethodType at '{0}' must be an array class"]*/79throw new IllegalArgumentException(Msg.getString("K05ca", collectPosition)); //$NON-NLS-1$80}81// Change the T[] into a 'T'82MethodType newType = type.changeParameterType(collectPosition, arrayComponent);8384// Add necessary additional 'T' to the type85if (0 == collectArraySize) {86newType = newType.dropParameterTypes(collectPosition , collectPosition + 1);87} else if (collectArraySize > 1) {88Class<?>[] classes = new Class[collectArraySize - 1];89int arrayLength = classes.length;90for (int j = 0; j < arrayLength; j++) {91classes[j] = arrayComponent;92}93newType = newType.insertParameterTypes(collectPosition + 1, classes);94}95return newType;96}9798@Override99MethodHandle cloneWithNewType(MethodType newType) {100return new CollectHandle(this, newType);101}102103/*[IF JAVA_SPEC_VERSION >= 15]*/104@Override105boolean addRelatedMHs(List<MethodHandle> relatedMHs) {106relatedMHs.add(next);107return true;108}109/*[ENDIF] JAVA_SPEC_VERSION >= 15 */110111// {{{ JIT support112113private static final ThunkTable _thunkTable = new ThunkTable();114protected final ThunkTable thunkTable(){ return _thunkTable; }115protected final ThunkTuple computeThunks(Object arg) {116int[] collectArguments = (int[]) arg;117return thunkTable().get(new ThunkKeyWithIntArray(ThunkKey.computeThunkableType(type()), collectArguments));118}119120private static final Object allocateArray(CollectHandle mh) {121return Array.newInstance(122mh.next.type.parameterType(mh.collectPosition).getComponentType(),123mh.collectArraySize);124}125126private static native int numArgsToCollect();127private static native int collectionStart();128private static native int numArgsAfterCollectArray();129130@FrameIteratorSkip131private final int invokeExact_thunkArchetype_X(int argPlaceholder) throws Throwable {132if (ILGenMacros.isShareableThunk()) {133undoCustomizationLogic(next);134}135if (!ILGenMacros.isCustomThunk()) {136doCustomizationLogic();137}138ILGenMacros.populateArray(139ILGenMacros.push(collectArraySize == 0 ? emptyArray : allocateArray(this)),140ILGenMacros.middleN(collectionStart(), numArgsToCollect(), argPlaceholder));141return ILGenMacros.invokeExact_X(142next,143ILGenMacros.placeholder(144ILGenMacros.firstN(collectionStart(), argPlaceholder),145ILGenMacros.pop_L(),146ILGenMacros.lastN(numArgsAfterCollectArray(), argPlaceholder)));147}148149// }}} JIT support150151final void compareWith(MethodHandle right, Comparator c) {152if (right instanceof CollectHandle) {153((CollectHandle)right).compareWithCollect(this, c);154} else {155c.fail();156}157}158159final void compareWithCollect(CollectHandle left, Comparator c) {160c.compareStructuralParameter(left.collectArraySize, this.collectArraySize);161c.compareStructuralParameter(left.collectPosition, this.collectPosition);162c.compareChildHandle(left.next, this.next);163}164}165166167