changeset 416:971e1b4846fc

meth-lazy: add missing int conversions to BMH.bindArgument
author jrose
date Thu, 19 Jul 2012 19:28:11 -0700
parents b6a3c70ad80a
children e27e7efee021
files meth-lazy-7023639.bmh.patch
diffstat 1 files changed, 92 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/meth-lazy-7023639.bmh.patch	Thu Jul 19 00:27:37 2012 -0700
+++ b/meth-lazy-7023639.bmh.patch	Thu Jul 19 19:28:11 2012 -0700
@@ -46,19 +46,18 @@
  
  /**
   * The flavor of method handle which emulates an invoke instruction
-@@ -83,19 +66,18 @@
+@@ -83,19 +66,17 @@
          // for some type signatures, there exist pre-defined concrete BMH classes
          try {
              switch (xtype) {
 -            case 'L': return new BMH_L(type, form, x);
 +            case 'L':
-+                if (true)
-+                    return bindSingle(type, form, x);
-+                return (BoundMethodHandle) Data.get("L").constructor[0].invokeBasic(type, form, x);
++                if (true)  return bindSingle(type, form, x);  // Use known fast path.
++                return (BoundMethodHandle) Data.EMPTY.extendWithType('L').constructor[0].invokeBasic(type, form, x);
              case 'I':
 -                assert x instanceof Integer : "expected Integer, found " + x.getClass();
 -                return (BoundMethodHandle) Data.get("I").constructor.invokeBasic(type, form, ((Integer) x).intValue());
-+                return (BoundMethodHandle) Data.EMPTY.extendWithType('I').constructor[0].invokeBasic(type, form, (int) x);
++                return (BoundMethodHandle) Data.EMPTY.extendWithType('I').constructor[0].invokeBasic(type, form, ValueConversions.widenSubword(x));
              case 'J':
 -                assert x instanceof Long;
 -                return new BMH_J(type, form, ((Long) x).longValue());
@@ -74,7 +73,7 @@
              default : throw new InternalError("unexpected xtype: " + xtype);
              }
          } catch (Throwable t) {
-@@ -103,6 +85,10 @@
+@@ -103,38 +84,29 @@
          }
      }
  
@@ -85,24 +84,45 @@
      MethodHandle cloneExtend(MethodType type, LambdaForm form, char xtype, Object x) {
          try {
              switch (xtype) {
-@@ -122,7 +108,6 @@
-             default : throw new InternalError("unexpected type: " + xtype);
+             case 'L': return cloneExtendL(type, form, x);
+-            case 'I':
+-                assert x instanceof Integer : "expected Integer, found " + x.getClass();
+-                return cloneExtendI(type, form, ((Integer) x).intValue());
+-            case 'J':
+-                assert x instanceof Long;
+-                return cloneExtendJ(type, form, ((Long) x).longValue());
+-            case 'F':
+-                assert x instanceof Float;
+-                return cloneExtendF(type, form, ((Float) x).floatValue());
+-            case 'D':
+-                assert x instanceof Double;
+-                return cloneExtendD(type, form, ((Double) x).doubleValue());
+-            default : throw new InternalError("unexpected type: " + xtype);
++            case 'I': return cloneExtendI(type, form, ValueConversions.widenSubword(x));
++            case 'J': return cloneExtendJ(type, form, (long) x);
++            case 'F': return cloneExtendF(type, form, (float) x);
++            case 'D': return cloneExtendD(type, form, (double) x);
              }
          } catch (Throwable t) {
 -            System.out.println("cloneExtend "+Arrays.asList(type, form, xtype, x));//@@
              throw new InternalError(t);
          }
++        throw new InternalError("unexpected type: " + xtype);
      }
-@@ -130,7 +115,7 @@
+ 
      @Override
      MethodHandle bindArgument(int pos, char basicType, Object value) {
          MethodType type = type().dropParameterTypes(pos, pos+1);
 -        LambdaForm form = internalForm().bind(basicType, 1+pos, tcount());
+-        if (basicType == 'I' && !(value instanceof Integer)) {
+-            // Cf. ValueConversions.unboxInteger
+-            value = ValueConversions.primitiveConversion(Wrapper.INT, value, true);
+-        }
 +        LambdaForm form = internalForm().bind(1+pos, myData());
-         if (basicType == 'I' && !(value instanceof Integer)) {
-             // Cf. ValueConversions.unboxInteger
-             value = ValueConversions.primitiveConversion(Wrapper.INT, value, true);
-@@ -157,68 +142,43 @@
+         return cloneExtend(type, form, basicType, value);
+     }
+ 
+@@ -157,68 +129,43 @@
           }
      }
  
@@ -196,7 +216,7 @@
      public final Object argL(int i) throws Throwable { return          myData().getters[i].invokeBasic(this); }
      public final int    argI(int i) throws Throwable { return (int)    myData().getters[i].invokeBasic(this); }
      public final float  argF(int i) throws Throwable { return (float)  myData().getters[i].invokeBasic(this); }
-@@ -236,54 +196,60 @@
+@@ -236,54 +183,60 @@
      public abstract BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float  narg) throws Throwable;
      public abstract BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable;
  
@@ -271,7 +291,7 @@
      static final class BMH_LL extends BoundMethodHandle {
          final Object argL0;
          final Object argL1;
-@@ -293,33 +259,33 @@
+@@ -293,33 +246,33 @@
              this.argL1 = argL1;
          }
          @Override
@@ -313,7 +333,7 @@
          }
      }
  
-@@ -332,10 +298,10 @@
+@@ -332,10 +285,10 @@
              this.argL1 = argL1;
          }
          @Override
@@ -327,7 +347,7 @@
          @Override public final long   argJ0() { return argJ0; }
          @Override public final Object argL1() { return argL1; }
          @Override
-@@ -344,103 +310,26 @@
+@@ -344,103 +297,26 @@
          }
          @Override
          public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
@@ -437,7 +457,7 @@
  
      //
      // BMH meta-data
-@@ -452,60 +341,157 @@
+@@ -452,60 +328,157 @@
      static class Data {
          final String                             types;
          final Class<? extends BoundMethodHandle> clazz;
@@ -625,7 +645,7 @@
      /**
       * Generation of concrete BMH classes.
       *
-@@ -520,18 +506,20 @@
+@@ -520,18 +493,20 @@
       */
      static class Factory {
  
@@ -655,7 +675,7 @@
  
          static final String SIG_INCIPIT = "(Ljava/lang/invoke/MethodType;Ljava/lang/invoke/LambdaForm;";
  
-@@ -547,7 +535,7 @@
+@@ -547,7 +522,7 @@
           * <pre>
           * class BMH_<<types>> extends BMH {
           *     <<fields>>
@@ -664,7 +684,7 @@
           * }
           * </pre>
           *
-@@ -572,25 +560,27 @@
+@@ -572,25 +547,27 @@
           *         this.argL1 = argL1;
           *         this.argI2 = argI2;
           *     }
@@ -700,7 +720,7 @@
           *     }
           * }
           * </pre>
-@@ -601,14 +591,13 @@
+@@ -601,14 +578,13 @@
          static Class<? extends BoundMethodHandle> generateConcreteBMHClass(String types) {
              final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
  
@@ -718,7 +738,7 @@
  
              // emit bound argument fields
              for (int i = 0; i < types.length(); ++i) {
-@@ -644,10 +633,20 @@
+@@ -644,10 +620,20 @@
              mv.visitMaxs(0, 0);
              mv.visitEnd();
  
@@ -742,7 +762,7 @@
              mv.visitInsn(ARETURN);
              mv.visitMaxs(0, 0);
              mv.visitEnd();
-@@ -655,11 +654,13 @@
+@@ -655,11 +641,13 @@
              // emit clone()
              mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "clone", makeSignature("", false), null, E_THROWABLE);
              mv.visitCode();
@@ -759,7 +779,7 @@
              // load mt, lf
              mv.visitVarInsn(ALOAD, 1);
              mv.visitVarInsn(ALOAD, 2);
-@@ -674,14 +675,18 @@
+@@ -674,14 +662,18 @@
              // for each type, emit cloneExtendT()
              for (Class<?> c : TYPES) {
                  char t = Wrapper.basicTypeChar(c);
@@ -783,7 +803,7 @@
                  // load mt, lf
                  mv.visitVarInsn(ALOAD, 1);
                  mv.visitVarInsn(ALOAD, 2);
-@@ -690,19 +695,31 @@
+@@ -690,19 +682,31 @@
                  // put narg on stack
                  mv.visitVarInsn(typeLoadOp(t), 3);
                  // finally, invoke the constructor and return
@@ -817,7 +837,7 @@
              UNSAFE.ensureClassInitialized(bmhClass);
  
              return bmhClass;
-@@ -745,24 +762,31 @@
+@@ -745,24 +749,31 @@
              }
          }
  
@@ -856,7 +876,7 @@
              }
          }
  
-@@ -832,13 +856,12 @@
+@@ -832,13 +843,12 @@
              return cmh;
          }
  
@@ -2646,6 +2666,50 @@
          return BoundMethodHandle.bindSingle(type2, form2, basicType, value);
      }
  
+diff --git a/src/share/classes/sun/invoke/util/ValueConversions.java b/src/share/classes/sun/invoke/util/ValueConversions.java
+--- a/src/share/classes/sun/invoke/util/ValueConversions.java
++++ b/src/share/classes/sun/invoke/util/ValueConversions.java
+@@ -214,6 +214,12 @@
+     static private final Integer ZERO_INT = 0, ONE_INT = 1;
+ 
+     /// Primitive conversions
++    /**
++     * Produce a Number which represents the given value {@code x}
++     * according to the primitive type of the given wrapper {@code wrap}.
++     * Caller must invoke intValue, byteValue, longValue (etc.) on the result
++     * to retrieve the desired primitive value.
++     */
+     public static Number primitiveConversion(Wrapper wrap, Object x, boolean cast) {
+         // Maybe merge this code with Wrapper.convert/cast.
+         Number res = null;
+@@ -238,6 +244,27 @@
+         return res;
+     }
+ 
++    /**
++     * The JVM verifier allows boolean, byte, short, or char to widen to int.
++     * Support exactly this conversion, from a boxed value type Boolean,
++     * Byte, Short, Character, or Integer.
++     */
++    public static int widenSubword(Object x) {
++        if (x instanceof Integer)
++            return (int) x;
++        else if (x instanceof Boolean)
++            return fromBoolean((boolean) x);
++        else if (x instanceof Character)
++            return (char) x;
++        else if (x instanceof Short)
++            return (short) x;
++        else if (x instanceof Byte)
++            return (byte) x;
++        else
++            // Fail with a ClassCastException.
++            return (int) x;
++    }
++
+     /// Converting primitives to references
+ 
+     static Integer boxInteger(int x) {
 diff --git a/test/java/lang/invoke/MethodHandlesTest.java b/test/java/lang/invoke/MethodHandlesTest.java
 --- a/test/java/lang/invoke/MethodHandlesTest.java
 +++ b/test/java/lang/invoke/MethodHandlesTest.java