mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-24 12:35:31 +00:00
Optimized, runs 6.5x faster now.
This commit is contained in:
parent
e52ef0a16c
commit
c4a33100ee
2 changed files with 49 additions and 76 deletions
|
|
@ -15,9 +15,9 @@ namespace Cosmos.Compiler
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class Scanner
|
public partial class Scanner
|
||||||
{
|
{
|
||||||
private HashSet<string> mMethodNames = new HashSet<string>(StringComparer.InvariantCulture);
|
private HashSet<MethodBase> mMethodsSet = new HashSet<MethodBase>();
|
||||||
private List<MethodBase> mMethods = new List<MethodBase>();
|
private List<MethodBase> mMethods = new List<MethodBase>();
|
||||||
private HashSet<string> mTypeNames = new HashSet<string>(StringComparer.InvariantCulture);
|
private HashSet<Type> mTypesSet = new HashSet<Type>();
|
||||||
private List<Type> mTypes = new List<Type>();
|
private List<Type> mTypes = new List<Type>();
|
||||||
|
|
||||||
private Func<Op>[] mOps;
|
private Func<Op>[] mOps;
|
||||||
|
|
@ -29,14 +29,10 @@ namespace Cosmos.Compiler
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if(value != mOps)
|
if(value != mOps) {
|
||||||
{
|
if(value == null) {
|
||||||
if(value == null)
|
|
||||||
{
|
|
||||||
throw new Exception("Cannot set Ops to null");
|
throw new Exception("Cannot set Ops to null");
|
||||||
}
|
} else if (value.Length != 0xFE1F) {
|
||||||
if(value.Length != 0xFE1F)
|
|
||||||
{
|
|
||||||
throw new Exception("Element count mismatch!");
|
throw new Exception("Element count mismatch!");
|
||||||
}
|
}
|
||||||
mOps = value;
|
mOps = value;
|
||||||
|
|
@ -51,9 +47,8 @@ namespace Cosmos.Compiler
|
||||||
//File.WriteAllLines(@"e:\cosmos.dbg", mMethodNames.ToArray());
|
//File.WriteAllLines(@"e:\cosmos.dbg", mMethodNames.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ScanList()
|
private void ScanList() {
|
||||||
{
|
// Cannot use foreach, the list changes as we go
|
||||||
// dont use a foreach here, the list will change.
|
|
||||||
for(int i = 0; i < mMethods.Count; i++)
|
for(int i = 0; i < mMethods.Count; i++)
|
||||||
{
|
{
|
||||||
ScanMethod(mMethods[i]);
|
ScanMethod(mMethods[i]);
|
||||||
|
|
@ -62,22 +57,16 @@ namespace Cosmos.Compiler
|
||||||
|
|
||||||
private void ScanMethod(MethodBase aMethodBase)
|
private void ScanMethod(MethodBase aMethodBase)
|
||||||
{
|
{
|
||||||
|
if ((aMethodBase.Attributes & MethodAttributes.PinvokeImpl) != 0) {
|
||||||
// pinvoke methods dont have an embedded implementation
|
// pinvoke methods dont have an embedded implementation
|
||||||
if ((aMethodBase.Attributes & MethodAttributes.PinvokeImpl) != 0)
|
|
||||||
{
|
|
||||||
// pinvoke
|
|
||||||
return;
|
return;
|
||||||
}
|
} else if (aMethodBase.IsAbstract) {
|
||||||
else if (aMethodBase.IsAbstract)
|
|
||||||
{
|
|
||||||
// abstract methods dont have an implementation
|
// abstract methods dont have an implementation
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var xImplFlags = aMethodBase.GetMethodImplementationFlags();
|
var xImplFlags = aMethodBase.GetMethodImplementationFlags();
|
||||||
if ((xImplFlags & MethodImplAttributes.Native) != 0)
|
if ((xImplFlags & MethodImplAttributes.Native) != 0) {
|
||||||
{
|
|
||||||
// native implementations cannot be compiled
|
// native implementations cannot be compiled
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -85,23 +74,26 @@ namespace Cosmos.Compiler
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var xBody = aMethodBase.GetMethodBody();
|
var xBody = aMethodBase.GetMethodBody();
|
||||||
if (xBody == null)
|
if (xBody == null) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
using(var xReader = new ILReader(aMethodBase, xBody))
|
using(var xReader = new ILReader(aMethodBase, xBody)) {
|
||||||
{
|
while(xReader.Read()) {
|
||||||
while(xReader.Read())
|
// Kudzu:
|
||||||
{
|
// Uncomment for debugging - has a small but noticable
|
||||||
InstructionCount++;
|
// 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];
|
var xCreate = mOps[(ushort) xReader.OpCode];
|
||||||
if(xCreate==null)
|
if(xCreate == null) {
|
||||||
{
|
|
||||||
LogMissingOp(xReader.OpCode);
|
LogMissingOp(xReader.OpCode);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var xOp = xCreate();
|
var xOp = xCreate();
|
||||||
QueueMethodCallCount = 0;
|
|
||||||
xOp.Scan(xReader, this);
|
xOp.Scan(xReader, this);
|
||||||
// TEMP
|
// TEMP
|
||||||
//if (xReader.OperandValueMethod!=null)
|
//if (xReader.OperandValueMethod!=null)
|
||||||
|
|
@ -113,53 +105,35 @@ namespace Cosmos.Compiler
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}catch(Exception E)
|
} catch(Exception E) {
|
||||||
{
|
|
||||||
throw new Exception("Error getting body!", E);
|
throw new Exception("Error getting body!", E);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void QueueMethod(MethodBase aMethod) {
|
||||||
private int QueueMethodCallCount = 0;
|
if (!mMethodsSet.Contains(aMethod)) {
|
||||||
public void QueueMethod(MethodBase aMethod)
|
mMethodsSet.Add(aMethod);
|
||||||
{
|
|
||||||
QueueMethodCallCount++;
|
|
||||||
var xName = aMethod.GetFullName();
|
|
||||||
if (!mMethodNames.Contains(xName))
|
|
||||||
{
|
|
||||||
mMethodNames.Add(xName);
|
|
||||||
mMethods.Add(aMethod);
|
mMethods.Add(aMethod);
|
||||||
QueueType(aMethod.DeclaringType);
|
QueueType(aMethod.DeclaringType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void QueueType(Type type)
|
public void QueueType(Type aType) {
|
||||||
{
|
if (aType != null) {
|
||||||
if(type == null)
|
if (!mTypesSet.Contains(aType)) {
|
||||||
{
|
mTypesSet.Add(aType);
|
||||||
return;
|
mTypes.Add(aType);
|
||||||
}
|
QueueType(aType.BaseType);
|
||||||
if (!mTypeNames.Contains(type.GetFullName()))
|
foreach (var xMethod in aType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) {
|
||||||
{
|
if (xMethod.DeclaringType == aType) {
|
||||||
QueueType(type.BaseType);
|
if (xMethod.IsVirtual) {
|
||||||
foreach (
|
|
||||||
var xMethod in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
|
|
||||||
{
|
|
||||||
if (xMethod.DeclaringType != type)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (xMethod.IsVirtual)
|
|
||||||
{
|
|
||||||
QueueMethod(xMethod);
|
QueueMethod(xMethod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mTypeNames.Add(type.GetFullName());
|
|
||||||
mTypes.Add(type);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//private void
|
}
|
||||||
|
|
||||||
public int MethodCount
|
public int MethodCount
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ using System.Collections.ObjectModel;
|
||||||
using Cosmos.Compiler;
|
using Cosmos.Compiler;
|
||||||
using Cosmos.Compiler.IL;
|
using Cosmos.Compiler.IL;
|
||||||
|
|
||||||
|
|
||||||
namespace TestApp {
|
namespace TestApp {
|
||||||
class Program {
|
class Program {
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue