Removed EmitHelper class and moved its methods into CodeEmitter.

This commit is contained in:
jfrijters 2009-08-31 05:02:34 +00:00
Родитель db9c796794
Коммит b9ceecc098
8 изменённых файлов: 116 добавлений и 121 удалений

Просмотреть файл

@ -135,7 +135,7 @@ namespace IKVM.Internal
MethodBuilder mb = typeBuilder.DefineMethod(mw.Name, MethodAttributes.FamORAssem | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.CheckAccessOnOverride, mw.ReturnTypeForDefineMethod, mw.GetParametersForDefineMethod());
AttributeHelper.HideFromJava(mb);
CodeEmitter ilgen = CodeEmitter.Create(mb);
EmitHelper.Throw(ilgen, "java.lang.AbstractMethodError");
ilgen.EmitThrow("java.lang.AbstractMethodError");
}
typeBuilder.CreateType();
}
@ -831,8 +831,8 @@ namespace IKVM.Internal
ilgen.MarkLabel(label);
}
// we need to do a null check (null fails all the isinst checks)
EmitHelper.NullCheck(ilgen);
EmitHelper.Throw(ilgen, "java.lang.IncompatibleClassChangeError", Name);
ilgen.EmitNullCheck();
ilgen.EmitThrow("java.lang.IncompatibleClassChangeError", Name);
ilgen.MarkLabel(end);
ilgen.Emit(OpCodes.Ret);
}

Просмотреть файл

@ -1407,7 +1407,7 @@ namespace IKVM.Internal
else if(!m.NoNullCheck)
{
ilgen.Emit(OpCodes.Ldarg_0);
EmitHelper.NullCheck(ilgen);
ilgen.EmitNullCheck();
}
if(mbCore != null &&
(m.@override == null || m.redirect != null) &&
@ -1967,7 +1967,7 @@ namespace IKVM.Internal
}
}
ilgen.Emit(OpCodes.Ldarg_0);
EmitHelper.Castclass(ilgen, shadowType);
ilgen.EmitCastclass(shadowType);
ilgen.Emit(OpCodes.Ret);
if(hasfail)

Просмотреть файл

@ -66,8 +66,12 @@ namespace IKVM.Internal
}
}
class CodeEmitter
sealed class CodeEmitter
{
private static readonly MethodInfo objectToString = typeof(object).GetMethod("ToString", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null);
private static readonly MethodInfo verboseCastFailure = JVM.SafeGetEnvironmentVariable("IKVM_VERBOSE_CAST") == null ? null : ByteCodeHelperMethods.VerboseCastFailure;
private static readonly MethodInfo getTypeHandle = typeof(Type).GetMethod("GetTypeHandle", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(object) }, null);
private static readonly MethodInfo get_Value = typeof(RuntimeTypeHandle).GetMethod("get_Value", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null);
private ILGenerator ilgen_real;
#if !IKVM_REF_EMIT
private int offset;
@ -648,6 +652,82 @@ namespace IKVM.Internal
}
#endif // STATIC_COMPILER
internal void EmitThrow(string dottedClassName)
{
TypeWrapper exception = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName(dottedClassName);
MethodWrapper mw = exception.GetMethodWrapper("<init>", "()V", false);
mw.Link();
mw.EmitNewobj(this);
Emit(OpCodes.Throw);
}
internal void EmitThrow(string dottedClassName, string message)
{
TypeWrapper exception = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName(dottedClassName);
Emit(OpCodes.Ldstr, message);
MethodWrapper mw = exception.GetMethodWrapper("<init>", "(Ljava.lang.String;)V", false);
mw.Link();
mw.EmitNewobj(this);
Emit(OpCodes.Throw);
}
internal void EmitNullCheck()
{
// I think this is the most efficient way to generate a NullReferenceException if the reference is null
Emit(OpCodes.Ldvirtftn, objectToString);
Emit(OpCodes.Pop);
}
internal void EmitCastclass(Type type)
{
if (verboseCastFailure != null)
{
LocalBuilder lb = DeclareLocal(typeof(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);
}
}
// This is basically the same as Castclass, except that it
// throws an IncompatibleClassChangeError on failure.
internal void EmitAssertType(Type type)
{
LocalBuilder lb = DeclareLocal(typeof(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);
}
internal void EmitGetTypeHandleValue()
{
Emit(OpCodes.Call, getTypeHandle);
LocalBuilder local = DeclareLocal(typeof(RuntimeTypeHandle));
Emit(OpCodes.Stloc, local);
Emit(OpCodes.Ldloca, local);
Emit(OpCodes.Call, get_Value);
}
internal void LazyEmitPop()
{
Expr exp = PeekStack();

Просмотреть файл

@ -1644,7 +1644,7 @@ namespace IKVM.Internal
CodeEmitterLabel label = ilgen.DefineLabel();
ilgen.Emit(OpCodes.Ldc_I4_0);
ilgen.Emit(OpCodes.Brtrue_S, label);
EmitHelper.Throw(ilgen, "java.lang.NoSuchMethodError");
ilgen.EmitThrow("java.lang.NoSuchMethodError");
ilgen.MarkLabel(label);
if (!isStatic)
{
@ -1686,7 +1686,7 @@ namespace IKVM.Internal
CodeEmitterLabel label = ilgen.DefineLabel();
ilgen.Emit(OpCodes.Ldc_I4_0);
ilgen.Emit(OpCodes.Brtrue_S, label);
EmitHelper.Throw(ilgen, "java.lang.NoSuchMethodError");
ilgen.EmitThrow("java.lang.NoSuchMethodError");
ilgen.MarkLabel(label);
ilgen.Emit(OpCodes.Pop);
if (!isStatic)

Просмотреть файл

@ -48,91 +48,6 @@ namespace IKVM.Internal
}
}
static class EmitHelper
{
private static MethodInfo objectToString = typeof(object).GetMethod("ToString", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null);
private static MethodInfo verboseCastFailure = JVM.SafeGetEnvironmentVariable("IKVM_VERBOSE_CAST") == null ? null : ByteCodeHelperMethods.VerboseCastFailure;
private static MethodInfo getTypeHandle = typeof(Type).GetMethod("GetTypeHandle", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(object) }, null);
private static MethodInfo get_Value = typeof(RuntimeTypeHandle).GetMethod("get_Value", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null);
internal static void Throw(CodeEmitter ilgen, string dottedClassName)
{
TypeWrapper exception = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName(dottedClassName);
MethodWrapper mw = exception.GetMethodWrapper("<init>", "()V", false);
mw.Link();
mw.EmitNewobj(ilgen);
ilgen.Emit(OpCodes.Throw);
}
internal static void Throw(CodeEmitter ilgen, string dottedClassName, string message)
{
TypeWrapper exception = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName(dottedClassName);
ilgen.Emit(OpCodes.Ldstr, message);
MethodWrapper mw = exception.GetMethodWrapper("<init>", "(Ljava.lang.String;)V", false);
mw.Link();
mw.EmitNewobj(ilgen);
ilgen.Emit(OpCodes.Throw);
}
internal static void NullCheck(CodeEmitter ilgen)
{
// I think this is the most efficient way to generate a NullReferenceException if the
// reference is null
ilgen.Emit(OpCodes.Ldvirtftn, objectToString);
ilgen.Emit(OpCodes.Pop);
}
internal static void Castclass(CodeEmitter ilgen, Type type)
{
if(verboseCastFailure != null)
{
LocalBuilder lb = ilgen.DeclareLocal(typeof(object));
ilgen.Emit(OpCodes.Stloc, lb);
ilgen.Emit(OpCodes.Ldloc, lb);
ilgen.Emit(OpCodes.Isinst, type);
ilgen.Emit(OpCodes.Dup);
CodeEmitterLabel ok = ilgen.DefineLabel();
ilgen.Emit(OpCodes.Brtrue_S, ok);
ilgen.Emit(OpCodes.Ldloc, lb);
ilgen.Emit(OpCodes.Brfalse_S, ok); // handle null
ilgen.Emit(OpCodes.Ldtoken, type);
ilgen.Emit(OpCodes.Ldloc, lb);
ilgen.Emit(OpCodes.Call, verboseCastFailure);
ilgen.MarkLabel(ok);
}
else
{
ilgen.Emit(OpCodes.Castclass, type);
}
}
// This is basically the same as Castclass, except that it
// throws an IncompatibleClassChangeError on failure.
internal static void EmitAssertType(CodeEmitter ilgen, Type type)
{
LocalBuilder lb = ilgen.DeclareLocal(typeof(object));
ilgen.Emit(OpCodes.Stloc, lb);
ilgen.Emit(OpCodes.Ldloc, lb);
ilgen.Emit(OpCodes.Isinst, type);
ilgen.Emit(OpCodes.Dup);
CodeEmitterLabel ok = ilgen.DefineLabel();
ilgen.Emit(OpCodes.Brtrue_S, ok);
ilgen.Emit(OpCodes.Ldloc, lb);
ilgen.Emit(OpCodes.Brfalse_S, ok); // handle null
EmitHelper.Throw(ilgen, "java.lang.IncompatibleClassChangeError");
ilgen.MarkLabel(ok);
}
internal static void GetTypeHandleValue(CodeEmitter ilgen)
{
ilgen.Emit(OpCodes.Call, getTypeHandle);
LocalBuilder local = ilgen.DeclareLocal(typeof(RuntimeTypeHandle));
ilgen.Emit(OpCodes.Stloc, local);
ilgen.Emit(OpCodes.Ldloca, local);
ilgen.Emit(OpCodes.Call, get_Value);
}
}
static class AttributeHelper
{
private static CustomAttributeBuilder hideFromJavaAttribute;
@ -3278,7 +3193,7 @@ namespace IKVM.Internal
{
MethodBuilder mb = typeBuilder.DefineMethod(mangledName, MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final, ifmethod.ReturnTypeForDefineMethod, ifmethod.GetParametersForDefineMethod());
AttributeHelper.HideFromJava(mb);
EmitHelper.Throw(CodeEmitter.Create(mb), "java.lang.LinkageError", wrapper.Name + "." + ifmethod.Name + ifmethod.Signature);
CodeEmitter.Create(mb).EmitThrow("java.lang.LinkageError", wrapper.Name + "." + ifmethod.Name + ifmethod.Signature);
typeBuilder.DefineMethodOverride(mb, (MethodInfo)ifmethod.GetMethod());
return;
}
@ -3295,7 +3210,7 @@ namespace IKVM.Internal
// methods. Sigh! So I have to use private methods and mangle the name
MethodBuilder mb = typeBuilder.DefineMethod(mangledName, MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final, ifmethod.ReturnTypeForDefineMethod, ifmethod.GetParametersForDefineMethod());
AttributeHelper.HideFromJava(mb);
EmitHelper.Throw(CodeEmitter.Create(mb), "java.lang.IllegalAccessError", wrapper.Name + "." + ifmethod.Name + ifmethod.Signature);
CodeEmitter.Create(mb).EmitThrow("java.lang.IllegalAccessError", wrapper.Name + "." + ifmethod.Name + ifmethod.Signature);
typeBuilder.DefineMethodOverride(mb, (MethodInfo)ifmethod.GetMethod());
wrapper.HasIncompleteInterfaceImplementation = true;
}
@ -3341,7 +3256,7 @@ namespace IKVM.Internal
// so we have to create a stub method that throws an AbstractMethodError
MethodBuilder mb = typeBuilder.DefineMethod(mangledName, MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final, ifmethod.ReturnTypeForDefineMethod, ifmethod.GetParametersForDefineMethod());
AttributeHelper.HideFromJava(mb);
EmitHelper.Throw(CodeEmitter.Create(mb), "java.lang.AbstractMethodError", wrapper.Name + "." + ifmethod.Name + ifmethod.Signature);
CodeEmitter.Create(mb).EmitThrow("java.lang.AbstractMethodError", wrapper.Name + "." + ifmethod.Name + ifmethod.Signature);
typeBuilder.DefineMethodOverride(mb, (MethodInfo)ifmethod.GetMethod());
wrapper.HasIncompleteInterfaceImplementation = true;
}
@ -3453,7 +3368,7 @@ namespace IKVM.Internal
// for any interface reference
else if(IsInterfaceOrInterfaceArray && (sourceType == null || sourceType.IsUnloadable || !sourceType.IsAssignableTo(this)))
{
EmitHelper.EmitAssertType(ilgen, TypeAsTBD);
ilgen.EmitAssertType(TypeAsTBD);
Profiler.Count("InterfaceDownCast");
}
else if(IsNonPrimitiveValueType)
@ -3497,7 +3412,7 @@ namespace IKVM.Internal
}
else
{
EmitHelper.Castclass(ilgen, TypeAsTBD);
ilgen.EmitCastclass(TypeAsTBD);
}
}
@ -6421,7 +6336,7 @@ namespace IKVM.Internal
}
else if(!wrapper.IsAbstract)
{
EmitHelper.Throw(CodeEmitter.Create(mb), "java.lang.AbstractMethodError", wrapper.Name + "." + methods[index].Name + methods[index].Signature);
CodeEmitter.Create(mb).EmitThrow("java.lang.AbstractMethodError", wrapper.Name + "." + methods[index].Name + methods[index].Signature);
}
return mb;
}
@ -7464,7 +7379,7 @@ namespace IKVM.Internal
typeBuilder.DefineMethodOverride(mb, mi);
}
AttributeHelper.HideFromJava(mb);
EmitHelper.Throw(CodeEmitter.Create(mb), "java.lang.AbstractMethodError", mw.DeclaringType.Name + "." + mw.Name + mw.Signature);
CodeEmitter.Create(mb).EmitThrow("java.lang.AbstractMethodError", mw.DeclaringType.Name + "." + mw.Name + mw.Signature);
}
}
}
@ -7524,7 +7439,7 @@ namespace IKVM.Internal
{
CodeEmitter ilGenerator = CodeEmitter.Create((MethodBuilder)mb);
TraceHelper.EmitMethodTrace(ilGenerator, classFile.Name + "." + m.Name + m.Signature);
EmitHelper.Throw(ilGenerator, "java.lang.AbstractMethodError", classFile.Name + "." + m.Name + m.Signature);
ilGenerator.EmitThrow("java.lang.AbstractMethodError", classFile.Name + "." + m.Name + m.Signature);
}
}
else if (m.IsNative)
@ -7609,7 +7524,7 @@ namespace IKVM.Internal
{
// since NoJniStubs can only be set when we're statically compiling, it is safe to use the "compiler" trace switch
Tracer.Warning(Tracer.Compiler, "Native method not implemented: {0}.{1}.{2}", classFile.Name, m.Name, m.Signature);
EmitHelper.Throw(ilGenerator, "java.lang.UnsatisfiedLinkError", "Native method not implemented (compiled with -nojni): " + classFile.Name + "." + m.Name + m.Signature);
ilGenerator.EmitThrow("java.lang.UnsatisfiedLinkError", "Native method not implemented (compiled with -nojni): " + classFile.Name + "." + m.Name + m.Signature);
}
else
{
@ -8480,7 +8395,7 @@ namespace IKVM.Internal
}
MethodAttributes attr = MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Private;
MethodBuilder m = typeBuilder.DefineMethod("__<unsupported>" + mb.DeclaringType.FullName + "/" + mb.Name, attr, ((MethodInfo)mb).ReturnType, parameterTypes);
EmitHelper.Throw(CodeEmitter.Create(m), "java.lang.AbstractMethodError", "Method " + mb.DeclaringType.FullName + "." + mb.Name + " is unsupported by IKVM.");
CodeEmitter.Create(m).EmitThrow("java.lang.AbstractMethodError", "Method " + mb.DeclaringType.FullName + "." + mb.Name + " is unsupported by IKVM.");
typeBuilder.DefineMethodOverride(m, (MethodInfo)mb);
}
@ -12005,9 +11920,9 @@ namespace IKVM.Internal
ilgen.Emit(OpCodes.Brtrue_S, label1);
CodeEmitterLabel label2 = ilgen.DefineLabel();
ilgen.Emit(OpCodes.Brfalse_S, label2);
EmitHelper.Throw(ilgen, "java.lang.CloneNotSupportedException");
ilgen.EmitThrow("java.lang.CloneNotSupportedException");
ilgen.MarkLabel(label2);
EmitHelper.Throw(ilgen, "java.lang.NullPointerException");
ilgen.EmitThrow("java.lang.NullPointerException");
ilgen.MarkLabel(label1);
ilgen.Emit(OpCodes.Call, typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null));
}
@ -12661,7 +12576,7 @@ namespace IKVM.Internal
return;
}
}
EmitHelper.Castclass(ilgen, type);
ilgen.EmitCastclass(type);
}
internal override void Finish()

Просмотреть файл

@ -876,7 +876,7 @@ class Compiler
clazz.HasVerifyError = true;
// because in Java the method is only verified if it is actually called,
// we generate code here to throw the VerificationError
EmitHelper.Throw(ilGenerator, "java.lang.VerifyError", x.Message);
ilGenerator.EmitThrow("java.lang.VerifyError", x.Message);
return;
}
catch(ClassFormatError x)
@ -886,7 +886,7 @@ class Compiler
#endif
Tracer.Error(Tracer.Verifier, x.ToString());
clazz.HasClassFormatError = true;
EmitHelper.Throw(ilGenerator, "java.lang.ClassFormatError", x.Message);
ilGenerator.EmitThrow("java.lang.ClassFormatError", x.Message);
return;
}
Profiler.Enter("Compile");
@ -2961,8 +2961,8 @@ class Compiler
break;
case NormalizedByteCode.__intrinsic_gettypehandlevalue:
ilGenerator.Emit(OpCodes.Dup);
EmitHelper.NullCheck(ilGenerator);
EmitHelper.GetTypeHandleValue(ilGenerator);
ilGenerator.EmitNullCheck();
ilGenerator.EmitGetTypeHandleValue();
break;
case NormalizedByteCode.__static_error:
{
@ -3149,7 +3149,7 @@ class Compiler
TypeWrapper tw = ma.GetStackTypeWrapper(instructionIndex, args.Length - 1 - i);
if(tw.IsUnloadable || (args[i].IsInterfaceOrInterfaceArray && !tw.IsAssignableTo(args[i])))
{
EmitHelper.EmitAssertType(ilGenerator, args[i].TypeAsTBD);
ilGenerator.EmitAssertType(args[i].TypeAsTBD);
Profiler.Count("InterfaceDownCast");
}
}

Просмотреть файл

@ -124,7 +124,7 @@ namespace IKVM.Internal
if (code[opcodeIndex + 1].NormalizedOpCode == NormalizedByteCode.__pop)
{
ilgen.Emit(OpCodes.Dup);
EmitHelper.NullCheck(ilgen);
ilgen.EmitNullCheck();
return true;
}
// this optimizes obj1.getClass() ==/!= obj2.getClass()
@ -139,8 +139,8 @@ namespace IKVM.Internal
{
// we can't patch the current opcode, so we have to emit the first call to GetTypeHandle here
ilgen.Emit(OpCodes.Dup);
EmitHelper.NullCheck(ilgen);
EmitHelper.GetTypeHandleValue(ilgen);
ilgen.EmitNullCheck();
ilgen.EmitGetTypeHandleValue();
code[opcodeIndex + 2].PatchOpCode(NormalizedByteCode.__intrinsic_gettypehandlevalue);
return true;
}

Просмотреть файл

@ -5859,7 +5859,7 @@ namespace IKVM.NativeCode.sun.reflect
{
// check target for null
ilgen.Emit(OpCodes.Ldarg_0);
EmitHelper.NullCheck(ilgen);
ilgen.EmitNullCheck();
}
// check args length
@ -5874,7 +5874,7 @@ namespace IKVM.NativeCode.sun.reflect
ilgen.Emit(OpCodes.Ldlen);
ilgen.Emit(OpCodes.Ldc_I4, mw.GetParameters().Length);
ilgen.Emit(OpCodes.Beq_S, argsLengthOK);
EmitHelper.Throw(ilgen, "java.lang.IllegalArgumentException");
ilgen.EmitThrow("java.lang.IllegalArgumentException");
ilgen.MarkLabel(argsLengthOK);
int thisCount = mw.IsStatic ? 0 : 1;
@ -5907,9 +5907,9 @@ namespace IKVM.NativeCode.sun.reflect
ilgen.Emit(OpCodes.Stloc, args[i]);
}
ilgen.BeginCatchBlock(typeof(InvalidCastException));
EmitHelper.Throw(ilgen, "java.lang.IllegalArgumentException");
ilgen.EmitThrow("java.lang.IllegalArgumentException");
ilgen.BeginCatchBlock(typeof(NullReferenceException));
EmitHelper.Throw(ilgen, "java.lang.IllegalArgumentException");
ilgen.EmitThrow("java.lang.IllegalArgumentException");
ilgen.EndExceptionBlock();
// this is the actual call
@ -6188,7 +6188,7 @@ namespace IKVM.NativeCode.sun.reflect
ilgen.Emit(OpCodes.Ldlen);
ilgen.Emit(OpCodes.Ldc_I4, mw.GetParameters().Length);
ilgen.Emit(OpCodes.Beq_S, argsLengthOK);
EmitHelper.Throw(ilgen, "java.lang.IllegalArgumentException");
ilgen.EmitThrow("java.lang.IllegalArgumentException");
ilgen.MarkLabel(argsLengthOK);
LocalBuilder[] args = new LocalBuilder[mw.GetParameters().Length];
@ -6209,9 +6209,9 @@ namespace IKVM.NativeCode.sun.reflect
ilgen.Emit(OpCodes.Stloc, args[i]);
}
ilgen.BeginCatchBlock(typeof(InvalidCastException));
EmitHelper.Throw(ilgen, "java.lang.IllegalArgumentException");
ilgen.EmitThrow("java.lang.IllegalArgumentException");
ilgen.BeginCatchBlock(typeof(NullReferenceException));
EmitHelper.Throw(ilgen, "java.lang.IllegalArgumentException");
ilgen.EmitThrow("java.lang.IllegalArgumentException");
ilgen.EndExceptionBlock();
// this is the actual call