8139756: Eliminate GuardedTypeConversion, DynamicLinker.getCurrentLinkRequest and its associated permission
Reviewed-by: hannesw, sundar
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinker.java Mon Oct 19 15:49:21 2015 +0530
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinker.java Mon Oct 19 18:24:47 2015 +0200
@@ -146,12 +146,6 @@
* </ul>
*/
public final class DynamicLinker {
- /**
- * A permission to invoke the {@link #getCurrentLinkRequest()} method. It is
- * named {@code "dynalink.getCurrentLinkRequest"}.
- */
- public static final RuntimePermission GET_CURRENT_LINK_REQUEST_PERMISSION = new RuntimePermission("dynalink.getCurrentLinkRequest");
-
private static final String CLASS_NAME = DynamicLinker.class.getName();
private static final String RELINK_METHOD_NAME = "relink";
@@ -303,18 +297,6 @@
}
/**
- * Returns the currently processed link request, or null if the method is
- * invoked outside of the linking process.
- * @return the currently processed link request, or null.
- * @throws SecurityException if the calling code doesn't have the
- * {@code "dynalink.getCurrentLinkRequest"} runtime permission (available as
- * {@link #GET_CURRENT_LINK_REQUEST_PERMISSION}).
- */
- public static LinkRequest getCurrentLinkRequest() {
- return LinkerServicesImpl.getCurrentLinkRequest();
- }
-
- /**
* Returns {@code true} if the frame represents {@code MethodHandleNatives.linkCallSite()},
* the frame immediately on top of the call site frame when the call site is
* being linked for the first time.
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/LinkerServicesImpl.java Mon Oct 19 15:49:21 2015 +0530
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/LinkerServicesImpl.java Mon Oct 19 18:24:47 2015 +0200
@@ -84,6 +84,7 @@
package jdk.internal.dynalink;
import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import jdk.internal.dynalink.linker.ConversionComparator.Comparison;
import jdk.internal.dynalink.linker.GuardedInvocation;
@@ -153,14 +154,11 @@
return internalObjectsFilter != null ? internalObjectsFilter.transform(target) : target;
}
- static LinkRequest getCurrentLinkRequest() {
+ static MethodHandles.Lookup getCurrentLookup() {
final LinkRequest currentRequest = threadLinkRequest.get();
if (currentRequest != null) {
- final SecurityManager sm = System.getSecurityManager();
- if(sm != null) {
- sm.checkPermission(DynamicLinker.GET_CURRENT_LINK_REQUEST_PERMISSION);
- }
+ return currentRequest.getCallSiteDescriptor().getLookup();
}
- return currentRequest;
+ return MethodHandles.publicLookup();
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/TypeConverterFactory.java Mon Oct 19 15:49:21 2015 +0530
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/TypeConverterFactory.java Mon Oct 19 18:24:47 2015 +0200
@@ -85,16 +85,17 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.lang.invoke.WrongMethodTypeException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.LinkedList;
import java.util.List;
+import java.util.function.Supplier;
import jdk.internal.dynalink.linker.ConversionComparator;
import jdk.internal.dynalink.linker.ConversionComparator.Comparison;
import jdk.internal.dynalink.linker.GuardedInvocation;
-import jdk.internal.dynalink.linker.GuardedTypeConversion;
import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.linker.MethodTypeConversionStrategy;
@@ -372,25 +373,49 @@
}
}
+ private static class LookupSupplier implements Supplier<MethodHandles.Lookup> {
+ volatile boolean returnedLookup;
+ volatile boolean closed;
+
+ @Override
+ public Lookup get() {
+ if (closed) {
+ // Something held on to this supplier and tried to invoke it
+ // after we're done with it.
+ throw new IllegalStateException();
+ }
+ final Lookup lookup = LinkerServicesImpl.getCurrentLookup();
+ returnedLookup = true;
+ return lookup;
+ }
+ }
+
/*private*/ MethodHandle createConverter(final Class<?> sourceType, final Class<?> targetType) throws Exception {
final MethodType type = MethodType.methodType(targetType, sourceType);
final MethodHandle identity = IDENTITY_CONVERSION.asType(type);
MethodHandle last = identity;
- boolean cacheable = true;
- for(int i = factories.length; i-- > 0;) {
- final GuardedTypeConversion next = factories[i].convertToType(sourceType, targetType);
- if(next != null) {
- cacheable = cacheable && next.isCacheable();
- final GuardedInvocation conversionInvocation = next.getConversionInvocation();
- last = conversionInvocation.compose(last);
+
+ final LookupSupplier lookupSupplier = new LookupSupplier();
+ try {
+ for(int i = factories.length; i-- > 0;) {
+ final GuardedInvocation next = factories[i].convertToType(sourceType, targetType, lookupSupplier);
+ if(next != null) {
+ last = next.compose(last);
+ }
}
+ } finally {
+ lookupSupplier.closed = true;
}
+
if(last == identity) {
return IDENTITY_CONVERSION;
}
- if(cacheable) {
+ if(!lookupSupplier.returnedLookup) {
return last;
}
+ // At least one of the consulted converter factories obtained the
+ // lookup, so we must presume the created converter is sensitive to the
+ // lookup class and thus we will not cache it.
throw new NotCacheableConverter(last);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardedInvocation.java Mon Oct 19 15:49:21 2015 +0530
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardedInvocation.java Mon Oct 19 18:24:47 2015 +0200
@@ -89,6 +89,7 @@
import java.lang.invoke.SwitchPoint;
import java.util.List;
import java.util.Objects;
+import java.util.function.Supplier;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.support.Guards;
@@ -96,17 +97,18 @@
* Represents a conditionally valid method handle. Usually produced as a return
* value of
* {@link GuardingDynamicLinker#getGuardedInvocation(LinkRequest, LinkerServices)}
- * and {@link GuardingTypeConverterFactory#convertToType(Class, Class)}. It is
- * an immutable tuple of an invocation method handle, a guard method handle that
- * defines the applicability of the invocation handle, zero or more switch
- * points that can be used for external invalidation of the invocation handle,
- * and an exception type that if thrown during an invocation of the method
- * handle also invalidates it. The invocation handle is suitable for invocation
- * if the guard handle returns true for its arguments, and as long as any of the
- * switch points are not invalidated, and as long as it does not throw an
- * exception of the designated type. The guard, the switch point, and the
- * exception type are all optional (a guarded invocation having none of them is
- * unconditionally valid).
+ * and
+ * {@link GuardingTypeConverterFactory#convertToType(Class, Class, Supplier)}.
+ * It is an immutable tuple of an invocation method handle, a guard method
+ * handle that defines the applicability of the invocation handle, zero or more
+ * switch points that can be used for external invalidation of the invocation
+ * handle, and an exception type that if thrown during an invocation of the
+ * method handle also invalidates it. The invocation handle is suitable for
+ * invocation if the guard handle returns true for its arguments, and as long
+ * as any of the switch points are not invalidated, and as long as it does not
+ * throw an exception of the designated type. The guard, the switch points, and
+ * the exception type are all optional (a guarded invocation having none of them
+ * is unconditionally valid).
*/
public class GuardedInvocation {
private final MethodHandle invocation;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardedTypeConversion.java Mon Oct 19 15:49:21 2015 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * This file is available under and governed by the GNU General Public
- * License version 2 only, as published by the Free Software Foundation.
- * However, the following notice accompanied the original version of this
- * file, and Oracle licenses the original version of this file under the BSD
- * license:
- */
-/*
- Copyright 2009-2013 Attila Szegedi
-
- Licensed under both the Apache License, Version 2.0 (the "Apache License")
- and the BSD License (the "BSD License"), with licensee being free to
- choose either of the two at their discretion.
-
- You may not use this file except in compliance with either the Apache
- License or the BSD License.
-
- If you choose to use this file in compliance with the Apache License, the
- following notice applies to you:
-
- You may obtain a copy of the Apache License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied. See the License for the specific language governing
- permissions and limitations under the License.
-
- If you choose to use this file in compliance with the BSD License, the
- following notice applies to you:
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- * Neither the name of the copyright holder nor the names of
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-package jdk.internal.dynalink.linker;
-
-
-/**
- * A tuple of a {@link GuardedInvocation} describing a conditional type
- * conversion and a boolean flag indicating whether the result is allowed to
- * be cached. While most type conversions are cacheable, some can have security
- * implications. An example is converting e.g. function objects from the source
- * language into implementations of Java functional interface objects, with
- * adapter classes for those interfaces being created on the fly and being
- * sensitive to the protection domain of their creator. Such converter
- * invocation must be marked as non-cacheable so that Dynalink will know not to
- * keep and reuse them in different contexts.
- */
-public class GuardedTypeConversion {
- private final GuardedInvocation conversionInvocation;
- private final boolean cacheable;
-
- /**
- * Creates a new guarded type conversion.
- * @param conversionInvocation guarded invocation implementing this type
- * conversion.
- * @param cacheable true if this invocation is cacheable, false otherwise.
- */
- public GuardedTypeConversion(final GuardedInvocation conversionInvocation, final boolean cacheable) {
- this.conversionInvocation = conversionInvocation;
- this.cacheable = cacheable;
- }
-
- /**
- * Returns the invocation implementing the type conversion.
- * @return the invocation implementing the type conversion.
- */
- public GuardedInvocation getConversionInvocation() {
- return conversionInvocation;
- }
-
- /**
- * Returns true if this conversion is allowed to be cached and reused by
- * Dynalink.
- * @return true if this conversion is allowed to be cached and reused by
- * Dynalink.
- */
- public boolean isCacheable() {
- return cacheable;
- }
-}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardingTypeConverterFactory.java Mon Oct 19 15:49:21 2015 +0530
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardingTypeConverterFactory.java Mon Oct 19 18:24:47 2015 +0200
@@ -83,6 +83,9 @@
package jdk.internal.dynalink.linker;
+import java.lang.invoke.MethodHandles;
+import java.util.function.Supplier;
+import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.beans.BeansLinker;
import jdk.internal.dynalink.support.TypeUtilities;
@@ -103,11 +106,24 @@
*
* @param sourceType source type
* @param targetType the target type.
- * @return a guarded type conversion that contains a guarded invocation that can take an object (if it passes guard)
+ * @param lookupSupplier a supplier for retrieving the lookup of the class
+ * on whose behalf a type converter is requested. When a converter is
+ * requested as part of linking an {@code invokedynamic} instruction the
+ * supplier will return the lookup passed to the bootstrap method, otherwise
+ * it will return the public lookup. For most conversions, the lookup is
+ * irrelevant. A typical case where the lookup might be needed is when the
+ * converter creates a Java adapter class on the fly (e.g. to convert some
+ * object from the dynamic language into a Java interface for
+ * interoperability). Invoking the {@link Supplier#get()} method on the
+ * passed supplier will be subject to the same security checks as
+ * {@link CallSiteDescriptor#getLookup()}. An implementation should avoid
+ * retrieving the lookup if it is not needed so to avoid the expense of
+ * {@code AccessController.doPrivileged} call.
+ * @return a guarded invocation that can take an object (if it passes guard)
* and return another object that is its representation coerced into the target type. In case the factory is certain
* it is unable to handle a conversion, it can return null. In case the factory is certain that it can always handle
* the conversion, it can return an unconditional invocation (one whose guard is null).
* @throws Exception if there was an error during creation of the converter
*/
- public GuardedTypeConversion convertToType(Class<?> sourceType, Class<?> targetType) throws Exception;
+ public GuardedInvocation convertToType(Class<?> sourceType, Class<?> targetType, Supplier<MethodHandles.Lookup> lookupSupplier) throws Exception;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java Mon Oct 19 15:49:21 2015 +0530
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java Mon Oct 19 18:24:47 2015 +0200
@@ -32,12 +32,13 @@
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
import java.util.HashMap;
import java.util.Map;
+import java.util.function.Supplier;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.beans.BeansLinker;
import jdk.internal.dynalink.linker.GuardedInvocation;
-import jdk.internal.dynalink.linker.GuardedTypeConversion;
import jdk.internal.dynalink.linker.GuardingDynamicLinker;
import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
import jdk.internal.dynalink.linker.LinkRequest;
@@ -135,9 +136,9 @@
}
@Override
- public GuardedTypeConversion convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception {
+ public GuardedInvocation convertToType(final Class<?> sourceType, final Class<?> targetType, final Supplier<MethodHandles.Lookup> lookupSupplier) throws Exception {
final GuardedInvocation gi = convertToTypeNoCast(sourceType, targetType);
- return gi == null ? null : new GuardedTypeConversion(gi.asType(MH.type(targetType, sourceType)), true);
+ return gi == null ? null : gi.asType(MH.type(targetType, sourceType));
}
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornLinker.java Mon Oct 19 15:49:21 2015 +0530
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornLinker.java Mon Oct 19 18:24:47 2015 +0200
@@ -38,12 +38,11 @@
import java.util.List;
import java.util.Map;
import java.util.Queue;
+import java.util.function.Supplier;
import javax.script.Bindings;
import jdk.internal.dynalink.CallSiteDescriptor;
-import jdk.internal.dynalink.DynamicLinker;
import jdk.internal.dynalink.linker.ConversionComparator;
import jdk.internal.dynalink.linker.GuardedInvocation;
-import jdk.internal.dynalink.linker.GuardedTypeConversion;
import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.linker.LinkerServices;
@@ -111,16 +110,12 @@
}
@Override
- public GuardedTypeConversion convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception {
+ public GuardedInvocation convertToType(final Class<?> sourceType, final Class<?> targetType, final Supplier<MethodHandles.Lookup> lookupSupplier) throws Exception {
GuardedInvocation gi = convertToTypeNoCast(sourceType, targetType);
- if(gi != null) {
- return new GuardedTypeConversion(gi.asType(MH.type(targetType, sourceType)), true);
+ if(gi == null) {
+ gi = getSamTypeConverter(sourceType, targetType, lookupSupplier);
}
- gi = getSamTypeConverter(sourceType, targetType);
- if(gi != null) {
- return new GuardedTypeConversion(gi.asType(MH.type(targetType, sourceType)), false);
- }
- return null;
+ return gi == null ? null : gi.asType(MH.type(targetType, sourceType));
}
/**
@@ -158,26 +153,25 @@
* @throws Exception if something goes wrong; generally, if there's an issue with creation of the SAM proxy type
* constructor.
*/
- private static GuardedInvocation getSamTypeConverter(final Class<?> sourceType, final Class<?> targetType) throws Exception {
+ private static GuardedInvocation getSamTypeConverter(final Class<?> sourceType, final Class<?> targetType, final Supplier<MethodHandles.Lookup> lookupSupplier) throws Exception {
// If source type is more generic than ScriptFunction class, we'll need to use a guard
final boolean isSourceTypeGeneric = sourceType.isAssignableFrom(ScriptFunction.class);
if ((isSourceTypeGeneric || ScriptFunction.class.isAssignableFrom(sourceType)) && isAutoConvertibleFromFunction(targetType)) {
- final MethodHandle ctor = JavaAdapterFactory.getConstructor(ScriptFunction.class, targetType, getCurrentLookup());
+ final MethodHandle ctor = JavaAdapterFactory.getConstructor(ScriptFunction.class, targetType, getCurrentLookup(lookupSupplier));
assert ctor != null; // if isAutoConvertibleFromFunction() returned true, then ctor must exist.
return new GuardedInvocation(ctor, isSourceTypeGeneric ? IS_SCRIPT_FUNCTION : null);
}
return null;
}
- private static MethodHandles.Lookup getCurrentLookup() {
+ private static MethodHandles.Lookup getCurrentLookup(final Supplier<MethodHandles.Lookup> lookupSupplier) {
return AccessController.doPrivileged(new PrivilegedAction<MethodHandles.Lookup>() {
@Override
public MethodHandles.Lookup run() {
- final LinkRequest currentRequest = DynamicLinker.getCurrentLinkRequest();
- return currentRequest == null ? MethodHandles.publicLookup() : currentRequest.getCallSiteDescriptor().getLookup();
+ return lookupSupplier.get();
}
- }, null, CallSiteDescriptor.GET_LOOKUP_PERMISSION, DynamicLinker.GET_CURRENT_LINK_REQUEST_PERMISSION);
+ }, null, CallSiteDescriptor.GET_LOOKUP_PERMISSION);
}
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java Mon Oct 19 15:49:21 2015 +0530
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java Mon Oct 19 18:24:47 2015 +0200
@@ -29,9 +29,9 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+import java.util.function.Supplier;
import jdk.internal.dynalink.linker.ConversionComparator;
import jdk.internal.dynalink.linker.GuardedInvocation;
-import jdk.internal.dynalink.linker.GuardedTypeConversion;
import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.linker.LinkerServices;
@@ -48,8 +48,8 @@
* primitive type conversions for these types when linking to Java methods.
*/
final class NashornPrimitiveLinker implements TypeBasedGuardingDynamicLinker, GuardingTypeConverterFactory, ConversionComparator {
- private static final GuardedTypeConversion VOID_TO_OBJECT = new GuardedTypeConversion(
- new GuardedInvocation(MethodHandles.constant(Object.class, ScriptRuntime.UNDEFINED)), true);
+ private static final GuardedInvocation VOID_TO_OBJECT =
+ new GuardedInvocation(MethodHandles.constant(Object.class, ScriptRuntime.UNDEFINED));
@Override
public boolean canLinkType(final Class<?> type) {
@@ -77,7 +77,7 @@
* @return a conditional converter from source to target type
*/
@Override
- public GuardedTypeConversion convertToType(final Class<?> sourceType, final Class<?> targetType) {
+ public GuardedInvocation convertToType(final Class<?> sourceType, final Class<?> targetType, final Supplier<MethodHandles.Lookup> lookupSupplier) {
final MethodHandle mh = JavaArgumentConverters.getConverter(targetType);
if (mh == null) {
if(targetType == Object.class && sourceType == void.class) {
@@ -86,7 +86,7 @@
return null;
}
- return new GuardedTypeConversion(new GuardedInvocation(mh, canLinkTypeStatic(sourceType) ? null : GUARD_PRIMITIVE).asType(mh.type().changeParameterType(0, sourceType)), true);
+ return new GuardedInvocation(mh, canLinkTypeStatic(sourceType) ? null : GUARD_PRIMITIVE).asType(mh.type().changeParameterType(0, sourceType));
}
/**