src/jdk/internal/dynalink/DynamicLinker.java

Print this page
rev 1199 : 8072595: nashorn should not use obj.getClass() for null checks
Reviewed-by: hannesw, attila


  71        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  72        IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  73        TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  74        PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
  75        BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  76        CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  77        SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  78        BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  79        WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  80        OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  81        ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  82 */
  83 
  84 package jdk.internal.dynalink;
  85 
  86 import java.lang.invoke.MethodHandle;
  87 import java.lang.invoke.MethodHandles;
  88 import java.lang.invoke.MethodType;
  89 import java.lang.invoke.MutableCallSite;
  90 import java.util.List;

  91 import jdk.internal.dynalink.linker.GuardedInvocation;
  92 import jdk.internal.dynalink.linker.GuardingDynamicLinker;
  93 import jdk.internal.dynalink.linker.LinkRequest;
  94 import jdk.internal.dynalink.linker.LinkerServices;
  95 import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
  96 import jdk.internal.dynalink.support.LinkRequestImpl;
  97 import jdk.internal.dynalink.support.Lookup;
  98 import jdk.internal.dynalink.support.RuntimeContextLinkRequestImpl;
  99 
 100 /**
 101  * The linker for {@link RelinkableCallSite} objects. Users of it (scripting frameworks and language runtimes) have to
 102  * create a linker using the {@link DynamicLinkerFactory} and invoke its link method from the invokedynamic bootstrap
 103  * methods to set the target of all the call sites in the code they generate. Usual usage would be to create one class
 104  * per language runtime to contain one linker instance as:
 105  *
 106  * <pre>
 107  * class MyLanguageRuntime {
 108  *     private static final GuardingDynamicLinker myLanguageLinker = new MyLanguageLinker();
 109  *     private static final DynamicLinker dynamicLinker = createDynamicLinker();
 110  *


 235         // None found - throw an exception
 236         if(guardedInvocation == null) {
 237             throw new NoSuchDynamicMethodException(callSiteDescriptor.toString());
 238         }
 239 
 240         // If our call sites have a runtime context, and the linker produced a context-stripped invocation, adapt the
 241         // produced invocation into contextual invocation (by dropping the context...)
 242         if(runtimeContextArgCount > 0) {
 243             final MethodType origType = callSiteDescriptor.getMethodType();
 244             final MethodHandle invocation = guardedInvocation.getInvocation();
 245             if(invocation.type().parameterCount() == origType.parameterCount() - runtimeContextArgCount) {
 246                 final List<Class<?>> prefix = origType.parameterList().subList(1, runtimeContextArgCount + 1);
 247                 final MethodHandle guard = guardedInvocation.getGuard();
 248                 guardedInvocation = guardedInvocation.dropArguments(1, prefix);
 249             }
 250         }
 251 
 252         // Make sure we filter the invocation before linking it into the call site. This is typically used to match the
 253         // return type of the invocation to the call site.
 254         guardedInvocation = prelinkFilter.filter(guardedInvocation, linkRequest, linkerServices);
 255         guardedInvocation.getClass(); // null pointer check
 256 
 257         int newRelinkCount = relinkCount;
 258         // Note that the short-circuited "&&" evaluation below ensures we'll increment the relinkCount until
 259         // threshold + 1 but not beyond that. Threshold + 1 is treated as a special value to signal that resetAndRelink
 260         // has already executed once for the unstable call site; we only want the call site to throw away its current
 261         // linkage once, when it transitions to unstable.
 262         if(unstableDetectionEnabled && newRelinkCount <= unstableRelinkThreshold && newRelinkCount++ == unstableRelinkThreshold) {
 263             callSite.resetAndRelink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
 264         } else {
 265             callSite.relink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
 266         }
 267         if(syncOnRelink) {
 268             MutableCallSite.syncAll(new MutableCallSite[] { (MutableCallSite)callSite });
 269         }
 270         return guardedInvocation.getInvocation();
 271     }
 272 
 273     /**
 274      * Returns a stack trace element describing the location of the call site currently being linked on the current
 275      * thread. The operation internally creates a Throwable object and inspects its stack trace, so it's potentially




  71        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  72        IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  73        TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  74        PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
  75        BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  76        CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  77        SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  78        BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  79        WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  80        OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  81        ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  82 */
  83 
  84 package jdk.internal.dynalink;
  85 
  86 import java.lang.invoke.MethodHandle;
  87 import java.lang.invoke.MethodHandles;
  88 import java.lang.invoke.MethodType;
  89 import java.lang.invoke.MutableCallSite;
  90 import java.util.List;
  91 import java.util.Objects;
  92 import jdk.internal.dynalink.linker.GuardedInvocation;
  93 import jdk.internal.dynalink.linker.GuardingDynamicLinker;
  94 import jdk.internal.dynalink.linker.LinkRequest;
  95 import jdk.internal.dynalink.linker.LinkerServices;
  96 import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
  97 import jdk.internal.dynalink.support.LinkRequestImpl;
  98 import jdk.internal.dynalink.support.Lookup;
  99 import jdk.internal.dynalink.support.RuntimeContextLinkRequestImpl;
 100 
 101 /**
 102  * The linker for {@link RelinkableCallSite} objects. Users of it (scripting frameworks and language runtimes) have to
 103  * create a linker using the {@link DynamicLinkerFactory} and invoke its link method from the invokedynamic bootstrap
 104  * methods to set the target of all the call sites in the code they generate. Usual usage would be to create one class
 105  * per language runtime to contain one linker instance as:
 106  *
 107  * <pre>
 108  * class MyLanguageRuntime {
 109  *     private static final GuardingDynamicLinker myLanguageLinker = new MyLanguageLinker();
 110  *     private static final DynamicLinker dynamicLinker = createDynamicLinker();
 111  *


 236         // None found - throw an exception
 237         if(guardedInvocation == null) {
 238             throw new NoSuchDynamicMethodException(callSiteDescriptor.toString());
 239         }
 240 
 241         // If our call sites have a runtime context, and the linker produced a context-stripped invocation, adapt the
 242         // produced invocation into contextual invocation (by dropping the context...)
 243         if(runtimeContextArgCount > 0) {
 244             final MethodType origType = callSiteDescriptor.getMethodType();
 245             final MethodHandle invocation = guardedInvocation.getInvocation();
 246             if(invocation.type().parameterCount() == origType.parameterCount() - runtimeContextArgCount) {
 247                 final List<Class<?>> prefix = origType.parameterList().subList(1, runtimeContextArgCount + 1);
 248                 final MethodHandle guard = guardedInvocation.getGuard();
 249                 guardedInvocation = guardedInvocation.dropArguments(1, prefix);
 250             }
 251         }
 252 
 253         // Make sure we filter the invocation before linking it into the call site. This is typically used to match the
 254         // return type of the invocation to the call site.
 255         guardedInvocation = prelinkFilter.filter(guardedInvocation, linkRequest, linkerServices);
 256         Objects.requireNonNull(guardedInvocation);
 257 
 258         int newRelinkCount = relinkCount;
 259         // Note that the short-circuited "&&" evaluation below ensures we'll increment the relinkCount until
 260         // threshold + 1 but not beyond that. Threshold + 1 is treated as a special value to signal that resetAndRelink
 261         // has already executed once for the unstable call site; we only want the call site to throw away its current
 262         // linkage once, when it transitions to unstable.
 263         if(unstableDetectionEnabled && newRelinkCount <= unstableRelinkThreshold && newRelinkCount++ == unstableRelinkThreshold) {
 264             callSite.resetAndRelink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
 265         } else {
 266             callSite.relink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
 267         }
 268         if(syncOnRelink) {
 269             MutableCallSite.syncAll(new MutableCallSite[] { (MutableCallSite)callSite });
 270         }
 271         return guardedInvocation.getInvocation();
 272     }
 273 
 274     /**
 275      * Returns a stack trace element describing the location of the call site currently being linked on the current
 276      * thread. The operation internally creates a Throwable object and inspects its stack trace, so it's potentially