jdk/src/share/classes/java/dyn/CallSite.java
changeset 8346 3b891698c4ec
parent 7562 a0ad195efe2c
child 8347 e5daa5772ffd
equal deleted inserted replaced
8345:9e2483e6cfab 8346:3b891698c4ec
     1 /*
     1 /*
     2  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    76   printArgs = lookup.findStatic(thisClass,
    76   printArgs = lookup.findStatic(thisClass,
    77       "printArgs", MethodType.methodType(void.class, Object[].class));
    77       "printArgs", MethodType.methodType(void.class, Object[].class));
    78 }
    78 }
    79 private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String name, MethodType type) {
    79 private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String name, MethodType type) {
    80   // ignore caller and name, but match the type:
    80   // ignore caller and name, but match the type:
    81   return new ConstantCallSite(MethodHandles.collectArguments(printArgs, type));
    81   return new ConstantCallSite(printArgs.asType(type));
    82 }
    82 }
    83 </pre></blockquote>
    83 </pre></blockquote>
    84  * @author John Rose, JSR 292 EG
    84  * @author John Rose, JSR 292 EG
    85  */
    85  */
    86 abstract
    86 abstract
    87 public class CallSite {
    87 public class CallSite {
    88     private static final Access IMPL_TOKEN = Access.getToken();
    88     private static final Access IMPL_TOKEN = Access.getToken();
       
    89     static { MethodHandleImpl.initStatics(); }
    89 
    90 
    90     // Fields used only by the JVM.  Do not use or change.
    91     // Fields used only by the JVM.  Do not use or change.
    91     private MemberName vmmethod; // supplied by the JVM (ref. to calling method)
    92     private MemberName vmmethod; // supplied by the JVM (ref. to calling method)
    92     private int        vmindex;  // supplied by the JVM (BCI within calling method)
    93     private int        vmindex;  // supplied by the JVM (BCI within calling method)
    93 
    94 
   123         target.type();  // null check
   124         target.type();  // null check
   124         this.target = target;
   125         this.target = target;
   125     }
   126     }
   126 
   127 
   127     /**
   128     /**
   128      * Report the type of this call site's target.
   129      * Returns the type of this call site's target.
   129      * Although targets may change, the call site's type can never change.
   130      * Although targets may change, any call site's type is permanent, and can never change to an unequal type.
   130      * The {@code setTarget} method enforces this invariant by refusing any new target that does
   131      * The {@code setTarget} method enforces this invariant by refusing any new target that does
   131      * not have the previous target's type.
   132      * not have the previous target's type.
   132      * @return the type of the current target, which is also the type of any future target
   133      * @return the type of the current target, which is also the type of any future target
   133      */
   134      */
   134     public MethodType type() {
   135     public MethodType type() {
   152         this.vmindex  = callerBCI;
   153         this.vmindex  = callerBCI;
   153         this.vmmethod = callerMethod;
   154         this.vmmethod = callerMethod;
   154     }
   155     }
   155 
   156 
   156     /**
   157     /**
   157      * Report the current linkage state of the call site, a value which may change over time.
   158      * Returns the target method of the call site, according to the
   158      * <p>
   159      * behavior defined by this call site's specific class.
   159      * If a {@code CallSite} object is returned
   160      * The immediate subclasses of {@code CallSite} document the
   160      * from the bootstrap method of the {@code invokedynamic} instruction,
   161      * class-specific behaviors of this method.
   161      * the {@code CallSite} is permanently bound to that instruction.
   162      *
   162      * When the {@code invokedynamic} instruction is executed, the target method
       
   163      * of its associated call site object is invoked directly.
       
   164      * It is as if the instruction calls {@code getTarget} and then
       
   165      * calls {@link MethodHandle#invokeExact invokeExact} on the result.
       
   166      * <p>
       
   167      * Unless specified differently by a subclass,
       
   168      * the interactions of {@code getTarget} with memory are the same
       
   169      * as of a read from an ordinary variable, such as an array element or a
       
   170      * non-volatile, non-final field.
       
   171      * <p>
       
   172      * In particular, the current thread may choose to reuse the result
       
   173      * of a previous read of the target from memory, and may fail to see
       
   174      * a recent update to the target by another thread.
       
   175      * <p>
       
   176      * In a {@linkplain ConstantCallSite constant call site}, the {@code getTarget} method behaves
       
   177      * like a read from a {@code final} field of the {@code CallSite}.
       
   178      * <p>
       
   179      * In a {@linkplain VolatileCallSite volatile call site}, the {@code getTarget} method behaves
       
   180      * like a read from a {@code volatile} field of the {@code CallSite}.
       
   181      * <p>
       
   182      * This method may not be overridden by application code.
       
   183      * @return the current linkage state of the call site, its target method handle
   163      * @return the current linkage state of the call site, its target method handle
   184      * @see ConstantCallSite
   164      * @see ConstantCallSite
   185      * @see VolatileCallSite
   165      * @see VolatileCallSite
   186      * @see #setTarget
   166      * @see #setTarget
   187      */
   167      * @see ConstantCallSite#getTarget
   188     public final MethodHandle getTarget() {
   168      * @see MutableCallSite#getTarget
   189         return getTarget0();
   169      * @see VolatileCallSite#getTarget
   190     }
   170      */
   191 
   171     public abstract MethodHandle getTarget();
   192     /**
   172 
   193      * Privileged implementations can override this to force final or volatile semantics on getTarget.
   173     /**
   194      */
   174      * Updates the target method of this call site, according to the
   195     /*package-private*/
   175      * behavior defined by this call site's specific class.
   196     MethodHandle getTarget0() {
   176      * The immediate subclasses of {@code CallSite} document the
   197         return target;
   177      * class-specific behaviors of this method.
   198     }
       
   199 
       
   200     /**
       
   201      * Set the target method of this call site.
       
   202      * <p>
   178      * <p>
   203      * Unless a subclass of CallSite documents otherwise,
   179      * The type of the new target must be {@linkplain MethodType#equals equal to}
   204      * the interactions of {@code setTarget} with memory are the same
   180      * the type of the old target.
   205      * as of a write to an ordinary variable, such as an array element or a
   181      *
   206      * non-volatile, non-final field.
       
   207      * <p>
       
   208      * In particular, unrelated threads may fail to see the updated target
       
   209      * until they perform a read from memory.
       
   210      * Stronger guarantees can be created by putting appropriate operations
       
   211      * into the bootstrap method and/or the target methods used
       
   212      * at any given call site.
       
   213      * @param newTarget the new target
   182      * @param newTarget the new target
   214      * @throws NullPointerException if the proposed new target is null
   183      * @throws NullPointerException if the proposed new target is null
   215      * @throws WrongMethodTypeException if the proposed new target
   184      * @throws WrongMethodTypeException if the proposed new target
   216      *         has a method type that differs from the previous target
   185      *         has a method type that differs from the previous target
   217      * @throws UnsupportedOperationException if the call site is
   186      * @see CallSite#getTarget
   218      *         in fact a {@link ConstantCallSite}
   187      * @see ConstantCallSite#setTarget
   219      */
   188      * @see MutableCallSite#setTarget
   220     public void setTarget(MethodHandle newTarget) {
   189      * @see VolatileCallSite#setTarget
   221         checkTargetChange(this.target, newTarget);
   190      */
   222         setTargetNormal(newTarget);
   191     public abstract void setTarget(MethodHandle newTarget);
   223     }
       
   224 
   192 
   225     void checkTargetChange(MethodHandle oldTarget, MethodHandle newTarget) {
   193     void checkTargetChange(MethodHandle oldTarget, MethodHandle newTarget) {
   226         MethodType oldType = oldTarget.type();
   194         MethodType oldType = oldTarget.type();
   227         MethodType newType = newTarget.type();  // null check!
   195         MethodType newType = newTarget.type();  // null check!
   228         if (!newType.equals(oldType))
   196         if (!newType.equals(oldType))
   234     }
   202     }
   235 
   203 
   236     /**
   204     /**
   237      * Produce a method handle equivalent to an invokedynamic instruction
   205      * Produce a method handle equivalent to an invokedynamic instruction
   238      * which has been linked to this call site.
   206      * which has been linked to this call site.
   239      * <p>If this call site is a {@linkplain ConstantCallSite constant call site},
   207      * <p>
   240      * this method simply returns the call site's target, since that will never change.
   208      * This method is equivalent to the following code:
   241      * <p>Otherwise, this method is equivalent to the following code:
   209      * <blockquote><pre>
   242      * <p><blockquote><pre>
       
   243      * MethodHandle getTarget, invoker, result;
   210      * MethodHandle getTarget, invoker, result;
   244      * getTarget = MethodHandles.lookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class));
   211      * getTarget = MethodHandles.publicLookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class));
   245      * invoker = MethodHandles.exactInvoker(this.type());
   212      * invoker = MethodHandles.exactInvoker(this.type());
   246      * result = MethodHandles.foldArguments(invoker, getTarget)
   213      * result = MethodHandles.foldArguments(invoker, getTarget)
   247      * </pre></blockquote>
   214      * </pre></blockquote>
       
   215      *
   248      * @return a method handle which always invokes this call site's current target
   216      * @return a method handle which always invokes this call site's current target
   249      */
   217      */
   250     public final MethodHandle dynamicInvoker() {
   218     public abstract MethodHandle dynamicInvoker();
   251         if (this instanceof ConstantCallSite) {
   219 
   252             return getTarget0();  // will not change dynamically
   220     /*non-public*/ MethodHandle makeDynamicInvoker() {
   253         }
       
   254         MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, GET_TARGET, this);
   221         MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, GET_TARGET, this);
   255         MethodHandle invoker = MethodHandles.exactInvoker(this.type());
   222         MethodHandle invoker = MethodHandles.exactInvoker(this.type());
   256         return MethodHandles.foldArguments(invoker, getTarget);
   223         return MethodHandles.foldArguments(invoker, getTarget);
   257     }
   224     }
       
   225 
   258     private static final MethodHandle GET_TARGET;
   226     private static final MethodHandle GET_TARGET;
   259     static {
   227     static {
   260         try {
   228         try {
   261             GET_TARGET = MethodHandles.Lookup.IMPL_LOOKUP.
   229             GET_TARGET = MethodHandles.Lookup.IMPL_LOOKUP.
   262                 findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
   230                 findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));