Beispiel #1
0
 static {
   try {
     MethodType idType = MethodType.genericMethodType(1);
     MethodType castType = idType.insertParameterTypes(0, Class.class);
     MethodType ignoreType = idType.changeReturnType(void.class);
     MethodType zeroObjectType = MethodType.genericMethodType(0);
     IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", idType);
     // CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
     CAST_REFERENCE = IMPL_LOOKUP.findStatic(THIS_CLASS, "castReference", castType);
     ZERO_OBJECT = IMPL_LOOKUP.findStatic(THIS_CLASS, "zeroObject", zeroObjectType);
     IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType);
     EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1));
     ARRAY_IDENTITY =
         IMPL_LOOKUP.findStatic(
             THIS_CLASS, "identity", MethodType.methodType(Object[].class, Object[].class));
     FILL_NEW_ARRAY =
         IMPL_LOOKUP.findStatic(
             THIS_CLASS,
             "fillNewArray",
             MethodType.methodType(Object[].class, Integer.class, Object[].class));
     FILL_NEW_TYPED_ARRAY =
         IMPL_LOOKUP.findStatic(
             THIS_CLASS,
             "fillNewTypedArray",
             MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class));
   } catch (NoSuchMethodException | IllegalAccessException ex) {
     throw newInternalError("uncaught exception", ex);
   }
 }
Beispiel #2
0
  public static MethodHandle identity(Wrapper wrap) {
    EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[1];
    MethodHandle mh = cache.get(wrap);
    if (mh != null) {
      return mh;
    }
    // slow path
    MethodType type = MethodType.methodType(wrap.primitiveType());
    if (wrap != Wrapper.VOID) type = type.appendParameterTypes(wrap.primitiveType());
    try {
      mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", type);
    } catch (ReflectiveOperationException ex) {
      mh = null;
    }
    if (mh == null && wrap == Wrapper.VOID) {
      mh = EMPTY; // #(){} : #()void
    }
    if (mh != null) {
      cache.put(wrap, mh);
      return mh;
    }

    if (mh != null) {
      cache.put(wrap, mh);
      return mh;
    }
    throw new IllegalArgumentException("cannot find identity for " + wrap);
  }
Beispiel #3
0
 /**
  * Return a method handle that takes the indicated number of typed arguments and returns an array
  * of them. The type argument is the array type.
  */
 public static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
   Class<?> elemType = arrayType.getComponentType();
   if (elemType == null) throw new IllegalArgumentException("not an array: " + arrayType);
   // FIXME: Need more special casing and caching here.
   if (nargs >= MAX_JVM_ARITY / 2 - 1) {
     int slots = nargs;
     final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1; // 1 for receiver MH
     if (arrayType == double[].class || arrayType == long[].class) slots *= 2;
     if (slots > MAX_ARRAY_SLOTS)
       throw new IllegalArgumentException(
           "too many arguments: " + arrayType.getSimpleName() + ", length " + nargs);
   }
   if (elemType == Object.class) return varargsArray(nargs);
   // other cases:  primitive arrays, subtypes of Object[]
   MethodHandle cache[] = TYPED_COLLECTORS.get(elemType);
   MethodHandle mh = nargs < cache.length ? cache[nargs] : null;
   if (mh != null) return mh;
   if (elemType.isPrimitive()) {
     MethodHandle builder = FILL_NEW_ARRAY;
     MethodHandle producer = buildArrayProducer(arrayType);
     mh = buildVarargsArray(builder, producer, nargs);
   } else {
     @SuppressWarnings("unchecked")
     Class<? extends Object[]> objArrayType = (Class<? extends Object[]>) arrayType;
     Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType);
     MethodHandle builder = FILL_NEW_TYPED_ARRAY.bindTo(example);
     MethodHandle producer = ARRAY_IDENTITY;
     mh = buildVarargsArray(builder, producer, nargs);
   }
   mh =
       mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)));
   assert (assertCorrectArity(mh, nargs));
   if (nargs < cache.length) cache[nargs] = mh;
   return mh;
 }
Beispiel #4
0
  public static MethodHandle convertPrimitive(Wrapper wsrc, Wrapper wdst) {
    EnumMap<Wrapper, MethodHandle> cache = CONVERT_PRIMITIVE_FUNCTIONS[wsrc.ordinal()];
    MethodHandle mh = cache.get(wdst);
    if (mh != null) {
      return mh;
    }
    // slow path
    Class<?> src = wsrc.primitiveType();
    Class<?> dst = wdst.primitiveType();
    MethodType type =
        src == void.class ? MethodType.methodType(dst) : MethodType.methodType(dst, src);
    if (wsrc == wdst) {
      mh = identity(src);
    } else if (wsrc == Wrapper.VOID) {
      mh = zeroConstantFunction(wdst);
    } else if (wdst == Wrapper.VOID) {
      mh = MethodHandles.dropArguments(EMPTY, 0, src); // Defer back to MethodHandles.
    } else if (wsrc == Wrapper.OBJECT) {
      mh = unboxCast(dst);
    } else if (wdst == Wrapper.OBJECT) {
      mh = box(src);
    } else {
      assert (src.isPrimitive() && dst.isPrimitive());
      try {
        mh =
            IMPL_LOOKUP.findStatic(
                THIS_CLASS, src.getSimpleName() + "To" + capitalize(dst.getSimpleName()), type);
      } catch (ReflectiveOperationException ex) {
        mh = null;
      }
    }
    if (mh != null) {
      assert (mh.type() == type) : mh;
      cache.put(wdst, mh);
      return mh;
    }

    throw new IllegalArgumentException(
        "cannot find primitive conversion function for "
            + src.getSimpleName()
            + " -> "
            + dst.getSimpleName());
  }
Beispiel #5
0
 static {
   try {
     // MAKE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeArray",
     // MethodType.methodType(Object[].class, Object[].class));
     COPY_AS_REFERENCE_ARRAY =
         IMPL_LOOKUP.findStatic(
             THIS_CLASS,
             "copyAsReferenceArray",
             MethodType.methodType(Object[].class, Class.class, Object[].class));
     COPY_AS_PRIMITIVE_ARRAY =
         IMPL_LOOKUP.findStatic(
             THIS_CLASS,
             "copyAsPrimitiveArray",
             MethodType.methodType(Object.class, Wrapper.class, Object[].class));
     MAKE_LIST =
         IMPL_LOOKUP.findStatic(
             THIS_CLASS, "makeList", MethodType.methodType(List.class, Object[].class));
   } catch (ReflectiveOperationException ex) {
     throw newInternalError("uncaught exception", ex);
   }
 }
Beispiel #6
0
  public static MethodHandle zeroConstantFunction(Wrapper wrap) {
    EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[0];
    MethodHandle mh = cache.get(wrap);
    if (mh != null) {
      return mh;
    }
    // slow path
    MethodType type = MethodType.methodType(wrap.primitiveType());
    switch (wrap) {
      case VOID:
        mh = EMPTY;
        break;
      case OBJECT:
      case INT:
      case LONG:
      case FLOAT:
      case DOUBLE:
        try {
          mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "zero" + wrap.wrapperSimpleName(), type);
        } catch (ReflectiveOperationException ex) {
          mh = null;
        }
        break;
    }
    if (mh != null) {
      cache.put(wrap, mh);
      return mh;
    }

    // use zeroInt and cast the result
    if (wrap.isSubwordOrInt() && wrap != Wrapper.INT) {
      mh = MethodHandles.explicitCastArguments(zeroConstantFunction(Wrapper.INT), type);
      cache.put(wrap, mh);
      return mh;
    }
    throw new IllegalArgumentException("cannot find zero constant for " + wrap);
  }
Beispiel #7
0
 private static MethodType boxType(Wrapper wrap) {
   // be exact, since return casts are hard to compose
   Class<?> boxType = wrap.wrapperType();
   return MethodType.methodType(boxType, wrap.primitiveType());
 }
Beispiel #8
0
 private static MethodType unboxType(Wrapper wrap) {
   return MethodType.methodType(wrap.primitiveType(), Object.class, boolean.class);
 }