Annihilate some common push/pop combinations.

This commit is contained in:
jfrijters 2010-09-30 07:31:27 +00:00
Родитель dc35f2e455
Коммит 8f28fe1e63
1 изменённых файлов: 62 добавлений и 16 удалений

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

@ -157,9 +157,16 @@ namespace IKVM.Internal
internal readonly OpCode opcode;
internal readonly object data;
internal OpCodeWrapper(CodeType type, OpCode opcode, object data)
internal OpCodeWrapper(CodeType type, object data)
{
this.type = type;
this.opcode = OpCodes.Nop;
this.data = data;
}
internal OpCodeWrapper(OpCode opcode, object data)
{
this.type = CodeType.OpCode;
this.opcode = opcode;
this.data = data;
}
@ -332,12 +339,12 @@ namespace IKVM.Internal
private void EmitPseudoOpCode(CodeType type, object data)
{
code.Add(new OpCodeWrapper(type, OpCodes.Nop, data));
code.Add(new OpCodeWrapper(type, data));
}
private void EmitOpCode(OpCode opcode, object arg)
{
code.Add(new OpCodeWrapper(CodeType.OpCode, opcode, arg));
code.Add(new OpCodeWrapper(opcode, arg));
}
private void RealEmitPseudoOpCode(int ilOffset, CodeType type, object data)
@ -399,7 +406,7 @@ namespace IKVM.Internal
}
}
private void RealEmitOpCode(int ilOffset, OpCode opcode, object arg)
private void RealEmitOpCode(OpCode opcode, object arg)
{
if (arg == null)
{
@ -529,11 +536,57 @@ namespace IKVM.Internal
&& code[i - 1].opcode == OpCodes.Br
&& code[i - 1].data == code[i].data)
{
code[i - 1] = new OpCodeWrapper(CodeType.Nop, OpCodes.Nop, null);
code.RemoveAt(i - 1);
i--;
}
}
}
private void AnnihilatePops()
{
for (int i = 1; i < code.Count; i++)
{
if (code[i].opcode == OpCodes.Pop
&& IsSideEffectFreePush(i - 1))
{
code.RemoveRange(i - 1, 2);
i -= 2;
}
}
}
private bool IsSideEffectFreePush(int index)
{
if (code[index].opcode == OpCodes.Ldstr)
{
return true;
}
else if (code[index].opcode == OpCodes.Ldnull)
{
return true;
}
else if (code[index].opcode == OpCodes.Ldsfld)
{
// Here we are considering BeforeFieldInit to mean that we really don't care about
// when the type is initialized (which is what we mean in the rest of the IKVM code as well)
// but it is good to point it out here because strictly speaking we're violating the
// BeforeFieldInit contract here by considering dummy loads not to be field accesses.
FieldInfo field = code[index].data as FieldInfo;
if (field != null && (field.DeclaringType.Attributes & TypeAttributes.BeforeFieldInit) != 0)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
private void OptimizeBranchSizes()
{
int offset = 0;
@ -613,7 +666,7 @@ namespace IKVM.Internal
{
opcode = OpCodes.Leave_S;
}
code[i] = new OpCodeWrapper(code[i].type, opcode, code[i].data);
code[i] = new OpCodeWrapper(opcode, code[i].data);
}
}
}
@ -622,13 +675,14 @@ namespace IKVM.Internal
internal void DoEmit()
{
RemoveJumpNext();
AnnihilatePops();
OptimizeBranchSizes();
int ilOffset = 0;
for (int i = 0; i < code.Count; i++)
{
if (code[i].type == CodeType.OpCode)
{
RealEmitOpCode(ilOffset, code[i].opcode, code[i].data);
RealEmitOpCode(code[i].opcode, code[i].data);
}
else
{
@ -1001,15 +1055,7 @@ namespace IKVM.Internal
internal void LazyEmitPop()
{
Expr exp = PeekStack();
if (exp == null || exp.HasSideEffect || exp.IsIncomplete)
{
Emit(OpCodes.Pop);
}
else
{
PopStack();
}
Emit(OpCodes.Pop);
}
internal void LazyEmitLoadClass(TypeWrapper type)