This commit is contained in:
jfrijters 2004-03-29 10:11:33 +00:00
Родитель 91dba9e184
Коммит bc9d509e5d
2 изменённых файлов: 165 добавлений и 51 удалений

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

@ -2060,6 +2060,8 @@ class DynamicTypeWrapper : TypeWrapper
this.map = map;
}
// this method doesn't work on Mono yet, so we use a Type based approach instead
#if USE_TYPEHANDLE_EXCEPTION_MAPPING
internal override void Emit(ILGenerator ilgen)
{
ilgen.Emit(OpCodes.Ldarg_0);
@ -2097,6 +2099,40 @@ class DynamicTypeWrapper : TypeWrapper
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ret);
}
#else // USE_TYPEHANDLE_EXCEPTION_MAPPING
internal override void Emit(ILGenerator ilgen)
{
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Callvirt, typeof(Object).GetMethod("GetType"));
MethodInfo GetTypeFromHandle = typeof(Type).GetMethod("GetTypeFromHandle");
for(int i = 0; i < map.Length; i++)
{
ilgen.Emit(OpCodes.Dup);
ilgen.Emit(OpCodes.Ldtoken, Type.GetType(map[i].src));
ilgen.Emit(OpCodes.Call, GetTypeFromHandle);
ilgen.Emit(OpCodes.Ceq);
Label label = ilgen.DefineLabel();
ilgen.Emit(OpCodes.Brfalse_S, label);
ilgen.Emit(OpCodes.Pop);
if(map[i].code != null)
{
ilgen.Emit(OpCodes.Ldarg_0);
map[i].code.Emit(ilgen);
ilgen.Emit(OpCodes.Ret);
}
else
{
TypeWrapper tw = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName(map[i].dst);
tw.GetMethodWrapper(MethodDescriptor.FromNameSig(tw.GetClassLoader(), "<init>", "()V"), false).EmitNewobj.Emit(ilgen);
ilgen.Emit(OpCodes.Ret);
}
ilgen.MarkLabel(label);
}
ilgen.Emit(OpCodes.Pop);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ret);
}
#endif // USE_TYPEHANDLE_EXCEPTION_MAPPING
}
internal static void LoadNativeMethods(MapXml.Root map)

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

@ -538,6 +538,7 @@ class Compiler
{
// NOTE Stub gets used for both the push stub (inside the exception block) as well as the pop stub (outside the block)
internal Label Stub;
internal Label TargetLabel;
internal bool ContentOnStack;
internal readonly int TargetPC;
internal DupHelper dh;
@ -689,6 +690,7 @@ class Compiler
{
if(args[i].IsUnloadable)
{
Profiler.Count("EmitDynamicCast");
ilGenerator.Emit(OpCodes.Ldarg, (ushort)(i + (m.IsStatic ? 0 : 1)));
ilGenerator.Emit(OpCodes.Ldtoken, clazz.TypeAsTBD);
ilGenerator.Emit(OpCodes.Ldstr, args[i].Name);
@ -724,20 +726,24 @@ class Compiler
ilGenerator.Emit(OpCodes.Stloc, monitor);
ilGenerator.Emit(OpCodes.Call, monitorEnterMethod);
ilGenerator.BeginExceptionBlock();
c.Compile(new Block(c, 0, int.MaxValue, -1, exits));
Block b = new Block(c, 0, int.MaxValue, -1, exits, true);
c.Compile(b);
b.Leave();
ilGenerator.BeginFinallyBlock();
ilGenerator.Emit(OpCodes.Ldloc, monitor);
ilGenerator.Emit(OpCodes.Call, monitorExitMethod);
ilGenerator.EndExceptionBlock();
foreach(ReturnCookie rc in exits)
{
rc.EmitRet(ilGenerator);
}
b.LeaveStubs(new Block(c, 0, int.MaxValue, -1, null, false));
}
else
{
c.Compile(new Block(c, 0, int.MaxValue, -1, null));
Block b = new Block(c, 0, int.MaxValue, -1, null, false);
c.Compile(b);
b.Leave();
}
// HACK because of the bogus Leave instruction that Reflection.Emit generates, this location
// sometimes appears reachable (it isn't), so we emit a bogus branch to keep the verifier happy.
ilGenerator.Emit(OpCodes.Br_S, (sbyte)-2);
Profiler.Leave("Compile");
}
@ -747,11 +753,12 @@ class Compiler
private ILGenerator ilgen;
private int begin;
private int end;
private ArrayList exits;
private int exceptionIndex;
private ArrayList exits;
private bool nested;
private object[] labels;
internal Block(Compiler compiler, int begin, int end, int exceptionIndex, ArrayList exits)
internal Block(Compiler compiler, int begin, int end, int exceptionIndex, ArrayList exits, bool nested)
{
this.compiler = compiler;
this.ilgen = compiler.ilGenerator;
@ -759,6 +766,7 @@ class Compiler
this.end = end;
this.exceptionIndex = exceptionIndex;
this.exits = exits;
this.nested = nested;
labels = new object[compiler.m.Instructions.Length];
}
@ -778,6 +786,17 @@ class Compiler
}
}
internal void SetBackwardBranchLabel(int instructionIndex, BranchCookie bc)
{
// NOTE we're overwriting the label that is already there
labels[instructionIndex] = bc.Stub;
if(exits == null)
{
exits = new ArrayList();
}
exits.Add(bc);
}
internal Label GetLabel(int targetPC)
{
int targetIndex = compiler.FindPcIndex(targetPC);
@ -814,6 +833,11 @@ class Compiler
}
}
internal bool HasLabel(int instructionIndex)
{
return labels[instructionIndex] != null;
}
internal void MarkLabel(int instructionIndex)
{
object label = labels[instructionIndex];
@ -835,6 +859,8 @@ class Compiler
}
internal void Leave()
{
if(exits != null)
{
for(int i = 0; i < exits.Count; i++)
{
@ -849,13 +875,23 @@ class Compiler
{
bc.dh.Store(n);
}
if(bc.TargetPC == -1)
{
ilgen.Emit(OpCodes.Br, bc.TargetLabel);
}
else
{
bc.Stub = ilgen.DefineLabel();
ilgen.Emit(OpCodes.Leave, bc.Stub);
}
}
}
}
}
internal void LeaveStubs(Block newBlock)
{
if(exits != null)
{
for(int i = 0; i < exits.Count; i++)
{
@ -875,7 +911,7 @@ class Compiler
else
{
BranchCookie bc = exit as BranchCookie;
if(bc != null)
if(bc != null && bc.TargetPC != -1)
{
Debug.Assert(!bc.ContentOnStack);
// if the target is within the new block, we handle it, otherwise we
@ -899,6 +935,7 @@ class Compiler
}
}
}
}
internal void AddExitHack(object bc)
{
@ -909,7 +946,7 @@ class Compiler
{
get
{
return exits != null;
return nested;
}
}
}
@ -956,6 +993,7 @@ class Compiler
int exceptionIndex = 0;
Instruction[] code = m.Instructions;
Stack blockStack = new Stack();
bool instructionIsForwardReachable = true;
for(int i = 0; i < code.Length; i++)
{
Instruction instr = code[i];
@ -1045,6 +1083,7 @@ class Compiler
{
if(exceptionTypeWrapper.IsUnloadable)
{
Profiler.Count("EmitDynamicGetTypeAsExceptionType");
ilGenerator.Emit(OpCodes.Ldtoken, clazz.TypeAsTBD);
ilGenerator.Emit(OpCodes.Ldstr, exceptionTypeWrapper.Name);
ilGenerator.Emit(OpCodes.Call, typeof(ByteCodeHelper).GetMethod("DynamicGetTypeAsExceptionType"));
@ -1079,10 +1118,36 @@ class Compiler
prevBlock.LeaveStubs(block);
}
// if there was a forward branch to this instruction, it is forward reachable
instructionIsForwardReachable |= block.HasLabel(i);
// TODO for now, every instruction has an associated label, I'm not sure it's worthwhile,
// but it could be optimized
block.MarkLabel(i);
// if the instruction is only backward reachable, ECMA says it must have an empty stack,
// so we move the stack to locals
if(!instructionIsForwardReachable && ma.IsReachable(i))
{
int stackHeight = ma.GetStackHeight(i);
if(stackHeight != 0)
{
BranchCookie bc = new BranchCookie(ilGenerator, stackHeight, -1);
bc.ContentOnStack = true;
bc.TargetLabel = ilGenerator.DefineLabel();
ilGenerator.MarkLabel(bc.TargetLabel);
for(int j = 0; j < stackHeight; j++)
{
bc.dh.SetType(j, ma.GetRawStackTypeWrapper(i, j));
}
for(int j = stackHeight - 1; j >= 0; j--)
{
bc.dh.Load(j);
}
block.SetBackwardBranchLabel(i, bc);
}
}
// if we're entering an exception block, we need to setup the exception block and
// transfer the stack into it
for(; exceptionIndex < exceptions.Length && exceptions[exceptionIndex].start_pc == instr.PC; exceptionIndex++)
@ -1107,7 +1172,7 @@ class Compiler
ilGenerator.BeginExceptionBlock();
}
blockStack.Push(block);
block = new Block(this, exceptions[exceptionIndex].start_pc, exceptions[exceptionIndex].end_pc, exceptionIndex, new ArrayList());
block = new Block(this, exceptions[exceptionIndex].start_pc, exceptions[exceptionIndex].end_pc, exceptionIndex, new ArrayList(), true);
block.MarkLabel(i);
}
@ -1198,6 +1263,7 @@ class Compiler
TypeWrapper tw = cf.GetConstantPoolClassType(constant, classLoader);
if(tw.IsUnloadable)
{
Profiler.Count("EmitDynamicClassLiteral");
ilGenerator.Emit(OpCodes.Ldtoken, clazz.TypeAsTBD);
ilGenerator.Emit(OpCodes.Ldstr, tw.Name);
ilGenerator.Emit(OpCodes.Call, typeof(ByteCodeHelper).GetMethod("DynamicClassLiteral"));
@ -1590,6 +1656,7 @@ class Compiler
TypeWrapper wrapper = instr.MethodCode.Method.ClassFile.GetConstantPoolClassType(instr.Arg1, classLoader);
if(wrapper.IsUnloadable)
{
Profiler.Count("EmitDynamicNewCheckOnly");
// this is here to make sure we throw the exception in the right location (before
// evaluating the constructor arguments)
ilGenerator.Emit(OpCodes.Ldtoken, clazz.TypeAsTBD);
@ -1625,6 +1692,7 @@ class Compiler
TypeWrapper wrapper = instr.MethodCode.Method.ClassFile.GetConstantPoolClassType(instr.Arg1, classLoader);
if(wrapper.IsUnloadable)
{
Profiler.Count("EmitDynamicMultianewarray");
ilGenerator.Emit(OpCodes.Ldtoken, clazz.TypeAsTBD);
ilGenerator.Emit(OpCodes.Ldstr, wrapper.Name);
ilGenerator.Emit(OpCodes.Ldloc, localArray);
@ -1649,6 +1717,7 @@ class Compiler
TypeWrapper wrapper = instr.MethodCode.Method.ClassFile.GetConstantPoolClassType(instr.Arg1, classLoader);
if(wrapper.IsUnloadable)
{
Profiler.Count("EmitDynamicNewarray");
ilGenerator.Emit(OpCodes.Ldtoken, clazz.TypeAsTBD);
ilGenerator.Emit(OpCodes.Ldstr, wrapper.Name);
ilGenerator.Emit(OpCodes.Call, typeof(ByteCodeHelper).GetMethod("DynamicNewarray"));
@ -1730,6 +1799,7 @@ class Compiler
TypeWrapper tw = ma.GetRawStackTypeWrapper(i, 1);
if(tw.IsUnloadable)
{
Profiler.Count("EmitDynamicAaload");
ilGenerator.Emit(OpCodes.Ldtoken, clazz.TypeAsTBD);
ilGenerator.Emit(OpCodes.Ldstr, tw.Name);
ilGenerator.Emit(OpCodes.Call, typeof(ByteCodeHelper).GetMethod("DynamicAaload"));
@ -1799,6 +1869,7 @@ class Compiler
TypeWrapper tw = ma.GetRawStackTypeWrapper(i, 2);
if(tw.IsUnloadable)
{
Profiler.Count("EmitDynamicAastore");
ilGenerator.Emit(OpCodes.Ldtoken, clazz.TypeAsTBD);
ilGenerator.Emit(OpCodes.Ldstr, tw.Name);
ilGenerator.Emit(OpCodes.Call, typeof(ByteCodeHelper).GetMethod("DynamicAastore"));
@ -2458,8 +2529,10 @@ class Compiler
case NormalizedByteCode.__areturn:
case NormalizedByteCode.__return:
case NormalizedByteCode.__athrow:
instructionIsForwardReachable = false;
break;
default:
instructionIsForwardReachable = true;
Debug.Assert(ma.IsReachable(i + 1));
// don't fall through end of try block
if(m.Instructions[i + 1].PC == block.End)
@ -2658,17 +2731,21 @@ class Compiler
switch(bytecode)
{
case NormalizedByteCode.__getfield:
Profiler.Count("EmitDynamicGetfield");
ilGenerator.Emit(OpCodes.Call, typeof(ByteCodeHelper).GetMethod("DynamicGetfield"));
EmitReturnTypeConversion(ilGenerator, fieldTypeWrapper);
break;
case NormalizedByteCode.__putfield:
Profiler.Count("EmitDynamicPutfield");
ilGenerator.Emit(OpCodes.Call, typeof(ByteCodeHelper).GetMethod("DynamicPutfield"));
break;
case NormalizedByteCode.__getstatic:
Profiler.Count("EmitDynamicGetstatic");
ilGenerator.Emit(OpCodes.Call, typeof(ByteCodeHelper).GetMethod("DynamicGetstatic"));
EmitReturnTypeConversion(ilGenerator, fieldTypeWrapper);
break;
case NormalizedByteCode.__putstatic:
Profiler.Count("EmitDynamicPutstatic");
ilGenerator.Emit(OpCodes.Call, typeof(ByteCodeHelper).GetMethod("DynamicPutstatic"));
break;
}
@ -2781,6 +2858,7 @@ class Compiler
internal override void Emit(ILGenerator ilGenerator)
{
Profiler.Count("EmitDynamicInvokeEmitter");
TypeWrapper[] args = cpi.GetArgTypes(classLoader);
LocalBuilder argarray = ilGenerator.DeclareLocal(typeof(object[]));
LocalBuilder val = ilGenerator.DeclareLocal(typeof(object));