src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 49935 2ace90aec488
child 58679 9c3209ff7550
equal deleted inserted replaced
58677:13588c901957 58678:9cf78a70fa4f
     1 /*
     1 /*
     2  * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2008, 2019, 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
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package java.lang.invoke;
    26 package java.lang.invoke;
    27 
    27 
    28 import jdk.internal.vm.annotation.Stable;
       
    29 import sun.invoke.util.Wrapper;
    28 import sun.invoke.util.Wrapper;
    30 
    29 
    31 import java.lang.ref.SoftReference;
    30 import java.lang.ref.SoftReference;
    32 
    31 
    33 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
    32 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
    44  * There are a little over 10 times that number of unerased types.
    43  * There are a little over 10 times that number of unerased types.
    45  * No more than half of these are likely to be loaded at once.
    44  * No more than half of these are likely to be loaded at once.
    46  * @author John Rose
    45  * @author John Rose
    47  */
    46  */
    48 final class MethodTypeForm {
    47 final class MethodTypeForm {
    49     final int[] argToSlotTable, slotToArgTable;
    48     final short parameterSlotCount;
    50     final long argCounts;               // packed slot & value counts
    49     final short primitiveCount;
    51     final long primCounts;              // packed prim & double counts
       
    52     final MethodType erasedType;        // the canonical erasure
    50     final MethodType erasedType;        // the canonical erasure
    53     final MethodType basicType;         // the canonical erasure, with primitives simplified
    51     final MethodType basicType;         // the canonical erasure, with primitives simplified
    54 
    52 
    55     // Cached adapter information:
    53     // Cached adapter information:
    56     @Stable final SoftReference<MethodHandle>[] methodHandles;
    54     final SoftReference<MethodHandle>[] methodHandles;
       
    55 
    57     // Indexes into methodHandles:
    56     // Indexes into methodHandles:
    58     static final int
    57     static final int
    59             MH_BASIC_INV      =  0,  // cached instance of MH.invokeBasic
    58             MH_BASIC_INV      =  0,  // cached instance of MH.invokeBasic
    60             MH_NF_INV         =  1,  // cached helper for LF.NamedFunction
    59             MH_NF_INV         =  1,  // cached helper for LF.NamedFunction
    61             MH_UNINIT_CS      =  2,  // uninitialized call site
    60             MH_UNINIT_CS      =  2,  // uninitialized call site
    62             MH_LIMIT          =  3;
    61             MH_LIMIT          =  3;
    63 
    62 
    64     // Cached lambda form information, for basic types only:
    63     // Cached lambda form information, for basic types only:
    65     final @Stable SoftReference<LambdaForm>[] lambdaForms;
    64     final SoftReference<LambdaForm>[] lambdaForms;
       
    65 
    66     // Indexes into lambdaForms:
    66     // Indexes into lambdaForms:
    67     static final int
    67     static final int
    68             LF_INVVIRTUAL              =  0,  // DMH invokeVirtual
    68             LF_INVVIRTUAL              =  0,  // DMH invokeVirtual
    69             LF_INVSTATIC               =  1,
    69             LF_INVSTATIC               =  1,
    70             LF_INVSPECIAL              =  2,
    70             LF_INVSPECIAL              =  2,
   102      */
   102      */
   103     public MethodType basicType() {
   103     public MethodType basicType() {
   104         return basicType;
   104         return basicType;
   105     }
   105     }
   106 
   106 
   107     private boolean assertIsBasicType() {
       
   108         // primitives must be flattened also
       
   109         assert(erasedType == basicType)
       
   110                 : "erasedType: " + erasedType + " != basicType: " + basicType;
       
   111         return true;
       
   112     }
       
   113 
       
   114     public MethodHandle cachedMethodHandle(int which) {
   107     public MethodHandle cachedMethodHandle(int which) {
   115         assert(assertIsBasicType());
       
   116         SoftReference<MethodHandle> entry = methodHandles[which];
   108         SoftReference<MethodHandle> entry = methodHandles[which];
   117         return (entry != null) ? entry.get() : null;
   109         return (entry != null) ? entry.get() : null;
   118     }
   110     }
   119 
   111 
   120     public synchronized MethodHandle setCachedMethodHandle(int which, MethodHandle mh) {
   112     public synchronized MethodHandle setCachedMethodHandle(int which, MethodHandle mh) {
   129         methodHandles[which] = new SoftReference<>(mh);
   121         methodHandles[which] = new SoftReference<>(mh);
   130         return mh;
   122         return mh;
   131     }
   123     }
   132 
   124 
   133     public LambdaForm cachedLambdaForm(int which) {
   125     public LambdaForm cachedLambdaForm(int which) {
   134         assert(assertIsBasicType());
       
   135         SoftReference<LambdaForm> entry = lambdaForms[which];
   126         SoftReference<LambdaForm> entry = lambdaForms[which];
   136         return (entry != null) ? entry.get() : null;
   127         return (entry != null) ? entry.get() : null;
   137     }
   128     }
   138 
   129 
   139     public synchronized LambdaForm setCachedLambdaForm(int which, LambdaForm form) {
   130     public synchronized LambdaForm setCachedLambdaForm(int which, LambdaForm form) {
   157     @SuppressWarnings({"rawtypes", "unchecked"})
   148     @SuppressWarnings({"rawtypes", "unchecked"})
   158     protected MethodTypeForm(MethodType erasedType) {
   149     protected MethodTypeForm(MethodType erasedType) {
   159         this.erasedType = erasedType;
   150         this.erasedType = erasedType;
   160 
   151 
   161         Class<?>[] ptypes = erasedType.ptypes();
   152         Class<?>[] ptypes = erasedType.ptypes();
   162         int ptypeCount = ptypes.length;
   153         int pslotCount = ptypes.length;
   163         int pslotCount = ptypeCount;            // temp. estimate
       
   164         int rtypeCount = 1;                     // temp. estimate
       
   165         int rslotCount = 1;                     // temp. estimate
       
   166 
       
   167         int[] argToSlotTab = null, slotToArgTab = null;
       
   168 
   154 
   169         // Walk the argument types, looking for primitives.
   155         // Walk the argument types, looking for primitives.
   170         int pac = 0, lac = 0, prc = 0, lrc = 0;
   156         short primitiveCount = 0, longArgCount = 0;
   171         Class<?>[] epts = ptypes;
   157         Class<?>[] erasedPtypes = ptypes;
   172         Class<?>[] bpts = epts;
   158         Class<?>[] basicPtypes = erasedPtypes;
   173         for (int i = 0; i < epts.length; i++) {
   159         for (int i = 0; i < erasedPtypes.length; i++) {
   174             Class<?> pt = epts[i];
   160             Class<?> ptype = erasedPtypes[i];
   175             if (pt != Object.class) {
   161             if (ptype != Object.class) {
   176                 ++pac;
   162                 ++primitiveCount;
   177                 Wrapper w = Wrapper.forPrimitiveType(pt);
   163                 Wrapper w = Wrapper.forPrimitiveType(ptype);
   178                 if (w.isDoubleWord())  ++lac;
   164                 if (w.isDoubleWord())  ++longArgCount;
   179                 if (w.isSubwordOrInt() && pt != int.class) {
   165                 if (w.isSubwordOrInt() && ptype != int.class) {
   180                     if (bpts == epts)
   166                     if (basicPtypes == erasedPtypes)
   181                         bpts = bpts.clone();
   167                         basicPtypes = basicPtypes.clone();
   182                     bpts[i] = int.class;
   168                     basicPtypes[i] = int.class;
   183                 }
   169                 }
   184             }
   170             }
   185         }
   171         }
   186         pslotCount += lac;                  // #slots = #args + #longs
   172         pslotCount += longArgCount;                  // #slots = #args + #longs
   187         Class<?> rt = erasedType.returnType();
   173         Class<?> returnType = erasedType.returnType();
   188         Class<?> bt = rt;
   174         Class<?> basicReturnType = returnType;
   189         if (rt != Object.class) {
   175         if (returnType != Object.class) {
   190             ++prc;          // even void.class counts as a prim here
   176             ++primitiveCount; // even void.class counts as a prim here
   191             Wrapper w = Wrapper.forPrimitiveType(rt);
   177             Wrapper w = Wrapper.forPrimitiveType(returnType);
   192             if (w.isDoubleWord())  ++lrc;
   178             if (w.isSubwordOrInt() && returnType != int.class)
   193             if (w.isSubwordOrInt() && rt != int.class)
   179                 basicReturnType = int.class;
   194                 bt = int.class;
   180         }
   195             // adjust #slots, #args
   181         if (erasedPtypes == basicPtypes && basicReturnType == returnType) {
   196             if (rt == void.class)
   182             // Basic type
   197                 rtypeCount = rslotCount = 0;
       
   198             else
       
   199                 rslotCount += lrc;
       
   200         }
       
   201         if (epts == bpts && bt == rt) {
       
   202             this.basicType = erasedType;
   183             this.basicType = erasedType;
       
   184 
       
   185             if (pslotCount >= 256)  throw newIllegalArgumentException("too many arguments");
       
   186 
       
   187             this.primitiveCount = primitiveCount;
       
   188             this.parameterSlotCount = (short)pslotCount;
       
   189             this.lambdaForms   = new SoftReference[LF_LIMIT];
       
   190             this.methodHandles = new SoftReference[MH_LIMIT];
   203         } else {
   191         } else {
   204             this.basicType = MethodType.makeImpl(bt, bpts, true);
   192             this.basicType = MethodType.makeImpl(basicReturnType, basicPtypes, true);
   205             // fill in rest of data from the basic type:
   193             // fill in rest of data from the basic type:
   206             MethodTypeForm that = this.basicType.form();
   194             MethodTypeForm that = this.basicType.form();
   207             assert(this != that);
   195             assert(this != that);
   208             this.primCounts = that.primCounts;
   196 
   209             this.argCounts = that.argCounts;
   197             this.parameterSlotCount = that.parameterSlotCount;
   210             this.argToSlotTable = that.argToSlotTable;
   198             this.primitiveCount = that.primitiveCount;
   211             this.slotToArgTable = that.slotToArgTable;
       
   212             this.methodHandles = null;
   199             this.methodHandles = null;
   213             this.lambdaForms = null;
   200             this.lambdaForms = null;
   214             return;
   201         }
   215         }
   202     }
   216         if (lac != 0) {
   203 
   217             int slot = ptypeCount + lac;
   204     public int parameterCount() {
   218             slotToArgTab = new int[slot+1];
   205         return erasedType.parameterCount();
   219             argToSlotTab = new int[1+ptypeCount];
   206     }
   220             argToSlotTab[0] = slot;  // argument "-1" is past end of slots
   207     public int parameterSlotCount() {
   221             for (int i = 0; i < epts.length; i++) {
   208         return parameterSlotCount;
   222                 Class<?> pt = epts[i];
       
   223                 Wrapper w = Wrapper.forBasicType(pt);
       
   224                 if (w.isDoubleWord())  --slot;
       
   225                 --slot;
       
   226                 slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
       
   227                 argToSlotTab[1+i]  = slot;
       
   228             }
       
   229             assert(slot == 0);  // filled the table
       
   230         } else if (pac != 0) {
       
   231             // have primitives but no long primitives; share slot counts with generic
       
   232             assert(ptypeCount == pslotCount);
       
   233             MethodTypeForm that = MethodType.genericMethodType(ptypeCount).form();
       
   234             assert(this != that);
       
   235             slotToArgTab = that.slotToArgTable;
       
   236             argToSlotTab = that.argToSlotTable;
       
   237         } else {
       
   238             int slot = ptypeCount; // first arg is deepest in stack
       
   239             slotToArgTab = new int[slot+1];
       
   240             argToSlotTab = new int[1+ptypeCount];
       
   241             argToSlotTab[0] = slot;  // argument "-1" is past end of slots
       
   242             for (int i = 0; i < ptypeCount; i++) {
       
   243                 --slot;
       
   244                 slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
       
   245                 argToSlotTab[1+i]  = slot;
       
   246             }
       
   247         }
       
   248         this.primCounts = pack(lrc, prc, lac, pac);
       
   249         this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount);
       
   250         this.argToSlotTable = argToSlotTab;
       
   251         this.slotToArgTable = slotToArgTab;
       
   252 
       
   253         if (pslotCount >= 256)  throw newIllegalArgumentException("too many arguments");
       
   254 
       
   255         // Initialize caches, but only for basic types
       
   256         assert(basicType == erasedType);
       
   257         this.lambdaForms   = new SoftReference[LF_LIMIT];
       
   258         this.methodHandles = new SoftReference[MH_LIMIT];
       
   259     }
       
   260 
       
   261     private static long pack(int a, int b, int c, int d) {
       
   262         assert(((a|b|c|d) & ~0xFFFF) == 0);
       
   263         long hw = ((a << 16) | b), lw = ((c << 16) | d);
       
   264         return (hw << 32) | lw;
       
   265     }
       
   266     private static char unpack(long packed, int word) { // word==0 => return a, ==3 => return d
       
   267         assert(word <= 3);
       
   268         return (char)(packed >> ((3-word) * 16));
       
   269     }
       
   270 
       
   271     public int parameterCount() {                      // # outgoing values
       
   272         return unpack(argCounts, 3);
       
   273     }
       
   274     public int parameterSlotCount() {                  // # outgoing interpreter slots
       
   275         return unpack(argCounts, 2);
       
   276     }
       
   277     public int returnCount() {                         // = 0 (V), or 1
       
   278         return unpack(argCounts, 1);
       
   279     }
       
   280     public int returnSlotCount() {                     // = 0 (V), 2 (J/D), or 1
       
   281         return unpack(argCounts, 0);
       
   282     }
       
   283     public int primitiveParameterCount() {
       
   284         return unpack(primCounts, 3);
       
   285     }
       
   286     public int longPrimitiveParameterCount() {
       
   287         return unpack(primCounts, 2);
       
   288     }
       
   289     public int primitiveReturnCount() {                // = 0 (obj), or 1
       
   290         return unpack(primCounts, 1);
       
   291     }
       
   292     public int longPrimitiveReturnCount() {            // = 1 (J/D), or 0
       
   293         return unpack(primCounts, 0);
       
   294     }
   209     }
   295     public boolean hasPrimitives() {
   210     public boolean hasPrimitives() {
   296         return primCounts != 0;
   211         return primitiveCount != 0;
   297     }
       
   298     public boolean hasNonVoidPrimitives() {
       
   299         if (primCounts == 0)  return false;
       
   300         if (primitiveParameterCount() != 0)  return true;
       
   301         return (primitiveReturnCount() != 0 && returnCount() != 0);
       
   302     }
       
   303     public boolean hasLongPrimitives() {
       
   304         return (longPrimitiveParameterCount() | longPrimitiveReturnCount()) != 0;
       
   305     }
       
   306     public int parameterToArgSlot(int i) {
       
   307         return argToSlotTable[1+i];
       
   308     }
       
   309     public int argSlotToParameter(int argSlot) {
       
   310         // Note:  Empty slots are represented by zero in this table.
       
   311         // Valid arguments slots contain incremented entries, so as to be non-zero.
       
   312         // We return -1 the caller to mean an empty slot.
       
   313         return slotToArgTable[argSlot] - 1;
       
   314     }
   212     }
   315 
   213 
   316     static MethodTypeForm findForm(MethodType mt) {
   214     static MethodTypeForm findForm(MethodType mt) {
   317         MethodType erased = canonicalize(mt, ERASE, ERASE);
   215         MethodType erased = canonicalize(mt, ERASE, ERASE);
   318         if (erased == null) {
   216         if (erased == null) {
   332      * according to size.  LONGS means convert all non-void primitives
   230      * according to size.  LONGS means convert all non-void primitives
   333      * to long, regardless of size.  RAW_RETURN means convert a type
   231      * to long, regardless of size.  RAW_RETURN means convert a type
   334      * (assumed to be a return type) to int if it is smaller than an int,
   232      * (assumed to be a return type) to int if it is smaller than an int,
   335      * or if it is void.
   233      * or if it is void.
   336      */
   234      */
   337     public static final int NO_CHANGE = 0, ERASE = 1, WRAP = 2, UNWRAP = 3, INTS = 4, LONGS = 5, RAW_RETURN = 6;
   235     public static final int ERASE = 1, WRAP = 2, UNWRAP = 3, INTS = 4, LONGS = 5, RAW_RETURN = 6;
   338 
   236 
   339     /** Canonicalize the types in the given method type.
   237     /** Canonicalize the types in the given method type.
   340      * If any types change, intern the new type, and return it.
   238      * If any types change, intern the new type, and return it.
   341      * Otherwise return null.
   239      * Otherwise return null.
   342      */
   240      */
   343     public static MethodType canonicalize(MethodType mt, int howRet, int howArgs) {
   241     public static MethodType canonicalize(MethodType mt, int howRet, int howArgs) {
   344         Class<?>[] ptypes = mt.ptypes();
   242         Class<?>[] ptypes = mt.ptypes();
   345         Class<?>[] ptc = MethodTypeForm.canonicalizeAll(ptypes, howArgs);
   243         Class<?>[] ptypesCanonical = canonicalizeAll(ptypes, howArgs);
   346         Class<?> rtype = mt.returnType();
   244         Class<?> rtype = mt.returnType();
   347         Class<?> rtc = MethodTypeForm.canonicalize(rtype, howRet);
   245         Class<?> rtypeCanonical = canonicalize(rtype, howRet);
   348         if (ptc == null && rtc == null) {
   246         if (ptypesCanonical == null && rtypeCanonical == null) {
   349             // It is already canonical.
   247             // It is already canonical.
   350             return null;
   248             return null;
   351         }
   249         }
   352         // Find the erased version of the method type:
   250         // Find the erased version of the method type:
   353         if (rtc == null)  rtc = rtype;
   251         if (rtypeCanonical == null)  rtypeCanonical = rtype;
   354         if (ptc == null)  ptc = ptypes;
   252         if (ptypesCanonical == null)  ptypesCanonical = ptypes;
   355         return MethodType.makeImpl(rtc, ptc, true);
   253         return MethodType.makeImpl(rtypeCanonical, ptypesCanonical, true);
   356     }
   254     }
   357 
   255 
   358     /** Canonicalize the given return or param type.
   256     /** Canonicalize the given return or param type.
   359      *  Return null if the type is already canonicalized.
   257      *  Return null if the type is already canonicalized.
   360      */
   258      */
   412      */
   310      */
   413     static Class<?>[] canonicalizeAll(Class<?>[] ts, int how) {
   311     static Class<?>[] canonicalizeAll(Class<?>[] ts, int how) {
   414         Class<?>[] cs = null;
   312         Class<?>[] cs = null;
   415         for (int imax = ts.length, i = 0; i < imax; i++) {
   313         for (int imax = ts.length, i = 0; i < imax; i++) {
   416             Class<?> c = canonicalize(ts[i], how);
   314             Class<?> c = canonicalize(ts[i], how);
   417             if (c == void.class)
   315             // Void parameters may be unwrapped to void; ignore those
   418                 c = null;  // a Void parameter was unwrapped to void; ignore
   316             if (c != null && c != void.class) {
   419             if (c != null) {
       
   420                 if (cs == null)
   317                 if (cs == null)
   421                     cs = ts.clone();
   318                     cs = ts.clone();
   422                 cs[i] = c;
   319                 cs[i] = c;
   423             }
   320             }
   424         }
   321         }