/** * Generate an invoker method for the passed {@link LambdaForm}. */ private Delegate generateCustomizedCodeBytes() { // iterate over the form's names, generating bytecode instructions for each // start iterating at the first name following the arguments Name onStack = null; for (int i = lambdaForm._arity(); i < lambdaForm.names.Length; i++) { Name name = lambdaForm.names[i]; emitStoreResult(onStack); onStack = name; // unless otherwise modified below MethodHandleImpl.Intrinsic intr = name.function.intrinsicName(); switch (intr.name()) { case "SELECT_ALTERNATIVE": //assert isSelectAlternative(i); onStack = emitSelectAlternative(name, lambdaForm.names[i + 1]); i++; // skip MH.invokeBasic of the selectAlternative result continue; case "GUARD_WITH_CATCH": //assert isGuardWithCatch(i); onStack = emitGuardWithCatch(i); i = i + 2; // Jump to the end of GWC idiom continue; case "NEW_ARRAY": Class rtype = name.function.methodType().returnType(); if (InvokerBytecodeGenerator.isStaticallyNameable(rtype)) { emitNewArray(name); continue; } break; case "ARRAY_LOAD": emitArrayLoad(name); continue; case "IDENTITY": //assert(name.arguments.length == 1); emitPushArguments(name); continue; case "NONE": // no intrinsic associated break; // [IKVM] ARRAY_STORE and ZERO appear to be unused default: throw new BailoutException(Bailout.UnsupportedIntrinsic, "Unknown intrinsic: " + intr); } MemberName member = name.function._member(); if (isStaticallyInvocable(member)) { emitStaticInvoke(member, name); } else { emitInvoke(name); } } // return statement emitReturn(onStack); ilgen.DoEmit(); return(dm.CreateDelegate(delegateType, constants.ToArray())); }
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()); } } }