[Interpreter] Multi-dim Array and Object instantiation (#8130)

This commit is contained in:
Toni Solarin-Sodara 2020-05-14 04:46:24 +01:00 коммит произвёл GitHub
Родитель c2e918fe57
Коммит 43e327cbc0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 114 добавлений и 12 удалений

Просмотреть файл

@ -25,6 +25,7 @@ using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Threading;
using Internal.Runtime.CompilerHelpers;
using Internal.Runtime.CompilerServices;
#if TARGET_64BIT
@ -161,6 +162,20 @@ namespace Internal.Runtime.Augments
return Array.NewMultiDimArray(typeHandleForArrayType.ToEETypePtr(), pLengths, lengths.Length);
}
//
// Helper to create an array from a newobj instruction
//
public static unsafe Array NewObjArray(RuntimeTypeHandle typeHandleForArrayType, int[] arguments)
{
EETypePtr eeTypePtr = typeHandleForArrayType.ToEETypePtr();
Debug.Assert(eeTypePtr.IsArray);
fixed (int* pArguments = arguments)
{
return ArrayHelpers.NewObjArray((IntPtr)eeTypePtr.ToPointer(), arguments.Length, pArguments);
}
}
public static ref byte GetSzArrayElementAddress(Array array, int index)
{
if ((uint)index >= (uint)array.Length)

Просмотреть файл

@ -18,7 +18,7 @@ namespace Internal.Runtime.CompilerHelpers
/// Helper for array allocations via `newobj` IL instruction. Dimensions are passed in as block of integers.
/// The content of the dimensions block may be modified by the helper.
/// </summary>
private static unsafe Array NewObjArray(IntPtr pEEType, int nDimensions, int* pDimensions)
public static unsafe Array NewObjArray(IntPtr pEEType, int nDimensions, int* pDimensions)
{
EETypePtr eeType = new EETypePtr(pEEType);
Debug.Assert(eeType.IsArray);

Просмотреть файл

@ -313,7 +313,8 @@ namespace Internal.Runtime.Interpreter
InterpretLoadConstant((string)_methodIL.GetObject(reader.ReadILToken()));
break;
case ILOpcode.newobj:
throw new NotImplementedException();
InterpretNewObj(reader.ReadILToken());
break;
case ILOpcode.castclass:
throw new NotImplementedException();
case ILOpcode.isinst:
@ -2449,10 +2450,9 @@ again:
// Holds information about a method call
private struct MethodCallInfo
{
public int ArgCount;
public TypeDesc OwningType;
public IntPtr MethodAddress;
public IntPtr UnboxingStubAddress;
public CallConverter.CallingConvention CallingConvention;
public TypeLoaderEnvironment.MethodAddressType MethodAddressType;
public MethodSignature Signature;
public LocalVariableType[] LocalVariableTypes;
@ -2461,10 +2461,19 @@ again:
private void InterpretCallDelegate(ref MethodCallInfo callInfo, ref LocalVariableSet localVariableSet)
{
for (int i = callInfo.ArgCount; i > 0; i--)
for (int i = callInfo.LocalVariableTypes.Length - 1; i > 0; i--)
{
StackItem stackItem = PopWithValidation();
TypeDesc argumentType = callInfo.Signature[i - 1];
TypeDesc argumentType = default;
if (i == 1 && !callInfo.Signature.IsStatic)
{
argumentType = callInfo.OwningType;
}
else
{
argumentType = callInfo.Signature[i - (callInfo.Signature.IsStatic ? 1 : 2)];
}
setvar:
switch (argumentType.Category)
@ -2521,7 +2530,8 @@ setvar:
if (callInfo.MethodAddress != IntPtr.Zero && callInfo.MethodAddressType == TypeLoaderEnvironment.MethodAddressType.Exact)
{
DynamicCallSignature dynamicCallSignature = new DynamicCallSignature(callInfo.CallingConvention, callInfo.LocalVariableTypes, callInfo.LocalVariableTypes.Length);
CallConverter.CallingConvention callingConvention = callInfo.Signature.IsStatic ? CallConverter.CallingConvention.ManagedStatic : CallConverter.CallingConvention.ManagedInstance;
DynamicCallSignature dynamicCallSignature = new DynamicCallSignature(callingConvention, callInfo.LocalVariableTypes, callInfo.LocalVariableTypes.Length);
CallInterceptor.CallInterceptor.MakeDynamicCall(callInfo.MethodAddress, dynamicCallSignature, localVariableSet);
}
else
@ -2595,7 +2605,9 @@ getvar:
private void InterpretCall(int token)
{
MethodDesc method = (MethodDesc)_methodIL.GetObject(token);
MethodSignature signature = method.Signature;
int nSignature = signature.Length;
TypeDesc owningType = method.OwningType;
TypeDesc returnType = signature.ReturnType;
@ -2605,7 +2617,7 @@ getvar:
int delta = (signature.IsStatic ? 1 : 2);
LocalVariableType[] localVariableTypes = new LocalVariableType[signature.Length + delta];
LocalVariableType[] localVariableTypes = new LocalVariableType[nSignature + delta];
if (returnType.IsByRef)
{
// TODO: Unwrap ref types
@ -2615,9 +2627,17 @@ getvar:
localVariableTypes[0] = new LocalVariableType(returnType.GetRuntimeTypeHandle(), false, returnType.IsByRef);
if (!signature.IsStatic)
localVariableTypes[1] = new LocalVariableType(owningType.GetRuntimeTypeHandle(), false, owningType.IsByRef);
{
if (owningType.IsByRef)
{
// TODO: Unwrap ref types
throw new NotImplementedException();
}
for (int i = 0; i < signature.Length; i++)
localVariableTypes[1] = new LocalVariableType(owningType.GetRuntimeTypeHandle(), false, owningType.IsByRef);
}
for (int i = 0; i < nSignature; i++)
{
var argument = signature[i];
if (argument.IsByRef)
@ -2632,11 +2652,10 @@ getvar:
TypeLoaderEnvironment.TryGetMethodAddressFromMethodDesc(method, out IntPtr methodAddress, out IntPtr unboxingStubAddress, out TypeLoaderEnvironment.MethodAddressType foundAddressType);
var callInfo = new MethodCallInfo();
callInfo.ArgCount = signature.Length + (delta - 1);
callInfo.OwningType = !signature.IsStatic ? owningType : null;
callInfo.MethodAddress = methodAddress;
callInfo.MethodAddressType = foundAddressType;
callInfo.UnboxingStubAddress = unboxingStubAddress;
callInfo.CallingConvention = signature.IsStatic ? CallConverter.CallingConvention.ManagedStatic : CallConverter.CallingConvention.ManagedInstance;
callInfo.Signature = signature;
callInfo.LocalVariableTypes = localVariableTypes;
@ -2645,5 +2664,73 @@ getvar:
if (!signature.ReturnType.IsVoid)
_stack.Push(callInfo.ReturnValue);
}
private unsafe void InterpretNewObj(int token)
{
MethodDesc method = (MethodDesc)_methodIL.GetObject(token);
TypeDesc owningType = method.OwningType;
MethodSignature signature = method.Signature;
int nSignature = signature.Length;
StackItem[] arguments = new StackItem[nSignature];
for (int i = 0; i < arguments.Length; i++)
{
arguments[i] = PopWithValidation();
}
if (owningType.IsArray)
{
int[] lArguments = new int[nSignature];
for (int i = nSignature - 1; i >= 0; i--)
{
lArguments[(nSignature - 1) - i] = arguments[i].AsInt32();
}
Array array = RuntimeAugments.NewObjArray(owningType.GetRuntimeTypeHandle(), lArguments);
_stack.Push(StackItem.FromObjectRef(array));
return;
}
object @this = RuntimeAugments.RawNewObject(owningType.GetRuntimeTypeHandle());
LocalVariableType[] localVariableTypes = new LocalVariableType[nSignature + 2];
localVariableTypes[0] = new LocalVariableType(_context.GetWellKnownType(WellKnownType.Void).GetRuntimeTypeHandle(), false, false);
localVariableTypes[1] = new LocalVariableType(owningType.GetRuntimeTypeHandle(), false, false);
for (int i = 0; i < nSignature; i++)
{
TypeDesc argument = signature[i];
if (argument.IsByRef)
{
// TODO: Unwrap ref types
throw new NotImplementedException();
}
localVariableTypes[i + 2] = new LocalVariableType(argument.GetRuntimeTypeHandle(), false, argument.IsByRef);
}
_stack.Push(StackItem.FromObjectRef(@this));
for (int i = nSignature - 1; i >= 0; i--)
{
_stack.Push(arguments[i]);
}
TypeLoaderEnvironment.TryGetMethodAddressFromMethodDesc(method, out IntPtr methodAddress, out IntPtr unboxingStubAddress, out TypeLoaderEnvironment.MethodAddressType foundAddressType);
var callInfo = new MethodCallInfo();
callInfo.OwningType = !signature.IsStatic ? owningType : null;
callInfo.MethodAddress = methodAddress;
callInfo.MethodAddressType = foundAddressType;
callInfo.UnboxingStubAddress = unboxingStubAddress;
callInfo.Signature = signature;
callInfo.LocalVariableTypes = localVariableTypes;
LocalVariableSet.SetupArbitraryLocalVariableSet(InterpretCallDelegate, ref callInfo, localVariableTypes);
_stack.Push(StackItem.FromObjectRef(@this));
}
}
}