Make Emit and AdvanceOpCode private, simplify it a bit now that it starts emiting from the entry point

This commit is contained in:
gdkchan 2018-11-30 23:32:05 -03:00
commit 0d448cde37
2 changed files with 72 additions and 78 deletions

View file

@ -21,7 +21,7 @@ namespace ChocolArm64.Translation
private Block _currBlock; private Block _currBlock;
public Block CurrBlock => _currBlock; public Block CurrBlock => _currBlock;
public OpCode64 CurrOp => _currBlock.OpCodes[_opcIndex]; public OpCode64 CurrOp => _currBlock?.OpCodes[_opcIndex];
private Dictionary<Block, ILBlock> _visitedBlocks; private Dictionary<Block, ILBlock> _visitedBlocks;
@ -67,7 +67,63 @@ namespace ChocolArm64.Translation
AdvanceOpCode(); AdvanceOpCode();
} }
public bool AdvanceOpCode() public ILBlock[] GetILBlocks()
{
EmitAllOpCodes();
return _ilBlocks.ToArray();
}
private void EmitAllOpCodes()
{
do
{
EmitOpCode();
}
while (AdvanceOpCode());
}
private void EmitOpCode()
{
if (_currBlock == null)
{
return;
}
if (_opcIndex == 0)
{
MarkLabel(GetLabel(_currBlock.Position));
EmitSynchronization();
}
CurrOp.Emitter(this);
_ilBlock.Add(new ILBarrier());
}
private void EmitSynchronization()
{
EmitLdarg(TranslatedSub.StateArgIdx);
EmitLdc_I4(_currBlock.OpCodes.Count);
EmitPrivateCall(typeof(CpuThreadState), nameof(CpuThreadState.Synchronize));
EmitLdc_I4(0);
ILLabel lblContinue = new ILLabel();
Emit(OpCodes.Bne_Un_S, lblContinue);
EmitLdc_I8(0);
Emit(OpCodes.Ret);
MarkLabel(lblContinue);
}
private bool AdvanceOpCode()
{ {
if (_currBlock == null) if (_currBlock == null)
{ {
@ -144,51 +200,6 @@ namespace ChocolArm64.Translation
return new ILBlock(); return new ILBlock();
} }
public void EmitOpCode()
{
if (_currBlock == null)
{
return;
}
if (_opcIndex == 0)
{
MarkLabel(GetLabel(_currBlock.Position));
EmitSynchronization();
}
CurrOp.Emitter(this);
_ilBlock.Add(new ILBarrier());
}
private void EmitSynchronization()
{
EmitLdarg(TranslatedSub.StateArgIdx);
EmitLdc_I4(_currBlock.OpCodes.Count);
EmitPrivateCall(typeof(CpuThreadState), nameof(CpuThreadState.Synchronize));
EmitLdc_I4(0);
ILLabel lblContinue = new ILLabel();
Emit(OpCodes.Bne_Un_S, lblContinue);
EmitLdc_I8(0);
Emit(OpCodes.Ret);
MarkLabel(lblContinue);
}
public ILBlock[] GetILBlocks()
{
return _ilBlocks.ToArray();
}
public bool TryOptEmitSubroutineCall() public bool TryOptEmitSubroutineCall()
{ {
if (_currBlock.Next == null) if (_currBlock.Next == null)

View file

@ -85,12 +85,6 @@ namespace ChocolArm64
ILEmitterCtx context = new ILEmitterCtx(_cache, block); ILEmitterCtx context = new ILEmitterCtx(_cache, block);
do
{
context.EmitOpCode();
}
while (context.AdvanceOpCode());
string subName = GetSubroutineName(position); string subName = GetSubroutineName(position);
ILMethodBuilder ilMthdBuilder = new ILMethodBuilder(context.GetILBlocks(), subName); ILMethodBuilder ilMthdBuilder = new ILMethodBuilder(context.GetILBlocks(), subName);
@ -110,34 +104,10 @@ namespace ChocolArm64
ILEmitterCtx context = new ILEmitterCtx(_cache, graph); ILEmitterCtx context = new ILEmitterCtx(_cache, graph);
if (context.CurrBlock.Position != position) ILBlock[] ilBlocks = context.GetILBlocks();
{
context.Emit(OpCodes.Br, context.GetLabel(position));
}
do
{
context.EmitOpCode();
}
while (context.AdvanceOpCode());
//Mark all methods that calls this method for ReJiting,
//since we can now call it directly which is faster.
if (_cache.TryGetSubroutine(position, out TranslatedSub oldSub))
{
foreach (long callerPos in oldSub.GetCallerPositions())
{
if (_cache.TryGetSubroutine(position, out TranslatedSub callerSub))
{
callerSub.MarkForReJit();
}
}
}
string subName = GetSubroutineName(position); string subName = GetSubroutineName(position);
ILBlock[] ilBlocks = context.GetILBlocks();
ILMethodBuilder ilMthdBuilder = new ILMethodBuilder(ilBlocks, subName); ILMethodBuilder ilMthdBuilder = new ILMethodBuilder(ilBlocks, subName);
TranslatedSub subroutine = ilMthdBuilder.GetSubroutine(); TranslatedSub subroutine = ilMthdBuilder.GetSubroutine();
@ -152,6 +122,19 @@ namespace ChocolArm64
} }
_cache.AddOrUpdate(position, subroutine, ilOpCount); _cache.AddOrUpdate(position, subroutine, ilOpCount);
//Mark all methods that calls this method for ReJiting,
//since we can now call it directly which is faster.
if (_cache.TryGetSubroutine(position, out TranslatedSub oldSub))
{
foreach (long callerPos in oldSub.GetCallerPositions())
{
if (_cache.TryGetSubroutine(position, out TranslatedSub callerSub))
{
callerSub.MarkForReJit();
}
}
}
} }
private string GetSubroutineName(long position) private string GetSubroutineName(long position)