Removed stream usage, now goes directly bytes. Is faster, but still can do more.

This commit is contained in:
kudzu_cp 2009-07-23 04:42:28 +00:00
parent 27cb7ebe1e
commit 047459fb37
3 changed files with 59 additions and 105 deletions

View file

@ -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() {

View file

@ -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));
} }

View file

@ -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);
} }
} }