Java Code Examples for java.lang.invoke.MethodType#returnType()
The following examples show how to use
java.lang.invoke.MethodType#returnType() .
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: ScriptObject.java From openjdk-jdk9 with GNU General Public License v2.0 | 6 votes |
/** * Find the appropriate GETINDEX method for an invoke dynamic call. * * @param desc the call site descriptor * @param request the link request * * @return GuardedInvocation to be invoked at call site. */ protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) { final MethodType callType = desc.getMethodType(); final Class<?> returnType = callType.returnType(); final Class<?> returnClass = returnType.isPrimitive() ? returnType : Object.class; final Class<?> keyClass = callType.parameterType(1); final boolean explicitInstanceOfCheck = explicitInstanceOfCheck(desc, request); final String name; if (returnClass.isPrimitive()) { //turn e.g. get with a double into getDouble final String returnTypeName = returnClass.getName(); name = "get" + Character.toUpperCase(returnTypeName.charAt(0)) + returnTypeName.substring(1, returnTypeName.length()); } else { name = "get"; } final MethodHandle mh = findGetIndexMethodHandle(returnClass, name, keyClass, desc); return new GuardedInvocation(mh, getScriptObjectGuard(callType, explicitInstanceOfCheck), (SwitchPoint)null, explicitInstanceOfCheck ? null : ClassCastException.class); }
Example 2
Source File: LinkerCallSite.java From openjdk-jdk8u with GNU General Public License v2.0 | 6 votes |
@Override public void setTarget(final MethodHandle newTarget) { final MethodType type = type(); final boolean isVoid = type.returnType() == void.class; final Class<?> newSelfType = newTarget.type().parameterType(0); MethodHandle selfFilter = MH.bindTo(PROFILEENTRY, this); if (newSelfType != Object.class) { // new target uses a more precise 'self' type than Object.class. We need to // convert the filter type. Note that the profileEntry method returns "self" // argument "as is" and so the cast introduced will succeed for any type. MethodType selfFilterType = MethodType.methodType(newSelfType, newSelfType); selfFilter = selfFilter.asType(selfFilterType); } MethodHandle methodHandle = MH.filterArguments(newTarget, 0, selfFilter); if (isVoid) { methodHandle = MH.filterReturnValue(methodHandle, MH.bindTo(PROFILEVOIDEXIT, this)); } else { final MethodType filter = MH.type(type.returnType(), type.returnType()); methodHandle = MH.filterReturnValue(methodHandle, MH.asType(MH.bindTo(PROFILEEXIT, this), filter)); } super.setTarget(methodHandle); }
Example 3
Source File: LinkerCallSite.java From openjdk-jdk9 with GNU General Public License v2.0 | 6 votes |
@Override public void setTarget(final MethodHandle newTarget) { if (!getNashornDescriptor().isTraceEnterExit()) { super.setTarget(newTarget); return; } final MethodType type = type(); final boolean isVoid = type.returnType() == void.class; MethodHandle traceMethodHandle = isVoid ? TRACEVOID : TRACEOBJECT; traceMethodHandle = MH.bindTo(traceMethodHandle, this); traceMethodHandle = MH.bindTo(traceMethodHandle, newTarget); traceMethodHandle = MH.asCollector(traceMethodHandle, Object[].class, type.parameterCount()); traceMethodHandle = MH.asType(traceMethodHandle, type); super.setTarget(traceMethodHandle); }
Example 4
Source File: ContinuousArrayData.java From jdk8u60 with GNU General Public License v2.0 | 6 votes |
/** * Return a fast linked array getter, or null if we have to dispatch to super class * @param desc descriptor * @param request link request * @return invocation or null if needs to be sent to slow relink */ @Override public GuardedInvocation findFastGetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) { final MethodType callType = desc.getMethodType(); final Class<?> indexType = callType.parameterType(1); final Class<?> returnType = callType.returnType(); if (ContinuousArrayData.class.isAssignableFrom(clazz) && indexType == int.class) { final Object[] args = request.getArguments(); final int index = (int)args[args.length - 1]; if (has(index)) { final MethodHandle getArray = ScriptObject.GET_ARRAY.methodHandle(); final int programPoint = NashornCallSiteDescriptor.isOptimistic(desc) ? NashornCallSiteDescriptor.getProgramPoint(desc) : INVALID_PROGRAM_POINT; MethodHandle getElement = getElementGetter(returnType, programPoint); if (getElement != null) { getElement = MH.filterArguments(getElement, 0, MH.asType(getArray, getArray.type().changeReturnType(clazz))); final MethodHandle guard = MH.insertArguments(FAST_ACCESS_GUARD, 0, clazz); return new GuardedInvocation(getElement, guard, (SwitchPoint)null, ClassCastException.class); } } } return null; }
Example 5
Source File: LinkerCallSite.java From openjdk-8-source with GNU General Public License v2.0 | 6 votes |
@Override public void setTarget(final MethodHandle newTarget) { final MethodType type = type(); final boolean isVoid = type.returnType() == void.class; MethodHandle methodHandle = MH.filterArguments(newTarget, 0, MH.bindTo(PROFILEENTRY, this)); if (isVoid) { methodHandle = MH.filterReturnValue(methodHandle, MH.bindTo(PROFILEVOIDEXIT, this)); } else { final MethodType filter = MH.type(type.returnType(), type.returnType()); methodHandle = MH.filterReturnValue(methodHandle, MH.asType(MH.bindTo(PROFILEEXIT, this), filter)); } super.setTarget(methodHandle); }
Example 6
Source File: LinkerCallSite.java From jdk8u60 with GNU General Public License v2.0 | 6 votes |
@Override public void setTarget(final MethodHandle newTarget) { final MethodType type = type(); final boolean isVoid = type.returnType() == void.class; MethodHandle methodHandle = MH.filterArguments(newTarget, 0, MH.bindTo(PROFILEENTRY, this)); if (isVoid) { methodHandle = MH.filterReturnValue(methodHandle, MH.bindTo(PROFILEVOIDEXIT, this)); } else { final MethodType filter = MH.type(type.returnType(), type.returnType()); methodHandle = MH.filterReturnValue(methodHandle, MH.asType(MH.bindTo(PROFILEEXIT, this), filter)); } super.setTarget(methodHandle); }
Example 7
Source File: LinkerCallSite.java From openjdk-jdk8u with GNU General Public License v2.0 | 6 votes |
@Override public void setTarget(final MethodHandle newTarget) { if (!getNashornDescriptor().isTraceEnterExit()) { super.setTarget(newTarget); return; } final MethodType type = type(); final boolean isVoid = type.returnType() == void.class; MethodHandle traceMethodHandle = isVoid ? TRACEVOID : TRACEOBJECT; traceMethodHandle = MH.bindTo(traceMethodHandle, this); traceMethodHandle = MH.bindTo(traceMethodHandle, newTarget); traceMethodHandle = MH.asCollector(traceMethodHandle, Object[].class, type.parameterCount()); traceMethodHandle = MH.asType(traceMethodHandle, type); super.setTarget(traceMethodHandle); }
Example 8
Source File: ContinuousArrayData.java From hottub with GNU General Public License v2.0 | 6 votes |
/** * Return a fast linked array getter, or null if we have to dispatch to super class * @param desc descriptor * @param request link request * @return invocation or null if needs to be sent to slow relink */ @Override public GuardedInvocation findFastGetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) { final MethodType callType = desc.getMethodType(); final Class<?> indexType = callType.parameterType(1); final Class<?> returnType = callType.returnType(); if (ContinuousArrayData.class.isAssignableFrom(clazz) && indexType == int.class) { final Object[] args = request.getArguments(); final int index = (int)args[args.length - 1]; if (has(index)) { final MethodHandle getArray = ScriptObject.GET_ARRAY.methodHandle(); final int programPoint = NashornCallSiteDescriptor.isOptimistic(desc) ? NashornCallSiteDescriptor.getProgramPoint(desc) : INVALID_PROGRAM_POINT; MethodHandle getElement = getElementGetter(returnType, programPoint); if (getElement != null) { getElement = MH.filterArguments(getElement, 0, MH.asType(getArray, getArray.type().changeReturnType(clazz))); final MethodHandle guard = MH.insertArguments(FAST_ACCESS_GUARD, 0, clazz); return new GuardedInvocation(getElement, guard, (SwitchPoint)null, ClassCastException.class); } } } return null; }
Example 9
Source File: LinkerCallSite.java From jdk8u_nashorn with GNU General Public License v2.0 | 6 votes |
@Override public void setTarget(final MethodHandle newTarget) { if (!getNashornDescriptor().isTraceEnterExit()) { super.setTarget(newTarget); return; } final MethodType type = type(); final boolean isVoid = type.returnType() == void.class; MethodHandle traceMethodHandle = isVoid ? TRACEVOID : TRACEOBJECT; traceMethodHandle = MH.bindTo(traceMethodHandle, this); traceMethodHandle = MH.bindTo(traceMethodHandle, newTarget); traceMethodHandle = MH.asCollector(traceMethodHandle, Object[].class, type.parameterCount()); traceMethodHandle = MH.asType(traceMethodHandle, type); super.setTarget(traceMethodHandle); }
Example 10
Source File: ContinuousArrayData.java From openjdk-jdk8u-backup with GNU General Public License v2.0 | 6 votes |
/** * Return a fast linked array getter, or null if we have to dispatch to super class * @param desc descriptor * @param request link request * @return invocation or null if needs to be sent to slow relink */ @Override public GuardedInvocation findFastGetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) { final MethodType callType = desc.getMethodType(); final Class<?> indexType = callType.parameterType(1); final Class<?> returnType = callType.returnType(); if (ContinuousArrayData.class.isAssignableFrom(clazz) && indexType == int.class) { final Object[] args = request.getArguments(); final int index = (int)args[args.length - 1]; if (has(index)) { final MethodHandle getArray = ScriptObject.GET_ARRAY.methodHandle(); final int programPoint = NashornCallSiteDescriptor.isOptimistic(desc) ? NashornCallSiteDescriptor.getProgramPoint(desc) : INVALID_PROGRAM_POINT; MethodHandle getElement = getElementGetter(returnType, programPoint); if (getElement != null) { getElement = MH.filterArguments(getElement, 0, MH.asType(getArray, getArray.type().changeReturnType(clazz))); final MethodHandle guard = MH.insertArguments(FAST_ACCESS_GUARD, 0, clazz); return new GuardedInvocation(getElement, guard, (SwitchPoint)null, ClassCastException.class); } } } return null; }
Example 11
Source File: LinkerCallSite.java From openjdk-jdk8u-backup with GNU General Public License v2.0 | 6 votes |
@Override public void setTarget(final MethodHandle newTarget) { if (!getNashornDescriptor().isTraceEnterExit()) { super.setTarget(newTarget); return; } final MethodType type = type(); final boolean isVoid = type.returnType() == void.class; MethodHandle traceMethodHandle = isVoid ? TRACEVOID : TRACEOBJECT; traceMethodHandle = MH.bindTo(traceMethodHandle, this); traceMethodHandle = MH.bindTo(traceMethodHandle, newTarget); traceMethodHandle = MH.asCollector(traceMethodHandle, Object[].class, type.parameterCount()); traceMethodHandle = MH.asType(traceMethodHandle, type); super.setTarget(traceMethodHandle); }
Example 12
Source File: ScriptObject.java From openjdk-8 with GNU General Public License v2.0 | 5 votes |
/** * Find the appropriate GETINDEX method for an invoke dynamic call. * * @param callType the call site method type * @return GuardedInvocation to be invoked at call site. */ private static GuardedInvocation findGetIndexMethod(final MethodType callType) { final Class<?> returnClass = callType.returnType(); final Class<?> keyClass = callType.parameterType(1); String name = "get"; if (returnClass.isPrimitive()) { //turn e.g. get with a double into getDouble final String returnTypeName = returnClass.getName(); name += Character.toUpperCase(returnTypeName.charAt(0)) + returnTypeName.substring(1, returnTypeName.length()); } return new GuardedInvocation(findOwnMH(name, returnClass, keyClass), getScriptObjectGuard(callType)); }
Example 13
Source File: LoopCombinatorTest.java From openjdk-jdk9 with GNU General Public License v2.0 | 5 votes |
@Test(dataProvider = "countedLoopBodyParameters") public static void testCountedLoopBodyParameters(MethodType countType, MethodType initType, MethodType bodyType) throws Throwable { MethodHandle loop = MethodHandles.countedLoop( MethodHandles.empty(countType), initType == null ? null : MethodHandles.empty(initType), MethodHandles.empty(bodyType)); // The rule: If body takes the minimum number of parameters, then take what countType offers. // The initType has to just roll with whatever the other two agree on. int innerParams = (bodyType.returnType() == void.class ? 1 : 2); MethodType expectType = bodyType.dropParameterTypes(0, innerParams); if (expectType.parameterCount() == 0) expectType = expectType.insertParameterTypes(0, countType.parameterList()); assertEquals(expectType, loop.type()); }
Example 14
Source File: ExplicitCastArgumentsTest.java From jdk8u_jdk with GNU General Public License v2.0 | 5 votes |
/** * Tests that MHs.eCA method works correctly with MHs with multiple arguments. * @throws Throwable */ public static void testMultipleArgs() throws Throwable { int arity = 1 + RNG.nextInt(Helper.MAX_ARITY / 2 - 2); int arityMinus = RNG.nextInt(arity); int arityPlus = arity + RNG.nextInt(Helper.MAX_ARITY / 2 - arity) + 1; MethodType mType = Helper.randomMethodTypeGenerator(arity); MethodType mTypeNew = Helper.randomMethodTypeGenerator(arity); MethodType mTypeNewMinus = Helper.randomMethodTypeGenerator(arityMinus); MethodType mTypeNewPlus = Helper.randomMethodTypeGenerator(arityPlus); Class<?> rType = mType.returnType(); MethodHandle original; if (rType.equals(void.class)) { MethodType mt = MethodType.methodType(void.class); original = MethodHandles.publicLookup() .findStatic(THIS_CLASS, "retVoid", mt); } else { Object rValue = Helper.castToWrapper(1, rType); original = MethodHandles.constant(rType, rValue); } original = Helper.addTrailingArgs(original, arity, mType.parameterList()); MethodHandle target = MethodHandles .explicitCastArguments(original, mTypeNew); Object[] parList = Helper.randomArgs(mTypeNew.parameterList()); for (int i = 0; i < parList.length; i++) { if (parList[i] instanceof String) { parList[i] = null; //getting rid of Stings produced by randomArgs } } target.invokeWithArguments(parList); checkForWrongMethodTypeException(original, mTypeNewMinus); checkForWrongMethodTypeException(original, mTypeNewPlus); }
Example 15
Source File: ExplicitCastArgumentsTest.java From TencentKona-8 with GNU General Public License v2.0 | 5 votes |
/** * Tests that MHs.eCA method works correctly with MHs with multiple arguments. * @throws Throwable */ public static void testMultipleArgs() throws Throwable { int arity = 1 + RNG.nextInt(Helper.MAX_ARITY / 2 - 2); int arityMinus = RNG.nextInt(arity); int arityPlus = arity + RNG.nextInt(Helper.MAX_ARITY / 2 - arity) + 1; MethodType mType = Helper.randomMethodTypeGenerator(arity); MethodType mTypeNew = Helper.randomMethodTypeGenerator(arity); MethodType mTypeNewMinus = Helper.randomMethodTypeGenerator(arityMinus); MethodType mTypeNewPlus = Helper.randomMethodTypeGenerator(arityPlus); Class<?> rType = mType.returnType(); MethodHandle original; if (rType.equals(void.class)) { MethodType mt = MethodType.methodType(void.class); original = MethodHandles.publicLookup() .findStatic(THIS_CLASS, "retVoid", mt); } else { Object rValue = Helper.castToWrapper(1, rType); original = MethodHandles.constant(rType, rValue); } original = Helper.addTrailingArgs(original, arity, mType.parameterList()); MethodHandle target = MethodHandles .explicitCastArguments(original, mTypeNew); Object[] parList = Helper.randomArgs(mTypeNew.parameterList()); for (int i = 0; i < parList.length; i++) { if (parList[i] instanceof String) { parList[i] = null; //getting rid of Stings produced by randomArgs } } target.invokeWithArguments(parList); checkForWrongMethodTypeException(original, mTypeNewMinus); checkForWrongMethodTypeException(original, mTypeNewPlus); }
Example 16
Source File: ExplicitCastArgumentsTest.java From openjdk-jdk8u-backup with GNU General Public License v2.0 | 5 votes |
/** * Tests that MHs.eCA method works correctly with MHs with multiple arguments. * @throws Throwable */ public static void testMultipleArgs() throws Throwable { int arity = 1 + RNG.nextInt(Helper.MAX_ARITY / 2 - 2); int arityMinus = RNG.nextInt(arity); int arityPlus = arity + RNG.nextInt(Helper.MAX_ARITY / 2 - arity) + 1; MethodType mType = Helper.randomMethodTypeGenerator(arity); MethodType mTypeNew = Helper.randomMethodTypeGenerator(arity); MethodType mTypeNewMinus = Helper.randomMethodTypeGenerator(arityMinus); MethodType mTypeNewPlus = Helper.randomMethodTypeGenerator(arityPlus); Class<?> rType = mType.returnType(); MethodHandle original; if (rType.equals(void.class)) { MethodType mt = MethodType.methodType(void.class); original = MethodHandles.publicLookup() .findStatic(THIS_CLASS, "retVoid", mt); } else { Object rValue = Helper.castToWrapper(1, rType); original = MethodHandles.constant(rType, rValue); } original = Helper.addTrailingArgs(original, arity, mType.parameterList()); MethodHandle target = MethodHandles .explicitCastArguments(original, mTypeNew); Object[] parList = Helper.randomArgs(mTypeNew.parameterList()); for (int i = 0; i < parList.length; i++) { if (parList[i] instanceof String) { parList[i] = null; //getting rid of Stings produced by randomArgs } } target.invokeWithArguments(parList); checkForWrongMethodTypeException(original, mTypeNewMinus); checkForWrongMethodTypeException(original, mTypeNewPlus); }
Example 17
Source File: MethodTypeTest.java From openjdk-jdk8u with GNU General Public License v2.0 | 5 votes |
/** * Test of returnType method, of class MethodType. */ @Test public void testReturnType() { System.out.println("returnType"); MethodType instance = mt_viS; Class<?> expResult = void.class; Class<?> result = instance.returnType(); assertSame(expResult, result); }
Example 18
Source File: AbstractJavaLinker.java From openjdk-jdk8u-backup with GNU General Public License v2.0 | 4 votes |
private GuardedInvocationComponent getPropertySetter(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices, final List<String> operations) throws Exception { switch(callSiteDescriptor.getNameTokenCount()) { case 2: { // Must have three arguments: target object, property name, and property value. assertParameterCount(callSiteDescriptor, 3); // We want setters that conform to "Object(O, V)". Note, we aren't doing "R(O, V)" as it might not be // valid for us to convert return values proactively. Also, since we don't know what setters will be // invoked, we'll conservatively presume Object return type. The one exception is void return. final MethodType origType = callSiteDescriptor.getMethodType(); final MethodType type = origType.returnType() == void.class ? origType : origType.changeReturnType(Object.class); // What's below is basically: // foldArguments(guardWithTest(isNotNull, invoke, null|nextComponent.invocation), // get_setter_handle(type, linkerServices)) // only with a bunch of method signature adjustments. Basically, retrieve method setter // MethodHandle; if it is non-null, invoke it, otherwise either return null, or delegate to next // component's invocation. // Call site type is "ret_type(object_type,property_name_type,property_value_type)", which we'll // abbreviate to R(O, N, V) going forward, although we don't really use R here (see above about using // Object return type). final MethodType setterType = type.dropParameterTypes(1, 2); // Bind property setter handle to the expected setter type and linker services. Type is // MethodHandle(Object, String, Object) final MethodHandle boundGetter = MethodHandles.insertArguments(getPropertySetterHandle, 0, callSiteDescriptor.changeMethodType(setterType), linkerServices); // Cast getter to MethodHandle(O, N, V) final MethodHandle typedGetter = linkerServices.asType(boundGetter, type.changeReturnType( MethodHandle.class)); // Handle to invoke the setter R(MethodHandle, O, V) final MethodHandle invokeHandle = MethodHandles.exactInvoker(setterType); // Handle to invoke the setter, dropping unnecessary fold arguments R(MethodHandle, O, N, V) final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandle, 2, type.parameterType( 1)); final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor, linkerServices, operations); final MethodHandle fallbackFolded; if(nextComponent == null) { // Object(MethodHandle)->Object(MethodHandle, O, N, V); returns constant null fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_METHOD_HANDLE, 1, type.parameterList()).asType(type.insertParameterTypes(0, MethodHandle.class)); } else { // Object(O, N, V)->Object(MethodHandle, O, N, V); adapts the next component's invocation to drop the // extra argument resulting from fold fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(), 0, MethodHandle.class); } // fold(R(MethodHandle, O, N, V), MethodHandle(O, N, V)) final MethodHandle compositeSetter = MethodHandles.foldArguments(MethodHandles.guardWithTest( IS_METHOD_HANDLE_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter); if(nextComponent == null) { return getClassGuardedInvocationComponent(compositeSetter, type); } return nextComponent.compose(compositeSetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS); } case 3: { // Must have two arguments: target object and property value assertParameterCount(callSiteDescriptor, 2); final GuardedInvocation gi = createGuardedDynamicMethodInvocation(callSiteDescriptor, linkerServices, callSiteDescriptor.getNameToken(CallSiteDescriptor.NAME_OPERAND), propertySetters); // If we have a property setter with this name, this composite operation will always stop here if(gi != null) { return new GuardedInvocationComponent(gi, clazz, ValidationType.EXACT_CLASS); } // If we don't have a property setter with this name, always fall back to the next operation in the // composite (if any) return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, operations); } default: { // More than two name components; don't know what to do with it. return null; } } }
Example 19
Source File: AbstractJavaLinker.java From hottub with GNU General Public License v2.0 | 4 votes |
private GuardedInvocationComponent getPropertySetter(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices, final List<String> operations) throws Exception { switch(callSiteDescriptor.getNameTokenCount()) { case 2: { // Must have three arguments: target object, property name, and property value. assertParameterCount(callSiteDescriptor, 3); // We want setters that conform to "Object(O, V)". Note, we aren't doing "R(O, V)" as it might not be // valid for us to convert return values proactively. Also, since we don't know what setters will be // invoked, we'll conservatively presume Object return type. The one exception is void return. final MethodType origType = callSiteDescriptor.getMethodType(); final MethodType type = origType.returnType() == void.class ? origType : origType.changeReturnType(Object.class); // What's below is basically: // foldArguments(guardWithTest(isNotNull, invoke, null|nextComponent.invocation), // get_setter_handle(type, linkerServices)) // only with a bunch of method signature adjustments. Basically, retrieve method setter // MethodHandle; if it is non-null, invoke it, otherwise either return null, or delegate to next // component's invocation. // Call site type is "ret_type(object_type,property_name_type,property_value_type)", which we'll // abbreviate to R(O, N, V) going forward, although we don't really use R here (see above about using // Object return type). final MethodType setterType = type.dropParameterTypes(1, 2); // Bind property setter handle to the expected setter type and linker services. Type is // MethodHandle(Object, String, Object) final MethodHandle boundGetter = MethodHandles.insertArguments(getPropertySetterHandle, 0, callSiteDescriptor.changeMethodType(setterType), linkerServices); // Cast getter to MethodHandle(O, N, V) final MethodHandle typedGetter = linkerServices.asType(boundGetter, type.changeReturnType( MethodHandle.class)); // Handle to invoke the setter R(MethodHandle, O, V) final MethodHandle invokeHandle = MethodHandles.exactInvoker(setterType); // Handle to invoke the setter, dropping unnecessary fold arguments R(MethodHandle, O, N, V) final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandle, 2, type.parameterType( 1)); final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor, linkerServices, operations); final MethodHandle fallbackFolded; if(nextComponent == null) { // Object(MethodHandle)->Object(MethodHandle, O, N, V); returns constant null fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_METHOD_HANDLE, 1, type.parameterList()).asType(type.insertParameterTypes(0, MethodHandle.class)); } else { // Object(O, N, V)->Object(MethodHandle, O, N, V); adapts the next component's invocation to drop the // extra argument resulting from fold fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(), 0, MethodHandle.class); } // fold(R(MethodHandle, O, N, V), MethodHandle(O, N, V)) final MethodHandle compositeSetter = MethodHandles.foldArguments(MethodHandles.guardWithTest( IS_METHOD_HANDLE_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter); if(nextComponent == null) { return getClassGuardedInvocationComponent(compositeSetter, type); } return nextComponent.compose(compositeSetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS); } case 3: { // Must have two arguments: target object and property value assertParameterCount(callSiteDescriptor, 2); final GuardedInvocation gi = createGuardedDynamicMethodInvocation(callSiteDescriptor, linkerServices, callSiteDescriptor.getNameToken(CallSiteDescriptor.NAME_OPERAND), propertySetters); // If we have a property setter with this name, this composite operation will always stop here if(gi != null) { return new GuardedInvocationComponent(gi, clazz, ValidationType.EXACT_CLASS); } // If we don't have a property setter with this name, always fall back to the next operation in the // composite (if any) return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, operations); } default: { // More than two name components; don't know what to do with it. return null; } } }
Example 20
Source File: AbstractJavaLinker.java From openjdk-jdk8u with GNU General Public License v2.0 | 4 votes |
private GuardedInvocationComponent getPropertySetter(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices, final List<String> operations) throws Exception { switch(callSiteDescriptor.getNameTokenCount()) { case 2: { // Must have three arguments: target object, property name, and property value. assertParameterCount(callSiteDescriptor, 3); // We want setters that conform to "Object(O, V)". Note, we aren't doing "R(O, V)" as it might not be // valid for us to convert return values proactively. Also, since we don't know what setters will be // invoked, we'll conservatively presume Object return type. The one exception is void return. final MethodType origType = callSiteDescriptor.getMethodType(); final MethodType type = origType.returnType() == void.class ? origType : origType.changeReturnType(Object.class); // What's below is basically: // foldArguments(guardWithTest(isNotNull, invoke, null|nextComponent.invocation), // get_setter_handle(type, linkerServices)) // only with a bunch of method signature adjustments. Basically, retrieve method setter // MethodHandle; if it is non-null, invoke it, otherwise either return null, or delegate to next // component's invocation. // Call site type is "ret_type(object_type,property_name_type,property_value_type)", which we'll // abbreviate to R(O, N, V) going forward, although we don't really use R here (see above about using // Object return type). final MethodType setterType = type.dropParameterTypes(1, 2); // Bind property setter handle to the expected setter type and linker services. Type is // MethodHandle(Object, String, Object) final MethodHandle boundGetter = MethodHandles.insertArguments(getPropertySetterHandle, 0, callSiteDescriptor.changeMethodType(setterType), linkerServices); // Cast getter to MethodHandle(O, N, V) final MethodHandle typedGetter = linkerServices.asType(boundGetter, type.changeReturnType( MethodHandle.class)); // Handle to invoke the setter R(MethodHandle, O, V) final MethodHandle invokeHandle = MethodHandles.exactInvoker(setterType); // Handle to invoke the setter, dropping unnecessary fold arguments R(MethodHandle, O, N, V) final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandle, 2, type.parameterType( 1)); final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor, linkerServices, operations); final MethodHandle fallbackFolded; if(nextComponent == null) { // Object(MethodHandle)->Object(MethodHandle, O, N, V); returns constant null fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_METHOD_HANDLE, 1, type.parameterList()).asType(type.insertParameterTypes(0, MethodHandle.class)); } else { // Object(O, N, V)->Object(MethodHandle, O, N, V); adapts the next component's invocation to drop the // extra argument resulting from fold fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(), 0, MethodHandle.class); } // fold(R(MethodHandle, O, N, V), MethodHandle(O, N, V)) final MethodHandle compositeSetter = MethodHandles.foldArguments(MethodHandles.guardWithTest( IS_METHOD_HANDLE_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter); if(nextComponent == null) { return getClassGuardedInvocationComponent(compositeSetter, type); } return nextComponent.compose(compositeSetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS); } case 3: { // Must have two arguments: target object and property value assertParameterCount(callSiteDescriptor, 2); final GuardedInvocation gi = createGuardedDynamicMethodInvocation(callSiteDescriptor, linkerServices, callSiteDescriptor.getNameToken(CallSiteDescriptor.NAME_OPERAND), propertySetters); // If we have a property setter with this name, this composite operation will always stop here if(gi != null) { return new GuardedInvocationComponent(gi, clazz, ValidationType.EXACT_CLASS); } // If we don't have a property setter with this name, always fall back to the next operation in the // composite (if any) return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, operations); } default: { // More than two name components; don't know what to do with it. return null; } } }