internal override void Emit(CodeEmitter ilgen) { base.Emit(ilgen); // unbox leaves a pointer to the value of the stack (instead of the value) // so we have to copy the value into a local variable and load the address // of the local onto the stack LocalBuilder local = ilgen.DeclareLocal(Type); ilgen.Emit(OpCodes.Stloc, local); ilgen.Emit(OpCodes.Ldloca, local); }
private static void CreateStaticInitializer(TypeBuilder tb, List <ProxyMethod> methods) { ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Static, CallingConventions.Standard, Type.EmptyTypes); CodeEmitter ilgen = CodeEmitter.Create(cb); CodeEmitterLocal callerID = ilgen.DeclareLocal([email protected]); TypeBuilder tbCallerID = DynamicTypeWrapper.FinishContext.EmitCreateCallerID(tb, ilgen); ilgen.Emit(OpCodes.Stloc, callerID); // HACK we shouldn't create the nested type here (the outer type must be created first) tbCallerID.CreateType(); ilgen.BeginExceptionBlock(); foreach (ProxyMethod method in methods) { method.mw.DeclaringType.EmitClassLiteral(ilgen); ilgen.Emit(OpCodes.Ldstr, method.mw.Name); TypeWrapper[] parameters = method.mw.GetParameters(); ilgen.Emit(OpCodes.Ldc_I4, parameters.Length); ilgen.Emit(OpCodes.Newarr, CoreClasses.java.lang.Class.Wrapper.TypeAsArrayType); for (int i = 0; i < parameters.Length; i++) { ilgen.Emit(OpCodes.Dup); ilgen.Emit(OpCodes.Ldc_I4, i); parameters[i].EmitClassLiteral(ilgen); ilgen.Emit(OpCodes.Stelem_Ref); } if (javaLangClass_getMethod.HasCallerID) { ilgen.Emit(OpCodes.Ldloc, callerID); } javaLangClass_getMethod.EmitCallvirt(ilgen); ilgen.Emit(OpCodes.Stsfld, method.fb); } CodeEmitterLabel label = ilgen.DefineLabel(); ilgen.Emit(OpCodes.Leave_S, label); ilgen.BeginCatchBlock(javaLangNoSuchMethodException.TypeAsExceptionType); javaLangThrowable_getMessage.EmitCallvirt(ilgen); javaLangNoClassDefFoundErrorConstructor.EmitNewobj(ilgen); ilgen.Emit(OpCodes.Throw); ilgen.EndExceptionBlock(); ilgen.MarkLabel(label); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); }
protected override void EmitSetImpl(CodeEmitter ilgen) { FieldInfo fi = GetField(); if(!IsStatic && DeclaringType.IsNonPrimitiveValueType) { CodeEmitterLocal temp = ilgen.DeclareLocal(FieldTypeWrapper.TypeAsSignatureType); ilgen.Emit(OpCodes.Stloc, temp); ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD); ilgen.Emit(OpCodes.Ldloc, temp); } if(IsVolatile) { ilgen.Emit(OpCodes.Volatile); } ilgen.Emit(IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fi); if(IsVolatile) { ilgen.EmitMemoryBarrier(); } }
internal override void EmitNewobj(CodeEmitter ilgen) { CodeEmitterLocal local = ilgen.DeclareLocal(DeclaringType.TypeAsTBD); ilgen.Emit(OpCodes.Ldloc, local); ilgen.Emit(OpCodes.Box, DeclaringType.TypeAsTBD); }
private void ConvertByRefArgs(CodeEmitter ilgen) { CodeEmitterLocal[] locals = new CodeEmitterLocal[args.Length]; for (int i = args.Length - 1; i >= 0; i--) { Type type = args[i]; if (type.IsByRef) { type = ArrayTypeWrapper.MakeArrayType(type.GetElementType(), 1); } locals[i] = ilgen.DeclareLocal(type); ilgen.Emit(OpCodes.Stloc, locals[i]); } for (int i = 0; i < args.Length; i++) { ilgen.Emit(OpCodes.Ldloc, locals[i]); if (args[i].IsByRef) { ilgen.Emit(OpCodes.Ldc_I4_0); ilgen.Emit(OpCodes.Ldelema, args[i].GetElementType()); } } }
internal override void EmitNewobj(CodeEmitter ilgen, MethodAnalyzer ma, int opcodeIndex) { LocalBuilder local = ilgen.DeclareLocal(DeclaringType.TypeAsTBD); ilgen.Emit(OpCodes.Ldloc, local); ilgen.Emit(OpCodes.Box, DeclaringType.TypeAsTBD); }
protected override void PreEmit(CodeEmitter ilgen) { LocalBuilder[] locals = new LocalBuilder[args.Length]; for (int i = args.Length - 1; i >= 0; i--) { Type type = args[i]; if (type.IsByRef) { type = ArrayTypeWrapper.MakeArrayType(type.GetElementType(), 1); } locals[i] = ilgen.DeclareLocal(type); ilgen.Emit(OpCodes.Stloc, locals[i]); } for (int i = 0; i < args.Length; i++) { ilgen.Emit(OpCodes.Ldloc, locals[i]); if (args[i].IsByRef) { ilgen.Emit(OpCodes.Ldc_I4_0); ilgen.Emit(OpCodes.Ldelema, args[i].GetElementType()); } } base.PreEmit(ilgen); }
internal override void EmitNewobj(CodeEmitter ilgen, MethodAnalyzer ma, int opcodeIndex) { TypeWrapper targetType = ma == null ? null : ma.GetStackTypeWrapper(opcodeIndex, 0); if (targetType == null || targetType.IsInterface) { MethodInfo createDelegate = Types.Delegate.GetMethod("CreateDelegate", new Type[] { Types.Type, Types.Object, Types.String }); LocalBuilder targetObj = ilgen.DeclareLocal(Types.Object); ilgen.Emit(OpCodes.Stloc, targetObj); ilgen.Emit(OpCodes.Ldtoken, delegateConstructor.DeclaringType); ilgen.Emit(OpCodes.Call, Types.Type.GetMethod("GetTypeFromHandle", new Type[] { Types.RuntimeTypeHandle })); ilgen.Emit(OpCodes.Ldloc, targetObj); ilgen.Emit(OpCodes.Ldstr, "Invoke"); ilgen.Emit(OpCodes.Call, createDelegate); ilgen.Emit(OpCodes.Castclass, delegateConstructor.DeclaringType); } else { ilgen.Emit(OpCodes.Dup); // we know that a DelegateInnerClassTypeWrapper has only one method Debug.Assert(iface.GetMethods().Length == 1); MethodWrapper mw = targetType.GetMethodWrapper("Invoke", iface.GetMethods()[0].Signature, true); // TODO linking here is not safe mw.Link(); ilgen.Emit(OpCodes.Ldvirtftn, (MethodInfo)mw.GetMethod()); ilgen.Emit(OpCodes.Newobj, delegateConstructor); } }
internal override void Generate(CodeGenContext context, CodeEmitter ilgen) { CodeEmitterLocal lb = (CodeEmitterLocal)context[Name]; if(lb == null) { if(typeWrapper == null && typeType == null) { Debug.Assert(Class == null ^ type == null); if(type != null) { typeType = StaticCompiler.GetTypeForMapXml(context.ClassLoader, type); } else { typeWrapper = context.ClassLoader.LoadClassByDottedName(Class); } } lb = ilgen.DeclareLocal(typeType != null ? typeType : typeWrapper.TypeAsTBD); context[Name] = lb; } ilgen.Emit(OpCodes.Stloc, lb); }
internal sealed override void Generate(CodeGenContext context, CodeEmitter ilgen) { Debug.Assert(Name != null); if(Name == ".ctor") { Debug.Assert(Class == null && type != null); Type[] argTypes = context.ClassLoader.ArgTypeListFromSig(Sig); ConstructorInfo ci = StaticCompiler.GetTypeForMapXml(context.ClassLoader, type).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, CallingConventions.Standard, argTypes, null); if(ci == null) { throw new InvalidOperationException("Missing .ctor: " + type + "..ctor" + Sig); } ilgen.Emit(opcode, ci); } else { Debug.Assert(Class == null ^ type == null); if(Class != null) { Debug.Assert(Sig != null); MethodWrapper method = context.ClassLoader.LoadClassByDottedName(Class).GetMethodWrapper(Name, Sig, false); if(method == null) { throw new InvalidOperationException("method not found: " + Class + "." + Name + Sig); } method.Link(); // TODO this code is part of what Compiler.CastInterfaceArgs (in compiler.cs) does, // it would be nice if we could avoid this duplication... TypeWrapper[] argTypeWrappers = method.GetParameters(); for(int i = 0; i < argTypeWrappers.Length; i++) { if(argTypeWrappers[i].IsGhost) { CodeEmitterLocal[] temps = new CodeEmitterLocal[argTypeWrappers.Length + (method.IsStatic ? 0 : 1)]; for(int j = temps.Length - 1; j >= 0; j--) { TypeWrapper tw; if(method.IsStatic) { tw = argTypeWrappers[j]; } else { if(j == 0) { tw = method.DeclaringType; } else { tw = argTypeWrappers[j - 1]; } } if(tw.IsGhost) { tw.EmitConvStackTypeToSignatureType(ilgen, null); } temps[j] = ilgen.DeclareLocal(tw.TypeAsSignatureType); ilgen.Emit(OpCodes.Stloc, temps[j]); } for(int j = 0; j < temps.Length; j++) { ilgen.Emit(OpCodes.Ldloc, temps[j]); } break; } } if(opcode.Value == OpCodes.Call.Value) { method.EmitCall(ilgen); } else if(opcode.Value == OpCodes.Callvirt.Value) { method.EmitCallvirt(ilgen); } else if(opcode.Value == OpCodes.Newobj.Value) { method.EmitNewobj(ilgen); } else { // ldftn or ldvirtftn ilgen.Emit(opcode, (MethodInfo)method.GetMethod()); } } else { Type[] argTypes; if(Sig.StartsWith("(")) { argTypes = context.ClassLoader.ArgTypeListFromSig(Sig); } else if(Sig == "") { argTypes = Type.EmptyTypes; } else { string[] types = Sig.Split(';'); argTypes = new Type[types.Length]; for(int i = 0; i < types.Length; i++) { argTypes[i] = StaticCompiler.GetTypeForMapXml(context.ClassLoader, types[i]); } } MethodInfo mi = StaticCompiler.GetTypeForMapXml(context.ClassLoader, type).GetMethod(Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, null, argTypes, null); if(mi == null) { throw new InvalidOperationException("Missing method: " + type + "." + Name + Sig); } ilgen.Emit(opcode, mi); } } }
private static void CreateMethod(CompilerClassLoader loader, TypeBuilder tb, ProxyMethod pm) { MethodBuilder mb = pm.mw.GetDefineMethodHelper().DefineMethod(loader.GetTypeWrapperFactory(), tb, pm.mw.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final); List <string> exceptions = new List <string>(); foreach (TypeWrapper tw in pm.exceptions) { exceptions.Add(tw.Name); } AttributeHelper.SetThrowsAttribute(mb, exceptions.ToArray()); CodeEmitter ilgen = CodeEmitter.Create(mb); ilgen.BeginExceptionBlock(); ilgen.Emit(OpCodes.Ldarg_0); invocationHandlerField.EmitGet(ilgen); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldsfld, pm.fb); TypeWrapper[] parameters = pm.mw.GetParameters(); if (parameters.Length == 0) { ilgen.Emit(OpCodes.Ldnull); } else { ilgen.EmitLdc_I4(parameters.Length); ilgen.Emit(OpCodes.Newarr, Types.Object); for (int i = 0; i < parameters.Length; i++) { ilgen.Emit(OpCodes.Dup); ilgen.EmitLdc_I4(i); ilgen.EmitLdarg(i); if (parameters[i].IsNonPrimitiveValueType) { parameters[i].EmitBox(ilgen); } else if (parameters[i].IsPrimitive) { Boxer.EmitBox(ilgen, parameters[i]); } ilgen.Emit(OpCodes.Stelem_Ref); } } invokeMethod.EmitCallvirt(ilgen); TypeWrapper returnType = pm.mw.ReturnType; CodeEmitterLocal returnValue = null; if (returnType != PrimitiveTypeWrapper.VOID) { returnValue = ilgen.DeclareLocal(returnType.TypeAsSignatureType); if (returnType.IsNonPrimitiveValueType) { returnType.EmitUnbox(ilgen); } else if (returnType.IsPrimitive) { Boxer.EmitUnbox(ilgen, returnType); } else if (returnType != CoreClasses.java.lang.Object.Wrapper) { ilgen.EmitCastclass(returnType.TypeAsSignatureType); } ilgen.Emit(OpCodes.Stloc, returnValue); } CodeEmitterLabel returnLabel = ilgen.DefineLabel(); ilgen.EmitLeave(returnLabel); // TODO consider using a filter here (but we would need to add filter support to CodeEmitter) ilgen.BeginCatchBlock(Types.Exception); ilgen.EmitLdc_I4(0); ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.mapException.MakeGenericMethod(Types.Exception)); CodeEmitterLocal exception = ilgen.DeclareLocal(Types.Exception); ilgen.Emit(OpCodes.Stloc, exception); CodeEmitterLabel rethrow = ilgen.DefineLabel(); ilgen.Emit(OpCodes.Ldloc, exception); errorClass.EmitInstanceOf(ilgen); ilgen.EmitBrtrue(rethrow); ilgen.Emit(OpCodes.Ldloc, exception); runtimeExceptionClass.EmitInstanceOf(ilgen); ilgen.EmitBrtrue(rethrow); foreach (TypeWrapper tw in pm.exceptions) { ilgen.Emit(OpCodes.Ldloc, exception); tw.EmitInstanceOf(ilgen); ilgen.EmitBrtrue(rethrow); } ilgen.Emit(OpCodes.Ldloc, exception); undeclaredThrowableExceptionConstructor.EmitNewobj(ilgen); ilgen.Emit(OpCodes.Throw); ilgen.MarkLabel(rethrow); ilgen.Emit(OpCodes.Rethrow); ilgen.EndExceptionBlock(); ilgen.MarkLabel(returnLabel); if (returnValue != null) { ilgen.Emit(OpCodes.Ldloc, returnValue); } ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); }
internal override void EmitNewobj(CodeEmitter ilgen) { MethodInfo createDelegate = Types.Delegate.GetMethod("CreateDelegate", new Type[] { Types.Type, Types.Object, Types.String }); CodeEmitterLocal targetObj = ilgen.DeclareLocal(Types.Object); ilgen.Emit(OpCodes.Stloc, targetObj); ilgen.Emit(OpCodes.Ldtoken, delegateConstructor.DeclaringType); ilgen.Emit(OpCodes.Call, Types.Type.GetMethod("GetTypeFromHandle", new Type[] { Types.RuntimeTypeHandle })); ilgen.Emit(OpCodes.Ldloc, targetObj); ilgen.Emit(OpCodes.Ldstr, GetDelegateInvokeStubName(DeclaringType.TypeAsTBD)); ilgen.Emit(OpCodes.Call, createDelegate); ilgen.Emit(OpCodes.Castclass, delegateConstructor.DeclaringType); }
protected override void EmitSetImpl(CodeEmitter ilgen) { if(!IsStatic && DeclaringType.IsNonPrimitiveValueType) { CodeEmitterLocal temp = ilgen.DeclareLocal(FieldTypeWrapper.TypeAsSignatureType); ilgen.Emit(OpCodes.Stloc, temp); ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD); ilgen.Emit(OpCodes.Ldloc, temp); } FieldInfo fi = GetField(); if(fi != null) { // common case (we're in a DynamicTypeWrapper and the caller is too) ilgen.Emit(IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fi); } else { // this means that we are an instance on a CompiledTypeWrapper and we're being called // from DynamicMethod based reflection, so we can safely emit a call to the private // setter, because the DynamicMethod is allowed to access our private members. ilgen.Emit(OpCodes.Call, prop.GetSetMethod(true)); } }
protected override void EmitSetImpl(CodeEmitter ilgen) { FieldInfo fi = GetField(); CodeEmitterLocal temp = ilgen.DeclareLocal(FieldTypeWrapper.TypeAsSignatureType); ilgen.Emit(OpCodes.Stloc, temp); if(fi.IsStatic) { ilgen.Emit(OpCodes.Ldsflda, fi); } else { if(DeclaringType.IsNonPrimitiveValueType) { ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD); } ilgen.Emit(OpCodes.Ldflda, fi); } ilgen.Emit(OpCodes.Ldloc, temp); if(FieldTypeWrapper == PrimitiveTypeWrapper.DOUBLE) { ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.volatileWriteDouble); } else { Debug.Assert(FieldTypeWrapper == PrimitiveTypeWrapper.LONG); ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.volatileWriteLong); } }
internal static void EmitThrowNoSuchMethodErrorForGetter(CodeEmitter ilgen, TypeWrapper type, MemberWrapper member) { #if STATIC_COMPILER StaticCompiler.IssueMessage(Message.EmittedNoSuchMethodError, "<unknown>", member.DeclaringType.Name + "." + member.Name + member.Signature); #endif // HACK the branch around the throw is to keep the verifier happy CodeEmitterLabel label = ilgen.DefineLabel(); ilgen.Emit(OpCodes.Ldc_I4_0); ilgen.EmitBrtrue(label); ilgen.EmitThrow("java.lang.NoSuchMethodError"); ilgen.MarkLabel(label); if (!member.IsStatic) { ilgen.Emit(OpCodes.Pop); } ilgen.Emit(OpCodes.Ldloc, ilgen.DeclareLocal(type.TypeAsLocalOrStackType)); }
internal static void EmitThrowNoSuchMethodErrorForGetter(CodeEmitter ilgen, TypeWrapper type, bool isStatic) { // HACK the branch around the throw is to keep the verifier happy CodeEmitterLabel label = ilgen.DefineLabel(); ilgen.Emit(OpCodes.Ldc_I4_0); ilgen.Emit(OpCodes.Brtrue_S, label); ilgen.EmitThrow("java.lang.NoSuchMethodError"); ilgen.MarkLabel(label); if (!isStatic) { ilgen.Emit(OpCodes.Pop); } ilgen.Emit(OpCodes.Ldloc, ilgen.DeclareLocal(type.TypeAsLocalOrStackType)); }
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()); } } }