private void emitPushArgument(Class ptype, object arg)
    {
        BasicType bptype = BasicType.basicType(ptype);

        if (arg is Name)
        {
            Name n = (Name)arg;
            emitLoadInsn(n._type(), n.index());
            emitImplicitConversion(n._type(), ptype, n);
        }
        else if ((arg == null || arg is string) && bptype == BasicType.L_TYPE)
        {
            emitConst(arg);
        }
        else
        {
            if (Wrapper.isWrapperType(ikvm.extensions.ExtensionMethods.getClass(arg)) && bptype != BasicType.L_TYPE)
            {
                emitConst(arg);
            }
            else
            {
                EmitConstant(arg);
                emitImplicitConversion(BasicType.L_TYPE, ptype, arg);
            }
        }
    }
 /**
  * Store the name to its local, if necessary.
  */
 private void emitStoreResult(Name name)
 {
     if (name != null && name._type() != BasicType.V_TYPE)
     {
         // non-void: actually assign
         emitStoreInsn(name._type(), name.index());
     }
 }
    /**
     * Emit bytecode for the selectAlternative idiom.
     *
     * The pattern looks like (Cf. MethodHandleImpl.makeGuardWithTest):
     * <blockquote><pre>{@code
     *   Lambda(a0:L,a1:I)=>{
     *     t2:I=foo.test(a1:I);
     *     t3:L=MethodHandleImpl.selectAlternative(t2:I,(MethodHandle(int)int),(MethodHandle(int)int));
     *     t4:I=MethodHandle.invokeBasic(t3:L,a1:I);t4:I}
     * }</pre></blockquote>
     */
    private Name emitSelectAlternative(Name selectAlternativeName, Name invokeBasicName)
    {
        //assert isStaticallyInvocable(invokeBasicName);

        Name receiver = (Name)invokeBasicName.arguments[0];

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

        // load test result
        emitPushArgument(selectAlternativeName, 0);

        // if_icmpne L_fallback
        ilgen.EmitBrfalse(L_fallback);

        // invoke selectAlternativeName.arguments[1]
        //Class<?>[] preForkClasses = localClasses.clone();
        emitPushArgument(selectAlternativeName, 1); // get 2nd argument of selectAlternative
        emitAstoreInsn(receiver.index());           // store the MH in the receiver slot
        emitStaticInvoke(invokeBasicName);

        // goto L_done
        ilgen.EmitBr(L_done);

        // L_fallback:
        ilgen.MarkLabel(L_fallback);

        // invoke selectAlternativeName.arguments[2]
        //System.arraycopy(preForkClasses, 0, localClasses, 0, preForkClasses.length);
        emitPushArgument(selectAlternativeName, 2); // get 3rd argument of selectAlternative
        emitAstoreInsn(receiver.index());           // store the MH in the receiver slot
        emitStaticInvoke(invokeBasicName);

        // L_done:
        ilgen.MarkLabel(L_done);
        // for now do not bother to merge typestate; just reset to the dominator state
        //System.arraycopy(preForkClasses, 0, localClasses, 0, preForkClasses.length);

        return(invokeBasicName);  // return what's on stack
    }
    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());
            }
        }
    }
 /**
  * Store the name to its local, if necessary.
  */
 private void emitStoreResult(Name name) {
     if (name != null && name._type() != BasicType.V_TYPE) {
         // non-void: actually assign
         emitStoreInsn(name._type(), name.index());
     }
 }