Skip to content

Commit

Permalink
slightly improved performance on accessing fields through aggressive …
Browse files Browse the repository at this point in the history
…inlining
  • Loading branch information
liiir1985 committed Feb 6, 2025
1 parent 2416133 commit 32fd571
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 156 deletions.
326 changes: 171 additions & 155 deletions ILRuntime/Runtime/Intepreter/RegisterVM/ILIntepreter.Register.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
using ILRuntime.Runtime.Intepreter.OpCodes;
using ILRuntime.Runtime.Enviorment;
using ILRuntime.CLR.Utils;
using System.Collections;


#if DEBUG && !DISABLE_ILRUNTIME_DEBUG
using AutoList = System.Collections.Generic.List<object>;
Expand Down Expand Up @@ -5395,7 +5397,171 @@ void LoadFromFieldReferenceToRegister(ref RegisterFrameInfo info, object obj, in
}
}

#if NET_4_6 || NET_STANDARD_2_0
void CopyStaticFieldToRegister(ref RegisterFrameInfo info, short reg, int idx, StackObject* v, StackObject* val, AutoList mStack)
{
var type = info.Intepreter.AppDomain.GetType(val->Value);
if (type is ILType)
{
var st = type as ILType;
if (st.IsValueType)
{
if (v->ObjectType == ObjectTypes.ValueTypeObjectReference)
{
var dst = *(StackObject**)&v->Value;
if (dst->Value != st.TypeIndex)
{
stack.FreeRegisterValueType(v);
stack.AllocValueType(v, st, true);
}
}
st.StaticInstance.CopyToRegister(val->ValueLow, ref info, reg);
}
else if (st.IsPrimitive)
{
st.StaticInstance.PushToStack(val->ValueLow, v, info.Intepreter, mStack);
}
else
{
v->ObjectType = ObjectTypes.Object;
v->Value = idx;
mStack[idx] = st.StaticInstance[val->ValueLow];
}
}
else
{
var st = type as CLRType;
var binder = st.ValueTypeBinder;
if (binder != null)
{
if (v->ObjectType == ObjectTypes.ValueTypeObjectReference)
{
var dst = *(StackObject**)&v->Value;
if (dst->Value != st.TypeIndex)
{
stack.FreeRegisterValueType(v);
stack.AllocValueType(v, st, true);
}
}
StackObject tmp;
StackObject* esp = &tmp;
if (!st.CopyFieldToStack(val->ValueLow, null, this, ref esp, mStack))
{
var obj = ((CLRType)type).GetFieldValue(val->ValueLow, null);
if (obj is CrossBindingAdaptorType)
obj = ((CrossBindingAdaptorType)obj).ILInstance;
AssignToRegister(ref info, reg, obj, false);
}
else
{
PopToRegister(ref info, reg, esp);
}
}
else
{
var obj = st.GetFieldValue(val->ValueLow, null);
if (obj is CrossBindingAdaptorType)
obj = ((CrossBindingAdaptorType)obj).ILInstance;
v->ObjectType = ObjectTypes.Object;
v->Value = idx;
mStack[idx] = obj;
}
}
}

void CopyValueTypeFieldToRegister(ref RegisterFrameInfo info, int idx, StackObject* v, StackObject* val, AutoList mStack, AutoList mStackSrc)
{
var obj = mStackSrc[val->Value];
if (obj is ILTypeInstance)
{
var st = ((ILTypeInstance)obj).Type;
//Delegate and enum instance's type is null
if (st != null && st.IsValueType)
{
var dst = *(StackObject**)&v->Value;
if (dst->Value != st.TypeIndex)
{
stack.FreeRegisterValueType(v);
stack.AllocValueType(v, st, true);
dst = *(StackObject**)&v->Value;
}
((ILTypeInstance)obj).CopyValueTypeToStack(dst, mStack);
}
else
{
v->ObjectType = ObjectTypes.Object;
v->Value = idx;
mStack[idx] = obj;
}
}
else
{
if (obj != null)
{
var st = domain.GetType(obj.GetType()) as CLRType;
var binder = st.ValueTypeBinder;
if (binder != null)
{
var dst = *(StackObject**)&v->Value;
if (dst->Value != st.TypeIndex)
{
stack.FreeRegisterValueType(v);
stack.AllocValueType(v, st, true);
dst = *(StackObject**)&v->Value;
}
binder.CopyValueTypeToStack(obj, dst, mStack);
}
else
{
v->ObjectType = ObjectTypes.Object;
v->Value = idx;
mStack[idx] = obj;
}
}
else
{
v->ObjectType = ObjectTypes.Object;
v->Value = idx;
mStack[idx] = obj;
}
}
}

void CopyValueTypeToRegister(ref RegisterFrameInfo info, StackObject* v, StackObject* val, AutoList mStack)
{
if (v->ObjectType == ObjectTypes.ValueTypeObjectReference)
{
bool noCheck = false;
if (!CanCopyStackValueType(val, v))
{
var dst = *(StackObject**)&val->Value;
var ct = domain.GetTypeByIndex(dst->Value);
stack.FreeRegisterValueType(v);
StackObject* endAddr = null;
int start = int.MaxValue, end = 0;
stack.CountValueTypeManaged(v, ref start, ref end, &endAddr);
noCheck = val <= ResolveReference(v) && val > endAddr;
stack.AllocValueType(v, ct, true, noCheck);
}
#if DEBUG
CopyStackValueType(val, v, mStack, noCheck);
#else
CopyStackValueType(val, v, mStack);
#endif
}
else
{
if (v >= info.RegisterStart && v < info.RegisterEnd)
{
var dst = ResolveReference(val);
var type = domain.GetTypeByIndex(dst->Value);
stack.AllocValueType(v, type, true);
CopyStackValueType(val, v, mStack);
}
else
throw new NotImplementedException();
}
}
#if NET_4_6 || NET_STANDARD_2_0 || NET_STANDARD_2_1 || NET_STANDARD_4_7 || NET_STANDARD_4_7_2
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
#endif
internal void CopyToRegister(ref RegisterFrameInfo info, short reg, StackObject* val, AutoList mStackSrc = null)
Expand All @@ -5416,134 +5582,15 @@ internal void CopyToRegister(ref RegisterFrameInfo info, short reg, StackObject*
break;
case ObjectTypes.StaticFieldReference:
{
var type = info.Intepreter.AppDomain.GetType(val->Value);
if (type is ILType)
{
var st = type as ILType;
if (st.IsValueType)
{
if (v->ObjectType == ObjectTypes.ValueTypeObjectReference)
{
var dst = *(StackObject**)&v->Value;
if (dst->Value != st.TypeIndex)
{
stack.FreeRegisterValueType(v);
stack.AllocValueType(v, st, true);
}
}
st.StaticInstance.CopyToRegister(val->ValueLow, ref info, reg);
}
else if (st.IsPrimitive)
{
st.StaticInstance.PushToStack(val->ValueLow, v, info.Intepreter, mStack);
}
else
{
v->ObjectType = ObjectTypes.Object;
v->Value = idx;
mStack[idx] = st.StaticInstance[val->ValueLow];
}
}
else
{
var st = type as CLRType;
var binder = st.ValueTypeBinder;
if (binder != null)
{
if (v->ObjectType == ObjectTypes.ValueTypeObjectReference)
{
var dst = *(StackObject**)&v->Value;
if (dst->Value != st.TypeIndex)
{
stack.FreeRegisterValueType(v);
stack.AllocValueType(v, st, true);
}
}
StackObject tmp;
StackObject* esp = &tmp;
if (!st.CopyFieldToStack(val->ValueLow, null, this, ref esp, mStack))
{
var obj = ((CLRType)type).GetFieldValue(val->ValueLow, null);
if (obj is CrossBindingAdaptorType)
obj = ((CrossBindingAdaptorType)obj).ILInstance;
AssignToRegister(ref info, reg, obj, false);
}
else
{
PopToRegister(ref info, reg, esp);
}
}
else
{
var obj = st.GetFieldValue(val->ValueLow, null);
if (obj is CrossBindingAdaptorType)
obj = ((CrossBindingAdaptorType)obj).ILInstance;
v->ObjectType = ObjectTypes.Object;
v->Value = idx;
mStack[idx] = obj;
}
}
CopyStaticFieldToRegister(ref info, reg, idx, v, val, mStack);
}
break;
case ObjectTypes.Object:
case ObjectTypes.FieldReference:
case ObjectTypes.ArrayReference:
if (v->ObjectType == ObjectTypes.ValueTypeObjectReference)
{
var obj = mStackSrc[val->Value];
if (obj is ILTypeInstance)
{
var st = ((ILTypeInstance)obj).Type;
//Delegate and enum instance's type is null
if (st != null && st.IsValueType)
{
var dst = *(StackObject**)&v->Value;
if (dst->Value != st.TypeIndex)
{
stack.FreeRegisterValueType(v);
stack.AllocValueType(v, st, true);
dst = *(StackObject**)&v->Value;
}
((ILTypeInstance)obj).CopyValueTypeToStack(dst, mStack);
}
else
{
v->ObjectType = ObjectTypes.Object;
v->Value = idx;
mStack[idx] = obj;
}
}
else
{
if (obj != null)
{
var st = domain.GetType(obj.GetType()) as CLRType;
var binder = st.ValueTypeBinder;
if (binder != null)
{
var dst = *(StackObject**)&v->Value;
if (dst->Value != st.TypeIndex)
{
stack.FreeRegisterValueType(v);
stack.AllocValueType(v, st, true);
dst = *(StackObject**)&v->Value;
}
binder.CopyValueTypeToStack(obj, dst, mStack);
}
else
{
v->ObjectType = ObjectTypes.Object;
v->Value = idx;
mStack[idx] = obj;
}
}
else
{
v->ObjectType = ObjectTypes.Object;
v->Value = idx;
mStack[idx] = obj;
}
}
CopyValueTypeFieldToRegister(ref info, idx, v, val, mStack, mStackSrc);
}
else
{
Expand All @@ -5554,38 +5601,7 @@ internal void CopyToRegister(ref RegisterFrameInfo info, short reg, StackObject*
}
break;
case ObjectTypes.ValueTypeObjectReference:
if (v->ObjectType == ObjectTypes.ValueTypeObjectReference)
{
bool noCheck = false;
if (!CanCopyStackValueType(val, v))
{
var dst = *(StackObject**)&val->Value;
var ct = domain.GetTypeByIndex(dst->Value);
stack.FreeRegisterValueType(v);
StackObject* endAddr = null;
int start = int.MaxValue, end = 0;
stack.CountValueTypeManaged(v, ref start, ref end, &endAddr);
noCheck = val <= ResolveReference(v) && val > endAddr;
stack.AllocValueType(v, ct, true, noCheck);
}
#if DEBUG
CopyStackValueType(val, v, mStack, noCheck);
#else
CopyStackValueType(val, v, mStack);
#endif
}
else
{
if (v >= info.RegisterStart && v < info.RegisterEnd)
{
var dst = ResolveReference(val);
var type = domain.GetTypeByIndex(dst->Value);
stack.AllocValueType(v, type, true);
CopyStackValueType(val, v, mStack);
}
else
throw new NotImplementedException();
}
CopyValueTypeToRegister(ref info, v, val, mStack);
//FreeStackValueType(val);
break;
default:
Expand All @@ -5595,7 +5611,7 @@ internal void CopyToRegister(ref RegisterFrameInfo info, short reg, StackObject*
}
}

#if NET_4_6 || NET_STANDARD_2_0
#if NET_4_6 || NET_STANDARD_2_0 || NET_STANDARD_2_1 || NET_STANDARD_4_7 || NET_STANDARD_4_7_2
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
#endif
static int GetManagedStackIndex(ref RegisterFrameInfo info, short reg)
Expand Down
2 changes: 1 addition & 1 deletion TestCases/Test01.cs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ public static void UnitTest_Performance11()
Console.WriteLine(string.Format("time=" + sw.ElapsedMilliseconds + ", cps:{0:0}", (1000000 * 1000 / sw.ElapsedMilliseconds)));
}
const int T12_NOBJS = 100;
const int T12_NLOOP = 1000000;
const int T12_NLOOP = 10000000;
int A;
string B;
float C;
Expand Down

0 comments on commit 32fd571

Please sign in to comment.