src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File jdk Sdiff src/java.base/share/classes/java/lang/invoke

src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java

Print this page
rev 10592 : 8050052: Small cleanups in java.lang.invoke code
Reviewed-by: ?
rev 10594 : 8050166: Get rid of some package-private methods on arguments in j.l.i.MethodHandle
Reviewed-by: vlivanov, ?
Contributed-by: john.r.rose@oracle.com
rev 10597 : 8050057: Improve caching of MethodHandle reinvokers
Reviewed-by: vlivanov, ?
Contributed-by: john.r.rose@oracle.com
rev 10605 : 8057657: Annotate LambdaForm parameters with types
Reviewed-by: vlivanov, ?
Contributed-by: john.r.rose@oracle.com
rev 10607 : 8057042: LambdaFormEditor: derive new LFs from a base LF
Reviewed-by: vlivanov, psandoz
Contributed-by: john.r.rose@oracle.com


  37 import java.util.HashMap;
  38 
  39 import sun.invoke.util.ValueConversions;
  40 import sun.invoke.util.Wrapper;
  41 
  42 import jdk.internal.org.objectweb.asm.ClassWriter;
  43 import jdk.internal.org.objectweb.asm.MethodVisitor;
  44 import jdk.internal.org.objectweb.asm.Type;
  45 
  46 /**
  47  * The flavor of method handle which emulates an invoke instruction
  48  * on a predetermined argument.  The JVM dispatches to the correct method
  49  * when the handle is created, not when it is invoked.
  50  *
  51  * All bound arguments are encapsulated in dedicated species.
  52  */
  53 /*non-public*/ abstract class BoundMethodHandle extends MethodHandle {
  54 
  55     /*non-public*/ BoundMethodHandle(MethodType type, LambdaForm form) {
  56         super(type, form);

  57     }
  58 
  59     //
  60     // BMH API and internals
  61     //
  62 
  63     static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) {
  64         // for some type signatures, there exist pre-defined concrete BMH classes
  65         try {
  66             switch (xtype) {
  67             case L_TYPE:
  68                 return bindSingle(type, form, x);  // Use known fast path.
  69             case I_TYPE:
  70                 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(I_TYPE).constructor().invokeBasic(type, form, ValueConversions.widenSubword(x));
  71             case J_TYPE:
  72                 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(J_TYPE).constructor().invokeBasic(type, form, (long) x);
  73             case F_TYPE:
  74                 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(F_TYPE).constructor().invokeBasic(type, form, (float) x);
  75             case D_TYPE:
  76                 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(D_TYPE).constructor().invokeBasic(type, form, (double) x);
  77             default : throw newInternalError("unexpected xtype: " + xtype);
  78             }
  79         } catch (Throwable t) {
  80             throw newInternalError(t);
  81         }
  82     }
  83 





  84     static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, Object x) {
  85         return Species_L.make(type, form, x);
  86     }
  87 
  88     @Override // there is a default binder in the super class, for 'L' types only
  89     /*non-public*/
  90     BoundMethodHandle bindArgumentL(int pos, Object value) {
  91         MethodType type = type().dropParameterTypes(pos, pos+1);
  92         LambdaForm form = internalForm().bind(1+pos, speciesData());
  93         return copyWithExtendL(type, form, value);
  94     }
  95     /*non-public*/
  96     BoundMethodHandle bindArgumentI(int pos, int value) {
  97         MethodType type = type().dropParameterTypes(pos, pos+1);
  98         LambdaForm form = internalForm().bind(1+pos, speciesData());
  99         return copyWithExtendI(type, form, value);
 100     }
 101     /*non-public*/
 102     BoundMethodHandle bindArgumentJ(int pos, long value) {
 103         MethodType type = type().dropParameterTypes(pos, pos+1);
 104         LambdaForm form = internalForm().bind(1+pos, speciesData());
 105         return copyWithExtendJ(type, form, value);
 106     }
 107     /*non-public*/
 108     BoundMethodHandle bindArgumentF(int pos, float value) {
 109         MethodType type = type().dropParameterTypes(pos, pos+1);
 110         LambdaForm form = internalForm().bind(1+pos, speciesData());
 111         return copyWithExtendF(type, form, value);
 112     }
 113     /*non-public*/
 114     BoundMethodHandle bindArgumentD(int pos, double value) {
 115         MethodType type = type().dropParameterTypes(pos, pos + 1);
 116         LambdaForm form = internalForm().bind(1+pos, speciesData());
 117         return copyWithExtendD(type, form, value);
 118     }
 119 
 120     @Override
 121     BoundMethodHandle rebind() {
 122         if (!tooComplex()) {
 123             return this;
 124         }
 125         return makeReinvoker(this);
 126     }
 127 
 128     private boolean tooComplex() {
 129         return (fieldCount() > FIELD_COUNT_THRESHOLD ||
 130                 form.expressionCount() > FORM_EXPRESSION_THRESHOLD);
 131     }
 132     private static final int FIELD_COUNT_THRESHOLD = 12;      // largest convenient BMH field count
 133     private static final int FORM_EXPRESSION_THRESHOLD = 24;  // largest convenient BMH expression count
 134 
 135     /**
 136      * A reinvoker MH has this form:
 137      * {@code lambda (bmh, arg*) { thismh = bmh[0]; invokeBasic(thismh, arg*) }}
 138      */
 139     static BoundMethodHandle makeReinvoker(MethodHandle target) {
 140         LambdaForm form = DelegatingMethodHandle.makeReinvokerForm(
 141                 target, MethodTypeForm.LF_REBIND,
 142                 Species_L.SPECIES_DATA, Species_L.SPECIES_DATA.getterFunction(0));
 143         return Species_L.make(target.type(), form, target);
 144     }
 145 
 146     /**
 147      * Return the {@link SpeciesData} instance representing this BMH species. All subclasses must provide a
 148      * static field containing this value, and they must accordingly implement this method.
 149      */
 150     /*non-public*/ abstract SpeciesData speciesData();
 151 








 152     /**
 153      * Return the number of fields in this BMH.  Equivalent to speciesData().fieldCount().
 154      */
 155     /*non-public*/ abstract int fieldCount();
 156 
 157     @Override
 158     Object internalProperties() {
 159         return "\n& BMH="+internalValues();
 160     }
 161 
 162     @Override
 163     final Object internalValues() {
 164         Object[] boundValues = new Object[speciesData().fieldCount()];
 165         for (int i = 0; i < boundValues.length; ++i) {
 166             boundValues[i] = arg(i);
 167         }
 168         return Arrays.asList(boundValues);
 169     }
 170 
 171     /*non-public*/ final Object arg(int i) {




  37 import java.util.HashMap;
  38 
  39 import sun.invoke.util.ValueConversions;
  40 import sun.invoke.util.Wrapper;
  41 
  42 import jdk.internal.org.objectweb.asm.ClassWriter;
  43 import jdk.internal.org.objectweb.asm.MethodVisitor;
  44 import jdk.internal.org.objectweb.asm.Type;
  45 
  46 /**
  47  * The flavor of method handle which emulates an invoke instruction
  48  * on a predetermined argument.  The JVM dispatches to the correct method
  49  * when the handle is created, not when it is invoked.
  50  *
  51  * All bound arguments are encapsulated in dedicated species.
  52  */
  53 /*non-public*/ abstract class BoundMethodHandle extends MethodHandle {
  54 
  55     /*non-public*/ BoundMethodHandle(MethodType type, LambdaForm form) {
  56         super(type, form);
  57         assert(speciesData() == speciesData(form));
  58     }
  59 
  60     //
  61     // BMH API and internals
  62     //
  63 
  64     static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) {
  65         // for some type signatures, there exist pre-defined concrete BMH classes
  66         try {
  67             switch (xtype) {
  68             case L_TYPE:
  69                 return bindSingle(type, form, x);  // Use known fast path.
  70             case I_TYPE:
  71                 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(I_TYPE).constructor().invokeBasic(type, form, ValueConversions.widenSubword(x));
  72             case J_TYPE:
  73                 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(J_TYPE).constructor().invokeBasic(type, form, (long) x);
  74             case F_TYPE:
  75                 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(F_TYPE).constructor().invokeBasic(type, form, (float) x);
  76             case D_TYPE:
  77                 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(D_TYPE).constructor().invokeBasic(type, form, (double) x);
  78             default : throw newInternalError("unexpected xtype: " + xtype);
  79             }
  80         } catch (Throwable t) {
  81             throw newInternalError(t);
  82         }
  83     }
  84 
  85     /*non-public*/
  86     LambdaFormEditor editor() {
  87         return form.editor();
  88     }
  89 
  90     static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, Object x) {
  91         return Species_L.make(type, form, x);
  92     }
  93 
  94     @Override // there is a default binder in the super class, for 'L' types only
  95     /*non-public*/
  96     BoundMethodHandle bindArgumentL(int pos, Object value) {
  97         return editor().bindArgumentL(this, pos, value);


  98     }
  99     /*non-public*/
 100     BoundMethodHandle bindArgumentI(int pos, int value) {
 101         return editor().bindArgumentI(this, pos, value);


 102     }
 103     /*non-public*/
 104     BoundMethodHandle bindArgumentJ(int pos, long value) {
 105         return editor().bindArgumentJ(this, pos, value);


 106     }
 107     /*non-public*/
 108     BoundMethodHandle bindArgumentF(int pos, float value) {
 109         return editor().bindArgumentF(this, pos, value);


 110     }
 111     /*non-public*/
 112     BoundMethodHandle bindArgumentD(int pos, double value) {
 113         return editor().bindArgumentD(this, pos, value);


 114     }
 115 
 116     @Override
 117     BoundMethodHandle rebind() {
 118         if (!tooComplex()) {
 119             return this;
 120         }
 121         return makeReinvoker(this);
 122     }
 123 
 124     private boolean tooComplex() {
 125         return (fieldCount() > FIELD_COUNT_THRESHOLD ||
 126                 form.expressionCount() > FORM_EXPRESSION_THRESHOLD);
 127     }
 128     private static final int FIELD_COUNT_THRESHOLD = 12;      // largest convenient BMH field count
 129     private static final int FORM_EXPRESSION_THRESHOLD = 24;  // largest convenient BMH expression count
 130 
 131     /**
 132      * A reinvoker MH has this form:
 133      * {@code lambda (bmh, arg*) { thismh = bmh[0]; invokeBasic(thismh, arg*) }}
 134      */
 135     static BoundMethodHandle makeReinvoker(MethodHandle target) {
 136         LambdaForm form = DelegatingMethodHandle.makeReinvokerForm(
 137                 target, MethodTypeForm.LF_REBIND,
 138                 Species_L.SPECIES_DATA, Species_L.SPECIES_DATA.getterFunction(0));
 139         return Species_L.make(target.type(), form, target);
 140     }
 141 
 142     /**
 143      * Return the {@link SpeciesData} instance representing this BMH species. All subclasses must provide a
 144      * static field containing this value, and they must accordingly implement this method.
 145      */
 146     /*non-public*/ abstract SpeciesData speciesData();
 147 
 148     /*non-public*/ static SpeciesData speciesData(LambdaForm form) {
 149         Object c = form.names[0].constraint;
 150         if (c instanceof SpeciesData)
 151             return (SpeciesData) c;
 152         // if there is no BMH constraint, then use the null constraint
 153         return SpeciesData.EMPTY;
 154     }
 155 
 156     /**
 157      * Return the number of fields in this BMH.  Equivalent to speciesData().fieldCount().
 158      */
 159     /*non-public*/ abstract int fieldCount();
 160 
 161     @Override
 162     Object internalProperties() {
 163         return "\n& BMH="+internalValues();
 164     }
 165 
 166     @Override
 167     final Object internalValues() {
 168         Object[] boundValues = new Object[speciesData().fieldCount()];
 169         for (int i = 0; i < boundValues.length; ++i) {
 170             boundValues[i] = arg(i);
 171         }
 172         return Arrays.asList(boundValues);
 173     }
 174 
 175     /*non-public*/ final Object arg(int i) {


src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File