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); } }
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); } }
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(); } }
internal CodeEmitterLabel DefineLabel() { CodeEmitterLabel label = new CodeEmitterLabel(ilgen_real.DefineLabel()); #if LABELCHECK labels.Add(label, new System.Diagnostics.StackFrame(1, true)); #endif return(label); }
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(); }
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); } }
// 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); }
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); } }
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(); }
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; } }
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); }
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); } }
internal void EmitBeq(CodeEmitterLabel label) { EmitOpCode(OpCodes.Beq, label); }
internal CodeEmitterLabel DefineLabel() { CodeEmitterLabel label = new CodeEmitterLabel(ilgen_real.DefineLabel()); #if LABELCHECK labels.Add(label, new System.Diagnostics.StackFrame(1, true)); #endif return label; }
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; }
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(); }
internal sealed override void EmitBcc(CodeEmitter ilgen, Comparison comp, CodeEmitterLabel label) { ilgen.EmitBcc(comp, label); }
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; } }
internal abstract void EmitBcc(CodeEmitter ilgen, Comparison comp, CodeEmitterLabel label);
internal void EmitBrfalse(CodeEmitterLabel label) { EmitOpCode(OpCodes.Brfalse, label); }
internal void EmitBgt(CodeEmitterLabel label) { EmitOpCode(OpCodes.Bgt, label); }
internal void LazyEmit_ifne(CodeEmitterLabel label) { LazyEmit_if_ne_eq(label, true); }
internal void LazyEmit_ifeq(CodeEmitterLabel label) { LazyEmit_if_ne_eq(label, false); }
internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label) { ilgen.EmitBrtrue(label); }
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); }
internal void EmitBge_Un(CodeEmitterLabel label) { EmitOpCode(OpCodes.Bge_Un, label); }
internal void EmitBle(CodeEmitterLabel label) { EmitOpCode(OpCodes.Ble, label); }
internal void EmitSwitch(CodeEmitterLabel[] labels) { EmitOpCode(OpCodes.Switch, labels); }
internal void EmitBrtrue(CodeEmitterLabel label) { EmitOpCode(OpCodes.Brtrue, label); }
internal abstract void Emit(CodeEmitter ilgen, CodeEmitterLabel label);
internal void EmitLeave(CodeEmitterLabel label) { EmitOpCode(OpCodes.Leave, label); }
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 void MarkLabel(CodeEmitterLabel loc) { #if LABELCHECK labels.Remove(loc); #endif EmitPseudoOpCode(CodeType.Label, loc); }
internal void Emit(OpCode opcode, CodeEmitterLabel label) { EmitOpCode(opcode, label); }
internal void Emit(OpCode opcode, CodeEmitterLabel[] labels) { EmitOpCode(opcode, labels); }
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; } }