Path: blob/master/jcl/src/java.base/share/classes/java/lang/invoke/ConvertHandle.java
12521 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 java.lang.invoke.MethodHandles.Lookup;25import java.util.concurrent.ConcurrentHashMap;26/*[IF JAVA_SPEC_VERSION >= 15]*/27import java.util.List;28/*[ENDIF] JAVA_SPEC_VERSION >= 15 */2930import com.ibm.oti.util.Msg;3132abstract class ConvertHandle extends MethodHandle {33@VMCONSTANTPOOL_FIELD34final MethodHandle next;3536ConvertHandle(MethodHandle handle, MethodType type, byte kind, Object thunkArg) {37super(type, kind, thunkArg);38if ((handle == null) || (type == null)) {39throw new IllegalArgumentException();40}41this.next = handle;42}4344ConvertHandle(ConvertHandle originalHandle, MethodType newType) {45super(originalHandle, newType);46this.next = originalHandle.next;47this.requiresBoxing = originalHandle.requiresBoxing;48}4950@VMCONSTANTPOOL_FIELD51boolean requiresBoxing = false;5253/*54* Determine if the arguments can be converted from the MethodType fromType to that of toType.55* Return conversions are handled by FilterReturnHandle.56*/57final void checkConversion(MethodType toType, MethodType fromType) {58Class<?>[] toArgs = toType.ptypes();59Class<?>[] fromArgs = fromType.ptypes();6061if (toArgs.length != fromArgs.length) {62throwWrongMethodTypeException(fromType, toType, toArgs.length);63}6465boolean isExplicitCast = (kind == KIND_EXPLICITCAST);6667// Ensure argsToCollect can be converted to type of array68for (int i = 0; i < toArgs.length; i++ ) {69Class<?> toClass = toArgs[i];70Class<?> fromClass = fromArgs[i];7172// identity conversion73if (fromClass == toClass) {74continue;75}7677boolean toIsPrimitive = toClass.isPrimitive();78boolean fromIsPrimitive = fromClass.isPrimitive();7980// both are reference types, then apply a cast at runtime81if (!toIsPrimitive && !fromIsPrimitive) {82continue;83}8485// primitive to primitive conversion86if (toIsPrimitive && fromIsPrimitive) {87// if not explicitCast, only widening primitive conversions allowed88if (isExplicitCast || FilterHelpers.checkIfWideningPrimitiveConversion(fromClass, toClass)) {89continue;90}91throwWrongMethodTypeException(fromType, toType, i);92}9394// unbox + widening primitive conversion95if (toIsPrimitive) {96if (isExplicitCast) {97continue;98} else {99// fromClass is reference type { Object, Number, Boolean, Byte, Integer, etc }100Class<?> unwrappedFromClass = MethodTypeHelper.unwrapPrimitive(fromClass);101if ((toClass == unwrappedFromClass) ||102fromClass.isAssignableFrom(MethodTypeHelper.wrapPrimitive(toClass)) ||103FilterHelpers.checkIfWideningPrimitiveConversion(unwrappedFromClass, toClass)) {104continue;105}106}107throwWrongMethodTypeException(fromType, toType, i);108}109110// toClass is reference type111// primitive wrapper is subclass of fromClass112if (toClass.isAssignableFrom(MethodTypeHelper.wrapPrimitive(fromClass))) {113requiresBoxing = true;114continue;115}116throwWrongMethodTypeException(fromType, toType, i);117}118}119120static final void throwWrongMethodTypeException(MethodType fromType, MethodType toType, int index) throws WrongMethodTypeException {121/*[MSG "K05cb", "No conversion from '{0}' to '{1} at index ({2})"]*/122throw new WrongMethodTypeException(Msg.getString("K05cb", fromType.toString(), toType.toString(), Integer.toString(index))); //$NON-NLS-1$123}124125/*[IF ]*/126protected void dumpDetailsTo(java.io.PrintStream out, String prefix, java.util.Set<MethodHandle> alreadyDumped) {127super.dumpDetailsTo(out, prefix, alreadyDumped);128next.dumpTo(out, prefix, "next: ", alreadyDumped); //$NON-NLS-1$129}130/*[ENDIF]*/131132static final class FilterHelpers {133/* shared privileged lookup object */134static Lookup privilegedLookup = MethodHandles.Lookup.internalPrivilegedLookup;135136/* local cache of previously looked up filters */137static final ConcurrentHashMap<MethodType, MethodHandle> cachedReturnFilters = new ConcurrentHashMap<MethodType, MethodHandle>();138139/*140* Return conversions: explicit vs asType handled by the boolean isExplicitCast141*/142static MethodHandle getReturnFilter(Class<?> fromReturn, Class<?> toReturn, boolean isExplicitCast) {143assert(fromReturn != toReturn);144try {145if (fromReturn == void.class) {146Object constantValue = null;147if (toReturn.isPrimitive()) {148if (toReturn == boolean.class) {149constantValue = Boolean.valueOf(false);150} else if (toReturn == char.class) {151constantValue = Character.valueOf((char)0);152} else {153/* covers all other cases as byte can be widened to any other primitive */154constantValue = Byte.valueOf((byte)0);155}156}157return MethodHandles.constant(toReturn, constantValue);158}159MethodType filterType = MethodType.methodType(toReturn, fromReturn);160if (fromReturn.isPrimitive()) {161if (toReturn.isPrimitive()) {162return getPrimitiveReturnFilter(filterType, isExplicitCast);163} else {164return getBoxingReturnFilter(filterType);165}166} else { // fromReturn is an object167if (!toReturn.isPrimitive()) {168return getCastFilter(filterType, isExplicitCast);169} else if (toReturn == void.class) {170MethodHandle filter = privilegedLookup.findStatic(FilterHelpers.class, "popObject", MethodType.methodType(void.class, Object.class)); //$NON-NLS-1$171return filter.cloneWithNewType(filterType);172} else {173return getUnboxingReturnFilter(filterType, isExplicitCast);174}175}176} catch(IllegalAccessException e) {177throw new Error(e);178} catch (NoSuchMethodException e) {179throw new Error(e);180}181}182183184/* JLSv3: 5.1.2: allowed widening primitive conversions185* byte to short, int, long, float, or double186* short to int, long, float, or double187* char to int, long, float, or double188* int to long, float, or double189* long to float or double190* float to double191*/192static boolean checkIfWideningPrimitiveConversion(Class<?> from, Class<?> to) {193if (!from.isPrimitive() || !to.isPrimitive()) {194return false;195}196if ((from == boolean.class) || (to == boolean.class) || (from == double.class) || (to == char.class)) {197return false;198}199200return primitiveIndex1(to) > primitiveIndex1(from);201}202203/*204* doesn't handle boolean or non-primitive. Also, can't widen to char.205* so it's a widening conversion if primitiveIndex1(to) > primitiveIndex1(from)206*207*/208private static int primitiveIndex1(Class<?> c) {209int ch = c.getName().charAt(0);210int shift = (ch ^ (ch >> 3)) & 0x7;211/* values for shift:2120 - double2132 - float2141 - long2154 - int2167 - char2175 - short2186 - byte219*/220return (021230546 >> (3*shift)) & 7; // octal value is 0x21230546 in hex221}222223static MethodHandle getPrimitiveReturnFilter(MethodType type, boolean isExplicitCast) throws IllegalAccessException, NoSuchMethodException {224Class<?> fromClass = type.parameterType(0);225Class<?> toClass = type.returnType();226227if (!isExplicitCast) {228if ((type.returnType() != void.class) && !checkIfWideningPrimitiveConversion(fromClass, toClass)) {229throw new WrongMethodTypeException();230}231}232MethodHandle filter = cachedReturnFilters.get(type);233if (filter == null) {234MethodHandle previous;235String to = MethodTypeHelper.getBytecodeStringName(toClass);236String from = MethodTypeHelper.getBytecodeStringName(type.parameterType(0));237filter = privilegedLookup.findStatic(FilterHelpers.class, from + "2" + to, type); //$NON-NLS-1$238if ((previous = cachedReturnFilters.putIfAbsent(type, filter)) != null) {239filter = previous;240}241}242return filter;243}244245/*[IF ]*/246/* From 292 javadoc:247* If T0 is a primitive and T1 a reference, a boxing conversion is applied if one exists,248* possibly followed by a reference conversion to a superclass. T1 must be a wrapper249* class or a supertype of one.250*/251/*[ENDIF]*/252/*253* Constructors of the Wrapper type provide the filter.254*/255static MethodHandle getBoxingReturnFilter(MethodType type) throws IllegalAccessException, NoSuchMethodException {256Class<?> wrapper = MethodTypeHelper.wrapPrimitive(type.parameterType(0));257if (!type.returnType().isAssignableFrom(wrapper)) {258throw new WrongMethodTypeException();259}260MethodHandle filter = cachedReturnFilters.get(type);261if (filter == null) {262MethodHandle previous;263filter = privilegedLookup.findStatic(wrapper, "valueOf", MethodType.methodType(wrapper, type.parameterType(0))); //$NON-NLS-1$264if ((previous = cachedReturnFilters.putIfAbsent(type, filter)) != null) {265filter = previous;266}267}268if (type.returnType() != wrapper) {269filter = filter.cloneWithNewType(type);270}271return filter;272}273274static MethodHandle getUnboxingReturnFilter(MethodType type, boolean isExplicitCast) throws IllegalAccessException, NoSuchMethodException {275Class<?> toUnbox = type.parameterType(0);276Class<?> returnType = type.returnType();277278if (toUnbox.equals(Object.class)) {279String methodName;280if (isExplicitCast) {281methodName = "explicitObject2"; //$NON-NLS-1$282} else {283methodName = "object2"; //$NON-NLS-1$284}285methodName += MethodTypeHelper.getBytecodeStringName(returnType);286return privilegedLookup.findStatic(FilterHelpers.class, methodName, MethodType.methodType(returnType, Object.class));287288} else if (toUnbox.equals(Number.class)) {289/* Widening conversions need to validate the conversion at runtime */290if (!isExplicitCast) {291if ((returnType != boolean.class) || (returnType != char.class)) {292return privilegedLookup.findStatic(FilterHelpers.class, "number2" + MethodTypeHelper.getBytecodeStringName(returnType), MethodType.methodType(returnType, Number.class)); //$NON-NLS-1$293}294} else {295/* special case these - can't be handled by the <type>Value() methods on Number */296if ((returnType == boolean.class) || (returnType == char.class)) {297String methodName = "explicitNumber2" + MethodTypeHelper.getBytecodeStringName(returnType); //$NON-NLS-1$298return privilegedLookup.findStatic(FilterHelpers.class, methodName, MethodType.methodType(returnType, Number.class));299}300String methodName = MethodTypeHelper.getBytecodeStringName(returnType) + "Value"; //$NON-NLS-1$301return privilegedLookup.findVirtual(Number.class, methodName, MethodType.methodType(returnType));302}303304} else if (toUnbox.equals(Boolean.class)) {305/* Boolean can be unboxed but there are no widening conversions */306MethodHandle filter = privilegedLookup.findVirtual(Boolean.class, "booleanValue", MethodType.methodType(boolean.class)); //$NON-NLS-1$307if (returnType.equals(boolean.class)) {308return filter;309}310if (isExplicitCast) {311return MethodHandles.filterReturnValue(filter, getPrimitiveReturnFilter(MethodType.methodType(returnType, boolean.class), isExplicitCast));312}313314} else if (toUnbox.equals(Character.class)) {315/* Character unboxes to char */316MethodHandle filter = privilegedLookup.findVirtual(Character.class, "charValue", MethodType.methodType(char.class)); //$NON-NLS-1$317if (returnType.equals(char.class)) {318return filter;319}320/* widen the return if possible */321return MethodHandles.filterReturnValue(filter, getPrimitiveReturnFilter(MethodType.methodType(returnType, char.class), isExplicitCast));322323} else if (MethodTypeHelper.WRAPPER_SET.contains(toUnbox)) {324/* remaining wrappers may have widening conversions - can be handled by toUnbox#'type'Value() methods (ie: Number subclasses)*/325Class<?> unwrapped = MethodTypeHelper.unwrapPrimitive(toUnbox);326boolean justUnwrap = returnType.equals(unwrapped);327if (justUnwrap || isExplicitCast || checkIfWideningPrimitiveConversion(unwrapped, returnType)) {328329if (isExplicitCast && !justUnwrap) {330/* Special case Boolean/Character --> (!boolean/!char) as it requires a two-step filter */331if ((returnType == char.class) || (returnType == boolean.class)) {332// get the unboxed version and filter with necessary conversion333MethodHandle unbox = privilegedLookup.findVirtual(toUnbox, unwrapped.getName()+"Value", MethodType.methodType(unwrapped)); //$NON-NLS-1$334MethodHandle filter = getPrimitiveReturnFilter(MethodType.methodType(returnType, unwrapped), isExplicitCast);335return MethodHandles.filterReturnValue(unbox, filter);336}337}338339return privilegedLookup.findVirtual(toUnbox, returnType.getName()+"Value", MethodType.methodType(returnType)); //$NON-NLS-1$;340}341}342343throw new WrongMethodTypeException();344}345346/*347* object to object conversion: use Class#cast(Object)348*/349static MethodHandle getCastFilter(MethodType type, boolean isExplicitCast) throws IllegalAccessException, NoSuchMethodException{350Class<?> returnClass = type.returnType();351if (isExplicitCast && returnClass.isInterface()) {352// Interfaces are passed unchecked353MethodType filterType = MethodType.methodType(Object.class, Object.class);354return privilegedLookup.findStatic(FilterHelpers.class, "explicitCastInterfaceUnchecked", filterType); //$NON-NLS-1$355}356MethodHandleCache methodHandleCache = MethodHandleCache.getCache(returnClass);357return methodHandleCache.getClassCastHandle();358}359360public static Object explicitCastInterfaceUnchecked(Object o) {361return o;362}363364public static boolean explicitObject2Z(Object o) {365if (o == null) {366return false;367} else if (o instanceof Boolean) {368return ((Boolean)o).booleanValue();369} else if (o instanceof Character) {370return ((byte)(((Character)o).charValue()) & 1) == 1;371} else {372// assume number - will throw ClassCast if required373return (((Number)o).byteValue() & 1) == 1;374}375}376377public static byte explicitObject2B(Object o) {378if (o == null) {379return 0;380} else if (o instanceof Boolean) {381return (byte)(((Boolean)o).booleanValue() ? 1 : 0);382} else if (o instanceof Character) {383return (byte)((Character)o).charValue();384} else {385// assume number - will throw ClassCast if required386return ((Number)o).byteValue();387}388}389public static short explicitObject2S(Object o) {390if (o == null) {391return 0;392} else if (o instanceof Boolean) {393return (short)(((Boolean)o).booleanValue() ? 1 : 0);394} else if (o instanceof Character) {395return (short)((Character)o).charValue();396} else {397// assume number - will throw ClassCast if required398return ((Number)o).shortValue();399}400}401public static char explicitObject2C(Object o) {402if (o == null) {403return 0;404} else if (o instanceof Boolean) {405return (char)(((Boolean)o).booleanValue() ? 1 : 0);406} else if (o instanceof Character) {407return ((Character)o).charValue();408} else {409// assume number - will throw ClassCast if required410return (char)((Number)o).intValue();411}412}413public static int explicitObject2I(Object o) {414if (o == null) {415return 0;416} else if (o instanceof Boolean) {417return ((Boolean)o).booleanValue() ? 1 : 0;418} else if (o instanceof Character) {419return ((Character)o).charValue();420} else {421// assume number - will throw ClassCast if required422return ((Number)o).intValue();423}424}425public static long explicitObject2J(Object o) {426if (o == null) {427return 0;428} else if (o instanceof Boolean) {429return ((Boolean)o).booleanValue() ? 1 : 0;430} else if (o instanceof Character) {431return ((Character)o).charValue();432} else {433// assume number - will throw ClassCast if required434return ((Number)o).longValue();435}436}437public static float explicitObject2F(Object o) {438if (o == null) {439return 0;440} else if (o instanceof Boolean) {441return ((Boolean)o).booleanValue() ? 1 : 0;442} else if (o instanceof Character) {443return ((Character)o).charValue();444} else {445// assume number - will throw ClassCast if required446return ((Number)o).floatValue();447}448}449public static double explicitObject2D(Object o) {450if (o == null) {451return 0;452} else if (o instanceof Boolean) {453return ((Boolean)o).booleanValue() ? 1 : 0;454} else if (o instanceof Character) {455return ((Character)o).charValue();456} else {457// assume number - will throw ClassCast if required458return ((Number)o).doubleValue();459}460}461462public static boolean explicitNumber2Z(Number n) {463if (n == null) {464return false;465}466return (n.byteValue() & 1) == 1;467}468469public static char explicitNumber2C(Number n) {470if (n == null) {471return 0;472}473return (char)n.intValue();474}475476/* Move exception allocation out of line */477private static final ClassCastException newClassCastException() {478return new ClassCastException();479}480481public static boolean object2Z(Object o) {482return ((Boolean)o).booleanValue();483}484public static char object2C(Object o) {485return ((Character)o).charValue();486}487public static byte object2B(Object o) {488return number2B((Number)o);489}490public static short object2S(Object o) {491return number2S((Number)o);492}493public static int object2I(Object o) {494o.getClass(); // implicit nullcheck495if (o instanceof Number) {496return number2I((Number) o);497} else if (o instanceof Character) {498return ((Character)o).charValue();499}500throw newClassCastException();501}502public static float object2F(Object o) {503o.getClass(); // implicit nullcheck504if (o instanceof Number) {505return number2F((Number) o);506} else if (o instanceof Character) {507return ((Character)o).charValue();508}509throw newClassCastException();510}511public static double object2D(Object o) {512o.getClass(); // implicit nullcheck513if (o instanceof Number) {514return number2D((Number) o);515} else if (o instanceof Character) {516return ((Character)o).charValue();517}518throw newClassCastException();519}520public static long object2J(Object o) {521o.getClass(); // implicit nullcheck522if (o instanceof Number) {523return number2J((Number)o);524} else if (o instanceof Character) {525return ((Character)o).charValue();526}527throw newClassCastException();528}529530public static byte number2B(Number n) {531/* Number can be { Byte, Short, Integer, Long, Float, Double}532* Number -> byte:533* Byte -> byte534*/535return ((Byte)n).byteValue(); //Implicit nullcheck;536}537public static short number2S(Number n) {538/* Number can be { Byte, Short, Integer, Long, Float, Double}539* Number -> short:540* Byte -> byte -> short541* Short -> short542*/543if ((n instanceof Short) || (n instanceof Byte)) {544return n.shortValue();545}546n.getClass(); // implicit nullcheck.547throw newClassCastException();548}549public static int number2I(Number n) {550/* Number can be { Byte, Short, Integer, Long, Float, Double}551* Number -> int:552* Byte -> byte -> int553* Short -> short -> int554* Integer-> int555*/556if ((n instanceof Integer) || (n instanceof Byte) || (n instanceof Short)) {557return n.intValue();558}559n.getClass(); // implicit nullcheck.560throw newClassCastException();561}562public static long number2J(Number n) {563/* Number can be { Byte, Short, Integer, Long, Float, Double}564* Number -> long:565* Byte -> byte -> long566* Short -> short -> long567* Integer-> int -> long568* Long -> long569*/570if ((n instanceof Long) || (n instanceof Integer) || (n instanceof Byte) || (n instanceof Short)) {571return n.longValue();572}573n.getClass(); // implicit nullcheck.574throw newClassCastException();575}576577public static float number2F(Number n) {578/* Number can be { Byte, Short, Integer, Long, Float, Double}579* Number -> float:580* Byte -> byte -> float581* Short -> short -> float582* Integer-> int -> float583* Long -> long -> float584* Float -> float585*/586if ((n instanceof Float) || (n instanceof Integer) || (n instanceof Long) || (n instanceof Byte) || (n instanceof Short)) {587return n.floatValue();588}589n.getClass(); // implicit nullcheck.590throw newClassCastException();591}592public static double number2D(Number n) {593/* Number can be { Byte, Short, Integer, Long, Float, Double}594* Number -> double:595* Byte -> byte -> double596* Short -> short -> double597* Integer-> int -> double598* Long -> long -> double599* Float -> float -> double600* Double -> double601*/602if ((n instanceof Double) || (n instanceof Float) || (n instanceof Integer) || (n instanceof Long) || (n instanceof Byte) || (n instanceof Short)) {603return n.doubleValue();604}605n.getClass(); // implicit nullcheck.606throw newClassCastException();607}608609public static void popObject(Object o) { }610611public static double V2D() { return 0; }612public static long V2J() { return 0; }613public static float V2F() { return 0; }614public static int V2I() { return 0; }615public static char V2C() { return 0; }616public static short V2S() { return 0; }617public static byte V2B() { return 0; }618public static boolean V2Z() { return false; }619public static Object V2object() { return null; }620621public static double Z2D(boolean j) { return j ? 1 : 0; }622public static long Z2J(boolean j) { return j ? 1 : 0; }623public static float Z2F(boolean j) { return j ? 1 : 0; }624public static int Z2I(boolean j) { return j ? 1 : 0; }625public static char Z2C(boolean j) { return (char)(j ? 1 : 0); }626public static short Z2S(boolean j) { return (short)(j ? 1 : 0); }627public static byte Z2B(boolean j) { return (byte)(j ? 1 : 0); }628public static void Z2V(boolean j) { }629public static Object Z2object(boolean j) { return Boolean.valueOf(j); }630631public static double B2D(byte j) { return j; }632public static long B2J(byte j) { return j; }633public static float B2F(byte j) { return j; }634public static int B2I(byte j) { return j; }635public static char B2C(byte j) { return (char)j; }636public static short B2S(byte j) { return j; }637public static boolean B2Z(byte j) { return (byte)(j & 1) == 1; }638public static void B2V(byte j) { }639public static Object B2object(byte j) { return Byte.valueOf(j); }640641public static double S2D(short j) { return j; }642public static long S2J(short j) { return j; }643public static float S2F(short j) { return j; }644public static int S2I(short j) { return j; }645public static char S2C(short j) { return (char)j; }646public static byte S2B(short j) { return (byte)j; }647public static boolean S2Z(short j) { return (((byte)j) & 1) == 1; }648public static void S2V(short j) { }649public static Object S2object(short j) { return Short.valueOf(j); }650651public static double C2D(char j) { return j; }652public static long C2J(char j) { return j; }653public static float C2F(char j) { return j; }654public static int C2I(char j) { return j; }655public static short C2S(char j) { return (short)j; }656public static byte C2B(char j) { return (byte)j; }657public static boolean C2Z(char j) { return (((byte)j) & 1) == 1; }658public static void C2V(char j) { }659public static Object C2object(char j) { return Character.valueOf(j); }660661public static boolean I2Z(int i) {return (((byte)i) & 1) == 1; }662public static byte I2B(int i) { return (byte)i; }663public static short I2S(int i) { return (short)i; }664public static char I2C(int i) { return (char)i; }665public static float I2F(int i) { return i; }666public static long I2J(int i) { return i; }667public static double I2D(int i) { return i; }668public static void I2V(int j) { }669public static Object I2object(int j) { return Integer.valueOf(j); }670671public static float J2F(long j) { return j; }672public static double J2D(long j) { return j; }673public static int J2I(long j) { return (int)j; }674public static char J2C(long j) { return (char)j; }675public static short J2S(long j) { return (short)j; }676public static byte J2B(long j) { return (byte)j; }677public static boolean J2Z(long j) { return (((byte)j) & 1) == 1; }678public static void J2V(long j) { }679public static Object J2object(long j) { return Long.valueOf(j); }680681public static long F2J(float j) { return (long)j; }682public static double F2D(float j) { return j; }683public static int F2I(float j) { return (int)j; }684public static char F2C(float j) { return (char)j; }685public static short F2S(float j) { return (short)j; }686public static byte F2B(float j) { return (byte)j; }687public static boolean F2Z(float j) { return (((byte)j) & 1) == 1; }688public static void F2V(float j) { }689public static Object F2object(float j) { return Float.valueOf(j); }690691public static float D2F(double j) { return (float) j; }692public static long D2J(double j) { return (long) j; }693public static int D2I(double j) { return (int)j; }694public static char D2C(double j) { return (char)j; }695public static short D2S(double j) { return (short)j; }696public static byte D2B(double j) { return (byte)j; }697public static boolean D2Z(double j) { return (((byte)j) & 1) == 1; }698public static void D2V(double j) { }699public static Object D2object(double j) { return Double.valueOf(j); }700701static void load(){}702}703704/*[IF JAVA_SPEC_VERSION >= 15]*/705@Override706boolean addRelatedMHs(List<MethodHandle> relatedMHs) {707relatedMHs.add(next);708return true;709}710/*[ENDIF] JAVA_SPEC_VERSION >= 15 */711712// {{{ JIT support713static { FilterHelpers.load(); } // JIT will need FilterHelpers loaded to compile thunks714// }}} JIT support715716final void compareWithConvert(ConvertHandle left, Comparator c) {717c.compareChildHandle(left.next, this.next);718}719}720721722