예제 #1
0
        internal void LazyEmitUnboxSpecial(Type type)
        {
            BoxExpr box = PeekStack() as BoxExpr;

            if (box != null)
            {
                PopStack();
                // the unbox and lazy box cancel each other out
                PushStackMayBeNull(box.Expr);
            }
            else
            {
                // NOTE if the reference is null, we treat it as a default instance of the value type.
                Emit(OpCodes.Dup);
                CodeEmitterLabel label1 = DefineLabel();
                Emit(OpCodes.Brtrue_S, label1);
                Emit(OpCodes.Pop);
                Emit(OpCodes.Ldloc, DeclareLocal(type));
                CodeEmitterLabel label2 = DefineLabel();
                Emit(OpCodes.Br_S, label2);
                MarkLabel(label1);
                Emit(OpCodes.Unbox, type);
                Emit(OpCodes.Ldobj, type);
                MarkLabel(label2);
            }
        }
예제 #2
0
        internal void LazyEmit_ldiv()
        {
            // we need to special case dividing by -1, because the CLR div instruction
            // throws an OverflowException when dividing Int32.MinValue by -1, and
            // Java just silently overflows
            ConstLongExpr v = PeekStack() as ConstLongExpr;

            if (v != null)
            {
                if (v.l == -1)
                {
                    PopStack();
                    Emit(OpCodes.Neg);
                }
                else
                {
                    Emit(OpCodes.Div);
                }
            }
            else
            {
                Emit(OpCodes.Dup);
                Emit(OpCodes.Ldc_I4_M1);
                Emit(OpCodes.Conv_I8);
                CodeEmitterLabel label = DefineLabel();
                Emit(OpCodes.Bne_Un_S, label);
                Emit(OpCodes.Pop);
                Emit(OpCodes.Neg);
                CodeEmitterLabel label2 = DefineLabel();
                Emit(OpCodes.Br_S, label2);
                MarkLabel(label);
                Emit(OpCodes.Div);
                MarkLabel(label2);
            }
        }
예제 #3
0
        private static void AddReadResolve(DynamicTypeWrapper wrapper, TypeBuilder tb)
        {
            MethodWrapper mw = wrapper.GetMethodWrapper("readResolve", "()Ljava.lang.Object;", false);

            if (mw != null && !wrapper.IsSubTypeOf(iobjectreference))
            {
                tb.AddInterfaceImplementation(JVM.Import(typeof(IObjectReference)));
                MethodBuilder getRealObject = tb.DefineMethod("IObjectReference.GetRealObject", MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final,
                                                              Types.Object, new Type[] { JVM.Import(typeof(StreamingContext)) });
                getRealObject.SetCustomAttribute(securityCriticalAttribute);
                AttributeHelper.HideFromJava(getRealObject);
                tb.DefineMethodOverride(getRealObject, JVM.Import(typeof(IObjectReference)).GetMethod("GetRealObject"));
                CodeEmitter ilgen = CodeEmitter.Create(getRealObject);
                mw.Link();
                if (!wrapper.IsFinal)
                {
                    // readResolve is only applicable if it exists on the actual type of the object, so if we're a subclass don't call it
                    ilgen.Emit(OpCodes.Ldarg_0);
                    ilgen.Emit(OpCodes.Callvirt, Compiler.getTypeMethod);
                    ilgen.Emit(OpCodes.Ldtoken, wrapper.TypeAsBaseType);
                    ilgen.Emit(OpCodes.Call, Compiler.getTypeFromHandleMethod);
                    CodeEmitterLabel label = ilgen.DefineLabel();
                    ilgen.Emit(OpCodes.Beq_S, label);
                    ilgen.Emit(OpCodes.Ldarg_0);
                    ilgen.Emit(OpCodes.Ret);
                    ilgen.MarkLabel(label);
                }
                ilgen.Emit(OpCodes.Ldarg_0);
                mw.EmitCall(ilgen);
                ilgen.Emit(OpCodes.Ret);
                ilgen.DoEmit();
            }
        }
예제 #4
0
        internal CodeEmitterLabel DefineLabel()
        {
            CodeEmitterLabel label = new CodeEmitterLabel(ilgen_real.DefineLabel());

#if LABELCHECK
            labels.Add(label, new System.Diagnostics.StackFrame(1, true));
#endif
            return(label);
        }
예제 #5
0
        internal void MarkLabel(CodeEmitterLabel loc)
        {
            if (lazyBranch == loc)
            {
                lazyBranch = null;
            }
            LazyGen();
#if LABELCHECK
            labels.Remove(loc);
#endif
            ilgen_real.MarkLabel(loc.Label);
            loc.Offset = GetILOffset();
        }
예제 #6
0
        internal void LazyEmit_if_le_lt_ge_gt(Comparison comp, CodeEmitterLabel label)
        {
            CmpExpr cmp = PeekStack() as CmpExpr;

            if (cmp != null)
            {
                PopStack();
                cmp.EmitBcc(this, comp, label);
            }
            else
            {
                Emit(OpCodes.Ldc_I4_0);
                EmitBcc(comp, label);
            }
        }
예제 #7
0
        // This is basically the same as Castclass, except that it
        // throws an IncompatibleClassChangeError on failure.
        internal void EmitAssertType(Type type)
        {
            LocalBuilder lb = DeclareLocal(Types.Object);

            Emit(OpCodes.Stloc, lb);
            Emit(OpCodes.Ldloc, lb);
            Emit(OpCodes.Isinst, type);
            Emit(OpCodes.Dup);
            CodeEmitterLabel ok = DefineLabel();

            Emit(OpCodes.Brtrue_S, ok);
            Emit(OpCodes.Ldloc, lb);
            Emit(OpCodes.Brfalse_S, ok);                // handle null
            EmitThrow("java.lang.IncompatibleClassChangeError");
            MarkLabel(ok);
        }
예제 #8
0
        private void LazyGen()
        {
            if (lazyBranch != null)
            {
#if !STATIC_COMPILER
                offset += OpCodes.Br.Size + 4;
#endif
                ilgen_real.Emit(OpCodes.Br, lazyBranch.Label);
                lazyBranch = null;
            }
            int len = topOfStack;
            topOfStack = 0;
            for (int i = 0; i < len; i++)
            {
                stackArray[i].Emit(this);
            }
        }
예제 #9
0
        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();
        }
예제 #10
0
        private void EmitBcc(Comparison comp, CodeEmitterLabel label)
        {
            switch (comp)
            {
            case Comparison.LessOrEqual:
                Emit(OpCodes.Ble, label);
                break;

            case Comparison.LessThan:
                Emit(OpCodes.Blt, label);
                break;

            case Comparison.GreaterOrEqual:
                Emit(OpCodes.Bge, label);
                break;

            case Comparison.GreaterThan:
                Emit(OpCodes.Bgt, label);
                break;
            }
        }
예제 #11
0
        private void LazyEmit_if_ne_eq(CodeEmitterLabel label, bool brtrue)
        {
            InstanceOfExpr instanceof = PeekStack() as InstanceOfExpr;

            if (instanceof != null)
            {
                PopStack();
                Emit(OpCodes.Isinst, instanceof.Type);
            }
            else
            {
                CmpExpr cmp = PeekStack() as CmpExpr;
                if (cmp != null)
                {
                    PopStack();
                    Emit(brtrue ? OpCodes.Bne_Un : OpCodes.Beq, label);
                    return;
                }
            }
            Emit(brtrue ? OpCodes.Brtrue : OpCodes.Brfalse, label);
        }
예제 #12
0
 internal void EmitCastclass(Type type)
 {
     if (verboseCastFailure != null)
     {
         LocalBuilder lb = DeclareLocal(Types.Object);
         Emit(OpCodes.Stloc, lb);
         Emit(OpCodes.Ldloc, lb);
         Emit(OpCodes.Isinst, type);
         Emit(OpCodes.Dup);
         CodeEmitterLabel ok = DefineLabel();
         Emit(OpCodes.Brtrue_S, ok);
         Emit(OpCodes.Ldloc, lb);
         Emit(OpCodes.Brfalse_S, ok);                    // handle null
         Emit(OpCodes.Ldtoken, type);
         Emit(OpCodes.Ldloc, lb);
         Emit(OpCodes.Call, verboseCastFailure);
         MarkLabel(ok);
     }
     else
     {
         Emit(OpCodes.Castclass, type);
     }
 }
예제 #13
0
		internal void EmitBeq(CodeEmitterLabel label)
		{
			EmitOpCode(OpCodes.Beq, label);
		}
예제 #14
0
		internal CodeEmitterLabel DefineLabel()
		{
			CodeEmitterLabel label = new CodeEmitterLabel(ilgen_real.DefineLabel());
#if LABELCHECK
			labels.Add(label, new System.Diagnostics.StackFrame(1, true));
#endif
			return label;
		}
예제 #15
0
		private bool HasBranchTo(int start, int end, CodeEmitterLabel label)
		{
			for (int i = start; i < end; i++)
			{
				if (code[i].HasLabel)
				{
					if (code[i].Label == label)
					{
						return true;
					}
				}
				else if (code[i].opcode == OpCodes.Switch)
				{
					foreach (CodeEmitterLabel swlbl in code[i].Labels)
					{
						if (swlbl == label)
						{
							return true;
						}
					}
				}
			}
			return false;
		}
예제 #16
0
		private int FindLabel(CodeEmitterLabel label)
		{
			for (int i = 0; i < code.Count; i++)
			{
				if (code[i].pseudo == CodeType.Label && code[i].Label == label)
				{
					return i;
				}
			}
			throw new InvalidOperationException();
		}
예제 #17
0
 internal sealed override void EmitBcc(CodeEmitter ilgen, Comparison comp, CodeEmitterLabel label)
 {
     ilgen.EmitBcc(comp, label);
 }
예제 #18
0
		internal void Emit_if_le_lt_ge_gt(Comparison comp, CodeEmitterLabel label)
		{
			// don't change this Ldc_I4_0 to Ldc_I4(0) because the optimizer recognizes
			// only this specific pattern
			Emit(OpCodes.Ldc_I4_0);
			switch (comp)
			{
				case Comparison.LessOrEqual:
					EmitBle(label);
					break;
				case Comparison.LessThan:
					EmitBlt(label);
					break;
				case Comparison.GreaterOrEqual:
					EmitBge(label);
					break;
				case Comparison.GreaterThan:
					EmitBgt(label);
					break;
			}
		}
예제 #19
0
 internal abstract void EmitBcc(CodeEmitter ilgen, Comparison comp, CodeEmitterLabel label);
예제 #20
0
		internal void EmitBrfalse(CodeEmitterLabel label)
		{
			EmitOpCode(OpCodes.Brfalse, label);
		}
예제 #21
0
		internal void EmitBgt(CodeEmitterLabel label)
		{
			EmitOpCode(OpCodes.Bgt, label);
		}
예제 #22
0
 internal void LazyEmit_ifne(CodeEmitterLabel label)
 {
     LazyEmit_if_ne_eq(label, true);
 }
예제 #23
0
 internal void LazyEmit_ifeq(CodeEmitterLabel label)
 {
     LazyEmit_if_ne_eq(label, false);
 }
예제 #24
0
 internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label)
 {
     ilgen.EmitBrtrue(label);
 }
예제 #25
0
        internal void Emit(OpCode opcode, CodeEmitterLabel label)
        {
            int currOffset = GetILOffset();

            if (label.Offset == -1)
            {
                if (opcode.Value == OpCodes.Br.Value)
                {
                    lazyBranch = label;
                    return;
                }
            }
            else if (currOffset - label.Offset < 126)
            {
                if (opcode.Value == OpCodes.Brtrue.Value)
                {
                    opcode = OpCodes.Brtrue_S;
                }
                else if (opcode.Value == OpCodes.Brfalse.Value)
                {
                    opcode = OpCodes.Brfalse_S;
                }
                else if (opcode.Value == OpCodes.Br.Value)
                {
                    opcode = OpCodes.Br_S;
                }
                else if (opcode.Value == OpCodes.Beq.Value)
                {
                    opcode = OpCodes.Beq_S;
                }
                else if (opcode.Value == OpCodes.Bne_Un.Value)
                {
                    opcode = OpCodes.Bne_Un_S;
                }
                else if (opcode.Value == OpCodes.Ble.Value)
                {
                    opcode = OpCodes.Ble_S;
                }
                else if (opcode.Value == OpCodes.Blt.Value)
                {
                    opcode = OpCodes.Blt_S;
                }
                else if (opcode.Value == OpCodes.Bge.Value)
                {
                    opcode = OpCodes.Bge_S;
                }
                else if (opcode.Value == OpCodes.Bgt.Value)
                {
                    opcode = OpCodes.Bgt_S;
                }
            }
#if !STATIC_COMPILER
            switch (opcode.OperandType)
            {
            case OperandType.InlineBrTarget:
                offset += opcode.Size + 4;
                break;

            case OperandType.ShortInlineBrTarget:
                offset += opcode.Size + 1;
                break;

            default:
                throw new NotImplementedException();
            }
#endif
            ilgen_real.Emit(opcode, label.Label);
        }
예제 #26
0
		internal void EmitBge_Un(CodeEmitterLabel label)
		{
			EmitOpCode(OpCodes.Bge_Un, label);
		}
예제 #27
0
		internal void EmitBle(CodeEmitterLabel label)
		{
			EmitOpCode(OpCodes.Ble, label);
		}
예제 #28
0
		internal void EmitSwitch(CodeEmitterLabel[] labels)
		{
			EmitOpCode(OpCodes.Switch, labels);
		}
예제 #29
0
		internal void EmitBrtrue(CodeEmitterLabel label)
		{
			EmitOpCode(OpCodes.Brtrue, label);
		}
예제 #30
0
 internal abstract void Emit(CodeEmitter ilgen, CodeEmitterLabel label);
예제 #31
0
		internal void EmitLeave(CodeEmitterLabel label)
		{
			EmitOpCode(OpCodes.Leave, label);
		}
예제 #32
0
        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();
        }
예제 #33
0
		internal void MarkLabel(CodeEmitterLabel loc)
		{
#if LABELCHECK
			labels.Remove(loc);
#endif
			EmitPseudoOpCode(CodeType.Label, loc);
		}
예제 #34
0
		internal void Emit(OpCode opcode, CodeEmitterLabel label)
		{
			EmitOpCode(opcode, label);
		}
예제 #35
0
		internal void Emit(OpCode opcode, CodeEmitterLabel[] labels)
		{
			EmitOpCode(opcode, labels);
		}
예제 #36
0
            internal sealed override void EmitBcc(CodeEmitter ilgen, Comparison comp, CodeEmitterLabel label)
            {
                switch (comp)
                {
                case Comparison.LessOrEqual:
                    ilgen.Emit(OpCodes.Ble, label);
                    break;

                case Comparison.LessThan:
                    ilgen.Emit(OpCodes.Blt, label);
                    break;

                case Comparison.GreaterOrEqual:
                    ilgen.Emit(OpCodes.Bge_Un, label);
                    break;

                case Comparison.GreaterThan:
                    ilgen.Emit(OpCodes.Bgt_Un, label);
                    break;
                }
            }