// 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);
  }
예제 #2
0
 // 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);
     }
   }
 }
예제 #3
0
 /**
  * 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();
 }
예제 #4
0
파일: Bootstrap.java 프로젝트: godfat/jruby
  public static CallSite ivar(Lookup lookup, String name, MethodType type) throws Throwable {
    String[] names = name.split(":");
    String operation = names[0];
    String varName = names[1];
    VariableSite site = new VariableSite(type, varName, "noname", 0);
    MethodHandle handle;

    handle =
        lookup.findStatic(
            Bootstrap.class, operation, type.insertParameterTypes(0, VariableSite.class));

    handle = handle.bindTo(site);
    site.setTarget(handle.asType(site.type()));

    return site;
  }
예제 #5
0
 /**
  * Return the actual type under which this method or constructor must be invoked. For non-static
  * methods or constructors, this is the type with a leading parameter, a reference to declaring
  * class. For static methods, it is the same as the declared type.
  */
 public MethodType getInvocationType() {
   MethodType itype = getMethodType();
   if (!isStatic()) itype = itype.insertParameterTypes(0, clazz);
   return itype;
 }
예제 #6
0
 private MethodHandle makePostDispatchInvoker() {
   // Take (MH'; MT, MH; A...) and run MH'(MT, MH; A...).
   MethodType invokerType = erasedCallerType.insertParameterTypes(0, EXTRA_ARGS);
   return invokerType.invokers().exactInvoker();
 }
예제 #7
0
  private static LambdaForm makePreparedFieldLambdaForm(
      byte formOp, boolean isVolatile, int ftypeKind) {
    boolean isGetter = (formOp & 1) == (AF_GETFIELD & 1);
    boolean isStatic = (formOp >= AF_GETSTATIC);
    boolean needsInit = (formOp >= AF_GETSTATIC_INIT);
    boolean needsCast = (ftypeKind == FT_CHECKED_REF);
    Wrapper fw = (needsCast ? Wrapper.OBJECT : ALL_WRAPPERS[ftypeKind]);
    Class<?> ft = fw.primitiveType();
    assert (ftypeKind(needsCast ? String.class : ft) == ftypeKind);

    // getObject, putIntVolatile, etc.
    StringBuilder nameBuilder = new StringBuilder();
    if (isGetter) {
      nameBuilder.append("get");
    } else {
      nameBuilder.append("put");
    }
    nameBuilder.append(fw.primitiveSimpleName());
    nameBuilder.setCharAt(3, Character.toUpperCase(nameBuilder.charAt(3)));
    if (isVolatile) {
      nameBuilder.append("Volatile");
    }

    MethodType linkerType;
    if (isGetter) linkerType = MethodType.methodType(ft, Object.class, long.class);
    else linkerType = MethodType.methodType(void.class, Object.class, long.class, ft);
    MemberName linker =
        new MemberName(Unsafe.class, nameBuilder.toString(), linkerType, REF_invokeVirtual);
    try {
      linker =
          IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, NoSuchMethodException.class);
    } catch (ReflectiveOperationException ex) {
      throw newInternalError(ex);
    }

    // What is the external type of the lambda form?
    MethodType mtype;
    if (isGetter) mtype = MethodType.methodType(ft);
    else mtype = MethodType.methodType(void.class, ft);
    mtype = mtype.basicType(); // erase short to int, etc.
    if (!isStatic) mtype = mtype.insertParameterTypes(0, Object.class);
    final int DMH_THIS = 0;
    final int ARG_BASE = 1;
    final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
    // if this is for non-static access, the base pointer is stored at this index:
    final int OBJ_BASE = isStatic ? -1 : ARG_BASE;
    // if this is for write access, the value to be written is stored at this index:
    final int SET_VALUE = isGetter ? -1 : ARG_LIMIT - 1;
    int nameCursor = ARG_LIMIT;
    final int F_HOLDER = (isStatic ? nameCursor++ : -1); // static base if any
    final int F_OFFSET = nameCursor++; // Either static offset or field offset.
    final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
    final int INIT_BAR = (needsInit ? nameCursor++ : -1);
    final int PRE_CAST = (needsCast && !isGetter ? nameCursor++ : -1);
    final int LINKER_CALL = nameCursor++;
    final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1);
    final int RESULT = nameCursor - 1; // either the call or the cast
    Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
    if (needsInit) names[INIT_BAR] = new Name(NF_ensureInitialized, names[DMH_THIS]);
    if (needsCast && !isGetter)
      names[PRE_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[SET_VALUE]);
    Object[] outArgs = new Object[1 + linkerType.parameterCount()];
    assert (outArgs.length == (isGetter ? 3 : 4));
    outArgs[0] = UNSAFE;
    if (isStatic) {
      outArgs[1] = names[F_HOLDER] = new Name(NF_staticBase, names[DMH_THIS]);
      outArgs[2] = names[F_OFFSET] = new Name(NF_staticOffset, names[DMH_THIS]);
    } else {
      outArgs[1] = names[OBJ_CHECK] = new Name(NF_checkBase, names[OBJ_BASE]);
      outArgs[2] = names[F_OFFSET] = new Name(NF_fieldOffset, names[DMH_THIS]);
    }
    if (!isGetter) {
      outArgs[3] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
    }
    for (Object a : outArgs) assert (a != null);
    names[LINKER_CALL] = new Name(linker, outArgs);
    if (needsCast && isGetter)
      names[POST_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[LINKER_CALL]);
    for (Name n : names) assert (n != null);
    // add some detail to the lambdaForm debugname,
    // significant only for debugging
    if (isStatic) {
      nameBuilder.append("Static");
    } else {
      nameBuilder.append("Field");
    }
    if (needsCast) nameBuilder.append("Cast");
    if (needsInit) nameBuilder.append("Init");
    return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT);
  }
예제 #8
0
  static LambdaForm makePreparedLambdaForm(MethodType mtype, int which) {
    boolean needsInit = (which == LF_INVSTATIC_INIT);
    boolean doesAlloc = (which == LF_NEWINVSPECIAL);
    String linkerName;
    LambdaForm.Kind kind;
    switch (which) {
      case LF_INVVIRTUAL:
        linkerName = "linkToVirtual";
        kind = DIRECT_INVOKE_VIRTUAL;
        break;
      case LF_INVSTATIC:
        linkerName = "linkToStatic";
        kind = DIRECT_INVOKE_STATIC;
        break;
      case LF_INVSTATIC_INIT:
        linkerName = "linkToStatic";
        kind = DIRECT_INVOKE_STATIC_INIT;
        break;
      case LF_INVSPECIAL:
        linkerName = "linkToSpecial";
        kind = DIRECT_INVOKE_SPECIAL;
        break;
      case LF_INVINTERFACE:
        linkerName = "linkToInterface";
        kind = DIRECT_INVOKE_INTERFACE;
        break;
      case LF_NEWINVSPECIAL:
        linkerName = "linkToSpecial";
        kind = DIRECT_NEW_INVOKE_SPECIAL;
        break;
      default:
        throw new InternalError("which=" + which);
    }

    MethodType mtypeWithArg = mtype.appendParameterTypes(MemberName.class);
    if (doesAlloc)
      mtypeWithArg =
          mtypeWithArg
              .insertParameterTypes(0, Object.class) // insert newly allocated obj
              .changeReturnType(void.class); // <init> returns void
    MemberName linker =
        new MemberName(MethodHandle.class, linkerName, mtypeWithArg, REF_invokeStatic);
    try {
      linker =
          IMPL_NAMES.resolveOrFail(REF_invokeStatic, linker, null, NoSuchMethodException.class);
    } catch (ReflectiveOperationException ex) {
      throw newInternalError(ex);
    }
    final int DMH_THIS = 0;
    final int ARG_BASE = 1;
    final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
    int nameCursor = ARG_LIMIT;
    final int NEW_OBJ = (doesAlloc ? nameCursor++ : -1);
    final int GET_MEMBER = nameCursor++;
    final int LINKER_CALL = nameCursor++;
    Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
    assert (names.length == nameCursor);
    if (doesAlloc) {
      // names = { argx,y,z,... new C, init method }
      names[NEW_OBJ] = new Name(NF_allocateInstance, names[DMH_THIS]);
      names[GET_MEMBER] = new Name(NF_constructorMethod, names[DMH_THIS]);
    } else if (needsInit) {
      names[GET_MEMBER] = new Name(NF_internalMemberNameEnsureInit, names[DMH_THIS]);
    } else {
      names[GET_MEMBER] = new Name(NF_internalMemberName, names[DMH_THIS]);
    }
    assert (findDirectMethodHandle(names[GET_MEMBER]) == names[DMH_THIS]);
    Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, GET_MEMBER + 1, Object[].class);
    assert (outArgs[outArgs.length - 1] == names[GET_MEMBER]); // look, shifted args!
    int result = LAST_RESULT;
    if (doesAlloc) {
      assert (outArgs[outArgs.length - 2] == names[NEW_OBJ]); // got to move this one
      System.arraycopy(outArgs, 0, outArgs, 1, outArgs.length - 2);
      outArgs[0] = names[NEW_OBJ];
      result = NEW_OBJ;
    }
    names[LINKER_CALL] = new Name(linker, outArgs);
    String lambdaName = kind.defaultLambdaName + "_" + shortenSignature(basicTypeSignature(mtype));
    LambdaForm lform = new LambdaForm(lambdaName, ARG_LIMIT, names, result, kind);

    // This is a tricky bit of code.  Don't send it through the LF interpreter.
    lform.compileToBytecode();
    return lform;
  }