Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kotas <jkotas@microsoft.com>2017-06-11 04:29:59 +0300
committerGitHub <noreply@github.com>2017-06-11 04:29:59 +0300
commite3be4f12df5eb685733f19978b442168b8e8d1f1 (patch)
tree3e807d7f164266e33770ee8f33146977f0d79125
parent13f87340d9089cb4a1d3828a4e67c846491526d3 (diff)
parent208de3dd1aa5f0de33c44bc024dc5122eb455208 (diff)
Merge pull request #3860 from dotnet/master
Merge master to nmirror
-rw-r--r--src/Common/src/Internal/Runtime/MetadataBlob.cs2
-rw-r--r--src/Common/src/TypeSystem/CodeGen/INonEmittableType.cs (renamed from src/ILCompiler.Compiler/src/Compiler/INonEmittableType.cs)2
-rw-r--r--src/Common/src/TypeSystem/CodeGen/NativeStructType.CodeGen.cs11
-rw-r--r--src/Common/src/TypeSystem/IL/HelperExtensions.cs15
-rw-r--r--src/Common/src/TypeSystem/IL/ILProvider.cs12
-rw-r--r--src/Common/src/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.cs29
-rw-r--r--src/Common/src/TypeSystem/Interop/IL/NativeStructType.cs18
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/Compilation.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs1
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CodeBasedDependencyAlgorithm.cs43
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs150
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs163
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDictionaryNode.cs3
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericLookupResult.cs5
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectWriter.cs3
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs6
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs7
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StructMarshallingStubMapNode.cs107
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunGenericHelperNode.cs1
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/VTableSliceNode.cs24
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/VirtualMethodUseNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/InteropStubManager.cs162
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/JitHelper.cs6
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs3
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/ReadyToRun.cs2
-rw-r--r--src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs121
-rw-r--r--src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj2
-rw-r--r--src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs2
-rw-r--r--src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj6
-rw-r--r--src/ILVerify/src/ILImporter.StackValue.cs5
-rw-r--r--src/ILVerify/src/ILImporter.Verify.cs35
-rw-r--r--src/ILVerify/src/ILVerify.csproj1
-rw-r--r--src/ILVerify/src/Resources/Strings.resx6
-rw-r--r--src/ILVerify/src/SimpleArrayOfTRuntimeInterfacesAlgorithm.cs64
-rw-r--r--src/ILVerify/src/SimpleTypeSystemContext.cs18
-rw-r--r--src/ILVerify/src/VerifierError.cs4
-rw-r--r--src/ILVerify/tests/ILTests/BranchingTests.il69
-rw-r--r--src/ILVerify/tests/ILTests/CastingTests.il211
-rw-r--r--src/ILVerify/tests/ILTests/LoadStoreIndirectTest.il11
-rw-r--r--src/JitInterface/src/CorInfoBase.cs172
-rw-r--r--src/JitInterface/src/CorInfoImpl.Intrinsics.cs12
-rw-r--r--src/JitInterface/src/CorInfoImpl.cs130
-rw-r--r--src/JitInterface/src/CorInfoTypes.cs4
-rw-r--r--src/JitInterface/src/ThunkGenerator/ThunkInput.txt3
-rw-r--r--src/JitInterface/src/ThunkGenerator/corinfo.h39
-rw-r--r--src/Native/Runtime/arm/CallDescrWorker.S25
-rw-r--r--src/Native/Runtime/arm/ExceptionHandling.S139
-rw-r--r--src/Native/Runtime/arm/StubDispatch.S75
-rw-r--r--src/Native/Runtime/arm/UniversalTransition.S80
-rw-r--r--src/Native/Runtime/arm/WriteBarriers.S34
-rw-r--r--src/Native/Runtime/rhassert.cpp4
-rw-r--r--src/Native/Runtime/rhassert.h10
-rw-r--r--src/Native/jitinterface/jitinterface.h29
-rw-r--r--src/Native/jitinterface/jitwrapper.cpp10
-rw-r--r--src/System.Private.CoreLib/shared/System/Char.cs1
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/DictionaryEntry.cs5
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Generic/KeyValuePair.cs5
-rw-r--r--src/System.Private.CoreLib/shared/System/DateTime.cs5
-rw-r--r--src/System.Private.CoreLib/shared/System/DateTimeOffset.cs9
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/SortVersion.cs1
-rw-r--r--src/System.Private.CoreLib/shared/System/StringComparer.cs22
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/ValueTuple.cs9
-rw-r--r--src/System.Private.CoreLib/shared/System/Version.cs9
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/Augments/InteropCallbacks.cs10
-rw-r--r--src/System.Private.CoreLib/src/System.Private.CoreLib.csproj7
-rw-r--r--src/System.Private.CoreLib/src/System/Activator.cs51
-rw-r--r--src/System.Private.CoreLib/src/System/Buffer.cs15
-rw-r--r--src/System.Private.CoreLib/src/System/EETypePtr.cs13
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs7
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/ClrThreadPool.HillClimbing.Complex.cs42
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/ClrThreadPool.HillClimbing.cs388
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/ClrThreadPool.cs48
-rw-r--r--src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/Callbacks.CoreRT.cs91
-rw-r--r--src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/LibraryInitializer.cs2
-rw-r--r--src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/RuntimeInteropData.CoreRT.cs203
-rw-r--r--src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/RuntimeInteropData.ProjectN.cs56
-rw-r--r--src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/RuntimeInteropData.cs (renamed from src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/Callbacks.ProjectN.cs)14
-rw-r--r--src/System.Private.Interop/src/System.Private.Interop.csproj5
-rw-r--r--src/System.Private.Interop/src/System/Runtime/InteropServices/Marshal.cs15
-rw-r--r--src/packaging/objectwriter/project.json (renamed from src/packaging/project.json)1
-rw-r--r--src/packaging/packages.targets7
-rw-r--r--src/packaging/ryujit/project.json13
-rw-r--r--tests/CoreCLR.issues.targets170
-rwxr-xr-xtests/runtest.sh6
-rw-r--r--tests/src/Simple/Generics/Generics.cs50
-rw-r--r--tests/src/Simple/PInvoke/PInvoke.cs30
90 files changed, 2660 insertions, 770 deletions
diff --git a/src/Common/src/Internal/Runtime/MetadataBlob.cs b/src/Common/src/Internal/Runtime/MetadataBlob.cs
index 2a3af789a..42fedd14e 100644
--- a/src/Common/src/Internal/Runtime/MetadataBlob.cs
+++ b/src/Common/src/Internal/Runtime/MetadataBlob.cs
@@ -21,7 +21,7 @@ namespace Internal.Runtime
EmbeddedMetadata = 13,
DefaultConstructorMap = 14,
UnboxingAndInstantiatingStubMap = 15,
- InvokeInstantiations = 16, // unused
+ StructMarshallingStubMap = 16,
DelegateMarshallingStubMap = 17,
GenericVirtualMethodTable = 18,
InterfaceGenericVirtualMethodTable = 19,
diff --git a/src/ILCompiler.Compiler/src/Compiler/INonEmittableType.cs b/src/Common/src/TypeSystem/CodeGen/INonEmittableType.cs
index 942fc93dd..24b1d2eee 100644
--- a/src/ILCompiler.Compiler/src/Compiler/INonEmittableType.cs
+++ b/src/Common/src/TypeSystem/CodeGen/INonEmittableType.cs
@@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-namespace ILCompiler
+namespace Internal.TypeSystem
{
/// <summary>
/// Used to mark TypeDesc types that are not part of the core type system
diff --git a/src/Common/src/TypeSystem/CodeGen/NativeStructType.CodeGen.cs b/src/Common/src/TypeSystem/CodeGen/NativeStructType.CodeGen.cs
new file mode 100644
index 000000000..8e2549913
--- /dev/null
+++ b/src/Common/src/TypeSystem/CodeGen/NativeStructType.CodeGen.cs
@@ -0,0 +1,11 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Internal.TypeSystem.Interop
+{
+ // Implements INonEmittableType
+ partial class NativeStructType : INonEmittableType
+ {
+ }
+}
diff --git a/src/Common/src/TypeSystem/IL/HelperExtensions.cs b/src/Common/src/TypeSystem/IL/HelperExtensions.cs
index 694430c8c..44ec59e00 100644
--- a/src/Common/src/TypeSystem/IL/HelperExtensions.cs
+++ b/src/Common/src/TypeSystem/IL/HelperExtensions.cs
@@ -77,6 +77,21 @@ namespace Internal.IL
}
/// <summary>
+ /// Retrieves a nested type on <paramref name="type"/> that is well known to the compiler.
+ /// Throws an exception if the nested type doesn't exist.
+ /// </summary>
+ public static MetadataType GetKnownNestedType(this MetadataType type, string name)
+ {
+ MetadataType nestedType = type.GetNestedType(name);
+ if (nestedType == null)
+ {
+ throw new InvalidOperationException(String.Format("Expected type '{0}' not found on type '{1}'", name, type));
+ }
+
+ return nestedType;
+ }
+
+ /// <summary>
/// Retrieves a namespace type in <paramref name= "module" /> that is well known to the compiler.
/// Throws an exception if the type doesn't exist.
/// </summary>
diff --git a/src/Common/src/TypeSystem/IL/ILProvider.cs b/src/Common/src/TypeSystem/IL/ILProvider.cs
index c1bcf486d..49930c921 100644
--- a/src/Common/src/TypeSystem/IL/ILProvider.cs
+++ b/src/Common/src/TypeSystem/IL/ILProvider.cs
@@ -90,11 +90,14 @@ namespace Internal.IL
if (owningType == null)
return null;
+ string methodName = method.Name;
+
switch (owningType.Name)
{
case "RuntimeHelpers":
{
- if (owningType.Namespace == "System.Runtime.CompilerServices" && method.Name == "IsReferenceOrContainsReferences")
+ if ((methodName == "IsReferenceOrContainsReferences" || methodName == "IsReference")
+ && owningType.Namespace == "System.Runtime.CompilerServices")
{
TypeDesc elementType = method.Instantiation[0];
@@ -102,8 +105,11 @@ namespace Internal.IL
if (elementType.IsCanonicalSubtype(CanonicalFormKind.Universal))
return null;
- bool result = elementType.IsGCPointer ||
- (elementType.IsDefType ? ((DefType)elementType).ContainsGCPointers : false);
+ bool result = elementType.IsGCPointer;
+ if (methodName == "IsReferenceOrContainsReferences")
+ {
+ result |= (elementType.IsDefType ? ((DefType)elementType).ContainsGCPointers : false);
+ }
return new ILStubMethodIL(method, new byte[] {
result ? (byte)ILOpcode.ldc_i4_1 : (byte)ILOpcode.ldc_i4_0,
diff --git a/src/Common/src/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.cs b/src/Common/src/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.cs
index 34a89d3aa..d23a8bcf0 100644
--- a/src/Common/src/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.cs
+++ b/src/Common/src/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.cs
@@ -93,6 +93,22 @@ namespace Internal.IL.Stubs
}
}
+ private TypeDesc GetNativeMethodParameterType(TypeDesc managedType, MarshalAsDescriptor marshalAs, InteropStateManager interopStateManager, bool isReturn, bool isAnsi)
+ {
+ TypeDesc nativeType;
+ try
+ {
+ nativeType = MarshalHelpers.GetNativeMethodParameterType(managedType, marshalAs, interopStateManager, isReturn, isAnsi);
+ }
+ catch (NotSupportedException)
+ {
+ // if marshalling is not supported for this type the generated stubs will emit appropriate
+ // error message. We just set native type to be same as managedtype
+ nativeType = managedType;
+ }
+ return nativeType;
+ }
+
public override MethodSignature Signature
{
get
@@ -123,7 +139,12 @@ namespace Internal.IL.Stubs
marshalAs = parameterMetadataArray[parameterIndex++].MarshalAsDescriptor;
}
- TypeDesc nativeReturnType = MarshalHelpers.GetNativeMethodParameterType(delegateSignature.ReturnType, null, _interopStateManager, true, isAnsi);
+ TypeDesc nativeReturnType = GetNativeMethodParameterType(delegateSignature.ReturnType,
+ marshalAs,
+ _interopStateManager,
+ isReturn:true,
+ isAnsi:isAnsi);
+
for (int i = 0; i < delegateSignature.Length; i++)
{
int sequence = i + 1;
@@ -142,7 +163,11 @@ namespace Internal.IL.Stubs
var managedType = isByRefType ? delegateSignature[i].GetParameterType() : delegateSignature[i];
- var nativeType = MarshalHelpers.GetNativeMethodParameterType(managedType, marshalAs, _interopStateManager, false, isAnsi);
+ var nativeType = GetNativeMethodParameterType(managedType,
+ marshalAs,
+ _interopStateManager,
+ isReturn:false,
+ isAnsi:isAnsi);
nativeParameterTypes[i] = isByRefType ? nativeType.MakePointerType() : nativeType;
}
diff --git a/src/Common/src/TypeSystem/Interop/IL/NativeStructType.cs b/src/Common/src/TypeSystem/Interop/IL/NativeStructType.cs
index c23c43555..313a5e998 100644
--- a/src/Common/src/TypeSystem/Interop/IL/NativeStructType.cs
+++ b/src/Common/src/TypeSystem/Interop/IL/NativeStructType.cs
@@ -127,7 +127,23 @@ namespace Internal.TypeSystem.Interop
private NativeStructField[] _fields;
private InteropStateManager _interopStateManager;
+ private bool _hasInvalidLayout;
+ public bool HasInvalidLayout
+ {
+ get
+ {
+ return _hasInvalidLayout;
+ }
+ }
+
+ public FieldDesc[] Fields
+ {
+ get
+ {
+ return _fields;
+ }
+ }
public NativeStructType(ModuleDesc owningModule, MetadataType managedStructType, InteropStateManager interopStateManager)
{
@@ -138,6 +154,7 @@ namespace Internal.TypeSystem.Interop
Module = owningModule;
ManagedStructType = managedStructType;
_interopStateManager = interopStateManager;
+ _hasInvalidLayout = false;
CalculateFields();
}
@@ -179,6 +196,7 @@ namespace Internal.TypeSystem.Interop
// if marshalling is not supported for this type the generated stubs will emit appropriate
// error message. We just set native type to be same as managedtype
nativeType = managedType;
+ _hasInvalidLayout = true;
}
_fields[index++] = new NativeStructField(nativeType, this, field);
diff --git a/src/ILCompiler.Compiler/src/Compiler/Compilation.cs b/src/ILCompiler.Compiler/src/Compiler/Compilation.cs
index f476ef2e5..a9770431a 100644
--- a/src/ILCompiler.Compiler/src/Compiler/Compilation.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/Compilation.cs
@@ -262,7 +262,7 @@ namespace ILCompiler
{
Debug.Assert(method.IsVirtual);
- if (!_factory.CompilationModuleGroup.ShouldProduceFullVTable(method.OwningType))
+ if (!_factory.VTable(method.OwningType).HasFixedSlots)
_graph.AddRoot(_factory.VirtualMethodUse(method), reason);
if (method.IsAbstract)
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs
index ae890f6cf..3d1378efe 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs
@@ -31,7 +31,6 @@ namespace ILCompiler.DependencyAnalysis
public override bool StaticDependenciesAreComputed => true;
public override bool IsShareable => IsTypeNodeShareable(_type);
- public override bool HasConditionalStaticDependencies => false;
protected override bool EmitVirtualSlotsAndInterfaces => true;
public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) => false;
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CodeBasedDependencyAlgorithm.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CodeBasedDependencyAlgorithm.cs
index 48fcdea9e..052e70dcb 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CodeBasedDependencyAlgorithm.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CodeBasedDependencyAlgorithm.cs
@@ -102,48 +102,7 @@ namespace ILCompiler.DependencyAnalysis
// On Project N, the compiler doesn't generate the interop code on the fly
if (method.Context.Target.Abi != TargetAbi.ProjectN)
{
- if (method.IsPInvoke)
- {
- if (dependencies == null)
- dependencies = new DependencyList();
-
- MethodSignature methodSig = method.Signature;
- AddPInvokeParameterDependencies(ref dependencies, factory, methodSig.ReturnType);
-
- for (int i = 0; i < methodSig.Length; i++)
- {
- AddPInvokeParameterDependencies(ref dependencies, factory, methodSig[i]);
- }
- }
- }
- }
-
- private static void AddPInvokeParameterDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc parameter)
- {
- if (parameter.IsDelegate)
- {
- dependencies.Add(factory.NecessaryTypeSymbol(parameter), "Delegate Marshalling Stub");
-
- dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetOpenStaticDelegateMarshallingStub(parameter)), "Delegate Marshalling Stub");
- dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetClosedDelegateMarshallingStub(parameter)), "Delegate Marshalling Stub");
- dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetForwardDelegateCreationStub(parameter)), "Delegate Marshalling Stub");
- }
- else if (Internal.TypeSystem.Interop.MarshalHelpers.IsStructMarshallingRequired(parameter))
- {
- var stub = (Internal.IL.Stubs.StructMarshallingThunk)factory.InteropStubManager.GetStructMarshallingManagedToNativeStub(parameter);
- dependencies.Add(factory.ConstructedTypeSymbol(factory.InteropStubManager.GetStructMarshallingType(parameter)), "Struct Marshalling Type");
- dependencies.Add(factory.MethodEntrypoint(stub), "Struct Marshalling stub");
- dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetStructMarshallingNativeToManagedStub(parameter)), "Struct Marshalling stub");
- dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetStructMarshallingCleanupStub(parameter)), "Struct Marshalling stub");
-
- foreach (var inlineArrayCandidate in stub.GetInlineArrayCandidates())
- {
- dependencies.Add(factory.ConstructedTypeSymbol(factory.InteropStubManager.GetInlineArrayType(inlineArrayCandidate)), "Struct Marshalling Type");
- foreach (var method in inlineArrayCandidate.ElementType.GetMethods())
- {
- dependencies.Add(factory.MethodEntrypoint(method), "inline array marshalling stub");
- }
- }
+ factory.InteropStubManager.AddDependeciesDueToPInvoke(ref dependencies, factory, method);
}
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs
index c308ff526..e7889f2aa 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs
@@ -2,12 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
using System.Collections.Generic;
using System.Diagnostics;
using Internal.Runtime;
-using Internal.Text;
using Internal.TypeSystem;
using Internal.IL;
@@ -53,79 +51,6 @@ namespace ILCompiler.DependencyAnalysis
dependencyList.Add(factory.InterfaceDispatchMap(_type), "Interface dispatch map");
}
- if (_type.RuntimeInterfaces.Length > 0 && !factory.CompilationModuleGroup.ShouldProduceFullVTable(_type))
- {
- foreach (var implementedInterface in _type.RuntimeInterfaces)
- {
- // If the type implements ICastable, the methods are implicitly necessary
- if (implementedInterface == factory.ICastableInterface)
- {
- MethodDesc isInstDecl = implementedInterface.GetKnownMethod("IsInstanceOfInterface", null);
- MethodDesc getImplTypeDecl = implementedInterface.GetKnownMethod("GetImplType", null);
-
- MethodDesc isInstMethodImpl = _type.ResolveInterfaceMethodTarget(isInstDecl);
- MethodDesc getImplTypeMethodImpl = _type.ResolveInterfaceMethodTarget(getImplTypeDecl);
-
- if (isInstMethodImpl != null)
- dependencyList.Add(factory.VirtualMethodUse(isInstMethodImpl), "ICastable IsInst");
- if (getImplTypeMethodImpl != null)
- dependencyList.Add(factory.VirtualMethodUse(getImplTypeMethodImpl), "ICastable GetImplType");
- }
-
- // If any of the implemented interfaces have variance, calls against compatible interface methods
- // could result in interface methods of this type being used (e.g. IEnumberable<object>.GetEnumerator()
- // can dispatch to an implementation of IEnumerable<string>.GetEnumerator()).
- // For now, we will not try to optimize this and we will pretend all interface methods are necessary.
- bool allInterfaceMethodsAreImplicitlyUsed = false;
- if (implementedInterface.HasVariance)
- {
- TypeDesc interfaceDefinition = implementedInterface.GetTypeDefinition();
- for (int i = 0; i < interfaceDefinition.Instantiation.Length; i++)
- {
- if (((GenericParameterDesc)interfaceDefinition.Instantiation[i]).Variance != 0 &&
- !implementedInterface.Instantiation[i].IsValueType)
- {
- allInterfaceMethodsAreImplicitlyUsed = true;
- break;
- }
- }
- }
- if (!allInterfaceMethodsAreImplicitlyUsed &&
- (_type.IsArray || _type.GetTypeDefinition() == factory.ArrayOfTEnumeratorType) &&
- implementedInterface.HasInstantiation)
- {
- // NOTE: we need to also do this for generic interfaces on arrays because they have a weird casting rule
- // that doesn't require the implemented interface to be variant to consider it castable.
- // For value types, we only need this when the array is castable by size (int[] and ICollection<uint>),
- // or it's a reference type (Derived[] and ICollection<Base>).
- TypeDesc elementType = _type.IsArray ? ((ArrayType)_type).ElementType : _type.Instantiation[0];
- allInterfaceMethodsAreImplicitlyUsed =
- CastingHelper.IsArrayElementTypeCastableBySize(elementType) ||
- (elementType.IsDefType && !elementType.IsValueType);
- }
-
- if (allInterfaceMethodsAreImplicitlyUsed)
- {
- foreach (var interfaceMethod in implementedInterface.GetAllMethods())
- {
- if (interfaceMethod.Signature.IsStatic)
- continue;
-
- // Generic virtual methods are tracked by an orthogonal mechanism.
- if (interfaceMethod.HasInstantiation)
- continue;
-
- MethodDesc implMethod = closestDefType.ResolveInterfaceMethodToVirtualMethodOnType(interfaceMethod);
- if (implMethod != null)
- {
- dependencyList.Add(factory.VirtualMethodUse(interfaceMethod), "Variant interface method");
- dependencyList.Add(factory.VirtualMethodUse(implMethod), "Variant interface method");
- }
- }
- }
- }
- }
-
if (_type.IsArray)
{
// Array EEType depends on System.Array's virtuals. Array EETypes don't point to
@@ -168,80 +93,9 @@ namespace ILCompiler.DependencyAnalysis
// Ask the metadata manager if we have any dependencies due to reflectability.
factory.MetadataManager.GetDependenciesDueToReflectability(ref dependencyList, factory, _type);
- return dependencyList;
- }
-
- public override bool HasConditionalStaticDependencies
- {
- get
- {
- // Since the vtable is dependency driven, generate conditional static dependencies for
- // all possible vtable entries
- foreach (var method in _type.GetClosestDefType().GetAllMethods())
- {
- if (method.IsVirtual)
- return true;
- }
-
- // If the type implements at least one interface, calls against that interface could result in this type's
- // implementation being used.
- if (_type.RuntimeInterfaces.Length > 0)
- return true;
+ factory.InteropStubManager.AddInterestingInteropConstructedTypeDependencies(ref dependencyList, factory, _type);
- return false;
- }
- }
-
- public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory)
- {
- DefType defType = _type.GetClosestDefType();
-
- // If we're producing a full vtable, none of the dependencies are conditional.
- if (!factory.CompilationModuleGroup.ShouldProduceFullVTable(defType))
- {
- foreach (MethodDesc decl in defType.EnumAllVirtualSlots())
- {
- // Generic virtual methods are tracked by an orthogonal mechanism.
- if (decl.HasInstantiation)
- continue;
-
- MethodDesc impl = defType.FindVirtualFunctionTargetMethodOnObjectType(decl);
- if (impl.OwningType == defType && !impl.IsAbstract)
- {
- MethodDesc canonImpl = impl.GetCanonMethodTarget(CanonicalFormKind.Specific);
- yield return new CombinedDependencyListEntry(factory.MethodEntrypoint(canonImpl, _type.IsValueType), factory.VirtualMethodUse(decl), "Virtual method");
- }
- }
-
- Debug.Assert(
- _type == defType ||
- ((System.Collections.IStructuralEquatable)defType.RuntimeInterfaces).Equals(_type.RuntimeInterfaces,
- EqualityComparer<DefType>.Default));
-
- // Add conditional dependencies for interface methods the type implements. For example, if the type T implements
- // interface IFoo which has a method M1, add a dependency on T.M1 dependent on IFoo.M1 being called, since it's
- // possible for any IFoo object to actually be an instance of T.
- foreach (DefType interfaceType in defType.RuntimeInterfaces)
- {
- Debug.Assert(interfaceType.IsInterface);
-
- foreach (MethodDesc interfaceMethod in interfaceType.GetAllMethods())
- {
- if (interfaceMethod.Signature.IsStatic)
- continue;
-
- // Generic virtual methods are tracked by an orthogonal mechanism.
- if (interfaceMethod.HasInstantiation)
- continue;
-
- MethodDesc implMethod = defType.ResolveInterfaceMethodToVirtualMethodOnType(interfaceMethod);
- if (implMethod != null)
- {
- yield return new CombinedDependencyListEntry(factory.VirtualMethodUse(implMethod), factory.VirtualMethodUse(interfaceMethod), "Interface method");
- }
- }
- }
- }
+ return dependencyList;
}
protected override ISymbolNode GetBaseTypeNode(NodeFactory factory)
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs
index bab3051cb..979868dd2 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs
@@ -146,11 +146,167 @@ namespace ILCompiler.DependencyAnalysis
public override bool IsShareable => IsTypeNodeShareable(_type);
+ public sealed override bool HasConditionalStaticDependencies
+ {
+ get
+ {
+ if (!EmitVirtualSlotsAndInterfaces)
+ return false;
+
+ // Since the vtable is dependency driven, generate conditional static dependencies for
+ // all possible vtable entries
+ foreach (var method in _type.GetClosestDefType().GetAllMethods())
+ {
+ if (method.IsVirtual)
+ return true;
+ }
+
+ // If the type implements at least one interface, calls against that interface could result in this type's
+ // implementation being used.
+ if (_type.RuntimeInterfaces.Length > 0)
+ return true;
+
+ return false;
+ }
+ }
+
+ public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory)
+ {
+ Debug.Assert(EmitVirtualSlotsAndInterfaces);
+
+ DefType defType = _type.GetClosestDefType();
+
+ // If we're producing a full vtable, none of the dependencies are conditional.
+ if (!factory.VTable(defType).HasFixedSlots)
+ {
+ foreach (MethodDesc decl in defType.EnumAllVirtualSlots())
+ {
+ // Generic virtual methods are tracked by an orthogonal mechanism.
+ if (decl.HasInstantiation)
+ continue;
+
+ MethodDesc impl = defType.FindVirtualFunctionTargetMethodOnObjectType(decl);
+ if (impl.OwningType == defType && !impl.IsAbstract)
+ {
+ MethodDesc canonImpl = impl.GetCanonMethodTarget(CanonicalFormKind.Specific);
+ yield return new CombinedDependencyListEntry(factory.MethodEntrypoint(canonImpl, _type.IsValueType), factory.VirtualMethodUse(decl), "Virtual method");
+ }
+ }
+
+ Debug.Assert(
+ _type == defType ||
+ ((System.Collections.IStructuralEquatable)defType.RuntimeInterfaces).Equals(_type.RuntimeInterfaces,
+ EqualityComparer<DefType>.Default));
+
+ // Add conditional dependencies for interface methods the type implements. For example, if the type T implements
+ // interface IFoo which has a method M1, add a dependency on T.M1 dependent on IFoo.M1 being called, since it's
+ // possible for any IFoo object to actually be an instance of T.
+ foreach (DefType interfaceType in defType.RuntimeInterfaces)
+ {
+ Debug.Assert(interfaceType.IsInterface);
+
+ foreach (MethodDesc interfaceMethod in interfaceType.GetAllMethods())
+ {
+ if (interfaceMethod.Signature.IsStatic)
+ continue;
+
+ // Generic virtual methods are tracked by an orthogonal mechanism.
+ if (interfaceMethod.HasInstantiation)
+ continue;
+
+ MethodDesc implMethod = defType.ResolveInterfaceMethodToVirtualMethodOnType(interfaceMethod);
+ if (implMethod != null)
+ {
+ yield return new CombinedDependencyListEntry(factory.VirtualMethodUse(implMethod), factory.VirtualMethodUse(interfaceMethod), "Interface method");
+ }
+ }
+ }
+ }
+ }
+
public static bool IsTypeNodeShareable(TypeDesc type)
{
return type.IsParameterizedType || type.IsFunctionPointer || type is InstantiatedType;
}
+ private void AddVirtualMethodUseDependencies(DependencyList dependencyList, NodeFactory factory)
+ {
+ if (_type.RuntimeInterfaces.Length > 0 && !factory.VTable(_type).HasFixedSlots)
+ {
+ DefType closestDefType = _type.GetClosestDefType();
+
+ foreach (var implementedInterface in _type.RuntimeInterfaces)
+ {
+ // If the type implements ICastable, the methods are implicitly necessary
+ if (implementedInterface == factory.ICastableInterface)
+ {
+ MethodDesc isInstDecl = implementedInterface.GetKnownMethod("IsInstanceOfInterface", null);
+ MethodDesc getImplTypeDecl = implementedInterface.GetKnownMethod("GetImplType", null);
+
+ MethodDesc isInstMethodImpl = _type.ResolveInterfaceMethodTarget(isInstDecl);
+ MethodDesc getImplTypeMethodImpl = _type.ResolveInterfaceMethodTarget(getImplTypeDecl);
+
+ if (isInstMethodImpl != null)
+ dependencyList.Add(factory.VirtualMethodUse(isInstMethodImpl), "ICastable IsInst");
+ if (getImplTypeMethodImpl != null)
+ dependencyList.Add(factory.VirtualMethodUse(getImplTypeMethodImpl), "ICastable GetImplType");
+ }
+
+ // If any of the implemented interfaces have variance, calls against compatible interface methods
+ // could result in interface methods of this type being used (e.g. IEnumberable<object>.GetEnumerator()
+ // can dispatch to an implementation of IEnumerable<string>.GetEnumerator()).
+ // For now, we will not try to optimize this and we will pretend all interface methods are necessary.
+ bool allInterfaceMethodsAreImplicitlyUsed = false;
+ if (implementedInterface.HasVariance)
+ {
+ TypeDesc interfaceDefinition = implementedInterface.GetTypeDefinition();
+ for (int i = 0; i < interfaceDefinition.Instantiation.Length; i++)
+ {
+ if (((GenericParameterDesc)interfaceDefinition.Instantiation[i]).Variance != 0 &&
+ !implementedInterface.Instantiation[i].IsValueType)
+ {
+ allInterfaceMethodsAreImplicitlyUsed = true;
+ break;
+ }
+ }
+ }
+ if (!allInterfaceMethodsAreImplicitlyUsed &&
+ (_type.IsArray || _type.GetTypeDefinition() == factory.ArrayOfTEnumeratorType) &&
+ implementedInterface.HasInstantiation)
+ {
+ // NOTE: we need to also do this for generic interfaces on arrays because they have a weird casting rule
+ // that doesn't require the implemented interface to be variant to consider it castable.
+ // For value types, we only need this when the array is castable by size (int[] and ICollection<uint>),
+ // or it's a reference type (Derived[] and ICollection<Base>).
+ TypeDesc elementType = _type.IsArray ? ((ArrayType)_type).ElementType : _type.Instantiation[0];
+ allInterfaceMethodsAreImplicitlyUsed =
+ CastingHelper.IsArrayElementTypeCastableBySize(elementType) ||
+ (elementType.IsDefType && !elementType.IsValueType);
+ }
+
+ if (allInterfaceMethodsAreImplicitlyUsed)
+ {
+ foreach (var interfaceMethod in implementedInterface.GetAllMethods())
+ {
+ if (interfaceMethod.Signature.IsStatic)
+ continue;
+
+ // Generic virtual methods are tracked by an orthogonal mechanism.
+ if (interfaceMethod.HasInstantiation)
+ continue;
+
+ MethodDesc implMethod = closestDefType.ResolveInterfaceMethodToVirtualMethodOnType(interfaceMethod);
+ if (implMethod != null)
+ {
+ dependencyList.Add(factory.VirtualMethodUse(interfaceMethod), "Variant interface method");
+ dependencyList.Add(factory.VirtualMethodUse(implMethod), "Variant interface method");
+ }
+ }
+ }
+ }
+ }
+ }
+
protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
{
DependencyList dependencies = new DependencyList();
@@ -164,6 +320,11 @@ namespace ILCompiler.DependencyAnalysis
StaticsInfoHashtableNode.AddStaticsInfoDependencies(ref dependencies, factory, _type);
ReflectionFieldMapNode.AddReflectionFieldMapEntryDependencies(ref dependencies, factory, _type);
+ if (EmitVirtualSlotsAndInterfaces)
+ {
+ AddVirtualMethodUseDependencies(dependencies, factory);
+ }
+
return dependencies;
}
@@ -450,7 +611,7 @@ namespace ILCompiler.DependencyAnalysis
// It's only okay to touch the actual list of slots if we're in the final emission phase
// or the vtable is not built lazily.
- if (relocsOnly && !factory.CompilationModuleGroup.ShouldProduceFullVTable(declType))
+ if (relocsOnly && !factory.VTable(declType).HasFixedSlots)
return;
// Actual vtable slots follow
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDictionaryNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDictionaryNode.cs
index c54b870e7..70d6147c5 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDictionaryNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDictionaryNode.cs
@@ -203,6 +203,9 @@ namespace ILCompiler.DependencyAnalysis
{
DependencyList dependencies = new DependencyList();
GenericMethodsHashtableNode.GetGenericMethodsHashtableDependenciesForMethod(ref dependencies, factory, _owningMethod);
+
+ factory.InteropStubManager.AddMarshalAPIsGenericDependencies(ref dependencies, factory, _owningMethod);
+
return dependencies;
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericLookupResult.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericLookupResult.cs
index fc63d1a43..05d2bb9e7 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericLookupResult.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericLookupResult.cs
@@ -362,7 +362,7 @@ namespace ILCompiler.DependencyAnalysis
MethodDesc canonMethod = _method.GetCanonMethodTarget(CanonicalFormKind.Universal);
// If we're producing a full vtable for the type, we don't need to report virtual method use.
- if (factory.CompilationModuleGroup.ShouldProduceFullVTable(canonMethod.OwningType))
+ if (factory.VTable(canonMethod.OwningType).HasFixedSlots)
return Array.Empty<DependencyNodeCore<NodeFactory>>();
return new DependencyNodeCore<NodeFactory>[] {
@@ -1203,8 +1203,7 @@ namespace ILCompiler.DependencyAnalysis
{
// If there isn't a default constructor, use the fallback one.
MetadataType missingCtorType = factory.TypeSystemContext.SystemModule.GetKnownType("System", "Activator");
- missingCtorType = missingCtorType.GetNestedType("ClassWithMissingConstructor");
- Debug.Assert(missingCtorType != null);
+ missingCtorType = missingCtorType.GetKnownNestedType("ClassWithMissingConstructor");
defaultCtor = missingCtorType.GetParameterlessConstructor();
}
else
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs
index a4425efee..3ec7d5fd2 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs
@@ -1331,7 +1331,7 @@ namespace ILCompiler.DependencyAnalysis
break;
case VTableEntriesToProcess.AllOnTypesThatShouldProduceFullVTables:
- if (factory.CompilationModuleGroup.ShouldProduceFullVTable(declType))
+ if (factory.VTable(declType).HasFixedSlots)
{
vtableEntriesToProcess = factory.VTable(declType).Slots;
}
@@ -1342,7 +1342,7 @@ namespace ILCompiler.DependencyAnalysis
break;
case VTableEntriesToProcess.AllOnTypesThatProducePartialVTables:
- if (factory.CompilationModuleGroup.ShouldProduceFullVTable(declType))
+ if (factory.VTable(declType).HasFixedSlots)
{
vtableEntriesToProcess = Array.Empty<MethodDesc>();
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs
index 37bea13c0..1f1b76c3c 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs
@@ -327,9 +327,9 @@ namespace ILCompiler.DependencyAnalysis
_virtMethods = new NodeCache<MethodDesc, VirtualMethodUseNode>((MethodDesc method) =>
{
- // We don't need to track virtual method uses for types that are producing full vtables.
+ // We don't need to track virtual method uses for types that have a vtable with a known layout.
// It's a waste of CPU time and memory.
- Debug.Assert(!CompilationModuleGroup.ShouldProduceFullVTable(method.OwningType));
+ Debug.Assert(!VTable(method.OwningType).HasFixedSlots);
return new VirtualMethodUseNode(method);
});
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectWriter.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectWriter.cs
index afeb432e2..0c2a49ead 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectWriter.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectWriter.cs
@@ -921,7 +921,8 @@ namespace ILCompiler.DependencyAnalysis
// Build symbol definition map.
objectWriter.BuildSymbolDefinitionMap(node, nodeContents.DefinedSymbols);
- if (!factory.Target.IsWindows)
+ // The DWARF CFI unwind is implemented for AMD64 only.
+ if (!factory.Target.IsWindows && (factory.Target.Architecture == TargetArchitecture.X64))
objectWriter.BuildCFIMap(factory, node);
// Build debug location map
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs
index a3a3fb44d..f5f788ee1 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs
@@ -55,6 +55,8 @@ namespace ILCompiler.DependencyAnalysis
return factory.GenericLookup.MethodEntry((MethodDesc)target);
case ReadyToRunHelperId.DelegateCtor:
return ((DelegateCreationInfo)target).GetLookupKind(factory);
+ case ReadyToRunHelperId.DefaultConstructor:
+ return factory.GenericLookup.DefaultCtorLookupResult((TypeDesc)target);
default:
throw new NotImplementedException();
}
@@ -111,7 +113,7 @@ namespace ILCompiler.DependencyAnalysis
if (createInfo.NeedsVirtualMethodUseTracking)
{
MethodDesc instantiatedTargetMethod = createInfo.TargetMethod.GetNonRuntimeDeterminedMethodFromRuntimeDeterminedMethodViaSubstitution(typeInstantiation, methodInstantiation);
- if (!factory.CompilationModuleGroup.ShouldProduceFullVTable(instantiatedTargetMethod.OwningType))
+ if (!factory.VTable(instantiatedTargetMethod.OwningType).HasFixedSlots)
{
result.Add(
new DependencyListEntry(
@@ -131,7 +133,7 @@ namespace ILCompiler.DependencyAnalysis
case ReadyToRunHelperId.ResolveVirtualFunction:
{
MethodDesc instantiatedTarget = ((MethodDesc)_target).GetNonRuntimeDeterminedMethodFromRuntimeDeterminedMethodViaSubstitution(typeInstantiation, methodInstantiation);
- if (!factory.CompilationModuleGroup.ShouldProduceFullVTable(instantiatedTarget.OwningType))
+ if (!factory.VTable(instantiatedTarget.OwningType).HasFixedSlots)
{
result.Add(
new DependencyListEntry(
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs
index c4dc1fac9..1ab4a73f4 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs
@@ -30,7 +30,8 @@ namespace ILCompiler.DependencyAnalysis
MethodHandle,
FieldHandle,
MethodDictionary,
- MethodEntry
+ MethodEntry,
+ DefaultConstructor,
}
public partial class ReadyToRunHelperNode : AssemblyStubNode
@@ -149,7 +150,7 @@ namespace ILCompiler.DependencyAnalysis
dependencyList.Add(factory.ReflectableMethod(targetMethod), "Abstract reflectable method");
}
- if (!factory.CompilationModuleGroup.ShouldProduceFullVTable(targetMethod.OwningType))
+ if (!factory.VTable(targetMethod.OwningType).HasFixedSlots)
{
dependencyList.Add(factory.VirtualMethodUse((MethodDesc)_target), "ReadyToRun Virtual Method Call");
@@ -173,7 +174,7 @@ namespace ILCompiler.DependencyAnalysis
dependencyList.Add(factory.ReflectableMethod(targetMethod), "Abstract reflectable method");
}
- if (!factory.CompilationModuleGroup.ShouldProduceFullVTable(info.TargetMethod.OwningType))
+ if (!factory.VTable(info.TargetMethod.OwningType).HasFixedSlots)
{
dependencyList.Add(factory.VirtualMethodUse(info.TargetMethod), "ReadyToRun Delegate to virtual method");
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs
index 3eae212d7..c55e4018e 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs
@@ -112,7 +112,7 @@ namespace ILCompiler.DependencyAnalysis
if (!method.HasInstantiation)
{
MethodDesc slotDefiningMethod = MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(method);
- if (!factory.CompilationModuleGroup.ShouldProduceFullVTable(slotDefiningMethod.OwningType))
+ if (!factory.VTable(slotDefiningMethod.OwningType).HasFixedSlots)
{
dependencies.Add(factory.VirtualMethodUse(slotDefiningMethod), "Reflection virtual invoke method");
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StructMarshallingStubMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StructMarshallingStubMapNode.cs
new file mode 100644
index 000000000..5f49f9a1d
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StructMarshallingStubMapNode.cs
@@ -0,0 +1,107 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+using Internal.NativeFormat;
+using Internal.Text;
+
+namespace ILCompiler.DependencyAnalysis
+{
+ /// <summary>
+ /// Represents a hash table of struct marshalling stub types generated into the image.
+ /// </summary>
+ internal sealed class StructMarshallingStubMapNode : ObjectNode, ISymbolDefinitionNode
+ {
+ private ObjectAndOffsetSymbolNode _endSymbol;
+ private ExternalReferencesTableNode _externalReferences;
+
+ public StructMarshallingStubMapNode(ExternalReferencesTableNode externalReferences)
+ {
+ _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__struct_marshalling_stub_map_End", true);
+ _externalReferences = externalReferences;
+ }
+
+ public ISymbolDefinitionNode EndSymbol => _endSymbol;
+
+ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
+ {
+ sb.Append(nameMangler.CompilationUnitPrefix).Append("__struct_marshalling_stub_map");
+ }
+ public int Offset => 0;
+ public override bool IsShareable => false;
+
+ public override ObjectNodeSection Section => _externalReferences.Section;
+
+ public override bool StaticDependenciesAreComputed => true;
+
+ protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
+
+ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
+ {
+ // This node does not trigger generation of other nodes.
+ if (relocsOnly)
+ return new ObjectData(Array.Empty<byte>(), Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this });
+
+ var writer = new NativeWriter();
+ var typeMapHashTable = new VertexHashtable();
+
+ Section hashTableSection = writer.NewSection();
+ hashTableSection.Place(typeMapHashTable);
+
+ foreach (var structEntry in factory.InteropStubManager.GetStructMarshallingTypes())
+ {
+ // the order of data written is as follows:
+ // 0. managed struct type
+ // 1. struct marshalling thunk
+ // 2. struct unmarshalling thunk
+ // 3. struct cleanup thunk
+ // 4. size
+ // 5. NumFields<< 1 | HasInvalidLayout
+ // 6 for each field
+ // a. name
+ // b. offset
+
+ var structType = structEntry.StructType;
+ var nativeType = structEntry.NativeStructType;
+ Vertex thunks= writer.GetTuple(
+ writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(structEntry.MarshallingThunk))),
+ writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(structEntry.UnmarshallingThunk))),
+ writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(structEntry.CleanupThunk))));
+
+ uint size = (uint)nativeType.InstanceByteCount.AsInt;
+ uint mask = (uint)(nativeType.Fields.Length << 1) | (uint)(nativeType.HasInvalidLayout ? 1 : 0);
+
+ Vertex data = writer.GetTuple(
+ thunks,
+ writer.GetUnsignedConstant(size),
+ writer.GetUnsignedConstant(mask)
+ );
+
+ for (int i = 0; i < nativeType.Fields.Length; i++)
+ {
+ data = writer.GetTuple(
+ data,
+ writer.GetStringConstant(nativeType.Fields[i].Name),
+ writer.GetUnsignedConstant((uint)nativeType.Fields[i].Offset.AsInt)
+ );
+ }
+
+ Vertex vertex = writer.GetTuple(
+ writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.NecessaryTypeSymbol(structType))),
+ data
+ );
+
+ int hashCode = structType.GetHashCode();
+ typeMapHashTable.Append((uint)hashCode, hashTableSection.Place(vertex));
+ }
+
+ byte[] hashTableBytes = writer.Save();
+
+ _endSymbol.SetSymbolOffset(hashTableBytes.Length);
+
+ return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol });
+ }
+ }
+}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunGenericHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunGenericHelperNode.cs
index 93241ff8d..c49d5eb8f 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunGenericHelperNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunGenericHelperNode.cs
@@ -210,6 +210,7 @@ namespace ILCompiler.DependencyAnalysis
case ReadyToRunHelperId.VirtualCall:
case ReadyToRunHelperId.ResolveVirtualFunction:
case ReadyToRunHelperId.MethodEntry:
+ case ReadyToRunHelperId.DefaultConstructor:
{
EmitDictionaryLookup(factory, ref encoder, contextRegister, encoder.TargetRegister.Result, _lookupSignature, relocsOnly);
encoder.EmitRET();
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/VTableSliceNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/VTableSliceNode.cs
index bdb4d5cfd..f01fbf406 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/VTableSliceNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/VTableSliceNode.cs
@@ -29,6 +29,14 @@ namespace ILCompiler.DependencyAnalysis
get;
}
+ /// <summary>
+ /// Gets a value indicating whether the slots are assigned at the beginning of the compilation.
+ /// </summary>
+ public abstract bool HasFixedSlots
+ {
+ get;
+ }
+
protected override string GetName(NodeFactory factory) => $"__vtable_{factory.NameMangler.GetMangledTypeName(_type).ToString()}";
public override bool StaticDependenciesAreComputed => true;
@@ -97,6 +105,14 @@ namespace ILCompiler.DependencyAnalysis
}
}
+ public override bool HasFixedSlots
+ {
+ get
+ {
+ return true;
+ }
+ }
+
public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
{
if (_type.HasBaseType)
@@ -153,6 +169,14 @@ namespace ILCompiler.DependencyAnalysis
}
}
+ public override bool HasFixedSlots
+ {
+ get
+ {
+ return false;
+ }
+ }
+
public void AddEntry(NodeFactory factory, MethodDesc virtualMethod)
{
// GVMs are not emitted in the type's vtable.
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/VirtualMethodUseNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/VirtualMethodUseNode.cs
index 66075291e..dfd0b0e86 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/VirtualMethodUseNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/VirtualMethodUseNode.cs
@@ -79,7 +79,7 @@ namespace ILCompiler.DependencyAnalysis
DefType universalCanonicalOwningType = (DefType)_decl.OwningType.ConvertToCanonForm(CanonicalFormKind.Universal);
Debug.Assert(universalCanonicalOwningType.IsCanonicalSubtype(CanonicalFormKind.Universal));
- if (!factory.CompilationModuleGroup.ShouldProduceFullVTable(universalCanonicalOwningType))
+ if (!factory.VTable(universalCanonicalOwningType).HasFixedSlots)
{
// This code ensures that in cases where we don't structurally force all universal canonical instantiations
// to have full vtables, that we ensure that all vtables are equivalently shaped between universal and non-universal types
diff --git a/src/ILCompiler.Compiler/src/Compiler/InteropStubManager.cs b/src/ILCompiler.Compiler/src/Compiler/InteropStubManager.cs
index 0c5850b1c..411adea69 100644
--- a/src/ILCompiler.Compiler/src/Compiler/InteropStubManager.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/InteropStubManager.cs
@@ -8,9 +8,10 @@ using System.Collections.Generic;
using Internal.IL.Stubs;
using Internal.TypeSystem;
using Internal.TypeSystem.Interop;
-
+using ILCompiler.DependencyAnalysis;
using Debug = System.Diagnostics.Debug;
+using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore<ILCompiler.DependencyAnalysis.NodeFactory>.DependencyList;
namespace ILCompiler
{
@@ -22,7 +23,9 @@ namespace ILCompiler
private readonly CompilationModuleGroup _compilationModuleGroup;
private readonly CompilerTypeSystemContext _typeSystemContext;
internal HashSet<TypeDesc> _delegateMarshalingTypes = new HashSet<TypeDesc>();
- private HashSet<NativeStructType> _structMarshallingTypes = new HashSet<NativeStructType>();
+ private HashSet<TypeDesc> _structMarshallingTypes = new HashSet<TypeDesc>();
+ private ModuleDesc _interopModule;
+ private const string _interopModuleName = "System.Private.Interop";
public InteropStateManager InteropStateManager
{
@@ -34,6 +37,9 @@ namespace ILCompiler
_compilationModuleGroup = compilationModuleGroup;
_typeSystemContext = typeSystemContext;
InteropStateManager = interopStateManager;
+
+ // Note: interopModule might be null if we're building with a class library that doesn't support rich interop
+ _interopModule = typeSystemContext.GetModuleForSimpleName(_interopModuleName, false);
}
internal MethodDesc GetOpenStaticDelegateMarshallingStub(TypeDesc delegateType)
@@ -62,18 +68,12 @@ namespace ILCompiler
return stub;
}
- internal TypeDesc GetStructMarshallingType(TypeDesc structType)
- {
- NativeStructType nativeType = InteropStateManager.GetStructMarshallingNativeType(structType);
- Debug.Assert(nativeType != null);
- _structMarshallingTypes.Add(nativeType);
- return nativeType;
- }
-
internal MethodDesc GetStructMarshallingManagedToNativeStub(TypeDesc structType)
{
MethodDesc stub = InteropStateManager.GetStructMarshallingManagedToNativeThunk(structType);
Debug.Assert(stub != null);
+
+ _structMarshallingTypes.Add(structType);
return stub;
}
@@ -81,6 +81,8 @@ namespace ILCompiler
{
MethodDesc stub = InteropStateManager.GetStructMarshallingNativeToManagedThunk(structType);
Debug.Assert(stub != null);
+
+ _structMarshallingTypes.Add(structType);
return stub;
}
@@ -88,6 +90,8 @@ namespace ILCompiler
{
MethodDesc stub = InteropStateManager.GetStructMarshallingCleanupThunk(structType);
Debug.Assert(stub != null);
+
+ _structMarshallingTypes.Add(structType);
return stub;
}
@@ -101,32 +105,148 @@ namespace ILCompiler
internal struct DelegateMarshallingThunks
{
public TypeDesc DelegateType;
- public DelegateMarshallingMethodThunk OpenStaticDelegateMarshallingThunk;
- public DelegateMarshallingMethodThunk ClosedDelegateMarshallingThunk;
- public ForwardDelegateCreationThunk DelegateCreationThunk;
+ public MethodDesc OpenStaticDelegateMarshallingThunk;
+ public MethodDesc ClosedDelegateMarshallingThunk;
+ public MethodDesc DelegateCreationThunk;
}
internal IEnumerable<DelegateMarshallingThunks> GetDelegateMarshallingThunks()
{
foreach (var delegateType in _delegateMarshalingTypes)
{
- var openStub = InteropStateManager.GetOpenStaticDelegateMarshallingThunk(delegateType);
- var closedStub = InteropStateManager.GetClosedDelegateMarshallingThunk(delegateType);
- var delegateCreationStub = InteropStateManager.GetForwardDelegateCreationThunk(delegateType);
yield return
new DelegateMarshallingThunks()
{
DelegateType = delegateType,
- OpenStaticDelegateMarshallingThunk = openStub,
- ClosedDelegateMarshallingThunk = closedStub,
- DelegateCreationThunk = delegateCreationStub
+ OpenStaticDelegateMarshallingThunk = InteropStateManager.GetOpenStaticDelegateMarshallingThunk(delegateType),
+ ClosedDelegateMarshallingThunk = InteropStateManager.GetClosedDelegateMarshallingThunk(delegateType),
+ DelegateCreationThunk = InteropStateManager.GetForwardDelegateCreationThunk(delegateType)
+ };
+ }
+ }
+
+ internal struct StructMarshallingThunks
+ {
+ public TypeDesc StructType;
+ public NativeStructType NativeStructType;
+ public MethodDesc MarshallingThunk;
+ public MethodDesc UnmarshallingThunk;
+ public MethodDesc CleanupThunk;
+ }
+
+ internal IEnumerable<StructMarshallingThunks> GetStructMarshallingTypes()
+ {
+ foreach (var structType in _structMarshallingTypes)
+ {
+ yield return
+ new StructMarshallingThunks()
+ {
+ StructType = structType,
+ NativeStructType = InteropStateManager.GetStructMarshallingNativeType(structType),
+ MarshallingThunk = InteropStateManager.GetStructMarshallingManagedToNativeThunk(structType),
+ UnmarshallingThunk = InteropStateManager.GetStructMarshallingNativeToManagedThunk(structType),
+ CleanupThunk = InteropStateManager.GetStructMarshallingCleanupThunk(structType)
};
}
}
- internal HashSet<NativeStructType> GetStructMarshallingTypes()
+ public void AddDependeciesDueToPInvoke(ref DependencyList dependencies, NodeFactory factory, MethodDesc method)
{
- return _structMarshallingTypes;
+ if (method.IsPInvoke)
+ {
+ dependencies = dependencies ?? new DependencyList();
+
+ MethodSignature methodSig = method.Signature;
+ AddDependenciesDueToPInvokeDelegate(ref dependencies, factory, methodSig.ReturnType);
+
+ for (int i = 0; i < methodSig.Length; i++)
+ {
+ AddDependenciesDueToPInvokeDelegate(ref dependencies, factory, methodSig[i]);
+ }
+ }
+
+ if (method.HasInstantiation)
+ {
+ dependencies = dependencies ?? new DependencyList();
+ AddMarshalAPIsGenericDependencies(ref dependencies, factory, method);
+ }
+ }
+
+ public void AddInterestingInteropConstructedTypeDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
+ {
+ if (type.IsDelegate)
+ {
+ var delegateType = (MetadataType)type;
+ if (delegateType.HasCustomAttribute("System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute"))
+ {
+ AddDependenciesDueToPInvokeDelegate(ref dependencies, factory, delegateType);
+ }
+ }
+ }
+
+ /// <summary>
+ /// For Marshal generic APIs(eg. Marshal.StructureToPtr<T>, GetFunctionPointerForDelegate) we add
+ /// the generic parameter as dependencies so that we can generate runtime data for them
+ /// </summary>
+ public void AddMarshalAPIsGenericDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method)
+ {
+ Debug.Assert(method.HasInstantiation);
+
+ TypeDesc owningType = method.OwningType;
+ MetadataType metadataType = owningType as MetadataType;
+ if (metadataType != null && metadataType.Module == _interopModule)
+ {
+ if (metadataType.Name == "Marshal" && metadataType.Namespace == "System.Runtime.InteropServices")
+ {
+ string methodName = method.Name;
+ if (methodName == "GetFunctionPointerForDelegate" ||
+ methodName == "GetDelegateForFunctionPointer" ||
+ methodName == "PtrToStructure" ||
+ methodName == "StructureToPtr" ||
+ methodName == "SizeOf" ||
+ methodName == "OffsetOf")
+ {
+ foreach (TypeDesc type in method.Instantiation)
+ {
+ AddDependenciesDueToPInvokeDelegate(ref dependencies, factory, type);
+ AddDependenciesDueToPInvokeStruct(ref dependencies, factory, type);
+ }
+ }
+ }
+ }
+ }
+
+ public void AddDependenciesDueToPInvokeDelegate(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
+ {
+ if (type.IsDelegate)
+ {
+ dependencies.Add(factory.NecessaryTypeSymbol(type), "Delegate Marshalling Stub");
+
+ dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetOpenStaticDelegateMarshallingStub(type)), "Delegate Marshalling Stub");
+ dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetClosedDelegateMarshallingStub(type)), "Delegate Marshalling Stub");
+ dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetForwardDelegateCreationStub(type)), "Delegate Marshalling Stub");
+ }
+ }
+
+ public void AddDependenciesDueToPInvokeStruct(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
+ {
+ if (MarshalHelpers.IsStructMarshallingRequired(type))
+ {
+ dependencies.Add(factory.NecessaryTypeSymbol(type), "Struct Marshalling Stub");
+
+ var stub = (Internal.IL.Stubs.StructMarshallingThunk)factory.InteropStubManager.GetStructMarshallingManagedToNativeStub(type);
+ dependencies.Add(factory.MethodEntrypoint(stub), "Struct Marshalling stub");
+ dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetStructMarshallingNativeToManagedStub(type)), "Struct Marshalling stub");
+ dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetStructMarshallingCleanupStub(type)), "Struct Marshalling stub");
+
+ foreach (var inlineArrayCandidate in stub.GetInlineArrayCandidates())
+ {
+ foreach (var method in inlineArrayCandidate.ElementType.GetMethods())
+ {
+ dependencies.Add(factory.MethodEntrypoint(method), "inline array marshalling stub");
+ }
+ }
+ }
}
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/JitHelper.cs b/src/ILCompiler.Compiler/src/Compiler/JitHelper.cs
index 59b675487..6f73bea93 100644
--- a/src/ILCompiler.Compiler/src/Compiler/JitHelper.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/JitHelper.cs
@@ -45,6 +45,12 @@ namespace ILCompiler
case ReadyToRunHelper.ThrowDivZero:
methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowDivideByZeroException");
break;
+ case ReadyToRunHelper.ThrowArgumentOutOfRange:
+ methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowArgumentOutOfRangeException");
+ break;
+ case ReadyToRunHelper.ThrowArgument:
+ methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowArgumentException");
+ break;
case ReadyToRunHelper.DebugBreak:
mangledName = "RhDebugBreak";
diff --git a/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs
index 23bce180d..725352626 100644
--- a/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs
@@ -100,6 +100,9 @@ namespace ILCompiler
var delegateMapNode = new DelegateMarshallingStubMapNode(commonFixupsTableNode);
header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.DelegateMarshallingStubMap), delegateMapNode, delegateMapNode, delegateMapNode.EndSymbol);
+ var structMapNode = new StructMarshallingStubMapNode(commonFixupsTableNode);
+ header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.StructMarshallingStubMap), structMapNode, structMapNode, structMapNode.EndSymbol);
+
var arrayMapNode = new ArrayMapNode(commonFixupsTableNode);
header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.ArrayMap), arrayMapNode, arrayMapNode, arrayMapNode.EndSymbol);
diff --git a/src/ILCompiler.Compiler/src/Compiler/ReadyToRun.cs b/src/ILCompiler.Compiler/src/Compiler/ReadyToRun.cs
index 462255ace..98314078d 100644
--- a/src/ILCompiler.Compiler/src/Compiler/ReadyToRun.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/ReadyToRun.cs
@@ -22,6 +22,8 @@ namespace ILCompiler
FailFast = 0x24,
ThrowNullRef = 0x25,
ThrowDivZero = 0x26,
+ ThrowArgumentOutOfRange = 0x27,
+ ThrowArgument = 0x28,
DebugBreak = 0x2F,
diff --git a/src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs b/src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs
index 4011819b1..eeaebf363 100644
--- a/src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs
+++ b/src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs
@@ -102,6 +102,27 @@ namespace Internal.IL
public DependencyList Import()
{
+ if (_canonMethod.Signature.IsStatic)
+ {
+ TypeDesc owningType = _canonMethod.OwningType;
+ if (!_isFallbackBodyCompilation && _factory.TypeSystemContext.HasLazyStaticConstructor(owningType))
+ {
+ // For beforefieldinit, we can wait for field access.
+ if (!((MetadataType)owningType).IsBeforeFieldInit)
+ {
+ MethodDesc method = _methodIL.OwningMethod;
+ if (method.OwningType.IsRuntimeDeterminedSubtype)
+ {
+ _dependencies.Add(GetGenericLookupHelper(ReadyToRunHelperId.GetNonGCStaticBase, method.OwningType), "Owning type cctor");
+ }
+ else
+ {
+ _dependencies.Add(_factory.ReadyToRunHelper(ReadyToRunHelperId.GetNonGCStaticBase, method.OwningType), "Owning type cctor");
+ }
+ }
+ }
+ }
+
FindBasicBlocks();
ImportBasicBlocks();
@@ -261,12 +282,8 @@ namespace Internal.IL
{
// String .ctor handled specially below
}
- else
+ else if (owningType.IsGCPointer)
{
- // Nullable needs to be unwrapped.
- if (owningType.IsNullable)
- owningType = owningType.Instantiation[0];
-
if (owningType.IsRuntimeDeterminedSubtype)
{
_dependencies.Add(GetGenericLookupHelper(ReadyToRunHelperId.TypeHandle, owningType), reason);
@@ -337,6 +354,27 @@ namespace Internal.IL
if (_previousInstructionOffset >= 0 && _ilBytes[_previousInstructionOffset] == (byte)ILOpcode.ldtoken)
return;
}
+
+ if (IsActivatorDefaultConstructorOf(method))
+ {
+ if (runtimeDeterminedMethod.IsRuntimeDeterminedExactMethod)
+ {
+ _dependencies.Add(GetGenericLookupHelper(ReadyToRunHelperId.DefaultConstructor, runtimeDeterminedMethod.Instantiation[0]), reason);
+ }
+ else
+ {
+ MethodDesc ctor = method.Instantiation[0].GetDefaultConstructor();
+ if (ctor == null)
+ {
+ MetadataType activatorType = _compilation.TypeSystemContext.SystemModule.GetKnownType("System", "Activator");
+ MetadataType classWithMissingCtor = activatorType.GetKnownNestedType("ClassWithMissingConstructor");
+ ctor = classWithMissingCtor.GetParameterlessConstructor();
+ }
+ _dependencies.Add(_factory.CanonicalEntrypoint(ctor), reason);
+ }
+
+ return;
+ }
}
TypeDesc exactType = method.OwningType;
@@ -466,6 +504,31 @@ namespace Internal.IL
{
if (targetMethod.IsSharedByGenericInstantiations && !resolvedConstraint && !referencingArrayAddressMethod)
{
+ ISymbolNode instParam = null;
+
+ if (targetMethod.RequiresInstMethodDescArg())
+ {
+ instParam = GetGenericLookupHelper(ReadyToRunHelperId.MethodDictionary, runtimeDeterminedMethod);
+ }
+ else if (targetMethod.RequiresInstMethodTableArg())
+ {
+ bool hasHiddenParameter = true;
+
+ if (targetMethod.IsIntrinsic)
+ {
+ if (_factory.TypeSystemContext.IsSpecialUnboxingThunkTargetMethod(targetMethod))
+ hasHiddenParameter = false;
+ }
+
+ if (hasHiddenParameter)
+ instParam = GetGenericLookupHelper(ReadyToRunHelperId.TypeHandle, runtimeDeterminedMethod.OwningType);
+ }
+
+ if (instParam != null)
+ {
+ _dependencies.Add(instParam, reason);
+ }
+
_dependencies.Add(_factory.RuntimeDeterminedMethod(runtimeDeterminedMethod), reason);
}
else
@@ -639,6 +702,23 @@ namespace Internal.IL
if (obj is TypeDesc)
{
var type = (TypeDesc)obj;
+
+ // First check if this is a ldtoken Type / GetValueInternal sequence.
+ BasicBlock nextBasicBlock = _basicBlocks[_currentOffset];
+ if (nextBasicBlock == null)
+ {
+ if ((ILOpcode)_ilBytes[_currentOffset] == ILOpcode.call)
+ {
+ int methodToken = ReadILTokenAt(_currentOffset + 1);
+ var method = (MethodDesc)_methodIL.GetObject(methodToken);
+ if (IsRuntimeTypeHandleGetValueInternal(method))
+ {
+ // Codegen expands this and doesn't do the normal ldtoken.
+ return;
+ }
+ }
+ }
+
if (type.IsRuntimeDeterminedSubtype)
{
_dependencies.Add(GetGenericLookupHelper(ReadyToRunHelperId.TypeHandle, type), "ldtoken");
@@ -769,6 +849,7 @@ namespace Internal.IL
private void ImportLoadString(int token)
{
// If we care, this can include allocating the frozen string node.
+ _dependencies.Add(_factory.SerializedStringObject(""), "ldstr");
}
private void ImportBox(int token)
@@ -841,6 +922,21 @@ namespace Internal.IL
_dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.RngChkFail), "ldelema");
}
+ private void ImportBinaryOperation(ILOpcode opcode)
+ {
+ switch (opcode)
+ {
+ case ILOpcode.add_ovf:
+ case ILOpcode.add_ovf_un:
+ case ILOpcode.mul_ovf:
+ case ILOpcode.mul_ovf_un:
+ case ILOpcode.sub_ovf:
+ case ILOpcode.sub_ovf_un:
+ _dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.Overflow), "_ovf");
+ break;
+ }
+ }
+
private void ImportFallthrough(BasicBlock next)
{
MarkBasicBlock(next);
@@ -882,6 +978,20 @@ namespace Internal.IL
return false;
}
+ private bool IsActivatorDefaultConstructorOf(MethodDesc method)
+ {
+ if (method.IsIntrinsic && method.Name == "DefaultConstructorOf" && method.Instantiation.Length == 1)
+ {
+ MetadataType owningType = method.OwningType as MetadataType;
+ if (owningType != null)
+ {
+ return owningType.Name == "Activator" && owningType.Namespace == "System";
+ }
+ }
+
+ return false;
+ }
+
private TypeDesc GetWellKnownType(WellKnownType wellKnownType)
{
return _compilation.TypeSystemContext.GetWellKnownType(wellKnownType);
@@ -903,7 +1013,6 @@ namespace Internal.IL
private void ImportLoadIndirect(TypeDesc type) { }
private void ImportStoreIndirect(int token) { }
private void ImportStoreIndirect(TypeDesc type) { }
- private void ImportBinaryOperation(ILOpcode opcode) { }
private void ImportShiftOperation(ILOpcode opcode) { }
private void ImportCompareOperation(ILOpcode opcode) { }
private void ImportConvert(WellKnownType wellKnownType, bool checkOverflow, bool unsigned) { }
diff --git a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj
index b189dd9e5..475866398 100644
--- a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj
+++ b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj
@@ -136,7 +136,6 @@
<Compile Include="Compiler\ILScanner.cs" />
<Compile Include="Compiler\ILScannerBuilder.cs" />
<Compile Include="Compiler\ILStreamReader.cs" />
- <Compile Include="Compiler\INonEmittableType.cs" />
<Compile Include="Compiler\LibraryInitializers.cs" />
<Compile Include="Compiler\ICompilationRootProvider.cs" />
<Compile Include="Compiler\Compilation.cs" />
@@ -151,6 +150,7 @@
<Compile Include="Compiler\DependencyAnalysis\CallingConventionConverterKey.cs" />
<Compile Include="Compiler\DependencyAnalysis\CodeBasedDependencyAlgorithm.cs" />
<Compile Include="Compiler\DependencyAnalysis\DelegateMarshallingStubMapNode.cs" />
+ <Compile Include="Compiler\DependencyAnalysis\StructMarshallingStubMapNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\GenericVirtualMethodTableNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\InterfaceGenericVirtualMethodTableNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\IObjectDumper.cs" />
diff --git a/src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs b/src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs
index ac3016c38..cac63cb1e 100644
--- a/src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs
+++ b/src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs
@@ -968,7 +968,7 @@ namespace Internal.IL
else
callViaSlot = true;
- if (!_nodeFactory.CompilationModuleGroup.ShouldProduceFullVTable(method.OwningType))
+ if (!_nodeFactory.VTable(method.OwningType).HasFixedSlots)
_dependencies.Add(_nodeFactory.VirtualMethodUse(method));
}
}
diff --git a/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj b/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj
index ce35bbb78..f47db6bf7 100644
--- a/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj
+++ b/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj
@@ -506,6 +506,12 @@
<Compile Include="..\..\Common\src\TypeSystem\Common\LocalVariableDefinition.cs">
<Link>TypeSystem\Common\LocalVariableDefinition.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\src\TypeSystem\CodeGen\INonEmittableType.cs">
+ <Link>TypeSystem\CodeGen\INonEmittableType.cs</Link>
+ </Compile>
+ <Compile Include="..\..\Common\src\TypeSystem\CodeGen\NativeStructType.CodeGen.cs">
+ <Link>TypeSystem\CodeGen\NativeStructType.CodeGen.cs</Link>
+ </Compile>
<Compile Include="..\..\Common\src\TypeSystem\RuntimeDetermined\ArrayType.RuntimeDetermined.cs">
<Link>TypeSystem\RuntimeDetermined\ArrayType.RuntimeDetermined.cs</Link>
</Compile>
diff --git a/src/ILVerify/src/ILImporter.StackValue.cs b/src/ILVerify/src/ILImporter.StackValue.cs
index 4c1afe5f5..d4fb4d835 100644
--- a/src/ILVerify/src/ILImporter.StackValue.cs
+++ b/src/ILVerify/src/ILImporter.StackValue.cs
@@ -39,6 +39,11 @@ namespace Internal.IL
get { return (Flags & StackValueFlags.ReadOnly) == StackValueFlags.ReadOnly; }
}
+ public bool IsNullReference
+ {
+ get { return Kind == StackValueKind.ObjRef && Type == null; }
+ }
+
public StackValue DereferenceByRef()
{
Debug.Assert(Kind == StackValueKind.ByRef && Type != null, "Cannot dereference");
diff --git a/src/ILVerify/src/ILImporter.Verify.cs b/src/ILVerify/src/ILImporter.Verify.cs
index bafd47369..806980e8f 100644
--- a/src/ILVerify/src/ILImporter.Verify.cs
+++ b/src/ILVerify/src/ILImporter.Verify.cs
@@ -123,7 +123,7 @@ namespace Internal.IL
_typeSystemContext = method.Context;
if (!_methodSignature.IsStatic)
- _thisType = method.OwningType;
+ _thisType = method.OwningType.InstantiateAsOpen();
_methodIL = methodIL;
@@ -235,6 +235,20 @@ namespace Internal.IL
AbortMethodVerification();
}
+ // Check whether the condition is true. If not, terminate the verification of current method.
+ void FatalCheck(bool cond, VerifierError error, StackValue found)
+ {
+ if (!Check(cond, error, found))
+ AbortMethodVerification();
+ }
+
+ // Check whether the condition is true. If not, terminate the verification of current method.
+ void FatalCheck(bool cond, VerifierError error, StackValue found, StackValue expected)
+ {
+ if (!Check(cond, error, found, expected))
+ AbortMethodVerification();
+ }
+
// If not, report verification error and continue verification.
void VerificationError(VerifierError error)
{
@@ -978,18 +992,19 @@ namespace Internal.IL
if (entryStack != null)
{
- // TODO: Better error messages
- if (entryStack.Length != _stackTop)
- throw new InvalidProgramException();
+ FatalCheck(entryStack.Length == _stackTop, VerifierError.PathStackDepth);
for (int i = 0; i < entryStack.Length; i++)
{
// TODO: Do we need to allow conversions?
- if (entryStack[i].Kind != _stack[i].Kind)
- throw new InvalidProgramException();
-
+ FatalCheck(entryStack[i].Kind == _stack[i].Kind, VerifierError.PathStackUnexpected, entryStack[i], _stack[i]);
+
if (entryStack[i].Type != _stack[i].Type)
- throw new InvalidProgramException();
+ {
+ // if we have two object references and one of them has a null type, then this is no error (see test Branching.NullConditional_Valid)
+ if (_stack[i].Kind == StackValueKind.ObjRef && entryStack[i].Type != null && _stack[i].Type != null)
+ FatalCheck(false, VerifierError.PathStackUnexpected, entryStack[i], _stack[i]);
+ }
}
}
else
@@ -1264,7 +1279,9 @@ namespace Internal.IL
Check(!address.IsReadOnly, VerifierError.ReadOnlyIllegalWrite);
CheckIsByRef(address);
- CheckIsAssignable(type, address.Type);
+ if (!value.IsNullReference)
+ CheckIsAssignable(type, address.Type);
+
CheckIsAssignable(value, StackValue.CreateFromType(type));
}
diff --git a/src/ILVerify/src/ILVerify.csproj b/src/ILVerify/src/ILVerify.csproj
index 3f3a92178..14624907b 100644
--- a/src/ILVerify/src/ILVerify.csproj
+++ b/src/ILVerify/src/ILVerify.csproj
@@ -13,6 +13,7 @@
<Compile Include="Program.cs" />
<Compile Include="ILImporter.Verify.cs" />
<Compile Include="ILImporter.StackValue.cs" />
+ <Compile Include="SimpleArrayOfTRuntimeInterfacesAlgorithm.cs" />
<Compile Include="SimpleTypeSystemContext.cs" />
<Compile Include="VerifierError.cs" />
</ItemGroup>
diff --git a/src/ILVerify/src/Resources/Strings.resx b/src/ILVerify/src/Resources/Strings.resx
index c40c9df99..c14d1a18f 100644
--- a/src/ILVerify/src/Resources/Strings.resx
+++ b/src/ILVerify/src/Resources/Strings.resx
@@ -174,6 +174,12 @@
<data name="InitLocals" xml:space="preserve">
<value>initlocals must be set for verifiable methods with one or more local variables.</value>
</data>
+ <data name="PathStackDepth" xml:space="preserve">
+ <value>Stack depth differs depending on path.</value>
+ </data>
+ <data name="PathStackUnexpected" xml:space="preserve">
+ <value>Non-compatible types on stack depending on path.</value>
+ </data>
<data name="ReadOnly" xml:space="preserve">
<value>Missing ldelema or call following readonly prefix.</value>
</data>
diff --git a/src/ILVerify/src/SimpleArrayOfTRuntimeInterfacesAlgorithm.cs b/src/ILVerify/src/SimpleArrayOfTRuntimeInterfacesAlgorithm.cs
new file mode 100644
index 000000000..5e62168f0
--- /dev/null
+++ b/src/ILVerify/src/SimpleArrayOfTRuntimeInterfacesAlgorithm.cs
@@ -0,0 +1,64 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics;
+using Internal.IL;
+using Internal.TypeSystem;
+
+namespace ILVerify
+{
+ internal class SimpleArrayOfTRuntimeInterfacesAlgorithm : RuntimeInterfacesAlgorithm
+ {
+ private DefType[] _arrayRuntimeInterfaces;
+ private MetadataType[] _genericRuntimeInterfaces;
+ private ModuleDesc _systemModule;
+
+ private static readonly string[] s_genericRuntimeInterfacesNames =
+ {
+ "IEnumerable`1",
+ "ICollection`1",
+ "IList`1",
+ "IReadOnlyList`1",
+ "IReadOnlyCollection`1",
+ };
+
+ public SimpleArrayOfTRuntimeInterfacesAlgorithm(ModuleDesc systemModule)
+ {
+ _systemModule = systemModule;
+
+ // initialize interfaces
+ _arrayRuntimeInterfaces = _systemModule.GetType("System", "Array")?.RuntimeInterfaces
+ ?? Array.Empty<DefType>();
+
+ _genericRuntimeInterfaces = new MetadataType[s_genericRuntimeInterfacesNames.Length];
+ int count = 0;
+ for (int i = 0; i < s_genericRuntimeInterfacesNames.Length; ++i)
+ {
+ MetadataType runtimeInterface =_systemModule.GetType("System.Collections.Generic", s_genericRuntimeInterfacesNames[i], false);
+ if (runtimeInterface != null)
+ _genericRuntimeInterfaces[count++] = runtimeInterface;
+ };
+ Array.Resize(ref _genericRuntimeInterfaces, count);
+ }
+
+ public override DefType[] ComputeRuntimeInterfaces(TypeDesc type)
+ {
+ ArrayType arrayType = (ArrayType)type;
+ TypeDesc elementType = arrayType.ElementType;
+ Debug.Assert(arrayType.IsSzArray);
+
+ // first copy runtime interfaces from System.Array
+ var result = new DefType[_arrayRuntimeInterfaces.Length + _genericRuntimeInterfaces.Length];
+ Array.Copy(_arrayRuntimeInterfaces, result, _arrayRuntimeInterfaces.Length);
+
+ // then copy instantiated generic interfaces
+ int offset = _arrayRuntimeInterfaces.Length;
+ for (int i = 0; i < _genericRuntimeInterfaces.Length; ++i)
+ result[i + offset] = _genericRuntimeInterfaces[i].MakeInstantiatedType(elementType);
+
+ return result;
+ }
+ }
+}
diff --git a/src/ILVerify/src/SimpleTypeSystemContext.cs b/src/ILVerify/src/SimpleTypeSystemContext.cs
index 791530220..123e2e0d2 100644
--- a/src/ILVerify/src/SimpleTypeSystemContext.cs
+++ b/src/ILVerify/src/SimpleTypeSystemContext.cs
@@ -4,7 +4,6 @@
using System;
using System.IO;
-using System.Diagnostics;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Metadata;
@@ -20,6 +19,9 @@ namespace ILVerify
{
class SimpleTypeSystemContext : MetadataTypeSystemContext
{
+ private RuntimeInterfacesAlgorithm _arrayOfTRuntimeInterfacesAlgorithm;
+ private MetadataRuntimeInterfacesAlgorithm _metadataRuntimeInterfacesAlgorithm = new MetadataRuntimeInterfacesAlgorithm();
+
Dictionary<string, EcmaModule> _modules = new Dictionary<string, EcmaModule>(StringComparer.OrdinalIgnoreCase);
class ModuleData
@@ -114,5 +116,19 @@ namespace ILVerify
{
return _moduleData[module].Path;
}
+
+ protected override RuntimeInterfacesAlgorithm GetRuntimeInterfacesAlgorithmForNonPointerArrayType(ArrayType type)
+ {
+ if (_arrayOfTRuntimeInterfacesAlgorithm == null)
+ {
+ _arrayOfTRuntimeInterfacesAlgorithm = new SimpleArrayOfTRuntimeInterfacesAlgorithm(SystemModule);
+ }
+ return _arrayOfTRuntimeInterfacesAlgorithm;
+ }
+
+ protected override RuntimeInterfacesAlgorithm GetRuntimeInterfacesAlgorithmForDefType(DefType type)
+ {
+ return _metadataRuntimeInterfacesAlgorithm;
+ }
}
}
diff --git a/src/ILVerify/src/VerifierError.cs b/src/ILVerify/src/VerifierError.cs
index 7f276889e..014448588 100644
--- a/src/ILVerify/src/VerifierError.cs
+++ b/src/ILVerify/src/VerifierError.cs
@@ -76,8 +76,8 @@ namespace ILVerify
//E_BAD_JMP_TARGET "jmp / exception into the middle of an instruction."
//E_PATH_LOC "Non-compatible types depending on path."
//E_PATH_THIS "Init state for this differs depending on path."
- //E_PATH_STACK "Non-compatible types on stack depending on path."
- //E_PATH_STACK_DEPTH "Stack depth differs depending on path."
+ PathStackUnexpected, //"Non-compatible types on stack depending on path."
+ PathStackDepth, //"Stack depth differs depending on path."
//E_THIS "Instance variable (this) missing."
//E_THIS_UNINIT_EXCEP "Uninitialized this on entering a try block."
//E_THIS_UNINIT_STORE "Store into this when it is uninitialized."
diff --git a/src/ILVerify/tests/ILTests/BranchingTests.il b/src/ILVerify/tests/ILTests/BranchingTests.il
new file mode 100644
index 000000000..57554cafe
--- /dev/null
+++ b/src/ILVerify/tests/ILTests/BranchingTests.il
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly Branching
+{
+}
+
+.class public auto ansi beforefieldinit BranchingTestsType
+ extends [System.Runtime]System.Object
+{
+ .method static public hidebysig void Branching.NullConditional_Valid() cil managed
+ {
+ //object o = null;
+ //Type t = o != null ? o.GetType() : null;
+ //Type.GetTypeCode(t);
+
+ .maxstack 1
+ .locals init (
+ [0] object o
+ )
+
+ IL_0000: ldnull
+ IL_0001: stloc.0
+ IL_0002: ldloc.0
+ IL_0003: brtrue.s IL_0008
+
+ IL_0005: ldnull
+ IL_0006: br.s IL_000E
+
+ IL_0008: ldloc.0
+ IL_0009: callvirt instance class [System.Runtime]System.Type [System.Runtime]System.Object::GetType()
+
+ IL_000E: call valuetype [System.Runtime]System.TypeCode [System.Runtime]System.Type::GetTypeCode(class [System.Runtime]System.Type)
+ IL_0013: pop
+ IL_0014: ret
+ }
+
+ .method static public hidebysig void Branching.NullConditional_Invalid_StackUnexpected.PathStackUnexpected() cil managed
+ {
+ //object o = null;
+ //Type t = o != null ? o.GetType() : o;
+ //Type.GetTypeCode(t);
+
+ .maxstack 1
+ .locals init (
+ [0] object o
+ )
+
+ IL_0000: ldnull
+ IL_0001: stloc.0
+ IL_0002: ldloc.0
+ IL_0003: brtrue.s IL_0008
+
+ IL_0005: ldloc.0
+ IL_0006: br.s IL_000E
+
+ IL_0008: ldloc.0
+ IL_0009: callvirt instance class [System.Runtime]System.Type [System.Runtime]System.Object::GetType()
+
+ IL_000E: call valuetype [System.Runtime]System.TypeCode [System.Runtime]System.Type::GetTypeCode(class [System.Runtime]System.Type)
+ IL_0013: pop
+ IL_0014: ret
+ }
+}
diff --git a/src/ILVerify/tests/ILTests/CastingTests.il b/src/ILVerify/tests/ILTests/CastingTests.il
new file mode 100644
index 000000000..b5b9c0a6d
--- /dev/null
+++ b/src/ILVerify/tests/ILTests/CastingTests.il
@@ -0,0 +1,211 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly Casting
+{
+}
+
+// Provides tests for casting arrays
+.class public auto ansi beforefieldinit ArrayCastingTestsType
+ extends [System.Runtime]System.Object
+{
+ // Array<T> tests
+ .method static public hidebysig void Casting.ArrayOfTToEnumerableOfT_Valid(int32[] test) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Collections.Generic.IEnumerable`1<int32> V_0
+ )
+ ldarg.0
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Casting.ArrayOfTToEnumerable_Valid(int32[] test) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Collections.IEnumerable V_0
+ )
+ ldarg.0
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Casting.ArrayOfTToICollectionOfT_Valid(int32[] test) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Collections.Generic.ICollection`1<int32> V_0
+ )
+ ldarg.0
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Casting.ArrayOfTToICollection_Valid(int32[] test) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Collections.ICollection V_0
+ )
+ ldarg.0
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Casting.ArrayOfTToIListOfT_Valid(int32[] test) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Collections.Generic.IList`1<int32> V_0
+ )
+ ldarg.0
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Casting.ArrayOfTToIList_Valid(int32[] test) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Collections.IList V_0
+ )
+ ldarg.0
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Casting.ArrayOfTToIReadOnlyCollectionOfT_Valid(int32[] test) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Collections.Generic.IReadOnlyCollection`1<int32> V_0
+ )
+ ldarg.0
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Casting.ArrayOfTToIReadOnlyListOfT_Valid(int32[] test) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Collections.Generic.IReadOnlyList`1<int32> V_0
+ )
+ ldarg.0
+ stloc.0
+ ret
+ }
+
+ .method static public hidebysig void Casting.ArrayOfTToArray_Valid(int32[] test) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Array V_0
+ )
+ ldarg.0
+ stloc.0
+ ret
+ }
+}
+
+.class public sequential ansi beforefieldinit GenericOtherFieldsType`1<T>
+ extends [System.Runtime]System.ValueType
+{
+ .field public !T GenericField;
+ .field int32 IntField;
+}
+
+// Provides casting logic tests for stfld, ldfld, call, callvirt
+.class public auto ansi beforefieldinit GenericCastingTestsType`1<T>
+ extends [System.Runtime]System.Object
+{
+ .field private int32 ThisIntField
+ .method public hidebysig instance void Casting.StorePlainFieldInThisGenericType_Valid(int32 v) cil managed
+ {
+ ldarg.0
+ ldarg.1
+ stfld int32 class GenericCastingTestsType`1<!T>::ThisIntField
+ ret
+ }
+
+ .method public hidebysig instance void Casting.StorePlainFieldInOtherGenericType_Valid(int32 v) cil managed
+ {
+ .locals init (
+ class GenericOtherFieldsType`1<!T> V_0
+ )
+
+ ldloc.0
+ ldarg.1
+ stfld !0 class GenericOtherFieldsType`1<!T>::IntField
+ ret
+ }
+
+ .field private !T ThisGenericField
+ .method public hidebysig instance void Casting.StoreGenericFieldInThisGenericType_Valid(!T v) cil managed
+ {
+ ldarg.0
+ ldarg.1
+ stfld !0 class GenericCastingTestsType`1<!T>::ThisGenericField
+ ret
+ }
+
+ .method public hidebysig instance void Casting.StoreGenericFieldInOtherGenericType_Valid(!T v) cil managed
+ {
+ .locals init (
+ class GenericOtherFieldsType`1<!T> V_0
+ )
+ ldloc.0
+ ldarg.1
+ stfld !0 class GenericOtherFieldsType`1<!T>::GenericField
+ ret
+ }
+
+ .method public hidebysig instance void Casting.CallPlainFunctionFromThisGenericType_Valid(int32 v) cil managed
+ {
+ ldarg.0
+ ldarg.1
+ callvirt instance void class GenericCastingTestsType`1<!T>::Casting.StorePlainFieldInThisGenericType_Valid(int32)
+ ret
+ }
+
+ .method public hidebysig instance void Casting.CallGenericFunctionFromThisGenericType_Valid(!T v) cil managed
+ {
+ ldarg.0
+ ldarg.1
+ callvirt instance void class GenericCastingTestsType`1<!T>::Casting.CallGenericFunctionFromOtherGenericType_Valid(!0)
+ ret
+ }
+
+ .method public hidebysig instance void Casting.CallGenericFunctionFromOtherGenericType_Valid(!T v) cil managed
+ {
+ .locals init (
+ class [System.Runtime]System.Func`1<!T> V_0
+ )
+
+ ldarg.0
+ ldloc.0
+ callvirt instance !0 class [System.Runtime]System.Func`1<!T>::Invoke()
+ ret
+ }
+
+ .method public hidebysig instance void Casting.AssignThisToSameTypeWithOtherGenericArgs_Invalid_StackUnexpected() cil managed
+ {
+ .locals init (
+ class GenericCastingTestsType`1<int32> V_0
+ )
+
+ ldarg.0
+ stloc.0
+ ret
+ }
+
+ .method public hidebysig static void Casting.AssignToSameTypeWithOtherGenericArgs_Invalid_StackUnexpected() cil managed
+ {
+ .locals init (
+ class GenericCastingTestsType`1<int32> V_0,
+ class GenericCastingTestsType`1<string> V_1
+ )
+
+ ldloc.0
+ stloc.1
+ ret
+ }
+}
diff --git a/src/ILVerify/tests/ILTests/LoadStoreIndirectTest.il b/src/ILVerify/tests/ILTests/LoadStoreIndirectTest.il
index 4a9da1ad8..7450a3499 100644
--- a/src/ILVerify/tests/ILTests/LoadStoreIndirectTest.il
+++ b/src/ILVerify/tests/ILTests/LoadStoreIndirectTest.il
@@ -71,6 +71,17 @@
ret
}
+ .method static public hidebysig void StoreIndirect.AssignNullToRefString_Valid(string&) cil managed
+ {
+ // ref string x;
+ // x = null;
+
+ ldarg.0
+ ldnull
+ stind.ref
+ ret
+ }
+
.method static public hidebysig void StoreObject.ValidTypeToken_Valid() cil managed
{
.locals init (object V_0)
diff --git a/src/JitInterface/src/CorInfoBase.cs b/src/JitInterface/src/CorInfoBase.cs
index 4ad9e7938..5e356a488 100644
--- a/src/JitInterface/src/CorInfoBase.cs
+++ b/src/JitInterface/src/CorInfoBase.cs
@@ -38,6 +38,8 @@ namespace Internal.JitInterface
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
delegate CORINFO_METHOD_STRUCT_* __resolveVirtualMethod(IntPtr _this, IntPtr* ppException, CORINFO_METHOD_STRUCT_* virtualMethod, CORINFO_CLASS_STRUCT_* implementingClass, CORINFO_CONTEXT_STRUCT* ownerType);
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
+ delegate void __expandRawHandleIntrinsic(IntPtr _this, IntPtr* ppException, ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref CORINFO_GENERICHANDLE_RESULT pResult);
+ [UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
delegate CorInfoIntrinsics __getIntrinsicID(IntPtr _this, IntPtr* ppException, CORINFO_METHOD_STRUCT_* method, [MarshalAs(UnmanagedType.U1)] ref bool pMustExpand);
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.I1)]delegate bool __isInSIMDModule(IntPtr _this, IntPtr* ppException, CORINFO_CLASS_STRUCT_* classHnd);
@@ -50,8 +52,6 @@ namespace Internal.JitInterface
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.Bool)]delegate bool __isCompatibleDelegate(IntPtr _this, IntPtr* ppException, CORINFO_CLASS_STRUCT_* objCls, CORINFO_CLASS_STRUCT_* methodParentCls, CORINFO_METHOD_STRUCT_* method, CORINFO_CLASS_STRUCT_* delegateCls, [MarshalAs(UnmanagedType.Bool)] ref bool pfIsOpenDelegate);
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
- [return: MarshalAs(UnmanagedType.Bool)]delegate bool __isDelegateCreationAllowed(IntPtr _this, IntPtr* ppException, CORINFO_CLASS_STRUCT_* delegateHnd, CORINFO_METHOD_STRUCT_* calleeHnd);
- [UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
delegate CorInfoInstantiationVerification __isInstantiationOfVerifiedGeneric(IntPtr _this, IntPtr* ppException, CORINFO_METHOD_STRUCT_* method);
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
delegate void __initConstraintsForVerification(IntPtr _this, IntPtr* ppException, CORINFO_METHOD_STRUCT_* method, [MarshalAs(UnmanagedType.Bool)] ref bool pfHasCircularClassConstraints, [MarshalAs(UnmanagedType.Bool)] ref bool pfHasCircularMethodConstraint);
@@ -238,8 +238,6 @@ namespace Internal.JitInterface
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
delegate int* __getAddrOfCaptureThreadGlobal(IntPtr _this, IntPtr* ppException, ref void* ppIndirection);
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
- delegate void* __getAddrModuleDomainID(IntPtr _this, IntPtr* ppException, CORINFO_MODULE_STRUCT_* module);
- [UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
delegate void* __getHelperFtn(IntPtr _this, IntPtr* ppException, CorInfoHelpFunc ftnNum, ref void* ppIndirection);
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
delegate void __getFunctionEntryPoint(IntPtr _this, IntPtr* ppException, CORINFO_METHOD_STRUCT_* ftn, ref CORINFO_CONST_LOOKUP pResult, CORINFO_ACCESS_FLAGS accessFlags);
@@ -520,6 +518,19 @@ namespace Internal.JitInterface
}
}
+ static void _expandRawHandleIntrinsic(IntPtr thisHandle, IntPtr* ppException, ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref CORINFO_GENERICHANDLE_RESULT pResult)
+ {
+ var _this = GetThis(thisHandle);
+ try
+ {
+ _this.expandRawHandleIntrinsic(ref pResolvedToken, ref pResult);
+ }
+ catch (Exception ex)
+ {
+ *ppException = _this.AllocException(ex);
+ }
+ }
+
static CorInfoIntrinsics _getIntrinsicID(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* method, [MarshalAs(UnmanagedType.U1)] ref bool pMustExpand)
{
var _this = GetThis(thisHandle);
@@ -604,20 +615,6 @@ namespace Internal.JitInterface
}
}
- [return: MarshalAs(UnmanagedType.Bool)]static bool _isDelegateCreationAllowed(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* delegateHnd, CORINFO_METHOD_STRUCT_* calleeHnd)
- {
- var _this = GetThis(thisHandle);
- try
- {
- return _this.isDelegateCreationAllowed(delegateHnd, calleeHnd);
- }
- catch (Exception ex)
- {
- *ppException = _this.AllocException(ex);
- return default(bool);
- }
- }
-
static CorInfoInstantiationVerification _isInstantiationOfVerifiedGeneric(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* method)
{
var _this = GetThis(thisHandle);
@@ -1900,20 +1897,6 @@ namespace Internal.JitInterface
}
}
- static void* _getAddrModuleDomainID(IntPtr thisHandle, IntPtr* ppException, CORINFO_MODULE_STRUCT_* module)
- {
- var _this = GetThis(thisHandle);
- try
- {
- return _this.getAddrModuleDomainID(module);
- }
- catch (Exception ex)
- {
- *ppException = _this.AllocException(ex);
- return default(void*);
- }
- }
-
static void* _getHelperFtn(IntPtr thisHandle, IntPtr* ppException, CorInfoHelpFunc ftnNum, ref void* ppIndirection)
{
var _this = GetThis(thisHandle);
@@ -2626,8 +2609,8 @@ namespace Internal.JitInterface
static IntPtr GetUnmanagedCallbacks(out Object keepAlive)
{
- IntPtr * callbacks = (IntPtr *)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 166);
- Object[] delegates = new Object[166];
+ IntPtr * callbacks = (IntPtr *)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 165);
+ Object[] delegates = new Object[165];
var d0 = new __getMethodAttribs(_getMethodAttribs);
callbacks[0] = Marshal.GetFunctionPointerForDelegate(d0);
@@ -2668,25 +2651,25 @@ namespace Internal.JitInterface
var d12 = new __resolveVirtualMethod(_resolveVirtualMethod);
callbacks[12] = Marshal.GetFunctionPointerForDelegate(d12);
delegates[12] = d12;
- var d13 = new __getIntrinsicID(_getIntrinsicID);
+ var d13 = new __expandRawHandleIntrinsic(_expandRawHandleIntrinsic);
callbacks[13] = Marshal.GetFunctionPointerForDelegate(d13);
delegates[13] = d13;
- var d14 = new __isInSIMDModule(_isInSIMDModule);
+ var d14 = new __getIntrinsicID(_getIntrinsicID);
callbacks[14] = Marshal.GetFunctionPointerForDelegate(d14);
delegates[14] = d14;
- var d15 = new __getUnmanagedCallConv(_getUnmanagedCallConv);
+ var d15 = new __isInSIMDModule(_isInSIMDModule);
callbacks[15] = Marshal.GetFunctionPointerForDelegate(d15);
delegates[15] = d15;
- var d16 = new __pInvokeMarshalingRequired(_pInvokeMarshalingRequired);
+ var d16 = new __getUnmanagedCallConv(_getUnmanagedCallConv);
callbacks[16] = Marshal.GetFunctionPointerForDelegate(d16);
delegates[16] = d16;
- var d17 = new __satisfiesMethodConstraints(_satisfiesMethodConstraints);
+ var d17 = new __pInvokeMarshalingRequired(_pInvokeMarshalingRequired);
callbacks[17] = Marshal.GetFunctionPointerForDelegate(d17);
delegates[17] = d17;
- var d18 = new __isCompatibleDelegate(_isCompatibleDelegate);
+ var d18 = new __satisfiesMethodConstraints(_satisfiesMethodConstraints);
callbacks[18] = Marshal.GetFunctionPointerForDelegate(d18);
delegates[18] = d18;
- var d19 = new __isDelegateCreationAllowed(_isDelegateCreationAllowed);
+ var d19 = new __isCompatibleDelegate(_isCompatibleDelegate);
callbacks[19] = Marshal.GetFunctionPointerForDelegate(d19);
delegates[19] = d19;
var d20 = new __isInstantiationOfVerifiedGeneric(_isInstantiationOfVerifiedGeneric);
@@ -2968,165 +2951,162 @@ namespace Internal.JitInterface
var d112 = new __getAddrOfCaptureThreadGlobal(_getAddrOfCaptureThreadGlobal);
callbacks[112] = Marshal.GetFunctionPointerForDelegate(d112);
delegates[112] = d112;
- var d113 = new __getAddrModuleDomainID(_getAddrModuleDomainID);
+ var d113 = new __getHelperFtn(_getHelperFtn);
callbacks[113] = Marshal.GetFunctionPointerForDelegate(d113);
delegates[113] = d113;
- var d114 = new __getHelperFtn(_getHelperFtn);
+ var d114 = new __getFunctionEntryPoint(_getFunctionEntryPoint);
callbacks[114] = Marshal.GetFunctionPointerForDelegate(d114);
delegates[114] = d114;
- var d115 = new __getFunctionEntryPoint(_getFunctionEntryPoint);
+ var d115 = new __getFunctionFixedEntryPoint(_getFunctionFixedEntryPoint);
callbacks[115] = Marshal.GetFunctionPointerForDelegate(d115);
delegates[115] = d115;
- var d116 = new __getFunctionFixedEntryPoint(_getFunctionFixedEntryPoint);
+ var d116 = new __getMethodSync(_getMethodSync);
callbacks[116] = Marshal.GetFunctionPointerForDelegate(d116);
delegates[116] = d116;
- var d117 = new __getMethodSync(_getMethodSync);
+ var d117 = new __getLazyStringLiteralHelper(_getLazyStringLiteralHelper);
callbacks[117] = Marshal.GetFunctionPointerForDelegate(d117);
delegates[117] = d117;
- var d118 = new __getLazyStringLiteralHelper(_getLazyStringLiteralHelper);
+ var d118 = new __embedModuleHandle(_embedModuleHandle);
callbacks[118] = Marshal.GetFunctionPointerForDelegate(d118);
delegates[118] = d118;
- var d119 = new __embedModuleHandle(_embedModuleHandle);
+ var d119 = new __embedClassHandle(_embedClassHandle);
callbacks[119] = Marshal.GetFunctionPointerForDelegate(d119);
delegates[119] = d119;
- var d120 = new __embedClassHandle(_embedClassHandle);
+ var d120 = new __embedMethodHandle(_embedMethodHandle);
callbacks[120] = Marshal.GetFunctionPointerForDelegate(d120);
delegates[120] = d120;
- var d121 = new __embedMethodHandle(_embedMethodHandle);
+ var d121 = new __embedFieldHandle(_embedFieldHandle);
callbacks[121] = Marshal.GetFunctionPointerForDelegate(d121);
delegates[121] = d121;
- var d122 = new __embedFieldHandle(_embedFieldHandle);
+ var d122 = new __embedGenericHandle(_embedGenericHandle);
callbacks[122] = Marshal.GetFunctionPointerForDelegate(d122);
delegates[122] = d122;
- var d123 = new __embedGenericHandle(_embedGenericHandle);
+ var d123 = new __getLocationOfThisType(_getLocationOfThisType);
callbacks[123] = Marshal.GetFunctionPointerForDelegate(d123);
delegates[123] = d123;
- var d124 = new __getLocationOfThisType(_getLocationOfThisType);
+ var d124 = new __getPInvokeUnmanagedTarget(_getPInvokeUnmanagedTarget);
callbacks[124] = Marshal.GetFunctionPointerForDelegate(d124);
delegates[124] = d124;
- var d125 = new __getPInvokeUnmanagedTarget(_getPInvokeUnmanagedTarget);
+ var d125 = new __getAddressOfPInvokeFixup(_getAddressOfPInvokeFixup);
callbacks[125] = Marshal.GetFunctionPointerForDelegate(d125);
delegates[125] = d125;
- var d126 = new __getAddressOfPInvokeFixup(_getAddressOfPInvokeFixup);
+ var d126 = new __getAddressOfPInvokeTarget(_getAddressOfPInvokeTarget);
callbacks[126] = Marshal.GetFunctionPointerForDelegate(d126);
delegates[126] = d126;
- var d127 = new __getAddressOfPInvokeTarget(_getAddressOfPInvokeTarget);
+ var d127 = new __GetCookieForPInvokeCalliSig(_GetCookieForPInvokeCalliSig);
callbacks[127] = Marshal.GetFunctionPointerForDelegate(d127);
delegates[127] = d127;
- var d128 = new __GetCookieForPInvokeCalliSig(_GetCookieForPInvokeCalliSig);
+ var d128 = new __canGetCookieForPInvokeCalliSig(_canGetCookieForPInvokeCalliSig);
callbacks[128] = Marshal.GetFunctionPointerForDelegate(d128);
delegates[128] = d128;
- var d129 = new __canGetCookieForPInvokeCalliSig(_canGetCookieForPInvokeCalliSig);
+ var d129 = new __getJustMyCodeHandle(_getJustMyCodeHandle);
callbacks[129] = Marshal.GetFunctionPointerForDelegate(d129);
delegates[129] = d129;
- var d130 = new __getJustMyCodeHandle(_getJustMyCodeHandle);
+ var d130 = new __GetProfilingHandle(_GetProfilingHandle);
callbacks[130] = Marshal.GetFunctionPointerForDelegate(d130);
delegates[130] = d130;
- var d131 = new __GetProfilingHandle(_GetProfilingHandle);
+ var d131 = new __getCallInfo(_getCallInfo);
callbacks[131] = Marshal.GetFunctionPointerForDelegate(d131);
delegates[131] = d131;
- var d132 = new __getCallInfo(_getCallInfo);
+ var d132 = new __canAccessFamily(_canAccessFamily);
callbacks[132] = Marshal.GetFunctionPointerForDelegate(d132);
delegates[132] = d132;
- var d133 = new __canAccessFamily(_canAccessFamily);
+ var d133 = new __isRIDClassDomainID(_isRIDClassDomainID);
callbacks[133] = Marshal.GetFunctionPointerForDelegate(d133);
delegates[133] = d133;
- var d134 = new __isRIDClassDomainID(_isRIDClassDomainID);
+ var d134 = new __getClassDomainID(_getClassDomainID);
callbacks[134] = Marshal.GetFunctionPointerForDelegate(d134);
delegates[134] = d134;
- var d135 = new __getClassDomainID(_getClassDomainID);
+ var d135 = new __getFieldAddress(_getFieldAddress);
callbacks[135] = Marshal.GetFunctionPointerForDelegate(d135);
delegates[135] = d135;
- var d136 = new __getFieldAddress(_getFieldAddress);
+ var d136 = new __getVarArgsHandle(_getVarArgsHandle);
callbacks[136] = Marshal.GetFunctionPointerForDelegate(d136);
delegates[136] = d136;
- var d137 = new __getVarArgsHandle(_getVarArgsHandle);
+ var d137 = new __canGetVarArgsHandle(_canGetVarArgsHandle);
callbacks[137] = Marshal.GetFunctionPointerForDelegate(d137);
delegates[137] = d137;
- var d138 = new __canGetVarArgsHandle(_canGetVarArgsHandle);
+ var d138 = new __constructStringLiteral(_constructStringLiteral);
callbacks[138] = Marshal.GetFunctionPointerForDelegate(d138);
delegates[138] = d138;
- var d139 = new __constructStringLiteral(_constructStringLiteral);
+ var d139 = new __emptyStringLiteral(_emptyStringLiteral);
callbacks[139] = Marshal.GetFunctionPointerForDelegate(d139);
delegates[139] = d139;
- var d140 = new __emptyStringLiteral(_emptyStringLiteral);
+ var d140 = new __getFieldThreadLocalStoreID(_getFieldThreadLocalStoreID);
callbacks[140] = Marshal.GetFunctionPointerForDelegate(d140);
delegates[140] = d140;
- var d141 = new __getFieldThreadLocalStoreID(_getFieldThreadLocalStoreID);
+ var d141 = new __setOverride(_setOverride);
callbacks[141] = Marshal.GetFunctionPointerForDelegate(d141);
delegates[141] = d141;
- var d142 = new __setOverride(_setOverride);
+ var d142 = new __addActiveDependency(_addActiveDependency);
callbacks[142] = Marshal.GetFunctionPointerForDelegate(d142);
delegates[142] = d142;
- var d143 = new __addActiveDependency(_addActiveDependency);
+ var d143 = new __GetDelegateCtor(_GetDelegateCtor);
callbacks[143] = Marshal.GetFunctionPointerForDelegate(d143);
delegates[143] = d143;
- var d144 = new __GetDelegateCtor(_GetDelegateCtor);
+ var d144 = new __MethodCompileComplete(_MethodCompileComplete);
callbacks[144] = Marshal.GetFunctionPointerForDelegate(d144);
delegates[144] = d144;
- var d145 = new __MethodCompileComplete(_MethodCompileComplete);
+ var d145 = new __getTailCallCopyArgsThunk(_getTailCallCopyArgsThunk);
callbacks[145] = Marshal.GetFunctionPointerForDelegate(d145);
delegates[145] = d145;
- var d146 = new __getTailCallCopyArgsThunk(_getTailCallCopyArgsThunk);
+ var d146 = new __getMemoryManager(_getMemoryManager);
callbacks[146] = Marshal.GetFunctionPointerForDelegate(d146);
delegates[146] = d146;
- var d147 = new __getMemoryManager(_getMemoryManager);
+ var d147 = new __allocMem(_allocMem);
callbacks[147] = Marshal.GetFunctionPointerForDelegate(d147);
delegates[147] = d147;
- var d148 = new __allocMem(_allocMem);
+ var d148 = new __reserveUnwindInfo(_reserveUnwindInfo);
callbacks[148] = Marshal.GetFunctionPointerForDelegate(d148);
delegates[148] = d148;
- var d149 = new __reserveUnwindInfo(_reserveUnwindInfo);
+ var d149 = new __allocUnwindInfo(_allocUnwindInfo);
callbacks[149] = Marshal.GetFunctionPointerForDelegate(d149);
delegates[149] = d149;
- var d150 = new __allocUnwindInfo(_allocUnwindInfo);
+ var d150 = new __allocGCInfo(_allocGCInfo);
callbacks[150] = Marshal.GetFunctionPointerForDelegate(d150);
delegates[150] = d150;
- var d151 = new __allocGCInfo(_allocGCInfo);
+ var d151 = new __yieldExecution(_yieldExecution);
callbacks[151] = Marshal.GetFunctionPointerForDelegate(d151);
delegates[151] = d151;
- var d152 = new __yieldExecution(_yieldExecution);
+ var d152 = new __setEHcount(_setEHcount);
callbacks[152] = Marshal.GetFunctionPointerForDelegate(d152);
delegates[152] = d152;
- var d153 = new __setEHcount(_setEHcount);
+ var d153 = new __setEHinfo(_setEHinfo);
callbacks[153] = Marshal.GetFunctionPointerForDelegate(d153);
delegates[153] = d153;
- var d154 = new __setEHinfo(_setEHinfo);
+ var d154 = new __logMsg(_logMsg);
callbacks[154] = Marshal.GetFunctionPointerForDelegate(d154);
delegates[154] = d154;
- var d155 = new __logMsg(_logMsg);
+ var d155 = new __doAssert(_doAssert);
callbacks[155] = Marshal.GetFunctionPointerForDelegate(d155);
delegates[155] = d155;
- var d156 = new __doAssert(_doAssert);
+ var d156 = new __reportFatalError(_reportFatalError);
callbacks[156] = Marshal.GetFunctionPointerForDelegate(d156);
delegates[156] = d156;
- var d157 = new __reportFatalError(_reportFatalError);
+ var d157 = new __allocBBProfileBuffer(_allocBBProfileBuffer);
callbacks[157] = Marshal.GetFunctionPointerForDelegate(d157);
delegates[157] = d157;
- var d158 = new __allocBBProfileBuffer(_allocBBProfileBuffer);
+ var d158 = new __getBBProfileData(_getBBProfileData);
callbacks[158] = Marshal.GetFunctionPointerForDelegate(d158);
delegates[158] = d158;
- var d159 = new __getBBProfileData(_getBBProfileData);
+ var d159 = new __recordCallSite(_recordCallSite);
callbacks[159] = Marshal.GetFunctionPointerForDelegate(d159);
delegates[159] = d159;
- var d160 = new __recordCallSite(_recordCallSite);
+ var d160 = new __recordRelocation(_recordRelocation);
callbacks[160] = Marshal.GetFunctionPointerForDelegate(d160);
delegates[160] = d160;
- var d161 = new __recordRelocation(_recordRelocation);
+ var d161 = new __getRelocTypeHint(_getRelocTypeHint);
callbacks[161] = Marshal.GetFunctionPointerForDelegate(d161);
delegates[161] = d161;
- var d162 = new __getRelocTypeHint(_getRelocTypeHint);
+ var d162 = new __getModuleNativeEntryPointRange(_getModuleNativeEntryPointRange);
callbacks[162] = Marshal.GetFunctionPointerForDelegate(d162);
delegates[162] = d162;
- var d163 = new __getModuleNativeEntryPointRange(_getModuleNativeEntryPointRange);
+ var d163 = new __getExpectedTargetArchitecture(_getExpectedTargetArchitecture);
callbacks[163] = Marshal.GetFunctionPointerForDelegate(d163);
delegates[163] = d163;
- var d164 = new __getExpectedTargetArchitecture(_getExpectedTargetArchitecture);
+ var d164 = new __getJitFlags(_getJitFlags);
callbacks[164] = Marshal.GetFunctionPointerForDelegate(d164);
delegates[164] = d164;
- var d165 = new __getJitFlags(_getJitFlags);
- callbacks[165] = Marshal.GetFunctionPointerForDelegate(d165);
- delegates[165] = d165;
keepAlive = delegates;
return (IntPtr)callbacks;
diff --git a/src/JitInterface/src/CorInfoImpl.Intrinsics.cs b/src/JitInterface/src/CorInfoImpl.Intrinsics.cs
index 10b345d41..de56a69f3 100644
--- a/src/JitInterface/src/CorInfoImpl.Intrinsics.cs
+++ b/src/JitInterface/src/CorInfoImpl.Intrinsics.cs
@@ -124,11 +124,13 @@ namespace Internal.JitInterface
// table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_GetManagedThreadId, "get_ManagedThreadId", "System", "Thread"); // not in .NET Core
table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_ByReference_Ctor, ".ctor", "System", "ByReference`1");
table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_ByReference_Value, "get_Value", "System", "ByReference`1");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Span_GetItem, "get_Item", "System", "Span`1"); // not handled
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_ReadOnlySpan_GetItem, "get_Item", "System", "ReadOnlySpan`1"); // not handled
+ table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Span_GetItem, "get_Item", "System", "Span`1");
+ table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_ReadOnlySpan_GetItem, "get_Item", "System", "ReadOnlySpan`1");
+ table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_GetRawHandle, "EETypePtrOf", "System", "EETypePtr");
+ table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_GetRawHandle, "DefaultConstructorOf", "System", "Activator");
// If this assert fails, make sure to add the new intrinsics to the table above and update the expected count below.
- Debug.Assert((int)CorInfoIntrinsics.CORINFO_INTRINSIC_Count == 49);
+ Debug.Assert((int)CorInfoIntrinsics.CORINFO_INTRINSIC_Count == 50);
return table;
}
@@ -203,6 +205,10 @@ namespace Internal.JitInterface
pMustExpand = true;
break;
+ case CorInfoIntrinsics.CORINFO_INTRINSIC_GetRawHandle:
+ pMustExpand = method.Name == "DefaultConstructorOf";
+ break;
+
default:
break;
}
diff --git a/src/JitInterface/src/CorInfoImpl.cs b/src/JitInterface/src/CorInfoImpl.cs
index 9e4508b19..9e8c802bf 100644
--- a/src/JitInterface/src/CorInfoImpl.cs
+++ b/src/JitInterface/src/CorInfoImpl.cs
@@ -797,6 +797,67 @@ namespace Internal.JitInterface
private CORINFO_METHOD_STRUCT_* resolveVirtualMethod(CORINFO_METHOD_STRUCT_* virtualMethod, CORINFO_CLASS_STRUCT_* implementingClass, CORINFO_CONTEXT_STRUCT* ownerType)
{ throw new NotImplementedException("resolveVirtualMethod"); }
+ private void expandRawHandleIntrinsic(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref CORINFO_GENERICHANDLE_RESULT pResult)
+ {
+ // Resolved token as a potentially RuntimeDetermined object.
+ MethodDesc method = (MethodDesc)GetRuntimeDeterminedObjectForToken(ref pResolvedToken);
+
+ if (method.IsRuntimeDeterminedExactMethod)
+ {
+ pResult.lookup.lookupKind.needsRuntimeLookup = true;
+ pResult.lookup.runtimeLookup.signature = null;
+ pResult.lookup.runtimeLookup.indirections = CORINFO.USEHELPER;
+
+ MethodDesc contextMethod = methodFromContext(pResolvedToken.tokenContext);
+
+ // Do not bother computing the runtime lookup if we are inlining. The JIT is going
+ // to abort the inlining attempt anyway.
+ if (contextMethod == MethodBeingCompiled)
+ {
+ switch (method.Name)
+ {
+ case "EETypePtrOf":
+ pResult.lookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.TypeHandle;
+ pResult.lookup.lookupKind.runtimeLookupArgs = ObjectToHandle(method.Instantiation[0]);
+ break;
+ case "DefaultConstructorOf":
+ pResult.lookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.DefaultConstructor;
+ pResult.lookup.lookupKind.runtimeLookupArgs = ObjectToHandle(method.Instantiation[0]);
+ break;
+ default:
+ Debug.Assert(false);
+ break;
+ }
+
+ pResult.lookup.lookupKind.runtimeLookupKind = GetGenericRuntimeLookupKind(contextMethod);
+ }
+ }
+ else
+ {
+ pResult.lookup.lookupKind.needsRuntimeLookup = false;
+
+ switch (method.Name)
+ {
+ case "EETypePtrOf":
+ pResult.lookup.constLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ConstructedTypeSymbol(method.Instantiation[0]));
+ break;
+ case "DefaultConstructorOf":
+ MethodDesc ctor = method.Instantiation[0].GetDefaultConstructor();
+ if (ctor == null)
+ {
+ MetadataType activatorType = _compilation.TypeSystemContext.SystemModule.GetKnownType("System", "Activator");
+ MetadataType classWithMissingCtor = activatorType.GetKnownNestedType("ClassWithMissingConstructor");
+ ctor = classWithMissingCtor.GetParameterlessConstructor();
+ }
+ pResult.lookup.constLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.CanonicalEntrypoint(ctor));
+ break;
+ default:
+ Debug.Assert(false);
+ break;
+ }
+ }
+ }
+
private SimdHelper _simdHelper;
private bool isInSIMDModule(CORINFO_CLASS_STRUCT_* classHnd)
{
@@ -856,12 +917,6 @@ namespace Internal.JitInterface
{ throw new NotImplementedException("satisfiesMethodConstraints"); }
private bool isCompatibleDelegate(CORINFO_CLASS_STRUCT_* objCls, CORINFO_CLASS_STRUCT_* methodParentCls, CORINFO_METHOD_STRUCT_* method, CORINFO_CLASS_STRUCT_* delegateCls, ref bool pfIsOpenDelegate)
{ throw new NotImplementedException("isCompatibleDelegate"); }
-
- private bool isDelegateCreationAllowed(CORINFO_CLASS_STRUCT_* delegateHnd, CORINFO_METHOD_STRUCT_* calleeHnd)
- {
- return true;
- }
-
private CorInfoInstantiationVerification isInstantiationOfVerifiedGeneric(CORINFO_METHOD_STRUCT_* method)
{ throw new NotImplementedException("isInstantiationOfVerifiedGeneric"); }
private void initConstraintsForVerification(CORINFO_METHOD_STRUCT_* method, ref bool pfHasCircularClassConstraints, ref bool pfHasCircularMethodConstraint)
@@ -927,8 +982,14 @@ namespace Internal.JitInterface
return result;
}
}
+ else
+ {
+ object result = methodIL.GetObject((int)pResolvedToken.token);
+ if (pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Newarr)
+ return ((TypeDesc)result).MakeArrayType();
- return null;
+ return result;
+ }
}
private void resolveToken(ref CORINFO_RESOLVED_TOKEN pResolvedToken)
@@ -964,7 +1025,12 @@ namespace Internal.JitInterface
{
TypeDesc type = (TypeDesc)result;
if (pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Newarr)
+ {
+ if (type.IsVoid)
+ throw new TypeSystemException.InvalidProgramException(ExceptionStringID.InvalidProgramSpecific, methodIL.OwningMethod);
+
type = type.MakeArrayType();
+ }
pResolvedToken.hClass = ObjectToHandle(type);
}
@@ -1352,23 +1418,6 @@ namespace Internal.JitInterface
return type.IsNullable ? CorInfoHelpFunc.CORINFO_HELP_UNBOX_NULLABLE : CorInfoHelpFunc.CORINFO_HELP_UNBOX;
}
- private object GetTargetForFixup(object resolvedToken, ReadyToRunHelperId helperId)
- {
- switch (helperId)
- {
- case ReadyToRunHelperId.TypeHandle:
- if (resolvedToken is TypeDesc)
- return resolvedToken;
- else if (resolvedToken is MethodDesc)
- return ((MethodDesc)resolvedToken).OwningType;
- else
- return ((FieldDesc)resolvedToken).OwningType;
-
- default:
- return resolvedToken;
- }
- }
-
private ISymbolNode GetGenericLookupHelper(CORINFO_RUNTIME_LOOKUP_KIND runtimeLookupKind, ReadyToRunHelperId helperId, object helperArgument)
{
if (runtimeLookupKind == CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_THISOBJ
@@ -1459,11 +1508,7 @@ namespace Internal.JitInterface
Debug.Assert(pGenericLookupKind.needsRuntimeLookup);
ReadyToRunHelperId helperId = (ReadyToRunHelperId)pGenericLookupKind.runtimeLookupFlags;
- object helperArg;
- if (helperId != ReadyToRunHelperId.DelegateCtor)
- helperArg = GetTargetForFixup(GetRuntimeDeterminedObjectForToken(ref pResolvedToken), helperId);
- else
- helperArg = HandleToObject((IntPtr)pGenericLookupKind.runtimeLookupArgs);
+ object helperArg = HandleToObject((IntPtr)pGenericLookupKind.runtimeLookupArgs);
ISymbolNode helper = GetGenericLookupHelper(pGenericLookupKind.runtimeLookupKind, helperId, helperArg);
pLookup = CreateConstLookupToSymbol(helper);
}
@@ -2286,8 +2331,6 @@ namespace Internal.JitInterface
{ throw new NotImplementedException("getInlinedCallFrameVptr"); }
private int* getAddrOfCaptureThreadGlobal(ref void* ppIndirection)
{ throw new NotImplementedException("getAddrOfCaptureThreadGlobal"); }
- private void* getAddrModuleDomainID(CORINFO_MODULE_STRUCT_* module)
- { throw new NotImplementedException("getAddrModuleDomainID"); }
private Dictionary<CorInfoHelpFunc, ISymbolNode> _helperCache = new Dictionary<CorInfoHelpFunc, ISymbolNode>();
private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum)
@@ -2304,6 +2347,8 @@ namespace Internal.JitInterface
case CorInfoHelpFunc.CORINFO_HELP_FAIL_FAST: id = ReadyToRunHelper.FailFast; break;
case CorInfoHelpFunc.CORINFO_HELP_THROWNULLREF: id = ReadyToRunHelper.ThrowNullRef; break;
case CorInfoHelpFunc.CORINFO_HELP_THROWDIVZERO: id = ReadyToRunHelper.ThrowDivZero; break;
+ case CorInfoHelpFunc.CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION: id = ReadyToRunHelper.ThrowArgumentOutOfRange; break;
+ case CorInfoHelpFunc.CORINFO_HELP_THROW_ARGUMENTEXCEPTION: id = ReadyToRunHelper.ThrowArgument; break;
case CorInfoHelpFunc.CORINFO_HELP_ASSIGN_REF: id = ReadyToRunHelper.WriteBarrier; break;
case CorInfoHelpFunc.CORINFO_HELP_CHECKED_ASSIGN_REF: id = ReadyToRunHelper.CheckedWriteBarrier; break;
@@ -2512,6 +2557,8 @@ namespace Internal.JitInterface
pResult.lookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.MethodDictionary;
else
throw new NotImplementedException();
+
+ pResult.lookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(GetRuntimeDeterminedObjectForToken(ref pResolvedToken));
}
}
else if (!fEmbedParent && pResolvedToken.hField != null)
@@ -2533,6 +2580,7 @@ namespace Internal.JitInterface
{
Debug.Assert(pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Ldtoken);
pResult.lookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.FieldHandle;
+ pResult.lookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(GetRuntimeDeterminedObjectForToken(ref pResolvedToken));
}
}
else
@@ -2558,6 +2606,23 @@ namespace Internal.JitInterface
else
{
pResult.lookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.TypeHandle;
+
+ object obj = GetRuntimeDeterminedObjectForToken(ref pResolvedToken);
+ TypeDesc type = obj as TypeDesc;
+ if (type == null)
+ {
+ if (obj is MethodDesc)
+ {
+ type = ((MethodDesc)obj).OwningType;
+ }
+ else
+ {
+ Debug.Assert(obj is FieldDesc);
+ type = ((FieldDesc)obj).OwningType;
+ }
+ }
+
+ pResult.lookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(type);
}
}
@@ -2807,6 +2872,7 @@ namespace Internal.JitInterface
{
pResult.codePointerOrStubLookup.lookupKind.runtimeLookupKind = GetGenericRuntimeLookupKind(contextMethod);
pResult.codePointerOrStubLookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.MethodEntry;
+ pResult.codePointerOrStubLookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(GetRuntimeDeterminedObjectForToken(ref pResolvedToken));
}
}
else
@@ -2939,6 +3005,7 @@ namespace Internal.JitInterface
{
pResult.codePointerOrStubLookup.lookupKind.runtimeLookupKind = GetGenericRuntimeLookupKind(contextMethod);
pResult.codePointerOrStubLookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.MethodHandle;
+ pResult.codePointerOrStubLookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(GetRuntimeDeterminedObjectForToken(ref pResolvedToken));
}
}
@@ -2979,6 +3046,7 @@ namespace Internal.JitInterface
{
pResult.codePointerOrStubLookup.lookupKind.runtimeLookupKind = GetGenericRuntimeLookupKind(contextMethod);
pResult.codePointerOrStubLookup.lookupKind.runtimeLookupFlags = (ushort)helperId;
+ pResult.codePointerOrStubLookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(GetRuntimeDeterminedObjectForToken(ref pResolvedToken));
}
}
else
diff --git a/src/JitInterface/src/CorInfoTypes.cs b/src/JitInterface/src/CorInfoTypes.cs
index ed8c6eec4..53bb1f721 100644
--- a/src/JitInterface/src/CorInfoTypes.cs
+++ b/src/JitInterface/src/CorInfoTypes.cs
@@ -280,6 +280,9 @@ namespace Internal.JitInterface
public IntPtr offset1;
public IntPtr offset2;
public IntPtr offset3;
+
+ public byte _indirectFirstOffset;
+ public bool indirectFirstOffset { get { return _indirectFirstOffset != 0; } set { _indirectFirstOffset = value ? (byte)1 : (byte)0; } }
}
// Result of calling embedGenericHandle
@@ -473,6 +476,7 @@ namespace Internal.JitInterface
CORINFO_INTRINSIC_ByReference_Value,
CORINFO_INTRINSIC_Span_GetItem,
CORINFO_INTRINSIC_ReadOnlySpan_GetItem,
+ CORINFO_INTRINSIC_GetRawHandle,
CORINFO_INTRINSIC_Count,
CORINFO_INTRINSIC_Illegal = -1, // Not a true intrinsic,
diff --git a/src/JitInterface/src/ThunkGenerator/ThunkInput.txt b/src/JitInterface/src/ThunkGenerator/ThunkInput.txt
index 9e34ade7e..25aaa420d 100644
--- a/src/JitInterface/src/ThunkGenerator/ThunkInput.txt
+++ b/src/JitInterface/src/ThunkGenerator/ThunkInput.txt
@@ -171,13 +171,13 @@ FUNCTIONS
CORINFO_MODULE_HANDLE getMethodModule( CORINFO_METHOD_HANDLE method );
void getMethodVTableOffset( CORINFO_METHOD_HANDLE method, unsigned* offsetOfIndirection, unsigned* offsetAfterIndirection );
CORINFO_METHOD_HANDLE resolveVirtualMethod( CORINFO_METHOD_HANDLE virtualMethod, CORINFO_CLASS_HANDLE implementingClass, CORINFO_CONTEXT_HANDLE ownerType);
+ void expandRawHandleIntrinsic(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_GENERICHANDLE_RESULT * pResult);
CorInfoIntrinsics getIntrinsicID( CORINFO_METHOD_HANDLE method , bool * pMustExpand);
bool isInSIMDModule( CORINFO_CLASS_HANDLE classHnd );
CorInfoUnmanagedCallConv getUnmanagedCallConv( CORINFO_METHOD_HANDLE method );
BOOL pInvokeMarshalingRequired( CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* callSiteSig );
BOOL satisfiesMethodConstraints( CORINFO_CLASS_HANDLE parent, CORINFO_METHOD_HANDLE method );
BOOL isCompatibleDelegate( CORINFO_CLASS_HANDLE objCls, CORINFO_CLASS_HANDLE methodParentCls, CORINFO_METHOD_HANDLE method, CORINFO_CLASS_HANDLE delegateCls, BOOL *pfIsOpenDelegate );
- BOOL isDelegateCreationAllowed( CORINFO_CLASS_HANDLE delegateHnd, CORINFO_METHOD_HANDLE calleeHnd );
CorInfoInstantiationVerification isInstantiationOfVerifiedGeneric( CORINFO_METHOD_HANDLE method );
void initConstraintsForVerification( CORINFO_METHOD_HANDLE method, BOOL *pfHasCircularClassConstraints, BOOL *pfHasCircularMethodConstraint );
CorInfoCanSkipVerificationResult canSkipMethodVerification( CORINFO_METHOD_HANDLE ftnHandle );
@@ -271,7 +271,6 @@ FUNCTIONS
DWORD getThreadTLSIndex(void **ppIndirection);
const void * getInlinedCallFrameVptr(void **ppIndirection);
LONG * getAddrOfCaptureThreadGlobal(void **ppIndirection);
- SIZE_T* getAddrModuleDomainID(CORINFO_MODULE_HANDLE module);
void* getHelperFtn (CorInfoHelpFunc ftnNum, void **ppIndirection);
void getFunctionEntryPoint(CORINFO_METHOD_HANDLE ftn, CORINFO_CONST_LOOKUP * pResult, CORINFO_ACCESS_FLAGS accessFlags);
void getFunctionFixedEntryPoint(CORINFO_METHOD_HANDLE ftn, CORINFO_CONST_LOOKUP * pResult);
diff --git a/src/JitInterface/src/ThunkGenerator/corinfo.h b/src/JitInterface/src/ThunkGenerator/corinfo.h
index 2495de251..e27283c8b 100644
--- a/src/JitInterface/src/ThunkGenerator/corinfo.h
+++ b/src/JitInterface/src/ThunkGenerator/corinfo.h
@@ -213,11 +213,11 @@ TODO: Talk about initializing strutures before use
#define SELECTANY extern __declspec(selectany)
#endif
-SELECTANY const GUID JITEEVersionIdentifier = { /* f00b3f49-ddd2-49be-ba43-6e49ffa66959 */
- 0xf00b3f49,
- 0xddd2,
- 0x49be,
- { 0xba, 0x43, 0x6e, 0x49, 0xff, 0xa6, 0x69, 0x59 }
+SELECTANY const GUID JITEEVersionIdentifier = { /* e5708e9e-dd18-4287-8745-5d10ff2697cf */
+ 0xe5708e9e,
+ 0xdd18,
+ 0x4287,
+ { 0x87, 0x45, 0x5d, 0x10, 0xff, 0x26, 0x97, 0xcf }
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -960,6 +960,7 @@ enum CorInfoIntrinsics
CORINFO_INTRINSIC_ByReference_Value,
CORINFO_INTRINSIC_Span_GetItem,
CORINFO_INTRINSIC_ReadOnlySpan_GetItem,
+ CORINFO_INTRINSIC_GetRawHandle,
CORINFO_INTRINSIC_Count,
CORINFO_INTRINSIC_Illegal = -1, // Not a true intrinsic,
@@ -1323,6 +1324,13 @@ struct CORINFO_RUNTIME_LOOKUP
bool testForFixup;
SIZE_T offsets[CORINFO_MAXINDIRECTIONS];
+
+ // If set, first offset is indirect.
+ // 0 means that value stored at first offset (offsets[0]) from pointer is next pointer, to which the next offset
+ // (offsets[1]) is added and so on.
+ // 1 means that value stored at first offset (offsets[0]) from pointer is offset1, and the next pointer is
+ // stored at pointer+offsets[0]+offset1.
+ bool indirectFirstOffset;
} ;
// Result of calling embedGenericHandle
@@ -1513,7 +1521,8 @@ enum CORINFO_CALL_KIND
CORINFO_VIRTUALCALL_VTABLE
};
-
+// Indicates that the CORINFO_VIRTUALCALL_VTABLE lookup needn't do a chunk indirection
+#define CORINFO_VIRTUALCALL_NO_CHUNK 0xFFFFFFFF
enum CORINFO_THIS_TRANSFORM
{
@@ -2067,6 +2076,15 @@ public:
CORINFO_CONTEXT_HANDLE ownerType = NULL /* IN */
) = 0;
+ // Given resolved token that corresponds to an intrinsic classified as
+ // a CORINFO_INTRINSIC_GetRawHandle intrinsic, fetch the handle associated
+ // with the token. If this is not possible at compile-time (because the current method's
+ // code is shared and the token contains generic parameters) then indicate
+ // how the handle should be looked up at runtime.
+ virtual void expandRawHandleIntrinsic(
+ CORINFO_RESOLVED_TOKEN * pResolvedToken,
+ CORINFO_GENERICHANDLE_RESULT * pResult) = 0;
+
// If a method's attributes have (getMethodAttribs) CORINFO_FLG_INTRINSIC set,
// getIntrinsicID() returns the intrinsic ID.
// *pMustExpand tells whether or not JIT must expand the intrinsic.
@@ -2111,13 +2129,6 @@ public:
BOOL *pfIsOpenDelegate /* is the delegate open */
) = 0;
- // Determines whether the delegate creation obeys security transparency rules
- virtual BOOL isDelegateCreationAllowed (
- CORINFO_CLASS_HANDLE delegateHnd,
- CORINFO_METHOD_HANDLE calleeHnd
- ) = 0;
-
-
// Indicates if the method is an instance of the generic
// method that passes (or has passed) verification
virtual CorInfoInstantiationVerification isInstantiationOfVerifiedGeneric (
@@ -2838,8 +2849,6 @@ public:
void **ppIndirection = NULL
) = 0;
- virtual SIZE_T* getAddrModuleDomainID(CORINFO_MODULE_HANDLE module) = 0;
-
// return the native entry point to an EE helper (see CorInfoHelpFunc)
virtual void* getHelperFtn (
CorInfoHelpFunc ftnNum,
diff --git a/src/Native/Runtime/arm/CallDescrWorker.S b/src/Native/Runtime/arm/CallDescrWorker.S
index de818954b..77017f4f8 100644
--- a/src/Native/Runtime/arm/CallDescrWorker.S
+++ b/src/Native/Runtime/arm/CallDescrWorker.S
@@ -4,4 +4,29 @@
#include <unixasmmacros.inc>
+.syntax unified
+.thumb
+
// TODO: Implement Arm support
+
+NESTED_ENTRY RhCallDescrWorker, _TEXT, NoHandler
+LOCAL_LABEL(ReturnFromCallDescrThunk):
+
+ // UNIXTODO: Implement this function
+ // int 3
+#ifdef _DEBUG
+ bl C_FUNC(NYI_Assert)
+#endif
+NESTED_END RhCallDescrWorker, _TEXT
+
+//.text
+//.align 8
+//C_FUNC(PointerToReturnFromCallDescrThunk):
+//.quad LOCAL_LABEL(ReturnFromCallDescrThunk)
+//.global C_FUNC(PointerToReturnFromCallDescrThunk)
+
+LEAF_ENTRY PointerToReturnFromCallDescrThunk, _TEXT
+#ifdef _DEBUG
+ bl C_FUNC(NYI_Assert)
+#endif
+LEAF_END PointerToReturnFromCallDescrThunk, _TEXT
diff --git a/src/Native/Runtime/arm/ExceptionHandling.S b/src/Native/Runtime/arm/ExceptionHandling.S
index de818954b..e5eaf6372 100644
--- a/src/Native/Runtime/arm/ExceptionHandling.S
+++ b/src/Native/Runtime/arm/ExceptionHandling.S
@@ -4,4 +4,143 @@
#include <unixasmmacros.inc>
+.syntax unified
+.thumb
+
// TODO: Implement Arm support
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// RhpThrowHwEx
+//
+// INPUT: RDI: exception code of fault
+// RSI: faulting RIP
+//
+// OUTPUT:
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+NESTED_ENTRY RhpThrowHwEx, _TEXT, NoHandler
+
+ALTERNATE_ENTRY RhpThrowHwEx2
+
+#ifdef _DEBUG
+ bl C_FUNC(NYI_Assert)
+#endif
+
+NESTED_END RhpThrowHwEx
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// RhpThrowEx
+//
+// INPUT: RDI: exception object
+//
+// OUTPUT:
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+NESTED_ENTRY RhpThrowEx, _TEXT, NoHandler
+
+ALTERNATE_ENTRY RhpThrowEx2
+
+#ifdef _DEBUG
+ bl C_FUNC(NYI_Assert)
+#endif
+
+NESTED_END RhpThrowEx, _TEXT
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// void FASTCALL RhpRethrow()
+//
+// SUMMARY: Similar to RhpThrowEx, except that it passes along the currently active ExInfo
+//
+// INPUT:
+//
+// OUTPUT:
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+NESTED_ENTRY RhpRethrow, _TEXT, NoHandler
+
+ALTERNATE_ENTRY RhpRethrow2
+
+#ifdef _DEBUG
+ bl C_FUNC(NYI_Assert)
+#endif
+
+NESTED_END RhpRethrow, _TEXT
+
+//
+// Prologue of all funclet calling helpers (RhpCallXXXXFunclet)
+//
+
+//
+// Epilogue of all funclet calling helpers (RhpCallXXXXFunclet)
+//
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// void* FASTCALL RhpCallCatchFunclet(RtuObjectRef exceptionObj, void* pHandlerIP, REGDISPLAY* pRegDisplay,
+// ExInfo* pExInfo)
+//
+// INPUT: RDI: exception object
+// RSI: handler funclet address
+// RDX: REGDISPLAY*
+// RCX: ExInfo*
+//
+// OUTPUT:
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+NESTED_ENTRY RhpCallCatchFunclet, _TEXT, NoHandler
+
+ALTERNATE_ENTRY RhpCallCatchFunclet2
+
+
+#ifdef _DEBUG
+ bl C_FUNC(NYI_Assert)
+#endif
+
+NESTED_END RhpCallCatchFunclet, _TEXT
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// void FASTCALL RhpCallFinallyFunclet(void* pHandlerIP, REGDISPLAY* pRegDisplay)
+//
+// INPUT: RDI: handler funclet address
+// RSI: REGDISPLAY*
+//
+// OUTPUT:
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+NESTED_ENTRY RhpCallFinallyFunclet, _TEXT, NoHandler
+
+ALTERNATE_ENTRY RhpCallFinallyFunclet2
+
+#ifdef _DEBUG
+ bl C_FUNC(NYI_Assert)
+#endif
+
+NESTED_END RhpCallFinallyFunclet, _TEXT
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// void* FASTCALL RhpCallFilterFunclet(RtuObjectRef exceptionObj, void* pFilterIP, REGDISPLAY* pRegDisplay)
+//
+// INPUT: RDI: exception object
+// RSI: filter funclet address
+// RDX: REGDISPLAY*
+//
+// OUTPUT:
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+NESTED_ENTRY RhpCallFilterFunclet, _TEXT, NoHandler
+
+ALTERNATE_ENTRY RhpCallFilterFunclet2
+
+#ifdef _DEBUG
+ bl C_FUNC(NYI_Assert)
+#endif
+
+NESTED_END RhpCallFilterFunclet, _TEXT
diff --git a/src/Native/Runtime/arm/StubDispatch.S b/src/Native/Runtime/arm/StubDispatch.S
index de818954b..7c79a11b8 100644
--- a/src/Native/Runtime/arm/StubDispatch.S
+++ b/src/Native/Runtime/arm/StubDispatch.S
@@ -4,4 +4,79 @@
#include <unixasmmacros.inc>
+.syntax unified
+.thumb
+
// TODO: Implement Arm support
+
+LEAF_ENTRY RhpCastableObjectDispatch_CommonStub, _TEXT
+ // UNIXTODO: Implement this function
+ //int 3
+LEAF_END RhpCastableObjectDispatch_CommonStub, _TEXT
+
+LEAF_ENTRY RhpTailCallTLSDispatchCell, _TEXT
+ // UNIXTODO: Implement this function
+ // int 3
+LEAF_END RhpTailCallTLSDispatchCell, _TEXT
+
+LEAF_ENTRY RhpCastableObjectDispatchHelper_TailCalled, _TEXT
+ // UNIXTODO: Implement this function
+ // int 3
+LEAF_END RhpCastableObjectDispatchHelper_TailCalled, _TEXT
+
+LEAF_ENTRY RhpCastableObjectDispatchHelper, _TEXT
+ // UNIXTODO: Implement this function
+ // int 3
+LEAF_END RhpCastableObjectDispatchHelper, _TEXT
+
+
+// Stub dispatch routine for dispatch to a vtable slot
+LEAF_ENTRY RhpVTableOffsetDispatch, _TEXT
+ // UNIXTODO: Implement this function
+ // int 3
+LEAF_END RhpVTableOffsetDispatch, _TEXT
+
+// Initial dispatch on an interface when we don't have a cache yet.
+LEAF_ENTRY RhpInitialInterfaceDispatch, _TEXT
+ALTERNATE_ENTRY RhpInitialDynamicInterfaceDispatch
+
+ // Just tail call to the cache miss helper.
+ // jmp C_FUNC(RhpInterfaceDispatchSlow)
+
+LEAF_END RhpInitialInterfaceDispatch, _TEXT
+
+// Cache miss case, call the runtime to resolve the target and update the cache.
+// Use universal transition helper to allow an exception to flow out of resolution
+LEAF_ENTRY RhpInterfaceDispatchSlow, _TEXT
+ // jmp C_FUNC(RhpUniversalTransition_DebugStepTailCall)
+
+LEAF_END RhpInterfaceDispatchSlow, _TEXT
+
+
+LEAF_ENTRY RhpInterfaceDispatch1, _TEXT
+
+LEAF_END RhpInterfaceDispatch1, _TEXT
+
+LEAF_ENTRY RhpInterfaceDispatch2, _TEXT
+
+LEAF_END RhpInterfaceDispatch2, _TEXT
+
+LEAF_ENTRY RhpInterfaceDispatch4, _TEXT
+
+LEAF_END RhpInterfaceDispatch4, _TEXT
+
+LEAF_ENTRY RhpInterfaceDispatch8, _TEXT
+
+LEAF_END RhpInterfaceDispatch8, _TEXT
+
+LEAF_ENTRY RhpInterfaceDispatch16, _TEXT
+
+LEAF_END RhpInterfaceDispatch16, _TEXT
+
+LEAF_ENTRY RhpInterfaceDispatch32, _TEXT
+
+LEAF_END RhpInterfaceDispatch32, _TEXT
+
+LEAF_ENTRY RhpInterfaceDispatch64, _TEXT
+
+LEAF_END RhpInterfaceDispatch64, _TEXT
diff --git a/src/Native/Runtime/arm/UniversalTransition.S b/src/Native/Runtime/arm/UniversalTransition.S
index de818954b..feaace2eb 100644
--- a/src/Native/Runtime/arm/UniversalTransition.S
+++ b/src/Native/Runtime/arm/UniversalTransition.S
@@ -4,4 +4,84 @@
#include <unixasmmacros.inc>
+.syntax unified
+.thumb
+
// TODO: Implement Arm support
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// RhpUniversalTransition
+//
+// At input to this function, r0-3, d0-7 and the stack may contain any number of arguments.
+//
+// In addition, there are 2 extra arguments passed in the RED ZONE (8 byte negative space
+// off of sp).
+// sp-4 will contain the managed function that is to be called by this transition function
+// sp-8 will contain the pointer sized extra argument to the managed function
+//
+// When invoking the callee:
+//
+// r0 shall contain a pointer to the TransitionBlock
+// r1 shall contain the value that was in sp-8 at entry to this function
+//
+// Frame layout is:
+//
+// {StackPassedArgs} ChildSP+078 CallerSP+000
+// {IntArgRegs (r0-r3) (0x10 bytes)} ChildSP+068 CallerSP-010
+// {ReturnBlock (0x20 bytes)} ChildSP+048 CallerSP-030
+// -- The base address of the Return block is the TransitionBlock pointer, the floating point args are
+// in the neg space of the TransitionBlock pointer. Note that the callee has knowledge of the exact
+// layout of all pieces of the frame that lie at or above the pushed floating point registers.
+// {FpArgRegs (d0-d7) (0x40 bytes)} ChildSP+008 CallerSP-070
+// {PushedLR} ChildSP+004 CallerSP-074
+// {PushedR11} ChildSP+000 CallerSP-078
+//
+// NOTE: If the frame layout ever changes, the C++ UniversalTransitionStackFrame structure
+// must be updated as well.
+//
+// NOTE: The callee receives a pointer to the base of the ReturnBlock, and the callee has
+// knowledge of the exact layout of all pieces of the frame that lie at or above the pushed
+// FpArgRegs.
+//
+// NOTE: The stack walker guarantees that conservative GC reporting will be applied to
+// everything between the base of the ReturnBlock and the top of the StackPassedArgs.
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+NESTED_ENTRY RhpUniversalTransition, _TEXT, NoHandler
+
+LOCAL_LABEL(ReturnFromUniversalTransition):
+
+#ifdef _DEBUG
+ bl C_FUNC(NYI_Assert)
+#endif
+
+NESTED_END RhpUniversalTransition
+
+NESTED_ENTRY PointerToReturnFromUniversalTransition, _TEXT, NoHandler
+
+#ifdef _DEBUG
+ bl C_FUNC(NYI_Assert)
+#endif
+
+NESTED_END PointerToReturnFromUniversalTransition
+
+
+NESTED_ENTRY RhpUniversalTransition_DebugStepTailCall, _TEXT, NoHandler
+
+LOCAL_LABEL(ReturnFromUniversalTransition_DebugStepTailCall):
+
+#ifdef _DEBUG
+ bl C_FUNC(NYI_Assert)
+#endif
+
+NESTED_END RhpUniversalTransition_DebugStepTailCall
+
+NESTED_ENTRY PointerToReturnFromUniversalTransition_DebugStepTailCall, _TEXT, NoHandler
+
+#ifdef _DEBUG
+ bl C_FUNC(NYI_Assert)
+#endif
+
+NESTED_END PointerToReturnFromUniversalTransition_DebugStepTailCall
diff --git a/src/Native/Runtime/arm/WriteBarriers.S b/src/Native/Runtime/arm/WriteBarriers.S
index 316770987..c34af7e09 100644
--- a/src/Native/Runtime/arm/WriteBarriers.S
+++ b/src/Native/Runtime/arm/WriteBarriers.S
@@ -5,12 +5,27 @@
// TODO: Implement Unix write barriers
#include <unixasmmacros.inc>
+.syntax unified
+.thumb
+
LEAF_ENTRY RhpAssignRef, _TEXT
+ALTERNATE_ENTRY RhpAssignRefAVLocation
str r1, [r0]
bx lr
LEAF_END RhpAssignRef, _TEXT
+// Define a helper with a name of the form RhpCheckedAssignRefEAX etc. (along with suitable calling standard
+// decoration). The location to be updated is always in RDI. The object reference that will be assigned into
+// that location is in one of the other general registers determined by the value of REFREG.
+
+// WARNING: Code in EHHelpers.cpp makes assumptions about write barrier code, in particular:
+// - Function "InWriteBarrierHelper" assumes an AV due to passed in null pointer will happen on the first instruction
+// - Function "UnwindWriteBarrierToCaller" assumes the stack contains just the pushed return address
LEAF_ENTRY RhpCheckedAssignRef, _TEXT
+
+// ALTERNATE_ENTRY RhpCheckedAssignRef
+ALTERNATE_ENTRY RhpCheckedAssignRefAVLocation
+
str r1, [r0]
bx lr
LEAF_END RhpCheckedAssignRef, _TEXT
@@ -32,3 +47,22 @@ LEAF_ENTRY RhpByRefAssignRef, _TEXT
str r3, [r0], #4
bx lr
LEAF_END RhpByRefAssignRef, _TEXT
+
+
+// WARNING: Code in EHHelpers.cpp makes assumptions about write barrier code, in particular:
+// - Function "InWriteBarrierHelper" assumes an AV due to passed in null pointer will happen at RhpCheckedLockCmpXchgAVLocation
+// - Function "UnwindWriteBarrierToCaller" assumes the stack contains just the pushed return address
+LEAF_ENTRY RhpCheckedLockCmpXchg, _TEXT
+ALTERNATE_ENTRY RhpCheckedLockCmpXchgAVLocation
+LEAF_END RhpCheckedLockCmpXchg, _TEXT
+
+
+// WARNING: Code in EHHelpers.cpp makes assumptions about write barrier code, in particular:
+// - Function "InWriteBarrierHelper" assumes an AV due to passed in null pointer will happen at RhpCheckedXchgAVLocation
+// - Function "UnwindWriteBarrierToCaller" assumes the stack contains just the pushed return address
+LEAF_ENTRY RhpCheckedXchg, _TEXT
+
+// Setup rax with the new object for the exchange, that way it will automatically hold the correct result
+// afterwards and we can leave rdx unaltered ready for the GC write barrier below.
+ALTERNATE_ENTRY RhpCheckedXchgAVLocation
+LEAF_END RhpCheckedXchg, _TEXT
diff --git a/src/Native/Runtime/rhassert.cpp b/src/Native/Runtime/rhassert.cpp
index 4928befa0..04fa1ac97 100644
--- a/src/Native/Runtime/rhassert.cpp
+++ b/src/Native/Runtime/rhassert.cpp
@@ -95,8 +95,10 @@ void Assert(const char * expr, const char * file, UInt32 line_num, const char *
#endif //!DACCESS_COMPILE
}
-void NYI_Assert()
+extern "C" void NYI_Assert()
{
+#if !defined(DACCESS_COMPILE)
ASSERT_UNCONDITIONALLY("NYI");
+#endif
}
#endif // _DEBUG
diff --git a/src/Native/Runtime/rhassert.h b/src/Native/Runtime/rhassert.h
index 5808941e8..9863822fc 100644
--- a/src/Native/Runtime/rhassert.h
+++ b/src/Native/Runtime/rhassert.h
@@ -26,8 +26,6 @@
void Assert(const char * expr, const char * file, unsigned int line_num, const char * message);
-void NYI_Assert();
-
#else
#define ASSERT(expr)
@@ -38,7 +36,13 @@ void NYI_Assert();
#define ASSERT_UNCONDITIONALLY(message)
-#endif
+#endif
+
+#if defined(_DEBUG)
+
+void NYI_ASSERT();
+
+#endif
#define PORTABILITY_ASSERT(message) \
ASSERT_UNCONDITIONALLY(message); \
diff --git a/src/Native/jitinterface/jitinterface.h b/src/Native/jitinterface/jitinterface.h
index d6a58a82f..c655eb1e5 100644
--- a/src/Native/jitinterface/jitinterface.h
+++ b/src/Native/jitinterface/jitinterface.h
@@ -23,13 +23,13 @@ struct JitInterfaceCallbacks
void* (__stdcall * getMethodModule)(void * thisHandle, CorInfoException** ppException, void* method);
void (__stdcall * getMethodVTableOffset)(void * thisHandle, CorInfoException** ppException, void* method, unsigned* offsetOfIndirection, unsigned* offsetAfterIndirection);
void* (__stdcall * resolveVirtualMethod)(void * thisHandle, CorInfoException** ppException, void* virtualMethod, void* implementingClass, void* ownerType);
+ void (__stdcall * expandRawHandleIntrinsic)(void * thisHandle, CorInfoException** ppException, void* pResolvedToken, void* pResult);
int (__stdcall * getIntrinsicID)(void * thisHandle, CorInfoException** ppException, void* method, bool* pMustExpand);
bool (__stdcall * isInSIMDModule)(void * thisHandle, CorInfoException** ppException, void* classHnd);
int (__stdcall * getUnmanagedCallConv)(void * thisHandle, CorInfoException** ppException, void* method);
int (__stdcall * pInvokeMarshalingRequired)(void * thisHandle, CorInfoException** ppException, void* method, void* callSiteSig);
int (__stdcall * satisfiesMethodConstraints)(void * thisHandle, CorInfoException** ppException, void* parent, void* method);
int (__stdcall * isCompatibleDelegate)(void * thisHandle, CorInfoException** ppException, void* objCls, void* methodParentCls, void* method, void* delegateCls, int* pfIsOpenDelegate);
- int (__stdcall * isDelegateCreationAllowed)(void * thisHandle, CorInfoException** ppException, void* delegateHnd, void* calleeHnd);
int (__stdcall * isInstantiationOfVerifiedGeneric)(void * thisHandle, CorInfoException** ppException, void* method);
void (__stdcall * initConstraintsForVerification)(void * thisHandle, CorInfoException** ppException, void* method, int* pfHasCircularClassConstraints, int* pfHasCircularMethodConstraint);
int (__stdcall * canSkipMethodVerification)(void * thisHandle, CorInfoException** ppException, void* ftnHandle);
@@ -123,7 +123,6 @@ struct JitInterfaceCallbacks
unsigned int (__stdcall * getThreadTLSIndex)(void * thisHandle, CorInfoException** ppException, void** ppIndirection);
const void* (__stdcall * getInlinedCallFrameVptr)(void * thisHandle, CorInfoException** ppException, void** ppIndirection);
long* (__stdcall * getAddrOfCaptureThreadGlobal)(void * thisHandle, CorInfoException** ppException, void** ppIndirection);
- size_t* (__stdcall * getAddrModuleDomainID)(void * thisHandle, CorInfoException** ppException, void* module);
void* (__stdcall * getHelperFtn)(void * thisHandle, CorInfoException** ppException, int ftnNum, void** ppIndirection);
void (__stdcall * getFunctionEntryPoint)(void * thisHandle, CorInfoException** ppException, void* ftn, void* pResult, int accessFlags);
void (__stdcall * getFunctionFixedEntryPoint)(void * thisHandle, CorInfoException** ppException, void* ftn, void* pResult);
@@ -301,6 +300,14 @@ public:
return _ret;
}
+ virtual void expandRawHandleIntrinsic(void* pResolvedToken, void* pResult)
+ {
+ CorInfoException* pException = nullptr;
+ _callbacks->expandRawHandleIntrinsic(_thisHandle, &pException, pResolvedToken, pResult);
+ if (pException != nullptr)
+ throw pException;
+ }
+
virtual int getIntrinsicID(void* method, bool* pMustExpand)
{
CorInfoException* pException = nullptr;
@@ -355,15 +362,6 @@ public:
return _ret;
}
- virtual int isDelegateCreationAllowed(void* delegateHnd, void* calleeHnd)
- {
- CorInfoException* pException = nullptr;
- int _ret = _callbacks->isDelegateCreationAllowed(_thisHandle, &pException, delegateHnd, calleeHnd);
- if (pException != nullptr)
- throw pException;
- return _ret;
- }
-
virtual int isInstantiationOfVerifiedGeneric(void* method)
{
CorInfoException* pException = nullptr;
@@ -1158,15 +1156,6 @@ public:
return _ret;
}
- virtual size_t* getAddrModuleDomainID(void* module)
- {
- CorInfoException* pException = nullptr;
- size_t* _ret = _callbacks->getAddrModuleDomainID(_thisHandle, &pException, module);
- if (pException != nullptr)
- throw pException;
- return _ret;
- }
-
virtual void* getHelperFtn(int ftnNum, void** ppIndirection)
{
CorInfoException* pException = nullptr;
diff --git a/src/Native/jitinterface/jitwrapper.cpp b/src/Native/jitinterface/jitwrapper.cpp
index 8a3af11f8..88699badb 100644
--- a/src/Native/jitinterface/jitwrapper.cpp
+++ b/src/Native/jitinterface/jitwrapper.cpp
@@ -27,11 +27,11 @@ private:
unsigned __int64 corJitFlags;
};
-static const GUID JITEEVersionIdentifier = { /* f00b3f49-ddd2-49be-ba43-6e49ffa66959 */
- 0xf00b3f49,
- 0xddd2,
- 0x49be,
- { 0xba, 0x43, 0x6e, 0x49, 0xff, 0xa6, 0x69, 0x59 }
+static const GUID JITEEVersionIdentifier = { /* e5708e9e-dd18-4287-8745-5d10ff2697cf */
+ 0xe5708e9e,
+ 0xdd18,
+ 0x4287,
+ { 0x87, 0x45, 0x5d, 0x10, 0xff, 0x26, 0x97, 0xcf }
};
class Jit
diff --git a/src/System.Private.CoreLib/shared/System/Char.cs b/src/System.Private.CoreLib/shared/System/Char.cs
index 3fad7a482..72441763e 100644
--- a/src/System.Private.CoreLib/shared/System/Char.cs
+++ b/src/System.Private.CoreLib/shared/System/Char.cs
@@ -21,6 +21,7 @@ namespace System
{
[Serializable]
[StructLayout(LayoutKind.Sequential)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct Char : IComparable, IComparable<Char>, IEquatable<Char>, IConvertible
{
//
diff --git a/src/System.Private.CoreLib/shared/System/Collections/DictionaryEntry.cs b/src/System.Private.CoreLib/shared/System/Collections/DictionaryEntry.cs
index 290306d00..3c1c0befa 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/DictionaryEntry.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/DictionaryEntry.cs
@@ -9,10 +9,11 @@ namespace System.Collections
// A DictionaryEntry holds a key and a value from a dictionary.
// It is returned by IDictionaryEnumerator::GetEntry().
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct DictionaryEntry
{
- private Object _key;
- private Object _value;
+ private Object _key; // Do not rename (binary serialization)
+ private Object _value; // Do not rename (binary serialization)
// Constructs a new DictionaryEnumerator by setting the Key
// and Value fields appropriately.
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Generic/KeyValuePair.cs b/src/System.Private.CoreLib/shared/System/Collections/Generic/KeyValuePair.cs
index fc51af25f..aeafecd95 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/Generic/KeyValuePair.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/Generic/KeyValuePair.cs
@@ -46,10 +46,11 @@ namespace System.Collections.Generic
// It is used by the IEnumerable<T> implementation for both IDictionary<TKey, TValue>
// and IReadOnlyDictionary<TKey, TValue>.
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct KeyValuePair<TKey, TValue>
{
- private TKey key; // DO NOT change the field name, it's required for compatibility with desktop .NET as it appears in serialization payload.
- private TValue value; // DO NOT change the field name, it's required for compatibility with desktop .NET as it appears in serialization payload.
+ private TKey key; // Do not rename (binary serialization)
+ private TValue value; // Do not rename (binary serialization)
public KeyValuePair(TKey key, TValue value)
{
diff --git a/src/System.Private.CoreLib/shared/System/DateTime.cs b/src/System.Private.CoreLib/shared/System/DateTime.cs
index ddb72da77..4fd9727fc 100644
--- a/src/System.Private.CoreLib/shared/System/DateTime.cs
+++ b/src/System.Private.CoreLib/shared/System/DateTime.cs
@@ -54,6 +54,7 @@ namespace System
//
[StructLayout(LayoutKind.Auto)]
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public partial struct DateTime : IComparable, IFormattable, IConvertible, IComparable<DateTime>, IEquatable<DateTime>, ISerializable
{
// Number of 100ns ticks per time unit
@@ -125,8 +126,8 @@ namespace System
private const UInt64 KindLocalAmbiguousDst = 0xC000000000000000;
private const Int32 KindShift = 62;
- private const String TicksField = "ticks";
- private const String DateDataField = "_dateData";
+ private const String TicksField = "ticks"; // Do not rename (binary serialization)
+ private const String DateDataField = "dateData"; // Do not rename (binary serialization)
// The data is stored as an unsigned 64-bit integeter
// Bits 01-62: The value of 100-nanosecond ticks where 0 represents 1/1/0001 12:00am, up until the value
diff --git a/src/System.Private.CoreLib/shared/System/DateTimeOffset.cs b/src/System.Private.CoreLib/shared/System/DateTimeOffset.cs
index d5ccbd919..ab35bdb0f 100644
--- a/src/System.Private.CoreLib/shared/System/DateTimeOffset.cs
+++ b/src/System.Private.CoreLib/shared/System/DateTimeOffset.cs
@@ -30,6 +30,7 @@ namespace System
[StructLayout(LayoutKind.Auto)]
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct DateTimeOffset : IComparable, IFormattable, IComparable<DateTimeOffset>, IEquatable<DateTimeOffset>, ISerializable, IDeserializationCallback
{
// Constants
@@ -573,8 +574,8 @@ namespace System
throw new ArgumentNullException(nameof(info));
}
- info.AddValue("DateTime", _dateTime);
- info.AddValue("OffsetMinutes", _offsetMinutes);
+ info.AddValue("DateTime", _dateTime); // Do not rename (binary serialization)
+ info.AddValue("OffsetMinutes", _offsetMinutes); // Do not rename (binary serialization)
}
@@ -585,8 +586,8 @@ namespace System
throw new ArgumentNullException(nameof(info));
}
- _dateTime = (DateTime)info.GetValue("DateTime", typeof(DateTime));
- _offsetMinutes = (Int16)info.GetValue("OffsetMinutes", typeof(Int16));
+ _dateTime = (DateTime)info.GetValue("DateTime", typeof(DateTime)); // Do not rename (binary serialization)
+ _offsetMinutes = (Int16)info.GetValue("OffsetMinutes", typeof(Int16)); // Do not rename (binary serialization)
}
// Returns the hash code for this DateTimeOffset.
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/SortVersion.cs b/src/System.Private.CoreLib/shared/System/Globalization/SortVersion.cs
index 94c04d706..46e9a833e 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/SortVersion.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/SortVersion.cs
@@ -5,6 +5,7 @@
namespace System.Globalization
{
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public sealed class SortVersion : IEquatable<SortVersion>
{
private int m_NlsVersion; // Do not rename (binary serialization)
diff --git a/src/System.Private.CoreLib/shared/System/StringComparer.cs b/src/System.Private.CoreLib/shared/System/StringComparer.cs
index b327e770d..4b6193c18 100644
--- a/src/System.Private.CoreLib/shared/System/StringComparer.cs
+++ b/src/System.Private.CoreLib/shared/System/StringComparer.cs
@@ -10,6 +10,7 @@ using System.Diagnostics.Contracts;
namespace System
{
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public abstract class StringComparer : IComparer, IEqualityComparer, IComparer<string>, IEqualityComparer<string>
{
private static readonly CultureAwareComparer s_invariantCulture = new CultureAwareComparer(CultureInfo.InvariantCulture, false);
@@ -170,30 +171,33 @@ namespace System
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal sealed class CultureAwareComparer : StringComparer
{
- private readonly CompareInfo _compareInfo;
- private readonly CompareOptions _options;
+ private readonly CompareInfo _compareInfo; // Do not rename (binary serialization)
+ private readonly bool _ignoreCase; // Do not rename (binary serialization)
internal CultureAwareComparer(CultureInfo culture, bool ignoreCase)
{
_compareInfo = culture.CompareInfo;
- _options = ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
+ _ignoreCase = ignoreCase;
}
+ private CompareOptions Options => _ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
+
public override int Compare(string x, string y)
{
if (object.ReferenceEquals(x, y)) return 0;
if (x == null) return -1;
if (y == null) return 1;
- return _compareInfo.Compare(x, y, _options);
+ return _compareInfo.Compare(x, y, Options);
}
public override bool Equals(string x, string y)
{
if (object.ReferenceEquals(x, y)) return true;
if (x == null || y == null) return false;
- return _compareInfo.Compare(x, y, _options) == 0;
+ return _compareInfo.Compare(x, y, Options) == 0;
}
public override int GetHashCode(string obj)
@@ -202,7 +206,7 @@ namespace System
{
throw new ArgumentNullException(nameof(obj));
}
- return _compareInfo.GetHashCodeOfString(obj, _options);
+ return _compareInfo.GetHashCodeOfString(obj, Options);
}
// Equals method for the comparer itself.
@@ -211,18 +215,19 @@ namespace System
CultureAwareComparer comparer = obj as CultureAwareComparer;
return
comparer != null &&
- _options == comparer._options &&
+ _ignoreCase == comparer._ignoreCase &&
_compareInfo.Equals(comparer._compareInfo);
}
public override int GetHashCode()
{
int hashCode = _compareInfo.GetHashCode();
- return _options == CompareOptions.None ? hashCode : ~hashCode;
+ return _ignoreCase ? ~hashCode : hashCode;
}
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal sealed class OrdinalComparer : StringComparer
{
public override int Compare(string x, string y) => string.CompareOrdinal(x, y);
@@ -248,6 +253,7 @@ namespace System
}
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
internal sealed class OrdinalIgnoreCaseComparer : StringComparer
{
public override int Compare(string x, string y) => string.Compare(x, y, StringComparison.OrdinalIgnoreCase);
diff --git a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs
index 3a06114bf..1167016cc 100644
--- a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs
@@ -35,6 +35,7 @@ namespace System.Text
// Console.WriteLine(sb2);
//
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public sealed partial class StringBuilder : ISerializable
{
// A StringBuilder is internally represented as a linked list of blocks each of which holds
@@ -58,10 +59,11 @@ namespace System.Text
//
//
internal const int DefaultCapacity = 16;
- private const String CapacityField = "Capacity";
- private const String MaxCapacityField = "m_MaxCapacity";
- private const String StringValueField = "m_StringValue";
- private const String ThreadIDField = "m_currentThread";
+ private const String CapacityField = "Capacity"; // Do not rename (binary serialization)
+ private const String MaxCapacityField = "m_MaxCapacity"; // Do not rename (binary serialization)
+ private const String StringValueField = "m_StringValue"; // Do not rename (binary serialization)
+ private const String ThreadIDField = "m_currentThread"; // Do not rename (binary serialization)
+
// We want to keep chunk arrays out of large object heap (< 85K bytes ~ 40K chars) to be sure.
// Making the maximum chunk size big means less allocation code called, but also more waste
// in unused characters and slower inserts / replaces (since you do need to slide characters over
diff --git a/src/System.Private.CoreLib/shared/System/ValueTuple.cs b/src/System.Private.CoreLib/shared/System/ValueTuple.cs
index e0cd02e91..3464f2781 100644
--- a/src/System.Private.CoreLib/shared/System/ValueTuple.cs
+++ b/src/System.Private.CoreLib/shared/System/ValueTuple.cs
@@ -29,6 +29,7 @@ namespace System
/// - their members (such as Item1, Item2, etc) are fields rather than properties.
/// </summary>
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple
: IEquatable<ValueTuple>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple>, IValueTupleInternal, ITuple
{
@@ -298,6 +299,7 @@ namespace System
/// <summary>Represents a 1-tuple, or singleton, as a value type.</summary>
/// <typeparam name="T1">The type of the tuple's only component.</typeparam>
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1>
: IEquatable<ValueTuple<T1>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1>>, IValueTupleInternal, ITuple
{
@@ -464,6 +466,7 @@ namespace System
/// <typeparam name="T2">The type of the tuple's second component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2>
: IEquatable<ValueTuple<T1, T2>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2>>, IValueTupleInternal, ITuple
{
@@ -674,6 +677,7 @@ namespace System
/// <typeparam name="T3">The type of the tuple's third component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2, T3>
: IEquatable<ValueTuple<T1, T2, T3>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3>>, IValueTupleInternal, ITuple
{
@@ -882,6 +886,7 @@ namespace System
/// <typeparam name="T4">The type of the tuple's fourth component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2, T3, T4>
: IEquatable<ValueTuple<T1, T2, T3, T4>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4>>, IValueTupleInternal, ITuple
{
@@ -1109,6 +1114,7 @@ namespace System
/// <typeparam name="T5">The type of the tuple's fifth component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2, T3, T4, T5>
: IEquatable<ValueTuple<T1, T2, T3, T4, T5>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5>>, IValueTupleInternal, ITuple
{
@@ -1355,6 +1361,7 @@ namespace System
/// <typeparam name="T6">The type of the tuple's sixth component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2, T3, T4, T5, T6>
: IEquatable<ValueTuple<T1, T2, T3, T4, T5, T6>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5, T6>>, IValueTupleInternal, ITuple
{
@@ -1620,6 +1627,7 @@ namespace System
/// <typeparam name="T7">The type of the tuple's seventh component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2, T3, T4, T5, T6, T7>
: IEquatable<ValueTuple<T1, T2, T3, T4, T5, T6, T7>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5, T6, T7>>, IValueTupleInternal, ITuple
{
@@ -1904,6 +1912,7 @@ namespace System
/// <typeparam name="TRest">The type of the tuple's eighth component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>
: IEquatable<ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>>, IValueTupleInternal, ITuple
where TRest : struct
diff --git a/src/System.Private.CoreLib/shared/System/Version.cs b/src/System.Private.CoreLib/shared/System/Version.cs
index 54b2052dd..a2140ab13 100644
--- a/src/System.Private.CoreLib/shared/System/Version.cs
+++ b/src/System.Private.CoreLib/shared/System/Version.cs
@@ -16,14 +16,15 @@ namespace System
// specified component.
[Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public sealed class Version : ICloneable, IComparable
, IComparable<Version>, IEquatable<Version>
{
// AssemblyName depends on the order staying the same
- private readonly int _Major;
- private readonly int _Minor;
- private readonly int _Build = -1;
- private readonly int _Revision = -1;
+ private readonly int _Major; // Do not rename (binary serialization)
+ private readonly int _Minor; // Do not rename (binary serialization)
+ private readonly int _Build = -1; // Do not rename (binary serialization)
+ private readonly int _Revision = -1; // Do not rename (binary serialization)
public Version(int major, int minor, int build, int revision)
{
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/InteropCallbacks.cs b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/InteropCallbacks.cs
index 4dd2c4369..7424ebcc5 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/InteropCallbacks.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/InteropCallbacks.cs
@@ -12,5 +12,15 @@ namespace Internal.Runtime.Augments
public abstract class InteropCallbacks
{
public abstract bool TryGetMarshallerDataForDelegate(RuntimeTypeHandle delegateTypeHandle, out McgPInvokeDelegateData delegateData);
+
+ public abstract bool TryGetStructUnmarshalStub(RuntimeTypeHandle structureTypeHandle, out IntPtr unmarshalStub);
+
+ public abstract bool TryGetStructMarshalStub(RuntimeTypeHandle structureTypeHandle, out IntPtr marshalStub);
+
+ public abstract bool TryGetDestroyStructureStub(RuntimeTypeHandle structureTypeHandle, out IntPtr destroyStructureStub, out bool hasInvalidLayout);
+
+ public abstract bool TryGetStructFieldOffset(RuntimeTypeHandle structureTypeHandle, string fieldName, out bool structExists, out uint offset);
+
+ public abstract bool TryGetStructUnsafeStructSize(RuntimeTypeHandle structureTypeHandle, out int size);
}
}
diff --git a/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj
index f028cf293..1a1706b1e 100644
--- a/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj
+++ b/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
@@ -647,6 +647,9 @@
<Compile Include="System\Globalization\FormatProvider.FormatAndParse.Unix.cs" />
<Compile Include="System\Environment.Unix.cs" />
<Compile Include="System\Runtime\InteropServices\PInvokeMarshal.Unix.cs" />
+ <Compile Include="System\Threading\ClrThreadPool.cs" />
+ <Compile Include="System\Threading\ClrThreadPool.HillClimbing.cs" />
+ <Compile Include="System\Threading\ClrThreadPool.HillClimbing.Complex.cs" />
<Compile Include="System\Threading\EventWaitHandle.Unix.cs" />
<Compile Include="System\Threading\LowLevelLock.Unix.cs" />
<Compile Include="System\Threading\LowLevelMonitor.Unix.cs" />
@@ -851,4 +854,4 @@
</ItemGroup>
<Import Project="..\shared\System.Private.CoreLib.Shared.projitems" Label="Shared" />
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
+</Project> \ No newline at end of file
diff --git a/src/System.Private.CoreLib/src/System/Activator.cs b/src/System.Private.CoreLib/src/System/Activator.cs
index e77006e0a..8ecfa24b8 100644
--- a/src/System.Private.CoreLib/src/System/Activator.cs
+++ b/src/System.Private.CoreLib/src/System/Activator.cs
@@ -35,12 +35,15 @@ namespace System
EETypePtr eetype = EETypePtr.EETypePtrOf<T>();
- // ProjectN:936613 - Early exit for variable sized types (strings, arrays, etc.) as we cannot call
- // CreateInstanceIntrinsic on them since the intrinsic will attempt to allocate an instance of these types
- // and that is verboten (it results in silent heap corruption!).
- if (eetype.ComponentSize != 0)
+ if (!RuntimeHelpers.IsReference<T>())
+ {
+ // Early out for valuetypes since we don't support default constructors anyway.
+ // This lets codegens that expand IsReference<T> optimize away the rest of this code.
+ }
+ else if (eetype.ComponentSize != 0)
{
// ComponentSize > 0 indicates an array-like type (e.g. string, array, etc).
+ // Allocating this using the normal allocator would result in silent heap corruption.
missingDefaultConstructor = true;
}
else if (eetype.IsInterface)
@@ -54,8 +57,19 @@ namespace System
try
{
+#if PROJECTN
t = CreateInstanceIntrinsic<T>();
- System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
+ DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
+#else
+ t = (T)(RuntimeImports.RhNewObject(eetype));
+
+ // Run the default constructor. If the default constructor was missing, codegen
+ // will expand DefaultConstructorOf to ClassWithMissingConstructor::.ctor
+ // and we detect that later.
+ IntPtr defaultConstructor = DefaultConstructorOf<T>();
+ RawCalliHelper.Call(defaultConstructor, t);
+ DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
+#endif
}
catch (Exception e)
{
@@ -81,27 +95,14 @@ namespace System
}
[Intrinsic]
- [DebuggerGuidedStepThrough]
- private static T CreateInstanceIntrinsic<T>()
- {
- // Fallback implementation for codegens that don't support this intrinsic.
- // This uses the type loader and doesn't have the kind of guarantees about it always working
- // as the intrinsic expansion has. Also, it's slower.
-
- EETypePtr eetype = EETypePtr.EETypePtrOf<T>();
+ private extern static T CreateInstanceIntrinsic<T>();
- // The default(T) check can be evaluated statically and will result in the body of this method
- // becoming empty for valuetype Ts. We still need a dynamic IsNullable check to cover Nullables though.
- // This will obviously need work once we start supporting default valuetype constructors.
- if (default(T) == null && !eetype.IsNullable)
- {
- object o = null;
- TypeLoaderExports.ActivatorCreateInstanceAny(ref o, eetype.RawValue);
- System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
- return (T)o;
- }
-
- return default(T);
+ [Intrinsic]
+ private static IntPtr DefaultConstructorOf<T>()
+ {
+ // Codegens must expand this intrinsic.
+ // We could implement a fallback with the type loader if we wanted to, but it will be slow and unreliable.
+ throw new NotSupportedException();
}
[ThreadStatic]
diff --git a/src/System.Private.CoreLib/src/System/Buffer.cs b/src/System.Private.CoreLib/src/System/Buffer.cs
index 0bdad3203..a7f2860f4 100644
--- a/src/System.Private.CoreLib/src/System/Buffer.cs
+++ b/src/System.Private.CoreLib/src/System/Buffer.cs
@@ -21,15 +21,8 @@ using nuint = System.UInt32;
namespace System
{
- [EagerStaticClassConstruction]
public static class Buffer
{
- /// <summary>
- /// This field is used to quickly check whether an array that is given to the BlockCopy
- /// method is a byte array and the code can take optimized path.
- /// </summary>
- private static readonly EETypePtr s_byteArrayEEType = EETypePtr.EETypePtrOf<byte[]>();
-
public static unsafe void BlockCopy(Array src, int srcOffset,
Array dst, int dstOffset,
int count)
@@ -43,8 +36,8 @@ namespace System
throw new ArgumentNullException(nameof(dst));
// Use optimized path for byte arrays since this is the main scenario for Buffer::BlockCopy
- EETypePtr byteArrayEEType = s_byteArrayEEType;
- if (src.EETypePtr.FastEquals(byteArrayEEType))
+ // We only need an unreliable comparison since the slow path can handle the byte[] case too.
+ if (src.EETypePtr.FastEqualsUnreliable(EETypePtr.EETypePtrOf<byte[]>()))
{
uSrcLen = (nuint)src.Length;
}
@@ -58,7 +51,9 @@ namespace System
if (src != dst)
{
- if (dst.EETypePtr.FastEquals(byteArrayEEType))
+ // Use optimized path for byte arrays since this is the main scenario for Buffer::BlockCopy
+ // We only need an unreliable comparison since the slow path can handle the byte[] case too.
+ if (dst.EETypePtr.FastEqualsUnreliable(EETypePtr.EETypePtrOf<byte[]>()))
{
uDstLen = (nuint)dst.Length;
}
diff --git a/src/System.Private.CoreLib/src/System/EETypePtr.cs b/src/System.Private.CoreLib/src/System/EETypePtr.cs
index 39215d209..fa5abb6b0 100644
--- a/src/System.Private.CoreLib/src/System/EETypePtr.cs
+++ b/src/System.Private.CoreLib/src/System/EETypePtr.cs
@@ -90,6 +90,19 @@ namespace System
return RuntimeImports.AreTypesEquivalent(this, other);
}
+ //
+ // An even faster version of FastEquals that only checks if two EEType pointers are identical.
+ // Note: this method might return false for cases where FastEquals would return true.
+ // Only use if you know what you're doing.
+ //
+ internal bool FastEqualsUnreliable(EETypePtr other)
+ {
+ Debug.Assert(!this.IsNull);
+ Debug.Assert(!other.IsNull);
+
+ return this.RawValue == other.RawValue;
+ }
+
// Caution: You cannot safely compare RawValue's as RH does NOT unify EETypes. Use the == or Equals() methods exposed by EETypePtr itself.
internal IntPtr RawValue
{
diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs
index b77a41343..2c1c1dfda 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs
+++ b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs
@@ -219,6 +219,13 @@ namespace System.Runtime.CompilerServices
return !pEEType.IsValueType || pEEType.HasPointers;
}
+ [Intrinsic]
+ public static bool IsReference<T>()
+ {
+ var pEEType = EETypePtr.EETypePtrOf<T>();
+ return !pEEType.IsValueType;
+ }
+
// Constrained Execution Regions APIs are NOP's because we do not support CERs in .NET Core at all.
public static void ProbeForSufficientStack() { }
public static void PrepareConstrainedRegions() { }
diff --git a/src/System.Private.CoreLib/src/System/Threading/ClrThreadPool.HillClimbing.Complex.cs b/src/System.Private.CoreLib/src/System/Threading/ClrThreadPool.HillClimbing.Complex.cs
new file mode 100644
index 000000000..7be30ed65
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Threading/ClrThreadPool.HillClimbing.Complex.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace System.Threading
+{
+ internal static partial class ClrThreadPool
+ {
+
+ private partial class HillClimbing
+ {
+ private struct Complex
+ {
+ public Complex(double real, double imaginary)
+ {
+ Real = real;
+ Imaginary = imaginary;
+ }
+
+ public double Imaginary { get; }
+ public double Real { get; }
+
+ public static Complex operator*(double scalar, Complex complex) => new Complex(scalar * complex.Real, scalar * complex.Imaginary);
+
+ public static Complex operator*(Complex complex, double scalar) => scalar * complex;
+
+ public static Complex operator/(Complex complex, double scalar) => new Complex(complex.Real / scalar, complex.Imaginary / scalar);
+
+ public static Complex operator-(Complex lhs, Complex rhs) => new Complex(lhs.Real - rhs.Real, lhs.Imaginary - rhs.Imaginary);
+
+ public static Complex operator/(Complex lhs, Complex rhs)
+ {
+ double denom = rhs.Real * rhs.Real + rhs.Imaginary * rhs.Imaginary;
+ return new Complex((lhs.Real * rhs.Real + lhs.Imaginary * rhs.Imaginary) / denom, (-lhs.Real * rhs.Imaginary + lhs.Imaginary * rhs.Real) / denom);
+ }
+
+ public double Abs() => Math.Sqrt(Real * Real + Imaginary * Imaginary);
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Threading/ClrThreadPool.HillClimbing.cs b/src/System.Private.CoreLib/src/System/Threading/ClrThreadPool.HillClimbing.cs
new file mode 100644
index 000000000..909a2fd72
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Threading/ClrThreadPool.HillClimbing.cs
@@ -0,0 +1,388 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+
+namespace System.Threading
+{
+ internal static partial class ClrThreadPool
+ {
+ // The Hill Climbing algorithm is described at http://mattwarren.org/2017/04/13/The-CLR-Thread-Pool-Thread-Injection-Algorithm/
+ private partial class HillClimbing
+ {
+ // Config values pulled from CoreCLR
+ // TODO: Move to runtime configuration variables.
+ public static HillClimbing ThreadPoolHillClimber { get; } = new HillClimbing(4, 20, 100 / 100.0, 8, 15 / 100.0, 300 / 100.0, 4, 20, 10, 200, 1 / 100.0, 200 / 100.0, 15 / 100.0);
+
+ public enum StateOrTransition
+ {
+ Warmup,
+ Initializing,
+ RandomMove,
+ ClimbingMove,
+ ChangePoint,
+ Stabilizing,
+ Starvation,
+ ThreadTimedOut,
+ }
+
+ private readonly int _wavePeriod;
+ private readonly int _samplesToMeasure;
+ private readonly double _targetThroughputRatio;
+ private readonly double _targetSignalToNoiseRatio;
+ private readonly double _maxChangePerSecond;
+ private readonly double _maxChangePerSample;
+ private readonly int _maxThreadWaveMagnitude;
+ private readonly int _sampleIntervalLow;
+ private readonly double _threadMagnitudeMultiplier;
+ private readonly int _sampleIntervalHigh;
+ private readonly double _throughputErrorSmoothingFactor;
+ private readonly double _gainExponent;
+ private readonly double _maxSampleError;
+
+ private double _currentControlSetting;
+ private int _totalSamples;
+ private int _lastThreadCount;
+ private double _averageThroughputNoise;
+ private double _secondsElapsedSinceLastChange;
+ private double _completionsSinceLastChange;
+ private int _accumulatedCompletionCount;
+ private double _accumulatedSampleDurationSeconds;
+ private double[] _samples;
+ private double[] _threadCounts;
+ private int _currentSampleInterval;
+
+ private Random _randomIntervalGenerator = new Random();
+
+ public HillClimbing(int wavePeriod, int maxWaveMagnitude, double waveMagnitudeMultiplier, int waveHistorySize, double targetThroughputRatio,
+ double targetSignalToNoiseRatio, double maxChangePerSecond, double maxChangePerSample, int sampleIntervalLow, int sampleIntervalHigh,
+ double errorSmoothingFactor, double gainExponent, double maxSampleError)
+ {
+ _wavePeriod = wavePeriod;
+ _maxThreadWaveMagnitude = maxWaveMagnitude;
+ _threadMagnitudeMultiplier = waveMagnitudeMultiplier;
+ _samplesToMeasure = wavePeriod * waveHistorySize;
+ _targetThroughputRatio = targetThroughputRatio;
+ _targetSignalToNoiseRatio = targetSignalToNoiseRatio;
+ _maxChangePerSecond = maxChangePerSecond;
+ _maxChangePerSample = maxChangePerSample;
+ _sampleIntervalLow = sampleIntervalLow;
+ _sampleIntervalHigh = sampleIntervalHigh;
+ _throughputErrorSmoothingFactor = errorSmoothingFactor;
+ _gainExponent = gainExponent;
+ _maxSampleError = maxSampleError;
+
+ _samples = new double[_samplesToMeasure];
+ _threadCounts = new double[_samplesToMeasure];
+
+ _currentSampleInterval = _randomIntervalGenerator.Next(_sampleIntervalLow, _sampleIntervalHigh + 1);
+ }
+
+ public (int newThreadCount, int newSampleInterval) Update(int currentThreadCount, double sampleDurationSeconds, int numCompletions)
+ {
+
+ //
+ // If someone changed the thread count without telling us, update our records accordingly.
+ //
+ if (currentThreadCount != _lastThreadCount)
+ ForceChange(currentThreadCount, StateOrTransition.Initializing);
+
+ //
+ // Update the cumulative stats for this thread count
+ //
+ _secondsElapsedSinceLastChange += sampleDurationSeconds;
+ _completionsSinceLastChange += numCompletions;
+
+ //
+ // Add in any data we've already collected about this sample
+ //
+ sampleDurationSeconds += _accumulatedSampleDurationSeconds;
+ numCompletions += _accumulatedCompletionCount;
+
+ //
+ // We need to make sure we're collecting reasonably accurate data. Since we're just counting the end
+ // of each work item, we are goinng to be missing some data about what really happened during the
+ // sample interval. The count produced by each thread includes an initial work item that may have
+ // started well before the start of the interval, and each thread may have been running some new
+ // work item for some time before the end of the interval, which did not yet get counted. So
+ // our count is going to be off by +/- threadCount workitems.
+ //
+ // The exception is that the thread that reported to us last time definitely wasn't running any work
+ // at that time, and the thread that's reporting now definitely isn't running a work item now. So
+ // we really only need to consider threadCount-1 threads.
+ //
+ // Thus the percent error in our count is +/- (threadCount-1)/numCompletions.
+ //
+ // We cannot rely on the frequency-domain analysis we'll be doing later to filter out this error, because
+ // of the way it accumulates over time. If this sample is off by, say, 33% in the negative direction,
+ // then the next one likely will be too. The one after that will include the sum of the completions
+ // we missed in the previous samples, and so will be 33% positive. So every three samples we'll have
+ // two "low" samples and one "high" sample. This will appear as periodic variation right in the frequency
+ // range we're targeting, which will not be filtered by the frequency-domain translation.
+ //
+ if (_totalSamples > 0 && ((currentThreadCount - 1.0) / numCompletions) >= _maxSampleError)
+ {
+ // not accurate enough yet. Let's accumulate the data so far, and tell the ThreadPool
+ // to collect a little more.
+ _accumulatedSampleDurationSeconds = sampleDurationSeconds;
+ _accumulatedCompletionCount = numCompletions;
+ return (currentThreadCount, 10);
+ }
+
+ //
+ // We've got enouugh data for our sample; reset our accumulators for next time.
+ //
+ _accumulatedSampleDurationSeconds = 0;
+ _accumulatedCompletionCount = 0;
+
+ //
+ // Add the current thread count and throughput sample to our history
+ //
+ double throughput = numCompletions / sampleDurationSeconds;
+ // TODO: Event: Worker Thread Adjustment Sample
+
+ int sampleIndex = _totalSamples % _samplesToMeasure;
+ _samples[sampleIndex] = throughput;
+ _threadCounts[sampleIndex] = currentThreadCount;
+ _totalSamples++;
+
+ //
+ // Set up defaults for our metrics
+ //
+ Complex threadWaveComponent = default(Complex);
+ Complex throughputWaveComponent = default(Complex);
+ double throughputErrorEstimate = 0;
+ Complex ratio = default(Complex);
+ double confidence = 0;
+
+ StateOrTransition state = StateOrTransition.Warmup;
+
+ //
+ // How many samples will we use? It must be at least the three wave periods we're looking for, and it must also be a whole
+ // multiple of the primary wave's period; otherwise the frequency we're looking for will fall between two frequency bands
+ // in the Fourier analysis, and we won't be able to measure it accurately.
+ //
+ int sampleCount = Math.Min(_totalSamples - 1, _samplesToMeasure) / _wavePeriod * _wavePeriod;
+
+ if (sampleCount > _wavePeriod)
+ {
+ //
+ // Average the throughput and thread count samples, so we can scale the wave magnitudes later.
+ //
+ double sampleSum = 0;
+ double threadSum = 0;
+ for (int i = 0; i < sampleCount; i++)
+ {
+ sampleSum += _samples[(_totalSamples - sampleCount + i) % _samplesToMeasure];
+ threadSum += _threadCounts[(_totalSamples - sampleCount + i) % _samplesToMeasure];
+ }
+ double averageThroughput = sampleSum / sampleCount;
+ double averageThreadCount = threadSum / sampleCount;
+
+ if (averageThroughput > 0 && averageThreadCount > 0)
+ {
+ //
+ // Calculate the periods of the adjacent frequency bands we'll be using to measure noise levels.
+ // We want the two adjacent Fourier frequency bands.
+ //
+ double adjacentPeriod1 = sampleCount / (((double)sampleCount / _wavePeriod) + 1);
+ double adjacentPeriod2 = sampleCount / (((double)sampleCount / _wavePeriod) - 1);
+
+ //
+ // Get the the three different frequency components of the throughput (scaled by average
+ // throughput). Our "error" estimate (the amount of noise that might be present in the
+ // frequency band we're really interested in) is the average of the adjacent bands.
+ //
+ throughputWaveComponent = GetWaveComponent(_samples, sampleCount, _wavePeriod) / averageThroughput;
+ throughputErrorEstimate = (GetWaveComponent(_samples, sampleCount, adjacentPeriod1) / averageThroughput).Abs();
+ if (adjacentPeriod2 <= sampleCount)
+ {
+ throughputErrorEstimate = Math.Max(throughputErrorEstimate, (GetWaveComponent(_samples, sampleCount, adjacentPeriod2) / averageThroughput).Abs());
+ }
+
+ //
+ // Do the same for the thread counts, so we have something to compare to. We don't measure thread count
+ // noise, because there is none; these are exact measurements.
+ //
+ threadWaveComponent = GetWaveComponent(_threadCounts, sampleCount, _wavePeriod) / averageThreadCount;
+
+ //
+ // Update our moving average of the throughput noise. We'll use this later as feedback to
+ // determine the new size of the thread wave.
+ //
+ if (_averageThroughputNoise == 0)
+ _averageThroughputNoise = throughputErrorEstimate;
+ else
+ _averageThroughputNoise = (_throughputErrorSmoothingFactor * throughputErrorEstimate) + ((1.0 - _throughputErrorSmoothingFactor) * _averageThroughputNoise);
+
+ if (threadWaveComponent.Abs() > 0)
+ {
+ //
+ // Adjust the throughput wave so it's centered around the target wave, and then calculate the adjusted throughput/thread ratio.
+ //
+ ratio = (throughputWaveComponent - (_targetThroughputRatio * threadWaveComponent)) / threadWaveComponent;
+ state = StateOrTransition.ClimbingMove;
+ }
+ else
+ {
+ ratio = new Complex(0, 0);
+ state = StateOrTransition.Stabilizing;
+ }
+
+ //
+ // Calculate how confident we are in the ratio. More noise == less confident. This has
+ // the effect of slowing down movements that might be affected by random noise.
+ //
+ double noiseForConfidence = Math.Max(_averageThroughputNoise, throughputErrorEstimate);
+ if (noiseForConfidence > 0)
+ confidence = (threadWaveComponent.Abs() / noiseForConfidence) / _targetSignalToNoiseRatio;
+ else
+ confidence = 1.0; //there is no noise!
+
+ }
+ }
+
+ //
+ // We use just the real part of the complex ratio we just calculated. If the throughput signal
+ // is exactly in phase with the thread signal, this will be the same as taking the magnitude of
+ // the complex move and moving that far up. If they're 180 degrees out of phase, we'll move
+ // backward (because this indicates that our changes are having the opposite of the intended effect).
+ // If they're 90 degrees out of phase, we won't move at all, because we can't tell wether we're
+ // having a negative or positive effect on throughput.
+ //
+ double move = Math.Min(1.0, Math.Max(-1.0, ratio.Real));
+
+ //
+ // Apply our confidence multiplier.
+ //
+ move *= Math.Min(1.0, Math.Max(0.0, confidence));
+
+ //
+ // Now apply non-linear gain, such that values around zero are attenuated, while higher values
+ // are enhanced. This allows us to move quickly if we're far away from the target, but more slowly
+ // if we're getting close, giving us rapid ramp-up without wild oscillations around the target.
+ //
+ double gain = _maxChangePerSecond * sampleDurationSeconds;
+ move = Math.Pow(Math.Abs(move), _gainExponent) * (move >= 0.0 ? 1 : -1) * gain;
+ move = Math.Min(move, _maxChangePerSample);
+
+ //
+ // If the result was positive, and CPU is > 95%, refuse the move.
+ //
+ if (move > 0.0 && s_cpuUtilization > CpuUtilizationHigh)
+ move = 0.0;
+
+ //
+ // Apply the move to our control setting
+ //
+ _currentControlSetting += move;
+
+ //
+ // Calculate the new thread wave magnitude, which is based on the moving average we've been keeping of
+ // the throughput error. This average starts at zero, so we'll start with a nice safe little wave at first.
+ //
+ int newThreadWaveMagnitude = (int)(0.5 + (_currentControlSetting * _averageThroughputNoise * _targetSignalToNoiseRatio * _threadMagnitudeMultiplier * 2.0));
+ newThreadWaveMagnitude = Math.Min(newThreadWaveMagnitude, _maxThreadWaveMagnitude);
+ newThreadWaveMagnitude = Math.Max(newThreadWaveMagnitude, 1);
+
+ //
+ // Make sure our control setting is within the ThreadPool's limits
+ //
+ int maxThreads = s_maxThreads;
+ int minThreads = s_minThreads;
+
+ _currentControlSetting = Math.Min(maxThreads - newThreadWaveMagnitude, _currentControlSetting);
+ _currentControlSetting = Math.Max(minThreads, _currentControlSetting);
+
+ //
+ // Calculate the new thread count (control setting + square wave)
+ //
+ int newThreadCount = (int)(_currentControlSetting + newThreadWaveMagnitude * ((_totalSamples / (_wavePeriod / 2)) % 2));
+
+ //
+ // Make sure the new thread count doesn't exceed the ThreadPool's limits
+ //
+ newThreadCount = Math.Min(maxThreads, newThreadCount);
+ newThreadCount = Math.Max(minThreads, newThreadCount);
+
+ //
+ // Record these numbers for posterity
+ //
+
+ // TODO: Event: Worker Thread Adjustment stats
+
+
+ //
+ // If all of this caused an actual change in thread count, log that as well.
+ //
+ if (newThreadCount != currentThreadCount)
+ ChangeThreadCount(newThreadCount, state);
+
+ //
+ // Return the new thread count and sample interval. This is randomized to prevent correlations with other periodic
+ // changes in throughput. Among other things, this prevents us from getting confused by Hill Climbing instances
+ // running in other processes.
+ //
+ // If we're at minThreads, and we seem to be hurting performance by going higher, we can't go any lower to fix this. So
+ // we'll simply stay at minThreads much longer, and only occasionally try a higher value.
+ //
+ int newSampleInterval;
+ if (ratio.Real < 0.0 && newThreadCount == minThreads)
+ newSampleInterval = (int)(0.5 + _currentSampleInterval * (10.0 * Math.Max(-ratio.Real, 1.0)));
+ else
+ newSampleInterval = _currentSampleInterval;
+
+ return (newThreadCount, newSampleInterval);
+ }
+
+ private void ChangeThreadCount(int newThreadCount, StateOrTransition state)
+ {
+ _lastThreadCount = newThreadCount;
+ _currentSampleInterval = _randomIntervalGenerator.Next(_sampleIntervalLow, _sampleIntervalHigh + 1);
+ double throughput = _secondsElapsedSinceLastChange > 0 ? _completionsSinceLastChange / _secondsElapsedSinceLastChange : 0;
+ LogTransition(newThreadCount, throughput, state);
+ _secondsElapsedSinceLastChange = 0;
+ _completionsSinceLastChange = 0;
+ }
+
+ private void LogTransition(int newThreadCount, double throughput, StateOrTransition state)
+ {
+ // TODO: Log transitions
+ }
+
+ public void ForceChange(int newThreadCount, StateOrTransition state)
+ {
+ if(_lastThreadCount != newThreadCount)
+ {
+ _currentControlSetting += newThreadCount - _lastThreadCount;
+ ChangeThreadCount(newThreadCount, state);
+ }
+ }
+
+ private Complex GetWaveComponent(double[] samples, int numSamples, double period)
+ {
+ Debug.Assert(numSamples >= period); // can't measure a wave that doesn't fit
+ Debug.Assert(period >= 2); // can't measure above the Nyquist frequency
+ Debug.Assert(numSamples <= samples.Length); // can't measure more samples than we have
+
+ //
+ // Calculate the sinusoid with the given period.
+ // We're using the Goertzel algorithm for this. See http://en.wikipedia.org/wiki/Goertzel_algorithm.
+ //
+
+ double w = 2 * Math.PI / period;
+ double cos = Math.Cos(w);
+ double coeff = 2 * cos;
+ double q0 = 0, q1 = 0, q2 = 0;
+ for(int i = 0; i < numSamples; ++i)
+ {
+ q0 = coeff * q1 - q2 + samples[(_totalSamples - numSamples + i) % _samplesToMeasure];
+ q2 = q1;
+ q1 = q0;
+ }
+ return new Complex(q1 - q2 * cos, q2 * Math.Sin(w)) / numSamples;
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Threading/ClrThreadPool.cs b/src/System.Private.CoreLib/src/System/Threading/ClrThreadPool.cs
new file mode 100644
index 000000000..0e56931ae
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Threading/ClrThreadPool.cs
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Threading
+{
+ internal static partial class ClrThreadPool
+ {
+ private const int CpuUtilizationHigh = 95;
+ private const int CpuUtilizationLow = 80;
+ private static int s_cpuUtilization = 85; // TODO: Add calculation for CPU utilization
+
+ private static int s_minThreads; // TODO: Initialize
+ private static int s_maxThreads; // TODO: Initialize
+
+ // TODO: SetMinThreads and SetMaxThreads need to be synchronized with a lock
+ // TODO: Compare with CoreCLR implementation and ensure this has the same guarantees.
+ public static bool SetMinThreads(int threads)
+ {
+ if (threads < 0 || threads > s_maxThreads)
+ {
+ return false;
+ }
+ else
+ {
+ s_minThreads = threads;
+ return true;
+ }
+ }
+
+ public static int GetMinThreads() => s_minThreads;
+
+ public static bool SetMaxThreads(int threads)
+ {
+ if (threads < s_minThreads || threads == 0)
+ {
+ return false;
+ }
+ else
+ {
+ s_maxThreads = threads;
+ return true;
+ }
+ }
+
+ public static int GetMaxThreads() => s_maxThreads;
+ }
+}
diff --git a/src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/Callbacks.CoreRT.cs b/src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/Callbacks.CoreRT.cs
deleted file mode 100644
index 9e30dffc7..000000000
--- a/src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/Callbacks.CoreRT.cs
+++ /dev/null
@@ -1,91 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using Internal.Runtime.Augments;
-using Internal.NativeFormat;
-using Internal.Runtime.TypeLoader;
-using Internal.Reflection.Execution;
-using System.Runtime.InteropServices;
-
-namespace Internal.Runtime.CompilerHelpers
-{
- internal class Callbacks : InteropCallbacks
- {
- public override bool TryGetMarshallerDataForDelegate(RuntimeTypeHandle delegateTypeHandle, out McgPInvokeDelegateData data)
- {
- IntPtr openStub, closedStub, delegateCreationStub;
- if (!TryGetMarshallersForDelegate(delegateTypeHandle, out openStub, out closedStub, out delegateCreationStub))
- {
- data = default(McgPInvokeDelegateData);
- return false;
- }
-
- data = new global::System.Runtime.InteropServices.McgPInvokeDelegateData()
- {
- ReverseOpenStaticDelegateStub = openStub,
- ReverseStub = closedStub,
- ForwardDelegateCreationStub = delegateCreationStub
- };
- return true;
- }
-
- private static unsafe bool TryGetNativeReaderForBlob(NativeFormatModuleInfo module, ReflectionMapBlob blob, out NativeReader reader)
- {
- byte* pBlob;
- uint cbBlob;
-
- if (module.TryFindBlob((int)blob, out pBlob, out cbBlob))
- {
- reader = new NativeReader(pBlob, cbBlob);
- return true;
- }
-
- reader = default(NativeReader);
- return false;
- }
-
- private unsafe bool TryGetMarshallersForDelegate(RuntimeTypeHandle delegateTypeHandle, out IntPtr openStub, out IntPtr closedStub, out IntPtr delegateCreationStub)
- {
- int delegateHashcode = delegateTypeHandle.GetHashCode();
- openStub = IntPtr.Zero;
- closedStub = IntPtr.Zero;
- delegateCreationStub = IntPtr.Zero;
-
- foreach (NativeFormatModuleInfo module in ModuleList.EnumerateModules())
- {
- NativeReader delegateMapReader;
- if (TryGetNativeReaderForBlob(module, ReflectionMapBlob.DelegateMarshallingStubMap, out delegateMapReader))
- {
- NativeParser delegateMapParser = new NativeParser(delegateMapReader, 0);
- NativeHashtable delegateHashtable = new NativeHashtable(delegateMapParser);
-
- ExternalReferencesTable externalReferences = default(ExternalReferencesTable);
- externalReferences.InitializeCommonFixupsTable(module);
-
- var lookup = delegateHashtable.Lookup(delegateHashcode);
- NativeParser entryParser;
- while (!(entryParser = lookup.GetNext()).IsNull)
- {
- RuntimeTypeHandle foundDelegateType = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
- if (foundDelegateType.Equals(delegateTypeHandle))
- {
- byte* pOpen = (byte*)externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
- byte* pClose = (byte*)externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
- byte* pDelegateCreation = (byte*)externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
- openStub = (IntPtr)pOpen;
- closedStub = (IntPtr)pClose;
- delegateCreationStub = (IntPtr)pDelegateCreation;
- return true;
- }
- }
- }
- }
-
- return false;
- }
-
- }
-
-}
diff --git a/src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/LibraryInitializer.cs b/src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/LibraryInitializer.cs
index 0b85c75cf..95ea711f0 100644
--- a/src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/LibraryInitializer.cs
+++ b/src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/LibraryInitializer.cs
@@ -22,7 +22,7 @@ namespace Internal.Runtime.CompilerHelpers
__vtable_IUnknown.Initialize();
McgModuleManager.Initialize();
#endif
- RuntimeAugments.InitializeInteropLookups(new Callbacks());
+ RuntimeAugments.InitializeInteropLookups(RuntimeInteropData.Instance);
}
}
}
diff --git a/src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/RuntimeInteropData.CoreRT.cs b/src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/RuntimeInteropData.CoreRT.cs
new file mode 100644
index 000000000..4de8b4603
--- /dev/null
+++ b/src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/RuntimeInteropData.CoreRT.cs
@@ -0,0 +1,203 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Internal.Runtime.Augments;
+using Internal.NativeFormat;
+using Internal.Runtime.TypeLoader;
+using Internal.Reflection.Execution;
+using System.Runtime.InteropServices;
+
+namespace Internal.Runtime.CompilerHelpers
+{
+ internal partial class RuntimeInteropData
+ {
+ public override bool TryGetMarshallerDataForDelegate(RuntimeTypeHandle delegateTypeHandle, out McgPInvokeDelegateData data)
+ {
+ IntPtr openStub, closedStub, delegateCreationStub;
+ if (!TryGetMarshallersForDelegate(delegateTypeHandle, out openStub, out closedStub, out delegateCreationStub))
+ {
+ data = default(McgPInvokeDelegateData);
+ return false;
+ }
+
+ data = new global::System.Runtime.InteropServices.McgPInvokeDelegateData()
+ {
+ ReverseOpenStaticDelegateStub = openStub,
+ ReverseStub = closedStub,
+ ForwardDelegateCreationStub = delegateCreationStub
+ };
+ return true;
+ }
+ #region "Struct Data"
+ public override bool TryGetStructUnmarshalStub(RuntimeTypeHandle structureTypeHandle, out IntPtr unmarshalStub)
+ {
+ IntPtr marshalStub;
+ IntPtr destroyStub;
+ bool hasInvalidLayout;
+ int size;
+ return TryGetMarshallersForStruct(structureTypeHandle, out marshalStub, out unmarshalStub, out destroyStub, out hasInvalidLayout, out size);
+ }
+
+ public override bool TryGetStructMarshalStub(RuntimeTypeHandle structureTypeHandle, out IntPtr marshalStub)
+ {
+ IntPtr unmarshalStub;
+ IntPtr destroyStub;
+ bool hasInvalidLayout;
+ int size;
+ return TryGetMarshallersForStruct(structureTypeHandle, out marshalStub, out unmarshalStub, out destroyStub, out hasInvalidLayout, out size);
+ }
+
+ public override bool TryGetDestroyStructureStub(RuntimeTypeHandle structureTypeHandle, out IntPtr destroyStub, out bool hasInvalidLayout)
+ {
+ IntPtr marshalStub;
+ IntPtr unmarshalStub;
+ int size;
+ return TryGetMarshallersForStruct(structureTypeHandle, out marshalStub, out unmarshalStub, out destroyStub, out hasInvalidLayout, out size);
+ }
+
+ public override bool TryGetStructUnsafeStructSize(RuntimeTypeHandle structureTypeHandle, out int size)
+ {
+ IntPtr marshalStub;
+ IntPtr unmarshalStub;
+ IntPtr destroyStub;
+ bool hasInvalidLayout;
+ return TryGetMarshallersForStruct(structureTypeHandle, out marshalStub, out unmarshalStub, out destroyStub, out hasInvalidLayout, out size);
+ }
+
+ public override bool TryGetStructFieldOffset(RuntimeTypeHandle structureTypeHandle, string fieldName, out bool structExists, out uint offset)
+ {
+ ExternalReferencesTable externalReferences;
+ NativeParser entryParser;
+ structExists = false;
+ if (TryGetStructData(structureTypeHandle, out externalReferences, out entryParser))
+ {
+ structExists = true;
+ // skip the first 4 IntPtrs(3 stubs and size)
+ entryParser.SkipInteger();
+ entryParser.SkipInteger();
+ entryParser.SkipInteger();
+ entryParser.SkipInteger();
+
+ uint mask = entryParser.GetUnsigned();
+ uint fieldCount = mask >> 1;
+ for (uint index = 0; index < fieldCount; index++)
+ {
+ string name = entryParser.GetString();
+ offset = entryParser.GetUnsigned();
+ if (name == fieldName)
+ {
+ return true;
+ }
+ }
+ }
+ offset = 0;
+ return false;
+ }
+ #endregion
+
+ private static unsafe bool TryGetNativeReaderForBlob(NativeFormatModuleInfo module, ReflectionMapBlob blob, out NativeReader reader)
+ {
+ byte* pBlob;
+ uint cbBlob;
+
+ if (module.TryFindBlob((int)blob, out pBlob, out cbBlob))
+ {
+ reader = new NativeReader(pBlob, cbBlob);
+ return true;
+ }
+
+ reader = default(NativeReader);
+ return false;
+ }
+
+ private unsafe bool TryGetMarshallersForDelegate(RuntimeTypeHandle delegateTypeHandle, out IntPtr openStub, out IntPtr closedStub, out IntPtr delegateCreationStub)
+ {
+ int delegateHashcode = delegateTypeHandle.GetHashCode();
+ openStub = IntPtr.Zero;
+ closedStub = IntPtr.Zero;
+ delegateCreationStub = IntPtr.Zero;
+
+ foreach (NativeFormatModuleInfo module in ModuleList.EnumerateModules())
+ {
+ NativeReader delegateMapReader;
+ if (TryGetNativeReaderForBlob(module, ReflectionMapBlob.DelegateMarshallingStubMap, out delegateMapReader))
+ {
+ NativeParser delegateMapParser = new NativeParser(delegateMapReader, 0);
+ NativeHashtable delegateHashtable = new NativeHashtable(delegateMapParser);
+
+ ExternalReferencesTable externalReferences = default(ExternalReferencesTable);
+ externalReferences.InitializeCommonFixupsTable(module);
+
+ var lookup = delegateHashtable.Lookup(delegateHashcode);
+ NativeParser entryParser;
+ while (!(entryParser = lookup.GetNext()).IsNull)
+ {
+ RuntimeTypeHandle foundDelegateType = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
+ if (foundDelegateType.Equals(delegateTypeHandle))
+ {
+ openStub = externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
+ closedStub = externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
+ delegateCreationStub = externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private unsafe bool TryGetStructData(RuntimeTypeHandle structTypeHandle, out ExternalReferencesTable externalReferences, out NativeParser entryParser)
+ {
+ int structHashcode = structTypeHandle.GetHashCode();
+ externalReferences = default(ExternalReferencesTable);
+ entryParser = default(NativeParser);
+ foreach (NativeFormatModuleInfo module in ModuleList.EnumerateModules())
+ {
+ NativeReader structMapReader;
+ if (TryGetNativeReaderForBlob(module, ReflectionMapBlob.StructMarshallingStubMap, out structMapReader))
+ {
+ NativeParser structMapParser = new NativeParser(structMapReader, 0);
+ NativeHashtable structHashtable = new NativeHashtable(structMapParser);
+
+ externalReferences.InitializeCommonFixupsTable(module);
+
+ var lookup = structHashtable.Lookup(structHashcode);
+ while (!(entryParser = lookup.GetNext()).IsNull)
+ {
+ RuntimeTypeHandle foundStructType = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
+ if (foundStructType.Equals(structTypeHandle))
+ {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private unsafe bool TryGetMarshallersForStruct(RuntimeTypeHandle structTypeHandle, out IntPtr marshalStub, out IntPtr unmarshalStub, out IntPtr destroyStub, out bool hasInvalidLayout, out int size)
+ {
+ marshalStub = IntPtr.Zero;
+ unmarshalStub = IntPtr.Zero;
+ destroyStub = IntPtr.Zero;
+ hasInvalidLayout = true;
+ size = 0;
+
+ ExternalReferencesTable externalReferences;
+ NativeParser entryParser;
+ if (TryGetStructData(structTypeHandle, out externalReferences, out entryParser))
+ {
+ marshalStub = externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
+ unmarshalStub = externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
+ destroyStub = externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
+ size = (int)entryParser.GetUnsigned();
+ uint mask = entryParser.GetUnsigned();
+ hasInvalidLayout = (mask & 0x1) == 1;
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/RuntimeInteropData.ProjectN.cs b/src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/RuntimeInteropData.ProjectN.cs
new file mode 100644
index 000000000..84678d1b9
--- /dev/null
+++ b/src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/RuntimeInteropData.ProjectN.cs
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System;
+using Internal.Runtime.Augments;
+using Internal.NativeFormat;
+using Internal.Runtime.TypeLoader;
+using Internal.Reflection.Execution;
+using System.Runtime.InteropServices;
+
+namespace Internal.Runtime.CompilerHelpers
+{
+ internal partial class RuntimeInteropData : InteropCallbacks
+ {
+ public override bool TryGetMarshallerDataForDelegate(RuntimeTypeHandle delegateTypeHandle, out McgPInvokeDelegateData data)
+ {
+ return McgModuleManager.GetPInvokeDelegateData(delegateTypeHandle, out data);
+ }
+
+ #region "Struct Data"
+ public override bool TryGetStructUnmarshalStub(RuntimeTypeHandle structureTypeHandle, out IntPtr unmarshalStub)
+ {
+ return McgModuleManager.TryGetStructUnmarshalStub(structureTypeHandle, out unmarshalStub);
+ }
+
+ public override bool TryGetStructMarshalStub(RuntimeTypeHandle structureTypeHandle, out IntPtr marshalStub)
+ {
+ return McgModuleManager.TryGetStructMarshalStub(structureTypeHandle, out marshalStub);
+ }
+
+ public override bool TryGetDestroyStructureStub(RuntimeTypeHandle structureTypeHandle, out IntPtr destroyStructureStub, out bool hasInvalidLayout)
+ {
+ return McgModuleManager.TryGetDestroyStructureStub(structureTypeHandle, out destroyStructureStub, out hasInvalidLayout);
+ }
+
+ public override bool TryGetStructFieldOffset(RuntimeTypeHandle structureTypeHandle, string fieldName, out bool structExists, out uint offset)
+ {
+ return McgModuleManager.TryGetStructFieldOffset(structureTypeHandle, fieldName, out structExists, out offset);
+ }
+
+ public override bool TryGetStructUnsafeStructSize(RuntimeTypeHandle structureTypeHandle, out int size)
+ {
+ RuntimeTypeHandle unsafeStructType;
+ size = 0;
+ if (McgModuleManager.TryGetStructUnsafeStructType(structureTypeHandle, out unsafeStructType))
+ {
+ size = unsafeStructType.GetValueTypeSize();
+ return true;
+ }
+ return false;
+ }
+ #endregion
+ }
+}
diff --git a/src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/Callbacks.ProjectN.cs b/src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/RuntimeInteropData.cs
index 9705cba33..4daf4ad66 100644
--- a/src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/Callbacks.ProjectN.cs
+++ b/src/System.Private.Interop/src/Internal/Runtime/CompilerHelpers/RuntimeInteropData.cs
@@ -12,11 +12,19 @@ using System.Runtime.InteropServices;
namespace Internal.Runtime.CompilerHelpers
{
- internal class Callbacks : InteropCallbacks
+ internal partial class RuntimeInteropData : InteropCallbacks
{
- public override bool TryGetMarshallerDataForDelegate(RuntimeTypeHandle delegateTypeHandle, out McgPInvokeDelegateData data)
+ private static RuntimeInteropData s_interopData;
+ public static RuntimeInteropData Instance
{
- return McgModuleManager.GetPInvokeDelegateData(delegateTypeHandle, out data);
+ get
+ {
+ if (s_interopData == null)
+ {
+ s_interopData = new RuntimeInteropData();
+ }
+ return s_interopData;
+ }
}
}
}
diff --git a/src/System.Private.Interop/src/System.Private.Interop.csproj b/src/System.Private.Interop/src/System.Private.Interop.csproj
index aa08ccddc..ec92627fa 100644
--- a/src/System.Private.Interop/src/System.Private.Interop.csproj
+++ b/src/System.Private.Interop/src/System.Private.Interop.csproj
@@ -139,8 +139,9 @@
<Compile Include="System\Runtime\InteropServices\WindowsRuntime\EventRegistrationToken.cs" />
<Compile Include="Internal\Runtime\CompilerHelpers\LibraryInitializer.cs" />
<Compile Include="Interop\Interop.Memory.cs" />
- <Compile Condition="'$(IsProjectNLibrary)' == 'true'" Include="Internal\Runtime\CompilerHelpers\Callbacks.ProjectN.cs"/>
- <Compile Condition="'$(IsProjectNLibrary)' != 'true'" Include="Internal\Runtime\CompilerHelpers\Callbacks.CoreRT.cs"/>
+ <Compile Include="Internal\Runtime\CompilerHelpers\RuntimeInteropData.cs"/>
+ <Compile Condition="'$(IsProjectNLibrary)' == 'true'" Include="Internal\Runtime\CompilerHelpers\RuntimeInteropData.ProjectN.cs"/>
+ <Compile Condition="'$(IsProjectNLibrary)' != 'true'" Include="Internal\Runtime\CompilerHelpers\RuntimeInteropData.CoreRT.cs"/>
</ItemGroup>
<ItemGroup Condition="'$(IsProjectNLibrary)' != 'true'">
<Compile Include="..\..\Common\src\Internal\Runtime\MetadataBlob.cs">
diff --git a/src/System.Private.Interop/src/System/Runtime/InteropServices/Marshal.cs b/src/System.Private.Interop/src/System/Runtime/InteropServices/Marshal.cs
index 6f1489bac..71fbdead9 100644
--- a/src/System.Private.Interop/src/System/Runtime/InteropServices/Marshal.cs
+++ b/src/System.Private.Interop/src/System/Runtime/InteropServices/Marshal.cs
@@ -20,6 +20,7 @@ using System.Security;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices.ComTypes;
+using Internal.Runtime.CompilerHelpers;
namespace System.Runtime.InteropServices
{
@@ -177,10 +178,10 @@ namespace System.Runtime.InteropServices
{
RuntimeTypeHandle typeHandle = t.TypeHandle;
- RuntimeTypeHandle unsafeStructType;
- if (McgModuleManager.TryGetStructUnsafeStructType(typeHandle, out unsafeStructType))
+ int size;
+ if (RuntimeInteropData.Instance.TryGetStructUnsafeStructSize(typeHandle, out size))
{
- return unsafeStructType.GetValueTypeSize();
+ return size;
}
if (!typeHandle.IsBlittable() && !typeHandle.IsValueType())
@@ -216,7 +217,7 @@ namespace System.Runtime.InteropServices
{
bool structExists;
uint offset;
- if (McgModuleManager.TryGetStructFieldOffset(t.TypeHandle, fieldName, out structExists, out offset))
+ if (RuntimeInteropData.Instance.TryGetStructFieldOffset(t.TypeHandle, fieldName, out structExists, out offset))
{
return new IntPtr(offset);
}
@@ -1096,7 +1097,7 @@ namespace System.Runtime.InteropServices
}
IntPtr unmarshalStub;
- if (McgModuleManager.TryGetStructUnmarshalStub(structureTypeHandle, out unmarshalStub))
+ if (RuntimeInteropData.Instance.TryGetStructUnmarshalStub(structureTypeHandle, out unmarshalStub))
{
InteropExtensions.PinObjectAndCall(structure,
unboxedStructPtr =>
@@ -1191,7 +1192,7 @@ namespace System.Runtime.InteropServices
bool isBlittable = false; // whether Mcg treat this struct as blittable struct
IntPtr marshalStub;
- if (McgModuleManager.TryGetStructMarshalStub(structureTypeHandle, out marshalStub))
+ if (RuntimeInteropData.Instance.TryGetStructMarshalStub(structureTypeHandle, out marshalStub))
{
if (marshalStub != IntPtr.Zero)
{
@@ -1279,7 +1280,7 @@ namespace System.Runtime.InteropServices
IntPtr destroyStructureStub;
bool hasInvalidLayout;
- if (McgModuleManager.TryGetDestroyStructureStub(structureTypeHandle, out destroyStructureStub, out hasInvalidLayout))
+ if (RuntimeInteropData.Instance.TryGetDestroyStructureStub(structureTypeHandle, out destroyStructureStub, out hasInvalidLayout))
{
if (hasInvalidLayout)
throw new ArgumentException(SR.Argument_MustHaveLayoutOrBeBlittable, structureTypeHandle.GetDisplayName());
diff --git a/src/packaging/project.json b/src/packaging/objectwriter/project.json
index b6098fb4b..beda765c3 100644
--- a/src/packaging/project.json
+++ b/src/packaging/objectwriter/project.json
@@ -1,6 +1,5 @@
{
"dependencies": {
- "Microsoft.NETCore.Jit": "2.1.0-preview1-25324-01",
"Microsoft.DotNet.ObjectWriter": "1.0.18-prerelease-00002"
},
"frameworks": {
diff --git a/src/packaging/packages.targets b/src/packaging/packages.targets
index 5ed71cd97..3695f21a9 100644
--- a/src/packaging/packages.targets
+++ b/src/packaging/packages.targets
@@ -26,8 +26,10 @@
<CoreFxNuPkgRid Condition="'$(OSGroup)'=='OSX'">osx-x64</CoreFxNuPkgRid>
<CoreFxNuPkgRid Condition="'$(CoreFxNuPkgRid)'==''">$(NuPkgRid)</CoreFxNuPkgRid>
- <JitPackageVersion>2.1.0-preview1-25324-01</JitPackageVersion>
- <JitNuPkgRid Condition="'$(OSGroup)'=='OSX'">osx.10.12-x64</JitNuPkgRid>
+ <JitPackageVersion>2.1.0-preview1-25406-04</JitPackageVersion>
+ <JitNuPkgRid Condition="'$(OSGroup)'=='Windows_NT'">win-x64</JitNuPkgRid>
+ <JitNuPkgRid Condition="'$(OSGroup)'=='OSX'">osx-x64</JitNuPkgRid>
+ <JitNuPkgRid Condition="'$(OSGroup)'=='Linux'">linux-x64</JitNuPkgRid>
<JitNuPkgRid Condition="'$(JitNuPkgRid)'==''">$(NuPkgRid)</JitNuPkgRid>
<MicrosoftNetCoreNativePackageVersion>2.0.0-beta-25021-03</MicrosoftNetCoreNativePackageVersion>
@@ -144,6 +146,7 @@
<ILCompilerAnyFrameworkFiles Include="System.IO.FileSystem.Primitives" />
<ILCompilerAnyFrameworkFiles Include="System.Linq" />
<ILCompilerAnyFrameworkFiles Include="System.Net.Primitives" />
+ <ILCompilerAnyFrameworkFiles Include="System.Numerics.Vectors" />
<ILCompilerAnyFrameworkFiles Include="System.ObjectModel" />
<ILCompilerAnyFrameworkFiles Include="System.Private.Uri" />
<ILCompilerAnyFrameworkFiles Include="System.Reflection" />
diff --git a/src/packaging/ryujit/project.json b/src/packaging/ryujit/project.json
new file mode 100644
index 000000000..fc003705f
--- /dev/null
+++ b/src/packaging/ryujit/project.json
@@ -0,0 +1,13 @@
+{
+ "dependencies": {
+ "Microsoft.NETCore.Jit": "2.1.0-preview1-25406-04"
+ },
+ "frameworks": {
+ "netcoreapp2.0": { }
+ },
+ "runtimes": {
+ "win-x64": { },
+ "osx-x64": { },
+ "linux-x64": { }
+ }
+}
diff --git a/tests/CoreCLR.issues.targets b/tests/CoreCLR.issues.targets
index dbfc551f5..3cd0938fc 100644
--- a/tests/CoreCLR.issues.targets
+++ b/tests/CoreCLR.issues.targets
@@ -10,6 +10,7 @@
<ExcludeList Include="$(XunitTestBinBase)\JIT\Methodical\NaN\intrinsic_cs_do\intrinsic_cs_do.*" />
<ExcludeList Include="$(XunitTestBinBase)\JIT\Directed\intrinsic\pow\pow1\pow1.*" />
<ExcludeList Include="$(XunitTestBinBase)\JIT\Methodical\NaN\intrinsic_cs_r\intrinsic_cs_r.*" />
+ <ExcludeList Include="$(XunitTestBinBase)\GC\Scenarios\Samples\gc\gc.*" />
<!-- Infinite generic expansion -->
<!-- https://github.com/dotnet/corert/issues/363 -->
@@ -36,155 +37,10 @@
<ExcludeList Include="$(XunitTestBinBase)\JIT\Methodical\VT\callconv\_il_dbgvtret\_il_dbgvtret.*" />
<ExcludeList Include="$(XunitTestBinBase)\JIT\Methodical\VT\callconv\_il_relvtret\_il_relvtret.*" />
- <!-- CreateInstance<T> -->
- <!-- https://github.com/dotnet/corert/issues/368 -->
- <ExcludeList Include="$(XunitTestBinBase)\JIT\Directed\CheckedCtor\Generic_Test_CSharp_Base_6\Generic_Test_CSharp_Base_6.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\Directed\CheckedCtor\Generic_Test_CSharp_Peer_6\Generic_Test_CSharp_Peer_6.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\Generics\ConstrainedCall\class1_cs_d\class1_cs_d.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\Generics\ConstrainedCall\class1_cs_do\class1_cs_do.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\Generics\ConstrainedCall\class1_cs_r\class1_cs_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\Generics\ConstrainedCall\class1_cs_ro\class1_cs_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\Generics\ConstrainedCall\class2_cs_d\class2_cs_d.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\Generics\ConstrainedCall\class2_cs_do\class2_cs_do.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\Generics\ConstrainedCall\class2_cs_r\class2_cs_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\Generics\ConstrainedCall\class2_cs_ro\class2_cs_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\Generics\ConstrainedCall\vt4_cs_d\vt4_cs_d.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\Generics\ConstrainedCall\vt4_cs_do\vt4_cs_do.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\Generics\ConstrainedCall\vt4_cs_r\vt4_cs_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\Generics\ConstrainedCall\vt4_cs_ro\vt4_cs_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\Loader\classloader\generics\regressions\341477\Test\Test.*" />
- <ExcludeList Include="$(XunitTestBinBase)\Loader\classloader\regressions\dev10_568786\4_Misc\SealedTypes\SealedTypes.*" />
-
<!-- System.Reflection.Emit.Lightweight -->
<!-- https://github.com/dotnet/corert/issues/370 -->
<ExcludeList Include="$(XunitTestBinBase)\JIT\Methodical\dynamic_methods\bug_445388\bug_445388.*" />
- <!-- SIMD -->
- <!-- https://github.com/dotnet/corert/issues/370 -->
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\AbsGeneric\AbsGeneric.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\AbsSqrt\AbsSqrt.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\AddingSequence\AddingSequence.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\BitwiseOperations\BitwiseOperations.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\BoxUnbox\BoxUnbox.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\BugWithAVX\BugWithAVX.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\CircleInConvex\CircleInConvex.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\CreateGeneric\CreateGeneric.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\CtorFromArray\CtorFromArray.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Ctors\Ctors.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\DivSignedUnsignedTest\DivSignedUnsignedTest.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Dup\Dup.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Haar-likeFeaturesGeneric\Haar-likeFeaturesGeneric.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Ldfld\Ldfld.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\LdfldGeneric\LdfldGeneric.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Ldind\Ldind.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\MinMax\MinMax.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Mul\Mul.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\SqrtGeneric\SqrtGeneric.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\StoreElement\StoreElement.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Sums\Sums.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Vector3\Vector3.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Vector4\Vector4.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\AbsGeneric_r\AbsGeneric_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\AbsGeneric_ro\AbsGeneric_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\AbsSqrt_r\AbsSqrt_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\AbsSqrt_ro\AbsSqrt_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\AddingSequence_r\AddingSequence_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\AddingSequence_ro\AddingSequence_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\BitwiseOperations_r\BitwiseOperations_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\BitwiseOperations_ro\BitwiseOperations_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\BoxUnbox_r\BoxUnbox_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\BoxUnbox_ro\BoxUnbox_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\BugWithAVX_r\BugWithAVX_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\BugWithAVX_ro\BugWithAVX_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\CircleInConvex_r\CircleInConvex_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\CircleInConvex_ro\CircleInConvex_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\CreateGeneric_r\CreateGeneric_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\CreateGeneric_ro\CreateGeneric_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\CtorFromArray_r\CtorFromArray_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\CtorFromArray_ro\CtorFromArray_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Ctors_r\Ctors_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Ctors_ro\Ctors_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\DivSignedUnsignedTest_r\DivSignedUnsignedTest_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\DivSignedUnsignedTest_ro\DivSignedUnsignedTest_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Dup_r\Dup_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Dup_ro\Dup_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Haar-likeFeaturesGeneric_r\Haar-likeFeaturesGeneric_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Haar-likeFeaturesGeneric_ro\Haar-likeFeaturesGeneric_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\LdfldGeneric_r\LdfldGeneric_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\LdfldGeneric_ro\LdfldGeneric_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Ldfld_r\Ldfld_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Ldfld_ro\Ldfld_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Ldind_r\Ldind_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Ldind_ro\Ldind_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\MinMax_r\MinMax_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\MinMax_ro\MinMax_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Mul_r\Mul_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Mul_ro\Mul_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\SqrtGeneric_r\SqrtGeneric_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\SqrtGeneric_ro\SqrtGeneric_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\StoreElement_r\StoreElement_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\StoreElement_ro\StoreElement_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Sums_r\Sums_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Sums_ro\Sums_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Vector3_r\Vector3_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Vector3_ro\Vector3_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Vector4_r\Vector4_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Vector4_ro\Vector4_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorAbs_r\VectorAbs_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorAbs_ro\VectorAbs_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorAdd_r\VectorAdd_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorAdd_ro\VectorAdd_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorArgs_r\VectorArgs_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorArgs_ro\VectorArgs_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorArrayInit_r\VectorArrayInit_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorArrayInit_ro\VectorArrayInit_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorArray_r\VectorArray_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorArray_ro\VectorArray_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorCopyToArray_r\VectorCopyToArray_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorCopyToArray_ro\VectorCopyToArray_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorDiv_r\VectorDiv_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorDiv_ro\VectorDiv_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorDot_r\VectorDot_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorDot_ro\VectorDot_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorExp_r\VectorExp_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorExp_ro\VectorExp_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorGet_r\VectorGet_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorGet_ro\VectorGet_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorHWAccel2_r\VectorHWAccel2_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorHWAccel2_ro\VectorHWAccel2_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorHWAccel_r\VectorHWAccel_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorHWAccel_ro\VectorHWAccel_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorInitN_r\VectorInitN_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorInitN_ro\VectorInitN_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorInit_r\VectorInit_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorInit_ro\VectorInit_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorIntEquals_r\VectorIntEquals_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorIntEquals_ro\VectorIntEquals_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorMatrix_r\VectorMatrix_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorMatrix_ro\VectorMatrix_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorMax_r\VectorMax_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorMax_ro\VectorMax_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorMin_r\VectorMin_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorMin_ro\VectorMin_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorMul_r\VectorMul_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorMul_ro\VectorMul_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorRelOp_r\VectorRelOp_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorRelOp_ro\VectorRelOp_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorReturn_r\VectorReturn_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorReturn_ro\VectorReturn_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorSet_r\VectorSet_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorSet_ro\VectorSet_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorSqrt_r\VectorSqrt_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorSqrt_ro\VectorSqrt_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorSub_r\VectorSub_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorSub_ro\VectorSub_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorUnused_r\VectorUnused_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\VectorUnused_ro\VectorUnused_ro.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\Regression\JitBlue\GitHub_6318\GitHub_6318\GitHub_6318.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\Regression\JitBlue\GitHub_7906\GitHub_7906\GitHub_7906.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Vector3Interop_r\Vector3Interop_r.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Vector3Interop_ro\Vector3Interop_ro.*" />
-
<!-- Test has expectations about CoreRun and running on CoreCLR -->
<ExcludeList Include="$(XunitTestBinBase)\Loader\NativeLibs\FromNativePaths\FromNativePaths.*" />
@@ -298,10 +154,6 @@
<!-- Reflection enabling a virtual method methodimpl'd by other virtual method -->
<ExcludeList Include="$(XunitTestBinBase)\Loader\classloader\methodoverriding\regressions\576621\VSW576621\VSW576621.*" />
- <!-- DynamicInvoke stub for a method with 8192 parameters -->
- <!-- https://github.com/dotnet/corert/issues/2349 -->
- <ExcludeList Include="$(XunitTestBinBase)\JIT\Regression\CLR-x86-JIT\V1.2-Beta1\b191926\b191926\b191926.*" />
-
<!-- Bogus MethodImpls -->
<!-- https://github.com/dotnet/corert/issues/2350 -->
<ExcludeList Include="$(XunitTestBinBase)\Loader\classloader\MethodImpl\self_override3\self_override3.*" />
@@ -439,6 +291,8 @@
<ExcludeList Include="$(XunitTestBinBase)\GC\Scenarios\Dynamo\dynamo\dynamo.*" />
<ExcludeList Include="$(XunitTestBinBase)\JIT\Regression\CLR-x86-JIT\V1-M09\b16294\b16294\b16294.*" />
<ExcludeList Include="$(XunitTestBinBase)\Regressions\common\AboveStackLimit\AboveStackLimit.*" />
+ <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Vector3Interop_r\Vector3Interop_r.*" />
+ <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\Vector3Interop_ro\Vector3Interop_ro.*" />
<!-- System.Diagnostics.Process -->
<ExcludeList Include="$(XunitTestBinBase)\GC\API\GC\Collect_Default_1\Collect_Default_1.*" />
@@ -568,6 +422,7 @@
<ExcludeList Include="$(XunitTestBinBase)\Loader\classloader\TSAmbiguities\CollapsedMethods\InterfaceImplementation\HelloWorld\HelloWorld.*" />
<ExcludeList Include="$(XunitTestBinBase)\Loader\classloader\TSAmbiguities\CollapsedMethods\Override\HelloWorld\HelloWorld.*" />
<ExcludeList Include="$(XunitTestBinBase)\Loader\classloader\regressions\dev10_568786\4_Misc\Variance2\Variance2.*" />
+ <ExcludeList Include="$(XunitTestBinBase)\Loader\classloader\regressions\dev10_568786\4_Misc\SealedTypes\SealedTypes.*" />
<!-- Marshal.GetExceptionForHR not setting HResult -->
<!-- https://github.com/dotnet/corert/issues/2256 -->
@@ -599,10 +454,6 @@
<!-- https://github.com/dotnet/corert/issues/2272 -->
<ExcludeList Include="$(XunitTestBinBase)\JIT\Directed\coverage\oldtests\callipinvoke\callipinvoke.*" />
- <!-- Newarr void -->
- <!-- https://github.com/dotnet/corert/issues/2280 -->
- <ExcludeList Include="$(XunitTestBinBase)\JIT\Regression\CLR-x86-JIT\V2.0-Beta2\b353858\b353858\b353858.*" />
-
<!-- Bad check for Explicit/Sequential layout -->
<!-- https://github.com/dotnet/corert/issues/2281 -->
<ExcludeList Include="$(XunitTestBinBase)\Loader\classloader\generics\Layout\General\Base01d_seq_ser\Base01d_seq_ser.*" />
@@ -723,17 +574,6 @@
<ExcludeList Include="$(XunitTestBinBase)\JIT\Methodical\Arrays\misc\_speed_dbgarrres\_speed_dbgarrres.*" />
<ExcludeList Include="$(XunitTestBinBase)\JIT\Methodical\Arrays\misc\_relarrres\_relarrres.*" />
- <!-- Tests that fail after RyuJIT update -->
- <!-- https://github.com/dotnet/corert/issues/2782 -->
- <ExcludeList Include="$(XunitTestBinBase)\GC\Scenarios\DoublinkList\doublinkstay\doublinkstay.*" />
- <ExcludeList Include="$(XunitTestBinBase)\GC\Scenarios\DoublinkList\doublinkgen\doublinkgen.*" />
- <ExcludeList Include="$(XunitTestBinBase)\GC\Scenarios\FinalNStruct\nstructresur\nstructresur.*" />
- <ExcludeList Include="$(XunitTestBinBase)\GC\Scenarios\NDPin\ndpinfinal\ndpinfinal.*" />
- <ExcludeList Include="$(XunitTestBinBase)\JIT\Directed\pinning\object-pin\object-pin\object-pin.*" />
-
- <!-- More failing GC tests -->
- <ExcludeList Include="$(XunitTestBinBase)\GC\Scenarios\Samples\gc\gc.*" />
-
<!-- Variant interface method resolution -->
<!-- https://github.com/dotnet/corert/issues/2358 -->
<ExcludeList Include="$(XunitTestBinBase)\JIT\Methodical\inlining\dev10_bug719093\variancesmall\variancesmall.*" />
@@ -809,6 +649,8 @@
<ExcludeList Include="$(XunitTestBinBase)\JIT\Methodical\fp\apps\bouncingball_cs_d\bouncingball_cs_d.*" />
<ExcludeList Include="$(XunitTestBinBase)\JIT\opt\perf\doublealign\Locals\Locals.*" />
<ExcludeList Include="$(XunitTestBinBase)\JIT\Regression\CLR-x86-JIT\V1.2-M02\b00719\b00719\b00719.*" />
+ <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\BitwiseOperations_r\BitwiseOperations_r.*" />
+ <ExcludeList Include="$(XunitTestBinBase)\JIT\SIMD\BitwiseOperations_ro\BitwiseOperations_ro.*" />
<!-- Crossgen tests, not runtime tests -->
<ExcludeList Include="$(XunitTestBinBase)\readytorun\genericsload\callgenericctor\callgenericctor.*" />
diff --git a/tests/runtest.sh b/tests/runtest.sh
index 94942284d..b315747d5 100755
--- a/tests/runtest.sh
+++ b/tests/runtest.sh
@@ -267,10 +267,10 @@ if [ ${CoreRT_CrossBuild} != 0 ]; then
source $ROOTFS_DIR/etc/os-release
fi
if [ "$ID" = "tizen" ]; then
- CoreRT_CrossCXXFlags="${CoreRT_CrossCXXFlags} -isystem ${CoreRT_CrossRootFS}/usr/lib/gcc/armv7l-tizen-linux-gnueabi/4.9.2/include/c++ `
- `-isystem ${CoreRT_CrossRootFS}//usr/lib/gcc/armv7l-tizen-linux-gnueabi/4.9.2/include/c++/armv7l-tizen-linux-gnueabi `
+ TIZEN_TOOLCHAIN="armv7l-tizen-linux-gnueabi/6.2.1"
+ CoreRT_CrossCXXFlags="${CoreRT_CrossCXXFlags} -isystem ${CoreRT_CrossRootFS}/usr/lib/gcc/${TIZEN_TOOLCHAIN}/include/c++ `
+ `-isystem ${CoreRT_CrossRootFS}//usr/lib/gcc/${TIZEN_TOOLCHAIN}/include/c++/armv7l-tizen-linux-gnueabi `
`-isystem ${CoreRT_CrossRootFS}/armel/usr/include"
- TIZEN_TOOLCHAIN="armv7l-tizen-linux-gnueabi/4.9.2"
CoreRT_CrossLinkerFlags="${CoreRT_CrossLinkerFlags} -B${CoreRT_CrossRootFS}/usr/lib/gcc/${TIZEN_TOOLCHAIN} `
`-L${CoreRT_CrossRootFS}/usr/lib/gcc/${TIZEN_TOOLCHAIN}"
else
diff --git a/tests/src/Simple/Generics/Generics.cs b/tests/src/Simple/Generics/Generics.cs
index f0b05e60f..213400efe 100644
--- a/tests/src/Simple/Generics/Generics.cs
+++ b/tests/src/Simple/Generics/Generics.cs
@@ -30,6 +30,7 @@ class Program
TestGvmDelegates.Run();
TestGvmDependencies.Run();
TestFieldAccess.Run();
+ TestNativeLayoutGeneration.Run();
return 100;
}
@@ -1964,4 +1965,53 @@ class Program
throw new Exception(s_NumErrors + " errors!");
}
}
+
+ // Regression test for https://github.com/dotnet/corert/issues/3659
+ class TestNativeLayoutGeneration
+ {
+#pragma warning disable 649 // s_ref was never assigned
+ private static object s_ref;
+#pragma warning restore 649
+
+ class Used
+ {
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public virtual string DoStuff()
+ {
+ return "Used";
+ }
+ }
+
+ class Unused<T> : Used
+ {
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public override string DoStuff()
+ {
+ return "Unused " + typeof(T).ToString();
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public void Blagh()
+ {
+ }
+ }
+
+ public static void Run()
+ {
+ new Used().DoStuff();
+
+ try
+ {
+ // Call an instance method on something we never allocated, but overrides a used virtual.
+ // This asserted the compiler when trying to build a template for Unused<__Canon>.
+ ((Unused<object>)s_ref).Blagh();
+ }
+ catch (NullReferenceException)
+ {
+ return;
+ }
+
+ throw new Exception();
+ }
+ }
}
diff --git a/tests/src/Simple/PInvoke/PInvoke.cs b/tests/src/Simple/PInvoke/PInvoke.cs
index fef465840..e4fe3c783 100644
--- a/tests/src/Simple/PInvoke/PInvoke.cs
+++ b/tests/src/Simple/PInvoke/PInvoke.cs
@@ -519,9 +519,20 @@ namespace PInvokeTests
public ExplicitStruct f2;
}
+
+ [StructLayout(LayoutKind.Explicit)]
+ public struct TestStruct2
+ {
+ [FieldOffset(0)]
+ public int f1;
+
+ [FieldOffset(8)]
+ public bool f2;
+ }
private static void TestStruct()
{
+#if !CODEGEN_CPP
Console.WriteLine("Testing Structs");
SequentialStruct ss = new SequentialStruct();
ss.f0 = 100;
@@ -581,7 +592,24 @@ namespace PInvokeTests
InlineUnicodeStruct ius = new InlineUnicodeStruct();
ius.inlineString = "Hello World";
-#if !CODEGEN_CPP
+
+ TestStruct2 ts = new TestStruct2() { f1 = 100, f2 = true };
+ int size = Marshal.SizeOf<TestStruct2>(ts);
+ IntPtr memory = Marshal.AllocHGlobal(size);
+ try
+ {
+ Marshal.StructureToPtr<TestStruct2>(ts, memory, false);
+ TestStruct2 ts2 = Marshal.PtrToStructure<TestStruct2>(memory);
+ ThrowIfNotEquals(true, ts2.f1 == 100 && ts2.f2 == true, "Struct marshalling Marshal API failed");
+
+ IntPtr offset = Marshal.OffsetOf<TestStruct2>("f2");
+ ThrowIfNotEquals(new IntPtr(8), offset, "Struct marshalling OffsetOf failed.");
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(memory);
+ }
+
ThrowIfNotEquals(true, InlineArrayTest(ref ias, ref ius), "inline array marshalling failed");
bool pass = true;
for (short i = 0; i < 128; i++)