Beispiel #1
0
 /**
  * Sole factory method to find or create an interned method type.
  *
  * @param rtype desired return type
  * @param ptypes desired parameter types
  * @param trusted whether the ptypes can be used without cloning
  * @return the unique method type of the desired structure
  */
 /*trusted*/ static MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
   if (ptypes.length == 0) {
     ptypes = NO_PTYPES;
     trusted = true;
   }
   MethodType mt1 = new MethodType(rtype, ptypes);
   MethodType mt0;
   synchronized (internTable) {
     mt0 = internTable.get(mt1);
     if (mt0 != null) return mt0;
   }
   if (!trusted)
     // defensively copy the array passed in by the user
     mt1 = new MethodType(rtype, ptypes.clone());
   // promote the object to the Real Thing, and reprobe
   MethodTypeForm form = MethodTypeForm.findForm(mt1);
   mt1.form = form;
   if (form.erasedType == mt1) {
     // This is a principal (erased) type; show it to the JVM.
     MethodHandleNatives.init(mt1);
   }
   synchronized (internTable) {
     mt0 = internTable.get(mt1);
     if (mt0 != null) return mt0;
     internTable.put(mt1, mt1);
   }
   return mt1;
 }
  private TestCase(Class<T> rtype, Function<Object, T> cast, ThrowMode throwMode, Throwable thrown)
      throws NoSuchMethodException, IllegalAccessException {
    this.cast = cast;
    filter =
        MethodHandles.lookup()
            .findVirtual(Function.class, "apply", MethodType.methodType(Object.class, Object.class))
            .bindTo(cast);
    this.rtype = rtype;
    this.throwMode = throwMode;
    this.throwableClass = thrown.getClass();
    switch (throwMode) {
      case NOTHING:
        this.thrown = null;
        break;
      case ADAPTER:
      case UNCAUGHT:
        this.thrown = new Error("do not catch this");
        break;
      default:
        this.thrown = thrown;
    }

    MethodHandle throwOrReturn = THROW_OR_RETURN;
    if (throwMode == ThrowMode.ADAPTER) {
      MethodHandle fakeIdentity = FAKE_IDENTITY.bindTo(this);
      for (int i = 0; i < 10; ++i) {
        throwOrReturn = MethodHandles.filterReturnValue(throwOrReturn, fakeIdentity);
      }
    }
    thrower = throwOrReturn.asType(MethodType.genericMethodType(2));
  }
Beispiel #3
0
  static MethodHandle getResultConversionHandle(NativeType nativeType, Class from, Class to) {
    try {
      switch (nativeType) {
        case FLOAT:
          return MethodHandles.explicitCastArguments(
              LOOKUP.findStatic(
                  Float.class, "intBitsToFloat", MethodType.methodType(float.class, int.class)),
              MethodType.methodType(to, from));

        case DOUBLE:
          return LOOKUP
              .findStatic(
                  Double.class, "longBitsToDouble", MethodType.methodType(double.class, long.class))
              .asType(MethodType.methodType(to, from));

        case VOID:
          return null;

        default:
          return getIntegerConversionHandle(nativeType, from, to);
      }

    } catch (NoSuchMethodException | IllegalAccessException e) {
      throw new IllegalArgumentException(e);
    }
  }
Beispiel #4
0
  static MethodHandle getIntegerConversionHandle(NativeType nativeType, Class from, Class to)
      throws NoSuchMethodException, IllegalAccessException {
    switch (nativeType) {
      case SCHAR:
      case UCHAR:
      case SSHORT:
      case USHORT:
      case SINT:
      case UINT:
      case SLONG:
      case ULONG:
      case SLONG_LONG:
      case ULONG_LONG:
      case POINTER:
        if (nativeType.size() <= 4) {
          Class nativeIntType = long.class == to ? long.class : int.class;
          String conversionHelper =
              (nativeType.isUnsigned() ? "u" : "s") + Integer.toString(nativeType.size() * 8);
          MethodHandle mh =
              LOOKUP.findStatic(
                  AsmRuntime.class,
                  conversionHelper,
                  MethodType.methodType(nativeIntType, nativeIntType));
          return MethodHandles.explicitCastArguments(mh, MethodType.methodType(to, from));
        }

        return null;

      default:
        return null;
    }
  }
Beispiel #5
0
 /** Return the declared type of this member, which must be a method or constructor. */
 public MethodType getMethodType() {
   if (type == null) {
     expandFromVM();
     if (type == null) return null;
   }
   if (!isInvocable()) throw newIllegalArgumentException("not invocable, no method type");
   if (type instanceof MethodType) {
     return (MethodType) type;
   }
   if (type instanceof String) {
     String sig = (String) type;
     MethodType res = MethodType.fromMethodDescriptorString(sig, getClassLoader());
     this.type = res;
     return res;
   }
   if (type instanceof Object[]) {
     Object[] typeInfo = (Object[]) type;
     Class<?>[] ptypes = (Class<?>[]) typeInfo[1];
     Class<?> rtype = (Class<?>) typeInfo[0];
     MethodType res = MethodType.methodType(rtype, ptypes);
     this.type = res;
     return res;
   }
   throw new InternalError("bad method type " + type);
 }
Beispiel #6
0
  static MethodHandle getParameterConversionHandle(NativeType nativeType, Class from, Class to) {
    try {
      switch (nativeType) {
        case FLOAT:
          return LOOKUP
              .findStatic(
                  Float.class, "floatToRawIntBits", MethodType.methodType(int.class, float.class))
              .asType(MethodType.methodType(to, from));

        case DOUBLE:
          return LOOKUP
              .findStatic(
                  Double.class,
                  "doubleToRawLongBits",
                  MethodType.methodType(long.class, double.class))
              .asType(MethodType.methodType(to, from));

        default:
          return getIntegerConversionHandle(nativeType, from, to);
      }

    } catch (NoSuchMethodException | IllegalAccessException e) {
      throw new IllegalArgumentException(e);
    }
  }
 private MethodHandle getMethodHandle(Method method) {
   MethodHandle methodHandle;
   try {
     methodHandle = lookup().unreflect(method);
   } catch (IllegalAccessException e) {
     throw new PrestoException(FUNCTION_IMPLEMENTATION_ERROR, e);
   }
   if (!isStatic(method.getModifiers())) {
     // Re-arrange the parameters, so that the "this" parameter is after the meta parameters
     int[] permutedIndices = new int[methodHandle.type().parameterCount()];
     permutedIndices[0] = dependencies.size();
     MethodType newType =
         methodHandle
             .type()
             .changeParameterType(dependencies.size(), methodHandle.type().parameterType(0));
     for (int i = 0; i < dependencies.size(); i++) {
       permutedIndices[i + 1] = i;
       newType = newType.changeParameterType(i, methodHandle.type().parameterType(i + 1));
     }
     for (int i = dependencies.size() + 1; i < permutedIndices.length; i++) {
       permutedIndices[i] = i;
     }
     methodHandle = permuteArguments(methodHandle, newType, permutedIndices);
   }
   return methodHandle;
 }
 // Factory methods:
 static DirectMethodHandle make(byte refKind, Class<?> receiver, MemberName member) {
   MethodType mtype = member.getMethodOrFieldType();
   if (!member.isStatic()) {
     if (!member.getDeclaringClass().isAssignableFrom(receiver) || member.isConstructor())
       throw new InternalError(member.toString());
     mtype = mtype.insertParameterTypes(0, receiver);
   }
   if (!member.isField()) {
     if (refKind == REF_invokeSpecial) {
       member = member.asSpecial();
       LambdaForm lform = preparedLambdaForm(member);
       return new Special(mtype, lform, member);
     } else {
       LambdaForm lform = preparedLambdaForm(member);
       return new DirectMethodHandle(mtype, lform, member);
     }
   } else {
     LambdaForm lform = preparedFieldLambdaForm(member);
     if (member.isStatic()) {
       long offset = MethodHandleNatives.staticFieldOffset(member);
       Object base = MethodHandleNatives.staticFieldBase(member);
       return new StaticAccessor(mtype, lform, member, base, offset);
     } else {
       long offset = MethodHandleNatives.objectFieldOffset(member);
       assert (offset == (int) offset);
       return new Accessor(mtype, lform, member, (int) offset);
     }
   }
 }
 public CatchExceptionTest(
     TestCase testCase, final boolean isVararg, final int argsCount, final int catchDrops) {
   this.testCase = testCase;
   this.dropped = catchDrops;
   if (Helper.IS_VERBOSE) {
     System.out.printf(
         "CatchException::CatchException(%s, isVararg=%b " + "argsCount=%d catchDrops=%d)%n",
         testCase, isVararg, argsCount, catchDrops);
   }
   MethodHandle thrower = testCase.thrower;
   int throwerLen = thrower.type().parameterCount();
   List<Class<?>> classes;
   int extra = Math.max(0, argsCount - throwerLen);
   classes = getThrowerParams(isVararg, extra);
   this.argsCount = throwerLen + classes.size();
   thrower = Helper.addTrailingArgs(thrower, this.argsCount, classes);
   if (isVararg && argsCount > throwerLen) {
     MethodType mt = thrower.type();
     Class<?> lastParam = mt.parameterType(mt.parameterCount() - 1);
     thrower = thrower.asVarargsCollector(lastParam);
   }
   this.thrower = thrower;
   this.dropped = Math.min(this.argsCount, catchDrops);
   catcher = testCase.getCatcher(getCatcherParams());
   nargs = Math.max(2, this.argsCount);
 }
 private boolean returnConversionNeeded(MethodType callerType, MethodHandle target) {
   Class<?> needType = callerType.returnType();
   if (needType == erasedCallerType.returnType())
     return false; // no conversions possible, since must be primitive or Object
   Class<?> haveType = target.type().returnType();
   if (VerifyType.isNullConversion(haveType, needType) && !needType.isInterface()) return false;
   return true;
 }
 /**
  * Compute and cache information for this adapter, so that it can call out to targets of the
  * erasure-family of the given erased type.
  */
 /*non-public*/ InvokeGeneric(MethodType erasedCallerType) throws ReflectiveOperationException {
   assert (erasedCallerType.equals(erasedCallerType.erase()));
   this.erasedCallerType = erasedCallerType;
   this.initialInvoker = makeInitialInvoker();
   assert initialInvoker
           .type()
           .equals(erasedCallerType.insertParameterTypes(0, MethodType.class, MethodHandle.class))
       : initialInvoker.type();
 }
Beispiel #12
0
 /*non-public*/
 boolean isConvertibleTo(MethodType newType) {
   if (!canConvert(returnType(), newType.returnType())) return false;
   int argc = parameterCount();
   if (argc != newType.parameterCount()) return false;
   for (int i = 0; i < argc; i++) {
     if (!canConvert(newType.parameterType(i), parameterType(i))) return false;
   }
   return true;
 }
 private MethodHandle addReturnConversion(MethodHandle finisher, Class<?> type) {
   // FIXME: This is slow because it creates a closure node on every call that requires a return
   // cast.
   MethodType finisherType = finisher.type();
   MethodHandle caster = ValueConversions.identity(type);
   caster = caster.asType(caster.type().changeParameterType(0, finisherType.returnType()));
   finisher = MethodHandles.filterReturnValue(finisher, caster);
   return finisher.asType(finisherType);
 }
Beispiel #14
0
 private static MethodType unwrapWithNoPrims(MethodType wt) {
   assert (!wt.hasPrimitives());
   MethodType uwt = wt.wrapAlt;
   if (uwt == null) {
     // fill in lazily
     uwt = MethodTypeForm.canonicalize(wt, MethodTypeForm.UNWRAP, MethodTypeForm.UNWRAP);
     if (uwt == null) uwt = wt; // type has no wrappers or prims at all
     wt.wrapAlt = uwt;
   }
   return uwt;
 }
Beispiel #15
0
 private static MethodType wrapWithPrims(MethodType pt) {
   assert (pt.hasPrimitives());
   MethodType wt = pt.wrapAlt;
   if (wt == null) {
     // fill in lazily
     wt = MethodTypeForm.canonicalize(pt, MethodTypeForm.WRAP, MethodTypeForm.WRAP);
     assert (wt != null);
     pt.wrapAlt = wt;
   }
   return wt;
 }
  public static void main(String[] args) throws Throwable {
    Object x, y;
    String s;
    int i;
    MethodType mt;
    MethodHandle mh;
    MethodHandles.Lookup lookup = MethodHandles.lookup();
    // mt is (char,char)String
    mt = MethodType.methodType(String.class, char.class, char.class);
    mh = lookup.findVirtual(String.class, "replace", mt);
    s = (String) mh.invokeExact("daddy", 'd', 'n');
    System.out.println("Result: " + s);
    // invokeExact(Ljava/lang/String;CC)Ljava/lang/String;

    // weakly typed invocation (using MHs.invoke)
    s = (String) mh.invokeWithArguments("sappy", 'p', 'v');
    System.out.println("Result: " + s);
    // mt is (Object[])List

    mt = MethodType.methodType(java.util.List.class, Object[].class);
    mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
    assert (mh.isVarargsCollector());
    x = mh.invoke("one", "two");
    // ArrayList
    System.out.println("x: " + x + " type: " + x.getClass().getCanonicalName());

    // invoke(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
    // assertEquals(x, java.util.Arrays.asList("one","two"));

    // mt is (Object,Object,Object)Object
    mt = MethodType.genericMethodType(3);
    mh = mh.asType(mt);
    x = mh.invokeExact((Object) 1, (Object) 2, (Object) 3);
    // invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
    // 1,2,3
    System.out.println("x: " + x + " type: " + x.getClass().getCanonicalName());

    // assertEquals(x, java.util.Arrays.asList(1,2,3));
    // mt is ()int
    mt = MethodType.methodType(int.class);
    mh = lookup.findVirtual(java.util.List.class, "size", mt);
    i = (int) mh.invokeExact(java.util.Arrays.asList(1, 2, 3));
    // invokeExact(Ljava/util/List;)I
    assert (i == 3);

    mt = MethodType.methodType(void.class, String.class);
    mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt);
    mh.invokeExact(System.out, "Hello, world.");
    // invokeExact(Ljava/io/PrintStream;Ljava/lang/String;)V
  }
 /**
  * Return a method handle to invoke on the callerType, target, and remaining arguments. The method
  * handle must finish the call. This is the first look at the caller type and target.
  */
 private MethodHandle dispatch(MethodType callerType, MethodHandle target) {
   MethodType targetType = target.type();
   if (USE_AS_TYPE_PATH || target.isVarargsCollector()) {
     MethodHandle newTarget = target.asType(callerType);
     targetType = callerType;
     Invokers invokers = targetType.invokers();
     MethodHandle invoker = invokers.erasedInvokerWithDrops;
     if (invoker == null) {
       invokers.erasedInvokerWithDrops = invoker = dropDispatchArguments(invokers.erasedInvoker());
     }
     return invoker.bindTo(newTarget);
   }
   throw new RuntimeException("NYI");
 }
 public static int add5(int a) throws Throwable {
   MethodHandles.Lookup lookup = MethodHandles.lookup();
   MethodType type = MethodType.methodType(int.class, int.class, int.class);
   MethodHandle mhAdd = lookup.findStatic(FunctionProgramming.class, "add", type);
   MethodHandle mh = curry(mhAdd, 5);
   return (int) mh.invoke(a);
 }
 private MethodHandle dispatcher(String dispatchName) throws ReflectiveOperationException {
   return lookup()
       .bind(
           this,
           dispatchName,
           MethodType.methodType(MethodHandle.class, MethodType.class, MethodHandle.class));
 }
Beispiel #20
0
 @Override
 public MethodHandle methodHandle(MethodType inputType) throws Exception {
   return MethodHandles.lookup()
       .findVirtual(
           ShadowFilter.class, "filter", MethodType.methodType(JSObject.class, Object.class))
       .bindTo(this);
 }
Beispiel #21
0
/** @author chengfu */
public class ToUpperCaseGenerator {

  private static final MethodHandle BSM =
      new MethodHandle(
          MH_INVOKESTATIC,
          ToUpperCase.class.getName().replace('.', '/'),
          "bootstrap",
          MethodType.methodType(
                  CallSite.class, Lookup.class, String.class, MethodType.class, String.class)
              .toMethodDescriptorString());

  /** @param args the command line arguments */
  public static void main(String[] args) throws IOException {
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
    cw.visit(V1_7, ACC_PUBLIC | ACC_SUPER, "ToUpperCaseMain", null, "java/lang/Object", null);

    MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
    mv.visitCode();
    mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
    mv.visitInvokeDynamicInsn("toUpperCase", "()Ljava/lang/String;", BSM, "Hello");
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");

    mv.visitInsn(RETURN);
    mv.visitMaxs(0, 0);
    mv.visitEnd();

    cw.visitEnd();

    Files.write(Paths.get("build", "classes", "ToUpperCaseMain.class"), cw.toByteArray());
  }
}
Beispiel #22
0
 void thinking() {
   try {
     MethodType mt = MethodType.methodType(void.class);
     MethodHandle mh = lookup().findSpecial(GrandFather.class, "thinking", mt, getClass());
     mh.invoke(this);
   } catch (Throwable e) {
   }
 }
  // warning ! stolen code ahead ! (http://code.google.com/p/jsr292-cookbook)
  public static CallSite myBSM(Lookup lookup, String name, MethodType type, Class<?> staticType)
      throws ReflectiveOperationException {
    MethodHandle target = lookup.findStatic(staticType, name, type);

    HashMap<String, HashMap<Object, Object>> cacheTable = cacheTables.get(staticType);

    String selector = name + type.toMethodDescriptorString();
    HashMap<Object, Object> cache = cacheTable.get(selector);

    if (cache == null) {
      cache = new HashMap<Object, Object>();
      cacheTable.put(selector, cache);
    }

    MethodHandle identity = MethodHandles.identity(type.returnType());
    identity = identity.asType(identity.type().changeParameterType(0, Object.class));
    identity = MethodHandles.dropArguments(identity, 1, type.parameterType(0));

    MethodHandle update = UPDATE.bindTo(cache);
    update = update.asType(type.insertParameterTypes(0, type.returnType()));

    MethodHandle fallback = MethodHandles.foldArguments(update, target);
    fallback = MethodHandles.dropArguments(fallback, 0, Object.class);

    MethodHandle combiner = MethodHandles.guardWithTest(NOT_NULL, identity, fallback);

    MethodHandle cacheQuerier = MAP_GET.bindTo(cache);
    cacheQuerier = cacheQuerier.asType(MethodType.methodType(Object.class, type.parameterType(0)));

    MethodHandle memoize = MethodHandles.foldArguments(combiner, cacheQuerier);
    return new ConstantCallSite(memoize);
  }
Beispiel #24
0
 private static MethodHandle virtualHandle(
     final String name, final Class<?> rtype, final Class<?>... ptypes) {
   try {
     return MethodHandles.lookup()
         .findVirtual(Prototype.class, name, MethodType.methodType(rtype, ptypes));
   } catch (final ReflectiveOperationException e) {
     throw new IllegalStateException(e);
   }
 }
Beispiel #25
0
 /**
  * Adapts the return type of the method handle with {@code explicitCastArguments} when it is an
  * unboxing conversion. This will ensure that nulls are unwrapped to false or 0.
  *
  * @param target the target method handle
  * @param newType the desired new type. Note that this method does not adapt the method handle
  *     completely to the new type, it only adapts the return type; this is allowed as per {@link
  *     DynamicLinkerFactory#setAutoConversionStrategy(MethodTypeConversionStrategy)}, which is
  *     what this method is used for.
  * @return the method handle with adapted return type, if it required an unboxing conversion.
  */
 private static MethodHandle unboxReturnType(final MethodHandle target, final MethodType newType) {
   final MethodType targetType = target.type();
   final Class<?> oldReturnType = targetType.returnType();
   final Class<?> newReturnType = newType.returnType();
   if (TypeUtilities.isWrapperType(oldReturnType)) {
     if (newReturnType.isPrimitive()) {
       // The contract of setAutoConversionStrategy is such that the difference between newType and
       // targetType
       // can only be JLS method invocation conversions.
       assert TypeUtilities.isMethodInvocationConvertible(oldReturnType, newReturnType);
       return MethodHandles.explicitCastArguments(
           target, targetType.changeReturnType(newReturnType));
     }
   } else if (oldReturnType == void.class && newReturnType == Object.class) {
     return MethodHandles.filterReturnValue(target, VOID_TO_OBJECT);
   }
   return target;
 }
  /**
   * Given a method handle and an expected return type, perform return value filtering according to
   * the optimistic type coercion rules
   *
   * @param mh method handle
   * @param expectedReturnType expected return type
   * @param programPoint program point
   * @return filtered method
   */
  public static MethodHandle filterOptimisticReturnValue(
      final MethodHandle mh, final Class<?> expectedReturnType, final int programPoint) {
    if (!isValid(programPoint)) {
      return mh;
    }

    final MethodType type = mh.type();
    final Class<?> actualReturnType = type.returnType();
    if (TypeUtilities.isConvertibleWithoutLoss(actualReturnType, expectedReturnType)) {
      return mh;
    }

    final MethodHandle guard = getOptimisticTypeGuard(expectedReturnType, actualReturnType);
    return guard == null
        ? mh
        : MH.filterReturnValue(
            mh, MH.insertArguments(guard, guard.type().parameterCount() - 1, programPoint));
  }
Beispiel #27
0
    public static Object call(InterfaceCallSite ics, Object o, Object[] args) throws Throwable {
      final Class<?> receiverClass = o.getClass();

      // drop the 'this' (locals[0]) parameter from the signature
      // since that is implicit in a virtual method
      MethodHandle handle =
          lookup.findVirtual(
              receiverClass, ics.methodName, ics.methodType.dropParameterTypes(0, 1));

      // cache receiver type as long as the CallSite
      // is not megamorphic
      if (ics.cacheDepth != -1) {
        // figure out what kind of an upgrade we're doing

        if (ics.cacheDepth < MAX_CACHE_DEPTH) {
          // upgrade, from either uninitialized or mono/polymorphic,
          // add class to polymorphic tree
          MethodHandle test =
              lookup
                  .findVirtual(
                      Class.class, "isInstance", MethodType.methodType(boolean.class, Object.class))
                  .bindTo(receiverClass);

          ics.cacheDepth++;

          // the new receiver type becomes the root
          // of the cache tree
          ics.setTarget(
              MethodHandles.guardWithTest(
                  test, handle.asType(ics.getTarget().type()), ics.getTarget()));
        } else {
          // call site has become megamorphic.
          // don't use a cache tree anymore, set cacheDepth
          // to indicate megamorphic call site
          ics.setTarget(ics.rootHandle);
          ics.cacheDepth = -1;

          // TODO: since rootHandle points to this method,
          //       every megmorphic invocation pays for
          //       the branch above with ics.cacheDepth != -1
          //       really another static method needs to be
          //       created that just does the invocation
          //       without the upgrade logic
        }
      }

      // cache is now setup for next invocation, but we still need
      // to handle this invocation, so spread arguments array
      // over resolved receiver method and invoke

      handle =
          MethodHandles.insertArguments(handle, 0, o)
              .asSpreader(Object[].class, ics.methodType.parameterCount() - 1);

      return handle.invoke(args);
    }
Beispiel #28
0
 /**
  * Return the declared type of this member, which must be a field or type. If it is a type member,
  * that type itself is returned.
  */
 public Class<?> getFieldType() {
   if (type == null) {
     expandFromVM();
     if (type == null) return null;
   }
   if (isInvocable())
     throw newIllegalArgumentException("not a field or nested class, no simple type");
   if (type instanceof Class<?>) {
     return (Class<?>) type;
   }
   if (type instanceof String) {
     String sig = (String) type;
     MethodType mtype = MethodType.fromMethodDescriptorString("()" + sig, getClassLoader());
     Class<?> res = mtype.returnType();
     this.type = res;
     return res;
   }
   throw new InternalError("bad field type " + type);
 }
  static {
    try {
      MethodHandles.Lookup lookup = MethodHandles.lookup();
      THROW_OR_RETURN =
          lookup.findStatic(
              TestCase.class,
              "throwOrReturn",
              MethodType.methodType(Object.class, Object.class, Throwable.class));
      CATCHER =
          lookup.findStatic(
              TestCase.class, "catcher", MethodType.methodType(Object.class, Object.class));
      FAKE_IDENTITY =
          lookup.findVirtual(
              TestCase.class, "fakeIdentity", MethodType.methodType(Object.class, Object.class));

    } catch (NoSuchMethodException | IllegalAccessException e) {
      throw new Error(e);
    }
    PartialConstructor[] constructors = {
      create(Object.class, Object.class::cast),
      create(String.class, Objects::toString),
      create(int[].class, x -> new int[] {Objects.hashCode(x)}),
      create(long.class, x -> Objects.hashCode(x) & (-1L >>> 32)),
      create(void.class, TestCase::noop)
    };
    Throwable[] throwables = {
      new ClassCastException("testing"),
      new java.io.IOException("testing"),
      new LinkageError("testing")
    };
    List<Supplier<TestCase>> list =
        new ArrayList<>(constructors.length * throwables.length * ThrowMode.values().length);
    //noinspection unchecked
    for (PartialConstructor f : constructors) {
      for (ThrowMode mode : ThrowMode.values()) {
        for (Throwable t : throwables) {
          list.add(f.apply(mode, t));
        }
      }
    }
    CONSTRUCTORS = Collections.unmodifiableList(list);
  }
  static {
    Lookup lookup = MethodHandles.lookup();
    try {
      NOT_NULL =
          lookup.findStatic(
              SpeedRecurenceWithIndyUsingBigInteger.class,
              "notNull",
              MethodType.methodType(boolean.class, Object.class));
      MAP_GET =
          lookup.findVirtual(
              HashMap.class, "get", MethodType.methodType(Object.class, Object.class));
      UPDATE =
          lookup.findStatic(
              SpeedRecurenceWithIndyUsingBigInteger.class,
              "update",
              MethodType.methodType(Object.class, HashMap.class, Object.class, Object.class));

    } catch (ReflectiveOperationException e) {
      throw (AssertionError) new AssertionError().initCause(e);
    }
  }