changeset 56200:aa3715655834

8230662: Remove dead code from MethodTypeForm Reviewed-by: vlivanov, mchung
author redestad
date Sat, 07 Sep 2019 15:44:04 +0200
parents 378007c18687
children c7374ff3f3a3
files src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java src/java.base/share/classes/java/lang/invoke/MethodType.java src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java
diffstat 3 files changed, 31 insertions(+), 163 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Fri Sep 06 12:41:21 2019 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Sat Sep 07 15:44:04 2019 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -123,9 +123,13 @@
     private InvokerBytecodeGenerator(String className, String invokerName, MethodType invokerType) {
         this(null, invokerType.parameterCount(),
              className, invokerName, invokerType);
+        MethodType mt = invokerType.erase();
         // Create an array to map name indexes to locals indexes.
-        for (int i = 0; i < localsMap.length; i++) {
-            localsMap[i] = invokerType.parameterSlotCount() - invokerType.parameterSlotDepth(i);
+        localsMap[0] = 0; // localsMap has at least one element
+        for (int i = 1, index = 0; i < localsMap.length; i++) {
+            Wrapper w = Wrapper.forBasicType(mt.parameterType(i - 1));
+            index += w.stackSlots();
+            localsMap[i] = index;
         }
     }
 
--- a/src/java.base/share/classes/java/lang/invoke/MethodType.java	Fri Sep 06 12:41:21 2019 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/MethodType.java	Sat Sep 07 15:44:04 2019 +0200
@@ -926,8 +926,8 @@
                 return false;
             return true;
         }
-        if ((oldForm.primitiveParameterCount() == 0 && oldForm.erasedType == this) ||
-            (newForm.primitiveParameterCount() == 0 && newForm.erasedType == newType)) {
+        if ((!oldForm.hasPrimitives() && oldForm.erasedType == this) ||
+            (!newForm.hasPrimitives() && newForm.erasedType == newType)) {
             // Somewhat complicated test to avoid a loop of 2 or more trips.
             // If either type has only Object parameters, we know we can convert.
             assert(canConvertParameters(srcTypes, dstTypes));
@@ -1073,49 +1073,6 @@
         return inv;
     }
 
-    /** Reports the number of JVM stack slots which carry all parameters including and after
-     * the given position, which must be in the range of 0 to
-     * {@code parameterCount} inclusive.  Successive parameters are
-     * more shallowly stacked, and parameters are indexed in the bytecodes
-     * according to their trailing edge.  Thus, to obtain the depth
-     * in the outgoing call stack of parameter {@code N}, obtain
-     * the {@code parameterSlotDepth} of its trailing edge
-     * at position {@code N+1}.
-     * <p>
-     * Parameters of type {@code long} and {@code double} occupy
-     * two stack slots (for historical reasons) and all others occupy one.
-     * Therefore, the number returned is the number of arguments
-     * <em>including</em> and <em>after</em> the given parameter,
-     * <em>plus</em> the number of long or double arguments
-     * at or after the argument for the given parameter.
-     * <p>
-     * This method is included for the benefit of applications that must
-     * generate bytecodes that process method handles and invokedynamic.
-     * @param num an index (zero-based, inclusive) within the parameter types
-     * @return the index of the (shallowest) JVM stack slot transmitting the
-     *         given parameter
-     * @throws IllegalArgumentException if {@code num} is negative or greater than {@code parameterCount()}
-     */
-    /*non-public*/ int parameterSlotDepth(int num) {
-        if (num < 0 || num > ptypes.length)
-            parameterType(num);  // force a range check
-        return form.parameterToArgSlot(num-1);
-    }
-
-    /** Reports the number of JVM stack slots required to receive a return value
-     * from a method of this type.
-     * If the {@link #returnType() return type} is void, it will be zero,
-     * else if the return type is long or double, it will be two, else one.
-     * <p>
-     * This method is included for the benefit of applications that must
-     * generate bytecodes that process method handles and invokedynamic.
-     * @return the number of JVM stack slots (0, 1, or 2) for this type's return value
-     * Will be removed for PFD.
-     */
-    /*non-public*/ int returnSlotCount() {
-        return form.returnSlotCount();
-    }
-
     /**
      * Finds or creates an instance of a method type, given the spelling of its bytecode descriptor.
      * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
--- a/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java	Fri Sep 06 12:41:21 2019 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java	Sat Sep 07 15:44:04 2019 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, 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
@@ -46,9 +46,8 @@
  * @author John Rose
  */
 final class MethodTypeForm {
-    final int[] argToSlotTable, slotToArgTable;
-    final long argCounts;               // packed slot & value counts
-    final long primCounts;              // packed prim & double counts
+    final short parameterSlotCount;
+    final short primitiveCount;
     final MethodType erasedType;        // the canonical erasure
     final MethodType basicType;         // the canonical erasure, with primitives simplified
 
@@ -159,23 +158,18 @@
         this.erasedType = erasedType;
 
         Class<?>[] ptypes = erasedType.ptypes();
-        int ptypeCount = ptypes.length;
-        int pslotCount = ptypeCount;            // temp. estimate
-        int rtypeCount = 1;                     // temp. estimate
-        int rslotCount = 1;                     // temp. estimate
-
-        int[] argToSlotTab = null, slotToArgTab = null;
+        int pslotCount = ptypes.length;
 
         // Walk the argument types, looking for primitives.
-        int pac = 0, lac = 0, prc = 0, lrc = 0;
+        short primitiveCount = 0, longArgCount = 0;
         Class<?>[] epts = ptypes;
         Class<?>[] bpts = epts;
         for (int i = 0; i < epts.length; i++) {
             Class<?> pt = epts[i];
             if (pt != Object.class) {
-                ++pac;
+                ++primitiveCount;
                 Wrapper w = Wrapper.forPrimitiveType(pt);
-                if (w.isDoubleWord())  ++lac;
+                if (w.isDoubleWord())  ++longArgCount;
                 if (w.isSubwordOrInt() && pt != int.class) {
                     if (bpts == epts)
                         bpts = bpts.clone();
@@ -183,20 +177,14 @@
                 }
             }
         }
-        pslotCount += lac;                  // #slots = #args + #longs
+        pslotCount += longArgCount;                  // #slots = #args + #longs
         Class<?> rt = erasedType.returnType();
         Class<?> bt = rt;
         if (rt != Object.class) {
-            ++prc;          // even void.class counts as a prim here
+            ++primitiveCount; // even void.class counts as a prim here
             Wrapper w = Wrapper.forPrimitiveType(rt);
-            if (w.isDoubleWord())  ++lrc;
             if (w.isSubwordOrInt() && rt != int.class)
                 bt = int.class;
-            // adjust #slots, #args
-            if (rt == void.class)
-                rtypeCount = rslotCount = 0;
-            else
-                rslotCount += lrc;
         }
         if (epts == bpts && bt == rt) {
             this.basicType = erasedType;
@@ -205,112 +193,32 @@
             // fill in rest of data from the basic type:
             MethodTypeForm that = this.basicType.form();
             assert(this != that);
-            this.primCounts = that.primCounts;
-            this.argCounts = that.argCounts;
-            this.argToSlotTable = that.argToSlotTable;
-            this.slotToArgTable = that.slotToArgTable;
+            this.parameterSlotCount = that.parameterSlotCount;
+            this.primitiveCount = that.primitiveCount;
             this.methodHandles = null;
             this.lambdaForms = null;
             return;
         }
-        if (lac != 0) {
-            int slot = ptypeCount + lac;
-            slotToArgTab = new int[slot+1];
-            argToSlotTab = new int[1+ptypeCount];
-            argToSlotTab[0] = slot;  // argument "-1" is past end of slots
-            for (int i = 0; i < epts.length; i++) {
-                Class<?> pt = epts[i];
-                Wrapper w = Wrapper.forBasicType(pt);
-                if (w.isDoubleWord())  --slot;
-                --slot;
-                slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
-                argToSlotTab[1+i]  = slot;
-            }
-            assert(slot == 0);  // filled the table
-        } else if (pac != 0) {
-            // have primitives but no long primitives; share slot counts with generic
-            assert(ptypeCount == pslotCount);
-            MethodTypeForm that = MethodType.genericMethodType(ptypeCount).form();
-            assert(this != that);
-            slotToArgTab = that.slotToArgTable;
-            argToSlotTab = that.argToSlotTable;
-        } else {
-            int slot = ptypeCount; // first arg is deepest in stack
-            slotToArgTab = new int[slot+1];
-            argToSlotTab = new int[1+ptypeCount];
-            argToSlotTab[0] = slot;  // argument "-1" is past end of slots
-            for (int i = 0; i < ptypeCount; i++) {
-                --slot;
-                slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
-                argToSlotTab[1+i]  = slot;
-            }
-        }
-        this.primCounts = pack(lrc, prc, lac, pac);
-        this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount);
-        this.argToSlotTable = argToSlotTab;
-        this.slotToArgTable = slotToArgTab;
 
         if (pslotCount >= 256)  throw newIllegalArgumentException("too many arguments");
 
+        this.primitiveCount = primitiveCount;
+        this.parameterSlotCount = (short)pslotCount;
+
         // Initialize caches, but only for basic types
         assert(basicType == erasedType);
         this.lambdaForms   = new SoftReference[LF_LIMIT];
         this.methodHandles = new SoftReference[MH_LIMIT];
     }
 
-    private static long pack(int a, int b, int c, int d) {
-        assert(((a|b|c|d) & ~0xFFFF) == 0);
-        long hw = ((a << 16) | b), lw = ((c << 16) | d);
-        return (hw << 32) | lw;
-    }
-    private static char unpack(long packed, int word) { // word==0 => return a, ==3 => return d
-        assert(word <= 3);
-        return (char)(packed >> ((3-word) * 16));
-    }
-
     public int parameterCount() {                      // # outgoing values
-        return unpack(argCounts, 3);
+        return erasedType.parameterCount();
     }
     public int parameterSlotCount() {                  // # outgoing interpreter slots
-        return unpack(argCounts, 2);
-    }
-    public int returnCount() {                         // = 0 (V), or 1
-        return unpack(argCounts, 1);
-    }
-    public int returnSlotCount() {                     // = 0 (V), 2 (J/D), or 1
-        return unpack(argCounts, 0);
-    }
-    public int primitiveParameterCount() {
-        return unpack(primCounts, 3);
-    }
-    public int longPrimitiveParameterCount() {
-        return unpack(primCounts, 2);
-    }
-    public int primitiveReturnCount() {                // = 0 (obj), or 1
-        return unpack(primCounts, 1);
-    }
-    public int longPrimitiveReturnCount() {            // = 1 (J/D), or 0
-        return unpack(primCounts, 0);
+        return parameterSlotCount;
     }
     public boolean hasPrimitives() {
-        return primCounts != 0;
-    }
-    public boolean hasNonVoidPrimitives() {
-        if (primCounts == 0)  return false;
-        if (primitiveParameterCount() != 0)  return true;
-        return (primitiveReturnCount() != 0 && returnCount() != 0);
-    }
-    public boolean hasLongPrimitives() {
-        return (longPrimitiveParameterCount() | longPrimitiveReturnCount()) != 0;
-    }
-    public int parameterToArgSlot(int i) {
-        return argToSlotTable[1+i];
-    }
-    public int argSlotToParameter(int argSlot) {
-        // Note:  Empty slots are represented by zero in this table.
-        // Valid arguments slots contain incremented entries, so as to be non-zero.
-        // We return -1 the caller to mean an empty slot.
-        return slotToArgTable[argSlot] - 1;
+        return primitiveCount != 0;
     }
 
     static MethodTypeForm findForm(MethodType mt) {
@@ -334,7 +242,7 @@
      * (assumed to be a return type) to int if it is smaller than an int,
      * or if it is void.
      */
-    public static final int NO_CHANGE = 0, ERASE = 1, WRAP = 2, UNWRAP = 3, INTS = 4, LONGS = 5, RAW_RETURN = 6;
+    public static final int ERASE = 1, WRAP = 2, UNWRAP = 3, INTS = 4, LONGS = 5, RAW_RETURN = 6;
 
     /** Canonicalize the types in the given method type.
      * If any types change, intern the new type, and return it.
@@ -342,9 +250,9 @@
      */
     public static MethodType canonicalize(MethodType mt, int howRet, int howArgs) {
         Class<?>[] ptypes = mt.ptypes();
-        Class<?>[] ptc = MethodTypeForm.canonicalizeAll(ptypes, howArgs);
+        Class<?>[] ptc = canonicalizeAll(ptypes, howArgs);
         Class<?> rtype = mt.returnType();
-        Class<?> rtc = MethodTypeForm.canonicalize(rtype, howRet);
+        Class<?> rtc = canonicalize(rtype, howRet);
         if (ptc == null && rtc == null) {
             // It is already canonical.
             return null;
@@ -414,9 +322,8 @@
         Class<?>[] cs = null;
         for (int imax = ts.length, i = 0; i < imax; i++) {
             Class<?> c = canonicalize(ts[i], how);
-            if (c == void.class)
-                c = null;  // a Void parameter was unwrapped to void; ignore
-            if (c != null) {
+            // Void parameters may be unwrapped to void; ignore those
+            if (c != null && c != void.class) {
                 if (cs == null)
                     cs = ts.clone();
                 cs[i] = c;