Skip to content

Commit

Permalink
Added binding for copy clr field value to stack
Browse files Browse the repository at this point in the history
  • Loading branch information
liiir1985 committed Apr 2, 2020
1 parent d32dcc7 commit c080159
Show file tree
Hide file tree
Showing 19 changed files with 721 additions and 162 deletions.
40 changes: 39 additions & 1 deletion ILRuntime/CLR/TypeSystem/CLRType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
using ILRuntime.CLR.Method;
using ILRuntime.Reflection;
using ILRuntime.Runtime.Enviorment;
using ILRuntime.Runtime.Stack;

namespace ILRuntime.CLR.TypeSystem
{
public class CLRType : IType
public unsafe class CLRType : IType
{
Type clrType;
bool isPrimitive, isValueType, isEnum;
Expand All @@ -24,6 +25,8 @@ public class CLRType : IType
Dictionary<int, FieldInfo> fieldInfoCache;
Dictionary<int, CLRFieldGetterDelegate> fieldGetterCache;
Dictionary<int, CLRFieldSetterDelegate> fieldSetterCache;
Dictionary<int, KeyValuePair<CLRFieldBindingDelegate, CLRFieldBindingDelegate>> fieldBindingCache;

Dictionary<int, int> fieldIdxMapping;
IType[] orderedFieldTypes;

Expand Down Expand Up @@ -349,6 +352,22 @@ public object GetFieldValue(int hash, object target)
return null;
}

public bool CopyFieldToStack(int hash, object target, Runtime.Intepreter.ILIntepreter intp, ref StackObject* esp, IList<object> mStack)
{
if (fieldMapping == null)
InitializeFields();
if (fieldBindingCache == null)
return false;
var binding = GetFieldBinding(hash);
if (binding.Key != null)
{
esp = binding.Key(ref target, intp, esp, mStack);
return true;
}
else
return false;
}

public void SetStaticFieldValue(int hash, object value)
{
if (fieldMapping == null)
Expand Down Expand Up @@ -388,6 +407,18 @@ public unsafe void SetFieldValue(int hash, ref object target, object value)
}
}

KeyValuePair<CLRFieldBindingDelegate,CLRFieldBindingDelegate> GetFieldBinding(int hash)
{
var dic = fieldBindingCache;
KeyValuePair<CLRFieldBindingDelegate, CLRFieldBindingDelegate> res;
if (dic != null && dic.TryGetValue(hash, out res))
return res;
else if (BaseType != null)
return ((CLRType)BaseType).GetFieldBinding(hash);
else
return default(KeyValuePair<CLRFieldBindingDelegate, CLRFieldBindingDelegate>);
}

private CLRFieldGetterDelegate GetFieldGetter(int hash)
{
var dic = fieldGetterCache;
Expand Down Expand Up @@ -517,6 +548,13 @@ void InitializeFields()
if (fieldSetterCache == null) fieldSetterCache = new Dictionary<int, CLRFieldSetterDelegate>();
fieldSetterCache[hashCode] = setter;
}

KeyValuePair<CLRFieldBindingDelegate, CLRFieldBindingDelegate> binding;
if(AppDomain.FieldBindingMap.TryGetValue(i, out binding))
{
if (fieldBindingCache == null) fieldBindingCache = new Dictionary<int, KeyValuePair<CLRFieldBindingDelegate, CLRFieldBindingDelegate>>();
fieldBindingCache[hashCode] = binding;
}
}
if (orderedFieldTypes != null)
{
Expand Down
4 changes: 2 additions & 2 deletions ILRuntime/Runtime/CLRBinding/BindingCodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public static void Register(ILRuntime.Runtime.Enviorment.AppDomain app)
ConstructorInfo[] ctors = i.GetConstructors(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly);
string ctorRegisterCode = i.GenerateConstructorRegisterCode(ctors, excludeMethods);
string methodWraperCode = i.GenerateMethodWraperCode(methods, realClsName, excludeMethods, valueTypeBinders, null);
string fieldWraperCode = i.GenerateFieldWraperCode(fields, realClsName, excludeFields);
string fieldWraperCode = i.GenerateFieldWraperCode(fields, realClsName, excludeFields, valueTypeBinders, null);
string cloneWraperCode = i.GenerateCloneWraperCode(fields, realClsName);
string ctorWraperCode = i.GenerateConstructorWraperCode(ctors, realClsName, excludeMethods, valueTypeBinders);

Expand Down Expand Up @@ -256,7 +256,7 @@ public static void Register(ILRuntime.Runtime.Enviorment.AppDomain app)
ConstructorInfo[] ctors = info.Value.Constructors.ToArray();
string ctorRegisterCode = i.GenerateConstructorRegisterCode(ctors, excludeMethods);
string methodWraperCode = i.GenerateMethodWraperCode(methods, realClsName, excludeMethods, valueTypeBinders, domain);
string fieldWraperCode = fields.Length > 0 ? i.GenerateFieldWraperCode(fields, realClsName, excludeFields) : null;
string fieldWraperCode = fields.Length > 0 ? i.GenerateFieldWraperCode(fields, realClsName, excludeFields, valueTypeBinders, domain) : null;
string cloneWraperCode = null;
if (info.Value.ValueTypeNeeded)
{
Expand Down
89 changes: 89 additions & 0 deletions ILRuntime/Runtime/CLRBinding/BindingGeneratorExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,95 @@ internal static void AppendParameters(this ParameterInfo[] param, StringBuilder
}
}

internal static void AppendArgumentCode(this Type p, StringBuilder sb, int idx, string name, List<Type> valueTypeBinders, bool isMultiArr, bool hasByRef, bool needFree)
{
string clsName, realClsName;
bool isByRef;
p.GetClassName(out clsName, out realClsName, out isByRef);
var pt = p.IsByRef ? p.GetElementType() : p;
string shouldFreeParam = hasByRef ? "false" : "true";

if (pt.IsValueType && !pt.IsPrimitive && valueTypeBinders != null && valueTypeBinders.Contains(pt))
{
if (isMultiArr)
sb.AppendLine(string.Format(" {0} a{1} = new {0}();", realClsName, idx));
else
sb.AppendLine(string.Format(" {0} @{1} = new {0}();", realClsName, name));

sb.AppendLine(string.Format(" if (ILRuntime.Runtime.Generated.CLRBindings.s_{0}_Binder != null) {{", clsName));

if (isMultiArr)
sb.AppendLine(string.Format(" ILRuntime.Runtime.Generated.CLRBindings.s_{1}_Binder.ParseValue(ref a{0}, __intp, ptr_of_this_method, __mStack, {2});", idx, clsName, shouldFreeParam));
else
sb.AppendLine(string.Format(" ILRuntime.Runtime.Generated.CLRBindings.s_{1}_Binder.ParseValue(ref @{0}, __intp, ptr_of_this_method, __mStack, {2});", name, clsName, shouldFreeParam));

sb.AppendLine(" } else {");

if (isByRef)
sb.AppendLine(" ptr_of_this_method = ILIntepreter.GetObjectAndResolveReference(ptr_of_this_method);");
if (isMultiArr)
sb.AppendLine(string.Format(" a{0} = {1};", idx, p.GetRetrieveValueCode(realClsName)));
else
sb.AppendLine(string.Format(" @{0} = {1};", name, p.GetRetrieveValueCode(realClsName)));
if (!hasByRef && needFree)
sb.AppendLine(" __intp.Free(ptr_of_this_method);");

sb.AppendLine(" }");
}
else
{
if (isByRef)
{
if (p.GetElementType().IsPrimitive)
{
if (pt == typeof(int) || pt == typeof(uint) || pt == typeof(short) || pt == typeof(ushort) || pt == typeof(byte) || pt == typeof(sbyte) || pt == typeof(char))
{
if (pt == typeof(int))
sb.AppendLine(string.Format(" {0} @{1} = __intp.RetriveInt32(ptr_of_this_method, __mStack);", realClsName, name));
else
sb.AppendLine(string.Format(" {0} @{1} = ({0})__intp.RetriveInt32(ptr_of_this_method, __mStack);", realClsName, name));
}
else if (pt == typeof(long) || pt == typeof(ulong))
{
if (pt == typeof(long))
sb.AppendLine(string.Format(" {0} @{1} = __intp.RetriveInt64(ptr_of_this_method, __mStack);", realClsName, name));
else
sb.AppendLine(string.Format(" {0} @{1} = ({0})__intp.RetriveInt64(ptr_of_this_method, __mStack);", realClsName, name));
}
else if (pt == typeof(float))
{
sb.AppendLine(string.Format(" {0} @{1} = __intp.RetriveFloat(ptr_of_this_method, __mStack);", realClsName, name));
}
else if (pt == typeof(double))
{
sb.AppendLine(string.Format(" {0} @{1} = __intp.RetriveDouble(ptr_of_this_method, __mStack);", realClsName, name));
}
else if (pt == typeof(bool))
{
sb.AppendLine(string.Format(" {0} @{1} = __intp.RetriveInt32(ptr_of_this_method, __mStack) == 1;", realClsName, name));
}
else
throw new NotSupportedException();
}
else
{
sb.AppendLine(string.Format(" {0} @{1} = ({0})typeof({0}).CheckCLRTypes(__intp.RetriveObject(ptr_of_this_method, __mStack));", realClsName, name));
}

}
else
{
if (isMultiArr)
sb.AppendLine(string.Format(" {0} a{1} = {2};", realClsName, idx, p.GetRetrieveValueCode(realClsName)));
else
sb.AppendLine(string.Format(" {0} @{1} = {2};", realClsName, name, p.GetRetrieveValueCode(realClsName)));
if (!hasByRef && !p.IsPrimitive && needFree)
sb.AppendLine(" __intp.Free(ptr_of_this_method);");

}
}
}

internal static string GetRetrieveValueCode(this Type type, string realClsName)
{
if (type.IsByRef)
Expand Down
77 changes: 62 additions & 15 deletions ILRuntime/Runtime/CLRBinding/FieldBindingGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,19 @@ internal static string GenerateFieldRegisterCode(this Type type, FieldInfo[] fie
if (!i.IsInitOnly && !i.IsLiteral)
{
sb.AppendLine(string.Format(" app.RegisterCLRFieldSetter(field, set_{0}_{1});", i.Name, idx));
sb.AppendLine(string.Format(" app.RegisterCLRFieldBinding(field, CopyToStack_{0}_{1}, AssignFromStack_{0}_{1});", i.Name, idx));
}
else
{
sb.AppendLine(string.Format(" app.RegisterCLRFieldBinding(field, CopyToStack_{0}_{1}, null);", i.Name, idx));
}

idx++;
}
return sb.ToString();
}

internal static string GenerateFieldWraperCode(this Type type, FieldInfo[] fields, string typeClsName, HashSet<FieldInfo> excludes)
internal static string GenerateFieldWraperCode(this Type type, FieldInfo[] fields, string typeClsName, HashSet<FieldInfo> excludes, List<Type> valueTypeBinders, Enviorment.AppDomain domain)
{
StringBuilder sb = new StringBuilder();

Expand All @@ -56,33 +61,75 @@ internal static string GenerateFieldWraperCode(this Type type, FieldInfo[] field
sb.AppendLine(string.Format(" return (({0})o).{1};", typeClsName, i.Name));
}
sb.AppendLine(" }");
sb.AppendLine();
sb.AppendLine(string.Format(" static StackObject* CopyToStack_{0}_{1}(ref object o, ILIntepreter __intp, StackObject* __ret, IList<object> __mStack)", i.Name, idx));
sb.AppendLine(" {");
if (i.IsStatic)
{
sb.AppendLine(string.Format(" var result_of_this_method = {0}.{1};", typeClsName, i.Name));
}
else
{
sb.AppendLine(string.Format(" var result_of_this_method = (({0})o).{1};", typeClsName, i.Name));
}
string clsName, realClsName;
bool isByRef;
i.FieldType.GetClassName(out clsName, out realClsName, out isByRef);

if (i.FieldType.IsValueType && !i.FieldType.IsPrimitive && valueTypeBinders != null && valueTypeBinders.Contains(i.FieldType))
{

sb.AppendLine(string.Format(" if (ILRuntime.Runtime.Generated.CLRBindings.s_{0}_Binder != null) {{", clsName));

sb.AppendLine(string.Format(" ILRuntime.Runtime.Generated.CLRBindings.s_{0}_Binder.PushValue(ref result_of_this_method, __intp, __ret, __mStack);", clsName));
sb.AppendLine(" return __ret + 1;");

sb.AppendLine(" } else {");

i.FieldType.GetReturnValueCode(sb, domain);

sb.AppendLine(" }");
}
else
{
i.FieldType.GetReturnValueCode(sb, domain);
}
sb.AppendLine(" }");
sb.AppendLine();

if (!i.IsInitOnly && !i.IsLiteral)
{
sb.AppendLine(string.Format(" static void set_{0}_{1}(ref object o, object v)", i.Name, idx));
sb.AppendLine(" {");
string clsName, realClsName;
bool isByRef;
i.FieldType.GetClassName(out clsName, out realClsName, out isByRef);
if (i.IsStatic)
{
sb.AppendLine(string.Format(" {0}.{1} = ({2})v;", typeClsName, i.Name, realClsName));
}
else
{
if (CheckCanPinn(type))
{
sb.AppendLine(" var h = GCHandle.Alloc(o, GCHandleType.Pinned);");
sb.AppendLine(string.Format(" {0}* p = ({0} *)(void *)h.AddrOfPinnedObject();", typeClsName));
sb.AppendLine(string.Format(" p->{0} = ({1})v;", i.Name, realClsName));
sb.AppendLine(" h.Free();");
}
else
{
sb.AppendLine(string.Format(" (({0})o).{1} = ({2})v;", typeClsName, i.Name, realClsName));
}
sb.AppendLine(string.Format(" {0} ins =({0})o;", typeClsName));
sb.AppendLine(string.Format(" ins.{0} = ({1})v;", i.Name, realClsName));
sb.AppendLine(" o = ins;");
}
sb.AppendLine(" }");
sb.AppendLine();
sb.AppendLine(string.Format(" static StackObject* AssignFromStack_{0}_{1}(ref object o, ILIntepreter __intp, StackObject* ptr_of_this_method, IList<object> __mStack)", i.Name, idx));
sb.AppendLine(" {");
sb.AppendLine(" ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain;");
i.FieldType.AppendArgumentCode(sb, 0, i.Name, valueTypeBinders, false, false, false);
if (i.IsStatic)
{
sb.AppendLine(string.Format(" {0}.{1} = @{1};", typeClsName, i.Name));
}
else
{
sb.AppendLine(string.Format(" {0} ins =({0})o;", typeClsName));
sb.AppendLine(string.Format(" ins.{0} = @{0};", i.Name));
sb.AppendLine(" o = ins;");
}
sb.AppendLine(" return ptr_of_this_method;");
sb.AppendLine(" }");
sb.AppendLine();
}
idx++;
}
Expand Down
Loading

0 comments on commit c080159

Please sign in to comment.