mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-26 21:42:11 +00:00
Removed stream usage, now goes directly bytes. Is faster, but still can do more.
This commit is contained in:
parent
27cb7ebe1e
commit
047459fb37
3 changed files with 59 additions and 105 deletions
|
|
@ -10,11 +10,7 @@ namespace Cosmos.IL2CPU.Profiler {
|
||||||
class Program {
|
class Program {
|
||||||
|
|
||||||
static void Main(string[] args) {
|
static void Main(string[] args) {
|
||||||
try {
|
DoScan();
|
||||||
DoScan();
|
|
||||||
} catch(Exception E) {
|
|
||||||
Console.WriteLine(E.ToString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DoScan() {
|
private static void DoScan() {
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,10 @@ using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Cosmos.IL2CPU {
|
namespace Cosmos.IL2CPU {
|
||||||
public class ILReader : IDisposable {
|
public class ILReader {
|
||||||
private Stream mStream;
|
private byte[] mBody;
|
||||||
private MethodBase mMethod;
|
private MethodBase mMethod;
|
||||||
private Module mModule;
|
private Module mModule;
|
||||||
private bool mDisposeStream;
|
|
||||||
|
|
||||||
public ILReader(MethodBase aMethod):this(aMethod, aMethod.GetMethodBody()) {
|
public ILReader(MethodBase aMethod):this(aMethod, aMethod.GetMethodBody()) {
|
||||||
}
|
}
|
||||||
|
|
@ -15,46 +14,13 @@ namespace Cosmos.IL2CPU {
|
||||||
public ILReader(MethodBase aMethod, MethodBody aBody) {
|
public ILReader(MethodBase aMethod, MethodBody aBody) {
|
||||||
mMethod = aMethod;
|
mMethod = aMethod;
|
||||||
mModule = mMethod.Module;
|
mModule = mMethod.Module;
|
||||||
//TODO: Why do we convert a small array of bytes in memory to a memory stream only to convert back to individual bytes?
|
mBody = aBody.GetILAsByteArray();
|
||||||
// Instead lets work on the array itself
|
|
||||||
mStream = new MemoryStream(aBody.GetILAsByteArray());
|
|
||||||
//TODO: Why do we suppress finalize here?
|
|
||||||
GC.SuppressFinalize(mStream);
|
|
||||||
mDisposeStream = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ILReader(MethodBase aMethod, Stream aStream)
|
|
||||||
{
|
|
||||||
mMethod = aMethod;
|
|
||||||
mModule = mMethod.Module;
|
|
||||||
mStream = aStream;
|
|
||||||
mDisposeStream = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose() {
|
|
||||||
if (mDisposeStream) {
|
|
||||||
mStream.Dispose();
|
|
||||||
//TODO: See comment above about supress finalize
|
|
||||||
GC.ReRegisterForFinalize(mStream);
|
|
||||||
}
|
|
||||||
mStream = null;
|
|
||||||
mMethod = null;
|
|
||||||
mModule = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ILOp.Code mOpCode;
|
private ILOp.Code mOpCode;
|
||||||
private byte[] mOperand;
|
private byte[] mOperand;
|
||||||
|
|
||||||
public uint Position {
|
protected int mPosition = 0;
|
||||||
get;
|
|
||||||
private set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint NextPosition {
|
|
||||||
get {
|
|
||||||
return (uint)mStream.Position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ILOp.Code OpCode {
|
public ILOp.Code OpCode {
|
||||||
get {
|
get {
|
||||||
|
|
@ -104,30 +70,21 @@ namespace Cosmos.IL2CPU {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private uint? mOperandValueBranchPosition;
|
|
||||||
private bool mIsShortcut;
|
private bool mIsShortcut;
|
||||||
public uint OperandValueBranchPosition {
|
|
||||||
get {
|
//private uint? mOperandValueBranchPosition;
|
||||||
if (mOperandValueBranchPosition == null) {
|
//public uint OperandValueBranchPosition {
|
||||||
//sbyte xTemp = (sbyte)mOperand;
|
// get {
|
||||||
//if (xTemp == mOperand) {
|
// if (mOperandValueBranchPosition == null) {
|
||||||
// mOperandValueBranchPosition = NextPosition + xTemp;
|
// if (mIsShortcut) {
|
||||||
//} else {
|
// mOperandValueBranchPosition = (uint?)(NextPosition + (sbyte)OperandValueInt32);
|
||||||
// if (mStream.Length < (NextPosition + mOperand + 1)) {
|
// } else {
|
||||||
// mOperandValueBranchPosition = (uint)mOperand;
|
// mOperandValueBranchPosition = (uint?)(NextPosition + OperandValueInt32);
|
||||||
// } else {
|
// }
|
||||||
// mOperandValueBranchPosition = (uint)(NextPosition + mOperand);
|
// }
|
||||||
// }
|
// return mOperandValueBranchPosition.Value;
|
||||||
if (mIsShortcut) {
|
// }
|
||||||
mOperandValueBranchPosition = (uint?)(NextPosition + (sbyte)OperandValueInt32);
|
//}
|
||||||
} else {
|
|
||||||
mOperandValueBranchPosition = (uint?)(NextPosition + OperandValueInt32);
|
|
||||||
}
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
return mOperandValueBranchPosition.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private FieldInfo mOperandValueField;
|
private FieldInfo mOperandValueField;
|
||||||
public FieldInfo OperandValueField {
|
public FieldInfo OperandValueField {
|
||||||
|
|
@ -230,18 +187,23 @@ namespace Cosmos.IL2CPU {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected byte ReadByte() {
|
||||||
|
var xResult = mBody[mPosition];
|
||||||
|
mPosition++;
|
||||||
|
return xResult;
|
||||||
|
}
|
||||||
|
|
||||||
public bool Read() {
|
public bool Read() {
|
||||||
Position = NextPosition;
|
|
||||||
// End of stream
|
// End of stream
|
||||||
if (mStream.Position == mStream.Length) {
|
if (mPosition == mBody.Length) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get OpCode
|
// Get OpCode
|
||||||
byte xOpCodeByte1 = (byte)mStream.ReadByte();
|
byte xOpCodeByte1 = ReadByte();
|
||||||
ILOp.Code xOpCode;
|
ILOp.Code xOpCode;
|
||||||
if (xOpCodeByte1 == 0xFE) {
|
if (xOpCodeByte1 == 0xFE) {
|
||||||
xOpCode = (ILOp.Code)(xOpCodeByte1 << 8 | (byte)mStream.ReadByte());
|
xOpCode = (ILOp.Code)(xOpCodeByte1 << 8 | ReadByte());
|
||||||
} else {
|
} else {
|
||||||
xOpCode = (ILOp.Code)xOpCodeByte1;
|
xOpCode = (ILOp.Code)xOpCodeByte1;
|
||||||
}
|
}
|
||||||
|
|
@ -254,7 +216,7 @@ namespace Cosmos.IL2CPU {
|
||||||
mOperandValueSingle = null;
|
mOperandValueSingle = null;
|
||||||
mOperandValueType = null;
|
mOperandValueType = null;
|
||||||
mOperandValueInt32 = null;
|
mOperandValueInt32 = null;
|
||||||
mOperandValueBranchPosition = null;
|
//mOperandValueBranchPosition = null;
|
||||||
OperandValueBranchLocations = null;
|
OperandValueBranchLocations = null;
|
||||||
mOperandValueDouble = null;
|
mOperandValueDouble = null;
|
||||||
mOpCode = ILOp.ExpandShortcut(xOpCode);
|
mOpCode = ILOp.ExpandShortcut(xOpCode);
|
||||||
|
|
@ -278,10 +240,10 @@ namespace Cosmos.IL2CPU {
|
||||||
}
|
}
|
||||||
uint[] xResult = new uint[xBranchLocations1.Length];
|
uint[] xResult = new uint[xBranchLocations1.Length];
|
||||||
for (int i = 0; i < xBranchLocations1.Length; i++) {
|
for (int i = 0; i < xBranchLocations1.Length; i++) {
|
||||||
if ((NextPosition + xBranchLocations1[i]) < 0) {
|
if ((mPosition + xBranchLocations1[i]) < 0) {
|
||||||
xResult[i] = (uint)xBranchLocations1[i];
|
xResult[i] = (uint)xBranchLocations1[i];
|
||||||
} else {
|
} else {
|
||||||
xResult[i] = (uint)(NextPosition + xBranchLocations1[i]);
|
xResult[i] = (uint)(mPosition + xBranchLocations1[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OperandValueBranchLocations = xResult;
|
OperandValueBranchLocations = xResult;
|
||||||
|
|
@ -291,15 +253,12 @@ namespace Cosmos.IL2CPU {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Int64 ReadInt64() {
|
private Int64 ReadInt64() {
|
||||||
long xResult = 0;
|
//TODO: Improve or eliminate
|
||||||
|
long xResult = 0;
|
||||||
byte xOperandSize = 8;
|
byte xOperandSize = 8;
|
||||||
byte[] xBytes = new byte[xOperandSize];
|
byte[] xBytes = new byte[xOperandSize];
|
||||||
while (xOperandSize > 0) {
|
while (xOperandSize > 0) {
|
||||||
int xByteValueInt = mStream.ReadByte();
|
xBytes[xOperandSize - 1] = ReadByte();
|
||||||
if (xByteValueInt == -1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
xBytes[xOperandSize - 1] = (byte)xByteValueInt;
|
|
||||||
xOperandSize--;
|
xOperandSize--;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < xBytes.Length; i++) {
|
for (int i = 0; i < xBytes.Length; i++) {
|
||||||
|
|
@ -312,7 +271,10 @@ namespace Cosmos.IL2CPU {
|
||||||
//TODO: If we need further peformance, this function is one of the bigger users of time
|
//TODO: If we need further peformance, this function is one of the bigger users of time
|
||||||
// We can load more data at a time, and use an index into larger buffers
|
// We can load more data at a time, and use an index into larger buffers
|
||||||
private byte[] ReadOperand(byte aOperandSize) {
|
private byte[] ReadOperand(byte aOperandSize) {
|
||||||
mStream.Read(mOperandBuff, 0, aOperandSize);
|
for (int i = 0; i < aOperandSize; i++) {
|
||||||
|
//TODO: can do better than readbyte, can do locally
|
||||||
|
mOperandBuff[i] = ReadByte();
|
||||||
|
}
|
||||||
return mOperandBuff;
|
return mOperandBuff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -325,6 +287,7 @@ namespace Cosmos.IL2CPU {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Int32 ReadInt32() {
|
private Int32 ReadInt32() {
|
||||||
|
//TODO: Improve or eliminate
|
||||||
return GetInt32FromOperandByteArray(ReadOperand(4));
|
return GetInt32FromOperandByteArray(ReadOperand(4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,32 +60,27 @@ namespace Cosmos.IL2CPU {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
var xBody = aMethodBase.GetMethodBody();
|
||||||
var xBody = aMethodBase.GetMethodBody();
|
if (xBody == null) {
|
||||||
if (xBody == null) {
|
return;
|
||||||
return;
|
}
|
||||||
|
var xReader = new ILReader(aMethodBase, xBody);
|
||||||
|
while (xReader.Read()) {
|
||||||
|
// Kudzu:
|
||||||
|
// Uncomment for debugging - has a small but noticable
|
||||||
|
// impact on runtime. Could be coincidental, but ran
|
||||||
|
// tests several times with and with out and without
|
||||||
|
// was consistently 0.5 secs faster on the Atom.
|
||||||
|
// Does not make much sense though as its only used 13000
|
||||||
|
// times or so, so possibly the compiling in is affecting
|
||||||
|
// some CPU cache hit or other?
|
||||||
|
//InstructionCount++;
|
||||||
|
var xCreate = mOps[(ushort)xReader.OpCode];
|
||||||
|
if (xCreate == null) {
|
||||||
|
throw new Exception("Unrecognized IL Operation");
|
||||||
}
|
}
|
||||||
using (var xReader = new ILReader(aMethodBase, xBody)) {
|
var xOp = xCreate();
|
||||||
while (xReader.Read()) {
|
xOp.Scan(xReader, this);
|
||||||
// Kudzu:
|
|
||||||
// Uncomment for debugging - has a small but noticable
|
|
||||||
// impact on runtime. Could be coincidental, but ran
|
|
||||||
// tests several times with and with out and without
|
|
||||||
// was consistently 0.5 secs faster on the Atom.
|
|
||||||
// Does not make much sense though as its only used 13000
|
|
||||||
// times or so, so possibly the compiling in is affecting
|
|
||||||
// some CPU cache hit or other?
|
|
||||||
//InstructionCount++;
|
|
||||||
var xCreate = mOps[(ushort)xReader.OpCode];
|
|
||||||
if (xCreate == null) {
|
|
||||||
throw new Exception("Unrecognized IL Operation");
|
|
||||||
}
|
|
||||||
var xOp = xCreate();
|
|
||||||
xOp.Scan(xReader, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception E) {
|
|
||||||
throw new Exception("Error getting body!", E);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue