internal static bool Emit(DynamicTypeWrapper.FinishContext context, TypeWrapper wrapper, CodeEmitter ilgen, ClassFile classFile, int i, ClassFile.Method.Instruction[] code, InstructionFlags[] flags) { if (i >= 3 && (flags[i - 0] & InstructionFlags.BranchTarget) == 0 && (flags[i - 1] & InstructionFlags.BranchTarget) == 0 && (flags[i - 2] & InstructionFlags.BranchTarget) == 0 && (flags[i - 3] & InstructionFlags.BranchTarget) == 0 && code[i - 1].NormalizedOpCode == NormalizedByteCode.__ldc && code[i - 2].NormalizedOpCode == NormalizedByteCode.__ldc && code[i - 3].NormalizedOpCode == NormalizedByteCode.__ldc) { // we now have a structural match, now we need to make sure that the argument values are what we expect TypeWrapper tclass = classFile.GetConstantPoolClassType(code[i - 3].Arg1); TypeWrapper vclass = classFile.GetConstantPoolClassType(code[i - 2].Arg1); string fieldName = classFile.GetConstantPoolConstantString(code[i - 1].Arg1); if (tclass == wrapper && !vclass.IsUnloadable && !vclass.IsPrimitive && !vclass.IsNonPrimitiveValueType) { FieldWrapper field = wrapper.GetFieldWrapper(fieldName, vclass.SigName); if (field != null && !field.IsStatic && field.IsVolatile && field.DeclaringType == wrapper && field.FieldTypeWrapper == vclass) { // everything matches up, now call the actual emitter DoEmit(context, wrapper, ilgen, field); return true; } } } return false; }
private static void DoEmit(DynamicTypeWrapper.FinishContext context, TypeWrapper wrapper, CodeEmitter ilgen, FieldWrapper field) { ConstructorBuilder cb; bool exists; lock (map) { exists = map.TryGetValue(field, out cb); } if (!exists) { // note that we don't need to lock here, because we're running as part of FinishCore, which is already protected by a lock TypeWrapper arfuTypeWrapper = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.IntrinsicAtomicReferenceFieldUpdater"); TypeBuilder tb = wrapper.TypeAsBuilder.DefineNestedType("__<ARFU>_" + field.Name + field.Signature.Replace('.', '/'), TypeAttributes.NestedPrivate | TypeAttributes.Sealed, arfuTypeWrapper.TypeAsBaseType); EmitCompareAndSet("compareAndSet", tb, field.GetField()); EmitGet(tb, field.GetField()); EmitSet("set", tb, field.GetField()); cb = tb.DefineConstructor(MethodAttributes.Assembly, CallingConventions.Standard, Type.EmptyTypes); lock (map) { map.Add(field, cb); } CodeEmitter ctorilgen = CodeEmitter.Create(cb); ctorilgen.Emit(OpCodes.Ldarg_0); MethodWrapper basector = arfuTypeWrapper.GetMethodWrapper("<init>", "()V", false); basector.Link(); basector.EmitCall(ctorilgen); ctorilgen.Emit(OpCodes.Ret); context.RegisterPostFinishProc(delegate { arfuTypeWrapper.Finish(); tb.CreateType(); }); } ilgen.LazyEmitPop(); ilgen.LazyEmitPop(); ilgen.LazyEmitPop(); ilgen.Emit(OpCodes.Newobj, cb); }
internal static bool Emit(DynamicTypeWrapper.FinishContext context, ClassFile classFile, int constantPoolIndex, ClassFile.ConstantPoolItemInvokeDynamic cpi, CodeEmitter ilgen) { ClassFile.BootstrapMethod bsm = classFile.GetBootstrapMethod(cpi.BootstrapMethod); if (!IsLambdaMetafactory(classFile, bsm) && !IsLambdaAltMetafactory(classFile, bsm)) { return false; } LambdaMetafactory lmf = context.GetValue<LambdaMetafactory>(constantPoolIndex); if (lmf.ctor == null && !lmf.EmitImpl(context, classFile, cpi, bsm, ilgen)) { #if STATIC_COMPILER if (context.TypeWrapper.GetClassLoader().DisableDynamicBinding) { StaticCompiler.IssueMessage(Message.UnableToCreateLambdaFactory); } #endif return false; } ilgen.Emit(OpCodes.Newobj, lmf.ctor); // the CLR verification rules about type merging mean we have to explicitly cast to the interface type here ilgen.Emit(OpCodes.Castclass, cpi.GetRetType().TypeAsBaseType); return true; }
protected override void EmitGetImpl(CodeEmitter ilgen) { // Reading a field should trigger the cctor, but since we're inlining the value // we have to trigger it explicitly DeclaringType.EmitRunClassConstructor(ilgen); // NOTE even though you're not supposed to access a constant static final (the compiler is supposed // to inline them), we have to support it (because it does happen, e.g. if the field becomes final // after the referencing class was compiled, or when we're accessing an unsigned primitive .NET field) object v = GetConstantValue(); if(v == null) { ilgen.Emit(OpCodes.Ldnull); } else if(constant is int || constant is short || constant is ushort || constant is byte || constant is sbyte || constant is char || constant is bool) { ilgen.Emit(OpCodes.Ldc_I4, ((IConvertible)constant).ToInt32(null)); } else if(constant is string) { ilgen.Emit(OpCodes.Ldstr, (string)constant); } else if(constant is float) { ilgen.Emit(OpCodes.Ldc_R4, (float)constant); } else if(constant is double) { ilgen.Emit(OpCodes.Ldc_R8, (double)constant); } else if(constant is long) { ilgen.Emit(OpCodes.Ldc_I8, (long)constant); } else if(constant is uint) { ilgen.Emit(OpCodes.Ldc_I4, unchecked((int)((IConvertible)constant).ToUInt32(null))); } else if(constant is ulong) { ilgen.Emit(OpCodes.Ldc_I8, unchecked((long)(ulong)constant)); } else { throw new InvalidOperationException(constant.GetType().FullName); } }
private static bool Double_longBitsToDouble(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { EmitConversion(ilgen, typeofDoubleConverter, "ToDouble"); return(true); }
protected override void EmitGetImpl(CodeEmitter ilgen) { FieldInfo fi = GetField(); if(fi.IsStatic) { ilgen.Emit(OpCodes.Ldsflda, fi); } else { if(DeclaringType.IsNonPrimitiveValueType) { ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD); } ilgen.Emit(OpCodes.Ldflda, fi); } if(FieldTypeWrapper == PrimitiveTypeWrapper.DOUBLE) { ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.volatileReadDouble); } else { Debug.Assert(FieldTypeWrapper == PrimitiveTypeWrapper.LONG); ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.volatileReadLong); } }
protected override void EmitSetImpl(CodeEmitter ilgen) { if(setter == null) { if(this.IsFinal) { ilgen.Emit(OpCodes.Pop); if(!this.IsStatic) { ilgen.Emit(OpCodes.Pop); } } else { EmitThrowNoSuchMethodErrorForSetter(ilgen, this.IsStatic); } } else if(setter.IsStatic) { setter.EmitCall(ilgen); } else { setter.EmitCallvirt(ilgen); } }
protected override void NewobjImpl(CodeEmitter ilgen) { ilgen.Emit(OpCodes.Newobj, (ConstructorInfo)GetMethod()); }
internal void EmitSet(CodeEmitter ilgen) { AssertLinked(); EmitSetImpl(ilgen); }
private static bool CallerID_getCallerID(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { if (caller.HasCallerID) { int arg = caller.GetParametersForDefineMethod().Length - 1; if (!caller.IsStatic) { arg++; } ilgen.Emit(OpCodes.Ldarg, (short)arg); return(true); } else { JVM.CriticalFailure("CallerID.getCallerID() requires a HasCallerID annotation", null); } return(false); }
private static bool Util_getInstanceTypeFromClass(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { TypeWrapper tw = ilgen.PeekLazyClassLiteral(); if (tw != null) { ilgen.LazyEmitPop(); if (tw.IsRemapped && tw.IsFinal) { ilgen.Emit(OpCodes.Ldtoken, tw.TypeAsTBD); } else { ilgen.Emit(OpCodes.Ldtoken, tw.TypeAsBaseType); } ilgen.Emit(OpCodes.Call, Compiler.getTypeFromHandleMethod); return(true); } return(false); }
private static bool Reflection_getCallerClass(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { if (caller.HasCallerID && opcodeIndex > 0 && (flags[opcodeIndex - 1] & InstructionFlags.BranchTarget) == 0 && code[opcodeIndex - 1].NormalizedOpCode == NormalizedByteCode.__iconst && code[opcodeIndex - 1].Arg1 == 2) { ilgen.LazyEmitPop(); int arg = caller.GetParametersForDefineMethod().Length - 1; if (!caller.IsStatic) { arg++; } ilgen.Emit(OpCodes.Ldarg, (short)arg); MethodWrapper mw = [email protected]("getCallerClass", "()Ljava.lang.Class;", false); mw.Link(); mw.EmitCallvirt(ilgen); return(true); } return(false); }
private static bool ClassLoader_getCallerClassLoader(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { if (caller.HasCallerID) { int arg = caller.GetParametersForDefineMethod().Length - 1; if (!caller.IsStatic) { arg++; } ilgen.Emit(OpCodes.Ldarg, (short)arg); MethodWrapper mw = [email protected]("getCallerClassLoader", "()Ljava.lang.ClassLoader;", false); mw.Link(); mw.EmitCallvirt(ilgen); return(true); } return(false); }
private static bool String_toCharArray(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { string str = ilgen.PopLazyLdstr(); if (str != null) { // arbitrary length for "big" strings if (str.Length > 128) { EmitLoadCharArrayLiteral(ilgen, str, caller.DeclaringType); return(true); } ilgen.Emit(OpCodes.Ldstr, str); } return(false); }
private static bool AtomicReferenceFieldUpdater_newUpdater(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { return(AtomicReferenceFieldUpdaterEmitter.Emit(context, caller.DeclaringType, ilgen, classFile, opcodeIndex, code, flags)); }
private static bool System_arraycopy(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { // if the array arguments on the stack are of a known array type, we can redirect to an optimized version of arraycopy. // Note that we also have to handle VMSystem.arraycopy, because on GNU Classpath StringBuffer directly calls // this method to avoid prematurely initialising System. TypeWrapper dst_type = ma.GetStackTypeWrapper(opcodeIndex, 2); TypeWrapper src_type = ma.GetStackTypeWrapper(opcodeIndex, 4); if (!dst_type.IsUnloadable && dst_type.IsArray && dst_type == src_type) { switch (dst_type.Name[1]) { case 'J': case 'D': ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_primitive_8); break; case 'I': case 'F': ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_primitive_4); break; case 'S': case 'C': ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_primitive_2); break; case 'B': case 'Z': ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_primitive_1); break; default: // TODO once the verifier tracks actual types (i.e. it knows that // a particular reference is the result of a "new" opcode) we can // use the fast version if the exact destination type is known // (in that case the "dst_type == src_type" above should // be changed to "src_type.IsAssignableTo(dst_type)". TypeWrapper elemtw = dst_type.ElementTypeWrapper; // note that IsFinal returns true for array types, so we have to be careful! if (!elemtw.IsArray && elemtw.IsFinal) { ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_fast); } else { ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy); } break; } return(true); } else { return(false); } }
protected virtual void NewobjImpl(CodeEmitter ilgen) { throw new InvalidOperationException(); }
private static bool Class_getPrimitiveClass(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { ilgen.LazyEmitPop(); ilgen.Emit(OpCodes.Ldnull); MethodWrapper mw = CoreClasses.java.lang.Class.Wrapper.GetMethodWrapper("<init>", "(Lcli.System.Type;)V", false); mw.Link(); mw.EmitNewobj(ilgen); return(true); }
protected override void CallvirtImpl(CodeEmitter ilgen) { ilgen.Emit(SimpleOpCodeToOpCode(callvirt), (MethodInfo)GetMethod()); }
private static bool ThreadLocal_new(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { // it is only valid to replace a ThreadLocal instantiation by our ThreadStatic based version, if we can prove that the instantiation only happens once // (which is the case when we're in <clinit> and there aren't any branches that lead to the current position) if (caller.Name != StringConstants.CLINIT) { return(false); } #if CLASSGC if (JVM.classUnloading) { // RunAndCollect assemblies do not support ThreadStaticAttribute return(false); } #endif for (int i = 0; i <= opcodeIndex; i++) { if ((flags[i] & InstructionFlags.BranchTarget) != 0) { return(false); } } ilgen.Emit(OpCodes.Newobj, DefineThreadLocalType(context, opcodeIndex, caller)); return(true); }
protected override void CallImpl(CodeEmitter ilgen) { ilgen.Emit(OpCodes.Call, stub); }
internal static void EmitUnbox(CodeEmitter ilgen, TypeWrapper tw, bool cast) { if (tw == PrimitiveTypeWrapper.BYTE) { if (cast) { javaLangByte.EmitCheckcast(ilgen); } byteValue.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.BOOLEAN) { if (cast) { javaLangBoolean.EmitCheckcast(ilgen); } booleanValue.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.SHORT) { if (cast) { javaLangShort.EmitCheckcast(ilgen); } shortValue.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.CHAR) { if (cast) { javaLangCharacter.EmitCheckcast(ilgen); } charValue.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.INT) { if (cast) { javaLangInteger.EmitCheckcast(ilgen); } intValue.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.FLOAT) { if (cast) { javaLangFloat.EmitCheckcast(ilgen); } floatValue.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.LONG) { if (cast) { javaLangLong.EmitCheckcast(ilgen); } longValue.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.DOUBLE) { if (cast) { javaLangDouble.EmitCheckcast(ilgen); } doubleValue.EmitCall(ilgen); } else { throw new InvalidOperationException(); } }
protected override void EmitGetImpl(CodeEmitter ilgen) { if(!IsStatic && DeclaringType.IsNonPrimitiveValueType) { ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD); } if(IsVolatile) { ilgen.Emit(OpCodes.Volatile); } ilgen.Emit(IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, GetField()); }
internal static bool Emit(DynamicTypeWrapper.FinishContext context, ClassFile classFile, int constantPoolIndex, ClassFile.ConstantPoolItemInvokeDynamic cpi, CodeEmitter ilgen) { ClassFile.BootstrapMethod bsm = classFile.GetBootstrapMethod(cpi.BootstrapMethod); if (!IsLambdaMetafactory(classFile, bsm) && !IsLambdaAltMetafactory(classFile, bsm)) { return(false); } LambdaMetafactory lmf = context.GetValue <LambdaMetafactory>(constantPoolIndex); if (lmf.ctor == null && !lmf.EmitImpl(context, classFile, cpi, bsm, ilgen)) { #if STATIC_COMPILER if (context.TypeWrapper.GetClassLoader().DisableDynamicBinding) { StaticCompiler.IssueMessage(Message.UnableToCreateLambdaFactory); } #endif return(false); } ilgen.Emit(OpCodes.Newobj, lmf.ctor); // the CLR verification rules about type merging mean we have to explicitly cast to the interface type here ilgen.Emit(OpCodes.Castclass, cpi.GetRetType().TypeAsBaseType); return(true); }
protected override void EmitGetImpl(CodeEmitter ilgen) { if(getter == null) { EmitThrowNoSuchMethodErrorForGetter(ilgen, this.FieldTypeWrapper, this.IsStatic); } else if(getter.IsStatic) { getter.EmitCall(ilgen); } else { getter.EmitCallvirt(ilgen); } }
private static MethodBuilder CreateConstructorAndDispatch(DynamicTypeWrapper.FinishContext context, ClassFile.ConstantPoolItemInvokeDynamic cpi, TypeBuilder tb, List <MethodWrapper> methods, TypeWrapper[] implParameters, ClassFile.ConstantPoolItemMethodType samMethodType, ClassFile.ConstantPoolItemMethodHandle implMethod, ClassFile.ConstantPoolItemMethodType instantiatedMethodType, bool serializable) { TypeWrapper[] args = cpi.GetArgTypes(); // captured values Type[] capturedTypes = new Type[args.Length]; FieldBuilder[] capturedFields = new FieldBuilder[capturedTypes.Length]; for (int i = 0; i < capturedTypes.Length; i++) { capturedTypes[i] = args[i].TypeAsSignatureType; FieldAttributes attr = FieldAttributes.Private; if (i > 0 || !args[0].IsGhost) { attr |= FieldAttributes.InitOnly; } capturedFields[i] = tb.DefineField("arg$" + (i + 1), capturedTypes[i], attr); } // constructor MethodBuilder ctor = ReflectUtil.DefineConstructor(tb, MethodAttributes.Assembly, capturedTypes); CodeEmitter ilgen = CodeEmitter.Create(ctor); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Call, Types.Object.GetConstructor(Type.EmptyTypes)); for (int i = 0; i < capturedTypes.Length; i++) { ilgen.EmitLdarg(0); ilgen.EmitLdarg(i + 1); ilgen.Emit(OpCodes.Stfld, capturedFields[i]); } ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); // dispatch methods foreach (MethodWrapper mw in methods) { EmitDispatch(context, args, tb, mw, implParameters, implMethod, instantiatedMethodType, capturedFields); } // writeReplace method if (serializable) { MethodBuilder writeReplace = tb.DefineMethod("writeReplace", MethodAttributes.Private, Types.Object, Type.EmptyTypes); ilgen = CodeEmitter.Create(writeReplace); context.TypeWrapper.EmitClassLiteral(ilgen); ilgen.Emit(OpCodes.Ldstr, cpi.GetRetType().Name.Replace('.', '/')); ilgen.Emit(OpCodes.Ldstr, cpi.Name); ilgen.Emit(OpCodes.Ldstr, samMethodType.Signature.Replace('.', '/')); ilgen.EmitLdc_I4((int)implMethod.Kind); ilgen.Emit(OpCodes.Ldstr, implMethod.Class.Replace('.', '/')); ilgen.Emit(OpCodes.Ldstr, implMethod.Name); ilgen.Emit(OpCodes.Ldstr, implMethod.Signature.Replace('.', '/')); ilgen.Emit(OpCodes.Ldstr, instantiatedMethodType.Signature.Replace('.', '/')); ilgen.EmitLdc_I4(capturedFields.Length); ilgen.Emit(OpCodes.Newarr, Types.Object); for (int i = 0; i < capturedFields.Length; i++) { ilgen.Emit(OpCodes.Dup); ilgen.EmitLdc_I4(i); ilgen.EmitLdarg(0); ilgen.Emit(OpCodes.Ldfld, capturedFields[i]); if (args[i].IsPrimitive) { Boxer.EmitBox(ilgen, args[i]); } else if (args[i].IsGhost) { args[i].EmitConvSignatureTypeToStackType(ilgen); } ilgen.Emit(OpCodes.Stelem, Types.Object); } MethodWrapper ctorSerializedLambda = ClassLoaderWrapper.LoadClassCritical("java.lang.invoke.SerializedLambda").GetMethodWrapper(StringConstants.INIT, "(Ljava.lang.Class;Ljava.lang.String;Ljava.lang.String;Ljava.lang.String;ILjava.lang.String;Ljava.lang.String;Ljava.lang.String;Ljava.lang.String;[Ljava.lang.Object;)V", false); ctorSerializedLambda.Link(); ctorSerializedLambda.EmitNewobj(ilgen); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); if (!context.TypeWrapper.GetClassLoader().NoAutomagicSerialization) { // add .NET serialization interop support Serialization.MarkSerializable(tb); Serialization.AddGetObjectData(tb); } } return(ctor); }
protected override void EmitGetImpl(CodeEmitter ilgen) { MethodInfo getter = property.GetGetMethod(true); if(getter == null) { DynamicPropertyFieldWrapper.EmitThrowNoSuchMethodErrorForGetter(ilgen, this.FieldTypeWrapper, this.IsStatic); } else if(getter.IsStatic) { ilgen.Emit(OpCodes.Call, getter); } else { ilgen.Emit(OpCodes.Callvirt, getter); } }
private static void EmitDispatch(DynamicTypeWrapper.FinishContext context, TypeWrapper[] args, TypeBuilder tb, MethodWrapper interfaceMethod, TypeWrapper[] implParameters, ClassFile.ConstantPoolItemMethodHandle implMethod, ClassFile.ConstantPoolItemMethodType instantiatedMethodType, FieldBuilder[] capturedFields) { MethodBuilder mb = interfaceMethod.GetDefineMethodHelper().DefineMethod(context.TypeWrapper, tb, interfaceMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final); if (interfaceMethod.Name != interfaceMethod.RealName) { tb.DefineMethodOverride(mb, (MethodInfo)interfaceMethod.GetMethod()); } CodeEmitter ilgen = CodeEmitter.Create(mb); for (int i = 0; i < capturedFields.Length; i++) { ilgen.EmitLdarg(0); OpCode opc = OpCodes.Ldfld; if (i == 0 && args[0].IsGhost) { switch (implMethod.Kind) { case ClassFile.RefKind.invokeInterface: case ClassFile.RefKind.invokeVirtual: case ClassFile.RefKind.invokeSpecial: opc = OpCodes.Ldflda; break; } } ilgen.Emit(opc, capturedFields[i]); } for (int i = 0, count = interfaceMethod.GetParameters().Length, k = capturedFields.Length; i < count; i++) { ilgen.EmitLdarg(i + 1); TypeWrapper Ui = interfaceMethod.GetParameters()[i]; TypeWrapper Ti = instantiatedMethodType.GetArgTypes()[i]; TypeWrapper Aj = implParameters[i + k]; if (Ui == PrimitiveTypeWrapper.BYTE) { ilgen.Emit(OpCodes.Conv_I1); } if (Ti != Ui) { if (Ti.IsGhost) { Ti.EmitConvStackTypeToSignatureType(ilgen, Ui); } else if (Ui.IsGhost) { Ui.EmitConvSignatureTypeToStackType(ilgen); } else { Ti.EmitCheckcast(ilgen); } } if (Ti != Aj) { if (Ti.IsPrimitive && !Aj.IsPrimitive) { Boxer.EmitBox(ilgen, Ti); } else if (!Ti.IsPrimitive && Aj.IsPrimitive) { TypeWrapper primitive = GetPrimitiveFromWrapper(Ti); Boxer.EmitUnbox(ilgen, primitive, false); if (primitive == PrimitiveTypeWrapper.BYTE) { ilgen.Emit(OpCodes.Conv_I1); } } else if (Aj == PrimitiveTypeWrapper.LONG) { ilgen.Emit(OpCodes.Conv_I8); } else if (Aj == PrimitiveTypeWrapper.FLOAT) { ilgen.Emit(OpCodes.Conv_R4); } else if (Aj == PrimitiveTypeWrapper.DOUBLE) { ilgen.Emit(OpCodes.Conv_R8); } } } switch (implMethod.Kind) { case ClassFile.RefKind.invokeVirtual: case ClassFile.RefKind.invokeInterface: ((MethodWrapper)implMethod.Member).EmitCallvirt(ilgen); break; case ClassFile.RefKind.newInvokeSpecial: ((MethodWrapper)implMethod.Member).EmitNewobj(ilgen); break; case ClassFile.RefKind.invokeStatic: case ClassFile.RefKind.invokeSpecial: ((MethodWrapper)implMethod.Member).EmitCall(ilgen); break; default: throw new InvalidOperationException(); } TypeWrapper Ru = interfaceMethod.ReturnType; TypeWrapper Ra = GetImplReturnType(implMethod); TypeWrapper Rt = instantiatedMethodType.GetRetType(); if (Ra == PrimitiveTypeWrapper.BYTE) { ilgen.Emit(OpCodes.Conv_I1); } if (Ra != Ru) { if (Ru == PrimitiveTypeWrapper.VOID) { ilgen.Emit(OpCodes.Pop); } else if (Ra.IsGhost) { Ra.EmitConvSignatureTypeToStackType(ilgen); } else if (Ru.IsGhost) { Ru.EmitConvStackTypeToSignatureType(ilgen, Ra); } } if (Ra != Rt) { if (Rt.IsPrimitive) { if (Rt == PrimitiveTypeWrapper.VOID) { // already popped } else if (!Ra.IsPrimitive) { TypeWrapper primitive = GetPrimitiveFromWrapper(Ra); if (primitive != null) { Boxer.EmitUnbox(ilgen, primitive, false); } else { // If Q is not a primitive wrapper, cast Q to the base Wrapper(S); for example Number for numeric types EmitConvertingUnbox(ilgen, Rt); } } else if (Rt == PrimitiveTypeWrapper.LONG) { ilgen.Emit(OpCodes.Conv_I8); } else if (Rt == PrimitiveTypeWrapper.FLOAT) { ilgen.Emit(OpCodes.Conv_R4); } else if (Rt == PrimitiveTypeWrapper.DOUBLE) { ilgen.Emit(OpCodes.Conv_R8); } } else if (Ra.IsPrimitive) { Boxer.EmitBox(ilgen, GetPrimitiveFromWrapper(Rt)); } else { Rt.EmitCheckcast(ilgen); } } ilgen.EmitTailCallPrevention(); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); }
protected override void EmitSetImpl(CodeEmitter ilgen) { ilgen.Emit(OpCodes.Call, setter); }
private bool EmitImpl(DynamicTypeWrapper.FinishContext context, ClassFile classFile, ClassFile.ConstantPoolItemInvokeDynamic cpi, ClassFile.BootstrapMethod bsm, CodeEmitter ilgen) { if (HasUnloadable(cpi)) { Fail("cpi has unloadable"); return(false); } bool serializable = false; TypeWrapper[] markers = TypeWrapper.EmptyArray; ClassFile.ConstantPoolItemMethodType[] bridges = null; if (bsm.ArgumentCount > 3) { AltFlags flags = (AltFlags)classFile.GetConstantPoolConstantInteger(bsm.GetArgument(3)); serializable = (flags & AltFlags.Serializable) != 0; int argpos = 4; if ((flags & AltFlags.Markers) != 0) { markers = new TypeWrapper[classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++))]; for (int i = 0; i < markers.Length; i++) { if ((markers[i] = classFile.GetConstantPoolClassType(bsm.GetArgument(argpos++))).IsUnloadable) { Fail("unloadable marker"); return(false); } } } if ((flags & AltFlags.Bridges) != 0) { bridges = new ClassFile.ConstantPoolItemMethodType[classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++))]; for (int i = 0; i < bridges.Length; i++) { bridges[i] = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(argpos++)); if (HasUnloadable(bridges[i])) { Fail("unloadable bridge"); return(false); } } } } ClassFile.ConstantPoolItemMethodType samMethodType = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(0)); ClassFile.ConstantPoolItemMethodHandle implMethod = classFile.GetConstantPoolConstantMethodHandle(bsm.GetArgument(1)); ClassFile.ConstantPoolItemMethodType instantiatedMethodType = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(2)); if (HasUnloadable(samMethodType) || HasUnloadable((ClassFile.ConstantPoolItemMI)implMethod.MemberConstantPoolItem) || HasUnloadable(instantiatedMethodType)) { Fail("bsm args has unloadable"); return(false); } TypeWrapper interfaceType = cpi.GetRetType(); MethodWrapper[] methodList; if (!CheckSupportedInterfaces(context.TypeWrapper, interfaceType, markers, bridges, out methodList)) { Fail("unsupported interface"); return(false); } if (serializable && Array.Exists(methodList, delegate(MethodWrapper mw) { return(mw.Name == "writeReplace" && mw.Signature == "()Ljava.lang.Object;"); })) { Fail("writeReplace"); return(false); } if (!IsSupportedImplMethod(implMethod, context.TypeWrapper, cpi.GetArgTypes(), instantiatedMethodType)) { Fail("implMethod " + implMethod.MemberConstantPoolItem.Class + "::" + implMethod.MemberConstantPoolItem.Name + implMethod.MemberConstantPoolItem.Signature); return(false); } TypeWrapper[] implParameters = GetImplParameters(implMethod); CheckConstraints(instantiatedMethodType, samMethodType, cpi.GetArgTypes(), implParameters); if (bridges != null) { foreach (ClassFile.ConstantPoolItemMethodType bridge in bridges) { if (bridge.Signature == samMethodType.Signature) { Fail("bridge signature matches sam"); return(false); } if (!CheckConstraints(instantiatedMethodType, bridge, cpi.GetArgTypes(), implParameters)) { Fail("bridge constraints"); return(false); } } } if (instantiatedMethodType.GetRetType() != PrimitiveTypeWrapper.VOID) { TypeWrapper Rt = instantiatedMethodType.GetRetType(); TypeWrapper Ra = GetImplReturnType(implMethod); if (Ra == PrimitiveTypeWrapper.VOID || !IsAdaptable(Ra, Rt, true)) { Fail("The return type Rt is void, or the return type Ra is not void and is adaptable to Rt"); return(false); } } MethodWrapper interfaceMethod = null; List <MethodWrapper> methods = new List <MethodWrapper>(); foreach (MethodWrapper mw in methodList) { if (mw.Name == cpi.Name && mw.Signature == samMethodType.Signature) { interfaceMethod = mw; methods.Add(mw); } else if (mw.IsAbstract && !IsObjectMethod(mw)) { methods.Add(mw); } } if (interfaceMethod == null || !interfaceMethod.IsAbstract || IsObjectMethod(interfaceMethod) || !MatchSignatures(interfaceMethod, samMethodType)) { Fail("interfaceMethod"); return(false); } TypeBuilder tb = context.DefineAnonymousClass(); // we're not implementing the interfaces recursively (because we don't care about .NET Compact anymore), // but should we decide to do that, we'd need to somehow communicate to AnonymousTypeWrapper what the 'real' interface is tb.AddInterfaceImplementation(interfaceType.TypeAsBaseType); if (serializable && Array.IndexOf(markers, CoreClasses.java.io.Serializable.Wrapper) == -1) { tb.AddInterfaceImplementation(CoreClasses.java.io.Serializable.Wrapper.TypeAsBaseType); } foreach (TypeWrapper marker in markers) { tb.AddInterfaceImplementation(marker.TypeAsBaseType); } ctor = CreateConstructorAndDispatch(context, cpi, tb, methods, implParameters, samMethodType, implMethod, instantiatedMethodType, serializable); AddDefaultInterfaceMethods(context, methodList, tb); return(true); }
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 abstract void Emit(CodeEmitter ilgen);
internal sealed override void EmitNewobj(CodeEmitter ilgen) { AssertLinked(); PreEmit(ilgen); NewobjImpl(ilgen); if(DeclaringType.IsNonPrimitiveValueType) { DeclaringType.EmitBox(ilgen); } }
internal override void Emit(CodeEmitter ilgen) { base.Emit(ilgen); ilgen.Emit(OpCodes.Ldobj, Type); }
internal override void EmitCallvirt(CodeEmitter ilgen) { ilgen.Emit(SimpleOpCodeToOpCode(callvirt), (MethodInfo)GetMethod()); }
internal override void Emit(CodeEmitter ilgen) { ilgen.Emit(OpCodes.Ldnull); }
protected override void CallImpl(CodeEmitter ilgen) { ilgen.Emit(OpCodes.Call, (ConstructorInfo)GetMethod()); }
internal override void Emit(CodeEmitter ilgen) { switch (l) { case -1: ilgen.Emit(OpCodes.Ldc_I4_M1); ilgen.Emit(OpCodes.Conv_I8); break; case 0: ilgen.Emit(OpCodes.Ldc_I4_0); ilgen.Emit(OpCodes.Conv_I8); break; case 1: ilgen.Emit(OpCodes.Ldc_I4_1); ilgen.Emit(OpCodes.Conv_I8); break; case 2: ilgen.Emit(OpCodes.Ldc_I4_2); ilgen.Emit(OpCodes.Conv_I8); break; case 3: ilgen.Emit(OpCodes.Ldc_I4_3); ilgen.Emit(OpCodes.Conv_I8); break; case 4: ilgen.Emit(OpCodes.Ldc_I4_4); ilgen.Emit(OpCodes.Conv_I8); break; case 5: ilgen.Emit(OpCodes.Ldc_I4_5); ilgen.Emit(OpCodes.Conv_I8); break; case 6: ilgen.Emit(OpCodes.Ldc_I4_6); ilgen.Emit(OpCodes.Conv_I8); break; case 7: ilgen.Emit(OpCodes.Ldc_I4_7); ilgen.Emit(OpCodes.Conv_I8); break; case 8: ilgen.Emit(OpCodes.Ldc_I4_8); ilgen.Emit(OpCodes.Conv_I8); break; default: if (l >= -2147483648L && l <= 4294967295L) { if (l >= -128 && l <= 127) { ilgen.Emit(OpCodes.Ldc_I4_S, (sbyte)l); } else { ilgen.Emit(OpCodes.Ldc_I4, (int)l); } if (l < 0) { ilgen.Emit(OpCodes.Conv_I8); } else { ilgen.Emit(OpCodes.Conv_U8); } } else { ilgen.Emit(OpCodes.Ldc_I8, l); } break; } }
protected override void CallvirtImpl(CodeEmitter ilgen) { ilgen.Emit(OpCodes.Callvirt, stubVirtual); }
internal override void Emit(CodeEmitter ilgen) { ilgen.Emit(OpCodes.Ldstr, str); }
protected override void NewobjImpl(CodeEmitter ilgen) { ilgen.Emit(OpCodes.Newobj, stub); }
internal override void Emit(CodeEmitter ilgen) { ilgen.Emit(OpCodes.Isinst, this.Type); ilgen.Emit(OpCodes.Ldnull); ilgen.Emit(OpCodes.Cgt_Un); }
protected abstract void EmitSetImpl(CodeEmitter ilgen);
internal abstract void EmitBcc(CodeEmitter ilgen, Comparison comp, CodeEmitterLabel label);
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 sealed override void EmitBcc(CodeEmitter ilgen, Comparison comp, CodeEmitterLabel label) { ilgen.EmitBcc(comp, label); }
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 override void Emit(CodeEmitter ilgen) { Type.EmitClassLiteral(ilgen); }
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)); }
internal override void Emit(CodeEmitter ilgen) { ilgen.Emit(OpCodes.Ldelem_I1); }
internal static void EmitThrowNoSuchMethodErrorForSetter(CodeEmitter ilgen, 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); ilgen.Emit(OpCodes.Pop); if (!isStatic) { ilgen.Emit(OpCodes.Pop); } }
internal override void Emit(CodeEmitter ilgen) { base.Emit(ilgen); ilgen.Emit(OpCodes.Conv_I8); }
protected override void EmitSetImpl(CodeEmitter ilgen) { MethodInfo setter = property.GetSetMethod(true); if (setter == null) { if(this.IsFinal) { ilgen.Emit(OpCodes.Pop); if(!this.IsStatic) { ilgen.Emit(OpCodes.Pop); } } else { DynamicPropertyFieldWrapper.EmitThrowNoSuchMethodErrorForSetter(ilgen, this.IsStatic); } } else if(setter.IsStatic) { ilgen.Emit(OpCodes.Call, setter); } else { ilgen.Emit(OpCodes.Callvirt, setter); } }
internal virtual void EmitNewobj(CodeEmitter ilgen) { throw new InvalidOperationException(); }
protected override void EmitSetImpl(CodeEmitter ilgen) { // when constant static final fields are updated, the JIT normally doesn't see that (because the // constant value is inlined), so we emulate that behavior by emitting a Pop ilgen.Emit(OpCodes.Pop); }
private static bool Class_desiredAssertionStatus(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { TypeWrapper classLiteral = ilgen.PeekLazyClassLiteral(); if (classLiteral != null && classLiteral.GetClassLoader().RemoveAsserts) { ilgen.LazyEmitPop(); ilgen.LazyEmitLdc_I4(0); return(true); } else { return(false); } }
internal virtual void EmitCallvirtReflect(CodeEmitter ilgen) { EmitCallvirt(ilgen); }
private static bool Float_floatToRawIntBits(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { EmitConversion(ilgen, typeofFloatConverter, "ToInt"); return(true); }
protected override void CallvirtImpl(CodeEmitter ilgen) { ResolveGhostMethod(); ilgen.Emit(OpCodes.Call, ghostMethod); }
internal EmitIntrinsicContext(MethodWrapper method, DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, CodeInfo ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { this.Method = method; this.Context = context; this.Emitter = ilgen; this.ma = ma; this.OpcodeIndex = opcodeIndex; this.Caller = caller; this.ClassFile = classFile; this.Code = code; this.Flags = flags; }