/**
     * Emit an invoke for the given name.
     */
    void emitInvoke(Name name)
    {
        //assert(!isLinkerMethodInvoke(name));  // should use the static path for these
        if (true)
        {
            // push receiver
            MethodHandle target = name.function._resolvedHandle();
            //assert(target != null) : name.exprString();
            //mv.visitLdcInsn(constantPlaceholder(target));
            EmitConstant(target);
            emitReferenceCast(CoreClasses.java.lang.invoke.MethodHandle.Wrapper.ClassObject, target);
        }
        else
        {
            // load receiver
            //emitAloadInsn(0);
            //emitReferenceCast(MethodHandle.class, null);
            //mv.visitFieldInsn(Opcodes.GETFIELD, MH, "form", LF_SIG);
            //mv.visitFieldInsn(Opcodes.GETFIELD, LF, "names", LFN_SIG);
            // TODO more to come
        }

        // push arguments
        emitPushArguments(name);

        // invocation
        MethodType type = name.function.methodType();

        //mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", type.basicType().toMethodDescriptorString(), false);
        EmitInvokeBasic(type.basicType());
    }
Esempio n. 2
0
    internal static Type GetMemberWrapperDelegateType(MethodType type)
    {
#if FIRST_PASS
        return(null);
#else
        return(GetDelegateTypeForInvokeExact(type.basicType()));
#endif
    }
    private NativeInvokerBytecodeGenerator(LambdaForm lambdaForm, MethodType invokerType)
    {
        if (invokerType != invokerType.basicType())
        {
            throw new BailoutException(Bailout.NotBasicType, invokerType);
        }
        this.lambdaForm   = lambdaForm;
        this.invokerType  = invokerType;
        this.delegateType = MethodHandleUtil.GetMemberWrapperDelegateType(invokerType);
        MethodInfo mi = MethodHandleUtil.GetDelegateInvokeMethod(delegateType);

        Type[] paramTypes = MethodHandleUtil.GetParameterTypes(typeof(object[]), mi);
        // HACK the code we generate is not verifiable (known issue: locals aren't typed correctly), so we stick the DynamicMethod into mscorlib (a security critical assembly)
        this.dm    = new DynamicMethod(lambdaForm.debugName, mi.ReturnType, paramTypes, typeof(object).Module, true);
        this.ilgen = CodeEmitter.Create(this.dm);
        if (invokerType.parameterCount() > MethodHandleUtil.MaxArity)
        {
            this.packedArgType = paramTypes[paramTypes.Length - 1];
            this.packedArgPos  = paramTypes.Length - 1;
        }
        else
        {
            this.packedArgPos = Int32.MaxValue;
        }

        locals = new CodeEmitterLocal[lambdaForm.names.Length];
        for (int i = lambdaForm._arity(); i < lambdaForm.names.Length; i++)
        {
            Name name = lambdaForm.names[i];
            if (name.index() != i)
            {
                throw new BailoutException(Bailout.PreconditionViolated, "name.index() != i");
            }
            switch (name.typeChar())
            {
            case 'L':
                locals[i] = ilgen.DeclareLocal(Types.Object);
                break;

            case 'I':
                locals[i] = ilgen.DeclareLocal(Types.Int32);
                break;

            case 'J':
                locals[i] = ilgen.DeclareLocal(Types.Int64);
                break;

            case 'F':
                locals[i] = ilgen.DeclareLocal(Types.Single);
                break;

            case 'D':
                locals[i] = ilgen.DeclareLocal(Types.Double);
                break;

            case 'V':
                break;

            default:
                throw new BailoutException(Bailout.PreconditionViolated, "Unsupported typeChar(): " + name.typeChar());
            }
        }
    }
    /**
     * Emit bytecode for the guardWithCatch idiom.
     *
     * The pattern looks like (Cf. MethodHandleImpl.makeGuardWithCatch):
     * <blockquote><pre>{@code
     *  guardWithCatch=Lambda(a0:L,a1:L,a2:L,a3:L,a4:L,a5:L,a6:L,a7:L)=>{
     *    t8:L=MethodHandle.invokeBasic(a4:L,a6:L,a7:L);
     *    t9:L=MethodHandleImpl.guardWithCatch(a1:L,a2:L,a3:L,t8:L);
     *   t10:I=MethodHandle.invokeBasic(a5:L,t9:L);t10:I}
     * }</pre></blockquote>
     *
     * It is compiled into bytecode equivalent of the following code:
     * <blockquote><pre>{@code
     *  try {
     *      return a1.invokeBasic(a6, a7);
     *  } catch (Throwable e) {
     *      if (!a2.isInstance(e)) throw e;
     *      return a3.invokeBasic(ex, a6, a7);
     *  }}</pre></blockquote>
     */
    private Name emitGuardWithCatch(int pos)
    {
        Name args    = lambdaForm.names[pos];
        Name invoker = lambdaForm.names[pos + 1];
        Name result  = lambdaForm.names[pos + 2];

        CodeEmitterLabel L_handler = ilgen.DefineLabel();
        CodeEmitterLabel L_done    = ilgen.DefineLabel();

        Class      returnType = result.function._resolvedHandle().type().returnType();
        MethodType type       = args.function._resolvedHandle().type()
                                .dropParameterTypes(0, 1)
                                .changeReturnType(returnType);

        // Normal case
        ilgen.BeginExceptionBlock();
        // load target
        emitPushArgument(invoker, 0);
        emitPushArguments(args, 1); // skip 1st argument: method handle
        EmitInvokeBasic(type.basicType());
        CodeEmitterLocal returnValue = null;

        if (returnType != java.lang.Void.TYPE)
        {
            returnValue = ilgen.DeclareLocal(TypeWrapper.FromClass(returnType).TypeAsLocalOrStackType);
            ilgen.Emit(OpCodes.Stloc, returnValue);
        }
        ilgen.EmitLeave(L_done);

        // Exceptional case
        ilgen.BeginCatchBlock(typeof(Exception));

        // [IKVM] map the exception and store it in a local and exit the handler
        ilgen.EmitLdc_I4(0);
        ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.mapException.MakeGenericMethod(typeof(Exception)));
        CodeEmitterLocal exception = ilgen.DeclareLocal(typeof(Exception));

        ilgen.Emit(OpCodes.Stloc, exception);
        ilgen.EmitLeave(L_handler);
        ilgen.EndExceptionBlock();

        // Check exception's type
        ilgen.MarkLabel(L_handler);
        // load exception class
        emitPushArgument(invoker, 1);
        ilgen.Emit(OpCodes.Ldloc, exception);
        CoreClasses.java.lang.Class.Wrapper.GetMethodWrapper("isInstance", "(Ljava.lang.Object;)Z", false).EmitCall(ilgen);
        CodeEmitterLabel L_rethrow = ilgen.DefineLabel();

        ilgen.EmitBrfalse(L_rethrow);

        // Invoke catcher
        // load catcher
        emitPushArgument(invoker, 2);
        ilgen.Emit(OpCodes.Ldloc, exception);
        emitPushArguments(args, 1); // skip 1st argument: method handle
        MethodType catcherType = type.insertParameterTypes(0, CoreClasses.java.lang.Throwable.Wrapper.ClassObject);

        EmitInvokeBasic(catcherType.basicType());
        if (returnValue != null)
        {
            ilgen.Emit(OpCodes.Stloc, returnValue);
        }
        ilgen.EmitBr(L_done);

        ilgen.MarkLabel(L_rethrow);
        ilgen.Emit(OpCodes.Ldloc, exception);
        ilgen.Emit(OpCodes.Call, Compiler.unmapExceptionMethod);
        ilgen.Emit(OpCodes.Throw);

        ilgen.MarkLabel(L_done);
        if (returnValue != null)
        {
            ilgen.Emit(OpCodes.Ldloc, returnValue);
        }

        return(result);
    }
    private NativeInvokerBytecodeGenerator(LambdaForm lambdaForm, MethodType invokerType)
    {
        if (invokerType != invokerType.basicType())
        {
            throw new BailoutException(Bailout.NotBasicType, invokerType);
        }
        this.lambdaForm = lambdaForm;
        this.invokerType = invokerType;
        this.delegateType = MethodHandleUtil.GetMemberWrapperDelegateType(invokerType);
        MethodInfo mi = MethodHandleUtil.GetDelegateInvokeMethod(delegateType);
        Type[] paramTypes = MethodHandleUtil.GetParameterTypes(typeof(object[]), mi);
        // HACK the code we generate is not verifiable (known issue: locals aren't typed correctly), so we stick the DynamicMethod into mscorlib (a security critical assembly)
        this.dm = new DynamicMethod(lambdaForm.debugName, mi.ReturnType, paramTypes, typeof(object).Module, true);
        this.ilgen = CodeEmitter.Create(this.dm);
        if (invokerType.parameterCount() > MethodHandleUtil.MaxArity)
        {
            this.packedArgType = paramTypes[paramTypes.Length - 1];
            this.packedArgPos = paramTypes.Length - 1;
        }
        else
        {
            this.packedArgPos = Int32.MaxValue;
        }

        locals = new CodeEmitterLocal[lambdaForm.names.Length];
        for (int i = lambdaForm._arity(); i < lambdaForm.names.Length; i++)
        {
            Name name = lambdaForm.names[i];
            if (name.index() != i)
            {
                throw new BailoutException(Bailout.PreconditionViolated, "name.index() != i");
            }
            switch (name.typeChar())
            {
                case 'L':
                    locals[i] = ilgen.DeclareLocal(Types.Object);
                    break;
                case 'I':
                    locals[i] = ilgen.DeclareLocal(Types.Int32);
                    break;
                case 'J':
                    locals[i] = ilgen.DeclareLocal(Types.Int64);
                    break;
                case 'F':
                    locals[i] = ilgen.DeclareLocal(Types.Single);
                    break;
                case 'D':
                    locals[i] = ilgen.DeclareLocal(Types.Double);
                    break;
                case 'V':
                    break;
                default:
                    throw new BailoutException(Bailout.PreconditionViolated, "Unsupported typeChar(): " + name.typeChar());
            }
        }
    }