summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.builds90
-rw-r--r--src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.pkgproj78
-rw-r--r--src/.nuget/Microsoft.NETCore.ILAsm/alpine/3.4.3/Microsoft.NETCore.ILAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILAsm/debian/Microsoft.NETCore.ILAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILAsm/fedora/23/Microsoft.NETCore.ILAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILAsm/fedora/24/Microsoft.NETCore.ILAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILAsm/opensuse/13.2/Microsoft.NETCore.ILAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILAsm/opensuse/42.1/Microsoft.NETCore.ILAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILAsm/rhel/Microsoft.NETCore.ILAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILAsm/runtime.Linux.Microsoft.NETCore.ILAsm.props (renamed from src/.nuget/Microsoft.NETCore.ILAsm/linux/Microsoft.NETCore.ILAsm.pkgproj)12
-rw-r--r--src/.nuget/Microsoft.NETCore.ILAsm/runtime.OSX.Microsoft.NETCore.ILAsm.props (renamed from src/.nuget/Microsoft.NETCore.ILAsm/osx/Microsoft.NETCore.ILAsm.pkgproj)12
-rw-r--r--src/.nuget/Microsoft.NETCore.ILAsm/runtime.Windows_NT.Microsoft.NETCore.ILAsm.props (renamed from src/.nuget/Microsoft.NETCore.ILAsm/win/Microsoft.NETCore.ILAsm.pkgproj)10
-rw-r--r--src/.nuget/Microsoft.NETCore.ILAsm/tizen/4.0.0/Microsoft.NETCore.ILAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/14.04/Microsoft.NETCore.ILAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/16.04/Microsoft.NETCore.ILAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/16.10/Microsoft.NETCore.ILAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.builds94
-rw-r--r--src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.pkgproj77
-rw-r--r--src/.nuget/Microsoft.NETCore.ILDAsm/alpine/3.4.3/Microsoft.NETCore.ILDAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILDAsm/debian/Microsoft.NETCore.ILDAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILDAsm/fedora/23/Microsoft.NETCore.ILDAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILDAsm/fedora/24/Microsoft.NETCore.ILDAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILDAsm/opensuse/13.2/Microsoft.NETCore.ILDAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILDAsm/opensuse/42.1/Microsoft.NETCore.ILDAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILDAsm/rhel/Microsoft.NETCore.ILDAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILDAsm/runtime.Linux.Microsoft.NETCore.ILDAsm.props (renamed from src/.nuget/Microsoft.NETCore.ILDAsm/linux/Microsoft.NETCore.ILDAsm.pkgproj)15
-rw-r--r--src/.nuget/Microsoft.NETCore.ILDAsm/runtime.OSX.Microsoft.NETCore.ILDAsm.props (renamed from src/.nuget/Microsoft.NETCore.ILDAsm/osx/Microsoft.NETCore.ILDAsm.pkgproj)12
-rw-r--r--src/.nuget/Microsoft.NETCore.ILDAsm/runtime.Windows_NT.Microsoft.NETCore.ILDAsm.props (renamed from src/.nuget/Microsoft.NETCore.ILDAsm/win/Microsoft.NETCore.ILDAsm.pkgproj)9
-rw-r--r--src/.nuget/Microsoft.NETCore.ILDAsm/tizen/4.0.0/Microsoft.NETCore.ILDAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/14.04/Microsoft.NETCore.ILDAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/16.04/Microsoft.NETCore.ILDAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/16.10/Microsoft.NETCore.ILDAsm.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.builds96
-rw-r--r--src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.pkgproj81
-rw-r--r--src/.nuget/Microsoft.NETCore.Jit/alpine/3.4.3/Microsoft.NETCore.Jit.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.Jit/debian/Microsoft.NETCore.Jit.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.Jit/fedora/23/Microsoft.NETCore.Jit.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.Jit/fedora/24/Microsoft.NETCore.Jit.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.Jit/opensuse/13.2/Microsoft.NETCore.Jit.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.Jit/opensuse/42.1/Microsoft.NETCore.Jit.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.Jit/rhel/Microsoft.NETCore.Jit.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.Jit/runtime.Linux.Microsoft.NETCore.Jit.props (renamed from src/.nuget/Microsoft.NETCore.Jit/linux/Microsoft.NETCore.Jit.pkgproj)12
-rw-r--r--src/.nuget/Microsoft.NETCore.Jit/runtime.OSX.Microsoft.NETCore.Jit.props (renamed from src/.nuget/Microsoft.NETCore.Jit/osx/Microsoft.NETCore.Jit.pkgproj)12
-rw-r--r--src/.nuget/Microsoft.NETCore.Jit/runtime.Windows_NT.Microsoft.NETCore.Jit.props (renamed from src/.nuget/Microsoft.NETCore.Jit/win/Microsoft.NETCore.Jit.pkgproj)11
-rw-r--r--src/.nuget/Microsoft.NETCore.Jit/tizen/4.0.0/Microsoft.NETCore.Jit.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.Jit/ubuntu/14.04/Microsoft.NETCore.Jit.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.Jit/ubuntu/16.04/Microsoft.NETCore.Jit.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.Jit/ubuntu/16.10/Microsoft.NETCore.Jit.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.Native/Microsoft.NETCore.Native.builds64
-rw-r--r--src/.nuget/Microsoft.NETCore.Native/Microsoft.NETCore.Native.pkgproj53
-rw-r--r--src/.nuget/Microsoft.NETCore.Native/Microsoft.NETCore.Native.props6
-rw-r--r--src/.nuget/Microsoft.NETCore.Native/alpine/3.4.3/Microsoft.NETCore.Native.pkgproj30
-rw-r--r--src/.nuget/Microsoft.NETCore.Native/debian/Microsoft.NETCore.Native.pkgproj30
-rw-r--r--src/.nuget/Microsoft.NETCore.Native/fedora/23/Microsoft.NETCore.Native.pkgproj30
-rw-r--r--src/.nuget/Microsoft.NETCore.Native/fedora/24/Microsoft.NETCore.Native.pkgproj30
-rw-r--r--src/.nuget/Microsoft.NETCore.Native/opensuse/13.2/Microsoft.NETCore.Native.pkgproj30
-rw-r--r--src/.nuget/Microsoft.NETCore.Native/opensuse/42.1/Microsoft.NETCore.Native.pkgproj30
-rw-r--r--src/.nuget/Microsoft.NETCore.Native/rhel/Microsoft.NETCore.Native.pkgproj30
-rw-r--r--src/.nuget/Microsoft.NETCore.Native/runtime.Linux.Microsoft.NETCore.Native.props (renamed from src/.nuget/Microsoft.NETCore.Native/linux/Microsoft.NETCore.Native.pkgproj)14
-rw-r--r--src/.nuget/Microsoft.NETCore.Native/runtime.OSX.Microsoft.NETCore.Native.props (renamed from src/.nuget/Microsoft.NETCore.Native/osx/Microsoft.NETCore.Native.pkgproj)14
-rw-r--r--src/.nuget/Microsoft.NETCore.Native/ubuntu/14.04/Microsoft.NETCore.Native.pkgproj30
-rw-r--r--src/.nuget/Microsoft.NETCore.Native/ubuntu/16.04/Microsoft.NETCore.Native.pkgproj30
-rw-r--r--src/.nuget/Microsoft.NETCore.Native/ubuntu/16.10/Microsoft.NETCore.Native.pkgproj30
-rw-r--r--src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/Microsoft.NETCore.Runtime.CoreCLR.builds95
-rw-r--r--src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/Microsoft.NETCore.Runtime.CoreCLR.pkgproj77
-rw-r--r--src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/alpine/3.4.3/Microsoft.NETCore.Runtime.CoreCLR.pkgproj56
-rw-r--r--src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/debian/Microsoft.NETCore.Runtime.CoreCLR.pkgproj56
-rw-r--r--src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/fedora/23/Microsoft.NETCore.Runtime.CoreCLR.pkgproj56
-rw-r--r--src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/fedora/24/Microsoft.NETCore.Runtime.CoreCLR.pkgproj56
-rw-r--r--src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/linux/Microsoft.NETCore.Runtime.CoreCLR.pkgproj56
-rw-r--r--src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/opensuse/13.2/Microsoft.NETCore.Runtime.CoreCLR.pkgproj56
-rw-r--r--src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/opensuse/42.1/Microsoft.NETCore.Runtime.CoreCLR.pkgproj56
-rw-r--r--src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/rhel/Microsoft.NETCore.Runtime.CoreCLR.pkgproj56
-rw-r--r--src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/runtime.Linux.Microsoft.NETCore.Runtime.CoreCLR.props (renamed from src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/tizen/4.0.0/Microsoft.NETCore.Runtime.CoreCLR.pkgproj)21
-rw-r--r--src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/runtime.OSX.Microsoft.NETCore.Runtime.CoreCLR.props (renamed from src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/osx/Microsoft.NETCore.Runtime.CoreCLR.pkgproj)15
-rw-r--r--src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/runtime.Windows_NT.Microsoft.NETCore.Runtime.CoreCLR.props (renamed from src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/win/Microsoft.NETCore.Runtime.CoreCLR.pkgproj)7
-rw-r--r--src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/14.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj56
-rw-r--r--src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/16.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj56
-rw-r--r--src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/16.10/Microsoft.NETCore.Runtime.CoreCLR.pkgproj56
-rw-r--r--src/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.builds92
-rw-r--r--src/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.pkgproj74
-rw-r--r--src/.nuget/Microsoft.NETCore.TestHost/alpine/3.4.3/Microsoft.NETCore.TestHost.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.TestHost/debian/Microsoft.NETCore.TestHost.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.TestHost/fedora/23/Microsoft.NETCore.TestHost.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.TestHost/fedora/24/Microsoft.NETCore.TestHost.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.TestHost/opensuse/13.2/Microsoft.NETCore.TestHost.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.TestHost/opensuse/42.1/Microsoft.NETCore.TestHost.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.TestHost/rhel/Microsoft.NETCore.TestHost.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.TestHost/runtime.Linux.Microsoft.NETCore.TestHost.props (renamed from src/.nuget/Microsoft.NETCore.TestHost/linux/Microsoft.NETCore.TestHost.pkgproj)12
-rw-r--r--src/.nuget/Microsoft.NETCore.TestHost/runtime.OSX.Microsoft.NETCore.TestHost.props (renamed from src/.nuget/Microsoft.NETCore.TestHost/osx/Microsoft.NETCore.TestHost.pkgproj)12
-rw-r--r--src/.nuget/Microsoft.NETCore.TestHost/runtime.Windows_NT.Microsoft.NETCore.TestHost.props (renamed from src/.nuget/Microsoft.NETCore.TestHost/win/Microsoft.NETCore.TestHost.pkgproj)9
-rw-r--r--src/.nuget/Microsoft.NETCore.TestHost/tizen/4.0.0/Microsoft.NETCore.TestHost.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.TestHost/ubuntu/14.04/Microsoft.NETCore.TestHost.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.TestHost/ubuntu/16.04/Microsoft.NETCore.TestHost.pkgproj29
-rw-r--r--src/.nuget/Microsoft.NETCore.TestHost/ubuntu/16.10/Microsoft.NETCore.TestHost.pkgproj29
-rw-r--r--src/.nuget/Microsoft.TargetingPack.Private.CoreCLR/Microsoft.TargetingPack.Private.CoreCLR.pkgproj1
-rw-r--r--src/.nuget/dir.props153
-rw-r--r--src/.nuget/dir.traversal.targets19
-rw-r--r--src/.nuget/init/project.json2
-rw-r--r--src/.nuget/packages.builds19
-rw-r--r--src/ToolBox/SOS/lldbplugin/CMakeLists.txt1
-rw-r--r--src/classlibnative/inc/nlsinfo.h6
-rw-r--r--src/classlibnative/nls/nlsinfo.cpp81
-rw-r--r--src/corefx/System.Globalization.Native/collation.cpp10
-rw-r--r--src/debug/daccess/nidump.cpp4
-rw-r--r--src/inc/clrconfigvalues.h1
-rw-r--r--src/inc/clrprivbinderutil.h3
-rw-r--r--src/inc/corcompile.h6
-rw-r--r--src/inc/corinfo.h2
-rw-r--r--src/inc/corprof.idl9
-rw-r--r--src/inc/jithelpers.h2
-rw-r--r--src/inc/newapis.h16
-rw-r--r--src/inc/readytorun.h10
-rw-r--r--src/inc/regdisp.h42
-rw-r--r--src/jit/compiler.cpp42
-rw-r--r--src/jit/compiler.h25
-rw-r--r--src/jit/compiler.hpp2
-rw-r--r--src/jit/compphases.h125
-rw-r--r--src/jit/emit.cpp2
-rw-r--r--src/jit/emitxarch.cpp16
-rw-r--r--src/jit/flowgraph.cpp406
-rw-r--r--src/jit/importer.cpp155
-rw-r--r--src/jit/inline.h9
-rw-r--r--src/jit/instrsxarch.h8
-rw-r--r--src/jit/jitconfigvalues.h3
-rw-r--r--src/jit/lclvars.cpp75
-rw-r--r--src/jit/lower.cpp36
-rw-r--r--src/jit/morph.cpp15
-rw-r--r--src/jit/simd.cpp15
-rw-r--r--src/jit/simdcodegenxarch.cpp38
-rw-r--r--src/jit/utils.cpp1
-rw-r--r--src/jit/valuenum.cpp16
-rw-r--r--src/jit/valuenumfuncs.h1
-rw-r--r--src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs2
-rw-r--r--src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs26
-rw-r--r--src/mscorlib/corefx/System/Globalization/CompareInfo.cs4
-rw-r--r--src/mscorlib/ref/mscorlib.cs2
-rw-r--r--src/mscorlib/src/System/Globalization/CompareInfo.cs37
-rw-r--r--src/mscorlib/src/System/Globalization/CultureInfo.cs3
-rw-r--r--src/mscorlib/src/System/Resources/ResourceFallbackManager.cs170
-rw-r--r--src/mscorlib/src/System/Runtime/Reliability/ReliabilityContractAttribute.cs7
-rw-r--r--src/mscorlib/src/System/Runtime/Versioning/NonVersionableAttribute.cs6
-rw-r--r--src/mscorlib/src/System/SharedStatics.cs6
-rw-r--r--src/mscorlib/src/System/String.Manipulation.cs90
-rw-r--r--src/utilcode/downlevel.cpp4
-rw-r--r--src/utilcode/newapis.cpp30
-rw-r--r--src/vm/amd64/remotingamd64.cpp672
-rw-r--r--src/vm/appdomain.cpp1
-rw-r--r--src/vm/appdomainhelper.cpp546
-rw-r--r--src/vm/appdomainhelper.h371
-rw-r--r--src/vm/appdomainnative.cpp1
-rw-r--r--src/vm/assembly.cpp1
-rw-r--r--src/vm/assemblynamesconfigfactory.cpp264
-rw-r--r--src/vm/assemblynamesconfigfactory.h72
-rw-r--r--src/vm/assemblynative.cpp1
-rw-r--r--src/vm/ceeload.cpp41
-rw-r--r--src/vm/ceeload.h10
-rw-r--r--src/vm/clrprivbinderfusion.cpp819
-rw-r--r--src/vm/clrprivbinderfusion.h228
-rw-r--r--src/vm/clrprivbinderreflectiononlywinrt.cpp497
-rw-r--r--src/vm/clrprivbinderreflectiononlywinrt.h295
-rw-r--r--src/vm/clrprivtypecachereflectiononlywinrt.cpp260
-rw-r--r--src/vm/clrprivtypecachereflectiononlywinrt.h58
-rw-r--r--src/vm/cominterfacemarshaler.cpp1
-rw-r--r--src/vm/commethodrental.cpp120
-rw-r--r--src/vm/commethodrental.h29
-rw-r--r--src/vm/compile.cpp7
-rw-r--r--src/vm/compile.h2
-rw-r--r--src/vm/comsynchronizable.cpp1
-rw-r--r--src/vm/constrainedexecutionregion.cpp2264
-rw-r--r--src/vm/crossdomaincalls.cpp2587
-rw-r--r--src/vm/dataimage.cpp3
-rw-r--r--src/vm/ecalllist.h2
-rw-r--r--src/vm/eeconfigfactory.cpp398
-rw-r--r--src/vm/eeconfigfactory.h149
-rw-r--r--src/vm/exceptionhandling.cpp26
-rw-r--r--src/vm/gchost.cpp28
-rw-r--r--src/vm/i386/cgenx86.cpp29
-rw-r--r--src/vm/i386/excepx86.cpp1
-rw-r--r--src/vm/i386/remotingx86.cpp225
-rw-r--r--src/vm/inlinetracking.cpp390
-rw-r--r--src/vm/inlinetracking.h221
-rw-r--r--src/vm/jitinterface.cpp21
-rw-r--r--src/vm/mda.cpp4017
-rw-r--r--src/vm/mda.h1
-rw-r--r--src/vm/mdadac.cpp48
-rw-r--r--src/vm/message.cpp1171
-rw-r--r--src/vm/mixedmode.cpp236
-rw-r--r--src/vm/mixedmode.hpp4
-rw-r--r--src/vm/mscorlib.cpp5
-rw-r--r--src/vm/ngenoptout.cpp12
-rw-r--r--src/vm/ngenoptout.h34
-rw-r--r--src/vm/objectclone.cpp3861
-rw-r--r--src/vm/pefile.h2
-rw-r--r--src/vm/prestub.cpp51
-rw-r--r--src/vm/proftoeeinterfaceimpl.cpp7
-rw-r--r--src/vm/readytoruninfo.cpp26
-rw-r--r--src/vm/readytoruninfo.h11
-rw-r--r--src/vm/remoting.cpp3773
-rw-r--r--src/vm/rwlock.cpp2952
-rw-r--r--src/vm/rwlock.h214
-rw-r--r--src/vm/securitymeta.cpp1
-rw-r--r--src/vm/securitystackwalk.h1
-rw-r--r--src/vm/stackbuildersink.cpp702
-rw-r--r--src/vm/threads.cpp1
-rw-r--r--src/vm/validator.cpp946
-rw-r--r--src/zap/zapimage.cpp1
-rw-r--r--src/zap/zapimage.h1
-rw-r--r--src/zap/zapinfo.cpp9
-rw-r--r--src/zap/zapreadytorun.cpp9
210 files changed, 2021 insertions, 31858 deletions
diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.builds b/src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.builds
index f84ccd07c8..b14c6b29ab 100644
--- a/src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.builds
+++ b/src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.builds
@@ -2,95 +2,9 @@
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <!-- This property must be set to the same value as $(PackageOutputPath) for the nuspecs and nupkgs to be binplaced to the intended location. -->
- <OutputPath>$(PackageOutputPath)</OutputPath>
- </PropertyGroup>
-
- <!-- We always build the identity/redirection package. However, the platform specific runtime-*.nupkg is built based upon the target OS we are building the product for. -->
<ItemGroup>
- <Project Include="Microsoft.NETCore.ILAsm.pkgproj">
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>arm64</Platform>
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>x86</Platform>
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>arm</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'linux-x64'" Include="linux/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'debian.8-x64'" Include="debian/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'debian.8-armel'" Include="debian/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>armel</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'fedora.23-x64'" Include="fedora/23/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'fedora.24-x64'" Include="fedora/24/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'opensuse.13.2-x64'" Include="opensuse/13.2/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'opensuse.42.1-x64'" Include="opensuse/42.1/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and $(DistroRid.StartsWith('rhel.7'))" Include="rhel/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.14.04-x64'" Include="ubuntu/14.04/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.14.04-arm'" Include="ubuntu/14.04/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>arm</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.16.04-x64'" Include="ubuntu/16.04/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.16.04-arm'" Include="ubuntu/16.04/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>arm</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.16.10-x64'" Include="ubuntu/16.10/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'alpine.3.4.3-x64'" Include="alpine/3.4.3/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'tizen.4.0.0-armel'" Include="tizen/4.0.0/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>armel</Platform>
- </Project>
- <Project Condition="'$(TargetsOSX)' == 'true'" Include="osx/Microsoft.NETCore.ILAsm.pkgproj">
- <OSGroup>OSX</OSGroup>
- <Platform>amd64</Platform>
- </Project>
+ <!-- identity project, runtime specific projects are included by props above -->
+ <Project Include="$(MSBuildProjectName).pkgproj" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.pkgproj
index 4a5b1ad584..c36aa5b2ec 100644
--- a/src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.ILAsm/Microsoft.NETCore.ILAsm.pkgproj
@@ -1,75 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <SkipValidatePackage>true</SkipValidatePackage>
- <PackagePlatforms>x64;x86;arm64;arm;armel;</PackagePlatforms>
- <OutputPath>$(PackagesOutputPath)</OutputPath>
- <IncludeRuntimeJson>true</IncludeRuntimeJson>
+
+ <PropertyGroup Condition="'$(PackageTargetRuntime)' == ''">
+ <IsLineupPackage Condition="'$(IsLineupPackage)' == ''">true</IsLineupPackage>
</PropertyGroup>
- <ItemGroup>
- <ProjectReference Include="..\Microsoft.NETCore.Runtime.CoreCLR\Microsoft.NETCore.Runtime.CoreCLR.pkgproj" />
- <ProjectReference Include="win\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="win\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>arm64</Platform>
- </ProjectReference>
- <ProjectReference Include="win\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>x86</Platform>
- </ProjectReference>
- <ProjectReference Include="win\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>arm</Platform>
- </ProjectReference>
- <ProjectReference Include="linux\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="debian\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="debian\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>armel</Platform>
- </ProjectReference>
- <ProjectReference Include="fedora\23\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="fedora\24\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="opensuse\13.2\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="opensuse\42.1\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="rhel\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\14.04\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\14.04\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>arm</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\16.04\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\16.04\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>arm</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\16.10\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="alpine\3.4.3\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="tizen\4.0.0\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>armel</Platform>
- </ProjectReference>
- <ProjectReference Include="osx\Microsoft.NETCore.ILAsm.pkgproj">
- <Platform>amd64</Platform>
+
+ <ItemGroup Condition="'$(IsLineupPackage)' == 'true'">
+ <ProjectReference Include="..\Microsoft.NETCore.Runtime.CoreCLR\Microsoft.NETCore.Runtime.CoreCLR.pkgproj" >
+ <!-- we should look at moving this into packaging.targets instead of having to carry this around for every pkgproj project reference -->
+ <AdditionalProperties>%(ProjectReference.AdditionalProperties);IsLineupPackage=false</AdditionalProperties>
</ProjectReference>
</ItemGroup>
+
+ <Import Condition="'$(_packageTargetOSGroup)' != ''" Project="$(MSBuildThisFileDirectory)runtime.$(_packageTargetOSGroup).$(MSBuildProjectName).props" />
+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/alpine/3.4.3/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/alpine/3.4.3/Microsoft.NETCore.ILAsm.pkgproj
deleted file mode 100644
index 41a5b4c301..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILAsm/alpine/3.4.3/Microsoft.NETCore.ILAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>alpine.3.4.3-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ilasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/debian/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/debian/Microsoft.NETCore.ILAsm.pkgproj
deleted file mode 100644
index 99c782c01d..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILAsm/debian/Microsoft.NETCore.ILAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>debian.8-$(PackagePlatform)</PackageTargetRuntime>
- <!-- build for x64, armel -->
- <PackagePlatforms>x64;armel;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ilasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/fedora/23/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/fedora/23/Microsoft.NETCore.ILAsm.pkgproj
deleted file mode 100644
index ac8f53b4fe..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILAsm/fedora/23/Microsoft.NETCore.ILAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>fedora.23-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ilasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/fedora/24/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/fedora/24/Microsoft.NETCore.ILAsm.pkgproj
deleted file mode 100644
index 3ad08a9b77..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILAsm/fedora/24/Microsoft.NETCore.ILAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>fedora.24-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ilasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/opensuse/13.2/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/opensuse/13.2/Microsoft.NETCore.ILAsm.pkgproj
deleted file mode 100644
index 6181ab366e..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILAsm/opensuse/13.2/Microsoft.NETCore.ILAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>opensuse.13.2-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ilasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/opensuse/42.1/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/opensuse/42.1/Microsoft.NETCore.ILAsm.pkgproj
deleted file mode 100644
index 85adbd6092..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILAsm/opensuse/42.1/Microsoft.NETCore.ILAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>opensuse.42.1-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ilasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/rhel/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/rhel/Microsoft.NETCore.ILAsm.pkgproj
deleted file mode 100644
index 6410798f63..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILAsm/rhel/Microsoft.NETCore.ILAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>rhel.7-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ilasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/linux/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/runtime.Linux.Microsoft.NETCore.ILAsm.props
index ce3bf6320e..fa72b48619 100644
--- a/src/.nuget/Microsoft.NETCore.ILAsm/linux/Microsoft.NETCore.ILAsm.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.ILAsm/runtime.Linux.Microsoft.NETCore.ILAsm.props
@@ -1,12 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>linux-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
<ItemGroup>
<NativeSplittableBinary Include="$(BinDir)ilasm" />
<ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
@@ -19,11 +12,10 @@
<AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
+ <ArchitectureSpecificNativeSymbol Include="..\_.pdb" />
<File Include="@(ArchitectureSpecificNativeSymbol)">
<TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
<IsSymbolFile>true</IsSymbolFile>
</File>
</ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/osx/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/runtime.OSX.Microsoft.NETCore.ILAsm.props
index bee340b23c..9048ff7544 100644
--- a/src/.nuget/Microsoft.NETCore.ILAsm/osx/Microsoft.NETCore.ILAsm.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.ILAsm/runtime.OSX.Microsoft.NETCore.ILAsm.props
@@ -1,12 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>osx.10.10-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
<ItemGroup>
<NativeSplittableBinary Include="$(BinDir)ilasm" />
<ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
@@ -19,11 +12,10 @@
<AdditionalLibPackageExcludes Include="%2A%2A\%2A.dwarf" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dylib" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
+ <ArchitectureSpecificNativeSymbol Include="..\_.pdb" />
<File Include="@(ArchitectureSpecificNativeSymbol)">
<TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
<IsSymbolFile>true</IsSymbolFile>
</File>
</ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/win/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/runtime.Windows_NT.Microsoft.NETCore.ILAsm.props
index 57364df706..478c4600de 100644
--- a/src/.nuget/Microsoft.NETCore.ILAsm/win/Microsoft.NETCore.ILAsm.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.ILAsm/runtime.Windows_NT.Microsoft.NETCore.ILAsm.props
@@ -1,9 +1,7 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<PackageTargetRuntime>$(MinOSForArch)-$(PackagePlatform)</PackageTargetRuntime>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
</PropertyGroup>
<ItemGroup>
<ArchitectureSpecificNativeFile Include="$(BinDir)ilasm.exe" />
@@ -14,11 +12,9 @@
<ItemGroup>
<ArchitectureSpecificNativeSymbol Include="@(ArchitectureSpecificNativeFile -> '%(RelativeDir)PDB\%(FileName).pdb')" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
+ <ArchitectureSpecificNativeSymbol Include="..\_.pdb" />
<File Include="@(ArchitectureSpecificNativeSymbol)">
<TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
<IsSymbolFile>true</IsSymbolFile>
</File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
+ </ItemGroup></Project>
diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/tizen/4.0.0/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/tizen/4.0.0/Microsoft.NETCore.ILAsm.pkgproj
deleted file mode 100644
index 1d235b6f59..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILAsm/tizen/4.0.0/Microsoft.NETCore.ILAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>tizen.4.0.0-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for armel -->
- <PackagePlatforms>armel;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ilasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/14.04/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/14.04/Microsoft.NETCore.ILAsm.pkgproj
deleted file mode 100644
index cacadc78b1..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/14.04/Microsoft.NETCore.ILAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>ubuntu.14.04-$(PackagePlatform)</PackageTargetRuntime>
- <!-- build for x64, arm -->
- <PackagePlatforms>x64;arm;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ilasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/16.04/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/16.04/Microsoft.NETCore.ILAsm.pkgproj
deleted file mode 100644
index 818495e6e2..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/16.04/Microsoft.NETCore.ILAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>ubuntu.16.04-$(PackagePlatform)</PackageTargetRuntime>
- <!-- build for x64, arm -->
- <PackagePlatforms>x64;arm;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ilasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/16.10/Microsoft.NETCore.ILAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/16.10/Microsoft.NETCore.ILAsm.pkgproj
deleted file mode 100644
index 91ee7f3503..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILAsm/ubuntu/16.10/Microsoft.NETCore.ILAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>ubuntu.16.10-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ilasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.builds b/src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.builds
index b312b3bc99..679fffeadd 100644
--- a/src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.builds
+++ b/src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.builds
@@ -2,96 +2,10 @@
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <!-- This property must be set to the same value as $(PackageOutputPath) for the nuspecs and nupkgs to be binplaced to the intended location. -->
- <OutputPath>$(PackageOutputPath)</OutputPath>
- </PropertyGroup>
-
- <!-- We always build the identity/redirection package. However, the platform specific runtime-*.nupkg is built based upon the target OS we are building the product for. -->
<ItemGroup>
- <Project Include="Microsoft.NETCore.ILDAsm.pkgproj">
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>arm64</Platform>
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>x86</Platform>
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>arm</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'linux-x64'" Include="linux/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'debian.8-x64'" Include="debian/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'debian.8-armel'" Include="debian/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>armel</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'fedora.23-x64'" Include="fedora/23/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'fedora.24-x64'" Include="fedora/24/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'opensuse.13.2-x64'" Include="opensuse/13.2/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'opensuse.42.1-x64'" Include="opensuse/42.1/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and $(DistroRid.StartsWith('rhel.7'))" Include="rhel/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.14.04-x64'" Include="ubuntu/14.04/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.14.04-arm'" Include="ubuntu/14.04/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>arm</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.16.04-x64'" Include="ubuntu/16.04/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.16.04-arm'" Include="ubuntu/16.04/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>arm</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.16.10-x64'" Include="ubuntu/16.10/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'alpine.3.4.3-x64'" Include="alpine/3.4.3/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'tizen.4.0.0-armel'" Include="tizen/4.0.0/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>armel</Platform>
- </Project>
- <Project Condition="'$(TargetsOSX)' == 'true'" Include="osx/Microsoft.NETCore.ILDAsm.pkgproj">
- <OSGroup>OSX</OSGroup>
- <Platform>amd64</Platform>
- </Project>
+ <!-- identity project, runtime specific projects are included by props above -->
+ <Project Include="$(MSBuildProjectName).pkgproj" />
</ItemGroup>
-
+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
-</Project>
+</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.pkgproj
index cdfee45ce4..b5fe3cb308 100644
--- a/src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.ILDAsm/Microsoft.NETCore.ILDAsm.pkgproj
@@ -1,75 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <SkipValidatePackage>true</SkipValidatePackage>
- <PackagePlatforms>x64;x86;arm64;arm;armel;</PackagePlatforms>
- <OutputPath>$(PackagesOutputPath)</OutputPath>
- <IncludeRuntimeJson>true</IncludeRuntimeJson>
+
+ <PropertyGroup Condition="'$(PackageTargetRuntime)' == ''">
+ <IsLineupPackage Condition="'$(IsLineupPackage)' == ''">true</IsLineupPackage>
</PropertyGroup>
- <ItemGroup>
- <ProjectReference Include="..\Microsoft.NETCore.Runtime.CoreCLR\Microsoft.NETCore.Runtime.CoreCLR.pkgproj" />
- <ProjectReference Include="win\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="win\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>arm64</Platform>
- </ProjectReference>
- <ProjectReference Include="win\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>x86</Platform>
- </ProjectReference>
- <ProjectReference Include="win\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>arm</Platform>
- </ProjectReference>
- <ProjectReference Include="linux\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="debian\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="debian\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>armel</Platform>
- </ProjectReference>
- <ProjectReference Include="fedora\23\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="fedora\24\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="opensuse\13.2\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="opensuse\42.1\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="rhel\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\14.04\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\14.04\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>arm</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\16.04\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\16.04\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>arm</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\16.10\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="alpine\3.4.3\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="tizen\4.0.0\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>armel</Platform>
- </ProjectReference>
- <ProjectReference Include="osx\Microsoft.NETCore.ILDAsm.pkgproj">
- <Platform>amd64</Platform>
+
+ <ItemGroup Condition="'$(PackageTargetRuntime)' == ''">
+ <ProjectReference Include="..\Microsoft.NETCore.Runtime.CoreCLR\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
+ <AdditionalProperties>%(ProjectReference.AdditionalProperties);IsLineupPackage=false</AdditionalProperties>
</ProjectReference>
</ItemGroup>
+
+ <Import Condition="'$(_packageTargetOSGroup)' != ''" Project="$(MSBuildThisFileDirectory)runtime.$(_packageTargetOSGroup).$(MSBuildProjectName).props" />
+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/alpine/3.4.3/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/alpine/3.4.3/Microsoft.NETCore.ILDAsm.pkgproj
deleted file mode 100644
index b27fe08767..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILDAsm/alpine/3.4.3/Microsoft.NETCore.ILDAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>alpine.3.4.3-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ildasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/debian/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/debian/Microsoft.NETCore.ILDAsm.pkgproj
deleted file mode 100644
index f73e785d4b..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILDAsm/debian/Microsoft.NETCore.ILDAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>debian.8-$(PackagePlatform)</PackageTargetRuntime>
- <!-- build for x64, armel -->
- <PackagePlatforms>x64;armel;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ildasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/fedora/23/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/fedora/23/Microsoft.NETCore.ILDAsm.pkgproj
deleted file mode 100644
index 8385c5d55a..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILDAsm/fedora/23/Microsoft.NETCore.ILDAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>fedora.23-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ildasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/fedora/24/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/fedora/24/Microsoft.NETCore.ILDAsm.pkgproj
deleted file mode 100644
index 20ad52225b..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILDAsm/fedora/24/Microsoft.NETCore.ILDAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>fedora.24-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ildasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/opensuse/13.2/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/opensuse/13.2/Microsoft.NETCore.ILDAsm.pkgproj
deleted file mode 100644
index d91ef02df3..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILDAsm/opensuse/13.2/Microsoft.NETCore.ILDAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>opensuse.13.2-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ildasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/opensuse/42.1/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/opensuse/42.1/Microsoft.NETCore.ILDAsm.pkgproj
deleted file mode 100644
index 07370b4915..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILDAsm/opensuse/42.1/Microsoft.NETCore.ILDAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>opensuse.42.1-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ildasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/rhel/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/rhel/Microsoft.NETCore.ILDAsm.pkgproj
deleted file mode 100644
index 355c1c9162..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILDAsm/rhel/Microsoft.NETCore.ILDAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>rhel.7-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ildasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/linux/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/runtime.Linux.Microsoft.NETCore.ILDAsm.props
index 7a7f82ddd5..3e604c2538 100644
--- a/src/.nuget/Microsoft.NETCore.ILDAsm/linux/Microsoft.NETCore.ILDAsm.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.ILDAsm/runtime.Linux.Microsoft.NETCore.ILDAsm.props
@@ -1,12 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>linux-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
<ItemGroup>
<NativeSplittableBinary Include="$(BinDir)ildasm" />
<ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
@@ -19,11 +12,9 @@
<AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
+ <ArchitectureSpecificNativeSymbol Include="..\_.pdb" />
<File Include="@(ArchitectureSpecificNativeSymbol)">
<TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
<IsSymbolFile>true</IsSymbolFile>
</File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
+ </ItemGroup></Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/osx/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/runtime.OSX.Microsoft.NETCore.ILDAsm.props
index 9a17267a66..c0a4d0f2b5 100644
--- a/src/.nuget/Microsoft.NETCore.ILDAsm/osx/Microsoft.NETCore.ILDAsm.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.ILDAsm/runtime.OSX.Microsoft.NETCore.ILDAsm.props
@@ -1,12 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>osx.10.10-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
<ItemGroup>
<NativeSplittableBinary Include="$(BinDir)ildasm" />
<ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
@@ -19,11 +12,10 @@
<AdditionalLibPackageExcludes Include="%2A%2A\%2A.dwarf" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dylib" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
+ <ArchitectureSpecificNativeSymbol Include="..\_.pdb" />
<File Include="@(ArchitectureSpecificNativeSymbol)">
<TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
<IsSymbolFile>true</IsSymbolFile>
</File>
</ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/win/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/runtime.Windows_NT.Microsoft.NETCore.ILDAsm.props
index d32b540b0b..850df28e6d 100644
--- a/src/.nuget/Microsoft.NETCore.ILDAsm/win/Microsoft.NETCore.ILDAsm.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.ILDAsm/runtime.Windows_NT.Microsoft.NETCore.ILDAsm.props
@@ -1,9 +1,7 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<PackageTargetRuntime>$(MinOSForArch)-$(PackagePlatform)</PackageTargetRuntime>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
</PropertyGroup>
<ItemGroup>
<ArchitectureSpecificNativeFile Include="$(BinDir)ildasm.exe" />
@@ -15,11 +13,10 @@
<ItemGroup>
<ArchitectureSpecificNativeSymbol Include="@(ArchitectureSpecificNativeFile -> '%(RelativeDir)PDB\%(FileName).pdb')" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
+ <ArchitectureSpecificNativeSymbol Include="..\_.pdb" />
<File Include="@(ArchitectureSpecificNativeSymbol)">
<TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
<IsSymbolFile>true</IsSymbolFile>
</File>
</ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/tizen/4.0.0/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/tizen/4.0.0/Microsoft.NETCore.ILDAsm.pkgproj
deleted file mode 100644
index 9ede1eb2e4..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILDAsm/tizen/4.0.0/Microsoft.NETCore.ILDAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>tizen.4.0.0-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for armel -->
- <PackagePlatforms>armel;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ildasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/14.04/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/14.04/Microsoft.NETCore.ILDAsm.pkgproj
deleted file mode 100644
index e087645962..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/14.04/Microsoft.NETCore.ILDAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>ubuntu.14.04-$(PackagePlatform)</PackageTargetRuntime>
- <!-- build for x64, arm -->
- <PackagePlatforms>x64;arm;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ildasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/16.04/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/16.04/Microsoft.NETCore.ILDAsm.pkgproj
deleted file mode 100644
index 776e59ba16..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/16.04/Microsoft.NETCore.ILDAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>ubuntu.16.04-$(PackagePlatform)</PackageTargetRuntime>
- <!-- build for x64, arm -->
- <PackagePlatforms>x64;arm;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ildasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/16.10/Microsoft.NETCore.ILDAsm.pkgproj b/src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/16.10/Microsoft.NETCore.ILDAsm.pkgproj
deleted file mode 100644
index 6c73eba240..0000000000
--- a/src/.nuget/Microsoft.NETCore.ILDAsm/ubuntu/16.10/Microsoft.NETCore.ILDAsm.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>ubuntu.16.10-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)ildasm" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.builds b/src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.builds
index 5f75a74196..dd00e039a6 100644
--- a/src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.builds
+++ b/src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.builds
@@ -1,97 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <!-- This property must be set to the same value as $(PackageOutputPath) for the nuspecs and nupkgs to be binplaced to the intended location. -->
- <OutputPath>$(PackageOutputPath)</OutputPath>
- </PropertyGroup>
-
- <!-- We always build the identity/redirection package. However, the platform specific runtime-*.nupkg is built based upon the target OS we are building the product for. -->
<ItemGroup>
- <Project Include="Microsoft.NETCore.Jit.pkgproj">
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>arm64</Platform>
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>x86</Platform>
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>arm</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'linux-x64'" Include="linux/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'debian.8-x64'" Include="debian/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'debian.8-armel'" Include="debian/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>armel</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'fedora.23-x64'" Include="fedora/23/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'fedora.24-x64'" Include="fedora/24/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'opensuse.13.2-x64'" Include="opensuse/13.2/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'opensuse.42.1-x64'" Include="opensuse/42.1/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and $(DistroRid.StartsWith('rhel.7'))" Include="rhel/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.14.04-x64'" Include="ubuntu/14.04/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.14.04-arm'" Include="ubuntu/14.04/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>arm</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.16.04-x64'" Include="ubuntu/16.04/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.16.04-arm'" Include="ubuntu/16.04/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>arm</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.16.10-x64'" Include="ubuntu/16.10/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'alpine.3.4.3-x64'" Include="alpine/3.4.3/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'tizen.4.0.0-armel'" Include="tizen/4.0.0/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>armel</Platform>
- </Project>
- <Project Condition="'$(TargetsOSX)' == 'true'" Include="osx/Microsoft.NETCore.Jit.pkgproj">
- <OSGroup>OSX</OSGroup>
- <Platform>amd64</Platform>
- </Project>
+ <!-- identity project, runtime specific projects are included by props above -->
+ <Project Include="$(MSBuildProjectName).pkgproj" />
</ItemGroup>
-
+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
-</Project>
+</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.pkgproj
index dd39f77b2b..a9ebe1cda4 100644
--- a/src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.Jit/Microsoft.NETCore.Jit.pkgproj
@@ -1,74 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+
+ <PropertyGroup Condition="'$(PackageTargetRuntime)' == ''">
+ <IsLineupPackage Condition="'$(IsLineupPackage)' == ''">true</IsLineupPackage>
+ </PropertyGroup>
+
<PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <SkipValidatePackage>true</SkipValidatePackage>
- <PackagePlatforms>x64;x86;arm64;arm;armel;</PackagePlatforms>
- <OutputPath>$(PackagesOutputPath)</OutputPath>
- <IncludeRuntimeJson>true</IncludeRuntimeJson>
+ <LongNamePlatform>$(PackagePlatform)</LongNamePlatform>
+ <LongNamePlatform Condition="'$(LongNamePlatform)'=='x64'">amd64</LongNamePlatform>
+ <CrossTargetPlatform>$(CrossTargetComponentFolder)</CrossTargetPlatform>
+ <CrossTargetPlatform Condition="'$(CrossTargetPlatform)'=='x64'">amd64</CrossTargetPlatform>
+ <LongNameSuffix>_$(LongNamePlatform)_$(LongNamePlatform)_$(MajorVersion).$(MinorVersion).$(BuildNumberMajor).0$(BuildNumberMinor)</LongNameSuffix>
+ <CrossTargetLongNameSuffix>_$(CrossTargetPlatform)_$(LongNamePlatform)_$(MajorVersion).$(MinorVersion).$(BuildNumberMajor).0$(BuildNumberMinor)</CrossTargetLongNameSuffix>
</PropertyGroup>
- <ItemGroup>
- <ProjectReference Include="win\Microsoft.NETCore.Jit.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="win\Microsoft.NETCore.Jit.pkgproj">
- <Platform>arm64</Platform>
- </ProjectReference>
- <ProjectReference Include="win\Microsoft.NETCore.Jit.pkgproj">
- <Platform>x86</Platform>
- </ProjectReference>
- <ProjectReference Include="win\Microsoft.NETCore.Jit.pkgproj">
- <Platform>arm</Platform>
- </ProjectReference>
- <ProjectReference Include="linux\Microsoft.NETCore.Jit.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="debian\Microsoft.NETCore.Jit.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="debian\Microsoft.NETCore.Jit.pkgproj">
- <Platform>armel</Platform>
- </ProjectReference>
- <ProjectReference Include="fedora\23\Microsoft.NETCore.Jit.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="fedora\24\Microsoft.NETCore.Jit.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="opensuse\13.2\Microsoft.NETCore.Jit.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="opensuse\42.1\Microsoft.NETCore.Jit.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="rhel\Microsoft.NETCore.Jit.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\14.04\Microsoft.NETCore.Jit.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\14.04\Microsoft.NETCore.Jit.pkgproj">
- <Platform>arm</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\16.04\Microsoft.NETCore.Jit.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\16.04\Microsoft.NETCore.Jit.pkgproj">
- <Platform>arm</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\16.10\Microsoft.NETCore.Jit.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="alpine\3.4.3\Microsoft.NETCore.Jit.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="tizen\4.0.0\Microsoft.NETCore.Jit.pkgproj">
- <Platform>armel</Platform>
- </ProjectReference>
- <ProjectReference Include="osx\Microsoft.NETCore.Jit.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- </ItemGroup>
+
+ <Import Condition="'$(_packageTargetOSGroup)' != ''" Project="$(MSBuildThisFileDirectory)runtime.$(_packageTargetOSGroup).$(MSBuildProjectName).props" />
+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Jit/alpine/3.4.3/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/alpine/3.4.3/Microsoft.NETCore.Jit.pkgproj
deleted file mode 100644
index 96851ff3ac..0000000000
--- a/src/.nuget/Microsoft.NETCore.Jit/alpine/3.4.3/Microsoft.NETCore.Jit.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>alpine.3.4.3-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libclrjit.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.Jit/debian/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/debian/Microsoft.NETCore.Jit.pkgproj
deleted file mode 100644
index db2a57c8c7..0000000000
--- a/src/.nuget/Microsoft.NETCore.Jit/debian/Microsoft.NETCore.Jit.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>debian.8-$(PackagePlatform)</PackageTargetRuntime>
- <!-- build for x64, armel -->
- <PackagePlatforms>x64;armel;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libclrjit.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Jit/fedora/23/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/fedora/23/Microsoft.NETCore.Jit.pkgproj
deleted file mode 100644
index 1dea18c33d..0000000000
--- a/src/.nuget/Microsoft.NETCore.Jit/fedora/23/Microsoft.NETCore.Jit.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>fedora.23-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libclrjit.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.Jit/fedora/24/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/fedora/24/Microsoft.NETCore.Jit.pkgproj
deleted file mode 100644
index 42f974ab96..0000000000
--- a/src/.nuget/Microsoft.NETCore.Jit/fedora/24/Microsoft.NETCore.Jit.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>fedora.24-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libclrjit.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.Jit/opensuse/13.2/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/opensuse/13.2/Microsoft.NETCore.Jit.pkgproj
deleted file mode 100644
index 28a8769d5e..0000000000
--- a/src/.nuget/Microsoft.NETCore.Jit/opensuse/13.2/Microsoft.NETCore.Jit.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>opensuse.13.2-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libclrjit.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.Jit/opensuse/42.1/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/opensuse/42.1/Microsoft.NETCore.Jit.pkgproj
deleted file mode 100644
index 930606c175..0000000000
--- a/src/.nuget/Microsoft.NETCore.Jit/opensuse/42.1/Microsoft.NETCore.Jit.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>opensuse.42.1-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libclrjit.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.Jit/rhel/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/rhel/Microsoft.NETCore.Jit.pkgproj
deleted file mode 100644
index fa9f58c81b..0000000000
--- a/src/.nuget/Microsoft.NETCore.Jit/rhel/Microsoft.NETCore.Jit.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>rhel.7-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libclrjit.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.Jit/linux/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/runtime.Linux.Microsoft.NETCore.Jit.props
index 541b81e4ab..cd0f45ea4f 100644
--- a/src/.nuget/Microsoft.NETCore.Jit/linux/Microsoft.NETCore.Jit.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.Jit/runtime.Linux.Microsoft.NETCore.Jit.props
@@ -1,12 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>linux-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
<ItemGroup>
<NativeSplittableBinary Include="$(BinDir)libclrjit.so" />
<ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
@@ -19,11 +12,10 @@
<AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
+ <ArchitectureSpecificNativeSymbol Include="..\_.pdb" />
<File Include="@(ArchitectureSpecificNativeSymbol)">
<TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
<IsSymbolFile>true</IsSymbolFile>
</File>
</ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.Jit/osx/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/runtime.OSX.Microsoft.NETCore.Jit.props
index 87e7e2bffd..310f2a12a5 100644
--- a/src/.nuget/Microsoft.NETCore.Jit/osx/Microsoft.NETCore.Jit.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.Jit/runtime.OSX.Microsoft.NETCore.Jit.props
@@ -1,12 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>osx.10.10-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
<ItemGroup>
<NativeSplittableBinary Include="$(BinDir)libclrjit.dylib" />
<ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
@@ -19,11 +12,10 @@
<AdditionalLibPackageExcludes Include="%2A%2A\%2A.dwarf" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dylib" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
+ <ArchitectureSpecificNativeSymbol Include="..\_.pdb" />
<File Include="@(ArchitectureSpecificNativeSymbol)">
<TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
<IsSymbolFile>true</IsSymbolFile>
</File>
</ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.Jit/win/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/runtime.Windows_NT.Microsoft.NETCore.Jit.props
index 66106c30dc..49a2164401 100644
--- a/src/.nuget/Microsoft.NETCore.Jit/win/Microsoft.NETCore.Jit.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.Jit/runtime.Windows_NT.Microsoft.NETCore.Jit.props
@@ -1,11 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>$(MinOSForArch)-$(PackagePlatform)</PackageTargetRuntime>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- </PropertyGroup>
<ItemGroup>
<ArchitectureSpecificNativeFile Include="$(BinDir)clrjit.dll" />
<ArchitectureSpecificNativeFile Condition="'$(PackagePlatform)' == 'x86'" Include="$(BinDir)compatjit.dll" />
@@ -25,7 +19,7 @@
<ArchitectureSpecificNativeSymbol Include="@(ArchitectureSpecificNativeFile -> '%(RelativeDir)PDB\%(FileName).pdb')" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
+ <ArchitectureSpecificNativeSymbol Include="..\_.pdb" />
<CrossArchitectureSpecificNativeSymbol Condition="'$(HasCrossTargetComponents)' == 'true'" Include="@(CrossArchitectureSpecificNativeFile -> '%(RelativeDir)PDB\%(FileName).pdb')" />
<File Include="@(ArchitectureSpecificNativeSymbol)">
<TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
@@ -36,5 +30,4 @@
<IsSymbolFile>true</IsSymbolFile>
</File>
</ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Jit/tizen/4.0.0/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/tizen/4.0.0/Microsoft.NETCore.Jit.pkgproj
deleted file mode 100644
index f2eaa55f3c..0000000000
--- a/src/.nuget/Microsoft.NETCore.Jit/tizen/4.0.0/Microsoft.NETCore.Jit.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>tizen.4.0.0-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for armel -->
- <PackagePlatforms>armel;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libclrjit.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Jit/ubuntu/14.04/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/ubuntu/14.04/Microsoft.NETCore.Jit.pkgproj
deleted file mode 100644
index 50d343f977..0000000000
--- a/src/.nuget/Microsoft.NETCore.Jit/ubuntu/14.04/Microsoft.NETCore.Jit.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>ubuntu.14.04-$(PackagePlatform)</PackageTargetRuntime>
- <!-- build for x64, arm -->
- <PackagePlatforms>x64;arm;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libclrjit.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Jit/ubuntu/16.04/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/ubuntu/16.04/Microsoft.NETCore.Jit.pkgproj
deleted file mode 100644
index e57b7c51d5..0000000000
--- a/src/.nuget/Microsoft.NETCore.Jit/ubuntu/16.04/Microsoft.NETCore.Jit.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>ubuntu.16.04-$(PackagePlatform)</PackageTargetRuntime>
- <!-- build for x64, arm -->
- <PackagePlatforms>x64;arm;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libclrjit.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Jit/ubuntu/16.10/Microsoft.NETCore.Jit.pkgproj b/src/.nuget/Microsoft.NETCore.Jit/ubuntu/16.10/Microsoft.NETCore.Jit.pkgproj
deleted file mode 100644
index 338d23372f..0000000000
--- a/src/.nuget/Microsoft.NETCore.Jit/ubuntu/16.10/Microsoft.NETCore.Jit.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>ubuntu.16.10-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libclrjit.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.Native/Microsoft.NETCore.Native.builds b/src/.nuget/Microsoft.NETCore.Native/Microsoft.NETCore.Native.builds
index a178ddb961..6318c1c0d1 100644
--- a/src/.nuget/Microsoft.NETCore.Native/Microsoft.NETCore.Native.builds
+++ b/src/.nuget/Microsoft.NETCore.Native/Microsoft.NETCore.Native.builds
@@ -1,65 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <Import Project="Microsoft.NETCore.Native.props" />
- <PropertyGroup>
- <!-- This property must be set to the same value as $(PackageOutputPath) for the nuspecs and nupkgs to be binplaced to the intended location. -->
- <OutputPath>$(PackageOutputPath)</OutputPath>
- </PropertyGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <!-- We always build the identity/redirection package. However, the platform specific runtime-*.nupkg is built based upon the target OS we are building the product for. -->
<ItemGroup>
- <Project Include="Microsoft.NETCore.Native.pkgproj">
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'linux-x64'" Include="linux/Microsoft.NETCore.Native.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'debian.8-x64'" Include="debian/Microsoft.NETCore.Native.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'fedora.23-x64'" Include="fedora/23/Microsoft.NETCore.Native.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'fedora.24-x64'" Include="fedora/24/Microsoft.NETCore.Native.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'opensuse.13.2-x64'" Include="opensuse/13.2/Microsoft.NETCore.Native.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'opensuse.42.1-x64'" Include="opensuse/42.1/Microsoft.NETCore.Native.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and $(DistroRid.StartsWith('rhel.7'))" Include="rhel/Microsoft.NETCore.Native.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.14.04-x64'" Include="ubuntu/14.04/Microsoft.NETCore.Native.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.16.04-x64'" Include="ubuntu/16.04/Microsoft.NETCore.Native.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.16.10-x64'" Include="ubuntu/16.10/Microsoft.NETCore.Native.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'alpine.3.4.3-x64'" Include="alpine/3.4.3/Microsoft.NETCore.Native.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsOSX)' == 'true'" Include="osx/Microsoft.NETCore.Native.pkgproj">
- <OSGroup>OSX</OSGroup>
- <Platform>amd64</Platform>
- </Project>
+ <!-- identity project, runtime specific projects are included by props above -->
+ <Project Include="$(MSBuildProjectName).pkgproj" />
</ItemGroup>
-
+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
-</Project>
+</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.Native/Microsoft.NETCore.Native.pkgproj b/src/.nuget/Microsoft.NETCore.Native/Microsoft.NETCore.Native.pkgproj
index 51b524a1c8..42ddfc9137 100644
--- a/src/.nuget/Microsoft.NETCore.Native/Microsoft.NETCore.Native.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.Native/Microsoft.NETCore.Native.pkgproj
@@ -1,50 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+ <Import Project="Microsoft.NETCore.Native.props" />
+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <SkipValidatePackage>true</SkipValidatePackage>
- <PackagePlatforms>x64;x86;arm64;arm;</PackagePlatforms>
- <OutputPath>$(PackagesOutputPath)</OutputPath>
- <IncludeRuntimeJson>true</IncludeRuntimeJson>
+
+ <PropertyGroup Condition="'$(PackageTargetRuntime)' == ''">
+ <IsLineupPackage Condition="'$(IsLineupPackage)' == ''">true</IsLineupPackage>
</PropertyGroup>
- <ItemGroup>
- <ProjectReference Include="linux\Microsoft.NETCore.Native.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="debian\Microsoft.NETCore.Native.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="fedora\23\Microsoft.NETCore.Native.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="fedora\24\Microsoft.NETCore.Native.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="opensuse\13.2\Microsoft.NETCore.Native.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="opensuse\42.1\Microsoft.NETCore.Native.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="rhel\Microsoft.NETCore.Native.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\14.04\Microsoft.NETCore.Native.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\16.04\Microsoft.NETCore.Native.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\16.10\Microsoft.NETCore.Native.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="alpine\3.4.3\Microsoft.NETCore.Native.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="osx\Microsoft.NETCore.Native.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- </ItemGroup>
+
+ <Import Condition="'$(_packageTargetOSGroup)' != ''" Project="$(MSBuildThisFileDirectory)runtime.$(_packageTargetOSGroup).$(MSBuildProjectName).props" />
+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Native/Microsoft.NETCore.Native.props b/src/.nuget/Microsoft.NETCore.Native/Microsoft.NETCore.Native.props
new file mode 100644
index 0000000000..ff2f587a1c
--- /dev/null
+++ b/src/.nuget/Microsoft.NETCore.Native/Microsoft.NETCore.Native.props
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <SupportedPackageOSGroups>Linux;OSX</SupportedPackageOSGroups>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.Native/alpine/3.4.3/Microsoft.NETCore.Native.pkgproj b/src/.nuget/Microsoft.NETCore.Native/alpine/3.4.3/Microsoft.NETCore.Native.pkgproj
deleted file mode 100644
index 90545a9001..0000000000
--- a/src/.nuget/Microsoft.NETCore.Native/alpine/3.4.3/Microsoft.NETCore.Native.pkgproj
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>alpine.3.4.3-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeBinary Include="$(BinDir)libSystem.Globalization.Native.a" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile);@(NativeBinary)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Native/debian/Microsoft.NETCore.Native.pkgproj b/src/.nuget/Microsoft.NETCore.Native/debian/Microsoft.NETCore.Native.pkgproj
deleted file mode 100644
index c136a2c057..0000000000
--- a/src/.nuget/Microsoft.NETCore.Native/debian/Microsoft.NETCore.Native.pkgproj
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>debian.8-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeBinary Include="$(BinDir)libSystem.Globalization.Native.a" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile);@(NativeBinary)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Native/fedora/23/Microsoft.NETCore.Native.pkgproj b/src/.nuget/Microsoft.NETCore.Native/fedora/23/Microsoft.NETCore.Native.pkgproj
deleted file mode 100644
index 8547114cdd..0000000000
--- a/src/.nuget/Microsoft.NETCore.Native/fedora/23/Microsoft.NETCore.Native.pkgproj
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>fedora.23-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeBinary Include="$(BinDir)libSystem.Globalization.Native.a" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile);@(NativeBinary)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Native/fedora/24/Microsoft.NETCore.Native.pkgproj b/src/.nuget/Microsoft.NETCore.Native/fedora/24/Microsoft.NETCore.Native.pkgproj
deleted file mode 100644
index f4987de01d..0000000000
--- a/src/.nuget/Microsoft.NETCore.Native/fedora/24/Microsoft.NETCore.Native.pkgproj
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>fedora.24-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeBinary Include="$(BinDir)libSystem.Globalization.Native.a" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile);@(NativeBinary)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Native/opensuse/13.2/Microsoft.NETCore.Native.pkgproj b/src/.nuget/Microsoft.NETCore.Native/opensuse/13.2/Microsoft.NETCore.Native.pkgproj
deleted file mode 100644
index bf8307a0b3..0000000000
--- a/src/.nuget/Microsoft.NETCore.Native/opensuse/13.2/Microsoft.NETCore.Native.pkgproj
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>opensuse.13.2-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeBinary Include="$(BinDir)libSystem.Globalization.Native.a" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile);@(NativeBinary)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Native/opensuse/42.1/Microsoft.NETCore.Native.pkgproj b/src/.nuget/Microsoft.NETCore.Native/opensuse/42.1/Microsoft.NETCore.Native.pkgproj
deleted file mode 100644
index 19ac91cd88..0000000000
--- a/src/.nuget/Microsoft.NETCore.Native/opensuse/42.1/Microsoft.NETCore.Native.pkgproj
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>opensuse.42.1-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeBinary Include="$(BinDir)libSystem.Globalization.Native.a" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile);@(NativeBinary)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Native/rhel/Microsoft.NETCore.Native.pkgproj b/src/.nuget/Microsoft.NETCore.Native/rhel/Microsoft.NETCore.Native.pkgproj
deleted file mode 100644
index f9dc309a6b..0000000000
--- a/src/.nuget/Microsoft.NETCore.Native/rhel/Microsoft.NETCore.Native.pkgproj
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>rhel.7-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeBinary Include="$(BinDir)libSystem.Globalization.Native.a" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile);@(NativeBinary)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Native/linux/Microsoft.NETCore.Native.pkgproj b/src/.nuget/Microsoft.NETCore.Native/runtime.Linux.Microsoft.NETCore.Native.props
index 8b1064f081..55a8deba19 100644
--- a/src/.nuget/Microsoft.NETCore.Native/linux/Microsoft.NETCore.Native.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.Native/runtime.Linux.Microsoft.NETCore.Native.props
@@ -1,12 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>linux-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
<ItemGroup>
<NativeBinary Include="$(BinDir)libSystem.Globalization.Native.a" />
<NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
@@ -20,11 +13,10 @@
<AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
+ <ArchitectureSpecificNativeSymbol Include="..\_.pdb" />
<File Include="@(ArchitectureSpecificNativeSymbol)">
<TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
<IsSymbolFile>true</IsSymbolFile>
</File>
</ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
+</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.Native/osx/Microsoft.NETCore.Native.pkgproj b/src/.nuget/Microsoft.NETCore.Native/runtime.OSX.Microsoft.NETCore.Native.props
index b358c86799..e338eb445e 100644
--- a/src/.nuget/Microsoft.NETCore.Native/osx/Microsoft.NETCore.Native.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.Native/runtime.OSX.Microsoft.NETCore.Native.props
@@ -1,12 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>osx.10.10-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
<ItemGroup>
<NativeBinary Include="$(BinDir)libSystem.Globalization.Native.a" />
<NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.dylib" />
@@ -20,11 +13,10 @@
<AdditionalLibPackageExcludes Include="%2A%2A\%2A.dwarf" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dylib" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
+ <ArchitectureSpecificNativeSymbol Include="..\_.pdb" />
<File Include="@(ArchitectureSpecificNativeSymbol)">
<TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
<IsSymbolFile>true</IsSymbolFile>
</File>
</ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
+</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.Native/ubuntu/14.04/Microsoft.NETCore.Native.pkgproj b/src/.nuget/Microsoft.NETCore.Native/ubuntu/14.04/Microsoft.NETCore.Native.pkgproj
deleted file mode 100644
index d1c5be74ff..0000000000
--- a/src/.nuget/Microsoft.NETCore.Native/ubuntu/14.04/Microsoft.NETCore.Native.pkgproj
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>ubuntu.14.04-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeBinary Include="$(BinDir)libSystem.Globalization.Native.a" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile);@(NativeBinary)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Native/ubuntu/16.04/Microsoft.NETCore.Native.pkgproj b/src/.nuget/Microsoft.NETCore.Native/ubuntu/16.04/Microsoft.NETCore.Native.pkgproj
deleted file mode 100644
index b2b0f96587..0000000000
--- a/src/.nuget/Microsoft.NETCore.Native/ubuntu/16.04/Microsoft.NETCore.Native.pkgproj
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>ubuntu.16.04-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeBinary Include="$(BinDir)libSystem.Globalization.Native.a" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile);@(NativeBinary)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Native/ubuntu/16.10/Microsoft.NETCore.Native.pkgproj b/src/.nuget/Microsoft.NETCore.Native/ubuntu/16.10/Microsoft.NETCore.Native.pkgproj
deleted file mode 100644
index da4a03d668..0000000000
--- a/src/.nuget/Microsoft.NETCore.Native/ubuntu/16.10/Microsoft.NETCore.Native.pkgproj
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>ubuntu.16.10-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeBinary Include="$(BinDir)libSystem.Globalization.Native.a" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile);@(NativeBinary)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/Microsoft.NETCore.Runtime.CoreCLR.builds b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/Microsoft.NETCore.Runtime.CoreCLR.builds
index 99bbbef6a1..dd00e039a6 100644
--- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/Microsoft.NETCore.Runtime.CoreCLR.builds
+++ b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/Microsoft.NETCore.Runtime.CoreCLR.builds
@@ -1,96 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <!-- This property must be set to the same value as $(PackageOutputPath) for the nuspecs and nupkgs to be binplaced to the intended location. -->
- <OutputPath>$(PackageOutputPath)</OutputPath>
- </PropertyGroup>
- <!-- We always build the identity/redirection package. However, the platform specific runtime-*.nupkg is built based upon the target OS we are building the product for. -->
<ItemGroup>
- <Project Include="Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>arm64</Platform>
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>x86</Platform>
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>arm</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'linux-x64'" Include="linux/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'debian.8-x64'" Include="debian/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'debian.8-armel'" Include="debian/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>armel</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'fedora.23-x64'" Include="fedora/23/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'fedora.24-x64'" Include="fedora/24/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'opensuse.13.2-x64'" Include="opensuse/13.2/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'opensuse.42.1-x64'" Include="opensuse/42.1/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and $(DistroRid.StartsWith('rhel.7'))" Include="rhel/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.14.04-x64'" Include="ubuntu/14.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.14.04-arm'" Include="ubuntu/14.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>arm</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.16.04-x64'" Include="ubuntu/16.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.16.04-arm'" Include="ubuntu/16.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>arm</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.16.10-x64'" Include="ubuntu/16.10/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'alpine.3.4.3-x64'" Include="alpine/3.4.3/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'tizen.4.0.0-armel'" Include="tizen/4.0.0/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>armel</Platform>
- </Project>
- <Project Condition="'$(TargetsOSX)' == 'true'" Include="osx/Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <OSGroup>OSX</OSGroup>
- <Platform>amd64</Platform>
- </Project>
+ <!-- identity project, runtime specific projects are included by props above -->
+ <Project Include="$(MSBuildProjectName).pkgproj" />
</ItemGroup>
-
+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
-</Project>
+</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
index bc4b86242b..b42a05595e 100644
--- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
@@ -1,75 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <SkipValidatePackage>true</SkipValidatePackage>
- <PackagePlatforms>x64;x86;arm64;arm;armel;</PackagePlatforms>
- <OutputPath>$(PackagesOutputPath)</OutputPath>
- <IncludeRuntimeJson>true</IncludeRuntimeJson>
+
+ <PropertyGroup Condition="'$(PackageTargetRuntime)' == ''">
+ <IsLineupPackage Condition="'$(IsLineupPackage)' == ''">true</IsLineupPackage>
</PropertyGroup>
- <ItemGroup>
- <ProjectReference Include="..\Microsoft.NETCore.Jit\Microsoft.NETCore.Jit.pkgproj" />
- <ProjectReference Include="win\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="win\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>arm64</Platform>
- </ProjectReference>
- <ProjectReference Include="win\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>x86</Platform>
- </ProjectReference>
- <ProjectReference Include="win\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>arm</Platform>
- </ProjectReference>
- <ProjectReference Include="linux\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="debian\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="debian\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>armel</Platform>
- </ProjectReference>
- <ProjectReference Include="fedora\23\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="fedora\24\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="opensuse\13.2\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="opensuse\42.1\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="rhel\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\14.04\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\14.04\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>arm</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\16.04\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\16.04\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>arm</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\16.10\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="alpine\3.4.3\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="tizen\4.0.0\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>armel</Platform>
- </ProjectReference>
- <ProjectReference Include="osx\Microsoft.NETCore.Runtime.CoreCLR.pkgproj">
- <Platform>amd64</Platform>
+
+ <ItemGroup Condition="'$(IsLineupPackage)' == 'true'">
+ <ProjectReference Include="..\Microsoft.NETCore.Jit\Microsoft.NETCore.Jit.pkgproj">
+ <AdditionalProperties>%(ProjectReference.AdditionalProperties);IsLineupPackage=false</AdditionalProperties>
</ProjectReference>
</ItemGroup>
+
+ <Import Condition="'$(_packageTargetOSGroup)' != ''" Project="$(MSBuildThisFileDirectory)runtime.$(_packageTargetOSGroup).$(MSBuildProjectName).props" />
+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/alpine/3.4.3/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/alpine/3.4.3/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
deleted file mode 100644
index c779349b7c..0000000000
--- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/alpine/3.4.3/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>alpine.3.4.3-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libcoreclr.so" />
- <NativeSplittableBinary Include="$(BinDir)libcoreclrtraceptprovider.so" />
- <NativeSplittableBinary Include="$(BinDir)libdbgshim.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordaccore.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordbi.so" />
- <NativeSplittableBinary Include="$(BinDir)libsos.so" />
- <NativeSplittableBinary Include="$(BinDir)libsosplugin.so" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)sosdocsunix.txt" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)mscorlib.ni.dll" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)System.Private.CoreLib.ni.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)mscorlib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)System.Private.CoreLib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)SOS.NETCore.dll" />
- <ArchitectureSpecificToolFile Include="$(BinDir)crossgen" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- <!-- Using lib/netstandard1.0 here. There is no TFM for this since it is a runtime itself. -->
- <File Include="@(ArchitectureSpecificLibFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/lib/netstandard1.0</TargetPath>
- </File>
- <!-- No reference: don't permit reference to the implementation from lib -->
- <File Include="$(PlaceholderFile)">
- <TargetPath>ref/netstandard1.0</TargetPath>
- </File>
- <File Include="@(ArchitectureSpecificToolFile)">
- <TargetPath>tools</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\sosdocsunix.txt" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\crossgen" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/debian/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/debian/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
deleted file mode 100644
index f982188fb3..0000000000
--- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/debian/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>debian.8-$(PackagePlatform)</PackageTargetRuntime>
- <!-- build for x64, armel -->
- <PackagePlatforms>x64;armel;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libcoreclr.so" />
- <NativeSplittableBinary Condition="'$(PackagePlatform)' != 'armel'" Include="$(BinDir)libcoreclrtraceptprovider.so" />
- <NativeSplittableBinary Include="$(BinDir)libdbgshim.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordaccore.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordbi.so" />
- <NativeSplittableBinary Include="$(BinDir)libsos.so" />
- <NativeSplittableBinary Include="$(BinDir)libsosplugin.so" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)sosdocsunix.txt" />
- <ArchitectureSpecificNativeFile Condition="'$(PackagePlatform)' != 'armel'" Include="$(BinDir)mscorlib.ni.dll" />
- <ArchitectureSpecificNativeFile Condition="'$(PackagePlatform)' != 'armel'" Include="$(BinDir)System.Private.CoreLib.ni.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)mscorlib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)System.Private.CoreLib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)SOS.NETCore.dll" />
- <ArchitectureSpecificToolFile Include="$(BinDir)crossgen" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- <!-- Using lib/netstandard1.0 here. There is no TFM for this since it is a runtime itself. -->
- <File Include="@(ArchitectureSpecificLibFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/lib/netstandard1.0</TargetPath>
- </File>
- <!-- No reference: don't permit reference to the implementation from lib -->
- <File Include="$(PlaceholderFile)">
- <TargetPath>ref/netstandard1.0</TargetPath>
- </File>
- <File Include="@(ArchitectureSpecificToolFile)">
- <TargetPath>tools</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\sosdocsunix.txt" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\crossgen" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/fedora/23/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/fedora/23/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
deleted file mode 100644
index a68fe2c0c6..0000000000
--- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/fedora/23/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>fedora.23-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libcoreclr.so" />
- <NativeSplittableBinary Include="$(BinDir)libcoreclrtraceptprovider.so" />
- <NativeSplittableBinary Include="$(BinDir)libdbgshim.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordaccore.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordbi.so" />
- <NativeSplittableBinary Include="$(BinDir)libsos.so" />
- <NativeSplittableBinary Include="$(BinDir)libsosplugin.so" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)sosdocsunix.txt" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)mscorlib.ni.dll" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)System.Private.CoreLib.ni.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)System.Private.CoreLib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)mscorlib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)SOS.NETCore.dll" />
- <ArchitectureSpecificToolFile Include="$(BinDir)crossgen" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- <!-- Using lib/netstandard1.0 here. There is no TFM for this since it is a runtime itself. -->
- <File Include="@(ArchitectureSpecificLibFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/lib/netstandard1.0</TargetPath>
- </File>
- <!-- No reference: don't permit reference to the implementation from lib -->
- <File Include="$(PlaceholderFile)">
- <TargetPath>ref/netstandard1.0</TargetPath>
- </File>
- <File Include="@(ArchitectureSpecificToolFile)">
- <TargetPath>tools</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\sosdocsunix.txt" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\crossgen" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/fedora/24/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/fedora/24/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
deleted file mode 100644
index d19a1dd80f..0000000000
--- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/fedora/24/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>fedora.24-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libcoreclr.so" />
- <NativeSplittableBinary Include="$(BinDir)libcoreclrtraceptprovider.so" />
- <NativeSplittableBinary Include="$(BinDir)libdbgshim.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordaccore.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordbi.so" />
- <NativeSplittableBinary Include="$(BinDir)libsos.so" />
- <NativeSplittableBinary Include="$(BinDir)libsosplugin.so" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)sosdocsunix.txt" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)mscorlib.ni.dll" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)System.Private.CoreLib.ni.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)System.Private.CoreLib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)mscorlib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)SOS.NETCore.dll" />
- <ArchitectureSpecificToolFile Include="$(BinDir)crossgen" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- <!-- Using lib/netstandard1.0 here. There is no TFM for this since it is a runtime itself. -->
- <File Include="@(ArchitectureSpecificLibFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/lib/netstandard1.0</TargetPath>
- </File>
- <!-- No reference: don't permit reference to the implementation from lib -->
- <File Include="$(PlaceholderFile)">
- <TargetPath>ref/netstandard1.0</TargetPath>
- </File>
- <File Include="@(ArchitectureSpecificToolFile)">
- <TargetPath>tools</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\sosdocsunix.txt" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\crossgen" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/linux/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/linux/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
deleted file mode 100644
index 31e719601d..0000000000
--- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/linux/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>linux-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libcoreclr.so" />
- <NativeSplittableBinary Include="$(BinDir)libcoreclrtraceptprovider.so" />
- <NativeSplittableBinary Include="$(BinDir)libdbgshim.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordaccore.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordbi.so" />
- <NativeSplittableBinary Include="$(BinDir)libsos.so" />
- <NativeSplittableBinary Include="$(BinDir)libsosplugin.so" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)sosdocsunix.txt" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)mscorlib.ni.dll" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)System.Private.CoreLib.ni.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)System.Private.CoreLib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)mscorlib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)SOS.NETCore.dll" />
- <ArchitectureSpecificToolFile Include="$(BinDir)crossgen" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- <!-- Using lib/netstandard1.0 here. There is no TFM for this since it is a runtime itself. -->
- <File Include="@(ArchitectureSpecificLibFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/lib/netstandard1.0</TargetPath>
- </File>
- <!-- No reference: don't permit reference to the implementation from lib -->
- <File Include="$(PlaceholderFile)">
- <TargetPath>ref/netstandard1.0</TargetPath>
- </File>
- <File Include="@(ArchitectureSpecificToolFile)">
- <TargetPath>tools</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\sosdocsunix.txt" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\crossgen" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/opensuse/13.2/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/opensuse/13.2/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
deleted file mode 100644
index e5c70c93da..0000000000
--- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/opensuse/13.2/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>opensuse.13.2-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libcoreclr.so" />
- <NativeSplittableBinary Include="$(BinDir)libcoreclrtraceptprovider.so" />
- <NativeSplittableBinary Include="$(BinDir)libdbgshim.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordaccore.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordbi.so" />
- <NativeSplittableBinary Include="$(BinDir)libsos.so" />
- <NativeSplittableBinary Include="$(BinDir)libsosplugin.so" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)sosdocsunix.txt" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)mscorlib.ni.dll" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)System.Private.CoreLib.ni.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)System.Private.CoreLib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)mscorlib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)SOS.NETCore.dll" />
- <ArchitectureSpecificToolFile Include="$(BinDir)crossgen" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- <!-- Using lib/netstandard1.0 here. There is no TFM for this since it is a runtime itself. -->
- <File Include="@(ArchitectureSpecificLibFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/lib/netstandard1.0</TargetPath>
- </File>
- <!-- No reference: don't permit reference to the implementation from lib -->
- <File Include="$(PlaceholderFile)">
- <TargetPath>ref/netstandard1.0</TargetPath>
- </File>
- <File Include="@(ArchitectureSpecificToolFile)">
- <TargetPath>tools</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\sosdocsunix.txt" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\crossgen" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/opensuse/42.1/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/opensuse/42.1/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
deleted file mode 100644
index 990a0526c5..0000000000
--- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/opensuse/42.1/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>opensuse.42.1-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libcoreclr.so" />
- <NativeSplittableBinary Include="$(BinDir)libcoreclrtraceptprovider.so" />
- <NativeSplittableBinary Include="$(BinDir)libdbgshim.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordaccore.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordbi.so" />
- <NativeSplittableBinary Include="$(BinDir)libsos.so" />
- <NativeSplittableBinary Include="$(BinDir)libsosplugin.so" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)sosdocsunix.txt" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)mscorlib.ni.dll" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)System.Private.CoreLib.ni.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)System.Private.CoreLib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)mscorlib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)SOS.NETCore.dll" />
- <ArchitectureSpecificToolFile Include="$(BinDir)crossgen" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- <!-- Using lib/netstandard1.0 here. There is no TFM for this since it is a runtime itself. -->
- <File Include="@(ArchitectureSpecificLibFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/lib/netstandard1.0</TargetPath>
- </File>
- <!-- No reference: don't permit reference to the implementation from lib -->
- <File Include="$(PlaceholderFile)">
- <TargetPath>ref/netstandard1.0</TargetPath>
- </File>
- <File Include="@(ArchitectureSpecificToolFile)">
- <TargetPath>tools</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\sosdocsunix.txt" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\crossgen" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/rhel/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/rhel/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
deleted file mode 100644
index f12793fe73..0000000000
--- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/rhel/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>rhel.7-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libcoreclr.so" />
- <NativeSplittableBinary Include="$(BinDir)libcoreclrtraceptprovider.so" />
- <NativeSplittableBinary Include="$(BinDir)libdbgshim.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordaccore.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordbi.so" />
- <NativeSplittableBinary Include="$(BinDir)libsos.so" />
- <NativeSplittableBinary Include="$(BinDir)libsosplugin.so" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)sosdocsunix.txt" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)mscorlib.ni.dll" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)System.Private.CoreLib.ni.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)System.Private.CoreLib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)mscorlib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)SOS.NETCore.dll" />
- <ArchitectureSpecificToolFile Include="$(BinDir)crossgen" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- <!-- Using lib/netstandard1.0 here. There is no TFM for this since it is a runtime itself. -->
- <File Include="@(ArchitectureSpecificLibFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/lib/netstandard1.0</TargetPath>
- </File>
- <!-- No reference: don't permit reference to the implementation from lib -->
- <File Include="$(PlaceholderFile)">
- <TargetPath>ref/netstandard1.0</TargetPath>
- </File>
- <File Include="@(ArchitectureSpecificToolFile)">
- <TargetPath>tools</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\sosdocsunix.txt" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\crossgen" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/tizen/4.0.0/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/runtime.Linux.Microsoft.NETCore.Runtime.CoreCLR.props
index dd2c46b077..ae9b34b124 100644
--- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/tizen/4.0.0/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/runtime.Linux.Microsoft.NETCore.Runtime.CoreCLR.props
@@ -1,14 +1,8 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>tizen.4.0.0-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for armel -->
- <PackagePlatforms>armel;</PackagePlatforms>
- </PropertyGroup>
<ItemGroup>
<NativeSplittableBinary Include="$(BinDir)libcoreclr.so" />
+ <NativeSplittableBinary Condition="'$(Platform)' != 'armel'" Include="$(BinDir)libcoreclrtraceptprovider.so" />
<NativeSplittableBinary Include="$(BinDir)libdbgshim.so" />
<NativeSplittableBinary Include="$(BinDir)libmscordaccore.so" />
<NativeSplittableBinary Include="$(BinDir)libmscordbi.so" />
@@ -16,10 +10,8 @@
<NativeSplittableBinary Include="$(BinDir)libsosplugin.so" />
<NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
<ArchitectureSpecificNativeFile Include="$(BinDir)sosdocsunix.txt" />
- <!-- cannot generate in build now
- <ArchitectureSpecificNativeFile Include="$(BinDir)mscorlib.ni.dll" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)System.Private.CoreLib.ni.dll" />
- -->
+ <ArchitectureSpecificNativeFile Condition="'$(Platform)' != 'armel'" Include="$(BinDir)mscorlib.ni.dll" />
+ <ArchitectureSpecificNativeFile Condition="'$(Platform)' != 'armel'" Include="$(BinDir)System.Private.CoreLib.ni.dll" />
<ArchitectureSpecificLibFile Include="$(BinDir)mscorlib.dll" />
<ArchitectureSpecificLibFile Include="$(BinDir)System.Private.CoreLib.dll" />
<ArchitectureSpecificLibFile Include="$(BinDir)SOS.NETCore.dll" />
@@ -47,11 +39,10 @@
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\sosdocsunix.txt" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\crossgen" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
+ <ArchitectureSpecificNativeSymbol Include="..\_.pdb" />
<File Include="@(ArchitectureSpecificNativeSymbol)">
<TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
<IsSymbolFile>true</IsSymbolFile>
</File>
</ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
+</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/osx/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/runtime.OSX.Microsoft.NETCore.Runtime.CoreCLR.props
index 6425e8b6f1..f8709fc55c 100644
--- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/osx/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/runtime.OSX.Microsoft.NETCore.Runtime.CoreCLR.props
@@ -1,12 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>osx.10.10-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
<ItemGroup>
<NativeSplittableBinary Include="$(BinDir)libcoreclr.dylib" />
<NativeSplittableBinary Include="$(BinDir)libdbgshim.dylib" />
@@ -44,11 +37,11 @@
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\sosdocsunix.txt" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\crossgen" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
+ <ArchitectureSpecificNativeSymbol Include="..\_.pdb" />
<File Include="@(ArchitectureSpecificNativeSymbol)">
<TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
<IsSymbolFile>true</IsSymbolFile>
</File>
</ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
+
+</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/win/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/runtime.Windows_NT.Microsoft.NETCore.Runtime.CoreCLR.props
index 844fb0b10f..533864ce87 100644
--- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/win/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/runtime.Windows_NT.Microsoft.NETCore.Runtime.CoreCLR.props
@@ -1,10 +1,7 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
-
<PropertyGroup>
<PackageTargetRuntime>$(MinOSForArch)-$(PackagePlatform)</PackageTargetRuntime>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
<LongNamePlatform>$(PackagePlatform)</LongNamePlatform>
<LongNamePlatform Condition="'$(LongNamePlatform)'=='x64'">amd64</LongNamePlatform>
<CrossTargetPlatform>$(CrossTargetComponentFolder)</CrossTargetPlatform>
@@ -94,6 +91,4 @@
<IsSymbolFile>true</IsSymbolFile>
</File>
</ItemGroup>
-
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/14.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/14.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
deleted file mode 100644
index 86cb61a264..0000000000
--- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/14.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>ubuntu.14.04-$(PackagePlatform)</PackageTargetRuntime>
- <!-- build for x64, arm -->
- <PackagePlatforms>x64;arm;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libcoreclr.so" />
- <NativeSplittableBinary Condition="'$(PackagePlatform)' != 'arm'" Include="$(BinDir)libcoreclrtraceptprovider.so" />
- <NativeSplittableBinary Include="$(BinDir)libdbgshim.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordaccore.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordbi.so" />
- <NativeSplittableBinary Include="$(BinDir)libsos.so" />
- <NativeSplittableBinary Include="$(BinDir)libsosplugin.so" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)sosdocsunix.txt" />
- <ArchitectureSpecificNativeFile Condition="'$(PackagePlatform)'!='arm'" Include="$(BinDir)mscorlib.ni.dll" />
- <ArchitectureSpecificNativeFile Condition="'$(PackagePlatform)'!='arm'" Include="$(BinDir)System.Private.CoreLib.ni.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)System.Private.CoreLib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)mscorlib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)SOS.NETCore.dll" />
- <ArchitectureSpecificToolFile Include="$(BinDir)crossgen" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- <!-- Using lib/netstandard1.0 here. There is no TFM for this since it is a runtime itself. -->
- <File Include="@(ArchitectureSpecificLibFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/lib/netstandard1.0</TargetPath>
- </File>
- <!-- No reference: don't permit reference to the implementation from lib -->
- <File Include="$(PlaceholderFile)">
- <TargetPath>ref/netstandard1.0</TargetPath>
- </File>
- <File Include="@(ArchitectureSpecificToolFile)">
- <TargetPath>tools</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\sosdocsunix.txt" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\crossgen" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/16.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/16.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
deleted file mode 100644
index 72c48ee459..0000000000
--- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/16.04/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>ubuntu.16.04-$(PackagePlatform)</PackageTargetRuntime>
- <!-- build for x64, arm -->
- <PackagePlatforms>x64;arm;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libcoreclr.so" />
- <NativeSplittableBinary Condition="'$(PackagePlatform)' != 'arm'" Include="$(BinDir)libcoreclrtraceptprovider.so" />
- <NativeSplittableBinary Include="$(BinDir)libdbgshim.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordaccore.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordbi.so" />
- <NativeSplittableBinary Include="$(BinDir)libsos.so" />
- <NativeSplittableBinary Include="$(BinDir)libsosplugin.so" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)sosdocsunix.txt" />
- <ArchitectureSpecificNativeFile Condition="'$(PackagePlatform)' != 'arm'" Include="$(BinDir)mscorlib.ni.dll" />
- <ArchitectureSpecificNativeFile Condition="'$(PackagePlatform)' != 'arm'" Include="$(BinDir)System.Private.CoreLib.ni.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)System.Private.CoreLib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)mscorlib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)SOS.NETCore.dll" />
- <ArchitectureSpecificToolFile Include="$(BinDir)crossgen" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- <!-- Using lib/netstandard1.0 here. There is no TFM for this since it is a runtime itself. -->
- <File Include="@(ArchitectureSpecificLibFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/lib/netstandard1.0</TargetPath>
- </File>
- <!-- No reference: don't permit reference to the implementation from lib -->
- <File Include="$(PlaceholderFile)">
- <TargetPath>ref/netstandard1.0</TargetPath>
- </File>
- <File Include="@(ArchitectureSpecificToolFile)">
- <TargetPath>tools</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\sosdocsunix.txt" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\crossgen" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/16.10/Microsoft.NETCore.Runtime.CoreCLR.pkgproj b/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/16.10/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
deleted file mode 100644
index 9f226f8530..0000000000
--- a/src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/ubuntu/16.10/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>ubuntu.16.10-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)libcoreclr.so" />
- <NativeSplittableBinary Include="$(BinDir)libcoreclrtraceptprovider.so" />
- <NativeSplittableBinary Include="$(BinDir)libdbgshim.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordaccore.so" />
- <NativeSplittableBinary Include="$(BinDir)libmscordbi.so" />
- <NativeSplittableBinary Include="$(BinDir)libsos.so" />
- <NativeSplittableBinary Include="$(BinDir)libsosplugin.so" />
- <NativeSplittableBinary Include="$(BinDir)System.Globalization.Native.so" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)sosdocsunix.txt" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)mscorlib.ni.dll" />
- <ArchitectureSpecificNativeFile Include="$(BinDir)System.Private.CoreLib.ni.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)System.Private.CoreLib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)mscorlib.dll" />
- <ArchitectureSpecificLibFile Include="$(BinDir)SOS.NETCore.dll" />
- <ArchitectureSpecificToolFile Include="$(BinDir)crossgen" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- <!-- Using lib/netstandard1.0 here. There is no TFM for this since it is a runtime itself. -->
- <File Include="@(ArchitectureSpecificLibFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/lib/netstandard1.0</TargetPath>
- </File>
- <!-- No reference: don't permit reference to the implementation from lib -->
- <File Include="$(PlaceholderFile)">
- <TargetPath>ref/netstandard1.0</TargetPath>
- </File>
- <File Include="@(ArchitectureSpecificToolFile)">
- <TargetPath>tools</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\sosdocsunix.txt" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\crossgen" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.builds b/src/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.builds
index 67b105ba76..c55af3a6d3 100644
--- a/src/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.builds
+++ b/src/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.builds
@@ -2,96 +2,10 @@
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <!-- This property must be set to the same value as $(PackageOutputPath) for the nuspecs and nupkgs to be binplaced to the intended location. -->
- <OutputPath>$(PackageOutputPath)</OutputPath>
- </PropertyGroup>
-
- <!-- We always build the identity/redirection package. However, the platform specific runtime-*.nupkg is built based upon the target OS we are building the product for. -->
<ItemGroup>
- <Project Include="Microsoft.NETCore.TestHost.pkgproj">
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>arm64</Platform>
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>x86</Platform>
- </Project>
- <Project Condition="'$(TargetsWindows)' == 'true'" Include="win/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>Windows_NT</OSGroup>
- <Platform>arm</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'linux-x64'" Include="linux/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'debian.8-x64'" Include="debian/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'debian.8-armel'" Include="debian/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>armel</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'fedora.23-x64'" Include="fedora/23/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'fedora.24-x64'" Include="fedora/24/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'opensuse.13.2-x64'" Include="opensuse/13.2/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'opensuse.42.1-x64'" Include="opensuse/42.1/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and $(DistroRid.StartsWith('rhel.7'))" Include="rhel/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.14.04-x64'" Include="ubuntu/14.04/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.14.04-arm'" Include="ubuntu/14.04/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>arm</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.16.04-x64'" Include="ubuntu/16.04/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.16.04-arm'" Include="ubuntu/16.04/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>arm</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'ubuntu.16.10-x64'" Include="ubuntu/16.10/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'alpine.3.4.3-x64'" Include="alpine/3.4.3/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>amd64</Platform>
- </Project>
- <Project Condition="'$(TargetsLinux)' == 'true' and '$(DistroRid)' == 'tizen.4.0.0-armel'" Include="tizen/4.0.0/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>Linux</OSGroup>
- <Platform>armel</Platform>
- </Project>
- <Project Condition="'$(TargetsOSX)' == 'true'" Include="osx/Microsoft.NETCore.TestHost.pkgproj">
- <OSGroup>OSX</OSGroup>
- <Platform>amd64</Platform>
- </Project>
+ <!-- identity project, runtime specific projects are included by props above -->
+ <Project Include="$(MSBuildProjectName).pkgproj" />
</ItemGroup>
-
+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
</Project>
diff --git a/src/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.pkgproj
index ee8f6a94c4..909206b58b 100644
--- a/src/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.pkgproj
@@ -1,74 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <SkipValidatePackage>true</SkipValidatePackage>
- <PackagePlatforms>x64;x86;arm64;arm;armel;</PackagePlatforms>
- <OutputPath>$(PackagesOutputPath)</OutputPath>
- <IncludeRuntimeJson>true</IncludeRuntimeJson>
+
+ <PropertyGroup Condition="'$(PackageTargetRuntime)' == ''">
+ <IsLineupPackage Condition="'$(IsLineupPackage)' == ''">true</IsLineupPackage>
</PropertyGroup>
- <ItemGroup>
- <ProjectReference Include="win\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="win\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>arm64</Platform>
- </ProjectReference>
- <ProjectReference Include="win\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>x86</Platform>
- </ProjectReference>
- <ProjectReference Include="win\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>arm</Platform>
- </ProjectReference>
- <ProjectReference Include="linux\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="debian\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="debian\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>armel</Platform>
- </ProjectReference>
- <ProjectReference Include="fedora\23\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="fedora\24\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="opensuse\13.2\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="opensuse\42.1\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="rhel\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\14.04\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\14.04\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>arm</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\16.04\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\16.04\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>arm</Platform>
- </ProjectReference>
- <ProjectReference Include="ubuntu\16.10\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="alpine\3.4.3\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- <ProjectReference Include="tizen\4.0.0\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>armel</Platform>
- </ProjectReference>
- <ProjectReference Include="osx\Microsoft.NETCore.TestHost.pkgproj">
- <Platform>amd64</Platform>
- </ProjectReference>
- </ItemGroup>
+
+ <Import Condition="'$(_packageTargetOSGroup)' != ''" Project="$(MSBuildThisFileDirectory)runtime.$(_packageTargetOSGroup).$(MSBuildProjectName).props" />
+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
diff --git a/src/.nuget/Microsoft.NETCore.TestHost/alpine/3.4.3/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/alpine/3.4.3/Microsoft.NETCore.TestHost.pkgproj
deleted file mode 100644
index dd142f6711..0000000000
--- a/src/.nuget/Microsoft.NETCore.TestHost/alpine/3.4.3/Microsoft.NETCore.TestHost.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>alpine.3.4.3-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)corerun" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.TestHost/debian/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/debian/Microsoft.NETCore.TestHost.pkgproj
deleted file mode 100644
index 5d739bd58d..0000000000
--- a/src/.nuget/Microsoft.NETCore.TestHost/debian/Microsoft.NETCore.TestHost.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>debian.8-$(PackagePlatform)</PackageTargetRuntime>
- <!-- build for x64, armel -->
- <PackagePlatforms>x64;armel;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)corerun" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.TestHost/fedora/23/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/fedora/23/Microsoft.NETCore.TestHost.pkgproj
deleted file mode 100644
index 2edb86a28a..0000000000
--- a/src/.nuget/Microsoft.NETCore.TestHost/fedora/23/Microsoft.NETCore.TestHost.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>fedora.23-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)corerun" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.TestHost/fedora/24/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/fedora/24/Microsoft.NETCore.TestHost.pkgproj
deleted file mode 100644
index 219026c703..0000000000
--- a/src/.nuget/Microsoft.NETCore.TestHost/fedora/24/Microsoft.NETCore.TestHost.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>fedora.24-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)corerun" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.TestHost/opensuse/13.2/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/opensuse/13.2/Microsoft.NETCore.TestHost.pkgproj
deleted file mode 100644
index 31740920e0..0000000000
--- a/src/.nuget/Microsoft.NETCore.TestHost/opensuse/13.2/Microsoft.NETCore.TestHost.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>opensuse.13.2-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)corerun" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.TestHost/opensuse/42.1/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/opensuse/42.1/Microsoft.NETCore.TestHost.pkgproj
deleted file mode 100644
index 8aaec62373..0000000000
--- a/src/.nuget/Microsoft.NETCore.TestHost/opensuse/42.1/Microsoft.NETCore.TestHost.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>opensuse.42.1-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)corerun" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.TestHost/rhel/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/rhel/Microsoft.NETCore.TestHost.pkgproj
deleted file mode 100644
index 1cfaf50d5d..0000000000
--- a/src/.nuget/Microsoft.NETCore.TestHost/rhel/Microsoft.NETCore.TestHost.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>rhel.7-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)corerun" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.TestHost/linux/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/runtime.Linux.Microsoft.NETCore.TestHost.props
index 06a6f4ce10..c48d595254 100644
--- a/src/.nuget/Microsoft.NETCore.TestHost/linux/Microsoft.NETCore.TestHost.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.TestHost/runtime.Linux.Microsoft.NETCore.TestHost.props
@@ -1,12 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>linux-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
<ItemGroup>
<NativeSplittableBinary Include="$(BinDir)corerun" />
<ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
@@ -19,11 +12,10 @@
<AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
+ <ArchitectureSpecificNativeSymbol Include="..\_.pdb" />
<File Include="@(ArchitectureSpecificNativeSymbol)">
<TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
<IsSymbolFile>true</IsSymbolFile>
</File>
</ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.TestHost/osx/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/runtime.OSX.Microsoft.NETCore.TestHost.props
index cbcc805d8d..b1cc2f8eef 100644
--- a/src/.nuget/Microsoft.NETCore.TestHost/osx/Microsoft.NETCore.TestHost.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.TestHost/runtime.OSX.Microsoft.NETCore.TestHost.props
@@ -1,12 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>osx.10.10-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
<ItemGroup>
<NativeSplittableBinary Include="$(BinDir)corerun" />
<ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
@@ -19,11 +12,10 @@
<AdditionalLibPackageExcludes Include="%2A%2A\%2A.dwarf" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dylib" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
+ <ArchitectureSpecificNativeSymbol Include="..\_.pdb" />
<File Include="@(ArchitectureSpecificNativeSymbol)">
<TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
<IsSymbolFile>true</IsSymbolFile>
</File>
</ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.NETCore.TestHost/win/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/runtime.Windows_NT.Microsoft.NETCore.TestHost.props
index 33ab15fb62..bab9b9f8ba 100644
--- a/src/.nuget/Microsoft.NETCore.TestHost/win/Microsoft.NETCore.TestHost.pkgproj
+++ b/src/.nuget/Microsoft.NETCore.TestHost/runtime.Windows_NT.Microsoft.NETCore.TestHost.props
@@ -1,9 +1,7 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<PackageTargetRuntime>$(MinOSForArch)-$(PackagePlatform)</PackageTargetRuntime>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
</PropertyGroup>
<ItemGroup>
<ArchitectureSpecificNativeFile Include="$(BinDir)CoreRun.exe" />
@@ -14,11 +12,10 @@
<ItemGroup>
<ArchitectureSpecificNativeSymbol Include="@(ArchitectureSpecificNativeFile -> '%(RelativeDir)PDB\%(FileName).pdb')" />
<AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\_.pdb" />
+ <ArchitectureSpecificNativeSymbol Include="..\_.pdb" />
<File Include="@(ArchitectureSpecificNativeSymbol)">
<TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
<IsSymbolFile>true</IsSymbolFile>
</File>
</ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/.nuget/Microsoft.NETCore.TestHost/tizen/4.0.0/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/tizen/4.0.0/Microsoft.NETCore.TestHost.pkgproj
deleted file mode 100644
index b7620b9806..0000000000
--- a/src/.nuget/Microsoft.NETCore.TestHost/tizen/4.0.0/Microsoft.NETCore.TestHost.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>tizen.4.0.0-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for armel -->
- <PackagePlatforms>armel;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)corerun" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.TestHost/ubuntu/14.04/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/ubuntu/14.04/Microsoft.NETCore.TestHost.pkgproj
deleted file mode 100644
index 8750e16817..0000000000
--- a/src/.nuget/Microsoft.NETCore.TestHost/ubuntu/14.04/Microsoft.NETCore.TestHost.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>ubuntu.14.04-$(PackagePlatform)</PackageTargetRuntime>
- <!-- build for x64, arm -->
- <PackagePlatforms>x64;arm;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)corerun" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.TestHost/ubuntu/16.04/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/ubuntu/16.04/Microsoft.NETCore.TestHost.pkgproj
deleted file mode 100644
index 3f1397f92f..0000000000
--- a/src/.nuget/Microsoft.NETCore.TestHost/ubuntu/16.04/Microsoft.NETCore.TestHost.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>ubuntu.16.04-$(PackagePlatform)</PackageTargetRuntime>
- <!-- build for x64, arm -->
- <PackagePlatforms>x64;arm;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)corerun" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/src/.nuget/Microsoft.NETCore.TestHost/ubuntu/16.10/Microsoft.NETCore.TestHost.pkgproj b/src/.nuget/Microsoft.NETCore.TestHost/ubuntu/16.10/Microsoft.NETCore.TestHost.pkgproj
deleted file mode 100644
index 88ad98a4db..0000000000
--- a/src/.nuget/Microsoft.NETCore.TestHost/ubuntu/16.10/Microsoft.NETCore.TestHost.pkgproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <SkipPackageFileCheck>true</SkipPackageFileCheck>
- <PackageTargetRuntime>ubuntu.16.10-$(PackagePlatform)</PackageTargetRuntime>
- <!-- only build for x64 -->
- <PackagePlatforms>x64;</PackagePlatforms>
- </PropertyGroup>
- <ItemGroup>
- <NativeSplittableBinary Include="$(BinDir)corerun" />
- <ArchitectureSpecificNativeFile Include="@(NativeSplittableBinary)" />
- <File Include="@(ArchitectureSpecificNativeFile)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- </File>
- </ItemGroup>
- <ItemGroup Condition="'$(__BuildType)' == 'Release'">
- <ArchitectureSpecificNativeSymbol Include="@(NativeSplittableBinary -> '%(Identity).dbg')" />
- <AdditionalLibPackageExcludes Include="%2A%2A\%2A.dbg" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.so" />
- <AdditionalSymbolPackageExcludes Include="%2A%2A\%2A.dll" />
- <ArchitectureSpecificNativeSymbol Include="..\..\..\_.pdb" />
- <File Include="@(ArchitectureSpecificNativeSymbol)">
- <TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
- <IsSymbolFile>true</IsSymbolFile>
- </File>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project> \ No newline at end of file
diff --git a/src/.nuget/Microsoft.TargetingPack.Private.CoreCLR/Microsoft.TargetingPack.Private.CoreCLR.pkgproj b/src/.nuget/Microsoft.TargetingPack.Private.CoreCLR/Microsoft.TargetingPack.Private.CoreCLR.pkgproj
index 253cba083d..27a4f21534 100644
--- a/src/.nuget/Microsoft.TargetingPack.Private.CoreCLR/Microsoft.TargetingPack.Private.CoreCLR.pkgproj
+++ b/src/.nuget/Microsoft.TargetingPack.Private.CoreCLR/Microsoft.TargetingPack.Private.CoreCLR.pkgproj
@@ -4,7 +4,6 @@
<PropertyGroup>
<SkipPackageFileCheck>true</SkipPackageFileCheck>
<SkipValidatePackage>true</SkipValidatePackage>
- <PackagePlatforms>x64;</PackagePlatforms>
<OutputPath>$(PackagesOutputPath)</OutputPath>
</PropertyGroup>
<ItemGroup>
diff --git a/src/.nuget/dir.props b/src/.nuget/dir.props
new file mode 100644
index 0000000000..bdae27a40a
--- /dev/null
+++ b/src/.nuget/dir.props
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildThisFileDirectory)..\..\dir.props" />
+
+ <PropertyGroup>
+ <!-- defined in buildtools packaging.targets, but we need this before targets are imported -->
+ <PackagePlatform>AnyCPU</PackagePlatform>
+
+ <!-- Distro rid is passed as runtimeos-arch-->
+ <_parseDistroRid>$(__DistroRid)</_parseDistroRid>
+ <_parseDistroRid Condition="'$(_parseDistroRid)' == '' and '$(__BuildOS)' == 'OSX'">osx.10.10-x64</_parseDistroRid>
+ <_distroRidIndex>$(_parseDistroRid.IndexOfAny("-"))</_distroRidIndex>
+ <_archRidIndex>$([MSBuild]::Add($(_distroRidIndex), 1))</_archRidIndex>
+ <OSRid Condition="'$(OSRid)' == '' and '$(_distroRidIndex)' != '-1'">$(_parseDistroRid.SubString(0, $(_distroRidIndex)))</OSRid>
+ <OSRid Condition="'$(OSRid)' == ''">win10</OSRid>
+
+ <ArchGroup Condition="'$(ArchGroup)' == '' and '$(_archRidIndex)' != '0'">$(_parseDistroRid.SubString($(_archRidIndex)))</ArchGroup>
+ <ArchGroup Condition="'$(ArchGroup)' == '' and '$(Platform)' != ''">$(Platform)</ArchGroup>
+ <ArchGroup Condition="'$(ArchGroup)' == ''">$(BuildArch)</ArchGroup>
+
+ <RuntimeOS Condition="'$(RuntimeOS)' == ''">$(OSRid)</RuntimeOS>
+
+ <SupportedPackageOSGroups Condition="'$(SupportedPackageOSGroups)' == ''">Windows_NT;OSX;Linux</SupportedPackageOSGroups>
+ <SupportedPackageOSGroups>;$(SupportedPackageOSGroups);</SupportedPackageOSGroups>
+
+ <_runtimeOSVersionIndex>$(RuntimeOS.IndexOfAny(".-0123456789"))</_runtimeOSVersionIndex>
+ <_runtimeOSFamily Condition="'$(_runtimeOSVersionIndex)' != '-1'">$(RuntimeOS.SubString(0, $(_runtimeOSVersionIndex)))</_runtimeOSFamily>
+ <_isSupportedOSGroup>true</_isSupportedOSGroup>
+ </PropertyGroup>
+
+ <!-- derive an OS Group based on the OS Family -->
+ <PropertyGroup>
+ <_derivedPackageTargetOSGroup Condition="'$(_derivedPackageTargetOSGroup)' == '' and '$(_runtimeOSFamily)' == 'osx'">OSX</_derivedPackageTargetOSGroup>
+ <_derivedPackageTargetOSGroup Condition="'$(_derivedPackageTargetOSGroup)' == '' and '$(_runtimeOSFamily)' == 'win'">Windows_NT</_derivedPackageTargetOSGroup>
+ <_derivedPackageTargetOSGroup Condition="'$(_derivedPackageTargetOSGroup)' == '' and '$(__BuildOS)' != ''">$(__BuildOS)</_derivedPackageTargetOSGroup>
+ <_derivedPackageTargetOSGroup Condition="'$(_derivedPackageTargetOSGroup)' == ''">Linux</_derivedPackageTargetOSGroup>
+
+ <_isSupportedOSGroup Condition="!$(SupportedPackageOSGroups.Contains(';$(_derivedPackageTargetOSGroup);'))">false</_isSupportedOSGroup>
+ </PropertyGroup>
+
+ <!-- _packageTargetOSGroup is used to control the runtime package imports, don't import runtime package targets for
+ an unsupported OS Group -->
+ <PropertyGroup Condition="'$(PackageTargetRuntime)' != '' and '$(_isSupportedOSGroup)' == 'true'">
+ <_packageTargetOSGroup>$(_derivedPackageTargetOSGroup)</_packageTargetOSGroup>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <SkipPackageFileCheck>true</SkipPackageFileCheck>
+ <OutputPath>$(PackageOutputPath)</OutputPath>
+ </PropertyGroup>
+
+ <PropertyGroup Condition="'$(IsLineupPackage)' == 'true'">
+ <SkipValidatePackage>true</SkipValidatePackage>
+ <IncludeRuntimeJson>true</IncludeRuntimeJson>
+ </PropertyGroup>
+
+ <Choose>
+ <When Condition="'$(PackageRID)' != ''" />
+ <When Condition="'$(_runtimeOSFamily)' == 'win'">
+ <PropertyGroup>
+ <PackageRID Condition="'$(ArchGroup)' == 'x86' OR '$(ArchGroup)' == 'x64'">win7-$(ArchGroup)</PackageRID>
+ <PackageRID Condition="'$(ArchGroup)' == 'arm'">win8-$(ArchGroup)</PackageRID>
+ <PackageRID Condition="'$(ArchGroup)' == 'arm64'">win10-$(ArchGroup)</PackageRID>
+ </PropertyGroup>
+ </When>
+ <When Condition="'$(_runtimeOSFamily)' == 'osx'">
+ <PropertyGroup>
+ <PackageRID>osx.10.10-$(ArchGroup)</PackageRID>
+ </PropertyGroup>
+ </When>
+ <When Condition="'$(_runtimeOSFamily)' == 'rhel'">
+ <PropertyGroup>
+ <PackageRID>rhel.7-$(ArchGroup)</PackageRID>
+ </PropertyGroup>
+ </When>
+ <Otherwise>
+ <PropertyGroup>
+ <PackageRID>$(RuntimeOS)-$(ArchGroup)</PackageRID>
+ </PropertyGroup>
+ </Otherwise>
+ </Choose>
+
+ <ItemGroup Condition="$(SupportedPackageOSGroups.Contains(';Linux;'))">
+ <OfficialBuildRID Include="alpine.3.4.3-x64" />
+ <OfficialBuildRID Include="debian.8-armel">
+ <Platform>armel</Platform>
+ </OfficialBuildRID>
+ <OfficialBuildRID Include="debian.8-x64" />
+ <OfficialBuildRID Include="fedora.23-x64" />
+ <OfficialBuildRID Include="fedora.24-x64" />
+ <OfficialBuildRID Include="linux-x64" />
+ <OfficialBuildRID Include="opensuse.13.2-x64" />
+ <OfficialBuildRID Include="opensuse.42.1-x64" />
+ <OfficialBuildRID Include="rhel.7-x64" />
+ <OfficialBuildRID Include="tizen.4.0.0-armel">
+ <Platform>armel</Platform>
+ </OfficialBuildRID>
+ <OfficialBuildRID Include="ubuntu.14.04-arm">
+ <Platform>arm</Platform>
+ </OfficialBuildRID>
+ <OfficialBuildRID Include="ubuntu.14.04-x64" />
+ <OfficialBuildRID Include="ubuntu.16.04-arm">
+ <Platform>arm</Platform>
+ </OfficialBuildRID>
+ <OfficialBuildRID Include="ubuntu.16.04-x64" />
+ <OfficialBuildRID Include="ubuntu.16.10-arm">
+ <Platform>arm</Platform>
+ </OfficialBuildRID>
+ <OfficialBuildRID Include="ubuntu.16.10-x64" />
+ </ItemGroup>
+ <ItemGroup Condition="$(SupportedPackageOSGroups.Contains(';OSX;'))">
+ <OfficialBuildRID Include="osx.10.10-x64" />
+ </ItemGroup>
+ <ItemGroup Condition="$(SupportedPackageOSGroups.Contains(';Windows_NT;'))">
+ <OfficialBuildRID Include="win7-x86">
+ <Platform>x86</Platform>
+ </OfficialBuildRID>
+ <OfficialBuildRID Include="win7-x64" />
+ <OfficialBuildRID Include="win8-arm">
+ <Platform>arm</Platform>
+ </OfficialBuildRID>
+ <OfficialBuildRID Include="win10-arm64">
+ <Platform>arm64</Platform>
+ </OfficialBuildRID>
+ </ItemGroup>
+ <ItemGroup>
+ <!-- Ensure we have a RID-specific package for the current build, even if it isn't in our official set, but
+ don't build the RID-specific package if we're in an unsupported os family -->
+ <BuildRID Include="@(OfficialBuildRID)" Exclude="$(PackageRID)"/>
+ <BuildRID Include="$(PackageRID)"
+ Condition="'$(_isSupportedOSGroup)' == 'true'">
+ <Platform Condition="'$(ArchGroup)' == 'x64'">amd64</Platform>
+ <Platform Condition="'$(ArchGroup)' != 'x64'">$(ArchGroup)</Platform>
+ </BuildRID>
+ </ItemGroup>
+
+ <ItemGroup>
+ <_project Include="@(BuildRID)">
+ <Platform Condition="'%(Platform)' == ''">amd64</Platform>
+ <PackageTargetRuntime>%(Identity)</PackageTargetRuntime>
+ <AdditionalProperties>PackageTargetRuntime=%(Identity);Platform=%(Platform)</AdditionalProperties>
+ </_project>
+
+ <_buildRidProjects Include="@(_project->'$(MSBuildProjectName).pkgproj')" />
+ <!-- Only include rid projects for a builds file, not for a lineup package -->
+ <Project Condition="'$(IsLineupPackage)' != 'true'" Include="@(_buildRidProjects)" />
+ </ItemGroup>
+
+ <ItemGroup Condition="'$(IsLineupPackage)' == 'true'">
+ <!-- Include project references for a lineup package to generate the runtime.json file -->
+ <ProjectReference Include="@(_buildRidProjects)" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/src/.nuget/dir.traversal.targets b/src/.nuget/dir.traversal.targets
new file mode 100644
index 0000000000..686ae749a7
--- /dev/null
+++ b/src/.nuget/dir.traversal.targets
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+ <Import Project="$(MSBuildThisFileDirectory)..\..\dir.traversal.targets" />
+
+ <Target Name="FilterProjects" BeforeTargets="Build">
+ <Error Condition="'$(PackageRID)' == ''" Text="'PackageRID' property must be specified."/>
+
+ <!-- Only build packages for current RID or non-RID-specific -->
+ <ItemGroup>
+ <_projectsToBuild Include="@(Project)" Condition="'%(Project.PackageTargetRuntime)' == '$(PackageRID)' OR '%(Project.PackageTargetRuntime)' == ''" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <Project Remove="@(Project)" />
+ <Project Include="@(_projectsToBuild)" />
+ </ItemGroup>
+ </Target>
+</Project> \ No newline at end of file
diff --git a/src/.nuget/init/project.json b/src/.nuget/init/project.json
index 5440fde0de..5908fcc3f9 100644
--- a/src/.nuget/init/project.json
+++ b/src/.nuget/init/project.json
@@ -1,6 +1,6 @@
{
"dependencies": {
- "Microsoft.NETCore.Platforms": "1.0.2-beta-24224-02",
+ "Microsoft.NETCore.Platforms": "1.0.2-beta-24224-02"
},
"frameworks": {
"dnxcore50": {
diff --git a/src/.nuget/packages.builds b/src/.nuget/packages.builds
index 5d1d025100..f57b9a9b50 100644
--- a/src/.nuget/packages.builds
+++ b/src/.nuget/packages.builds
@@ -1,6 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <Import Project="$(MSBuildThisFileDirectory)..\..\dir.props" />
<PropertyGroup>
<!-- This property must be set to the same value as $(PackageOutputPath) for the nuspecs and nupkgs to be binplaced to the intended location. -->
@@ -8,23 +7,23 @@
</PropertyGroup>
<ItemGroup Condition="'$(__SkipCoreLibBuild)'==''">
- <Project Include="Microsoft.NETCore.Runtime.CoreCLR\Microsoft.NETCore.Runtime.CoreCLR.builds" />
+ <Project Include="Microsoft.NETCore.Runtime.CoreCLR\Microsoft.NETCore.Runtime.CoreCLR.builds" />
</ItemGroup>
<ItemGroup Condition="'$(TargetsWindows)'=='true'">
- <Project Include="Microsoft.TargetingPack.Private.CoreCLR\Microsoft.TargetingPack.Private.CoreCLR.pkgproj" />
+ <Project Include="Microsoft.TargetingPack.Private.CoreCLR\Microsoft.TargetingPack.Private.CoreCLR.pkgproj" />
</ItemGroup>
<ItemGroup Condition="'$(__SkipNativeBuild)'==''">
- <Project Include="Microsoft.NETCore.Jit\Microsoft.NETCore.Jit.builds" />
- <Project Include="Microsoft.NETCore.TestHost\Microsoft.NETCore.TestHost.builds" />
- <Project Include="Microsoft.NETCore.Native\Microsoft.NETCore.Native.builds" />
+ <Project Include="Microsoft.NETCore.Jit\Microsoft.NETCore.Jit.builds" />
+ <Project Include="Microsoft.NETCore.TestHost\Microsoft.NETCore.TestHost.builds" />
+ <Project Include="Microsoft.NETCore.Native\Microsoft.NETCore.Native.builds" />
</ItemGroup>
<ItemGroup>
- <Project Include="Microsoft.NETCore.ILAsm\Microsoft.NETCore.ILAsm.builds" />
- <Project Include="Microsoft.NETCore.ILDAsm\Microsoft.NETCore.ILDAsm.builds" />
+ <Project Include="Microsoft.NETCore.ILAsm\Microsoft.NETCore.ILAsm.builds" />
+ <Project Include="Microsoft.NETCore.ILDAsm\Microsoft.NETCore.ILDAsm.builds" />
</ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
+ <Import Project="$(MSBuildThisFileDirectory)..\..\dir.traversal.targets" />
</Project>
diff --git a/src/ToolBox/SOS/lldbplugin/CMakeLists.txt b/src/ToolBox/SOS/lldbplugin/CMakeLists.txt
index 29b36e8fa2..7b58447f86 100644
--- a/src/ToolBox/SOS/lldbplugin/CMakeLists.txt
+++ b/src/ToolBox/SOS/lldbplugin/CMakeLists.txt
@@ -35,6 +35,7 @@ elseif(CLR_CMAKE_PLATFORM_ARCH_ARM64)
add_definitions(-DDBG_TARGET_ARM64=1)
add_definitions(-DDBG_TARGET_WIN64=1)
add_definitions(-DBIT64)
+ SET(REQUIRE_LLDBPLUGIN false)
endif()
set(ENABLE_LLDBPLUGIN ${CLR_CMAKE_PLATFORM_UNIX} CACHE BOOL "Enable building the SOS plugin for LLDB.")
diff --git a/src/classlibnative/inc/nlsinfo.h b/src/classlibnative/inc/nlsinfo.h
index 67677c7576..1650ab3ef2 100644
--- a/src/classlibnative/inc/nlsinfo.h
+++ b/src/classlibnative/inc/nlsinfo.h
@@ -81,9 +81,6 @@ public:
static BOOL QCALLTYPE InternalGetUserDefaultUILanguage(QCall::StringHandleOnStack userDefaultUiLanguage);
static BOOL QCALLTYPE InternalGetSystemDefaultUILanguage(QCall::StringHandleOnStack systemDefaultUiLanguage);
-// Added but disabled from desktop in .NET 4.0, stayed disabled in .NET 4.5
- static FCDECL0(Object*, nativeGetResourceFallbackArray);
-
//
// Native helper functions for methods in DateTimeFormatInfo
//
@@ -165,7 +162,8 @@ public:
__in int cchSource, // number of characters lpStringSource after sourceIndex
__in int sourceIndex, // index from where the search will start in lpStringSource
__in_ecount(cchValue) LPCWSTR lpStringValue, // the string we search for
- __in int cchValue); // length of the string we search for
+ __in int cchValue, // length of the string we search for
+ __out_opt LPINT pcchFound); // length of the string we found in source
static int QCALLTYPE InternalGetSortKey(
__in_opt INT_PTR handle, // PSORTHANDLE
diff --git a/src/classlibnative/nls/nlsinfo.cpp b/src/classlibnative/nls/nlsinfo.cpp
index 507a18b221..da565e5fdd 100644
--- a/src/classlibnative/nls/nlsinfo.cpp
+++ b/src/classlibnative/nls/nlsinfo.cpp
@@ -307,70 +307,6 @@ BOOL QCALLTYPE COMNlsInfo::InternalGetUserDefaultUILanguage(QCall::StringHandleO
return result;
}
-// Added but disabled from desktop in .NET 4.0, stayed disabled in .NET 4.5
-FCIMPL0(Object*, COMNlsInfo::nativeGetResourceFallbackArray)
-{
- CONTRACTL
- {
- FCALL_CHECK;
- } CONTRACTL_END;
-
- DWORD dwFlags = MUI_MERGE_USER_FALLBACK | MUI_MERGE_SYSTEM_FALLBACK;
- ULONG cchLanguagesBuffer = 0;
- ULONG ulNumLanguages = 0;
- BOOL result = FALSE;
-
- struct _gc
- {
- PTRARRAYREF resourceFallbackArray;
- } gc;
-
- gc.resourceFallbackArray = NULL;
-
- // If the resource lookups we're planning on doing are going to be written to a non-Unicode console,
- // then we should ideally only return languages that can be displayed correctly on the console. The
- // trick is guessing at whether we're writing this data to the console, which we can't do well.
- // Instead, we ask new apps to call GetConsoleFallbackUICulture & fall back to en-US.
- bool disableUserFallback;
- BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
- disableUserFallback = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_Resources_DisableUserPreferredFallback) == 1
- END_SO_INTOLERANT_CODE;
-
- if (disableUserFallback)
- return NULL;
-
- HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
-
- // first call with null buffer to get size
- result = NewApis::GetThreadPreferredUILanguages(dwFlags, &ulNumLanguages, NULL, &cchLanguagesBuffer);
- if (cchLanguagesBuffer > 0)
- {
- NewArrayHolder<WCHAR> stringBuffer = new (nothrow) WCHAR[cchLanguagesBuffer];
- if (stringBuffer != NULL)
- {
- result = NewApis::GetThreadPreferredUILanguages(dwFlags, &ulNumLanguages, stringBuffer, &cchLanguagesBuffer);
- _ASSERTE(result);
-
- // now string into strings
- gc.resourceFallbackArray = (PTRARRAYREF) AllocateObjectArray(ulNumLanguages, g_pStringClass);
-
- LPCWSTR buffer = stringBuffer; // Restart @ buffer beginning
- for(DWORD i = 0; i < ulNumLanguages; i++)
- {
- OBJECTREF o = (OBJECTREF) StringObject::NewString(buffer);
- gc.resourceFallbackArray->SetAt(i, o);
- buffer += (lstrlenW(buffer) + 1);
- }
- }
- }
-
- HELPER_METHOD_FRAME_END();
-
- return OBJECTREFToObject(gc.resourceFallbackArray);
-
-}
-FCIMPLEND
-
INT32 COMNlsInfo::CallGetUserDefaultUILanguage()
{
CONTRACTL
@@ -2452,7 +2388,8 @@ int QCALLTYPE COMNlsInfo::InternalFindNLSStringEx(
__in int cchSource, // number of characters lpStringSource after sourceIndex
__in int sourceIndex, // index from where the search will start in lpStringSource
__in_ecount(cchValue) LPCWSTR lpStringValue, // the string we search for
- __in int cchValue) // length of the string we search for
+ __in int cchValue, // length of the string we search for
+ __out_opt LPINT pcchFound) // length of the string we found in source
{
CONTRACTL {
QCALL_CHECK;
@@ -2496,7 +2433,8 @@ int QCALLTYPE COMNlsInfo::InternalFindNLSStringEx(
lpStringValue,
cchValue,
dwFindNLSStringFlags & FIND_NLS_STRING_FLAGS_NEGATION,
- dwFindNLSStringFlags & FIND_ENDSWITH);
+ dwFindNLSStringFlags & FIND_ENDSWITH,
+ pcchFound);
if (retValue >= 0)
{
retValue += sourceIndex - cchSource + 1;
@@ -2511,7 +2449,8 @@ int QCALLTYPE COMNlsInfo::InternalFindNLSStringEx(
lpStringValue,
cchValue,
dwFindNLSStringFlags & FIND_NLS_STRING_FLAGS_NEGATION,
- dwFindNLSStringFlags & FIND_STARTSWITH);
+ dwFindNLSStringFlags & FIND_STARTSWITH,
+ pcchFound);
if (retValue >= 0)
{
@@ -2530,7 +2469,9 @@ int QCALLTYPE COMNlsInfo::InternalFindNLSStringEx(
&lpStringSource[sourceIndex - cchSource + 1],
cchSource,
lpStringValue,
- cchValue, NULL, NULL, NULL, (LPARAM) handle);
+ cchValue,
+ pcchFound,
+ NULL, NULL, (LPARAM) handle);
}
if (retValue >= 0)
@@ -2547,7 +2488,9 @@ int QCALLTYPE COMNlsInfo::InternalFindNLSStringEx(
&lpStringSource[sourceIndex],
cchSource,
lpStringValue,
- cchValue, NULL, NULL, NULL, (LPARAM) handle);
+ cchValue,
+ pcchFound,
+ NULL, NULL, (LPARAM) handle);
}
if (retValue >= 0)
diff --git a/src/corefx/System.Globalization.Native/collation.cpp b/src/corefx/System.Globalization.Native/collation.cpp
index f37211208e..a8c24e16ad 100644
--- a/src/corefx/System.Globalization.Native/collation.cpp
+++ b/src/corefx/System.Globalization.Native/collation.cpp
@@ -440,7 +440,8 @@ extern "C" int32_t GlobalizationNative_IndexOf(
int32_t cwTargetLength,
const UChar* lpSource,
int32_t cwSourceLength,
- int32_t options)
+ int32_t options,
+ int32_t* pMatchedLength)
{
static_assert(USEARCH_DONE == -1, "managed side requires -1 for not found");
@@ -455,6 +456,13 @@ extern "C" int32_t GlobalizationNative_IndexOf(
if (U_SUCCESS(err))
{
result = usearch_first(pSearch, &err);
+
+ // if the search was successful,
+ // we'll try to get the matched string length.
+ if(result != USEARCH_DONE && pMatchedLength != NULL)
+ {
+ *pMatchedLength = usearch_getMatchedLength(pSearch);
+ }
usearch_close(pSearch);
}
}
diff --git a/src/debug/daccess/nidump.cpp b/src/debug/daccess/nidump.cpp
index 2b46da2fe0..c300e6fa01 100644
--- a/src/debug/daccess/nidump.cpp
+++ b/src/debug/daccess/nidump.cpp
@@ -7519,9 +7519,7 @@ NativeImageDumper::DumpMethodTable( PTR_MethodTable mt, const char * name,
else
{
_ASSERTE(mt->GetNumVtableSlots() > 0 );
- /* REVISIT_TODO Tue 12/13/2005
- * One liner copied from CrossDomainCalls.cpp
- */
+
unsigned size = sizeof(RemotableMethodInfo) * mt->GetNumVtableSlots();
//one remotable method info for each method.
m_display->StartStructureWithOffset( "OptionalMember_RemotableMethodInfo",
diff --git a/src/inc/clrconfigvalues.h b/src/inc/clrconfigvalues.h
index 347cdd0c34..6a30af16db 100644
--- a/src/inc/clrconfigvalues.h
+++ b/src/inc/clrconfigvalues.h
@@ -1058,7 +1058,6 @@ CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_AlwaysUseMetadataInterfaceMapLayout, W(
CONFIG_DWORD_INFO(INTERNAL_AssertOnUnneededThis, W("AssertOnUnneededThis"), 0, "While the ConfigDWORD is unnecessary, the contained ASSERT should be kept. This may result in some work tracking down violating MethodDescCallSites.")
CONFIG_DWORD_INFO_EX(INTERNAL_AssertStacktrace, W("AssertStacktrace"), 1, "", CLRConfig::REGUTIL_default)
RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS(UNSUPPORTED_BuildFlavor, W("BuildFlavor"), "Choice of build flavor (wks or svr) of CLR")
-CONFIG_DWORD_INFO(INTERNAL_CerLogging, W("CerLogging"), 0, "In vm\\ConstrainedExecutionRegion.cpp. Debug-only logging when we prepare methods, find reliability contract problems, restore stuff from ngen images, etc.")
CONFIG_DWORD_INFO_EX(INTERNAL_clearNativeImageStress, W("clearNativeImageStress"), 0, "", CLRConfig::REGUTIL_default)
RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS(INTERNAL_CLRLoadLogDir, W("CLRLoadLogDir"), "Enable logging of CLR selection")
RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CONFIG, W("CONFIG"), "Used to specify an XML config file for EEConfig", CLRConfig::REGUTIL_default)
diff --git a/src/inc/clrprivbinderutil.h b/src/inc/clrprivbinderutil.h
index 1a645dccc0..d42f2b8d66 100644
--- a/src/inc/clrprivbinderutil.h
+++ b/src/inc/clrprivbinderutil.h
@@ -737,9 +737,6 @@ namespace CLRPrivBinderUtil
/** probably should be exposed on an instance (of something) method rather that magically calling GetAppDomain() **/
ICLRPrivAssembly* RaiseAssemblyResolveEvent(IAssemblyName *pAssemblyName, ICLRPrivAssembly* pRequestingAssembly);
- /** PLACEHOLDER - CLRPRivBinderFusion::BindAssemblyByName throws, despite being an HRESULT function,
- most presumably because returning HRESULT is too lossy **/
-
/** Ultimately, only the binder can do ref-def matching, and it should be opaque to CLR.
This is not trivial to do, however, since we cannot do data conversion as the function is nofault **/
BOOL CompareHostBinderSpecs(AssemblySpec* a1, AssemblySpec* a2);
diff --git a/src/inc/corcompile.h b/src/inc/corcompile.h
index e2d3c05d82..f99e27eec0 100644
--- a/src/inc/corcompile.h
+++ b/src/inc/corcompile.h
@@ -1304,6 +1304,12 @@ class ICorCompilePreloader
CORINFO_METHOD_HANDLE method,
CORINFO_METHOD_HANDLE duplicateMethod) = 0;
+ // Returns a compressed encoding of the inline tracking map
+ // for this compilation
+ virtual void GetSerializedInlineTrackingMap(
+ IN OUT SBuffer * pSerializedInlineTrackingMap
+ ) = 0;
+
//
// Release frees the preloader
//
diff --git a/src/inc/corinfo.h b/src/inc/corinfo.h
index f515fcbd6d..492dbece6c 100644
--- a/src/inc/corinfo.h
+++ b/src/inc/corinfo.h
@@ -691,6 +691,8 @@ enum CorInfoHelpFunc
CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, // Transition to cooperative mode in reverse P/Invoke prolog, frame is the first argument
CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, // Transition to preemptive mode in reverse P/Invoke epilog, frame is the first argument
+
+ CORINFO_HELP_GVMLOOKUP_FOR_SLOT, // Resolve a generic virtual method target from this pointer and runtime method handle
#endif
CORINFO_HELP_COUNT,
diff --git a/src/inc/corprof.idl b/src/inc/corprof.idl
index 9af1cd97a8..3378431317 100644
--- a/src/inc/corprof.idl
+++ b/src/inc/corprof.idl
@@ -3740,15 +3740,20 @@ interface ICorProfilerInfo6 : ICorProfilerInfo5
{
/*
* Returns an enumerator for all methods that
- * - belong to a given NGen module (inlinersModuleId) and
+ * - belong to a given NGen or R2R module (inlinersModuleId) and
* - inlined a body of a given method (inlineeModuleId / inlineeMethodId).
*
* If incompleteData is set to TRUE after function is called, it means that the methods enumerator
* doesn't contain all methods inlining a given method.
* It can happen when one or more direct or indirect dependencies of inliners module haven't been loaded yet.
- * If profiler needs accurate data it should retry later when more modules are loaded (preferable on each module load).
+ * If profiler needs accurate data it should retry later when more modules are loaded (preferably on each module load).
*
* It can be used to lift limitation on inlining for ReJIT.
+ *
+ * NOTE: If the inlinee method is decorated with the System.Runtime.Versioning.NonVersionable attribute then
+ * then some inliners may not ever be reported. If you need to get a full accounting you can avoid the issue
+ * by disabling the use of all native images.
+ *
*/
HRESULT EnumNgenModuleMethodsInliningThisMethod(
[in] ModuleID inlinersModuleId,
diff --git a/src/inc/jithelpers.h b/src/inc/jithelpers.h
index f84db9142d..c9726cdd7f 100644
--- a/src/inc/jithelpers.h
+++ b/src/inc/jithelpers.h
@@ -389,6 +389,8 @@
JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, NULL, CORINFO_HELP_SIG_UNDEF)
JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, NULL, CORINFO_HELP_SIG_UNDEF)
+ JITHELPER(CORINFO_HELP_GVMLOOKUP_FOR_SLOT, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)
+
#endif // COR_JIT_EE_VERSION
#undef JITHELPER
diff --git a/src/inc/newapis.h b/src/inc/newapis.h
index dfe77a5000..e0e6d999e1 100644
--- a/src/inc/newapis.h
+++ b/src/inc/newapis.h
@@ -288,15 +288,17 @@ namespace NewApis
__in_ecount(cchCount2) LPCWSTR pString2, // String we're looking for
__in int cchCount2, // length of pString2
__in DWORD dwFlags, // search flags
- __in BOOL startWith);
+ __in BOOL startWith,
+ __out_opt LPINT pcchFound);
int LastIndexOfString(__in LPCWSTR lpLocaleName,
- __in_ecount(cchCount1) LPCWSTR pString1, // String to search in
- __in int cchCount1, // length of pString1
- __in_ecount(cchCount2) LPCWSTR pString2, // String we're looking for
- __in int cchCount2, // length of pString2
- __in DWORD dwFlags,
- __in BOOL endWith);
+ __in_ecount(cchCount1) LPCWSTR pString1, // String to search in
+ __in int cchCount1, // length of pString1
+ __in_ecount(cchCount2) LPCWSTR pString2, // String we're looking for
+ __in int cchCount2, // length of pString2
+ __in DWORD dwFlags,
+ __in BOOL endWith,
+ __out_opt LPINT pcchFound);
int FindNLSStringEx(__in LPCWSTR lpLocaleName,
__in DWORD dwFindNLSStringFlags,
diff --git a/src/inc/readytorun.h b/src/inc/readytorun.h
index ebc557b6f1..9084b92814 100644
--- a/src/inc/readytorun.h
+++ b/src/inc/readytorun.h
@@ -16,7 +16,8 @@
#define READYTORUN_SIGNATURE 0x00525452 // 'RTR'
#define READYTORUN_MAJOR_VERSION 0x0002
-#define READYTORUN_MINOR_VERSION 0x0000
+#define READYTORUN_MINOR_VERSION 0x0001
+// R2R Version 2.1 adds the READYTORUN_SECTION_INLINING_INFO section
struct READYTORUN_HEADER
{
@@ -57,6 +58,13 @@ enum ReadyToRunSectionType
// 107 used by an older format of READYTORUN_SECTION_AVAILABLE_TYPES
READYTORUN_SECTION_AVAILABLE_TYPES = 108,
READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS = 109,
+ READYTORUN_SECTION_INLINING_INFO = 110 // Added in V2.1
+
+ // If you add a new section consider whether it is a breaking or non-breaking change.
+ // Usually it is non-breaking, but if it is preferable to have older runtimes fail
+ // to load the image vs. ignoring the new section it could be marked breaking.
+ // Increment the READYTORUN_MINOR_VERSION (non-breaking) or READYTORUN_MAJOR_VERSION
+ // (breaking) as appropriate.
};
//
diff --git a/src/inc/regdisp.h b/src/inc/regdisp.h
index d08c44c904..befff68449 100644
--- a/src/inc/regdisp.h
+++ b/src/inc/regdisp.h
@@ -477,35 +477,21 @@ inline void CopyRegDisplay(const PREGDISPLAY pInRD, PREGDISPLAY pOutRD, T_CONTEX
inline size_t * getRegAddr (unsigned regNum, PTR_CONTEXT regs)
{
#ifdef _TARGET_X86_
- switch (regNum)
+ _ASSERTE(regNum < 8);
+
+ static const SIZE_T OFFSET_OF_REGISTERS[] =
{
- case 0:
- return (size_t *)&regs->Eax;
- break;
- case 1:
- return (size_t *)&regs->Ecx;
- break;
- case 2:
- return (size_t *)&regs->Edx;
- break;
- case 3:
- return (size_t *)&regs->Ebx;
- break;
- case 4:
- return (size_t *)&regs->Esp;
- break;
- case 5:
- return (size_t *)&regs->Ebp;
- break;
- case 6:
- return (size_t *)&regs->Esi;
- break;
- case 7:
- return (size_t *)&regs->Edi;
- break;
- default:
- _ASSERTE (!"unknown regNum");
- }
+ offsetof(CONTEXT, Eax),
+ offsetof(CONTEXT, Ecx),
+ offsetof(CONTEXT, Edx),
+ offsetof(CONTEXT, Ebx),
+ offsetof(CONTEXT, Esp),
+ offsetof(CONTEXT, Ebp),
+ offsetof(CONTEXT, Esi),
+ offsetof(CONTEXT, Edi),
+ };
+
+ return (PTR_size_t)(PTR_BYTE(regs) + OFFSET_OF_REGISTERS[regNum]);
#elif defined(_TARGET_AMD64_)
_ASSERTE(regNum < 16);
return &regs->Rax + regNum;
diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp
index 613e8ee4f6..28a5bcf742 100644
--- a/src/jit/compiler.cpp
+++ b/src/jit/compiler.cpp
@@ -7218,29 +7218,34 @@ double JitTimer::s_cyclesPerSec = CycleTimer::CyclesPerSecond();
#if defined(FEATURE_JIT_METHOD_PERF) || DUMP_FLOWGRAPHS || defined(FEATURE_TRACELOGGING)
const char* PhaseNames[] = {
-#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent) string_nm,
+#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) string_nm,
#include "compphases.h"
};
const char* PhaseEnums[] = {
-#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent) #enum_nm,
+#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) #enum_nm,
#include "compphases.h"
};
const LPCWSTR PhaseShortNames[] = {
-#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent) W(short_nm),
+#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) W(short_nm),
#include "compphases.h"
};
#endif // defined(FEATURE_JIT_METHOD_PERF) || DUMP_FLOWGRAPHS
#ifdef FEATURE_JIT_METHOD_PERF
bool PhaseHasChildren[] = {
-#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent) hasChildren,
+#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) hasChildren,
#include "compphases.h"
};
int PhaseParent[] = {
-#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent) parent,
+#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) parent,
+#include "compphases.h"
+};
+
+bool PhaseReportsIRSize[] = {
+#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) measureIR,
#include "compphases.h"
};
@@ -7648,7 +7653,7 @@ JitTimer::JitTimer(unsigned byteCodeSize) : m_info(byteCodeSize)
}
}
-void JitTimer::EndPhase(Phases phase)
+void JitTimer::EndPhase(Compiler* compiler, Phases phase)
{
// Otherwise...
// We re-run some phases currently, so this following assert doesn't work.
@@ -7699,6 +7704,15 @@ void JitTimer::EndPhase(Phases phase)
m_curPhaseStart = threadCurCycles;
}
}
+
+ if ((JitConfig.JitMeasureIR() != 0) && PhaseReportsIRSize[phase])
+ {
+ m_info.m_nodeCountAfterPhase[phase] = compiler->fgMeasureIR();
+ }
+ else
+ {
+ m_info.m_nodeCountAfterPhase[phase] = 0;
+ }
}
#ifdef DEBUG
@@ -7807,6 +7821,9 @@ void JitTimer::PrintCsvHeader()
FILE* fp = _wfopen(jitTimeLogCsv, W("a"));
if (fp != nullptr)
{
+ // Seek to the end of the file s.t. `ftell` doesn't lie to us on Windows
+ fseek(fp, 0, SEEK_END);
+
// Write the header if the file is empty
if (ftell(fp) == 0)
{
@@ -7820,10 +7837,16 @@ void JitTimer::PrintCsvHeader()
for (int i = 0; i < PHASE_NUMBER_OF; i++)
{
fprintf(fp, "\"%s\",", PhaseNames[i]);
+ if (PhaseReportsIRSize[i])
+ {
+ fprintf(fp, "\"Node Count After %s\",", PhaseNames[i]);
+ }
}
InlineStrategy::DumpCsvHeader(fp);
+ fprintf(fp, "\"Executable Code Bytes\",");
+ fprintf(fp, "\"GC Info Bytes\",");
fprintf(fp, "\"Total Bytes Allocated\",");
fprintf(fp, "\"Total Cycles\",");
fprintf(fp, "\"CPS\"\n");
@@ -7871,10 +7894,17 @@ void JitTimer::PrintCsvMethodStats(Compiler* comp)
totCycles += m_info.m_cyclesByPhase[i];
}
fprintf(fp, "%I64u,", m_info.m_cyclesByPhase[i]);
+
+ if (PhaseReportsIRSize[i])
+ {
+ fprintf(fp, "%u,", m_info.m_nodeCountAfterPhase[i]);
+ }
}
comp->m_inlineStrategy->DumpCsvData(fp);
+ fprintf(fp, "%Iu,", comp->info.compNativeCodeSize);
+ fprintf(fp, "%Iu,", comp->compInfoBlkSize);
fprintf(fp, "%Iu,", comp->compGetAllocator()->getTotalBytesAllocated());
fprintf(fp, "%I64u,", m_info.m_totalCycles);
fprintf(fp, "%f\n", CycleTimer::CyclesPerSecond());
diff --git a/src/jit/compiler.h b/src/jit/compiler.h
index 7c5565c9c7..1cbd3e3195 100644
--- a/src/jit/compiler.h
+++ b/src/jit/compiler.h
@@ -917,7 +917,7 @@ struct ArrayInfo
// partition a compilation.
enum Phases
{
-#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent) enum_nm,
+#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) enum_nm,
#include "compphases.h"
PHASE_NUMBER_OF
};
@@ -952,6 +952,7 @@ struct CompTimeInfo
static bool PhaseHasChildren[];
static int PhaseParent[];
+ static bool PhaseReportsIRSize[];
unsigned m_byteCodeBytes;
unsigned __int64 m_totalCycles;
@@ -961,6 +962,9 @@ struct CompTimeInfo
unsigned __int64 m_CLRinvokesByPhase[PHASE_NUMBER_OF];
unsigned __int64 m_CLRcyclesByPhase[PHASE_NUMBER_OF];
#endif
+
+ unsigned m_nodeCountAfterPhase[PHASE_NUMBER_OF];
+
// For better documentation, we call EndPhase on
// non-leaf phases. We should also call EndPhase on the
// last leaf subphase; obviously, the elapsed cycles between the EndPhase
@@ -1077,7 +1081,7 @@ public:
static void PrintCsvHeader();
// Ends the current phase (argument is for a redundant check).
- void EndPhase(Phases phase);
+ void EndPhase(Compiler* compiler, Phases phase);
#if MEASURE_CLRAPI_CALLS
// Start and end a timed CLR API call.
@@ -2138,9 +2142,10 @@ public:
bool gtIsStaticFieldPtrToBoxedStruct(var_types fieldNodeType, CORINFO_FIELD_HANDLE fldHnd);
// Return true if call is a recursive call; return false otherwise.
+ // Note when inlining, this looks for calls back to the root method.
bool gtIsRecursiveCall(GenTreeCall* call)
{
- return (call->gtCallMethHnd == info.compMethodHnd);
+ return (call->gtCallMethHnd == impInlineRoot()->info.compMethodHnd);
}
//-------------------------------------------------------------------------
@@ -3470,6 +3475,8 @@ public:
void fgInsertBBafter(BasicBlock* insertAfterBlk, BasicBlock* newBlk);
void fgUnlinkBlock(BasicBlock* block);
+ unsigned fgMeasureIR();
+
#if OPT_BOOL_OPS // Used to detect multiple logical "not" assignments.
bool fgMultipleNots;
#endif
@@ -3555,12 +3562,18 @@ public:
void fgRemoveEmptyFinally();
+ void fgMergeFinallyChains();
+
void fgCloneFinally();
void fgCleanupContinuation(BasicBlock* continuation);
void fgUpdateFinallyTargetFlags();
+ bool fgRetargetBranchesToCanonicalCallFinally(BasicBlock* block,
+ BasicBlock* handler,
+ BlockToBlockMap& continuationMap);
+
GenTreePtr fgGetCritSectOfStaticMethod();
#if !defined(_TARGET_X86_)
@@ -5568,6 +5581,12 @@ public:
optMethodFlags &= ~OMF_HAS_FATPOINTER;
}
+ void addFatPointerCandidate(GenTreeCall* call)
+ {
+ setMethodHasFatPointer();
+ call->SetFatPointerCandidate();
+ }
+
unsigned optMethodFlags;
// Recursion bound controls how far we can go backwards tracking for a SSA value.
diff --git a/src/jit/compiler.hpp b/src/jit/compiler.hpp
index 6baf601892..beb3c79618 100644
--- a/src/jit/compiler.hpp
+++ b/src/jit/compiler.hpp
@@ -4450,7 +4450,7 @@ inline void Compiler::EndPhase(Phases phase)
#if defined(FEATURE_JIT_METHOD_PERF)
if (pCompJitTimer != nullptr)
{
- pCompJitTimer->EndPhase(phase);
+ pCompJitTimer->EndPhase(this, phase);
}
#endif
#if DUMP_FLOWGRAPHS
diff --git a/src/jit/compphases.h b/src/jit/compphases.h
index 5038d6e9c9..e4dfedd499 100644
--- a/src/jit/compphases.h
+++ b/src/jit/compphases.h
@@ -11,95 +11,98 @@
// corresponding array of string names of those phases. This include file undefines CompPhaseNameMacro
// after the last use.
// The arguments are:
-// CompPhaseNameMacro(enumName, stringName, shortName, hasChildren, parent)
+// CompPhaseNameMacro(enumName, stringName, shortName, hasChildren, parent, measureIR)
// "enumName" is an Enumeration-style all-caps name.
// "stringName" is a self-explanatory.
// "shortName" is an abbreviated form for stringName
// "hasChildren" is true if this phase is broken out into subphases.
// (We should never do EndPhase on a phase that has children, only on 'leaf phases.')
// "parent" is -1 for leaf phases, otherwise it is the "enumName" of the parent phase.
+// "measureIR" is true for phases that generate a count of IR nodes during EndPhase when JitConfig.MeasureIR is
+// true.
// clang-format off
-CompPhaseNameMacro(PHASE_PRE_IMPORT, "Pre-import", "PRE-IMP", false, -1)
-CompPhaseNameMacro(PHASE_IMPORTATION, "Importation", "IMPORT", false, -1)
-CompPhaseNameMacro(PHASE_POST_IMPORT, "Post-import", "POST-IMP", false, -1)
-CompPhaseNameMacro(PHASE_MORPH_INIT, "Morph - Init", "MOR-INIT" ,false, -1)
-CompPhaseNameMacro(PHASE_MORPH_INLINE, "Morph - Inlining", "MOR-INL", false, -1)
-CompPhaseNameMacro(PHASE_MORPH_IMPBYREF, "Morph - ByRefs", "MOR-BYREF",false, -1)
-CompPhaseNameMacro(PHASE_EMPTY_TRY, "Remove empty try", "EMPTYTRY", false, -1)
-CompPhaseNameMacro(PHASE_EMPTY_FINALLY, "Remove empty finally", "EMPTYFIN", false, -1)
-CompPhaseNameMacro(PHASE_CLONE_FINALLY, "Clone finally", "CLONEFIN", false, -1)
-CompPhaseNameMacro(PHASE_STR_ADRLCL, "Morph - Structs/AddrExp", "MOR-STRAL",false, -1)
-CompPhaseNameMacro(PHASE_MORPH_GLOBAL, "Morph - Global", "MOR-GLOB", false, -1)
-CompPhaseNameMacro(PHASE_MORPH_END, "Morph - Finish", "MOR-END", false, -1)
-CompPhaseNameMacro(PHASE_GS_COOKIE, "GS Cookie", "GS-COOK", false, -1)
-CompPhaseNameMacro(PHASE_COMPUTE_PREDS, "Compute preds", "PREDS", false, -1)
-CompPhaseNameMacro(PHASE_MARK_GC_POLL_BLOCKS, "Mark GC poll blocks", "GC-POLL", false, -1)
-CompPhaseNameMacro(PHASE_COMPUTE_EDGE_WEIGHTS, "Compute edge weights (1)", "EDG-WGT", false, -1)
+CompPhaseNameMacro(PHASE_PRE_IMPORT, "Pre-import", "PRE-IMP", false, -1, false)
+CompPhaseNameMacro(PHASE_IMPORTATION, "Importation", "IMPORT", false, -1, true)
+CompPhaseNameMacro(PHASE_POST_IMPORT, "Post-import", "POST-IMP", false, -1, false)
+CompPhaseNameMacro(PHASE_MORPH_INIT, "Morph - Init", "MOR-INIT" ,false, -1, false)
+CompPhaseNameMacro(PHASE_MORPH_INLINE, "Morph - Inlining", "MOR-INL", false, -1, true)
+CompPhaseNameMacro(PHASE_MORPH_IMPBYREF, "Morph - ByRefs", "MOR-BYREF",false, -1, false)
+CompPhaseNameMacro(PHASE_EMPTY_TRY, "Remove empty try", "EMPTYTRY", false, -1, false)
+CompPhaseNameMacro(PHASE_EMPTY_FINALLY, "Remove empty finally", "EMPTYFIN", false, -1, false)
+CompPhaseNameMacro(PHASE_MERGE_FINALLY_CHAINS, "Merge callfinally chains", "MRGCFCHN", false, -1, false)
+CompPhaseNameMacro(PHASE_CLONE_FINALLY, "Clone finally", "CLONEFIN", false, -1, false)
+CompPhaseNameMacro(PHASE_STR_ADRLCL, "Morph - Structs/AddrExp", "MOR-STRAL",false, -1, false)
+CompPhaseNameMacro(PHASE_MORPH_GLOBAL, "Morph - Global", "MOR-GLOB", false, -1, false)
+CompPhaseNameMacro(PHASE_MORPH_END, "Morph - Finish", "MOR-END", false, -1, true)
+CompPhaseNameMacro(PHASE_GS_COOKIE, "GS Cookie", "GS-COOK", false, -1, false)
+CompPhaseNameMacro(PHASE_COMPUTE_PREDS, "Compute preds", "PREDS", false, -1, false)
+CompPhaseNameMacro(PHASE_MARK_GC_POLL_BLOCKS, "Mark GC poll blocks", "GC-POLL", false, -1, false)
+CompPhaseNameMacro(PHASE_COMPUTE_EDGE_WEIGHTS, "Compute edge weights (1, false)", "EDG-WGT", false, -1, false)
#if FEATURE_EH_FUNCLETS
-CompPhaseNameMacro(PHASE_CREATE_FUNCLETS, "Create EH funclets", "EH-FUNC", false, -1)
+CompPhaseNameMacro(PHASE_CREATE_FUNCLETS, "Create EH funclets", "EH-FUNC", false, -1, false)
#endif // FEATURE_EH_FUNCLETS
-CompPhaseNameMacro(PHASE_OPTIMIZE_LAYOUT, "Optimize layout", "LAYOUT", false, -1)
-CompPhaseNameMacro(PHASE_ALLOCATE_OBJECTS, "Allocate Objects", "ALLOC-OBJ",false, -1)
-CompPhaseNameMacro(PHASE_OPTIMIZE_LOOPS, "Optimize loops", "LOOP-OPT", false, -1)
-CompPhaseNameMacro(PHASE_CLONE_LOOPS, "Clone loops", "LP-CLONE", false, -1)
-CompPhaseNameMacro(PHASE_UNROLL_LOOPS, "Unroll loops", "UNROLL", false, -1)
-CompPhaseNameMacro(PHASE_HOIST_LOOP_CODE, "Hoist loop code", "LP-HOIST", false, -1)
-CompPhaseNameMacro(PHASE_MARK_LOCAL_VARS, "Mark local vars", "MARK-LCL", false, -1)
-CompPhaseNameMacro(PHASE_OPTIMIZE_BOOLS, "Optimize bools", "OPT-BOOL", false, -1)
-CompPhaseNameMacro(PHASE_FIND_OPER_ORDER, "Find oper order", "OPER-ORD", false, -1)
-CompPhaseNameMacro(PHASE_SET_BLOCK_ORDER, "Set block order", "BLK-ORD", false, -1)
-CompPhaseNameMacro(PHASE_BUILD_SSA, "Build SSA representation", "SSA", true, -1)
-CompPhaseNameMacro(PHASE_BUILD_SSA_TOPOSORT, "SSA: topological sort", "SSA-SORT", false, PHASE_BUILD_SSA)
-CompPhaseNameMacro(PHASE_BUILD_SSA_DOMS, "SSA: Doms1", "SSA-DOMS", false, PHASE_BUILD_SSA)
-CompPhaseNameMacro(PHASE_BUILD_SSA_LIVENESS, "SSA: liveness", "SSA-LIVE", false, PHASE_BUILD_SSA)
-CompPhaseNameMacro(PHASE_BUILD_SSA_IDF, "SSA: IDF", "SSA-IDF", false, PHASE_BUILD_SSA)
-CompPhaseNameMacro(PHASE_BUILD_SSA_INSERT_PHIS, "SSA: insert phis", "SSA-PHI", false, PHASE_BUILD_SSA)
-CompPhaseNameMacro(PHASE_BUILD_SSA_RENAME, "SSA: rename", "SSA-REN", false, PHASE_BUILD_SSA)
+CompPhaseNameMacro(PHASE_OPTIMIZE_LAYOUT, "Optimize layout", "LAYOUT", false, -1, false)
+CompPhaseNameMacro(PHASE_ALLOCATE_OBJECTS, "Allocate Objects", "ALLOC-OBJ",false, -1, false)
+CompPhaseNameMacro(PHASE_OPTIMIZE_LOOPS, "Optimize loops", "LOOP-OPT", false, -1, false)
+CompPhaseNameMacro(PHASE_CLONE_LOOPS, "Clone loops", "LP-CLONE", false, -1, false)
+CompPhaseNameMacro(PHASE_UNROLL_LOOPS, "Unroll loops", "UNROLL", false, -1, false)
+CompPhaseNameMacro(PHASE_HOIST_LOOP_CODE, "Hoist loop code", "LP-HOIST", false, -1, false)
+CompPhaseNameMacro(PHASE_MARK_LOCAL_VARS, "Mark local vars", "MARK-LCL", false, -1, false)
+CompPhaseNameMacro(PHASE_OPTIMIZE_BOOLS, "Optimize bools", "OPT-BOOL", false, -1, false)
+CompPhaseNameMacro(PHASE_FIND_OPER_ORDER, "Find oper order", "OPER-ORD", false, -1, false)
+CompPhaseNameMacro(PHASE_SET_BLOCK_ORDER, "Set block order", "BLK-ORD", false, -1, true)
+CompPhaseNameMacro(PHASE_BUILD_SSA, "Build SSA representation", "SSA", true, -1, false)
+CompPhaseNameMacro(PHASE_BUILD_SSA_TOPOSORT, "SSA: topological sort", "SSA-SORT", false, PHASE_BUILD_SSA, false)
+CompPhaseNameMacro(PHASE_BUILD_SSA_DOMS, "SSA: Doms1", "SSA-DOMS", false, PHASE_BUILD_SSA, false)
+CompPhaseNameMacro(PHASE_BUILD_SSA_LIVENESS, "SSA: liveness", "SSA-LIVE", false, PHASE_BUILD_SSA, false)
+CompPhaseNameMacro(PHASE_BUILD_SSA_IDF, "SSA: IDF", "SSA-IDF", false, PHASE_BUILD_SSA, false)
+CompPhaseNameMacro(PHASE_BUILD_SSA_INSERT_PHIS, "SSA: insert phis", "SSA-PHI", false, PHASE_BUILD_SSA, false)
+CompPhaseNameMacro(PHASE_BUILD_SSA_RENAME, "SSA: rename", "SSA-REN", false, PHASE_BUILD_SSA, false)
-CompPhaseNameMacro(PHASE_EARLY_PROP, "Early Value Propagation", "ERL-PROP", false, -1)
-CompPhaseNameMacro(PHASE_VALUE_NUMBER, "Do value numbering", "VAL-NUM", false, -1)
+CompPhaseNameMacro(PHASE_EARLY_PROP, "Early Value Propagation", "ERL-PROP", false, -1, false)
+CompPhaseNameMacro(PHASE_VALUE_NUMBER, "Do value numbering", "VAL-NUM", false, -1, false)
-CompPhaseNameMacro(PHASE_OPTIMIZE_INDEX_CHECKS, "Optimize index checks", "OPT-CHK", false, -1)
+CompPhaseNameMacro(PHASE_OPTIMIZE_INDEX_CHECKS, "Optimize index checks", "OPT-CHK", false, -1, false)
#if FEATURE_VALNUM_CSE
-CompPhaseNameMacro(PHASE_OPTIMIZE_VALNUM_CSES, "Optimize Valnum CSEs", "OPT-CSE", false, -1)
+CompPhaseNameMacro(PHASE_OPTIMIZE_VALNUM_CSES, "Optimize Valnum CSEs", "OPT-CSE", false, -1, false)
#endif
-CompPhaseNameMacro(PHASE_VN_COPY_PROP, "VN based copy prop", "CP-PROP", false, -1)
+CompPhaseNameMacro(PHASE_VN_COPY_PROP, "VN based copy prop", "CP-PROP", false, -1, false)
#if ASSERTION_PROP
-CompPhaseNameMacro(PHASE_ASSERTION_PROP_MAIN, "Assertion prop", "AST-PROP", false, -1)
+CompPhaseNameMacro(PHASE_ASSERTION_PROP_MAIN, "Assertion prop", "AST-PROP", false, -1, false)
#endif
-CompPhaseNameMacro(PHASE_UPDATE_FLOW_GRAPH, "Update flow graph", "UPD-FG", false, -1)
-CompPhaseNameMacro(PHASE_COMPUTE_EDGE_WEIGHTS2, "Compute edge weights (2)", "EDG-WGT2", false, -1)
-CompPhaseNameMacro(PHASE_DETERMINE_FIRST_COLD_BLOCK, "Determine first cold block", "COLD-BLK", false, -1)
-CompPhaseNameMacro(PHASE_RATIONALIZE, "Rationalize IR", "RAT", false, -1)
-CompPhaseNameMacro(PHASE_SIMPLE_LOWERING, "Do 'simple' lowering", "SMP-LWR", false, -1)
+CompPhaseNameMacro(PHASE_UPDATE_FLOW_GRAPH, "Update flow graph", "UPD-FG", false, -1, false)
+CompPhaseNameMacro(PHASE_COMPUTE_EDGE_WEIGHTS2, "Compute edge weights (2, false)", "EDG-WGT2", false, -1, false)
+CompPhaseNameMacro(PHASE_DETERMINE_FIRST_COLD_BLOCK, "Determine first cold block", "COLD-BLK", false, -1, true)
+CompPhaseNameMacro(PHASE_RATIONALIZE, "Rationalize IR", "RAT", false, -1, false)
+CompPhaseNameMacro(PHASE_SIMPLE_LOWERING, "Do 'simple' lowering", "SMP-LWR", false, -1, false)
-CompPhaseNameMacro(PHASE_LCLVARLIVENESS, "Local var liveness", "LIVENESS", true, -1)
-CompPhaseNameMacro(PHASE_LCLVARLIVENESS_INIT, "Local var liveness init", "LIV-INIT", false, PHASE_LCLVARLIVENESS)
-CompPhaseNameMacro(PHASE_LCLVARLIVENESS_PERBLOCK,"Per block local var liveness", "LIV-BLK", false, PHASE_LCLVARLIVENESS)
-CompPhaseNameMacro(PHASE_LCLVARLIVENESS_INTERBLOCK, "Global local var liveness", "LIV-GLBL", false, PHASE_LCLVARLIVENESS)
+CompPhaseNameMacro(PHASE_LCLVARLIVENESS, "Local var liveness", "LIVENESS", true, -1, false)
+CompPhaseNameMacro(PHASE_LCLVARLIVENESS_INIT, "Local var liveness init", "LIV-INIT", false, PHASE_LCLVARLIVENESS, false)
+CompPhaseNameMacro(PHASE_LCLVARLIVENESS_PERBLOCK,"Per block local var liveness", "LIV-BLK", false, PHASE_LCLVARLIVENESS, false)
+CompPhaseNameMacro(PHASE_LCLVARLIVENESS_INTERBLOCK, "Global local var liveness", "LIV-GLBL", false, PHASE_LCLVARLIVENESS, false)
#ifdef LEGACY_BACKEND
-CompPhaseNameMacro(PHASE_RA_ASSIGN_VARS, "RA assign vars", "REGALLOC", false, -1)
+CompPhaseNameMacro(PHASE_RA_ASSIGN_VARS, "RA assign vars", "REGALLOC", false, -1, false)
#endif // LEGACY_BACKEND
-CompPhaseNameMacro(PHASE_LOWERING_DECOMP, "Lowering decomposition", "LWR-DEC", false, -1)
-CompPhaseNameMacro(PHASE_LOWERING, "Lowering nodeinfo", "LWR-INFO", false, -1)
+CompPhaseNameMacro(PHASE_LOWERING_DECOMP, "Lowering decomposition", "LWR-DEC", false, -1, false)
+CompPhaseNameMacro(PHASE_LOWERING, "Lowering nodeinfo", "LWR-INFO", false, -1, true)
#ifndef LEGACY_BACKEND
-CompPhaseNameMacro(PHASE_LINEAR_SCAN, "Linear scan register alloc", "LSRA", true, -1)
-CompPhaseNameMacro(PHASE_LINEAR_SCAN_BUILD, "LSRA build intervals", "LSRA-BLD", false, PHASE_LINEAR_SCAN)
-CompPhaseNameMacro(PHASE_LINEAR_SCAN_ALLOC, "LSRA allocate", "LSRA-ALL", false, PHASE_LINEAR_SCAN)
-CompPhaseNameMacro(PHASE_LINEAR_SCAN_RESOLVE, "LSRA resolve", "LSRA-RES", false, PHASE_LINEAR_SCAN)
+CompPhaseNameMacro(PHASE_LINEAR_SCAN, "Linear scan register alloc", "LSRA", true, -1, true)
+CompPhaseNameMacro(PHASE_LINEAR_SCAN_BUILD, "LSRA build intervals", "LSRA-BLD", false, PHASE_LINEAR_SCAN, false)
+CompPhaseNameMacro(PHASE_LINEAR_SCAN_ALLOC, "LSRA allocate", "LSRA-ALL", false, PHASE_LINEAR_SCAN, false)
+CompPhaseNameMacro(PHASE_LINEAR_SCAN_RESOLVE, "LSRA resolve", "LSRA-RES", false, PHASE_LINEAR_SCAN, false)
#endif // !LEGACY_BACKEND
-CompPhaseNameMacro(PHASE_GENERATE_CODE, "Generate code", "CODEGEN", false, -1)
-CompPhaseNameMacro(PHASE_EMIT_CODE, "Emit code", "EMIT", false, -1)
-CompPhaseNameMacro(PHASE_EMIT_GCEH, "Emit GC+EH tables", "EMT-GCEH", false, -1)
+CompPhaseNameMacro(PHASE_GENERATE_CODE, "Generate code", "CODEGEN", false, -1, false)
+CompPhaseNameMacro(PHASE_EMIT_CODE, "Emit code", "EMIT", false, -1, false)
+CompPhaseNameMacro(PHASE_EMIT_GCEH, "Emit GC+EH tables", "EMT-GCEH", false, -1, false)
#if MEASURE_CLRAPI_CALLS
// The following is a "pseudo-phase" - it aggregates timing info
// for calls through ICorJitInfo across all "real" phases.
-CompPhaseNameMacro(PHASE_CLR_API, "CLR API calls", "CLR-API", false, -1)
+CompPhaseNameMacro(PHASE_CLR_API, "CLR API calls", "CLR-API", false, -1, false)
#endif
// clang-format on
diff --git a/src/jit/emit.cpp b/src/jit/emit.cpp
index 1e566b2e76..70a4905e26 100644
--- a/src/jit/emit.cpp
+++ b/src/jit/emit.cpp
@@ -4233,7 +4233,7 @@ void emitter::emitCheckFuncletBranch(instrDesc* jmp, insGroup* jmpIG)
// meets one of those criteria...
assert(jmp->idIsBound());
-#ifdef _TARGET_AMD64_
+#ifdef _TARGET_XARCH_
// An lea of a code address (for constant data stored with the code)
// is treated like a jump for emission purposes but is not really a jump so
// we don't have to check anything here.
diff --git a/src/jit/emitxarch.cpp b/src/jit/emitxarch.cpp
index be5cefbfea..796af19a92 100644
--- a/src/jit/emitxarch.cpp
+++ b/src/jit/emitxarch.cpp
@@ -81,9 +81,11 @@ bool emitter::IsThreeOperandBinaryAVXInstruction(instruction ins)
ins == INS_minsd || ins == INS_divps || ins == INS_divpd || ins == INS_maxps || ins == INS_maxpd ||
ins == INS_maxss || ins == INS_maxsd || ins == INS_andnps || ins == INS_andnpd || ins == INS_paddb ||
ins == INS_paddw || ins == INS_paddd || ins == INS_paddq || ins == INS_psubb || ins == INS_psubw ||
- ins == INS_psubd || ins == INS_psubq || ins == INS_pmuludq || ins == INS_pxor || ins == INS_pmaxub ||
- ins == INS_pminub || ins == INS_pmaxsw || ins == INS_pminsw || ins == INS_insertps ||
- ins == INS_vinsertf128 || ins == INS_punpckldq || ins == INS_phaddd);
+ ins == INS_psubd || ins == INS_psubq || ins == INS_pmuludq || ins == INS_pxor || ins == INS_insertps ||
+ ins == INS_vinsertf128 || ins == INS_punpckldq || ins == INS_phaddd || ins == INS_pminub ||
+ ins == INS_pminsw || ins == INS_pminsb || ins == INS_pminsd || ins == INS_pminuw || ins == INS_pminud ||
+ ins == INS_pmaxub || ins == INS_pmaxsw || ins == INS_pmaxsb || ins == INS_pmaxsd || ins == INS_pmaxuw ||
+ ins == INS_pmaxud);
}
// Returns true if the AVX instruction is a move operator that requires 3 operands.
@@ -115,7 +117,9 @@ bool emitter::Is4ByteAVXInstruction(instruction ins)
(ins == INS_dpps || ins == INS_dppd || ins == INS_insertps || ins == INS_pcmpeqq || ins == INS_pcmpgtq ||
ins == INS_vbroadcastss || ins == INS_vbroadcastsd || ins == INS_vpbroadcastb || ins == INS_vpbroadcastw ||
ins == INS_vpbroadcastd || ins == INS_vpbroadcastq || ins == INS_vextractf128 || ins == INS_vinsertf128 ||
- ins == INS_pmulld || ins == INS_ptest || ins == INS_phaddd);
+ ins == INS_pmulld || ins == INS_ptest || ins == INS_phaddd || ins == INS_pminsb || ins == INS_pminsd ||
+ ins == INS_pminuw || ins == INS_pminud || ins == INS_pmaxsb || ins == INS_pmaxsd || ins == INS_pmaxuw ||
+ ins == INS_pmaxud);
}
#endif // FEATURE_AVX_SUPPORT
@@ -135,7 +139,9 @@ bool emitter::Is4ByteSSE4Instruction(instruction ins)
return false;
#else
return UseSSE3_4() && (ins == INS_dpps || ins == INS_dppd || ins == INS_insertps || ins == INS_pcmpeqq ||
- ins == INS_pcmpgtq || ins == INS_pmulld || ins == INS_ptest || ins == INS_phaddd);
+ ins == INS_pcmpgtq || ins == INS_pmulld || ins == INS_ptest || ins == INS_phaddd ||
+ ins == INS_pminsb || ins == INS_pminsd || ins == INS_pminuw || ins == INS_pminud ||
+ ins == INS_pmaxsb || ins == INS_pmaxsd || ins == INS_pmaxuw || ins == INS_pmaxud);
#endif
}
diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp
index 50318b0940..cd6ff3d527 100644
--- a/src/jit/flowgraph.cpp
+++ b/src/jit/flowgraph.cpp
@@ -5779,11 +5779,12 @@ void Compiler::fgFindBasicBlocks()
compHndBBtabCount = impInlineInfo->InlinerCompiler->compHndBBtabCount;
info.compXcptnsCount = impInlineInfo->InlinerCompiler->info.compXcptnsCount;
- // Use a spill temp for the return value if there are multiple return blocks.
- if ((info.compRetNativeType != TYP_VOID) && (retBlocks > 1))
+ // Use a spill temp for the return value if there are multiple return blocks,
+ // or if the inlinee has GC ref locals.
+ if ((info.compRetNativeType != TYP_VOID) && ((retBlocks > 1) || impInlineInfo->HasGcRefLocals()))
{
// The lifetime of this var might expand multiple BBs. So it is a long lifetime compiler temp.
- lvaInlineeReturnSpillTemp = lvaGrabTemp(false DEBUGARG("Inline candidate multiple BBJ_RETURN spill temp"));
+ lvaInlineeReturnSpillTemp = lvaGrabTemp(false DEBUGARG("Inline return value spill temp"));
lvaTable[lvaInlineeReturnSpillTemp].lvType = info.compRetNativeType;
}
@@ -21784,7 +21785,7 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo)
}
#endif // DEBUG
- // Append statements to unpin, if necessary.
+ // Append statements to null out gc ref locals, if necessary.
fgInlineAppendStatements(pInlineInfo, iciBlock, stmtAfter);
goto _Done;
@@ -21954,7 +21955,7 @@ void Compiler::fgInsertInlineeBlocks(InlineInfo* pInlineInfo)
//
fgBBcount += InlineeCompiler->fgBBcount;
- // Append statements to unpin if necessary.
+ // Append statements to null out gc ref locals, if necessary.
fgInlineAppendStatements(pInlineInfo, bottomBlock, nullptr);
#ifdef DEBUG
@@ -22336,45 +22337,71 @@ GenTreePtr Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo)
// inlineInfo - information about the inline
// block - basic block for the new statements
// stmtAfter - (optional) insertion point for mid-block cases
+//
+// Notes:
+// If the call we're inlining is in tail position then
+// we skip nulling the locals, since it can interfere
+// with tail calls introduced by the local.
void Compiler::fgInlineAppendStatements(InlineInfo* inlineInfo, BasicBlock* block, GenTreePtr stmtAfter)
{
- // Null out any inline pinned locals
- if (!inlineInfo->hasPinnedLocals)
+ // Null out any gc ref locals
+ if (!inlineInfo->HasGcRefLocals())
{
- // No pins, nothing to do
+ // No ref locals, nothing to do.
+ JITDUMP("fgInlineAppendStatements: no gc ref inline locals.\n");
return;
}
- JITDUMP("Unpin inlinee locals:\n");
+ if (inlineInfo->iciCall->IsImplicitTailCall())
+ {
+ JITDUMP("fgInlineAppendStatements: implicit tail call; skipping nulling.\n");
+ return;
+ }
+
+ JITDUMP("fgInlineAppendStatements: nulling out gc ref inlinee locals.\n");
GenTreePtr callStmt = inlineInfo->iciStmt;
IL_OFFSETX callILOffset = callStmt->gtStmt.gtStmtILoffsx;
CORINFO_METHOD_INFO* InlineeMethodInfo = InlineeCompiler->info.compMethodInfo;
- unsigned lclCnt = InlineeMethodInfo->locals.numArgs;
+ const unsigned lclCnt = InlineeMethodInfo->locals.numArgs;
InlLclVarInfo* lclVarInfo = inlineInfo->lclVarInfo;
+ unsigned gcRefLclCnt = inlineInfo->numberOfGcRefLocals;
+ const unsigned argCnt = inlineInfo->argCnt;
noway_assert(callStmt->gtOper == GT_STMT);
for (unsigned lclNum = 0; lclNum < lclCnt; lclNum++)
{
- unsigned tmpNum = inlineInfo->lclTmpNum[lclNum];
+ // Is the local a gc ref type? Need to look at the
+ // inline info for this since we will not have local
+ // temps for unused inlinee locals.
+ const var_types lclTyp = lclVarInfo[argCnt + lclNum].lclTypeInfo;
- // Is the local used at all?
- if (tmpNum == BAD_VAR_NUM)
+ if (!varTypeIsGC(lclTyp))
{
- // Nope, nothing to unpin.
+ // Nope, nothing to null out.
continue;
}
- // Is the local pinned?
- if (!lvaTable[tmpNum].lvPinned)
+ // Ensure we're examining just the right number of locals.
+ assert(gcRefLclCnt > 0);
+ gcRefLclCnt--;
+
+ // Fetch the temp for this inline local
+ const unsigned tmpNum = inlineInfo->lclTmpNum[lclNum];
+
+ // Is the local used at all?
+ if (tmpNum == BAD_VAR_NUM)
{
- // Nope, nothing to unpin.
+ // Nope, nothing to null out.
continue;
}
- // Does the local we're about to unpin appear in the return
+ // Local was used, make sure the type is consistent.
+ assert(lvaTable[tmpNum].lvType == lclTyp);
+
+ // Does the local we're about to null out appear in the return
// expression? If so we somehow messed up and didn't properly
// spill the return value. See impInlineFetchLocal.
GenTreePtr retExpr = inlineInfo->retExpr;
@@ -22384,29 +22411,29 @@ void Compiler::fgInlineAppendStatements(InlineInfo* inlineInfo, BasicBlock* bloc
noway_assert(!interferesWithReturn);
}
- // Emit the unpin, by assigning null to the local.
- var_types lclTyp = (var_types)lvaTable[tmpNum].lvType;
- noway_assert(lclTyp == lclVarInfo[lclNum + inlineInfo->argCnt].lclTypeInfo);
- noway_assert(!varTypeIsStruct(lclTyp));
- GenTreePtr unpinExpr = gtNewTempAssign(tmpNum, gtNewZeroConNode(genActualType(lclTyp)));
- GenTreePtr unpinStmt = gtNewStmt(unpinExpr, callILOffset);
+ // Assign null to the local.
+ GenTreePtr nullExpr = gtNewTempAssign(tmpNum, gtNewZeroConNode(lclTyp));
+ GenTreePtr nullStmt = gtNewStmt(nullExpr, callILOffset);
if (stmtAfter == nullptr)
{
- stmtAfter = fgInsertStmtAtBeg(block, unpinStmt);
+ stmtAfter = fgInsertStmtAtBeg(block, nullStmt);
}
else
{
- stmtAfter = fgInsertStmtAfter(block, stmtAfter, unpinStmt);
+ stmtAfter = fgInsertStmtAfter(block, stmtAfter, nullStmt);
}
#ifdef DEBUG
if (verbose)
{
- gtDispTree(unpinStmt);
+ gtDispTree(nullStmt);
}
#endif // DEBUG
}
+
+ // There should not be any GC ref locals left to null out.
+ assert(gcRefLclCnt == 0);
}
/*****************************************************************************/
@@ -22512,6 +22539,14 @@ void Compiler::fgRemoveEmptyFinally()
{
JITDUMP("\n*************** In fgRemoveEmptyFinally()\n");
+#if FEATURE_EH_FUNCLETS
+ // We need to do this transformation before funclets are created.
+ assert(!fgFuncletsCreated);
+#endif // FEATURE_EH_FUNCLETS
+
+ // Assume we don't need to update the bbPreds lists.
+ assert(!fgComputePredsDone);
+
if (compHndBBtabCount == 0)
{
JITDUMP("No EH in this method, nothing to remove.\n");
@@ -22741,6 +22776,14 @@ void Compiler::fgRemoveEmptyTry()
{
JITDUMP("\n*************** In fgRemoveEmptyTry()\n");
+#if FEATURE_EH_FUNCLETS
+ // We need to do this transformation before funclets are created.
+ assert(!fgFuncletsCreated);
+#endif // FEATURE_EH_FUNCLETS
+
+ // Assume we don't need to update the bbPreds lists.
+ assert(!fgComputePredsDone);
+
#ifdef FEATURE_CORECLR
bool enableRemoveEmptyTry = true;
#else
@@ -22995,6 +23038,7 @@ void Compiler::fgRemoveEmptyTry()
fgRemoveStmt(block, finallyRet);
block->bbJumpKind = BBJ_ALWAYS;
block->bbJumpDest = continuation;
+ fgAddRefPred(continuation, block);
}
}
}
@@ -23060,6 +23104,14 @@ void Compiler::fgCloneFinally()
{
JITDUMP("\n*************** In fgCloneFinally()\n");
+#if FEATURE_EH_FUNCLETS
+ // We need to do this transformation before funclets are created.
+ assert(!fgFuncletsCreated);
+#endif // FEATURE_EH_FUNCLETS
+
+ // Assume we don't need to update the bbPreds lists.
+ assert(!fgComputePredsDone);
+
#ifdef FEATURE_CORECLR
bool enableCloning = true;
#else
@@ -23564,7 +23616,7 @@ void Compiler::fgCloneFinally()
BasicBlock* firstClonedBlock = blockMap[firstBlock];
firstClonedBlock->bbCatchTyp = BBCT_NONE;
- // Cleanup the contination
+ // Cleanup the continuation
fgCleanupContinuation(normalCallFinallyReturn);
// Todo -- mark cloned blocks as a cloned finally....
@@ -23873,6 +23925,271 @@ void Compiler::fgUpdateFinallyTargetFlags()
#endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
}
+//------------------------------------------------------------------------
+// fgMergeFinallyChains: tail merge finally invocations
+//
+// Notes:
+//
+// Looks for common suffixes in chains of finally invocations
+// (callfinallys) and merges them. These typically arise from
+// try-finallys where there are multiple exit points in the try
+// that have the same target.
+
+void Compiler::fgMergeFinallyChains()
+{
+ JITDUMP("\n*************** In fgMergeFinallyChains()\n");
+
+#if FEATURE_EH_FUNCLETS
+ // We need to do this transformation before funclets are created.
+ assert(!fgFuncletsCreated);
+#endif // FEATURE_EH_FUNCLETS
+
+ // Assume we don't need to update the bbPreds lists.
+ assert(!fgComputePredsDone);
+
+ if (compHndBBtabCount == 0)
+ {
+ JITDUMP("No EH in this method, nothing to merge.\n");
+ return;
+ }
+
+ if (opts.MinOpts())
+ {
+ JITDUMP("Method compiled with minOpts, no merging.\n");
+ return;
+ }
+
+ if (opts.compDbgCode)
+ {
+ JITDUMP("Method compiled with debug codegen, no merging.\n");
+ return;
+ }
+
+#if !FEATURE_EH_FUNCLETS
+ // For non-funclet models (x86) the callfinallys may contain
+ // statements and the continuations contain GT_END_LFINs. So no
+ // merging is possible until the GT_END_LFIN blocks can be merged
+ // and merging is not safe unless the callfinally blocks are split.
+ JITDUMP("EH using non-funclet model; merging not yet implemented.\n");
+ return;
+#endif // !FEATURE_EH_FUNCLETS
+
+#if !FEATURE_EH_CALLFINALLY_THUNKS
+ // For non-thunk EH models (arm32) the callfinallys may contain
+ // statements, and merging is not safe unless the callfinally
+ // blocks are split.
+ JITDUMP("EH using non-callfinally thunk model; merging not yet implemented.\n");
+ return;
+#endif
+
+#ifdef DEBUG
+ if (verbose)
+ {
+ printf("\n*************** Before fgMergeFinallyChains()\n");
+ fgDispBasicBlocks();
+ fgDispHandlerTab();
+ printf("\n");
+ }
+#endif // DEBUG
+
+ // Look for finallys.
+ bool hasFinally = false;
+ for (unsigned XTnum = 0; XTnum < compHndBBtabCount; XTnum++)
+ {
+ EHblkDsc* const HBtab = &compHndBBtab[XTnum];
+
+ // Check if this is a try/finally.
+ if (HBtab->HasFinallyHandler())
+ {
+ hasFinally = true;
+ break;
+ }
+ }
+
+ if (!hasFinally)
+ {
+ JITDUMP("Method does not have any try-finallys; no merging.\n");
+ return;
+ }
+
+ // Process finallys from outside in, merging as we go. This gives
+ // us the desired bottom-up tail merge order for callfinally
+ // chains: outer merges may enable inner merges.
+ bool canMerge = false;
+ bool didMerge = false;
+ BlockToBlockMap continuationMap(getAllocator());
+
+ // Note XTnum is signed here so we can count down.
+ for (int XTnum = compHndBBtabCount - 1; XTnum >= 0; XTnum--)
+ {
+ EHblkDsc* const HBtab = &compHndBBtab[XTnum];
+
+ // Screen out non-finallys
+ if (!HBtab->HasFinallyHandler())
+ {
+ continue;
+ }
+
+ JITDUMP("Examining callfinallys for EH#%d.\n", XTnum);
+
+ // Find all the callfinallys that invoke this finally.
+ BasicBlock* firstCallFinallyRangeBlock = nullptr;
+ BasicBlock* endCallFinallyRangeBlock = nullptr;
+ ehGetCallFinallyBlockRange(XTnum, &firstCallFinallyRangeBlock, &endCallFinallyRangeBlock);
+
+ // Clear out any stale entries in the continuation map
+ continuationMap.RemoveAll();
+
+ // Build a map from each continuation to the "canonical"
+ // callfinally for that continuation.
+ unsigned callFinallyCount = 0;
+ BasicBlock* const beginHandlerBlock = HBtab->ebdHndBeg;
+
+ for (BasicBlock* currentBlock = firstCallFinallyRangeBlock; currentBlock != endCallFinallyRangeBlock;
+ currentBlock = currentBlock->bbNext)
+ {
+ // Ignore "retless" callfinallys (where the finally doesn't return).
+ if (currentBlock->isBBCallAlwaysPair() && (currentBlock->bbJumpDest == beginHandlerBlock))
+ {
+ // The callfinally must be empty, so that we can
+ // safely retarget anything that branches here to
+ // another callfinally with the same contiuation.
+ assert(currentBlock->isEmpty());
+
+ // This callfinally invokes the finally for this try.
+ callFinallyCount++;
+
+ // Locate the continuation
+ BasicBlock* const leaveBlock = currentBlock->bbNext;
+ BasicBlock* const continuationBlock = leaveBlock->bbJumpDest;
+
+ // If this is the first time we've seen this
+ // continuation, register this callfinally as the
+ // canonical one.
+ if (!continuationMap.Lookup(continuationBlock))
+ {
+ continuationMap.Set(continuationBlock, currentBlock);
+ }
+ }
+ }
+
+ // Now we've seen all the callfinallys and their continuations.
+ JITDUMP("EH#%i has %u callfinallys, %u continuations\n", XTnum, callFinallyCount, continuationMap.GetCount());
+
+ // If there are more callfinallys than continuations, some of the
+ // callfinallys must share a continuation, and we can merge them.
+ const bool tryMerge = callFinallyCount > continuationMap.GetCount();
+
+ if (!tryMerge)
+ {
+ JITDUMP("EH#%i does not have any mergeable callfinallys\n", XTnum);
+ continue;
+ }
+
+ canMerge = true;
+
+ // Walk the callfinally region, looking for blocks that jump
+ // to a callfinally that invokes this try's finally, and make
+ // sure they all jump to the appropriate canonical
+ // callfinally.
+ for (BasicBlock* currentBlock = firstCallFinallyRangeBlock; currentBlock != endCallFinallyRangeBlock;
+ currentBlock = currentBlock->bbNext)
+ {
+ bool merged = fgRetargetBranchesToCanonicalCallFinally(currentBlock, beginHandlerBlock, continuationMap);
+ didMerge = didMerge || merged;
+ }
+ }
+
+ if (!canMerge)
+ {
+ JITDUMP("Method had try-finallys, but did not have any mergeable finally chains.\n");
+ }
+ else
+ {
+ assert(didMerge);
+ JITDUMP("Method had try-finallys and some callfinally merges were performed.\n");
+
+#if DEBUG
+
+ if (verbose)
+ {
+ printf("\n*************** After fgMergeFinallyChains()\n");
+ fgDispBasicBlocks();
+ fgDispHandlerTab();
+ printf("\n");
+ }
+
+#endif // DEBUG
+ }
+}
+
+//------------------------------------------------------------------------
+// fgRetargetBranchesToCanonicalCallFinally: find non-canonical callfinally
+// invocations and make them canonical.
+//
+// Arguments:
+// block -- block to examine for call finally invocation
+// handler -- start of the finally region for the try
+// continuationMap -- map giving the canonical callfinally for
+// each continuation
+//
+// Returns:
+// true iff the block's branch was retargeted.
+
+bool Compiler::fgRetargetBranchesToCanonicalCallFinally(BasicBlock* block,
+ BasicBlock* handler,
+ BlockToBlockMap& continuationMap)
+{
+ // We expect callfinallys to be invoked by a BBJ_ALWAYS at this
+ // stage in compilation.
+ if (block->bbJumpKind != BBJ_ALWAYS)
+ {
+ // Possible paranoia assert here -- no flow successor of
+ // this block should be a callfinally for this try.
+ return false;
+ }
+
+ // Screen out cases that are not callfinallys to the right
+ // handler.
+ BasicBlock* const callFinally = block->bbJumpDest;
+
+ if (!callFinally->isBBCallAlwaysPair())
+ {
+ return false;
+ }
+
+ if (callFinally->bbJumpDest != handler)
+ {
+ return false;
+ }
+
+ // Ok, this is a callfinally that invokes the right handler.
+ // Get its continuation.
+ BasicBlock* const leaveBlock = callFinally->bbNext;
+ BasicBlock* const continuationBlock = leaveBlock->bbJumpDest;
+
+ // Find the canonical callfinally for that continuation.
+ BasicBlock* const canonicalCallFinally = continuationMap[continuationBlock];
+ assert(canonicalCallFinally != nullptr);
+
+ // If the block already jumps to the canoncial call finally, no work needed.
+ if (block->bbJumpDest == canonicalCallFinally)
+ {
+ return false;
+ }
+
+ // Else, retarget it so that it does...
+ JITDUMP("Redirecting branch in BB%02u from BB%02u to BB%02u.\n", block->bbNum, callFinally->bbNum,
+ canonicalCallFinally->bbNum);
+
+ block->bbJumpDest = canonicalCallFinally;
+ fgAddRefPred(canonicalCallFinally, block);
+ assert(callFinally->bbRefs > 0);
+ fgRemoveRefPred(callFinally, block);
+
+ return true;
+}
+
// FatCalliTransformer transforms calli that can use fat function pointer.
// Fat function pointer is pointer with the second least significant bit set,
// if the bit is set, the pointer (after clearing the bit) actually points to
@@ -24256,3 +24573,36 @@ void Compiler::fgTransformFatCalli()
CheckNoFatPointerCandidatesLeft();
#endif
}
+
+//------------------------------------------------------------------------
+// fgMeasureIR: count and return the number of IR nodes in the function.
+//
+unsigned Compiler::fgMeasureIR()
+{
+ unsigned nodeCount = 0;
+
+ for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
+ {
+ if (!block->IsLIR())
+ {
+ for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt())
+ {
+ fgWalkTreePre(&stmt->gtStmtExpr,
+ [](GenTree** slot, fgWalkData* data) -> Compiler::fgWalkResult {
+ (*reinterpret_cast<unsigned*>(data->pCallbackData))++;
+ return Compiler::WALK_CONTINUE;
+ },
+ &nodeCount);
+ }
+ }
+ else
+ {
+ for (GenTree* node : LIR::AsRange(block))
+ {
+ nodeCount++;
+ }
+ }
+ }
+
+ return nodeCount;
+}
diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp
index 7a489332f5..c1b879041d 100644
--- a/src/jit/importer.cpp
+++ b/src/jit/importer.cpp
@@ -6467,8 +6467,7 @@ var_types Compiler::impImportCall(OPCODE opcode,
bool managedCall = (calliSig.callConv & GTF_CALL_UNMANAGED) == 0;
if (managedCall)
{
- call->AsCall()->SetFatPointerCandidate();
- setMethodHasFatPointer();
+ addFatPointerCandidate(call->AsCall());
}
}
}
@@ -6772,7 +6771,31 @@ var_types Compiler::impImportCall(OPCODE opcode,
thisPtr = impCloneExpr(thisPtr, &thisPtrCopy, NO_CLASS_HANDLE, (unsigned)CHECK_SPILL_ALL,
nullptr DEBUGARG("LDVIRTFTN this pointer"));
- GenTreePtr fptr = impImportLdvirtftn(thisPtr, pResolvedToken, callInfo);
+ GenTreePtr fptr = nullptr;
+ bool coreRTGenericVirtualMethod =
+ ((sig->callConv & CORINFO_CALLCONV_GENERIC) != 0) && IsTargetAbi(CORINFO_CORERT_ABI);
+#if COR_JIT_EE_VERSION > 460
+ if (coreRTGenericVirtualMethod)
+ {
+ GenTreePtr runtimeMethodHandle = nullptr;
+ if (callInfo->exactContextNeedsRuntimeLookup)
+ {
+ runtimeMethodHandle =
+ impRuntimeLookupToTree(pResolvedToken, &callInfo->codePointerLookup, methHnd);
+ }
+ else
+ {
+ runtimeMethodHandle = gtNewIconEmbMethHndNode(pResolvedToken->hMethod);
+ }
+ fptr = gtNewHelperCallNode(CORINFO_HELP_GVMLOOKUP_FOR_SLOT, TYP_I_IMPL, GTF_EXCEPT,
+ gtNewArgList(thisPtr, runtimeMethodHandle));
+ }
+ else
+#endif // COR_JIT_EE_VERSION
+ {
+ fptr = impImportLdvirtftn(thisPtr, pResolvedToken, callInfo);
+ }
+
if (compDonotInline())
{
return callRetTyp;
@@ -6792,6 +6815,10 @@ var_types Compiler::impImportCall(OPCODE opcode,
call->gtCall.gtCallObjp = thisPtrCopy;
call->gtFlags |= GTF_EXCEPT | (fptr->gtFlags & GTF_GLOB_EFFECT);
+ if (coreRTGenericVirtualMethod)
+ {
+ addFatPointerCandidate(call->AsCall());
+ }
#ifdef FEATURE_READYTORUN_COMPILER
if (opts.IsReadyToRun())
{
@@ -7692,10 +7719,33 @@ DONE_CALL:
call = gtNewLclvNode(calliSlot, type);
}
}
+
// For non-candidates we must also spill, since we
// might have locals live on the eval stack that this
// call can modify.
- impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("non-inline candidate call"));
+ //
+ // Suppress this for certain well-known call targets
+ // that we know won't modify locals, eg calls that are
+ // recognized in gtCanOptimizeTypeEquality. Otherwise
+ // we may break key fragile pattern matches later on.
+ bool spillStack = true;
+ if (call->IsCall())
+ {
+ GenTreeCall* callNode = call->AsCall();
+ if ((callNode->gtCallType == CT_HELPER) && gtIsTypeHandleToRuntimeTypeHelper(callNode))
+ {
+ spillStack = false;
+ }
+ else if ((callNode->gtCallMoreFlags & GTF_CALL_M_SPECIAL_INTRINSIC) != 0)
+ {
+ spillStack = false;
+ }
+ }
+
+ if (spillStack)
+ {
+ impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("non-inline candidate call"));
+ }
}
}
@@ -12813,7 +12863,7 @@ void Compiler::impImportBlockCode(BasicBlock* block)
impHandleAccessAllowed(callInfo.accessAllowed, &callInfo.callsiteCalloutHelper);
#if 0 // DevDiv 410397 - This breaks too many obfuscated apps to do this in an in-place release
-
+
// DevDiv 291703 - we need to check for accessibility between the caller of InitializeArray
// and the field it is reading, thus it is now unverifiable to not immediately precede with
// ldtoken <filed token>, and we now check accessibility
@@ -15014,6 +15064,16 @@ bool Compiler::impReturnInstruction(BasicBlock* block, int prefixFlags, OPCODE&
Verify(verCurrentState.esStackDepth == expectedStack, "stack non-empty on return");
}
+#ifdef DEBUG
+ // If we are importing an inlinee and have GC ref locals we always
+ // need to have a spill temp for the return value. This temp
+ // should have been set up in advance, over in fgFindBasicBlocks.
+ if (compIsForInlining() && impInlineInfo->HasGcRefLocals() && (info.compRetType != TYP_VOID))
+ {
+ assert(lvaInlineeReturnSpillTemp != BAD_VAR_NUM);
+ }
+#endif // DEBUG
+
GenTree* op2 = nullptr;
GenTree* op1 = nullptr;
CORINFO_CLASS_HANDLE retClsHnd = nullptr;
@@ -15120,7 +15180,7 @@ bool Compiler::impReturnInstruction(BasicBlock* block, int prefixFlags, OPCODE&
if (lvaInlineeReturnSpillTemp != BAD_VAR_NUM)
{
assert(info.compRetNativeType != TYP_VOID &&
- (fgMoreThanOneReturnBlock() || impInlineInfo->hasPinnedLocals));
+ (fgMoreThanOneReturnBlock() || impInlineInfo->HasGcRefLocals()));
// This is a bit of a workaround...
// If we are inlining a call that returns a struct, where the actual "native" return type is
@@ -15211,7 +15271,7 @@ bool Compiler::impReturnInstruction(BasicBlock* block, int prefixFlags, OPCODE&
// in this case we have to insert multiple struct copies to the temp
// and the retexpr is just the temp.
assert(info.compRetNativeType != TYP_VOID);
- assert(fgMoreThanOneReturnBlock() || impInlineInfo->hasPinnedLocals);
+ assert(fgMoreThanOneReturnBlock() || impInlineInfo->HasGcRefLocals());
impAssignTempGen(lvaInlineeReturnSpillTemp, op2, se.seTypeInfo.GetClassHandle(),
(unsigned)CHECK_SPILL_ALL);
@@ -17641,6 +17701,11 @@ void Compiler::impInlineInitVars(InlineInfo* pInlineInfo)
lclVarInfo[i + argCnt].lclIsPinned = isPinned;
lclVarInfo[i + argCnt].lclTypeInfo = type;
+ if (varTypeIsGC(type))
+ {
+ pInlineInfo->numberOfGcRefLocals++;
+ }
+
if (isPinned)
{
// Pinned locals may cause inlines to fail.
@@ -17705,6 +17770,23 @@ void Compiler::impInlineInitVars(InlineInfo* pInlineInfo)
#endif // FEATURE_SIMD
}
+//------------------------------------------------------------------------
+// impInlineFetchLocal: get a local var that represents an inlinee local
+//
+// Arguments:
+// lclNum -- number of the inlinee local
+// reason -- debug string describing purpose of the local var
+//
+// Returns:
+// Number of the local to use
+//
+// Notes:
+// This method is invoked only for locals actually used in the
+// inlinee body.
+//
+// Allocates a new temp if necessary, and copies key properties
+// over from the inlinee local var info.
+
unsigned Compiler::impInlineFetchLocal(unsigned lclNum DEBUGARG(const char* reason))
{
assert(compIsForInlining());
@@ -17713,55 +17795,46 @@ unsigned Compiler::impInlineFetchLocal(unsigned lclNum DEBUGARG(const char* reas
if (tmpNum == BAD_VAR_NUM)
{
- var_types lclTyp = impInlineInfo->lclVarInfo[lclNum + impInlineInfo->argCnt].lclTypeInfo;
+ const InlLclVarInfo& inlineeLocal = impInlineInfo->lclVarInfo[lclNum + impInlineInfo->argCnt];
+ const var_types lclTyp = inlineeLocal.lclTypeInfo;
// The lifetime of this local might span multiple BBs.
// So it is a long lifetime local.
impInlineInfo->lclTmpNum[lclNum] = tmpNum = lvaGrabTemp(false DEBUGARG(reason));
- lvaTable[tmpNum].lvType = lclTyp;
- if (impInlineInfo->lclVarInfo[lclNum + impInlineInfo->argCnt].lclHasLdlocaOp)
- {
- lvaTable[tmpNum].lvHasLdAddrOp = 1;
- }
-
- if (impInlineInfo->lclVarInfo[lclNum + impInlineInfo->argCnt].lclIsPinned)
- {
- lvaTable[tmpNum].lvPinned = 1;
-
- if (!impInlineInfo->hasPinnedLocals)
- {
- // If the inlinee returns a value, use a spill temp
- // for the return value to ensure that even in case
- // where the return expression refers to one of the
- // pinned locals, we can unpin the local right after
- // the inlined method body.
- if ((info.compRetNativeType != TYP_VOID) && (lvaInlineeReturnSpillTemp == BAD_VAR_NUM))
- {
- lvaInlineeReturnSpillTemp =
- lvaGrabTemp(false DEBUGARG("Inline candidate pinned local return spill temp"));
- lvaTable[lvaInlineeReturnSpillTemp].lvType = info.compRetNativeType;
- }
- }
-
- impInlineInfo->hasPinnedLocals = true;
- }
+ // Copy over key info
+ lvaTable[tmpNum].lvType = lclTyp;
+ lvaTable[tmpNum].lvHasLdAddrOp = inlineeLocal.lclHasLdlocaOp;
+ lvaTable[tmpNum].lvPinned = inlineeLocal.lclIsPinned;
- if (impInlineInfo->lclVarInfo[lclNum + impInlineInfo->argCnt].lclVerTypeInfo.IsStruct())
+ if (inlineeLocal.lclVerTypeInfo.IsStruct())
{
if (varTypeIsStruct(lclTyp))
{
- lvaSetStruct(tmpNum,
- impInlineInfo->lclVarInfo[lclNum + impInlineInfo->argCnt].lclVerTypeInfo.GetClassHandle(),
- true /* unsafe value cls check */);
+ lvaSetStruct(tmpNum, inlineeLocal.lclVerTypeInfo.GetClassHandle(), true /* unsafe value cls check */);
}
else
{
// This is a wrapped primitive. Make sure the verstate knows that
- lvaTable[tmpNum].lvVerTypeInfo =
- impInlineInfo->lclVarInfo[lclNum + impInlineInfo->argCnt].lclVerTypeInfo;
+ lvaTable[tmpNum].lvVerTypeInfo = inlineeLocal.lclVerTypeInfo;
}
}
+
+#ifdef DEBUG
+ // Sanity check that we're properly prepared for gc ref locals.
+ if (varTypeIsGC(lclTyp))
+ {
+ // Since there are gc locals we should have seen them earlier
+ // and if there was a return value, set up the spill temp.
+ assert(impInlineInfo->HasGcRefLocals());
+ assert((info.compRetNativeType == TYP_VOID) || (lvaInlineeReturnSpillTemp != BAD_VAR_NUM));
+ }
+ else
+ {
+ // Make sure all pinned locals count as gc refs.
+ assert(!inlineeLocal.lclIsPinned);
+ }
+#endif // DEBUG
}
return tmpNum;
diff --git a/src/jit/inline.h b/src/jit/inline.h
index 2634ebe6fa..7bd0ae483c 100644
--- a/src/jit/inline.h
+++ b/src/jit/inline.h
@@ -563,8 +563,15 @@ struct InlineInfo
int lclTmpNum[MAX_INL_LCLS]; // map local# -> temp# (-1 if unused)
InlLclVarInfo lclVarInfo[MAX_INL_LCLS + MAX_INL_ARGS + 1]; // type information from local sig
+ unsigned numberOfGcRefLocals; // Number of TYP_REF and TYP_BYREF locals
+
+ bool HasGcRefLocals() const
+ {
+ return numberOfGcRefLocals > 0;
+ }
+
bool thisDereferencedFirst;
- bool hasPinnedLocals;
+
#ifdef FEATURE_SIMD
bool hasSIMDTypeArgLocalOrReturn;
#endif // FEATURE_SIMD
diff --git a/src/jit/instrsxarch.h b/src/jit/instrsxarch.h
index 8ab3a845ba..70a7243866 100644
--- a/src/jit/instrsxarch.h
+++ b/src/jit/instrsxarch.h
@@ -323,6 +323,14 @@ INST3( phaddd, "phaddd" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SS
INST3( pabsb, "pabsb" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE38(0x1C)) // Packed absolute value of bytes
INST3( pabsw, "pabsw" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE38(0x1D)) // Packed absolute value of 16-bit integers
INST3( pabsd, "pabsd" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE38(0x1E)) // Packed absolute value of 32-bit integers
+INST3( pminsb, "pminsb" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE38(0x38)) // packed minimum signed bytes
+INST3( pminsd, "pminsd" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE38(0x39)) // packed minimum 32-bit signed integers
+INST3( pminuw, "pminuw" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE38(0x3A)) // packed minimum 16-bit unsigned integers
+INST3( pminud, "pminud" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE38(0x3B)) // packed minimum 32-bit unsigned integers
+INST3( pmaxsb, "pmaxsb" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE38(0x3C)) // packed maximum signed bytes
+INST3( pmaxsd, "pmaxsd" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE38(0x3D)) // packed maximum 32-bit signed integers
+INST3( pmaxuw, "pmaxuw" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE38(0x3E)) // packed maximum 16-bit unsigned integers
+INST3( pmaxud, "pmaxud" , 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, SSE38(0x3F)) // packed maximum 32-bit unsigned integers
INST3(LAST_SSE4_INSTRUCTION, "LAST_SSE4_INSTRUCTION", 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, BAD_CODE)
INST3(FIRST_AVX_INSTRUCTION, "FIRST_AVX_INSTRUCTION", 0, IUM_WR, 0, 0, BAD_CODE, BAD_CODE, BAD_CODE)
diff --git a/src/jit/jitconfigvalues.h b/src/jit/jitconfigvalues.h
index ea6a3aac23..a3e30de10f 100644
--- a/src/jit/jitconfigvalues.h
+++ b/src/jit/jitconfigvalues.h
@@ -258,6 +258,9 @@ CONFIG_STRING(AltJitExcludeAssemblies,
W("AltJitExcludeAssemblies")) // Do not use AltJit on this semicolon-delimited list of assemblies.
#endif // defined(ALT_JIT)
+CONFIG_INTEGER(JitMeasureIR, W("JitMeasureIR"), 0) // If set, measure the IR size after some phases and report it in
+ // the time log.
+
CONFIG_STRING(JitFuncInfoFile, W("JitFuncInfoLogFile")) // If set, gather JIT function info and write to this file.
CONFIG_STRING(JitTimeLogCsv, W("JitTimeLogCsv")) // If set, gather JIT throughput data and write to a CSV file. This
// mode must be used in internal retail builds.
diff --git a/src/jit/lclvars.cpp b/src/jit/lclvars.cpp
index b4e4cc6e55..61cf8a1e7e 100644
--- a/src/jit/lclvars.cpp
+++ b/src/jit/lclvars.cpp
@@ -1522,15 +1522,8 @@ void Compiler::lvaCanPromoteStructType(CORINFO_CLASS_HANDLE typeHnd,
pFieldInfo->fldOffset = (BYTE)fldOffset;
pFieldInfo->fldOrdinal = ordinal;
CorInfoType corType = info.compCompHnd->getFieldType(pFieldInfo->fldHnd, &pFieldInfo->fldTypeHnd);
- var_types varType = JITtype2varType(corType);
- pFieldInfo->fldType = varType;
- unsigned size = genTypeSize(varType);
- pFieldInfo->fldSize = size;
-
- if (varTypeIsGC(varType))
- {
- containsGCpointers = true;
- }
+ pFieldInfo->fldType = JITtype2varType(corType);
+ pFieldInfo->fldSize = genTypeSize(pFieldInfo->fldType);
#ifdef FEATURE_SIMD
// Check to see if this is a SIMD type.
@@ -1542,8 +1535,7 @@ void Compiler::lvaCanPromoteStructType(CORINFO_CLASS_HANDLE typeHnd,
var_types simdBaseType = getBaseTypeAndSizeOfSIMDType(pFieldInfo->fldTypeHnd, &simdSize);
if (simdBaseType != TYP_UNKNOWN)
{
- varType = getSIMDTypeForSize(simdSize);
- pFieldInfo->fldType = varType;
+ pFieldInfo->fldType = getSIMDTypeForSize(simdSize);
pFieldInfo->fldSize = simdSize;
}
}
@@ -1551,8 +1543,60 @@ void Compiler::lvaCanPromoteStructType(CORINFO_CLASS_HANDLE typeHnd,
if (pFieldInfo->fldSize == 0)
{
- // Non-primitive struct field. Don't promote.
- return;
+ // Size of TYP_BLK, TYP_FUNC, TYP_VOID and TYP_STRUCT is zero.
+ // Early out if field type is other than TYP_STRUCT.
+ // This is a defensive check as we don't expect a struct to have
+ // fields of TYP_BLK, TYP_FUNC or TYP_VOID.
+ if (pFieldInfo->fldType != TYP_STRUCT)
+ {
+ return;
+ }
+
+ // Non-primitive struct field.
+ // Try to promote structs of single field of scalar types aligned at their
+ // natural boundary.
+
+ // Do Not promote if the struct field in turn has more than one field.
+ if (info.compCompHnd->getClassNumInstanceFields(pFieldInfo->fldTypeHnd) != 1)
+ {
+ return;
+ }
+
+ // Do not promote if the single field is not aligned at its natural boundary within
+ // the struct field.
+ CORINFO_FIELD_HANDLE fHnd = info.compCompHnd->getFieldInClass(pFieldInfo->fldTypeHnd, 0);
+ unsigned fOffset = info.compCompHnd->getFieldOffset(fHnd);
+ if (fOffset != 0)
+ {
+ return;
+ }
+
+ CORINFO_CLASS_HANDLE cHnd;
+ CorInfoType fieldCorType = info.compCompHnd->getFieldType(fHnd, &cHnd);
+ var_types fieldVarType = JITtype2varType(fieldCorType);
+ unsigned fieldSize = genTypeSize(fieldVarType);
+
+ // Do not promote if either not a primitive type or size equal to ptr size on
+ // target or a struct containing a single floating-point field.
+ //
+ // TODO-PERF: Structs containing a single floating-point field on Amd64
+ // needs to be passed in integer registers. Right now LSRA doesn't support
+ // passing of floating-point LCL_VARS in integer registers. Enabling promotion
+ // of such structs results in an assert in lsra right now.
+ //
+ // TODO-PERF: Right now promotion is confined to struct containing a ptr sized
+ // field (int/uint/ref/byref on 32-bits and long/ulong/ref/byref on 64-bits).
+ // Though this would serve the purpose of promoting Span<T> containing ByReference<T>,
+ // this can be extended to other primitive types as long as they are aligned at their
+ // natural boundary.
+ if (fieldSize == 0 || fieldSize != TARGET_POINTER_SIZE || varTypeIsFloating(fieldVarType))
+ {
+ return;
+ }
+
+ // Retype the field as the type of the single field of the struct
+ pFieldInfo->fldType = fieldVarType;
+ pFieldInfo->fldSize = fieldSize;
}
if ((pFieldInfo->fldOffset % pFieldInfo->fldSize) != 0)
@@ -1563,6 +1607,11 @@ void Compiler::lvaCanPromoteStructType(CORINFO_CLASS_HANDLE typeHnd,
return;
}
+ if (varTypeIsGC(pFieldInfo->fldType))
+ {
+ containsGCpointers = true;
+ }
+
// The end offset for this field should never be larger than our structSize.
noway_assert(fldOffset + pFieldInfo->fldSize <= structSize);
diff --git a/src/jit/lower.cpp b/src/jit/lower.cpp
index b3a674eec2..3c685f67c1 100644
--- a/src/jit/lower.cpp
+++ b/src/jit/lower.cpp
@@ -971,6 +971,42 @@ GenTreePtr Lowering::NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryP
assert(!varTypeIsSIMD(arg));
numRefs = comp->info.compCompHnd->getClassGClayout(arg->gtObj.gtClass, gcLayout);
putArg->AsPutArgStk()->setGcPointers(numRefs, gcLayout);
+
+#ifdef _TARGET_X86_
+ // On x86 VM lies about the type of a struct containing a pointer sized
+ // integer field by returning the type of its field as the type of struct.
+ // Such struct can be passed in a register depending its position in
+ // parameter list. VM does this unwrapping only one level and therefore
+ // a type like Struct Foo { Struct Bar { int f}} awlays needs to be
+ // passed on stack. Also, VM doesn't lie about type of such a struct
+ // when it is a field of another struct. That is VM doesn't lie about
+ // the type of Foo.Bar
+ //
+ // Promotion of structs containing structs of single field can promote
+ // such a struct. Say Foo.Bar field is getting passed as a parameter
+ // to a call, Since it is a TYP_STRUCT, as per x86 ABI it should always
+ // be passed on stack. Therefore GenTree node under a PUTARG_STK could
+ // be GT_OBJ(GT_LCL_VAR_ADDR(v1)), where local v1 could be a promoted
+ // field standing for Foo.Bar. Note that the type of v1 will be the
+ // type of field of Foo.Bar.f when Foo is promoted. That is v1
+ // will be a scalar type. In this case we need to pass v1 on stack
+ // instead of in a register.
+ //
+ // TODO-PERF: replace GT_OBJ(GT_LCL_VAR_ADDR(v1)) with v1 if v1 is
+ // a scalar type and the width of GT_OBJ matches the type size of v1.
+ // Note that this cannot be done till call node arguments are morphed
+ // because we should not lose the fact that the type of argument is
+ // a struct so that the arg gets correctly marked to be passed on stack.
+ GenTree* objOp1 = arg->gtGetOp1();
+ if (objOp1->OperGet() == GT_LCL_VAR_ADDR)
+ {
+ unsigned lclNum = objOp1->AsLclVarCommon()->GetLclNum();
+ if (comp->lvaTable[lclNum].lvType != TYP_STRUCT)
+ {
+ comp->lvaSetVarDoNotEnregister(lclNum DEBUGARG(Compiler::DNER_VMNeedsStackAddr));
+ }
+ }
+#endif // _TARGET_X86_
}
}
#endif // FEATURE_PUT_STRUCT_ARG_STK
diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp
index 1132d6ae39..ef752db7f7 100644
--- a/src/jit/morph.cpp
+++ b/src/jit/morph.cpp
@@ -7951,7 +7951,16 @@ GenTreePtr Compiler::fgMorphCall(GenTreeCall* call)
GenTreeStmt* popStmt = nextMorphStmt;
nextMorphStmt = nextMorphStmt->gtNextStmt;
- noway_assert((popStmt->gtStmtExpr->gtFlags & GTF_ALL_EFFECT) == 0);
+ // Side effect flags on a GT_COMMA may be overly pessimistic, so examine
+ // the constituent nodes.
+ GenTreePtr popExpr = popStmt->gtStmtExpr;
+ bool isSideEffectFree = (popExpr->gtFlags & GTF_ALL_EFFECT) == 0;
+ if (!isSideEffectFree && (popExpr->OperGet() == GT_COMMA))
+ {
+ isSideEffectFree = ((popExpr->gtGetOp1()->gtFlags & GTF_ALL_EFFECT) == 0) &&
+ ((popExpr->gtGetOp2()->gtFlags & GTF_ALL_EFFECT) == 0);
+ }
+ noway_assert(isSideEffectFree);
fgRemoveStmt(compCurBB, popStmt);
}
@@ -16963,6 +16972,10 @@ void Compiler::fgMorph()
EndPhase(PHASE_EMPTY_FINALLY);
+ fgMergeFinallyChains();
+
+ EndPhase(PHASE_MERGE_FINALLY_CHAINS);
+
fgCloneFinally();
EndPhase(PHASE_CLONE_FINALLY);
diff --git a/src/jit/simd.cpp b/src/jit/simd.cpp
index fb190c4fa1..4ba7832cca 100644
--- a/src/jit/simd.cpp
+++ b/src/jit/simd.cpp
@@ -1374,20 +1374,22 @@ GenTreePtr Compiler::impSIMDMinMax(SIMDIntrinsicID intrinsicId,
#ifdef _TARGET_XARCH_
// SSE2 has direct support for float/double/signed word/unsigned byte.
+ // SSE4.1 has direct support for int32/uint32/signed byte/unsigned word.
// For other integer types we compute min/max as follows
//
- // int32/uint32/int64/uint64:
+ // int32/uint32 (SSE2)
+ // int64/uint64 (SSE2&SSE3_4):
// compResult = (op1 < op2) in case of Min
// (op1 > op2) in case of Max
// Min/Max(op1, op2) = Select(compResult, op1, op2)
//
- // unsigned word:
+ // unsigned word (SSE2):
// op1 = op1 - 2^15 ; to make it fit within a signed word
// op2 = op2 - 2^15 ; to make it fit within a signed word
// result = SSE2 signed word Min/Max(op1, op2)
// result = result + 2^15 ; readjust it back
//
- // signed byte:
+ // signed byte (SSE2):
// op1 = op1 + 2^7 ; to make it unsigned
// op1 = op1 + 2^7 ; to make it unsigned
// result = SSE2 unsigned byte Min/Max(op1, op2)
@@ -1395,13 +1397,16 @@ GenTreePtr Compiler::impSIMDMinMax(SIMDIntrinsicID intrinsicId,
GenTree* simdTree = nullptr;
- if (varTypeIsFloating(baseType) || baseType == TYP_SHORT || baseType == TYP_UBYTE)
+ if (varTypeIsFloating(baseType) || baseType == TYP_SHORT || baseType == TYP_UBYTE ||
+ (getSIMDInstructionSet() >= InstructionSet_SSE3_4 &&
+ (baseType == TYP_BYTE || baseType == TYP_INT || baseType == TYP_UINT || baseType == TYP_CHAR)))
{
- // SSE2 has direct support
+ // SSE2 or SSE4.1 has direct support
simdTree = gtNewSIMDNode(simdType, op1, op2, intrinsicId, baseType, size);
}
else if (baseType == TYP_CHAR || baseType == TYP_BYTE)
{
+ assert(getSIMDInstructionSet() == InstructionSet_SSE2);
int constVal;
SIMDIntrinsicID operIntrinsic;
SIMDIntrinsicID adjustIntrinsic;
diff --git a/src/jit/simdcodegenxarch.cpp b/src/jit/simdcodegenxarch.cpp
index ace36422fb..468d302d17 100644
--- a/src/jit/simdcodegenxarch.cpp
+++ b/src/jit/simdcodegenxarch.cpp
@@ -243,6 +243,25 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type
{
result = INS_pminsw;
}
+ else if (compiler->getSIMDInstructionSet() >= InstructionSet_SSE3_4)
+ {
+ if (baseType == TYP_BYTE)
+ {
+ result = INS_pminsb;
+ }
+ else if (baseType == TYP_CHAR)
+ {
+ result = INS_pminuw;
+ }
+ else if (baseType == TYP_INT)
+ {
+ result = INS_pminsd;
+ }
+ else if (baseType == TYP_UINT)
+ {
+ result = INS_pminud;
+ }
+ }
else
{
unreached();
@@ -266,6 +285,25 @@ instruction CodeGen::getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_type
{
result = INS_pmaxsw;
}
+ else if (compiler->getSIMDInstructionSet() >= InstructionSet_SSE3_4)
+ {
+ if (baseType == TYP_BYTE)
+ {
+ result = INS_pmaxsb;
+ }
+ else if (baseType == TYP_CHAR)
+ {
+ result = INS_pmaxuw;
+ }
+ else if (baseType == TYP_INT)
+ {
+ result = INS_pmaxsd;
+ }
+ else if (baseType == TYP_UINT)
+ {
+ result = INS_pmaxud;
+ }
+ }
else
{
unreached();
diff --git a/src/jit/utils.cpp b/src/jit/utils.cpp
index 3a45039aa7..df5bd2bea6 100644
--- a/src/jit/utils.cpp
+++ b/src/jit/utils.cpp
@@ -1358,6 +1358,7 @@ void HelperCallProperties::init()
case CORINFO_HELP_ISINSTANCEOFCLASS:
case CORINFO_HELP_ISINSTANCEOFANY:
case CORINFO_HELP_READYTORUN_ISINSTANCEOF:
+ case CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE:
isPure = true;
noThrow = true; // These return null for a failing cast
diff --git a/src/jit/valuenum.cpp b/src/jit/valuenum.cpp
index aba29c4411..4d20087b17 100644
--- a/src/jit/valuenum.cpp
+++ b/src/jit/valuenum.cpp
@@ -833,7 +833,7 @@ ValueNum ValueNumStore::VNForHandle(ssize_t cnsVal, unsigned handleFlags)
}
// Returns the value number for zero of the given "typ".
-// It has an unreached() for a "typ" that has no zero value, such as TYP_BYREF.
+// It has an unreached() for a "typ" that has no zero value, such as TYP_VOID.
ValueNum ValueNumStore::VNZeroForType(var_types typ)
{
switch (typ)
@@ -861,6 +861,8 @@ ValueNum ValueNumStore::VNZeroForType(var_types typ)
case TYP_REF:
case TYP_ARRAY:
return VNForNull();
+ case TYP_BYREF:
+ return VNForByrefCon(0);
case TYP_STRUCT:
#ifdef FEATURE_SIMD
// TODO-CQ: Improve value numbering for SIMD types.
@@ -1876,6 +1878,7 @@ ValueNum ValueNumStore::EvalCastForConstantArgs(var_types typ, VNFunc func, Valu
{
#ifndef _TARGET_64BIT_
case TYP_REF:
+ case TYP_BYREF:
#endif
case TYP_INT:
{
@@ -1934,6 +1937,9 @@ ValueNum ValueNumStore::EvalCastForConstantArgs(var_types typ, VNFunc func, Valu
else
return VNForLongCon(INT64(arg0Val));
#endif
+ case TYP_BYREF:
+ assert(typ == TYP_BYREF);
+ return VNForByrefCon((INT64)arg0Val);
case TYP_FLOAT:
assert(typ == TYP_FLOAT);
if (srcIsUnsigned)
@@ -1962,6 +1968,7 @@ ValueNum ValueNumStore::EvalCastForConstantArgs(var_types typ, VNFunc func, Valu
{
#ifdef _TARGET_64BIT_
case TYP_REF:
+ case TYP_BYREF:
#endif
case TYP_LONG:
INT64 arg0Val = GetConstantInt64(arg0VN);
@@ -1992,6 +1999,9 @@ ValueNum ValueNumStore::EvalCastForConstantArgs(var_types typ, VNFunc func, Valu
case TYP_ULONG:
assert(typ == TYP_LONG);
return arg0VN;
+ case TYP_BYREF:
+ assert(typ == TYP_BYREF);
+ return VNForByrefCon((INT64)arg0Val);
case TYP_FLOAT:
assert(typ == TYP_FLOAT);
if (srcIsUnsigned)
@@ -7466,6 +7476,10 @@ VNFunc Compiler::fgValueNumberHelperMethVNFunc(CorInfoHelpFunc helpFunc)
vnf = VNF_IsInstanceOf;
break;
+ case CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE:
+ vnf = VNF_TypeHandleToRuntimeType;
+ break;
+
case CORINFO_HELP_READYTORUN_ISINSTANCEOF:
vnf = VNF_ReadyToRunIsInstanceOf;
break;
diff --git a/src/jit/valuenumfuncs.h b/src/jit/valuenumfuncs.h
index cb99507921..2711b4f056 100644
--- a/src/jit/valuenumfuncs.h
+++ b/src/jit/valuenumfuncs.h
@@ -34,6 +34,7 @@ ValueNumFuncDef(CastClass, 2, false, false, false) // Args: 0: Handle o
ValueNumFuncDef(IsInstanceOf, 2, false, false, false) // Args: 0: Handle of class being queried, 1: object being queried.
ValueNumFuncDef(ReadyToRunCastClass, 2, false, false, false) // Args: 0: Helper stub address, 1: object being cast.
ValueNumFuncDef(ReadyToRunIsInstanceOf, 2, false, false, false) // Args: 0: Helper stub address, 1: object being queried.
+ValueNumFuncDef(TypeHandleToRuntimeType, 1, false, false, false) // Args: 0: TypeHandle to translate
ValueNumFuncDef(LdElemA, 3, false, false, false) // Args: 0: array value; 1: index value; 2: type handle of element.
diff --git a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs
index 25585c6dfb..79aedd74d3 100644
--- a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs
+++ b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs
@@ -21,7 +21,7 @@ internal static partial class Interop
internal unsafe static extern int CompareString(SafeSortHandle sortHandle, char* lpStr1, int cwStr1Len, char* lpStr2, int cwStr2Len, CompareOptions options);
[DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_IndexOf")]
- internal unsafe static extern int IndexOf(SafeSortHandle sortHandle, string target, int cwTargetLength, char* pSource, int cwSourceLength, CompareOptions options);
+ internal unsafe static extern int IndexOf(SafeSortHandle sortHandle, string target, int cwTargetLength, char* pSource, int cwSourceLength, CompareOptions options, int* matchLengthPtr);
[DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_LastIndexOf")]
internal unsafe static extern int LastIndexOf(SafeSortHandle sortHandle, string target, int cwTargetLength, char* pSource, int cwSourceLength, CompareOptions options);
diff --git a/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs b/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs
index 21c3c9f7e4..a5232b8883 100644
--- a/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs
+++ b/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs
@@ -159,30 +159,46 @@ namespace System.Globalization
}
}
- private unsafe int IndexOfCore(string source, string target, int startIndex, int count, CompareOptions options)
+ internal unsafe int IndexOfCore(string source, string target, int startIndex, int count, CompareOptions options, int* matchLengthPtr)
{
Debug.Assert(!string.IsNullOrEmpty(source));
Debug.Assert(target != null);
Debug.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0);
+ int index;
+
if (target.Length == 0)
{
+ if(matchLengthPtr != null)
+ *matchLengthPtr = 0;
return startIndex;
}
if (options == CompareOptions.Ordinal)
{
- return IndexOfOrdinal(source, target, startIndex, count, ignoreCase: false);
+ index = IndexOfOrdinal(source, target, startIndex, count, ignoreCase: false);
+ if(index != -1)
+ {
+ if(matchLengthPtr != null)
+ *matchLengthPtr = target.Length;
+ }
+ return index;
}
if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options) && source.IsFastSort() && target.IsFastSort())
{
- return IndexOf(source, target, startIndex, count, GetOrdinalCompareOptions(options));
+ index = IndexOf(source, target, startIndex, count, GetOrdinalCompareOptions(options));
+ if(index != -1)
+ {
+ if(matchLengthPtr != null)
+ *matchLengthPtr = target.Length;
+ }
+ return index;
}
-
+
fixed (char* pSource = source)
{
- int index = Interop.GlobalizationInterop.IndexOf(_sortHandle, target, target.Length, pSource + startIndex, count, options);
+ index = Interop.GlobalizationInterop.IndexOf(_sortHandle, target, target.Length, pSource + startIndex, count, options, matchLengthPtr);
return index != -1 ? index + startIndex : -1;
}
diff --git a/src/mscorlib/corefx/System/Globalization/CompareInfo.cs b/src/mscorlib/corefx/System/Globalization/CompareInfo.cs
index 64dbfe84f7..94cfcad709 100644
--- a/src/mscorlib/corefx/System/Globalization/CompareInfo.cs
+++ b/src/mscorlib/corefx/System/Globalization/CompareInfo.cs
@@ -694,7 +694,7 @@ namespace System.Globalization
if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal))
throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
- return IndexOfCore(source, new string(value, 1), startIndex, count, options);
+ return IndexOfCore(source, new string(value, 1), startIndex, count, options, null);
}
@@ -741,7 +741,7 @@ namespace System.Globalization
if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal))
throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
- return IndexOfCore(source, value, startIndex, count, options);
+ return IndexOfCore(source, value, startIndex, count, options, null);
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/mscorlib/ref/mscorlib.cs b/src/mscorlib/ref/mscorlib.cs
index 680bf20675..945e9689da 100644
--- a/src/mscorlib/ref/mscorlib.cs
+++ b/src/mscorlib/ref/mscorlib.cs
@@ -3245,6 +3245,8 @@ namespace System
[System.Security.SecuritySafeCriticalAttribute]
public System.String Replace(char oldChar, char newChar) { throw null; }
public System.String Replace(System.String oldValue, System.String newValue) { throw null; }
+ public System.String Replace(System.String oldValue, System.String newValue, System.StringComparison comparison) { throw null; }
+ public System.String Replace(System.String oldValue, System.String newValue, System.Boolean ignoreCase, System.Globalization.CultureInfo cultureInfo) { throw null; }
[System.Runtime.InteropServices.ComVisibleAttribute(false)]
public string[] Split(char separator, int count, System.StringSplitOptions options = (System.StringSplitOptions)(0)) { throw null; }
[System.Runtime.InteropServices.ComVisibleAttribute(false)]
diff --git a/src/mscorlib/src/System/Globalization/CompareInfo.cs b/src/mscorlib/src/System/Globalization/CompareInfo.cs
index 6c2230b66b..dac7b0bf4e 100644
--- a/src/mscorlib/src/System/Globalization/CompareInfo.cs
+++ b/src/mscorlib/src/System/Globalization/CompareInfo.cs
@@ -564,11 +564,11 @@ namespace System.Globalization {
// to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to
// the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString.
-
return (InternalFindNLSStringEx(
m_dataHandle, m_handleOrigin, m_sortName,
GetNativeCompareFlags(options) | Win32Native.FIND_STARTSWITH | ((source.IsAscii() && prefix.IsAscii()) ? RESERVED_FIND_ASCII_STRING : 0),
- source, source.Length, 0, prefix, prefix.Length) > -1);
+ source, source.Length, 0, prefix, prefix.Length,
+ null) > -1);
}
public virtual bool IsPrefix(String source, String prefix)
@@ -618,7 +618,7 @@ namespace System.Globalization {
return InternalFindNLSStringEx(
m_dataHandle, m_handleOrigin, m_sortName,
GetNativeCompareFlags(options) | Win32Native.FIND_ENDSWITH | ((source.IsAscii() && suffix.IsAscii()) ? RESERVED_FIND_ASCII_STRING : 0),
- source, source.Length, source.Length - 1, suffix, suffix.Length) >= 0;
+ source, source.Length, source.Length - 1, suffix, suffix.Length, null) >= 0;
}
@@ -760,12 +760,16 @@ namespace System.Globalization {
return InternalFindNLSStringEx(
m_dataHandle, m_handleOrigin, m_sortName,
GetNativeCompareFlags(options) | Win32Native.FIND_FROMSTART | ((source.IsAscii() && (value <= '\x007f')) ? RESERVED_FIND_ASCII_STRING : 0),
- source, count, startIndex, new String(value, 1), 1);
+ source, count, startIndex, new String(value, 1), 1, null);
}
-
public unsafe virtual int IndexOf(String source, String value, int startIndex, int count, CompareOptions options)
{
+ return IndexOfCore(source, value, startIndex, count, options, null);
+ }
+
+ internal unsafe int IndexOfCore(String source, String value, int startIndex, int count, CompareOptions options, int* matchLengthPtr)
+ {
// Validate inputs
if (source == null)
throw new ArgumentNullException(nameof(source));
@@ -784,6 +788,8 @@ namespace System.Globalization {
{
if (value.Length == 0)
{
+ if(matchLengthPtr != null)
+ *matchLengthPtr = 0;
return 0;
}
return -1;
@@ -795,11 +801,17 @@ namespace System.Globalization {
}
if (count < 0 || startIndex > source.Length - count)
- throw new ArgumentOutOfRangeException(nameof(count),Environment.GetResourceString("ArgumentOutOfRange_Count"));
+ throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count"));
if (options == CompareOptions.OrdinalIgnoreCase)
{
- return source.IndexOf(value, startIndex, count, StringComparison.OrdinalIgnoreCase);
+ int index = source.IndexOf(value, startIndex, count, StringComparison.OrdinalIgnoreCase);
+ if (index != -1)
+ {
+ if(matchLengthPtr != null)
+ *matchLengthPtr = value.Length;
+ }
+ return index;
}
// Validate CompareOptions
@@ -810,9 +822,9 @@ namespace System.Globalization {
// to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to
// the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString.
return InternalFindNLSStringEx(
- m_dataHandle, m_handleOrigin, m_sortName,
+ m_dataHandle, m_handleOrigin, m_sortName,
GetNativeCompareFlags(options) | Win32Native.FIND_FROMSTART | ((source.IsAscii() && value.IsAscii()) ? RESERVED_FIND_ASCII_STRING : 0),
- source, count, startIndex, value, value.Length);
+ source, count, startIndex, value, value.Length, matchLengthPtr);
}
////////////////////////////////////////////////////////////////////////
@@ -956,7 +968,7 @@ namespace System.Globalization {
return InternalFindNLSStringEx(
m_dataHandle, m_handleOrigin, m_sortName,
GetNativeCompareFlags(options) | Win32Native.FIND_FROMEND | ((source.IsAscii() && (value <= '\x007f')) ? RESERVED_FIND_ASCII_STRING : 0),
- source, count, startIndex, new String(value, 1), 1);
+ source, count, startIndex, new String(value, 1), 1, null);
}
@@ -1010,7 +1022,7 @@ namespace System.Globalization {
return InternalFindNLSStringEx(
m_dataHandle, m_handleOrigin, m_sortName,
GetNativeCompareFlags(options) | Win32Native.FIND_FROMEND | ((source.IsAscii() && value.IsAscii()) ? RESERVED_FIND_ASCII_STRING : 0),
- source, count, startIndex, value, value.Length);
+ source, count, startIndex, value, value.Length, null);
}
@@ -1292,7 +1304,8 @@ namespace System.Globalization {
// Call through to NewApis::FindNLSStringEx so we can get the right behavior
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
- private static extern int InternalFindNLSStringEx(IntPtr handle, IntPtr handleOrigin, String localeName, int flags, String source, int sourceCount, int startIndex, string target, int targetCount);
+ private unsafe static extern int InternalFindNLSStringEx(IntPtr handle, IntPtr handleOrigin, String localeName, int flags, String source, int sourceCount, int startIndex, string target, int targetCount, int* matchLengthPtr);
+
// Call through to NewAPis::LCMapStringEx so we can get appropriate behavior for all platforms
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
diff --git a/src/mscorlib/src/System/Globalization/CultureInfo.cs b/src/mscorlib/src/System/Globalization/CultureInfo.cs
index ba61c146f6..88bf29b479 100644
--- a/src/mscorlib/src/System/Globalization/CultureInfo.cs
+++ b/src/mscorlib/src/System/Globalization/CultureInfo.cs
@@ -1842,9 +1842,6 @@ namespace System.Globalization {
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool InternalGetSystemDefaultUILanguage(StringHandleOnStack systemDefaultUiLanguage);
-
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal static extern String[] nativeGetResourceFallbackArray();
}
}
diff --git a/src/mscorlib/src/System/Resources/ResourceFallbackManager.cs b/src/mscorlib/src/System/Resources/ResourceFallbackManager.cs
index de50cccc33..f57995c92d 100644
--- a/src/mscorlib/src/System/Resources/ResourceFallbackManager.cs
+++ b/src/mscorlib/src/System/Resources/ResourceFallbackManager.cs
@@ -85,180 +85,12 @@ namespace System.Resources
yield break;
}
- // 2. user preferred cultures, omitting starting culture if tried already
- // Compat note: For console apps, this API will return cultures like Arabic
- // or Hebrew that are displayed right-to-left. These don't work with today's
- // CMD.exe. Since not all apps can short-circuit RTL languages to look at
- // US English resources, we're exposing an appcompat flag for this, to make the
- // osFallbackArray an empty array, mimicing our V2 behavior. Apps should instead
- // be using CultureInfo.GetConsoleFallbackUICulture, and then test whether that
- // culture's code page can be displayed on the console, and if not, they should
- // set their culture to their neutral resources language.
- // Note: the app compat switch will omit the OS Preferred fallback culture.
- // Compat note 2: This feature breaks certain apps dependent on fallback to neutral
- // resources. See extensive note in GetResourceFallbackArray.
- CultureInfo[] osFallbackArray = LoadPreferredCultures();
- if (osFallbackArray != null)
- {
- foreach (CultureInfo ci in osFallbackArray)
- {
- // only have to check starting culture and immediate parent for now.
- // in Dev10, revisit this policy.
- if (m_startingCulture.Name != ci.Name && m_startingCulture.Parent.Name != ci.Name)
- {
- yield return ci;
- }
- }
- }
-
- // 3. invariant
+ // 2. invariant
// Don't return invariant twice though.
if (reachedNeutralResourcesCulture)
yield break;
yield return CultureInfo.InvariantCulture;
}
-
- private static CultureInfo[] LoadPreferredCultures()
- {
- // The list of preferred cultures includes thread, process, user, and OS
- // information and may theoretically change every time we call it.
- // The caching does save us some allocations - this complexity saved about
- // 7% of the wall clock time on a US English machine, and may save more on non-English
- // boxes (since the fallback list may be longer).
- String[] cultureNames = GetResourceFallbackArray();
- if (cultureNames == null)
- return null;
-
- bool useCachedNames = (cachedOsFallbackArray != null && cultureNames.Length == cachedOsFallbackArray.Length);
- if (useCachedNames)
- {
- for (int i = 0; i < cultureNames.Length; i++)
- {
- if (!String.Equals(cultureNames[i], cachedOsFallbackArray[i].Name))
- {
- useCachedNames = false;
- break;
- }
- }
- }
- if (useCachedNames)
- return cachedOsFallbackArray;
-
- cachedOsFallbackArray = LoadCulturesFromNames(cultureNames);
- return cachedOsFallbackArray;
- }
-
- private static CultureInfo[] LoadCulturesFromNames(String[] cultureNames)
- {
- if (cultureNames == null)
- return null;
-
- CultureInfo[] cultures = new CultureInfo[cultureNames.Length];
- int culturesIndex = 0;
- for (int i = 0; i < cultureNames.Length; i++)
- {
- // get cached, read-only cultures to avoid excess allocations
- cultures[culturesIndex] = CultureInfo.GetCultureInfo(cultureNames[i]);
- // Note GetCultureInfo can return null for a culture name that we don't support on the current OS.
- // Don't leave a null in the middle of the array.
- if (!Object.ReferenceEquals(cultures[culturesIndex], null))
- culturesIndex++;
- }
-
- // If we couldn't create a culture, return an array of the right length.
- if (culturesIndex != cultureNames.Length)
- {
- CultureInfo[] ret = new CultureInfo[culturesIndex];
- Array.Copy(cultures, ret, culturesIndex);
- cultures = ret;
- }
-
- return cultures;
- }
-
-
- // Note: May return null.
- private static String[] GetResourceFallbackArray()
- {
- // AppCompat note: We've added this feature for desktop V4 but we ripped it out
- // before shipping V4. It shipped in SL 2 and SL 3. We preserved this behavior in SL 4
- // for compat with previous Silverlight releases. We considered re-introducing this in .NET
- // 4.5 for Windows 8 but chose not to because the Windows 8 immersive resources model
- // has been redesigned from the ground up and we chose to support it (for portable libraries
- // only) instead of further enhancing support for the classic resources model.
- // ---------------------------------------------------------------------
- //
- // We have an appcompat problem that prevents us from adopting the ideal MUI model for
- // culture fallback. Up until .NET Framework v4, our fallback was this:
- //
- // CurrentUICulture & parents Neutral
- //
- // We also had applications that took a dependency on falling back to neutral resources.
- // IE, say an app is developed by US English developers - they may include English resources
- // in the main assembly, not ship an "en" satellite assembly, and ship a French satellite.
- // They may also omit the NeutralResourcesLanguageAttribute.
- //
- // Starting with Silverlight v2 and following advice from the MUI team, we wanted to call
- // the OS's GetThreadPreferredUILanguages, inserting the results like this:
- //
- // CurrentUICulture & parents user-preferred fallback OS-preferred fallback Neutral
- //
- // This does not fit well for two reasons:
- // 1) There is no concept of neutral resources in MUI
- // 2) The user-preferred culture fallbacks make no sense in servers & non-interactive apps
- // This leads to bad results on certain combinations of OS language installations, user
- // settings, and applications built in certain styles. The OS-preferred fallback should
- // be last, and the user-preferred fallback just breaks certain apps no matter where you put it.
- //
- // Necessary and sufficient conditions for an AppCompat bug (if we respected user & OS fallbacks):
- // 1) A French OS (ie, you walk into an Internet café in Paris)
- // 2) A .NET application whose neutral resources are authored in English.
- // 3) The application did not provide an English satellite assembly (a common pattern).
- // 4) The application is localized to French.
- // 5) The user wants to read English, expressed in either of two ways:
- // a. Changing Windows’ Display Language in the Regional Options Control Panel
- // b. The application explicitly ASKS THE USER what language to display.
- //
- // Obviously the exact languages above can be interchanged a bit - I’m keeping this concrete.
- // Also the NeutralResourcesLanguageAttribute will allow this to work, but usually we set it
- // to en-US for our assemblies, meaning all other English cultures are broken.
- //
- // Workarounds:
- // *) Use the NeutralResourcesLanguageAttribute and tell us that your neutral resources
- // are in region-neutral English (en).
- // *) Consider shipping a region-neutral English satellite assembly.
-
- // Future work:
- // 2) Consider a mechanism for individual assemblies to opt into wanting user-preferred fallback.
- // They should ship their neutral resources in a satellite assembly, or use the
- // NeutralResourcesLanguageAttribute to say their neutral resources are in a REGION-NEUTRAL
- // language. An appdomain or process-wide flag may not be sufficient.
- // 3) Ask Windows to clarify the scenario for the OS preferred fallback list, to decide whether
- // we should probe there before or after looking at the neutral resources. If we move it
- // to after the neutral resources, ask Windows to return a user-preferred fallback list
- // without the OS preferred fallback included. This is a feature request for
- // GetThreadPreferredUILanguages. We can muddle through without it by removing the OS
- // preferred fallback cultures from end of the combined user + OS preferred fallback list, carefully.
- // 4) Do not look at user-preferred fallback if Environment.UserInteractive is false. (IE,
- // the Windows user who launches ASP.NET shouldn't determine how a web page gets
- // localized - the server itself must respect the remote client's requested languages.)
- // 6) Figure out what should happen in servers (ASP.NET, SQL, NT Services, etc).
- //
- // Done:
- // 1) Got data from Windows on priority of supporting OS preferred fallback. We need to do it.
- // Helps with consistency w/ Windows, and may be necessary for a long tail of other languages
- // (ie, Windows has various degrees of localization support for ~135 languages, and fallbacks
- // to certain languages is important.)
- // 5) Revisited guidance for using the NeutralResourcesLanguageAttribute. Our docs should now say
- // always pick a region-neutral language (ie, "en").
-
-// TODO (matell): I think we actually want to pull this into the PAL on CultureInfo?
-#if FEATURE_COREFX_GLOBALIZATION
- return null;
-#else
- return CultureInfo.nativeGetResourceFallbackArray();
-#endif
- }
}
}
diff --git a/src/mscorlib/src/System/Runtime/Reliability/ReliabilityContractAttribute.cs b/src/mscorlib/src/System/Runtime/Reliability/ReliabilityContractAttribute.cs
index 4a14e5733c..a889f1559c 100644
--- a/src/mscorlib/src/System/Runtime/Reliability/ReliabilityContractAttribute.cs
+++ b/src/mscorlib/src/System/Runtime/Reliability/ReliabilityContractAttribute.cs
@@ -20,13 +20,6 @@ namespace System.Runtime.ConstrainedExecution {
using System.Runtime.InteropServices;
using System;
- // **************************************************************************************************************************
- //
- // Note that if you change either of the enums below or the constructors, fields or properties of the custom attribute itself
- // you must also change the logic and definitions in vm\ConstrainedExecutionRegion.cpp to match.
- //
- // **************************************************************************************************************************
-
[Serializable]
public enum Consistency : int
{
diff --git a/src/mscorlib/src/System/Runtime/Versioning/NonVersionableAttribute.cs b/src/mscorlib/src/System/Runtime/Versioning/NonVersionableAttribute.cs
index 0a9845d9c2..9fafce4caa 100644
--- a/src/mscorlib/src/System/Runtime/Versioning/NonVersionableAttribute.cs
+++ b/src/mscorlib/src/System/Runtime/Versioning/NonVersionableAttribute.cs
@@ -13,6 +13,12 @@
** is never changed in ReadyToRun native images. Any changes to such members or types would be
** breaking changes for ReadyToRun.
**
+** Applying this type also has the side effect that the inlining tables in R2R images will not
+** report that inlining of NonVersionable attributed methods occured. These inlining tables are used
+** by profilers to figure out the set of methods that need to be rejited when one method is instrumented,
+** so in effect NonVersionable methods are also non-instrumentable. Generally this is OK for
+** extremely trivial low level methods where NonVersionable gets used, but if there is any plan to
+** significantly extend its usage or allow 3rd parties to use it please discuss with the diagnostics team.
===========================================================*/
using System;
using System.Diagnostics;
diff --git a/src/mscorlib/src/System/SharedStatics.cs b/src/mscorlib/src/System/SharedStatics.cs
index d9364335f5..0ba1d8a029 100644
--- a/src/mscorlib/src/System/SharedStatics.cs
+++ b/src/mscorlib/src/System/SharedStatics.cs
@@ -34,12 +34,6 @@ namespace System
BCLDebug.Assert(false, "SharedStatics..ctor() is never called.");
}
- private volatile String _Remoting_Identity_IDGuid;
-
- // Note this may not need to be process-wide.
- private int _Remoting_Identity_IDSeqNum;
-
-
// This is the total amount of memory currently "reserved" via
// all MemoryFailPoints allocated within the process.
// Stored as a long because we need to use Interlocked.Add.
diff --git a/src/mscorlib/src/System/String.Manipulation.cs b/src/mscorlib/src/System/String.Manipulation.cs
index e06141d669..5a9be5c248 100644
--- a/src/mscorlib/src/System/String.Manipulation.cs
+++ b/src/mscorlib/src/System/String.Manipulation.cs
@@ -946,7 +946,95 @@ namespace System
Contract.EndContractBlock();
return Substring(0, startIndex);
- }
+ }
+
+ public string Replace(string oldValue, string newValue, bool ignoreCase, CultureInfo culture)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ return ReplaceCore(oldValue, newValue, culture, ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None);
+ }
+
+ public string Replace(string oldValue, string newValue, StringComparison comparisonType)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ switch (comparisonType)
+ {
+ case StringComparison.CurrentCulture:
+ return ReplaceCore(oldValue, newValue, CultureInfo.CurrentCulture, CompareOptions.None);
+
+ case StringComparison.CurrentCultureIgnoreCase:
+ return ReplaceCore(oldValue, newValue, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase);
+
+ case StringComparison.InvariantCulture:
+ return ReplaceCore(oldValue, newValue, CultureInfo.InvariantCulture, CompareOptions.None);
+
+ case StringComparison.InvariantCultureIgnoreCase:
+ return ReplaceCore(oldValue, newValue, CultureInfo.InvariantCulture, CompareOptions.IgnoreCase);
+
+ case StringComparison.Ordinal:
+ return ReplaceCore(oldValue, newValue, CultureInfo.InvariantCulture, CompareOptions.Ordinal);
+
+ case StringComparison.OrdinalIgnoreCase:
+ return ReplaceCore(oldValue, newValue, CultureInfo.InvariantCulture, CompareOptions.OrdinalIgnoreCase);
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), nameof(comparisonType));
+ }
+ }
+
+ private unsafe String ReplaceCore(string oldValue, string newValue, CultureInfo culture, CompareOptions options)
+ {
+ if (oldValue == null)
+ throw new ArgumentNullException(nameof(oldValue));
+
+ // If they asked to replace oldValue with a null, replace all occurences
+ // with the empty string.
+ if (newValue == null)
+ newValue = string.Empty;
+
+ CultureInfo referenceCulture = culture ?? CultureInfo.CurrentCulture;
+ StringBuilder result = StringBuilderCache.Acquire();
+
+ int startIndex = 0;
+ int index = 0;
+
+ int matchLength = 0;
+
+ bool hasDoneAnyReplacements = false;
+
+ do
+ {
+ index = referenceCulture.CompareInfo.IndexOfCore(this, oldValue, startIndex, m_stringLength - startIndex, options, &matchLength);
+ if (index >= 0)
+ {
+ // append the unmodified portion of string
+ result.Append(this, startIndex, index - startIndex);
+
+ // append the replacement
+ result.Append(newValue);
+
+ startIndex = index + matchLength;
+ hasDoneAnyReplacements = true;
+ }
+ else if (!hasDoneAnyReplacements)
+ {
+ // small optimization,
+ // if we have not done any replacements,
+ // we will return the original string
+ return this;
+ }
+ else
+ {
+ result.Append(this, startIndex, m_stringLength - startIndex);
+ }
+ } while (index >= 0);
+
+ return StringBuilderCache.GetStringAndRelease(result);
+ }
// Replaces all instances of oldChar with newChar.
//
diff --git a/src/utilcode/downlevel.cpp b/src/utilcode/downlevel.cpp
index ec8d3f5a15..6ff7b82815 100644
--- a/src/utilcode/downlevel.cpp
+++ b/src/utilcode/downlevel.cpp
@@ -1924,11 +1924,11 @@ namespace DownLevel
if (dwFindNLSStringFlags & (FIND_ENDSWITH | FIND_FROMEND))
{
- retValue = NewApis::LastIndexOfString(lpLocaleName, lpStringSource, cchSource, lpStringValue, cchValue, (int) dwFindNLSStringFlags & FIND_NLS_STRING_FLAGS_NEGATION, dwFindNLSStringFlags & FIND_ENDSWITH);
+ retValue = NewApis::LastIndexOfString(lpLocaleName, lpStringSource, cchSource, lpStringValue, cchValue, (int) dwFindNLSStringFlags & FIND_NLS_STRING_FLAGS_NEGATION, dwFindNLSStringFlags & FIND_ENDSWITH, pcchFound);
}
else
{
- retValue = NewApis::IndexOfString(lpLocaleName, lpStringSource, cchSource, lpStringValue, cchValue, (int) dwFindNLSStringFlags & FIND_NLS_STRING_FLAGS_NEGATION, dwFindNLSStringFlags & FIND_STARTSWITH);
+ retValue = NewApis::IndexOfString(lpLocaleName, lpStringSource, cchSource, lpStringValue, cchValue, (int) dwFindNLSStringFlags & FIND_NLS_STRING_FLAGS_NEGATION, dwFindNLSStringFlags & FIND_STARTSWITH, pcchFound);
}
return retValue;
}
diff --git a/src/utilcode/newapis.cpp b/src/utilcode/newapis.cpp
index c05d024b7e..599197c944 100644
--- a/src/utilcode/newapis.cpp
+++ b/src/utilcode/newapis.cpp
@@ -754,12 +754,14 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags)
int IndexOfString( __in LPCWSTR lpLocaleName,
__in_ecount(cchCount1) LPCWSTR pString1, // String to search in
__in int cchCount1, // length of pString1
- __in_ecount(cchCount2) LPCWSTR pString2, // String we're looking for
+ __in_ecount(cchCount2) LPCWSTR pString2, // String we're looking for
__in int cchCount2, // length of pString2
__in DWORD dwFlags, // search flags
- __in BOOL startWith) // true if we need to check for prefix case
+ __in BOOL startWith, // true if we need to check for prefix case
+ __out_opt LPINT pcchFound) // length of the string we found in source
{
int iRetVal = -1;
+ int foundLengthInSource = 0;
//
// Check the ranges.
@@ -788,6 +790,7 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags)
if (dwFlags == COMPARE_OPTIONS_ORDINAL)
{
iRetVal = FastIndexOfString(pString1, cchCount1, pString2, cchCount2);
+ foundLengthInSource = cchCount2;
goto lExit;
}
//For dwFlags, 0 is the default, 1 is ignore case, we can handle both.
@@ -801,6 +804,11 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags)
iRetVal = FastIndexOfString(pString1, cchCount1, pString2, cchCount2);
else
iRetVal = FastIndexOfStringInsensitive(pString1, cchCount1, pString2, cchCount2);
+
+ // both are ascii strings,
+ // the length should be the same as the length of the string we are searching for.
+ foundLengthInSource = cchCount2;
+
goto lExit;
}
}
@@ -832,6 +840,7 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags)
if (result == CSTR_EQUAL)
{
iRetVal = iOffset;
+ foundLengthInSource = iLength;
break;
}
else if (result == 0)
@@ -848,6 +857,9 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags)
{
iRetVal = -1;
}
+
+ if(iRetVal != -1 && pcchFound != NULL)
+ *pcchFound = foundLengthInSource;
return iRetVal;
}
@@ -859,13 +871,16 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags)
int LastIndexOfString( __in LPCWSTR lpLocaleName,
__in_ecount(cchCount1) LPCWSTR pString1, // String to search in
__in int cchCount1, // length of pString1
- __in_ecount(cchCount2) LPCWSTR pString2, // String we're looking for
+ __in_ecount(cchCount2) LPCWSTR pString2, // String we're looking for
__in int cchCount2, // length of pString2
__in DWORD dwFlags,
- __in BOOL endWith) // check suffix case
+ __in BOOL endWith, // check suffix case
+ __out_opt LPINT pcchFound) // length of the string we found in source
{
INT32 iRetVal = -1;
BOOL comparedOrdinal = FALSE;
+
+ int foundLengthInSource = 0;
// Check for empty strings
if (cchCount1 == 0)
@@ -896,6 +911,7 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags)
{
iRetVal = FastLastIndexOfString(pString1, cchCount1, pString2, cchCount2);
comparedOrdinal = TRUE;
+ foundLengthInSource = cchCount2;
goto lExit;
}
@@ -910,6 +926,8 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags)
else
iRetVal = FastLastIndexOfStringInsensitive(pString1, cchCount1, pString2, cchCount2);
comparedOrdinal = TRUE;
+
+ foundLengthInSource = cchCount2;
goto lExit;
}
}
@@ -923,6 +941,7 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags)
if (NewApis::CompareStringEx(lpLocaleName, dwFlags, pString2, cchCount2, &pString1[cchCount1 + iOffset - iLength], iLength, NULL, NULL, 0) == CSTR_EQUAL)
{
iRetVal= cchCount1 + iOffset - iLength;
+ foundLengthInSource = iLength;
break;
}
}
@@ -940,6 +959,9 @@ inline BOOL IsInvariantCasing(__in LPCWSTR lpLocaleName, __in DWORD dwMapFlags)
iRetVal = -1;
}
}
+
+ if(iRetVal != -1 && pcchFound != NULL)
+ *pcchFound = foundLengthInSource;
return iRetVal;
}
diff --git a/src/vm/amd64/remotingamd64.cpp b/src/vm/amd64/remotingamd64.cpp
deleted file mode 100644
index 587afae124..0000000000
--- a/src/vm/amd64/remotingamd64.cpp
+++ /dev/null
@@ -1,672 +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.
-/*===========================================================================
-**
-** File: RemotingCpu.cpp
-**
-**
-**
-** Purpose: Defines various remoting related functions for the AMD64 architecture
-**
-**
-** See code:EEStartup#TableOfContents for EE overview
-**
-=============================================================================*/
-
-#include "common.h"
-
-#ifdef FEATURE_REMOTING
-
-#include "excep.h"
-#include "comdelegate.h"
-#include "remoting.h"
-#include "field.h"
-#include "siginfo.hpp"
-#include "stackbuildersink.h"
-#include "threads.h"
-#include "method.hpp"
-
-#include "asmconstants.h"
-
-// External variables
-extern DWORD g_dwNonVirtualThunkRemotingLabelOffset;
-extern DWORD g_dwNonVirtualThunkReCheckLabelOffset;
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::CheckForContextMatch public
-//
-// Synopsis: This code generates a check to see if the current context and
-// the context of the proxy match.
-//
-//+----------------------------------------------------------------------------
-//
-// returns zero if contexts match
-// returns non-zero if contexts don't match
-//
-extern "C" UINT_PTR __stdcall CRemotingServices__CheckForContextMatch(Object* pStubData)
-{
- // This method cannot have a contract because CreateStubForNonVirtualMethod assumes
- // it won't trash XMM registers. The code generated for contracts by recent compilers
- // is trashing XMM registers.
- STATIC_CONTRACT_NOTHROW;
- STATIC_CONTRACT_GC_NOTRIGGER;
- STATIC_CONTRACT_MODE_COOPERATIVE; // due to the Object parameter
- STATIC_CONTRACT_SO_TOLERANT;
-
- UINT_PTR contextID = *(UINT_PTR*)pStubData->UnBox();
- UINT_PTR contextCur = (UINT_PTR)GetThread()->m_Context;
- return (contextCur != contextID); // chosen to match x86 convention
-}
-
-
-//+----------------------------------------------------------------------------
-//
-// Method: CTPMethodTable::CreateThunkForVirtualMethod private
-//
-// Synopsis: Creates the thunk that pushes the supplied slot number and jumps
-// to TP Stub
-//
-//+----------------------------------------------------------------------------
-PCODE CTPMethodTable::CreateThunkForVirtualMethod(DWORD dwSlot, BYTE* pbCode)
-{
- LIMITED_METHOD_CONTRACT;
-
- BYTE *pbCodeStart = pbCode;
-
- // NOTE: if you change the code generated here, update
- // CVirtualThunkMgr::IsThunkByASM, CVirtualThunkMgr::GetMethodDescByASM
-
- //
- // mov r10, <dwSlot>
- // mov rax, TransparentProxyStub
- // jmp rax
- //
- *pbCode++ = 0x49;
- *pbCode++ = 0xc7;
- *pbCode++ = 0xc2;
- *((DWORD*)pbCode) = dwSlot;
- pbCode += sizeof(DWORD);
- *pbCode++ = 0x48;
- *pbCode++ = 0xB8;
- *((UINT64*)pbCode) = (UINT64)(TransparentProxyStub);
- pbCode += sizeof(UINT64);
- *pbCode++ = 0xFF;
- *pbCode++ = 0xE0;
-
- _ASSERTE(pbCode - pbCodeStart == ConstVirtualThunkSize);
- _ASSERTE(CVirtualThunkMgr::IsThunkByASM((PCODE)pbCodeStart));
-
- return (PCODE)pbCodeStart;
-}
-
-
-#ifdef HAS_REMOTING_PRECODE
-
-//+----------------------------------------------------------------------------
-//
-// Method: CTPMethodTable::ActivatePrecodeRemotingThunk private
-//
-// Synopsis: Patch the precode remoting thunk to begin interception
-//
-//+----------------------------------------------------------------------------
-void CTPMethodTable::ActivatePrecodeRemotingThunk()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- PORTABILITY_WARNING("CTPMethodTable::ActivatePrecodeRemotingThunk");
-}
-
-#else // HAS_REMOTING_PRECODE
-
-//+----------------------------------------------------------------------------
-//
-// Method: CTPMethodTable::CreateStubForNonVirtualMethod public
-//
-// Synopsis: Create a stub for a non virtual method
-//
-//+----------------------------------------------------------------------------
-Stub* CTPMethodTable::CreateStubForNonVirtualMethod(MethodDesc* pMD, CPUSTUBLINKER* psl,
- LPVOID pvAddrOfCode, Stub* pInnerStub)
-{
- STANDARD_VM_CONTRACT;
-
- // Sanity check
-
- Stub *pStub = NULL;
-
- // we need a hash table only for virtual methods
- _ASSERTE(!pMD->IsVirtual());
-
- // Ensure the TP MethodTable's fields have been initialized.
- EnsureFieldsInitialized();
-
- /*
- NonVirtualMethodStub<thisReg, pvAddrOfCode, pTPMethodTable, pvTPStub>
- {
- ;; thisReg: this
-
- sub rsp, 0x28
-
- test thisReg, thisReg
- je JmpAddrLabel
-
- mov rax, [thisReg]
- mov r10, <pTPMethodTable>
- cmp rax, r10
- jne JmpAddrLabel
-
- mov [rsp+0x30], rcx ;|
- mov [rsp+0x38], rdx ;|
- mov [rsp+0x40], r8 ;|
- mov [rsp+0x48], r9 ;|
- ;|
- mov rax, [thisReg + TransparentProxyObject___stubData] ;|
- call [thisReg + TransparentProxyObject___stub] ;| EmitCallToStub<pCtxMismatch>
- ;|
- mov rcx, [rsp+0x30] ;|
- mov rdx, [rsp+0x38] ;|
- mov r8, [rsp+0x40] ;|
- mov r9, [rsp+0x48] ;|
- ;|
- test rax, rax ;|
- jnz RemotingLabel ;|
-
- JmpAddrLabel:
- mov rax, <pvAddrOfCode>
- add rsp, 0x28
- jmp rax
-
- RemotingLabel:
- mov r10, <pMD>
- mov rax, <pvTPStub>
- add rsp, 0x20
- jmp rax
- }
- */
-
- X86Reg thisReg = kRCX;
- void* pvTPStub = TransparentProxyStub_CrossContext;
-
- // Generate label where a null reference exception will be thrown
- CodeLabel *pJmpAddrLabel = psl->NewCodeLabel();
- // Generate label where remoting code will execute
- CodeLabel *pRemotingLabel = psl->NewCodeLabel();
-
- // NOTE: if you change any of this code, you must update
- // CNonVirtualThunkMgr::IsThunkByASM.
-
- // Allocate callee scratch area
- // sub rsp, 0x28
- psl->X86EmitSubEsp(0x28);
-
- // test thisReg, thisReg
- psl->X86EmitR2ROp(0x85, thisReg, thisReg);
- // je JmpAddrLabel
- psl->X86EmitCondJump(pJmpAddrLabel, X86CondCode::kJE);
-
- // Emit a label here for the debugger. A breakpoint will
- // be set at the next instruction and the debugger will
- // call CNonVirtualThunkMgr::TraceManager when the
- // breakpoint is hit with the thread's context.
- CodeLabel *pRecheckLabel = psl->NewCodeLabel();
- psl->EmitLabel(pRecheckLabel);
-
- // mov rax, [thisReg]
- psl->X86EmitIndexRegLoad(kRAX, thisReg, 0);
-
- // mov r10, CTPMethodTable::GetMethodTable()
- psl->X86EmitRegLoad(kR10, (UINT_PTR)CTPMethodTable::GetMethodTable());
- // cmp rax, r10
- psl->X86EmitR2ROp(0x3B, kRAX, kR10);
-
- // jne JmpAddrLabel
- psl->X86EmitCondJump(pJmpAddrLabel, X86CondCode::kJNE);
-
- // CONSIDER: write all possible stubs in asm to ensure param registers are not trashed
-
- // mov [rsp+0x30], rcx
- // mov [rsp+0x38], rdx
- // mov [rsp+0x40], r8
- // mov [rsp+0x48], r9
- psl->X86EmitRegSave(kRCX, 0x30);
- psl->X86EmitRegSave(kRDX, 0x38);
- psl->X86EmitRegSave(kR8, 0x40);
- psl->X86EmitRegSave(kR9, 0x48);
-
- // mov rax, [thisReg + TransparentProxyObject___stub]
- psl->X86EmitIndexRegLoad(kRAX, thisReg, TransparentProxyObject___stub);
-
- // mov rcx, [thisReg + TransparentProxyObject___stubData]
- psl->X86EmitIndexRegLoad(kRCX, thisReg, TransparentProxyObject___stubData);
-
- // call rax
- psl->Emit16(0xd0ff);
-
- // mov rcx, [rsp+0x30]
- // mov rdx, [rsp+0x38]
- // mov r8, [rsp+0x40]
- // mov r9, [rsp+0x48]
- psl->X86EmitEspOffset(0x8b, kRCX, 0x30);
- psl->X86EmitEspOffset(0x8b, kRDX, 0x38);
- psl->X86EmitEspOffset(0x8b, kR8, 0x40);
- psl->X86EmitEspOffset(0x8b, kR9, 0x48);
-
- // test rax, rax
- psl->X86EmitR2ROp(0x85, kRAX, kRAX);
- // jnz RemotingLabel
- psl->X86EmitCondJump(pRemotingLabel, X86CondCode::kJNZ);
-
-// pJmpAddrLabel:
- psl->EmitLabel(pJmpAddrLabel);
-
- // Make sure that the actual code does not require MethodDesc in r10
- _ASSERTE(!pMD->RequiresMethodDescCallingConvention());
-
- // mov rax, <pvAddrOfCode>
- // add rsp, 0x28
- // REX.W jmp rax
- psl->X86EmitTailcallWithESPAdjust(psl->NewExternalCodeLabel(pvAddrOfCode), 0x28);
-
-// pRemotingLabel:
- psl->EmitLabel(pRemotingLabel);
-
- // mov r10, <pMD>
- psl->X86EmitRegLoad(kR10, (UINT_PTR)pMD);
-
- // mov rax, <pvTPStub>
- // add rsp, 0x28
- // REX.W jmp rax
- psl->X86EmitTailcallWithESPAdjust(psl->NewExternalCodeLabel(pvTPStub), 0x28);
-
- // Link and produce the stub
- pStub = psl->LinkInterceptor(pMD->GetLoaderAllocator()->GetStubHeap(),
- pInnerStub, pvAddrOfCode);
-
- return pStub;
-}
-
-
-//+----------------------------------------------------------------------------
-//
-// Synopsis: Find an existing thunk or create a new one for the given
-// method descriptor. NOTE: This is used for the methods that do
-// not go through the vtable such as constructors, private and
-// final methods.
-//
-//+----------------------------------------------------------------------------
-PCODE CTPMethodTable::CreateNonVirtualThunkForVirtualMethod(MethodDesc* pMD)
-{
- CONTRACTL
- {
- STANDARD_VM_CHECK;
- PRECONDITION(CheckPointer(pMD));
- }
- CONTRACTL_END;
-
- CPUSTUBLINKER sl;
- CPUSTUBLINKER* psl = &sl;
-
- Stub *pStub = NULL;
-
- // The thunk has not been created yet. Go ahead and create it.
- // Compute the address of the slot
- LPVOID pvEntryPoint = (LPVOID)pMD->GetMethodEntryPoint();
-
- X86Reg thisReg = kRCX;
- void* pvStub = CRemotingServices__DispatchInterfaceCall;
-
- // Generate label where a null reference exception will be thrown
- CodeLabel *pExceptionLabel = psl->NewCodeLabel();
-
- // !!! WARNING WARNING WARNING WARNING WARNING !!!
- //
- // DO NOT CHANGE this code without changing the thunk recognition
- // code in CNonVirtualThunkMgr::IsThunkByASM
- // & CNonVirtualThunkMgr::GetMethodDescByASM
- //
- // !!! WARNING WARNING WARNING WARNING WARNING !!!
-
- // NOTE: constant mov's should use an extended register to force a REX
- // prefix and the full 64-bit immediate value, so that
- // g_dwNonVirtualThunkRemotingLabelOffset and
- // g_dwNonVirtualThunkReCheckLabelOffset are the same for all
- // generated code.
-
- // if this == NULL throw NullReferenceException
- // test rcx, rcx
- psl->X86EmitR2ROp(0x85, thisReg, thisReg);
-
- // je ExceptionLabel
- psl->X86EmitCondJump(pExceptionLabel, X86CondCode::kJE);
-
- // Generate label where remoting code will execute
- CodeLabel *pRemotingLabel = psl->NewCodeLabel();
-
- // Emit a label here for the debugger. A breakpoint will
- // be set at the next instruction and the debugger will
- // call CNonVirtualThunkMgr::TraceManager when the
- // breakpoint is hit with the thread's context.
- CodeLabel *pRecheckLabel = psl->NewCodeLabel();
- psl->EmitLabel(pRecheckLabel);
-
- // If this.MethodTable == TPMethodTable then do RemotingCall
- // mov rax, [thisReg]
- psl->X86EmitIndexRegLoad(kRAX, thisReg, 0);
- // mov r10, CTPMethodTable::GetMethodTable()
- psl->X86EmitRegLoad(kR10, (UINT_PTR)CTPMethodTable::GetMethodTable());
- // cmp rax, r10
- psl->X86EmitR2ROp(0x3B, kRAX, kR10);
- // je RemotingLabel
- psl->X86EmitCondJump(pRemotingLabel, X86CondCode::kJE);
-
- // Exception handling and non-remoting share the
- // same codepath
- psl->EmitLabel(pExceptionLabel);
-
- // Non-RemotingCode
- // Jump to the vtable slot of the method
- // mov rax, pvEntryPoint
- // Encoded the mov manually so that it always uses the 64-bit form.
- //psl->X86EmitRegLoad(kRAX, (UINT_PTR)pvEntryPoint);
- psl->Emit8(REX_PREFIX_BASE | REX_OPERAND_SIZE_64BIT);
- psl->Emit8(0xb8);
- psl->EmitBytes((BYTE*)&pvEntryPoint, 8);
- // jmp rax
- psl->Emit8(0xff);
- psl->Emit8(0xe0);
-
- // Remoting code. Note: CNonVirtualThunkMgr::TraceManager
- // relies on this label being right after the jmp pvEntryPoint
- // instruction above. If you move this label, update
- // CNonVirtualThunkMgr::DoTraceStub.
- psl->EmitLabel(pRemotingLabel);
-
- // Save the MethodDesc and goto TPStub
- // push MethodDesc
- psl->X86EmitRegLoad(kR10, (UINT_PTR)pMD);
-
- // jmp TPStub
- psl->X86EmitNearJump(psl->NewExternalCodeLabel(pvStub));
-
- // Link and produce the stub
- // FUTURE: Do we have to provide the loader heap ?
- pStub = psl->Link(SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap());
-
- // Grab the offset of the RemotingLabel and RecheckLabel
- // for use in CNonVirtualThunkMgr::DoTraceStub and
- // TraceManager.
- DWORD dwOffset;
-
- dwOffset = psl->GetLabelOffset(pRemotingLabel);
- ASSERT(!g_dwNonVirtualThunkRemotingLabelOffset || g_dwNonVirtualThunkRemotingLabelOffset == dwOffset);
- g_dwNonVirtualThunkRemotingLabelOffset = dwOffset;
-
- dwOffset = psl->GetLabelOffset(pRecheckLabel);
- ASSERT(!g_dwNonVirtualThunkReCheckLabelOffset || g_dwNonVirtualThunkReCheckLabelOffset == dwOffset);
- g_dwNonVirtualThunkReCheckLabelOffset = dwOffset;
-
- return (pStub->GetEntryPoint());
-}
-
-#endif // HAS_REMOTING_PRECODE
-
-//+----------------------------------------------------------------------------
-//
-// Method: CVirtualThunkMgr::DoTraceStub public
-//
-// Synopsis: Traces the stub given the starting address
-//
-//+----------------------------------------------------------------------------
-BOOL CVirtualThunkMgr::DoTraceStub(PCODE stubStartAddress, TraceDestination *trace)
-{
- LIMITED_METHOD_CONTRACT;
-
- // <TODO> implement this </TODO>
- return FALSE;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CVirtualThunkMgr::IsThunkByASM public
-//
-// Synopsis: Check assembly to see if this one of our thunks
-//
-//+----------------------------------------------------------------------------
-BOOL CVirtualThunkMgr::IsThunkByASM(PCODE startaddr)
-{
- LIMITED_METHOD_CONTRACT;
-
- PTR_BYTE pbCode = PTR_BYTE(startaddr);
-
- // NOTE: this depends on the code generated by
- // CTPMethodTable::CreateThunkForVirtualMethod.
-
- // mov r10, <dwSlot>
- return 0x49 == pbCode[0]
- && 0xc7 == pbCode[1]
- && 0xc2 == pbCode[2]
- // mov rax, TransparentProxyStub
- && 0x48 == pbCode[7]
- && 0xb8 == pbCode[8]
- && (TADDR)TransparentProxyStub == *PTR_TADDR(pbCode+9)
- // jmp rax
- && 0xff == pbCode[17]
- && 0xe0 == pbCode[18];
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CVirtualThunkMgr::GetMethodDescByASM public
-//
-// Synopsis: Parses MethodDesc out of assembly code
-//
-//+----------------------------------------------------------------------------
-MethodDesc *CVirtualThunkMgr::GetMethodDescByASM(PCODE pbThunkCode, MethodTable *pMT)
-{
- LIMITED_METHOD_CONTRACT;
-
- // NOTE: this depends on the code generated by
- // CTPMethodTable::CreateThunkForVirtualMethod.
-
- return pMT->GetMethodDescForSlot(*((DWORD *) (pbThunkCode + 3)));
-}
-
-
-#ifndef HAS_REMOTING_PRECODE
-
-//+----------------------------------------------------------------------------
-//
-// Method: CNonVirtualThunkMgr::TraceManager public
-//
-// Synopsis: Traces the stub given the current context
-//
-//+----------------------------------------------------------------------------
-BOOL CNonVirtualThunkMgr::TraceManager(Thread* thread,
- TraceDestination* trace,
- CONTEXT* pContext,
- BYTE** pRetAddr)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(thread, NULL_OK));
- PRECONDITION(CheckPointer(trace));
- PRECONDITION(CheckPointer(pContext));
- PRECONDITION(CheckPointer(pRetAddr));
- }
- CONTRACTL_END;
-
- BOOL bRet = FALSE;
-
- MethodDesc * pMD = GetMethodDescByASM(GetIP(pContext) - g_dwNonVirtualThunkReCheckLabelOffset);
-
- LPBYTE pThis = (LPBYTE)pContext->Rcx;
-
- if ((pThis != NULL) &&
- (*(LPBYTE*)(SIZE_T)pThis == (LPBYTE)(SIZE_T)CTPMethodTable::GetMethodTable()))
- {
- // <TODO>We know that we've got a proxy
- // in the way. If the proxy is to a remote call, with no
- // managed code in between, then the debugger doesn't care and
- // we should just be able to return FALSE.
- //
- // </TODO>
- bRet = FALSE;
- }
- else
- {
- // No proxy in the way, so figure out where we're really going
- // to and let the stub manager try to pickup the trace from
- // there.
- LPBYTE stubStartAddress = (LPBYTE)GetIP(pContext) -
- g_dwNonVirtualThunkReCheckLabelOffset;
-
- // Extract the address of the destination
- BYTE* pbAddr = (BYTE *)(SIZE_T)(stubStartAddress +
- g_dwNonVirtualThunkRemotingLabelOffset - 2 - sizeof(void *));
-
- SIZE_T destAddress = *(SIZE_T *)pbAddr;
-
- // Ask the stub manager to trace the destination address
- bRet = StubManager::TraceStub((PCODE)(BYTE *)(size_t)destAddress, trace);
- }
-
- // While we may have made it this far, further tracing may reveal
- // that the debugger can't continue on. Therefore, since there is
- // no frame currently pushed, we need to tell the debugger where
- // we're returning to just in case it hits such a situtation. We
- // know that the return address is on the top of the thread's
- // stack.
- (*pRetAddr) = *((BYTE**)(size_t)(GetSP(pContext)));
-
- return bRet;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CNonVirtualThunkMgr::DoTraceStub public
-//
-// Synopsis: Traces the stub given the starting address
-//
-//+----------------------------------------------------------------------------
-BOOL CNonVirtualThunkMgr::DoTraceStub(PCODE stubStartAddress,
- TraceDestination* trace)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(stubStartAddress != NULL);
- PRECONDITION(CheckPointer(trace));
- }
- CONTRACTL_END;
-
- BOOL bRet = FALSE;
-
- if (!IsThunkByASM(stubStartAddress))
- return FALSE;
-
- CNonVirtualThunk* pThunk = FindThunk((const BYTE *)stubStartAddress);
-
- if(NULL != pThunk)
- {
- // We can either jump to
- // (1) a slot in the transparent proxy table (UNMANAGED)
- // (2) a slot in the non virtual part of the vtable
- // ... so, we need to return TRACE_MGR_PUSH with the address
- // at which we want to be called back with the thread's context
- // so we can figure out which way we're gonna go.
- if((const BYTE *)stubStartAddress == pThunk->GetThunkCode())
- {
- trace->InitForManagerPush(
- (PCODE) (stubStartAddress + g_dwNonVirtualThunkReCheckLabelOffset),
- this);
- bRet = TRUE;
- }
- }
-
- return bRet;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CNonVirtualThunkMgr::IsThunkByASM public
-//
-// Synopsis: Check assembly to see if this one of our thunks
-//
-//+----------------------------------------------------------------------------
-BOOL CNonVirtualThunkMgr::IsThunkByASM(PCODE startaddr)
-{
- LIMITED_METHOD_CONTRACT;
-
- PTR_BYTE pbCode = PTR_BYTE(startaddr);
-
- // test rcx, rcx ; 3 bytes
- return 0x48 == pbCode[0]
- && 0x85 == pbCode[1]
- && 0xc9 == pbCode[2]
- // je ... ; 2 bytes
- && 0x74 == pbCode[3]
- // mov rax, [rcx] ; 3 bytes
- // mov r10, CTPMethodTable::GetMethodTable() ; 2 bytes + MethodTable*
- && (TADDR)CTPMethodTable::GetMethodTable() == *PTR_TADDR(pbCode + 10);
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CNonVirtualThunkMgr::GetMethodDescByASM public
-//
-// Synopsis: Parses MethodDesc out of assembly code
-//
-//+----------------------------------------------------------------------------
-MethodDesc* CNonVirtualThunkMgr::GetMethodDescByASM(PCODE pbThunkCode)
-{
- LIMITED_METHOD_CONTRACT;
-
- return *((MethodDesc **) (pbThunkCode + g_dwNonVirtualThunkRemotingLabelOffset + 2));
-}
-
-#endif // HAS_REMOTING_PRECODE
-
-
-//+----------------------------------------------------------------------------
-//
-// Method: CTPMethodTable::GenericCheckForContextMatch private
-//
-// Synopsis: Calls the stub in the TP & returns TRUE if the contexts
-// match, FALSE otherwise.
-//
-// Note: 1. Called during FieldSet/Get, used for proxy extensibility
-//
-//+----------------------------------------------------------------------------
-BOOL __stdcall CTPMethodTable__GenericCheckForContextMatch(Object* orTP)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_COOPERATIVE; // due to the Object parameter
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- Object *StubData = OBJECTREFToObject(((TransparentProxyObject*)orTP)->GetStubData());
- CTPMethodTable::CheckContextCrossingProc *pfnCheckContextCrossing =
- (CTPMethodTable::CheckContextCrossingProc*)(((TransparentProxyObject*)orTP)->GetStub());
- return pfnCheckContextCrossing(StubData) == 0;
-}
-
-#endif // FEATURE_REMOTING
-
-
diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp
index e6d4ed1b4b..e13c7dbe2a 100644
--- a/src/vm/appdomain.cpp
+++ b/src/vm/appdomain.cpp
@@ -37,7 +37,6 @@
#include "comdelegate.h"
#include "siginfo.hpp"
#ifdef FEATURE_REMOTING
-#include "appdomainhelper.h"
#include "objectclone.h"
#endif
#include "typekey.h"
diff --git a/src/vm/appdomainhelper.cpp b/src/vm/appdomainhelper.cpp
deleted file mode 100644
index 2c0531648f..0000000000
--- a/src/vm/appdomainhelper.cpp
+++ /dev/null
@@ -1,546 +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.
-
-
-//
-
-#include "common.h"
-
-#ifdef FEATURE_REMOTING
-
-#include "appdomainhelper.h"
-#include "appdomain.inl"
-
-void AppDomainHelper::CopyEncodingToByteArray(IN PBYTE pbData,
- IN DWORD cbData,
- OUT OBJECTREF* pArray)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(cbData==0 || pbData!=NULL);
- PRECONDITION(CheckPointer(pArray));
- }
- CONTRACTL_END;
- PREFIX_ASSUME(pArray != NULL);
-
- U1ARRAYREF pObj;
-
- if(cbData) {
- pObj = (U1ARRAYREF)AllocatePrimitiveArray(ELEMENT_TYPE_U1,cbData);
- memcpyNoGCRefs(pObj->m_Array, pbData, cbData);
- *pArray = (OBJECTREF) pObj;
- } else
- *pArray = NULL;
-
- VALIDATEOBJECTREF(*pArray);
-}
-
-
-void AppDomainHelper::CopyByteArrayToEncoding(IN U1ARRAYREF* pArray,
- OUT PBYTE* ppbData,
- OUT DWORD* pcbData)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- PRECONDITION(pArray!=NULL);
- PRECONDITION(ppbData!=NULL);
- PRECONDITION(pcbData!=NULL);
- }
- CONTRACTL_END;
-
- VALIDATEOBJECTREF(*pArray);
-
- if (*pArray == NULL) {
- *ppbData = NULL;
- *pcbData = 0;
- return;
- }
-
- DWORD size = (*pArray)->GetNumComponents();
- if(size) {
- *ppbData = new BYTE[size];
- *pcbData = size;
-
- CopyMemory(*ppbData, (*pArray)->GetDirectPointerToNonObjectElements(), size);
- }
-}
-
-
-struct MarshalObjectArgs : public CtxTransitionBaseArgs
-{
- OBJECTREF* orObject;
- U1ARRAYREF* porBlob;
-};
-
-void MarshalObjectADCallback(MarshalObjectArgs * args)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
- MethodDescCallSite marshalObject(METHOD__APP_DOMAIN__MARSHAL_OBJECT);
-
- ARG_SLOT argsCall[] = {
- ObjToArgSlot(*(args->orObject))
- };
-
- *(args->porBlob) = (U1ARRAYREF) marshalObject.Call_RetOBJECTREF(argsCall);
-}
-
-
-// Marshal a single object into a serialized blob.
-void AppDomainHelper::MarshalObject(ADID appDomain,
- IN OBJECTREF *orObject, // Object must be GC protected
- OUT U1ARRAYREF *porBlob)
-{
-
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(orObject!=NULL);
- PRECONDITION(porBlob!=NULL);
- PRECONDITION(IsProtectedByGCFrame(orObject));
- }
- CONTRACTL_END;
-
- VALIDATEOBJECTREF(*orObject);
-
- MarshalObjectArgs args;
- args.orObject = orObject;
- args.porBlob = porBlob;
-
- MakeCallWithPossibleAppDomainTransition(appDomain, (FPAPPDOMAINCALLBACK) MarshalObjectADCallback, &args);
-
- VALIDATEOBJECTREF(*porBlob);
-
-}
-
-void AppDomainHelper::MarshalObject(IN OBJECTREF *orObject, // Object must be GC protected
- OUT U1ARRAYREF *porBlob)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(orObject!=NULL);
- PRECONDITION(porBlob!=NULL);
- PRECONDITION(IsProtectedByGCFrame(orObject));
- }
- CONTRACTL_END;
-
- VALIDATEOBJECTREF(*orObject);
-
- MethodDescCallSite marshalObject(METHOD__APP_DOMAIN__MARSHAL_OBJECT);
-
- ARG_SLOT argsCall[] = {
- ObjToArgSlot(*orObject)
- };
-
- *porBlob = (U1ARRAYREF) marshalObject.Call_RetOBJECTREF(argsCall);
-
- VALIDATEOBJECTREF(*porBlob);
-}
-
-// Marshal a single object into a serialized blob.
-void AppDomainHelper::MarshalObject(IN AppDomain *pDomain,
- IN OBJECTREF *orObject, // Object must be GC protected
- OUT BYTE **ppbBlob,
- OUT DWORD *pcbBlob)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(pDomain!=NULL);
- PRECONDITION(orObject!=NULL);
- PRECONDITION(ppbBlob!=NULL);
- PRECONDITION(pcbBlob!=NULL);
- PRECONDITION(IsProtectedByGCFrame(orObject));
- }
- CONTRACTL_END;
-
- VALIDATEOBJECTREF(*orObject);
-
- U1ARRAYREF orBlob = NULL;
-
- GCPROTECT_BEGIN(orBlob);
-
- MethodDescCallSite marshalObject(METHOD__APP_DOMAIN__MARSHAL_OBJECT);
-
- ENTER_DOMAIN_PTR(pDomain,ADV_RUNNINGIN)
- {
- ARG_SLOT args[] =
- {
- ObjToArgSlot(*orObject)
- };
-
- orBlob = (U1ARRAYREF) marshalObject.Call_RetOBJECTREF(args);
- }
- END_DOMAIN_TRANSITION;
-
- if (orBlob != NULL)
- CopyByteArrayToEncoding(&orBlob,
- ppbBlob,
- pcbBlob);
- GCPROTECT_END();
-}
-
-// Marshal two objects into serialized blobs.
-void AppDomainHelper::MarshalObjects(IN AppDomain *pDomain,
- IN OBJECTREF *orObject1,
- IN OBJECTREF *orObject2,
- OUT BYTE **ppbBlob1,
- OUT DWORD *pcbBlob1,
- OUT BYTE **ppbBlob2,
- OUT DWORD *pcbBlob2)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(pDomain!=NULL);
- PRECONDITION(orObject1!=NULL);
- PRECONDITION(ppbBlob1!=NULL);
- PRECONDITION(pcbBlob1!=NULL);
- PRECONDITION(orObject2!=NULL);
- PRECONDITION(ppbBlob2!=NULL);
- PRECONDITION(pcbBlob2!=NULL);
- PRECONDITION(IsProtectedByGCFrame(orObject1));
- PRECONDITION(IsProtectedByGCFrame(orObject2));
- }
- CONTRACTL_END;
-
- VALIDATEOBJECTREF(*orObject1);
- VALIDATEOBJECTREF(*orObject2);
-
- struct _gc {
- U1ARRAYREF orBlob1;
- U1ARRAYREF orBlob2;
- } gc;
- ZeroMemory(&gc, sizeof(gc));
-
- GCPROTECT_BEGIN(gc);
-
- MethodDescCallSite marshalObjects(METHOD__APP_DOMAIN__MARSHAL_OBJECTS);
-
- ENTER_DOMAIN_PTR(pDomain,ADV_RUNNINGIN)
- {
- ARG_SLOT args[] =
- {
- ObjToArgSlot(*orObject1),
- ObjToArgSlot(*orObject2),
- PtrToArgSlot(&gc.orBlob2),
- };
-
- gc.orBlob1 = (U1ARRAYREF) marshalObjects.Call_RetOBJECTREF(args);
- }
- END_DOMAIN_TRANSITION;
-
- if (gc.orBlob1 != NULL)
- {
- CopyByteArrayToEncoding(&gc.orBlob1,
- ppbBlob1,
- pcbBlob1);
- }
-
- if (gc.orBlob2 != NULL)
- {
- CopyByteArrayToEncoding(&gc.orBlob2,
- ppbBlob2,
- pcbBlob2);
- }
-
- GCPROTECT_END();
-}
-
-// Unmarshal a single object from a serialized blob.
-// Callers must GC protect both porBlob and porObject.
-void AppDomainHelper::UnmarshalObject(IN AppDomain *pDomain,
- IN U1ARRAYREF *porBlob, // Object must be GC protected
- OUT OBJECTREF *porObject) // Object must be GC protected
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(pDomain!=NULL);
- PRECONDITION(porBlob!=NULL);
- PRECONDITION(porObject!=NULL);
- PRECONDITION(IsProtectedByGCFrame(porBlob));
- PRECONDITION(IsProtectedByGCFrame(porObject));
- }
- CONTRACTL_END;
-
- VALIDATEOBJECTREF(*porBlob);
-
- MethodDescCallSite unmarshalObject(METHOD__APP_DOMAIN__UNMARSHAL_OBJECT);
-
- ENTER_DOMAIN_PTR(pDomain,ADV_RUNNINGIN)
- {
- ARG_SLOT args[] =
- {
- ObjToArgSlot(*porBlob)
- };
-
- *porObject = unmarshalObject.Call_RetOBJECTREF(args);
- }
- END_DOMAIN_TRANSITION;
-
- VALIDATEOBJECTREF(*porObject);
-}
-
-// Unmarshal a single object from a serialized blob.
-void AppDomainHelper::UnmarshalObject(IN AppDomain *pDomain,
- IN BYTE *pbBlob,
- IN DWORD cbBlob,
- OUT OBJECTREF *porObject)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(pDomain!=NULL);
- PRECONDITION(porObject!=NULL);
- PRECONDITION(IsProtectedByGCFrame(porObject));
- }
- CONTRACTL_END;
-
- OBJECTREF orBlob = NULL;
-
- MethodDescCallSite unmarshalObject(METHOD__APP_DOMAIN__UNMARSHAL_OBJECT);
-
- ENTER_DOMAIN_PTR(pDomain,ADV_RUNNINGIN)
- {
- GCPROTECT_BEGIN(orBlob);
-
- AppDomainHelper::CopyEncodingToByteArray(pbBlob,
- cbBlob,
- &orBlob);
-
- ARG_SLOT args[] =
- {
- ObjToArgSlot(orBlob)
- };
-
- *porObject = unmarshalObject.Call_RetOBJECTREF(args);
-
- GCPROTECT_END();
- }
- END_DOMAIN_TRANSITION;
-
- VALIDATEOBJECTREF(*porObject);
-}
-
-// Unmarshal two objects from serialized blobs.
-void AppDomainHelper::UnmarshalObjects(IN AppDomain *pDomain,
- IN BYTE *pbBlob1,
- IN DWORD cbBlob1,
- IN BYTE *pbBlob2,
- IN DWORD cbBlob2,
- OUT OBJECTREF *porObject1,
- OUT OBJECTREF *porObject2)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(pDomain!=NULL);
- PRECONDITION(porObject1!=NULL);
- PRECONDITION(porObject2!=NULL);
- PRECONDITION(IsProtectedByGCFrame(porObject1));
- PRECONDITION(IsProtectedByGCFrame(porObject2));
- }
- CONTRACTL_END;
-
- MethodDescCallSite unmarshalObjects(METHOD__APP_DOMAIN__UNMARSHAL_OBJECTS);
-
- struct _gc {
- OBJECTREF orBlob1;
- OBJECTREF orBlob2;
- OBJECTREF orObject2;
- } gc;
- ZeroMemory(&gc, sizeof(gc));
-
- ENTER_DOMAIN_PTR(pDomain,ADV_RUNNINGIN)
- {
-
- GCPROTECT_BEGIN(gc);
-
- AppDomainHelper::CopyEncodingToByteArray(pbBlob1,
- cbBlob1,
- &gc.orBlob1);
-
- AppDomainHelper::CopyEncodingToByteArray(pbBlob2,
- cbBlob2,
- &gc.orBlob2);
-
- ARG_SLOT args[] =
- {
- ObjToArgSlot(gc.orBlob1),
- ObjToArgSlot(gc.orBlob2),
- PtrToArgSlot(&gc.orObject2),
- };
-
- *porObject1 = unmarshalObjects.Call_RetOBJECTREF(args);
- *porObject2 = gc.orObject2;
-
- GCPROTECT_END();
- }
- END_DOMAIN_TRANSITION;
-
- VALIDATEOBJECTREF(*porObject1);
- VALIDATEOBJECTREF(*porObject2);
-}
-
-// Copy an object from the given appdomain into the current appdomain.
-OBJECTREF AppDomainHelper::CrossContextCopyFrom(IN ADID dwDomainId,
- IN OBJECTREF *orObject) // Object must be GC protected
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(orObject!=NULL);
- PRECONDITION(IsProtectedByGCFrame(orObject));
- }
- CONTRACTL_END;
-
- struct _gc
- {
- U1ARRAYREF orBlob;
- OBJECTREF pResult;
- } gc;
- ZeroMemory(&gc, sizeof(gc));
-
- GCPROTECT_BEGIN(gc);
- AppDomainHelper::MarshalObject(dwDomainId, orObject, &gc.orBlob);
- AppDomainHelper::UnmarshalObject(GetAppDomain(), &gc.orBlob, &gc.pResult);
- GCPROTECT_END();
- VALIDATEOBJECTREF(gc.pResult);
- return gc.pResult;
-}
-
-// Copy an object from the given appdomain into the current appdomain.
-OBJECTREF AppDomainHelper::CrossContextCopyTo(IN ADID dwDomainId,
- IN OBJECTREF *orObject) // Object must be GC protected
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(orObject!=NULL);
- PRECONDITION(IsProtectedByGCFrame(orObject));
- }
- CONTRACTL_END;
-
-
- struct _gc
- {
- U1ARRAYREF orBlob;
- OBJECTREF pResult;
- } gc;
- ZeroMemory(&gc, sizeof(gc));
-
- GCPROTECT_BEGIN(gc);
- AppDomainHelper::MarshalObject(orObject, &gc.orBlob);
- ENTER_DOMAIN_ID(dwDomainId);
- AppDomainHelper::UnmarshalObject(GetAppDomain(),&gc.orBlob, &gc.pResult);
- END_DOMAIN_TRANSITION;
- GCPROTECT_END();
- VALIDATEOBJECTREF(gc.pResult);
- return gc.pResult;
-
-}
-
-// Copy an object from the given appdomain into the current appdomain.
-OBJECTREF AppDomainHelper::CrossContextCopyFrom(IN AppDomain *pDomain,
- IN OBJECTREF *orObject) // Object must be GC protected
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(orObject!=NULL);
- PRECONDITION(IsProtectedByGCFrame(orObject));
- PRECONDITION(pDomain!=NULL);
- PRECONDITION(pDomain != GetAppDomain());
- }
- CONTRACTL_END;
-
- VALIDATEOBJECTREF(*orObject);
-
- struct _gc {
- U1ARRAYREF orBlob;
- OBJECTREF result;
- } gc;
- ZeroMemory(&gc, sizeof(gc));
-
- GCPROTECT_BEGIN(gc);
- ENTER_DOMAIN_PTR(pDomain, ADV_RUNNINGIN);
- AppDomainHelper::MarshalObject(orObject, &gc.orBlob);
- END_DOMAIN_TRANSITION;
- AppDomainHelper::UnmarshalObject(GetAppDomain(),&gc.orBlob, &gc.result);
- GCPROTECT_END();
-
- VALIDATEOBJECTREF(gc.result);
-
- return gc.result;
-}
-
-// Copy an object to the given appdomain from the current appdomain.
-OBJECTREF AppDomainHelper::CrossContextCopyTo(IN AppDomain *pDomain,
- IN OBJECTREF *orObject) // Object must be GC protected
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(orObject!=NULL);
- PRECONDITION(IsProtectedByGCFrame(orObject));
- PRECONDITION(pDomain!=NULL);
- PRECONDITION(pDomain != GetAppDomain());
- }
- CONTRACTL_END;
-
- VALIDATEOBJECTREF(*orObject);
-
- struct _gc {
- U1ARRAYREF orBlob;
- OBJECTREF result;
- } gc;
- ZeroMemory(&gc, sizeof(gc));
-
- GCPROTECT_BEGIN(gc);
- AppDomainHelper::MarshalObject(orObject, &gc.orBlob);
- AppDomainHelper::UnmarshalObject(pDomain, &gc.orBlob, &gc.result);
- GCPROTECT_END();
-
- VALIDATEOBJECTREF(gc.result);
-
- return gc.result;
-}
-
-#endif // FEATURE_REMOTING
-
diff --git a/src/vm/appdomainhelper.h b/src/vm/appdomainhelper.h
deleted file mode 100644
index e331555292..0000000000
--- a/src/vm/appdomainhelper.h
+++ /dev/null
@@ -1,371 +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.
-
-
-#ifndef _APPDOMAIN_HELPER_H_
-#define _APPDOMAIN_HELPER_H_
-
-#ifndef FEATURE_REMOTING
-#error FEATURE_REMOTING is not set, please do not include appdomainhelper.h
-#endif
-
-// Marshal a single object into a serialized blob.
-//
-//
-
-class AppDomainHelper {
-
- friend class MarshalCache;
-
- // A pair of helper to move serialization info between managed byte-array and
- // unmanaged blob.
- static void AppDomainHelper::CopyEncodingToByteArray(IN PBYTE pbData,
- IN DWORD cbData,
- OUT OBJECTREF* pArray);
-
- static void AppDomainHelper::CopyByteArrayToEncoding(IN U1ARRAYREF* pArray,
- OUT PBYTE* ppbData,
- OUT DWORD* pcbData);
-
-public:
- // Marshal a single object into a serialized blob.
- static void AppDomainHelper::MarshalObject(IN OBJECTREF *orObject,
- OUT U1ARRAYREF *porBlob);
-
- static void AppDomainHelper::MarshalObject(IN ADID pDomain,
- IN OBJECTREF *orObject,
- OUT U1ARRAYREF *porBlob);
- // Marshal one object into a seraialized blob.
- static void AppDomainHelper::MarshalObject(IN AppDomain *pDomain,
- IN OBJECTREF *orObject,
- OUT BYTE **ppbBlob,
- OUT DWORD *pcbBlob);
-
- // Marshal two objects into serialized blobs.
- static void AppDomainHelper::MarshalObjects(IN AppDomain *pDomain,
- IN OBJECTREF *orObject1,
- IN OBJECTREF *orObject2,
- OUT BYTE **ppbBlob1,
- OUT DWORD *pcbBlob1,
- OUT BYTE **ppbBlob2,
- OUT DWORD *pcbBlob2);
-
- // Unmarshal a single object from a serialized blob.
- static void AppDomainHelper::UnmarshalObject(IN AppDomain *pDomain,
- IN U1ARRAYREF *porBlob,
- OUT OBJECTREF *porObject);
-
- // Unmarshal a single object from a serialized blob.
- static void AppDomainHelper::UnmarshalObject(IN AppDomain *pDomain,
- IN BYTE *pbBlob,
- IN DWORD cbBlob,
- OUT OBJECTREF *porObject);
-
- // Unmarshal two objects from serialized blobs.
- static void AppDomainHelper::UnmarshalObjects(IN AppDomain *pDomain,
- IN BYTE *pbBlob1,
- IN DWORD cbBlob1,
- IN BYTE *pbBlob2,
- IN DWORD cbBlob2,
- OUT OBJECTREF *porObject1,
- OUT OBJECTREF *porObject2);
-
- // Copy an object from the given appdomain into the current appdomain.
- static OBJECTREF AppDomainHelper::CrossContextCopyFrom(IN AppDomain *pAppDomain,
- IN OBJECTREF *orObject);
- // Copy an object to the given appdomain from the current appdomain.
- static OBJECTREF AppDomainHelper::CrossContextCopyTo(IN AppDomain *pAppDomain,
- IN OBJECTREF *orObject);
- // Copy an object from the given appdomain into the current appdomain.
- static OBJECTREF AppDomainHelper::CrossContextCopyFrom(IN ADID dwDomainId,
- IN OBJECTREF *orObject);
- // Copy an object to the given appdomain from the current appdomain.
- static OBJECTREF AppDomainHelper::CrossContextCopyTo(IN ADID dwDomainId,
- IN OBJECTREF *orObject);
-
-};
-
-// Cache the bits needed to serialize/deserialize managed objects that will be
-// passed across appdomain boundaries during a stackwalk. The serialization is
-// performed lazily the first time it's needed and remains valid throughout the
-// stackwalk. The last deserialized object is cached and tagged with its
-// appdomain context. It's valid as long as we're walking frames within the same
-// appdomain.
-//
-class MarshalCache
-{
-public:
- MarshalCache()
- {
- LIMITED_METHOD_CONTRACT;
- ZeroMemory(this, sizeof(*this));
- }
-
- ~MarshalCache()
- {
- LIMITED_METHOD_CONTRACT;
- if (m_pbObj1)
- delete [] m_pbObj1;
- if (m_pbObj2)
- delete [] m_pbObj2;
- }
-
- void EnsureSerializationOK()
- {
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
- if ((m_sGC.m_orInput1 != NULL && (m_pbObj1 == NULL || m_cbObj1 == 0)) ||
- (m_sGC.m_orInput2 != NULL && (m_pbObj2 == NULL || m_cbObj2 == 0)))
- {
- // Serialization went bad -> Throw exception indicating so.
- COMPlusThrow(kSecurityException, IDS_UNMARSHALABLE_DEMAND_OBJECT);
- }
- }
-
- void EnsureDeserializationOK()
- {
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
- if ((m_pbObj1 != NULL && m_sGC.m_orOutput1 == NULL ) ||
- (m_pbObj2 != NULL && m_sGC.m_orOutput2 == NULL ) )
- {
- // DeSerialization went bad -> Throw exception indicating so.
- COMPlusThrow(kSecurityException, IDS_UNMARSHALABLE_DEMAND_OBJECT);
- }
- }
-
-#ifndef DACCESS_COMPILE
-
- // Set the original value of the first cached object.
- void SetObject(OBJECTREF orObject)
- {
- LIMITED_METHOD_CONTRACT;
- m_pOriginalDomain = ::GetAppDomain();
- m_sGC.m_orInput1 = orObject;
- }
-
- // Set the original values of both cached objects.
- void SetObjects(OBJECTREF orObject1, OBJECTREF orObject2)
- {
- LIMITED_METHOD_CONTRACT;
- m_pOriginalDomain = ::GetAppDomain();
- m_sGC.m_orInput1 = orObject1;
- m_sGC.m_orInput2 = orObject2;
- }
-
-#endif //!DACCESS_COMPILE
-
- // Get a copy of the first object suitable for use in the given appdomain.
- OBJECTREF GetObject(AppDomain *pDomain)
- {
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
- CheckADValidity(pDomain, ADV_RUNNINGIN);
-
- // No transition -- just return original object.
- if (pDomain == m_pOriginalDomain) {
- if (m_fObjectUpdated)
- UpdateObjectFinish();
- return m_sGC.m_orInput1;
- }
-
- // We've already deserialized the object into the correct context.
- if (pDomain == m_pCachedDomain)
- return m_sGC.m_orOutput1;
-
- // If we've updated the object in a different appdomain from the one we
- // originally started in, the cached object will be more up to date than
- // the original. Resync the objects.
- if (m_fObjectUpdated)
- UpdateObjectFinish();
-
- // Check whether we've serialized the original input object yet.
- if (m_pbObj1 == NULL && m_sGC.m_orInput1 != NULL)
- {
- AppDomainHelper::MarshalObject(m_pOriginalDomain,
- &m_sGC.m_orInput1,
- &m_pbObj1,
- &m_cbObj1);
- EnsureSerializationOK();
- }
-
- // Deserialize into the correct context.
- if (m_pbObj1 != NULL)
- {
- AppDomainHelper::UnmarshalObject(pDomain,
- m_pbObj1,
- m_cbObj1,
- &m_sGC.m_orOutput1);
- EnsureDeserializationOK();
- }
- m_pCachedDomain = pDomain;
-
- return m_sGC.m_orOutput1;
- }
-
- // As above, but retrieve both objects.
- OBJECTREF GetObjects(AppDomain *pDomain, OBJECTREF *porObject2)
- {
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
- CheckADValidity(pDomain, ADV_RUNNINGIN);
- // No transition -- just return original objects.
- if (pDomain == m_pOriginalDomain) {
- if (m_fObjectUpdated)
- UpdateObjectFinish();
- *porObject2 = m_sGC.m_orInput2;
- return m_sGC.m_orInput1;
- }
-
- // We've already deserialized the objects into the correct context.
- if (pDomain == m_pCachedDomain) {
- *porObject2 = m_sGC.m_orOutput2;
- return m_sGC.m_orOutput1;
- }
-
- // If we've updated the object in a different appdomain from the one we
- // originally started in, the cached object will be more up to date than
- // the original. Resync the objects.
- if (m_fObjectUpdated)
- UpdateObjectFinish();
-
- // Check whether we've serialized the original input objects yet.
- if ((m_pbObj1 == NULL && m_sGC.m_orInput1 != NULL) ||
- (m_pbObj2 == NULL && m_sGC.m_orInput2 != NULL))
- {
- AppDomainHelper::MarshalObjects(m_pOriginalDomain,
- &m_sGC.m_orInput1,
- &m_sGC.m_orInput2,
- &m_pbObj1,
- &m_cbObj1,
- &m_pbObj2,
- &m_cbObj2);
- EnsureSerializationOK();
-
- }
- if (m_pbObj1 != NULL || m_pbObj2 != NULL)
- {
- // Deserialize into the correct context.
- AppDomainHelper::UnmarshalObjects(pDomain,
- m_pbObj1,
- m_cbObj1,
- m_pbObj2,
- m_cbObj2,
- &m_sGC.m_orOutput1,
- &m_sGC.m_orOutput2);
- EnsureDeserializationOK();
- }
- m_pCachedDomain = pDomain;
-
- *porObject2 = m_sGC.m_orOutput2;
- return m_sGC.m_orOutput1;
- }
-
- // Change the first object (updating the cacheing information
- // appropriately).
- void UpdateObject(AppDomain *pDomain, OBJECTREF orObject)
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- // The cached serialized blob is now useless.
- CheckADValidity(pDomain, ADV_RUNNINGIN);
- if (m_pbObj1)
- delete [] m_pbObj1;
- m_pbObj1 = NULL;
- m_cbObj1 = 0;
-
- // The object we have now is valid in it's own appdomain, so place that
- // in the object cache.
- m_pCachedDomain = pDomain;
- m_sGC.m_orOutput1 = orObject;
-
- // If the object is updated in the original context, just use the new
- // value as is. In this case we have the data to re-marshal the updated
- // object as normal, so we can consider the cache fully updated and exit
- // now.
- if (pDomain == m_pOriginalDomain) {
- m_sGC.m_orInput1 = orObject;
- m_fObjectUpdated = false;
- return;
- }
-
- // We want to avoid re-marshaling the updated value as long as possible
- // (it might be updated again before we need its value in a different
- // context). So set a flag to indicate that the object must be
- // re-marshaled when the value is queried in a new context.
- m_fObjectUpdated = true;
- }
-
- // This structure is public only so that it can be GC protected. Do not
- // access the fields directly, they change in an unpredictable fashion due
- // to the lazy cacheing algorithm.
- struct _gc {
- OBJECTREF m_orInput1;
- OBJECTREF m_orInput2;
- OBJECTREF m_orOutput1;
- OBJECTREF m_orOutput2;
- } m_sGC;
-
-private:
-
- // Called after one or more calls to UpdateObject to marshal the updated
- // object back into its original context (it's assumed we're called in this
- // context).
- void UpdateObjectFinish()
- {
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(m_fObjectUpdated && m_pbObj1 == NULL);
- }
- CONTRACTL_END;
- AppDomainHelper::MarshalObject(m_pCachedDomain,
- &m_sGC.m_orOutput1,
- &m_pbObj1,
- &m_cbObj1);
- AppDomainHelper::UnmarshalObject(m_pOriginalDomain,
- m_pbObj1,
- m_cbObj1,
- &m_sGC.m_orInput1);
- m_fObjectUpdated = false;
- }
-
- BYTE *m_pbObj1;
- DWORD m_cbObj1;
- BYTE *m_pbObj2;
- DWORD m_cbObj2;
- AppDomain *m_pCachedDomain;
- AppDomain *m_pOriginalDomain;
- bool m_fObjectUpdated;
-};
-
-#endif
diff --git a/src/vm/appdomainnative.cpp b/src/vm/appdomainnative.cpp
index 47509d731f..dd46add6ee 100644
--- a/src/vm/appdomainnative.cpp
+++ b/src/vm/appdomainnative.cpp
@@ -9,7 +9,6 @@
#include "appdomainnative.hpp"
#ifdef FEATURE_REMOTING
#include "remoting.h"
-#include "appdomainhelper.h"
#endif
#include "security.h"
#include "vars.hpp"
diff --git a/src/vm/assembly.cpp b/src/vm/assembly.cpp
index 3e1745b23d..fc9ce7189c 100644
--- a/src/vm/assembly.cpp
+++ b/src/vm/assembly.cpp
@@ -46,7 +46,6 @@
#include "appdomainnative.hpp"
#ifdef FEATURE_REMOTING
#include "remoting.h"
-#include "appdomainhelper.h"
#endif
#include "customattribute.h"
#include "winnls.h"
diff --git a/src/vm/assemblynamesconfigfactory.cpp b/src/vm/assemblynamesconfigfactory.cpp
deleted file mode 100644
index ed5da9679b..0000000000
--- a/src/vm/assemblynamesconfigfactory.cpp
+++ /dev/null
@@ -1,264 +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.
-// AssemblyNamesConfigFactory.cpp
-//
-
-//
-//
-// Parses XML files and adding runtime entries to assembly list
-// Abstract, derived classes need to override AddAssemblyName
-#include "common.h"
-#include "common.h"
-#include <xmlparser.h>
-#include <objbase.h>
-#include "parse.h"
-#include "assemblynamesconfigfactory.h"
-
-
-#define ISWHITE(ch) ((ch) >= 0x09 && (ch) <= 0x0D || (ch) == 0x20)
-
-#define CONST_STRING_AND_LEN(str) str, NumItems(str)-1
-
-extern int EEXMLStringCompare(const WCHAR *pStr1,
- DWORD cchStr1,
- const WCHAR *pStr2,
- DWORD cchStr2);
-extern HRESULT VersionFromString(LPCWSTR wzVersion, WORD *pwVerMajor, WORD *pwVerMinor,
- WORD *pwVerBld, WORD *pwVerRev);
-extern HRESULT MapProcessorArchitectureToPEKIND(LPCWSTR pwzProcArch, PEKIND *pe);
-
-AssemblyNamesConfigFactory::AssemblyNamesConfigFactory()
-{
- LIMITED_METHOD_CONTRACT;
- m_pAssemblyName = NULL;
- m_bCurrentEntryInvalid = TRUE;
- m_dwCurrentElementDepth = 0;
- m_dwProperty = ASM_NAME_MAX_PARAMS;
-}
-
-AssemblyNamesConfigFactory::~AssemblyNamesConfigFactory()
-{
- LIMITED_METHOD_CONTRACT;
-}
-
-
-HRESULT STDMETHODCALLTYPE AssemblyNamesConfigFactory::NotifyEvent(
- /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
- /* [in] */ XML_NODEFACTORY_EVENT iEvt)
-{
- LIMITED_METHOD_CONTRACT;
-
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE AssemblyNamesConfigFactory::BeginChildren(
- /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
- /* [in] */ XML_NODE_INFO __RPC_FAR *pNodeInfo)
-{
- LIMITED_METHOD_CONTRACT;
- m_dwCurrentElementDepth ++;
-
- return S_OK;
-}
-
-//---------------------------------------------------------------------------
-HRESULT STDMETHODCALLTYPE AssemblyNamesConfigFactory::EndChildren(
- /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
- /* [in] */ BOOL fEmptyNode,
- /* [in] */ XML_NODE_INFO __RPC_FAR *pNodeInfo)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- INJECT_FAULT(return E_OUTOFMEMORY;);
- }
- CONTRACTL_END;
-
- HRESULT hr = S_OK;
- EX_TRY
- {
- if (m_dwCurrentElementDepth == 1 && m_pAssemblyName != NULL)
- {
- if (!m_bCurrentEntryInvalid)
- {
- // publish
- AddAssemblyName(m_pAssemblyName);
- };
- m_pAssemblyName->Release();
- m_pAssemblyName = NULL;
- }
-
- if (!fEmptyNode)
- m_dwCurrentElementDepth --;
- }
- EX_CATCH_HRESULT(hr);
- return hr;
-}
-
-
-
-HRESULT STDMETHODCALLTYPE AssemblyNamesConfigFactory::CreateNode(
- /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
- /* [in] */ PVOID pNode,
- /* [in] */ USHORT cNumRecs,
- /* [in] */ XML_NODE_INFO* __RPC_FAR * __RPC_FAR apNodeInfo)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- INJECT_FAULT(return E_OUTOFMEMORY;);
- }
- CONTRACTL_END;
-
- if(m_dwCurrentElementDepth > 1)
- return S_OK;
-
- HRESULT hr = S_OK;
-
- for(DWORD i = 0; i < cNumRecs; i++) {
- CONTRACT_VIOLATION(ThrowsViolation); // Lots of stuff in here throws!
-
- if(apNodeInfo[i]->dwType == XML_ELEMENT ||
- apNodeInfo[i]->dwType == XML_ATTRIBUTE ||
- apNodeInfo[i]->dwType == XML_PCDATA)
- {
-
- DWORD dwStringSize = apNodeInfo[i]->ulLen;
- LPWSTR pszString = (WCHAR*) apNodeInfo[i]->pwcText;
- // Trim the value
-
- // we should never decrement lgth if it's 0, because it's unsigned
-
- for(;*pszString && ISWHITE(*pszString) && dwStringSize>0; pszString++, dwStringSize--);
- while( dwStringSize > 0 && ISWHITE(pszString[dwStringSize-1]))
- dwStringSize--;
- switch(apNodeInfo[i]->dwType)
- {
- case XML_ELEMENT :
- if(EEXMLStringCompare(pszString, dwStringSize, CONST_STRING_AND_LEN(W("assemblyIdentity"))) == 0)
- {
- // new entry
- _ASSERTE(m_pAssemblyName == NULL);
- IfFailRet(CreateAssemblyNameObject(&m_pAssemblyName, NULL,0,NULL));
- m_bCurrentEntryInvalid = FALSE;
- }
- else
- {
- m_bCurrentEntryInvalid = TRUE;
- }
-
- break;
-
-
- case XML_ATTRIBUTE :
- if(m_bCurrentEntryInvalid)
- break;
-
- if(EEXMLStringCompare(pszString, dwStringSize, CONST_STRING_AND_LEN(W("name"))) == 0)
- {
- m_dwProperty = ASM_NAME_NAME;
- }
- else
- if(EEXMLStringCompare(pszString, dwStringSize, CONST_STRING_AND_LEN(W("version"))) == 0)
- {
- m_dwProperty = ASM_NAME_MAJOR_VERSION;
- }
- else
- if(EEXMLStringCompare(pszString, dwStringSize, CONST_STRING_AND_LEN(W("publicKeyToken"))) == 0)
- {
- m_dwProperty = ASM_NAME_PUBLIC_KEY_TOKEN;
- }
- else
- if(EEXMLStringCompare(pszString, dwStringSize, CONST_STRING_AND_LEN(W("processorArchitecture"))) == 0)
- {
- m_dwProperty = ASM_NAME_ARCHITECTURE;
- }
- else
- {
- m_bCurrentEntryInvalid = TRUE;
- }
- break;
-
-
- case XML_PCDATA :
- if(m_bCurrentEntryInvalid)
- break;
-
- _ASSERTE(m_pAssemblyName!= NULL); // can only be null if m_bCurrentEntryInvalid
- switch(m_dwProperty)
- {
- case ASM_NAME_NAME:
- {
- StackSString s(pszString,dwStringSize);
- // takes number of bytes, thus *2
- IfFailRet(m_pAssemblyName->SetProperty(ASM_NAME_NAME, LPCWSTR(s), (dwStringSize+1)*sizeof(WCHAR)));
- }
- break;
- case ASM_NAME_MAJOR_VERSION:
- {
- StackSString s(pszString,dwStringSize);
- WORD wVerMajor = 0;
- WORD wVerMinor = 0;
- WORD wVerBld = 0;
- WORD wVerRev = 0;
- if (SUCCEEDED(VersionFromString(s, &wVerMajor, &wVerMinor, &wVerBld, &wVerRev)))
- {
- IfFailRet(m_pAssemblyName->SetProperty(ASM_NAME_MAJOR_VERSION, &wVerMajor, sizeof(WORD)));
- IfFailRet(m_pAssemblyName->SetProperty(ASM_NAME_MINOR_VERSION, &wVerMinor, sizeof(WORD)));
- IfFailRet(m_pAssemblyName->SetProperty(ASM_NAME_BUILD_NUMBER, &wVerBld, sizeof(WORD)));
- IfFailRet(m_pAssemblyName->SetProperty(ASM_NAME_REVISION_NUMBER, &wVerRev, sizeof(WORD)));
- }
- else
- m_bCurrentEntryInvalid = TRUE;
-
- }
- break;
- case ASM_NAME_ARCHITECTURE:
- {
- StackSString s(pszString,dwStringSize);
- PEKIND PeKind = peNone;
- if(SUCCEEDED(MapProcessorArchitectureToPEKIND(s, &PeKind)))
- {
- IfFailRet(m_pAssemblyName->SetProperty(ASM_NAME_ARCHITECTURE, (LPBYTE) &PeKind, sizeof(PeKind)));
- }
- else
- {
- m_bCurrentEntryInvalid = TRUE;
- }
-
- }
- break;
- case ASM_NAME_PUBLIC_KEY_TOKEN:
- {
- if(EEXMLStringCompare(pszString, dwStringSize, CONST_STRING_AND_LEN(W("null"))) == 0)
- {
- IfFailRet(m_pAssemblyName->SetProperty(ASM_NAME_NULL_PUBLIC_KEY_TOKEN, NULL, 0));
- }
- else
- {
- if (dwStringSize % 2 != 0)
- return FUSION_E_INVALID_NAME;
-
- DWORD cbProp = dwStringSize / 2;
- NewHolder<BYTE> pbProp = new BYTE[cbProp];
- CParseUtils::UnicodeHexToBin(pszString, dwStringSize, pbProp); //????
- IfFailRet(m_pAssemblyName->SetProperty(ASM_NAME_PUBLIC_KEY_TOKEN, pbProp, cbProp));
- }
- break;
- }
-
- default:
- _ASSERTE(!"Invalid format");
- m_bCurrentEntryInvalid = TRUE;
- break;
- }
- break;
- }
-
- }
- }
- return S_OK;
-}
diff --git a/src/vm/assemblynamesconfigfactory.h b/src/vm/assemblynamesconfigfactory.h
deleted file mode 100644
index 234adb9208..0000000000
--- a/src/vm/assemblynamesconfigfactory.h
+++ /dev/null
@@ -1,72 +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.
-// AssemblyNamesConfigFactory.h
-//
-
-//
-//
-// Parses XML files and adding runtime entries to assembly list
-// Abstract, derived classes need to override AddAssemblyName
-
-
-#ifndef ASSEMBLYNAMESCONFIGFACTORY_H
-#define ASSEMBLYNAMESCONFIGFACTORY_H
-
-#include "unknwn.h"
-#include "../xmlparser/_reference.h"
-#include "../xmlparser/_unknown.h"
-
-
-class AssemblyNamesConfigFactory : public _unknown<IXMLNodeFactory, &IID_IXMLNodeFactory>
-{
-
-public:
- AssemblyNamesConfigFactory ();
- ~AssemblyNamesConfigFactory ();
- HRESULT STDMETHODCALLTYPE NotifyEvent(
- /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
- /* [in] */ XML_NODEFACTORY_EVENT iEvt);
-
- HRESULT STDMETHODCALLTYPE BeginChildren(
- /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
- /* [in] */ XML_NODE_INFO* __RPC_FAR pNodeInfo);
-
- HRESULT STDMETHODCALLTYPE EndChildren(
- /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
- /* [in] */ BOOL fEmptyNode,
- /* [in] */ XML_NODE_INFO* __RPC_FAR pNodeInfo);
-
- HRESULT STDMETHODCALLTYPE Error(
- /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
- /* [in] */ HRESULT hrErrorCode,
- /* [in] */ USHORT cNumRecs,
- /* [in] */ XML_NODE_INFO* __RPC_FAR * __RPC_FAR apNodeInfo)
- {
- LIMITED_METHOD_CONTRACT;
- /*
- UNUSED(pSource);
- UNUSED(hrErrorCode);
- UNUSED(cNumRecs);
- UNUSED(apNodeInfo);
- */
- return hrErrorCode;
- }
-
- HRESULT STDMETHODCALLTYPE CreateNode(
- /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
- /* [in] */ PVOID pNodeParent,
- /* [in] */ USHORT cNumRecs,
- /* [in] */ XML_NODE_INFO* __RPC_FAR * __RPC_FAR apNodeInfo);
-
- virtual void AddAssemblyName(IAssemblyName*) = 0;
-protected:
- IAssemblyName* m_pAssemblyName;
- BOOL m_bCurrentEntryInvalid;
- DWORD m_dwCurrentElementDepth;
- DWORD m_dwProperty;
-
-};
-
-
-#endif
diff --git a/src/vm/assemblynative.cpp b/src/vm/assemblynative.cpp
index 7175b156f0..8daa851c74 100644
--- a/src/vm/assemblynative.cpp
+++ b/src/vm/assemblynative.cpp
@@ -29,7 +29,6 @@
#include "frames.h"
#include "typeparse.h"
#ifdef FEATURE_REMOTING
-#include "appdomainhelper.h"
#endif
#include "stackprobe.h"
diff --git a/src/vm/ceeload.cpp b/src/vm/ceeload.cpp
index 4a03927ee4..00fa966640 100644
--- a/src/vm/ceeload.cpp
+++ b/src/vm/ceeload.cpp
@@ -183,10 +183,32 @@ ARRAY_PTR_COR_IL_MAP InstrumentedILOffsetMapping::GetOffsets() const
return m_rgMap;
}
-PTR_PersistentInlineTrackingMap Module::GetNgenInlineTrackingMap()
+BOOL Module::HasInlineTrackingMap()
{
LIMITED_METHOD_DAC_CONTRACT;
- return m_persistentInlineTrackingMap;
+#ifdef FEATURE_READYTORUN
+ if (IsReadyToRun() && GetReadyToRunInfo()->GetInlineTrackingMap() != NULL)
+ {
+ return TRUE;
+ }
+#endif
+ return (m_pPersistentInlineTrackingMapNGen != NULL);
+}
+
+COUNT_T Module::GetInliners(PTR_Module inlineeOwnerMod, mdMethodDef inlineeTkn, COUNT_T inlinersSize, MethodInModule inliners[], BOOL *incompleteData)
+{
+ WRAPPER_NO_CONTRACT;
+#ifdef FEATURE_READYTORUN
+ if(IsReadyToRun() && GetReadyToRunInfo()->GetInlineTrackingMap() != NULL)
+ {
+ return GetReadyToRunInfo()->GetInlineTrackingMap()->GetInliners(inlineeOwnerMod, inlineeTkn, inlinersSize, inliners, incompleteData);
+ }
+#endif
+ if(m_pPersistentInlineTrackingMapNGen != NULL)
+ {
+ return m_pPersistentInlineTrackingMapNGen->GetInliners(inlineeOwnerMod, inlineeTkn, inlinersSize, inliners, incompleteData);
+ }
+ return 0;
}
@@ -10064,8 +10086,8 @@ void Module::Save(DataImage *image)
InlineTrackingMap *inlineTrackingMap = image->GetInlineTrackingMap();
if (inlineTrackingMap)
{
- m_persistentInlineTrackingMap = new (image->GetHeap()) PersistentInlineTrackingMap(this);
- m_persistentInlineTrackingMap->Save(image, inlineTrackingMap);
+ m_pPersistentInlineTrackingMapNGen = new (image->GetHeap()) PersistentInlineTrackingMapNGen(this);
+ m_pPersistentInlineTrackingMapNGen->Save(image, inlineTrackingMap);
}
if (m_pNgenStats && g_CorCompileVerboseLevel >= CORCOMPILE_STATS)
@@ -11064,14 +11086,14 @@ void Module::Fixup(DataImage *image)
}
// Fix up inlining data
- if(m_persistentInlineTrackingMap)
+ if(m_pPersistentInlineTrackingMapNGen)
{
- image->FixupPointerField(this, offsetof(Module, m_persistentInlineTrackingMap));
- m_persistentInlineTrackingMap->Fixup(image);
+ image->FixupPointerField(this, offsetof(Module, m_pPersistentInlineTrackingMapNGen));
+ m_pPersistentInlineTrackingMapNGen->Fixup(image);
}
else
{
- image->ZeroPointerField(this, offsetof(Module, m_persistentInlineTrackingMap));
+ image->ZeroPointerField(this, offsetof(Module, m_pPersistentInlineTrackingMapNGen));
}
SetIsModuleSaved();
@@ -15368,9 +15390,6 @@ void Module::VerifyAllMethods()
};
//Verify all methods in a module eagerly, forcing them to get loaded.
- /* XXX Thu 4/26/2007
- * This code is lifted mostly from Validator.cpp
- */
IMDInternalImport * pMDI = GetMDImport();
HENUMTypeDefInternalHolder hEnum(pMDI);
mdTypeDef td;
diff --git a/src/vm/ceeload.h b/src/vm/ceeload.h
index 42023b3ec1..de92900b2e 100644
--- a/src/vm/ceeload.h
+++ b/src/vm/ceeload.h
@@ -81,7 +81,8 @@ class TypeHandleList;
class ProfileEmitter;
class ReJitManager;
class TrackingMap;
-class PersistentInlineTrackingMap;
+struct MethodInModule;
+class PersistentInlineTrackingMapNGen;
// Hash table parameter of available classes (name -> module/class) hash
#define AVAILABLE_CLASSES_HASH_BUCKETS 1024
@@ -104,7 +105,7 @@ class PersistentInlineTrackingMap;
#define NATIVE_SYMBOL_READER_DLL W("diasymreader.dll")
#endif
-typedef DPTR(PersistentInlineTrackingMap) PTR_PersistentInlineTrackingMap;
+typedef DPTR(PersistentInlineTrackingMapNGen) PTR_PersistentInlineTrackingMapNGen;
extern VerboseLevel g_CorCompileVerboseLevel;
#endif // FEATURE_PREJIT
@@ -2667,7 +2668,8 @@ public:
void NotifyProfilerLoadFinished(HRESULT hr);
#endif // PROFILING_SUPPORTED
- PTR_PersistentInlineTrackingMap GetNgenInlineTrackingMap();
+ BOOL HasInlineTrackingMap();
+ COUNT_T GetInliners(PTR_Module inlineeOwnerMod, mdMethodDef inlineeTkn, COUNT_T inlinersSize, MethodInModule inliners[], BOOL *incompleteData);
public:
void NotifyEtwLoadFinished(HRESULT hr);
@@ -3436,7 +3438,7 @@ private:
DebuggerSpecificData m_debuggerSpecificData;
// This is a compressed read only copy of m_inlineTrackingMap, which is being saved to NGEN image.
- PTR_PersistentInlineTrackingMap m_persistentInlineTrackingMap;
+ PTR_PersistentInlineTrackingMapNGen m_pPersistentInlineTrackingMapNGen;
LPCSTR *m_AssemblyRefByNameTable; // array that maps mdAssemblyRef tokens into their simple name
diff --git a/src/vm/clrprivbinderfusion.cpp b/src/vm/clrprivbinderfusion.cpp
deleted file mode 100644
index d31774f7b2..0000000000
--- a/src/vm/clrprivbinderfusion.cpp
+++ /dev/null
@@ -1,819 +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.
-
-
-
-#include "common.h" // precompiled header
-
-#ifndef DACCESS_COMPILE
-
-//=====================================================================================================================
-#include "assemblyspec.hpp"
-#include "corhdr.h"
-#include "domainfile.h"
-#include "fusion.h"
-#include "policy.h"
-#include "sstring.h"
-#include "stackingallocator.h"
-#include "threads.h"
-#include "clrprivbinderfusion.h"
-#include "clrprivbinderutil.h"
-#include "fusionlogging.h"
-
-using namespace CLRPrivBinderUtil;
-
-//=================================================================================================
-#define STDMETHOD_NOTIMPL(...) \
- STDMETHOD(__VA_ARGS__) \
- { \
- WRAPPER_NO_CONTRACT; \
- _ASSERTE_MSG(false, "Method not implemented."); \
- return E_NOTIMPL; \
- }
-
-//=================================================================================================
-static HRESULT PropagateOutStringArgument(
- __in LPCSTR pszValue,
- __out_ecount_opt(*pcchArg) LPWSTR pwzArg,
- __in DWORD cchArg,
- __out DWORD * pcchArg)
-{
- LIMITED_METHOD_CONTRACT;
-
- VALIDATE_PTR_RET(pszValue);
- VALIDATE_CONDITION((pwzArg == nullptr || cchArg > 0), return E_INVALIDARG);
-
- HRESULT hr = S_OK;
-
- if (pwzArg != nullptr)
- {
- DWORD cchWritten = WszMultiByteToWideChar(
- CP_UTF8, 0 /*flags*/, pszValue, -1, pwzArg, cchArg);
-
- if (cchWritten == 0)
- {
- hr = HRESULT_FROM_GetLastError();
- }
- else if (pcchArg != nullptr)
- {
- *pcchArg = cchWritten;
- }
- }
-
- if (pcchArg != nullptr && (pwzArg == nullptr || hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)))
- {
- *pcchArg = WszMultiByteToWideChar(
- CP_UTF8, 0 /*flags*/, pszValue, -1, nullptr, 0);
-
- if (*pcchArg == 0)
- {
- hr = HRESULT_FROM_GetLastError();
- }
- }
-
- return hr;
-}
-
-//=================================================================================================
-// This is needed to allow calls to IsAnyFrameworkAssembly in GC_NOTRIGGER/NO_FAULT regions (i.e.,
-// GC stack walking). CAssemblyName (which implements IAssemblyName in most other uses) allocates
-// during construction and so cannot be used in this scenario.
-
-class AssemblySpecAsIAssemblyName
- : public IAssemblyName
-{
-public:
- AssemblySpecAsIAssemblyName(
- AssemblySpec * pSpec)
- : m_pSpec(pSpec)
- { LIMITED_METHOD_CONTRACT; }
-
- //=============================================================================================
- // IUnknown methods
-
- // Not used by IsAnyFrameworkAssembly
- STDMETHOD_(ULONG, AddRef())
- {
- WRAPPER_NO_CONTRACT;
- _ASSERTE_MSG(false, "Method not implemented.");
- return E_NOTIMPL;
- }
-
- // Not used by IsAnyFrameworkAssembly
- STDMETHOD_(ULONG, Release())
- {
- WRAPPER_NO_CONTRACT;
- _ASSERTE_MSG(false, "Method not implemented.");
- return E_NOTIMPL;
- }
-
- // Not used by IsAnyFrameworkAssembly
- STDMETHOD_NOTIMPL(QueryInterface(
- REFIID riid,
- void **ppvObject));
-
- //=============================================================================================
- // IAssemblyName methods
-
- STDMETHOD_NOTIMPL(SetProperty(
- DWORD PropertyId,
- void const * pvProperty,
- DWORD cbProperty));
-
-#define ASSURE_SUFFICIENT_BUFFER(SRCSIZE) \
- do { \
- if ((pvProperty == nullptr) || (*pcbProperty < SRCSIZE)) { \
- *pcbProperty = SRCSIZE; \
- return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); \
- } \
- } while (false)
-
- STDMETHOD(GetProperty)(
- DWORD PropertyId,
- LPVOID pvProperty,
- LPDWORD pcbProperty)
- {
- LIMITED_METHOD_CONTRACT;
-
- VALIDATE_PTR_RET(pcbProperty);
- VALIDATE_CONDITION((pvProperty == nullptr) == (*pcbProperty == 0), return E_INVALIDARG);
-
- HRESULT hr = S_OK;
-
- switch (PropertyId)
- {
- case ASM_NAME_NAME:
- return PropagateOutStringArgument(m_pSpec->GetName(), (LPWSTR) pvProperty,
- *pcbProperty / sizeof(WCHAR), pcbProperty);
-
- case ASM_NAME_MAJOR_VERSION:
- ASSURE_SUFFICIENT_BUFFER(sizeof(USHORT));
- *reinterpret_cast<USHORT*>(pvProperty) = m_pSpec->GetContext()->usMajorVersion;
- *pcbProperty = sizeof(USHORT);
- return S_OK;
-
- case ASM_NAME_MINOR_VERSION:
- ASSURE_SUFFICIENT_BUFFER(sizeof(USHORT));
- *reinterpret_cast<USHORT*>(pvProperty) = m_pSpec->GetContext()->usMinorVersion;
- *pcbProperty = sizeof(USHORT);
- return S_OK;
-
- case ASM_NAME_BUILD_NUMBER:
- ASSURE_SUFFICIENT_BUFFER(sizeof(USHORT));
- *reinterpret_cast<USHORT*>(pvProperty) = m_pSpec->GetContext()->usBuildNumber;
- *pcbProperty = sizeof(USHORT);
- return S_OK;
-
- case ASM_NAME_REVISION_NUMBER:
- ASSURE_SUFFICIENT_BUFFER(sizeof(USHORT));
- *reinterpret_cast<USHORT*>(pvProperty) = m_pSpec->GetContext()->usRevisionNumber;
- *pcbProperty = sizeof(USHORT);
- return S_OK;
-
- case ASM_NAME_CULTURE:
- if (m_pSpec->GetContext()->szLocale == nullptr)
- {
- return FUSION_E_INVALID_NAME;
- }
- return PropagateOutStringArgument(m_pSpec->GetContext()->szLocale, (LPWSTR) pvProperty,
- *pcbProperty / sizeof(WCHAR), pcbProperty);
-
- case ASM_NAME_PUBLIC_KEY_TOKEN:
- {
- if (!m_pSpec->HasPublicKeyToken())
- {
- return FUSION_E_INVALID_NAME;
- }
-
- PBYTE pbSN;
- DWORD cbSN;
- m_pSpec->GetPublicKeyToken(&pbSN, &cbSN);
- ASSURE_SUFFICIENT_BUFFER(cbSN);
- memcpy_s(pvProperty, *pcbProperty, pbSN, cbSN);
- *pcbProperty = cbSN;
- }
- return S_OK;
-
- case ASM_NAME_RETARGET:
- ASSURE_SUFFICIENT_BUFFER(sizeof(BOOL));
- *reinterpret_cast<BOOL*>(pvProperty) = m_pSpec->IsRetargetable();
- *pcbProperty = sizeof(BOOL);
- return S_OK;
-
- default:
- _ASSERTE_MSG(false, "Unexpected property requested.");
- return E_INVALIDARG;
- }
- }
-
-#undef ASSURE_SUFFICIENT_BUFFER
-
- // Not used by IsAnyFrameworkAssembly
- STDMETHOD_NOTIMPL(Finalize());
-
- // Not used by IsAnyFrameworkAssembly
- STDMETHOD_NOTIMPL(GetDisplayName(
- __out_ecount_opt(*pccDisplayName) LPOLESTR szDisplayName,
- __inout LPDWORD pccDisplayName,
- DWORD dwDisplayFlags));
-
- // Not used by IsAnyFrameworkAssembly
- STDMETHOD_NOTIMPL(Reserved(
- REFIID refIID,
- IUnknown *pUnkReserved1,
- IUnknown *pUnkReserved2,
- LPCOLESTR szReserved,
- LONGLONG llReserved,
- LPVOID pvReserved,
- DWORD cbReserved,
- LPVOID *ppReserved));
-
-
- STDMETHOD(GetName)(
- __inout LPDWORD lpcwBuffer,
- __out_ecount_opt(*lpcwBuffer) WCHAR *pwzName)
- {
- LIMITED_METHOD_CONTRACT;
-
- VALIDATE_PTR_RET(lpcwBuffer);
- return PropagateOutStringArgument(
- m_pSpec->GetName(), pwzName, *lpcwBuffer, lpcwBuffer);
- }
-
- STDMETHOD(GetVersion)(
- LPDWORD pdwVersionHi,
- LPDWORD pdwVersionLow)
- {
- LIMITED_METHOD_CONTRACT;
-
- HRESULT hr = S_OK;
-
- VALIDATE_PTR_RET(pdwVersionHi);
- VALIDATE_PTR_RET(pdwVersionLow);
-
- AssemblyMetaDataInternal * pAMDI = m_pSpec->GetContext();
-
- *pdwVersionHi = MAKELONG(pAMDI->usMinorVersion, pAMDI->usMajorVersion);
- *pdwVersionLow = MAKELONG(pAMDI->usRevisionNumber, pAMDI->usBuildNumber);
-
- return S_OK;
- }
-
-
- // Exists exclusively to support fusion's IsSystem helper, which compares against 'mscorlib'.
- STDMETHOD(IsEqual)(
- IAssemblyName *pName,
- DWORD dwCmpFlags)
- {
- LIMITED_METHOD_CONTRACT;
-
- HRESULT hr = S_OK;
-
- VALIDATE_PTR_RET(pName);
-
- // This function is here just to support checks against the name 'mscorlib'.
- if ((dwCmpFlags & ASM_CMPF_NAME) != ASM_CMPF_NAME)
- {
- return E_NOTIMPL;
- }
-
- DWORD cchName1 = 0;
- WCHAR wzName1[_MAX_PATH];
- IfFailRet(pName->GetName(&cchName1, wzName1));
- _ASSERTE(SString::_wcsicmp(wzName1, W("mscorlib")) == 0);
-
- WCHAR wzName2[_MAX_PATH];
- DWORD cchName2 = WszMultiByteToWideChar(
- CP_UTF8, 0 /*flags*/, m_pSpec->GetName(), -1, wzName2, (int) (sizeof(wzName2) / sizeof(wzName2[0])));
-
- if (0 == cchName2)
- {
- _ASSERTE(HRESULT_FROM_GetLastError() != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER));
- return HRESULT_FROM_GetLastError();
- }
-
- if (cchName1 != cchName2)
- {
- return S_FALSE;
- }
-
- return SString::_wcsnicmp(wzName1, wzName2, cchName1) == 0
- ? S_OK
- : S_FALSE;
- }
-
- STDMETHOD_NOTIMPL(Clone(
- IAssemblyName **pName));
-
-private:
- AssemblySpec * m_pSpec;
-};
-
-//=====================================================================================================================
-HRESULT CLRPrivBinderFusion::FindFusionAssemblyBySpec(
- LPVOID pvAppDomain,
- LPVOID pvAssemblySpec,
- BindingScope kBindingScope,
- HRESULT * pResult,
- ICLRPrivAssembly ** ppAssembly)
-{
- LIMITED_METHOD_CONTRACT;;
- HRESULT hr = S_OK;
-
- AppDomain* pAppDomain = reinterpret_cast<AppDomain*>(pvAppDomain);
- AssemblySpec* pAssemblySpec = reinterpret_cast<AssemblySpec*>(pvAssemblySpec);
- VALIDATE_PTR_RET(pAppDomain);
- VALIDATE_PTR_RET(pAssemblySpec);
- VALIDATE_PTR_RET(pResult);
- VALIDATE_PTR_RET(ppAssembly);
-
- if (pAssemblySpec->IsContentType_WindowsRuntime())
- {
- return CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT;
- }
-
- BOOL fIsSupportedInAppX;
- {
- AssemblySpecAsIAssemblyName asName(pAssemblySpec);
-
- if (Fusion::Util::IsAnyFrameworkAssembly(&asName, &fIsSupportedInAppX) != S_OK)
- { // Not a framework assembly identity.
- IfFailRet(CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT);
- }
- }
-
- if (kBindingScope == kBindingScope_FrameworkSubset)
- { // We should allow only some framework assemblies to load
-
- // DevMode has to allow all FX assemblies, not just a subset - see code:PreBind for more info
- {
- // Disabling for now, as it causes too many violations.
- //CONTRACT_VIOLATION(GCViolation | FaultViolation | ModeViolation);
- //_ASSERTE(!AppX::IsAppXDesignMode());
- }
-
- if (!fIsSupportedInAppX)
- { // Assembly is blocked for AppX, fail the load
- *pResult = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
- *ppAssembly = nullptr;
- return S_OK;
- }
- }
-
- return FindAssemblyBySpec(pvAppDomain, pvAssemblySpec, pResult, ppAssembly);
-}
-
-//=====================================================================================================================
-static
-PEAssembly * FindCachedFile(AppDomain * pDomain, AssemblySpec * pSpec)
-{
- // Look for cached bind result. Prefer a cached DomainAssembly, as it takes priority over a
- // cached PEAssembly (which can be different from the one associated with the DomainAssembly).
- DomainAssembly * pDomainAssembly = pDomain->FindCachedAssembly(pSpec, FALSE);
- return (pDomainAssembly != nullptr)
- ? (pDomainAssembly->GetFile())
- : (pDomain->FindCachedFile(pSpec, FALSE));
-}
-
-//=====================================================================================================================
-// There is no need to create a separate binding record, since we can always just look in the AppDomain's
-// AssemblySpecBindingCache for an answer (which is precisely what this function does).
-
-HRESULT CLRPrivBinderFusion::FindAssemblyBySpec(
- LPVOID pvAppDomain,
- LPVOID pvAssemblySpec,
- HRESULT * pResult,
- ICLRPrivAssembly ** ppAssembly)
-{
- LIMITED_METHOD_CONTRACT;;
- HRESULT hr = S_OK;
-
- AppDomain* pAppDomain = reinterpret_cast<AppDomain*>(pvAppDomain);
- AssemblySpec* pAssemblySpec = reinterpret_cast<AssemblySpec*>(pvAssemblySpec);
- VALIDATE_PTR_RET(pAppDomain);
- VALIDATE_PTR_RET(pAssemblySpec);
- VALIDATE_PTR_RET(pResult);
- VALIDATE_PTR_RET(ppAssembly);
-
- // For the Architecture property, canonicalize peMSIL to peNone (which are considered equivalent),
- // to ensure consistent lookups in the AssemblySpecBindingCache for the CLRPrivBinderFusion binder.
- if (pAssemblySpec->GetPEKIND() == peMSIL)
- {
- pAssemblySpec->SetPEKIND(peNone);
- }
-
- PEAssembly * pPEAssembly = FindCachedFile(pAppDomain, pAssemblySpec);
- if (pPEAssembly == nullptr)
- {
- return E_FAIL;
- }
-
- // Could be racing with another thread that has just added the PEAssembly to the binding cache
- // but not yet allocated and assigned a host assembly.
- if (!pPEAssembly->HasHostAssembly())
- {
- return E_FAIL;
- }
-
- *pResult = S_OK;
- *ppAssembly = clr::SafeAddRef(pPEAssembly->GetHostAssembly());
-
- return S_OK;
-}
-
-//=====================================================================================================================
-HRESULT CLRPrivBinderFusion::BindAssemblyByNameWorker(
- IAssemblyName * pAssemblyName,
- ICLRPrivAssembly ** ppAssembly)
-{
- STANDARD_VM_CONTRACT;
- PRECONDITION(CheckPointer(pAssemblyName));
- PRECONDITION(CheckPointer(ppAssembly));
-
- HRESULT hr = S_OK;
-
- AppDomain * pCurDomain = AppDomain::GetCurrentDomain();
- if (pCurDomain == nullptr)
- ThrowHR(E_UNEXPECTED);
-
- AssemblySpec prePolicySpec;
- AssemblySpec postPolicySpec;
-
- prePolicySpec.InitializeSpec(pAssemblyName);
-
- // For the Architecture property, canonicalize peMSIL to peNone (which are considered equivalent),
- // to ensure consistent lookups in the AssemblySpecBindingCache for the CLRPrivBinderFusion binder.
- if (prePolicySpec.GetPEKIND() == peMSIL)
- {
- prePolicySpec.SetPEKIND(peNone);
- }
-
- AssemblySpec * pBindSpec = &prePolicySpec;
- PEAssemblyHolder pPEAssembly = clr::SafeAddRef(FindCachedFile(pCurDomain, pBindSpec));
-
- if (pPEAssembly == nullptr)
- {
- // Early on in domain setup there may not be a fusion context, so skip ApplyPolicy then.
- _ASSERTE(pCurDomain->GetFusionContext() != nullptr || prePolicySpec.IsMscorlib());
- if (pCurDomain->GetFusionContext() != nullptr)
- {
- ReleaseHolder<IAssemblyName> pPolicyAssemblyName;
- DWORD dwPolicyApplied = 0;
- ApplyPolicy(pAssemblyName, pCurDomain->GetFusionContext(), nullptr, &pPolicyAssemblyName, nullptr, nullptr, &dwPolicyApplied);
-
- if (dwPolicyApplied != 0)
- {
- postPolicySpec.InitializeSpec(pPolicyAssemblyName);
- pBindSpec = &postPolicySpec;
- pPEAssembly = clr::SafeAddRef(FindCachedFile(pCurDomain, pBindSpec));
- }
- }
-
- if (pPEAssembly == nullptr)
- {
- // Trigger a load.
- pPEAssembly = pCurDomain->BindAssemblySpec(
- pBindSpec, // AssemblySpec
- TRUE, // ThrowOnFileNotFound
- FALSE, // RaisePrebindEvents
- nullptr, // CallerStackMark
- nullptr, // AssemblyLoadSecurity
- FALSE); // fUseHostBinderIfAvailable - to avoid infinite recursion
- _ASSERTE(FindCachedFile(pCurDomain, pBindSpec) == pPEAssembly || pBindSpec->IsMscorlib());
- }
-
- // If a post-policy spec was used, add the pre-policy spec to the binding cache
- // so that it can be found by FindAssemblyBySpec.
- if (&prePolicySpec != pBindSpec)
- {
- // Failure to add simply means someone else beat us to it. In that case
- // the FindCachedFile call below (after catch block) will update result
- // to the cached value.
- INDEBUG(BOOL fRes =) pCurDomain->AddFileToCache(&prePolicySpec, pPEAssembly, TRUE /* fAllowFailure */);
- _ASSERTE(!fRes || prePolicySpec.IsMscorlib() || FindCachedFile(pCurDomain, &prePolicySpec) == pPEAssembly);
- }
-
- // Ensure that the assembly is discoverable through a consistent assembly name (the assembly def name of the assembly)
- AssemblySpec specAssemblyDef;
- specAssemblyDef.InitializeSpec(pPEAssembly);
-
- // It is expected that all assemlbies found here will be unified assemblies, and therefore have a public key.
- _ASSERTE(specAssemblyDef.IsStrongNamed());
-
- // Convert public key into the format that matches the garaunteed cache in the AssemblySpecBindingCache ... see the extended logic
- // in Module::GetAssemblyIfLoaded.
- if (specAssemblyDef.IsStrongNamed() && specAssemblyDef.HasPublicKey())
- {
- specAssemblyDef.ConvertPublicKeyToToken();
- }
- pCurDomain->AddFileToCache(&specAssemblyDef, pPEAssembly, TRUE);
- }
-
- if (!pPEAssembly->HasHostAssembly())
- {
- // This can happen if we just loaded the PEAssembly with BindAssemblySpec above, or if the PEAssembly
- // Was not loaded through this binder. (NGEN Case)
-
- // Note: There can be multiple PEAssembly objects for the same file, however we have to create unique
- // CLRPrivAssemblyFusion object, otherwise code:AppDomain::FindAssembly will not recognize the duplicates which
- // will lead to creation of multiple code:DomainAssembly objects for the same file in the same AppDomain.
-
- InlineSString<128> ssPEAssemblyName;
- FusionBind::GetAssemblyNameDisplayName(pPEAssembly->GetFusionAssemblyName(), ssPEAssemblyName, ASM_DISPLAYF_FULL);
- NewHolder<CLRPrivAssemblyFusion> pAssemblyObj = new CLRPrivAssemblyFusion(ssPEAssemblyName.GetUnicode(), this);
-
- {
- CrstHolder lock(&m_SetHostAssemblyLock);
- if (!pPEAssembly->HasHostAssembly())
- {
- // Add the host assembly to the PEAssembly.
- pPEAssembly->SetHostAssembly(pAssemblyObj.Extract());
- }
- }
- }
-
- // Trigger a load so that a DomainAssembly is associated with the ICLRPrivAssembly created above.
- pPEAssembly = clr::SafeAddRef(pCurDomain->LoadDomainAssembly(pBindSpec, pPEAssembly, FILE_LOADED)->GetFile());
-
- _ASSERTE(pPEAssembly != nullptr);
- _ASSERTE(pPEAssembly->HasHostAssembly());
- _ASSERTE(pCurDomain->FindAssembly(pPEAssembly->GetHostAssembly()) != nullptr);
-
- fusion::logging::LogMessage(0, ID_FUSLOG_BINDING_STATUS_FOUND, pPEAssembly->GetPath().GetUnicode());
-
- *ppAssembly = clr::SafeAddRef(pPEAssembly->GetHostAssembly());
-
- return hr;
-}
-
-//=====================================================================================================================
-void CLRPrivBinderFusion::BindMscorlib(
- PEAssembly * pPEAssembly)
-{
- STANDARD_VM_CONTRACT;
-
-#ifdef _DEBUG
- NewArrayHolder<WCHAR> dbg_wszAssemblySimpleName;
- _ASSERTE(SUCCEEDED(fusion::util::GetProperty(pPEAssembly->GetFusionAssemblyName(), ASM_NAME_NAME, &dbg_wszAssemblySimpleName)));
-
- _ASSERTE(wcscmp(dbg_wszAssemblySimpleName, W("mscorlib")) == 0);
-#endif //_DEBUG
-
- NewHolder<CLRPrivAssemblyFusion> pPrivAssembly = new CLRPrivAssemblyFusion(W("mscorlib"), this);
-
- pPEAssembly->SetHostAssembly(pPrivAssembly.Extract());
-}
-
-//=====================================================================================================================
-HRESULT CLRPrivBinderFusion::BindFusionAssemblyByName(
- IAssemblyName * pAssemblyName,
- BindingScope kBindingScope,
- ICLRPrivAssembly ** ppAssembly)
-{
- STANDARD_VM_CONTRACT;
- HRESULT hr = S_OK;
-
- fusion::logging::StatusScope logStatus(0, ID_FUSLOG_BINDING_STATUS_FRAMEWORK, &hr);
-
- DWORD dwContentType = AssemblyContentType_Default;
- IfFailRet(fusion::util::GetProperty(pAssemblyName, ASM_NAME_CONTENT_TYPE, &dwContentType));
- if ((hr == S_OK) && (dwContentType != AssemblyContentType_Default))
- { // Not a NetFX content type.
- IfFailRet(CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT);
- }
-
- BOOL fIsSupportedInAppX;
- if (Fusion::Util::IsAnyFrameworkAssembly(pAssemblyName, &fIsSupportedInAppX) != S_OK)
- { // Not a framework assembly identity.
- IfFailRet(CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT);
- }
- if (kBindingScope == kBindingScope_FrameworkSubset)
- { // We should allow only some framework assemblies to load
-
- // DevMode has to allow all FX assemblies, not just a subset - see code:PreBind for more info
- _ASSERTE(!AppX::IsAppXDesignMode());
-
- if (!fIsSupportedInAppX)
- { // Assembly is blocked for AppX, fail the load
- fusion::logging::LogMessage(0, ID_FUSLOG_BINDING_STATUS_FX_ASSEMBLY_BLOCKED);
-
- IfFailRet(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
- }
- }
-
- return (hr = BindAssemblyByNameWorker(pAssemblyName, ppAssembly));
-}
-
-//=====================================================================================================================
-// Implements code:ICLRPrivBinder::BindAssemblyByName
-HRESULT CLRPrivBinderFusion::BindAssemblyByName(
- IAssemblyName * pAssemblyName,
- ICLRPrivAssembly ** ppAssembly)
-{
- WRAPPER_NO_CONTRACT;
- return BindAssemblyByNameWorker(
- pAssemblyName,
- ppAssembly);
-}
-
-//=====================================================================================================================
-// Implements code:ICLRPrivBinder::GetBinderID
-HRESULT CLRPrivBinderFusion::GetBinderID(
- UINT_PTR *pBinderId)
-{
- LIMITED_METHOD_CONTRACT;
-
- *pBinderId = (UINT_PTR)this;
- return S_OK;
-}
-
-//=====================================================================================================================
-// Implements code:IBindContext::PreBind
-HRESULT CLRPrivBinderFusion::PreBind(
- IAssemblyName * pIAssemblyName,
- DWORD dwPreBindFlags,
- IBindResult ** ppIBindResult)
-{
- STANDARD_BIND_CONTRACT;
- PRECONDITION(CheckPointer(pIAssemblyName));
- PRECONDITION(CheckPointer(ppIBindResult));
-
- HRESULT hr = S_OK;
-
- BOOL fIsSupportedInAppX;
- if (Fusion::Util::IsAnyFrameworkAssembly(pIAssemblyName, &fIsSupportedInAppX) != S_OK)
- { // Not a framework assembly identity.
- return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
- }
-
- EX_TRY
- {
- // Create new IL binding scope.
- fusion::logging::BindingScope defaultScope(pIAssemblyName, FUSION_BIND_LOG_CATEGORY_DEFAULT);
-
- // Ideally the caller would give us arg kBindingContext like in code:BindFusionAssemblyByName, so we can give the same answer.
- // That is not easy, so we will make the decision here:
- // - DevMode will allow all FX assemblies (that covers designer binding context scenario for designers that need to
- // load WPF with ngen images for perf reasons).
- // We know that the real bind via code:BindFusionAssemblyByName will succeed for the assemblies (because we are in DevMode).
- // - Normal mode (non-DevMode) we will allow only subset of FX assemblies.
- // It implies that designer binding context (used by debuggers) will not use ngen images for blocked FX assemblies
- // (transitively). That is acceptable performance trade-off.
- if (!AppX::IsAppXDesignMode())
- { // We should allow only some framework assemblies to load
- if (!fIsSupportedInAppX)
- { // Assembly is blocked for AppX, fail the load
- fusion::logging::LogMessage(0, ID_FUSLOG_BINDING_STATUS_FX_ASSEMBLY_BLOCKED);
-
- hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
- }
- }
-
- if (SUCCEEDED(hr))
- {
- AppDomain * pDomain = AppDomain::GetCurrentDomain();
- ReleaseHolder<IBindContext> pIBindContext;
- if (SUCCEEDED(hr = GetBindContextFromApplicationContext(pDomain->CreateFusionContext(), &pIBindContext)))
- {
- hr = pIBindContext->PreBind(pIAssemblyName, dwPreBindFlags, ppIBindResult);
- }
- }
- }
- EX_CATCH_HRESULT(hr);
-
- return hr;
-}
-
-//=====================================================================================================================
-HRESULT CLRPrivBinderFusion::PreBindFusionAssemblyByName(
- IAssemblyName *pIAssemblyName,
- DWORD dwPreBindFlags,
- IBindResult **ppIBindResult)
-{
- STANDARD_VM_CONTRACT;
- HRESULT hr = S_OK;
-
- DWORD dwContentType = AssemblyContentType_Default;
- IfFailRet(fusion::util::GetProperty(pIAssemblyName, ASM_NAME_CONTENT_TYPE, &dwContentType));
- if ((hr == S_OK) && (dwContentType != AssemblyContentType_Default))
- { // Not a NetFX content type.
- IfFailRet(CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT);
- }
-
- IfFailRet(PreBind(pIAssemblyName, dwPreBindFlags, ppIBindResult));
- _ASSERTE(*ppIBindResult != nullptr);
-
- if (*ppIBindResult == nullptr)
- IfFailRet(E_UNEXPECTED);
-
- return S_OK;
-}
-
-//=====================================================================================================================
-// Implements code:IBindContext::IsDefaultContext
-HRESULT CLRPrivBinderFusion::IsDefaultContext()
-{
- STANDARD_BIND_CONTRACT;
- return S_OK;
-}
-
-//=====================================================================================================================
-CLRPrivBinderFusion::~CLRPrivBinderFusion()
-{
- WRAPPER_NO_CONTRACT;
-}
-
-//=====================================================================================================================
-CLRPrivAssemblyFusion::CLRPrivAssemblyFusion(
- LPCWSTR wszName,
- CLRPrivBinderFusion * pBinder)
- : m_pBinder(clr::SafeAddRef(pBinder)),
- m_wszName(DuplicateStringThrowing(wszName))
-{
- STANDARD_VM_CONTRACT;
-}
-
-//=====================================================================================================================
-LPCWSTR CLRPrivAssemblyFusion::GetName() const
-{
- LIMITED_METHOD_CONTRACT;
-
- return m_wszName;
-}
-
-//=====================================================================================================================
-// Implements code:IUnknown::Release
-ULONG CLRPrivAssemblyFusion::Release()
-{
- LIMITED_METHOD_CONTRACT;
- STATIC_CONTRACT_CAN_TAKE_LOCK;
- _ASSERTE(m_cRef > 0);
-
- ULONG cRef = InterlockedDecrement(&m_cRef);
-
- if (cRef == 0)
- {
- delete this;
- }
-
- return cRef;
-}
-
-//=====================================================================================================================
-// Implements code:ICLRPrivBinder::BindAssemblyByName
-HRESULT CLRPrivAssemblyFusion::BindAssemblyByName(
- IAssemblyName * pAssemblyName,
- ICLRPrivAssembly ** ppAssembly)
-{
- WRAPPER_NO_CONTRACT;
- return m_pBinder->BindAssemblyByName(
- pAssemblyName,
- ppAssembly);
-}
-
-//=====================================================================================================================
-// Implements code:ICLRPrivBinder::GetBinderID
-HRESULT CLRPrivAssemblyFusion::GetBinderID(
- UINT_PTR *pBinderId)
-{
- LIMITED_METHOD_CONTRACT;
-
- *pBinderId = reinterpret_cast<UINT_PTR>(m_pBinder.GetValue());
- return S_OK;
-}
-
-//=====================================================================================================================
-// Implements code:ICLRPrivAssembly::IsShareable
-HRESULT CLRPrivAssemblyFusion::IsShareable(
- BOOL * pbIsShareable)
-{
- LIMITED_METHOD_CONTRACT;
- *pbIsShareable = TRUE; // These things are only used in the AppX scenario, where all fusion assemblies are unified, shareable assemblies.
- return S_OK;
-}
-
-//=====================================================================================================================
-// Implements code:ICLRPrivAssembly::GetAvailableImageTypes
-HRESULT CLRPrivAssemblyFusion::GetAvailableImageTypes(
- LPDWORD pdwImageTypes)
-{
- LIMITED_METHOD_CONTRACT;
- _ASSERTE(!"CLRPrivAssemblyFusion::GetAvailableImageTypes");
- return E_NOTIMPL;
-}
-
-//=====================================================================================================================
-// Implements code:ICLRPrivAssembly::GetImageResource
-HRESULT CLRPrivAssemblyFusion::GetImageResource(
- DWORD dwImageType,
- DWORD *pdwImageType,
- ICLRPrivResource ** ppIResource)
-{
- LIMITED_METHOD_CONTRACT;
- _ASSERTE(!"CLRPrivAssemblyFusion::GetImageResource");
- return E_NOTIMPL;
-}
-
-#endif // !DACCESS_COMPILE
-
diff --git a/src/vm/clrprivbinderfusion.h b/src/vm/clrprivbinderfusion.h
deleted file mode 100644
index 3cf3694e4f..0000000000
--- a/src/vm/clrprivbinderfusion.h
+++ /dev/null
@@ -1,228 +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.
-
-
-
-#pragma once
-
-#include "holder.h"
-#include "internalunknownimpl.h"
-#include "shash.h"
-#include "clrprivbinding.h"
-#include "clrprivruntimebinders.h"
-
-//=====================================================================================================================
-// Forward declarations
-class CLRPrivBinderFusion;
-class CLRPrivAssemblyFusion;
-
-class PEAssembly;
-class DomainAssembly;
-struct IMDInternalImport;
-
-//=====================================================================================================================
-class CLRPrivBinderFusion :
- public IUnknownCommon<ICLRPrivBinder, IBindContext>
-{
- friend class CLRPrivAssemblyFusion;
-
-public:
- // Scope for the bind operation
- enum BindingScope
- {
- // Binds only to subset of framework that is not on the black list (non-FX assemblies bindings are rejected)
- kBindingScope_FrameworkSubset,
- // Binds to all framework assemblies (incl. those on the black list) (non-FX assemblies bindings are rejected)
- // Used by designer binding context and in DevMode
- kBindingScope_FrameworkAll
- };
-
-public:
- //=============================================================================================
- // ICLRPrivBinder methods
-
- //---------------------------------------------------------------------------------------------
- // Implements code:ICLRPrivBinder::BindAssemblyByName
- STDMETHOD(BindAssemblyByName(
- IAssemblyName * pAssemblyName,
- ICLRPrivAssembly ** ppAssembly));
-
- //---------------------------------------------------------------------------------------------
- // Implements code:ICLRPrivBinder::VerifyBind
- STDMETHOD(VerifyBind)(
- IAssemblyName *pAssemblyName,
- ICLRPrivAssembly *pAssembly,
- ICLRPrivAssemblyInfo *pAssemblyInfo)
- {
- LIMITED_METHOD_CONTRACT;
- if (pAssemblyName == nullptr || pAssembly == nullptr || pAssemblyInfo == nullptr)
- return E_INVALIDARG;
- return S_OK;
- }
-
- //---------------------------------------------------------------------------------------------
- // Implements code:ICLRPrivBinder::GetBinderFlags
- STDMETHOD(GetBinderFlags)(
- DWORD *pBinderFlags)
- {
- LIMITED_METHOD_CONTRACT;
- *pBinderFlags = BINDER_FINDASSEMBLYBYSPEC_REQUIRES_EXACT_MATCH;
- return S_OK;
- }
-
- //---------------------------------------------------------------------------------------------
- // Implements code:ICLRPrivBinder::GetBinderID
- STDMETHOD(GetBinderID)(
- UINT_PTR *pBinderId);
-
- STDMETHOD(FindAssemblyBySpec)(
- LPVOID pvAppDomain,
- LPVOID pvAssemblySpec,
- HRESULT * pResult,
- ICLRPrivAssembly ** ppAssembly);
-
- //=============================================================================================
- // IBindContext methods
-
- // Implements code:IBindContext::PreBind
- STDMETHOD(PreBind)(
- IAssemblyName *pIAssemblyName,
- DWORD dwPreBindFlags,
- IBindResult **ppIBindResult);
-
- // Implements code:IBindContext::IsDefaultContext
- STDMETHOD(IsDefaultContext)();
-
- //=============================================================================================
- // Class methods
-
- //---------------------------------------------------------------------------------------------
- CLRPrivBinderFusion()
- : m_SetHostAssemblyLock(CrstLeafLock)
- { STANDARD_VM_CONTRACT; }
-
- //---------------------------------------------------------------------------------------------
- ~CLRPrivBinderFusion();
-
- //---------------------------------------------------------------------------------------------
- HRESULT FindFusionAssemblyBySpec(
- LPVOID pvAppDomain,
- LPVOID pvAssemblySpec,
- BindingScope kBindingScope,
- HRESULT * pResult,
- ICLRPrivAssembly ** ppAssembly);
-
- //---------------------------------------------------------------------------------------------
- HRESULT BindFusionAssemblyByName(
- IAssemblyName * pAssemblyName,
- BindingScope kBindingScope,
- ICLRPrivAssembly ** ppAssembly);
-
- //---------------------------------------------------------------------------------------------
- HRESULT PreBindFusionAssemblyByName(
- IAssemblyName * pIAssemblyName,
- DWORD dwPreBindFlags,
- IBindResult ** ppIBindResult);
-
- //---------------------------------------------------------------------------------------------
- // Binds mscorlib.dll
- void BindMscorlib(
- PEAssembly * pPEAssembly);
-
-private:
- //---------------------------------------------------------------------------------------------
- HRESULT BindAssemblyByNameWorker(
- IAssemblyName * pAssemblyName,
- ICLRPrivAssembly ** ppAssembly);
-
-private:
- //---------------------------------------------------------------------------------------------
- // This lock is used to serialize assigning ICLRPrivAssembly instances to PEAssembly objects.
- Crst m_SetHostAssemblyLock;
-
-}; // class CLRPrivBinderFusion
-
-//=====================================================================================================================
-class CLRPrivAssemblyFusion :
- public IUnknownCommon<ICLRPrivAssembly>
-{
-public:
- //---------------------------------------------------------------------------------------------
- CLRPrivAssemblyFusion(
- LPCWSTR wszName,
- CLRPrivBinderFusion * pBinder);
-
- //---------------------------------------------------------------------------------------------
- LPCWSTR GetName() const;
-
- //---------------------------------------------------------------------------------------------
- // Implements code:IUnknown::Release
- STDMETHOD_(ULONG, Release)();
-
- //---------------------------------------------------------------------------------------------
- // Implements code:ICLRPrivBinder::BindAssemblyByName
- STDMETHOD(BindAssemblyByName)(
- IAssemblyName * pAssemblyName,
- ICLRPrivAssembly ** ppAssembly);
-
- //---------------------------------------------------------------------------------------------
- // Implements code:ICLRPrivAssembly::IsShareable
- STDMETHOD(IsShareable)(
- BOOL * pbIsShareable);
-
- //---------------------------------------------------------------------------------------------
- // Implements code:ICLRPrivAssembly::GetAvailableImageTypes
- STDMETHOD(GetAvailableImageTypes)(
- LPDWORD pdwImageTypes);
-
- //---------------------------------------------------------------------------------------------
- // Implements code:ICLRPrivAssembly::GetImageResource
- STDMETHOD(GetImageResource)(
- DWORD dwImageType,
- DWORD *pdwImageType,
- ICLRPrivResource ** ppIResource);
-
- //---------------------------------------------------------------------------------------------
- // Implements code:ICLRPrivBinder::VerifyBind
- STDMETHOD(VerifyBind)(
- IAssemblyName *pAssemblyName,
- ICLRPrivAssembly *pAssembly,
- ICLRPrivAssemblyInfo *pAssemblyInfo)
- {
- WRAPPER_NO_CONTRACT;
- return m_pBinder->VerifyBind(pAssemblyName, pAssembly, pAssemblyInfo);
- }
-
- //---------------------------------------------------------------------------------------------
- // Implements code:ICLRPrivBinder::GetBinderFlags
- STDMETHOD(GetBinderFlags)(
- DWORD *pBinderFlags)
- {
- LIMITED_METHOD_CONTRACT;
- return m_pBinder->GetBinderFlags(pBinderFlags);
- }
-
- //---------------------------------------------------------------------------------------------
- // Implements code:ICLRPrivBinder::GetBinderID
- STDMETHOD(GetBinderID)(
- UINT_PTR *pBinderId);
-
- //---------------------------------------------------------------------------------------------
- // Implements code:ICLRPrivBinder::FindAssemblyBySpec
- STDMETHOD(FindAssemblyBySpec)(
- LPVOID pvAppDomain,
- LPVOID pvAssemblySpec,
- HRESULT * pResult,
- ICLRPrivAssembly ** ppAssembly)
- { STATIC_CONTRACT_WRAPPER; return m_pBinder->FindAssemblyBySpec(pvAppDomain, pvAssemblySpec, pResult, ppAssembly); }
-
-protected:
- //---------------------------------------------------------------------------------------------
- // The fusion binder. Need to keep it around as long as this object is around.
- ReleaseHolder<CLRPrivBinderFusion> m_pBinder;
-
- // Full display name of the assembly - used to avoid duplicate CLRPrivAssemblyFusion objects
- NewArrayHolder<WCHAR> m_wszName;
-
-}; // class CLRPrivAssemblyFusion
diff --git a/src/vm/clrprivbinderreflectiononlywinrt.cpp b/src/vm/clrprivbinderreflectiononlywinrt.cpp
deleted file mode 100644
index ad46511e81..0000000000
--- a/src/vm/clrprivbinderreflectiononlywinrt.cpp
+++ /dev/null
@@ -1,497 +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.
-//
-
-//
-// Contains the types that implement code:ICLRPrivBinder and code:ICLRPrivAssembly for WinRT ReflectionOnly (aka introspection) binding.
-//
-//=====================================================================================================================
-
-#include "common.h" // precompiled header
-
-#ifndef DACCESS_COMPILE
-#ifdef FEATURE_REFLECTION_ONLY_LOAD
-
-//=====================================================================================================================
-#include "sstring.h"
-#include "policy.h"
-#include "clrprivbinderreflectiononlywinrt.h"
-#include "appxutil.h"
-#include "clrprivbinderutil.h"
-#include "imprthelpers.h" // in fusion/inc
-
-#include <winstring.h>
-#include <typeresolution.h>
-
-using namespace CLRPrivBinderUtil;
-
-//=====================================================================================================================
-
-//=====================================================================================================================
-CLRPrivBinderReflectionOnlyWinRT::CLRPrivBinderReflectionOnlyWinRT(
- CLRPrivTypeCacheReflectionOnlyWinRT * pTypeCache)
- : m_MapsLock(CrstLeafLock, CRST_REENTRANCY) // Reentracy is needed for code:CLRPrivAssemblyReflectionOnlyWinRT::Release
-{
- STANDARD_VM_CONTRACT;
-
- // This binder is not supported in AppX scenario.
- _ASSERTE(!AppX::IsAppXProcess());
-
- _ASSERTE(pTypeCache != nullptr);
- m_pTypeCache = clr::SafeAddRef(pTypeCache);
-}
-
-//=====================================================================================================================
-CLRPrivBinderReflectionOnlyWinRT::~CLRPrivBinderReflectionOnlyWinRT()
-{
- WRAPPER_NO_CONTRACT;
-
- if (m_pTypeCache != nullptr)
- {
- m_pTypeCache->Release();
- }
-}
-
-//=====================================================================================================================
-HRESULT
-CLRPrivBinderReflectionOnlyWinRT::BindWinRtType_Internal(
- LPCSTR szTypeNamespace,
- LPCSTR szTypeClassName,
- DomainAssembly * pParentAssembly,
- CLRPrivAssemblyReflectionOnlyWinRT ** ppAssembly)
-{
- STANDARD_VM_CONTRACT;
-
- HRESULT hr = S_OK;
-
- VALIDATE_ARG_RET(ppAssembly != nullptr);
-
- CLRPrivBinderUtil::WStringList * pFileNameList = nullptr;
-
- StackSString ssTypeNamespace(SString::Utf8, szTypeNamespace);
-
- GetFileNameListForNamespace(ssTypeNamespace.GetUnicode(), pParentAssembly, &pFileNameList);
-
- if (pFileNameList == nullptr)
- { // There are no files associated with the namespace
- return CLR_E_BIND_TYPE_NOT_FOUND;
- }
-
- StackSString ssTypeName(ssTypeNamespace);
- ssTypeName.Append(W('.'));
- ssTypeName.AppendUTF8(szTypeClassName);
-
- CLRPrivBinderUtil::WStringListElem * pFileNameElem = pFileNameList->GetHead();
- while (pFileNameElem != nullptr)
- {
- const WCHAR * wszFileName = pFileNameElem->GetValue();
- ReleaseHolder<CLRPrivAssemblyReflectionOnlyWinRT> pAssembly = FindOrCreateAssemblyByFileName(wszFileName);
- _ASSERTE(pAssembly != NULL);
-
- IfFailRet(hr = m_pTypeCache->ContainsType(pAssembly, ssTypeName.GetUnicode()));
- if (hr == S_OK)
- { // The type we are looking for has been found in this assembly
- *ppAssembly = pAssembly.Extract();
- return S_OK;
- }
- _ASSERTE(hr == S_FALSE);
-
- // Try next file name for this namespace
- pFileNameElem = CLRPrivBinderUtil::WStringList::GetNext(pFileNameElem);
- }
-
- // The type has not been found in any of the files from the type's namespace
- return CLR_E_BIND_TYPE_NOT_FOUND;
-} // CLRPrivBinderReflectionOnlyWinRT::BindWinRtType_Internal
-
-//=====================================================================================================================
-HRESULT
-CLRPrivBinderReflectionOnlyWinRT::BindWinRtType(
- LPCSTR szTypeNamespace,
- LPCSTR szTypeClassName,
- DomainAssembly * pParentAssembly,
- ICLRPrivAssembly ** ppPrivAssembly)
-{
- STANDARD_VM_CONTRACT;
-
- HRESULT hr = S_OK;
-
- ReleaseHolder<CLRPrivAssemblyReflectionOnlyWinRT> pWinRTAssembly;
- IfFailRet(BindWinRtType_Internal(szTypeNamespace, szTypeClassName, pParentAssembly, &pWinRTAssembly));
- IfFailRet(pWinRTAssembly->QueryInterface(__uuidof(ICLRPrivAssembly), (LPVOID *)ppPrivAssembly));
-
- return hr;
-}
-
-//=====================================================================================================================
-// Implements interface method code:ICLRPrivBinder::BindAssemblyByName.
-//
-HRESULT CLRPrivBinderReflectionOnlyWinRT::BindAssemblyByName(
- IAssemblyName * pAssemblyName,
- ICLRPrivAssembly ** ppAssembly)
-{
- LIMITED_METHOD_CONTRACT;
-
- _ASSERTE_MSG(false, "Unexpected call to CLRPrivBinderReflectionOnlyWinRT::BindAssemblyByName");
- return E_UNEXPECTED;
-}
-
-//=====================================================================================================================
-ReleaseHolder<CLRPrivAssemblyReflectionOnlyWinRT>
-CLRPrivBinderReflectionOnlyWinRT::FindAssemblyByFileName(
- LPCWSTR wszFileName)
-{
- LIMITED_METHOD_CONTRACT;
- STATIC_CONTRACT_CAN_TAKE_LOCK;
-
- CrstHolder lock(&m_MapsLock);
- const FileNameToAssemblyMapEntry * pEntry = m_FileNameToAssemblyMap.LookupPtr(wszFileName);
- return (pEntry == nullptr) ? nullptr : clr::SafeAddRef(pEntry->m_pAssembly);
-}
-
-//=====================================================================================================================
-// Add FileName -> CLRPrivAssemblyReflectionOnlyWinRT * mapping to the map (multi-thread safe).
-ReleaseHolder<CLRPrivAssemblyReflectionOnlyWinRT>
-CLRPrivBinderReflectionOnlyWinRT::AddFileNameToAssemblyMapping(
- LPCWSTR wszFileName,
- CLRPrivAssemblyReflectionOnlyWinRT * pAssembly)
-{
- STANDARD_VM_CONTRACT;
-
- _ASSERTE(pAssembly != nullptr);
-
- CrstHolder lock(&m_MapsLock);
-
- const FileNameToAssemblyMapEntry * pEntry = m_FileNameToAssemblyMap.LookupPtr(wszFileName);
- CLRPrivAssemblyReflectionOnlyWinRT * pResultAssembly = nullptr;
- if (pEntry != nullptr)
- {
- pResultAssembly = pEntry->m_pAssembly;
- }
- else
- {
- FileNameToAssemblyMapEntry e;
- e.m_wszFileName = wszFileName;
- e.m_pAssembly = pAssembly;
- m_FileNameToAssemblyMap.Add(e);
-
- pResultAssembly = pAssembly;
- }
- return clr::SafeAddRef(pResultAssembly);
-}
-
-//=====================================================================================================================
-void
-CLRPrivBinderReflectionOnlyWinRT::RemoveFileNameToAssemblyMapping(
- LPCWSTR wszFileName)
-{
- LIMITED_METHOD_CONTRACT;
- STATIC_CONTRACT_CAN_TAKE_LOCK;
-
- CrstHolder lock(&m_MapsLock);
- m_FileNameToAssemblyMap.Remove(wszFileName);
-}
-
-//=====================================================================================================================
-ReleaseHolder<CLRPrivAssemblyReflectionOnlyWinRT>
-CLRPrivBinderReflectionOnlyWinRT::FindOrCreateAssemblyByFileName(
- LPCWSTR wszFileName)
-{
- STANDARD_VM_CONTRACT;
-
- ReleaseHolder<CLRPrivAssemblyReflectionOnlyWinRT> pAssembly = FindAssemblyByFileName(wszFileName);
-
- if (pAssembly == nullptr)
- {
- NewHolder<CLRPrivResourcePathImpl> pResource(
- new CLRPrivResourcePathImpl(wszFileName));
-
- NewHolder<CLRPrivAssemblyReflectionOnlyWinRT> pNewAssembly(
- new CLRPrivAssemblyReflectionOnlyWinRT(wszFileName, this, pResource));
-
- // pNewAssembly holds reference to this now
- pResource.SuppressRelease();
-
- // Add the assembly into cache (multi-thread aware)
- pAssembly = AddFileNameToAssemblyMapping(pResource->GetPath(), pNewAssembly);
-
- if (pAssembly == pNewAssembly)
- { // We did not find an existing assembly in the cache and are using the newly created pNewAssembly.
- // Stop it from being deleted when we go out of scope.
- pNewAssembly.SuppressRelease();
- }
- }
- return pAssembly.Extract();
-}
-
-//=====================================================================================================================
-// Returns list of file names from code:m_NamespaceToFileNameListMap for the namespace.
-//
-void
-CLRPrivBinderReflectionOnlyWinRT::GetFileNameListForNamespace(
- LPCWSTR wszNamespace,
- DomainAssembly * pParentAssembly,
- CLRPrivBinderUtil::WStringList ** ppFileNameList)
-{
- STANDARD_VM_CONTRACT;
-
- CLRPrivBinderUtil::WStringList * pFileNameList = nullptr;
- {
- CrstHolder lock(&m_MapsLock);
-
- const NamespaceToFileNameListMapEntry * pEntry = m_NamespaceToFileNameListMap.LookupPtr(wszNamespace);
- if (pEntry != nullptr)
- {
- // Entries from the map are never removed, so we do not have to protect the file name list with a lock
- pFileNameList = pEntry->m_pFileNameList;
- }
- }
-
- if (pFileNameList != nullptr)
- {
- *ppFileNameList = pFileNameList;
- }
- else
- {
- CLRPrivBinderUtil::WStringListHolder hFileNameList;
-
- EX_TRY
- {
- m_pTypeCache->RaiseNamespaceResolveEvent(wszNamespace, pParentAssembly, &hFileNameList);
- }
- EX_CATCH
- {
- Exception * ex = GET_EXCEPTION();
- if (!ex->IsTransient())
- { // Exception was caused by user code
- // Cache empty file name list for this namespace
- (void)AddFileNameListForNamespace(wszNamespace, nullptr, ppFileNameList);
- }
- EX_RETHROW;
- }
- EX_END_CATCH_UNREACHABLE
-
- if (AddFileNameListForNamespace(wszNamespace, hFileNameList.GetValue(), ppFileNameList))
- { // The file name list was added to the cache - do not delete it
- _ASSERTE(*ppFileNameList == hFileNameList.GetValue());
- (void)hFileNameList.Extract();
- }
- }
-} // CLRPrivBinderReflectionOnlyWinRT::GetFileNameListForNamespace
-
-//=====================================================================================================================
-// Adds (thread-safe) list of file names to code:m_NamespaceToFileNameListMap for the namespace - returns the cached value.
-// Returns TRUE, if pFileNameList was added to the cache and caller should NOT delete it.
-// Returns FALSE, if pFileNameList was not added to the cache and caller should delete it.
-//
-BOOL
-CLRPrivBinderReflectionOnlyWinRT::AddFileNameListForNamespace(
- LPCWSTR wszNamespace,
- CLRPrivBinderUtil::WStringList * pFileNameList,
- CLRPrivBinderUtil::WStringList ** ppFileNameList)
-{
- STANDARD_VM_CONTRACT;
-
- NewArrayHolder<WCHAR> wszEntryNamespace = DuplicateStringThrowing(wszNamespace);
-
- NamespaceToFileNameListMapEntry entry;
- entry.m_wszNamespace = wszEntryNamespace;
- entry.m_pFileNameList = pFileNameList;
-
- {
- CrstHolder lock(&m_MapsLock);
-
- const NamespaceToFileNameListMapEntry * pEntry = m_NamespaceToFileNameListMap.LookupPtr(wszEntryNamespace);
- if (pEntry == nullptr)
- {
- m_NamespaceToFileNameListMap.Add(entry);
-
- // These values are now owned by the hash table element
- wszEntryNamespace.SuppressRelease();
- *ppFileNameList = pFileNameList;
- return TRUE;
- }
- else
- { // Another thread beat us adding this entry to the hash table
- *ppFileNameList = pEntry->m_pFileNameList;
- return FALSE;
- }
- }
-} // CLRPrivBinderReflectionOnlyWinRT::AddFileNameListForNamespace
-
-//=====================================================================================================================
-HRESULT
-CLRPrivBinderReflectionOnlyWinRT::BindAssemblyExplicit(
- const WCHAR * wszFileName,
- ICLRPrivAssembly ** ppAssembly)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- HRESULT hr;
-
- GCX_PREEMP();
-
- ReleaseHolder<CLRPrivAssemblyReflectionOnlyWinRT> pAssembly = FindOrCreateAssemblyByFileName(wszFileName);
- _ASSERTE(pAssembly != NULL);
-
- IfFailRet(pAssembly->QueryInterface(__uuidof(ICLRPrivAssembly), (LPVOID *)ppAssembly));
-
- return S_OK;
-}
-
-//=====================================================================================================================
-CLRPrivAssemblyReflectionOnlyWinRT::CLRPrivAssemblyReflectionOnlyWinRT(
- LPCWSTR wzSimpleName,
- CLRPrivBinderReflectionOnlyWinRT * pBinder,
- CLRPrivResourcePathImpl * pResourceIL)
-{
- STANDARD_VM_CONTRACT;
- VALIDATE_ARG_THROW((wzSimpleName != nullptr) && (pBinder != nullptr) && (pResourceIL != nullptr));
-
- m_pBinder = clr::SafeAddRef(pBinder);
- m_pResourceIL = clr::SafeAddRef(pResourceIL);
-}
-
-//=====================================================================================================================
-ULONG CLRPrivAssemblyReflectionOnlyWinRT::Release()
-{
- LIMITED_METHOD_CONTRACT;
- STATIC_CONTRACT_CAN_TAKE_LOCK;
- _ASSERTE(m_cRef > 0);
-
- ULONG cRef;
-
- {
- // To achieve proper lifetime semantics, the name to assembly map elements' CLRPrivAssemblyReflectionOnlyWinRT
- // instances are not ref counted. We cannot allow discovery of the object via m_FileNameToAssemblyMap
- // when the ref count is 0 (to prevent another thread to AddRef and Release it back to 0 in parallel).
- // All uses of the map are guarded by the map lock, so we have to decrease the ref count under that
- // lock (to avoid the chance that 2 threads are running Release to ref count 0 at once).
- CrstHolder lock(&m_pBinder->m_MapsLock);
-
- cRef = InterlockedDecrement(&m_cRef);
- if (cRef == 0)
- {
- m_pBinder->RemoveFileNameToAssemblyMapping(m_pResourceIL->GetPath());
- }
- }
-
- if (cRef == 0)
- {
- delete this;
- }
- return cRef;
-}
-
-//=====================================================================================================================
-// Implements interface method code:ICLRPrivAssembly::IsShareable.
-//
-HRESULT CLRPrivAssemblyReflectionOnlyWinRT::IsShareable(
- BOOL * pbIsShareable)
-{
- LIMITED_METHOD_CONTRACT;
-
- VALIDATE_ARG_RET(pbIsShareable != nullptr);
-
- *pbIsShareable = FALSE;
- return S_OK;
-}
-
-//=====================================================================================================================
-// Implements interface method code:ICLRPrivAssembly::GetAvailableImageTypes.
-//
-HRESULT CLRPrivAssemblyReflectionOnlyWinRT::GetAvailableImageTypes(
- LPDWORD pdwImageTypes)
-{
- LIMITED_METHOD_CONTRACT;
-
- VALIDATE_ARG_RET(pdwImageTypes != nullptr);
-
- *pdwImageTypes = 0;
-
- if (m_pResourceIL != nullptr)
- *pdwImageTypes |= ASSEMBLY_IMAGE_TYPE_IL;
-
- return S_OK;
-}
-
-//=====================================================================================================================
-// Implements interface method code:ICLRPrivAssembly::GetImageResource.
-//
-HRESULT CLRPrivAssemblyReflectionOnlyWinRT::GetImageResource(
- DWORD dwImageType,
- DWORD * pdwImageType,
- ICLRPrivResource ** ppIResource)
-{
- STANDARD_BIND_CONTRACT;
- HRESULT hr = S_OK;
-
- VALIDATE_ARG_RET(ppIResource != nullptr);
-
- EX_TRY
- {
- DWORD _dwImageType;
- if (pdwImageType == nullptr)
- {
- pdwImageType = &_dwImageType;
- }
-
- if ((dwImageType & ASSEMBLY_IMAGE_TYPE_IL) == ASSEMBLY_IMAGE_TYPE_IL)
- {
- *ppIResource = clr::SafeAddRef(m_pResourceIL);
- *pdwImageType = ASSEMBLY_IMAGE_TYPE_IL;
- }
- else
- { // Native image is not supported by this binder
- hr = CLR_E_BIND_IMAGE_UNAVAILABLE;
- }
- }
- EX_CATCH_HRESULT(hr);
-
- return hr;
-}
-
-//=====================================================================================================================
-// Implements interface method code:ICLRPrivBinder::VerifyBind.
-//
-HRESULT CLRPrivBinderReflectionOnlyWinRT::VerifyBind(
- IAssemblyName * pAssemblyName,
- ICLRPrivAssembly * pAssembly,
- ICLRPrivAssemblyInfo * pAssemblyInfo)
-{
- STANDARD_BIND_CONTRACT;
- HRESULT hr = S_OK;
-
- UINT_PTR binderID;
- IfFailRet(pAssembly->GetBinderID(&binderID));
- if (binderID != reinterpret_cast<UINT_PTR>(this))
- {
- return pAssembly->VerifyBind(pAssemblyName, pAssembly, pAssemblyInfo);
- }
-
- // Since WinRT types are bound by type name and not assembly name, assembly-level version validation
- // does not make sense here. Just return S_OK.
- return S_OK;
-}
-
-//=====================================================================================================================
-// Implements interface method code:ICLRPrivBinder::GetBinderID.
-//
-HRESULT CLRPrivBinderReflectionOnlyWinRT::GetBinderID(
- UINT_PTR * pBinderId)
-{
- LIMITED_METHOD_CONTRACT;
-
- *pBinderId = reinterpret_cast<UINT_PTR>(this);
- return S_OK;
-}
-
-#endif //FEATURE_REFLECTION_ONLY_LOAD
-#endif //!DACCESS_COMPILE
diff --git a/src/vm/clrprivbinderreflectiononlywinrt.h b/src/vm/clrprivbinderreflectiononlywinrt.h
deleted file mode 100644
index 5f8ef46773..0000000000
--- a/src/vm/clrprivbinderreflectiononlywinrt.h
+++ /dev/null
@@ -1,295 +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.
-//
-
-//
-// Contains the types that implement code:ICLRPrivBinder and code:ICLRPrivAssembly for WinRT ReflectionOnly (aka introspection) binding.
-//
-//=====================================================================================================================
-
-#ifdef FEATURE_REFLECTION_ONLY_LOAD
-
-#pragma once
-
-#include "holder.h"
-#include "internalunknownimpl.h"
-#include "clrprivbinding.h"
-#include "clrprivruntimebinders.h"
-#include "clrprivbinderutil.h"
-#include "clr_std/utility"
-
-//=====================================================================================================================
-// Forward declarations
-class CLRPrivBinderReflectionOnlyWinRT;
-class CLRPrivAssemblyReflectionOnlyWinRT;
-class CLRPrivTypeCacheReflectionOnlyWinRT;
-class DomainAssembly;
-
-//=====================================================================================================================
-//=====================================================================================================================
-//=====================================================================================================================
-class CLRPrivBinderReflectionOnlyWinRT :
- public IUnknownCommon<ICLRPrivBinder>
-{
- friend class CLRPrivAssemblyReflectionOnlyWinRT;
-
-private:
- //=============================================================================================
- // Data structures for Namespace -> FileNameList hash (as returned by RoResolveNamespace API)
-
- // Entry in SHash table that maps namespace to list of files
- struct NamespaceToFileNameListMapEntry
- {
- PWSTR m_wszNamespace;
- CLRPrivBinderUtil::WStringList * m_pFileNameList;
- };
-
- // SHash traits for Namespace -> FileNameList hash
- class NamespaceToFileNameListMapTraits : public NoRemoveSHashTraits< DefaultSHashTraits< NamespaceToFileNameListMapEntry > >
- {
- public:
- typedef PCWSTR key_t;
- static const NamespaceToFileNameListMapEntry Null() { NamespaceToFileNameListMapEntry e; e.m_wszNamespace = nullptr; return e; }
- static bool IsNull(const NamespaceToFileNameListMapEntry & e) { return e.m_wszNamespace == nullptr; }
- static PCWSTR GetKey(const NamespaceToFileNameListMapEntry & e) { return e.m_wszNamespace; }
- static count_t Hash(PCWSTR str) { return HashString(str); }
- static BOOL Equals(PCWSTR lhs, PCWSTR rhs) { LIMITED_METHOD_CONTRACT; return (wcscmp(lhs, rhs) == 0); }
-
- void OnDestructPerEntryCleanupAction(const NamespaceToFileNameListMapEntry & e)
- {
- delete [] e.m_wszNamespace;
- CLRPrivBinderUtil::WStringList_Delete(e.m_pFileNameList);
- }
- static const bool s_DestructPerEntryCleanupAction = true;
- };
-
- typedef SHash<NamespaceToFileNameListMapTraits> NamespaceToFileNameListMap;
-
- //=============================================================================================
- // Data structure for FileName -> CLRPrivAssemblyReflectionOnlyWinRT * map
-
- struct FileNameToAssemblyMapEntry
- {
- PCWSTR m_wszFileName; // File name (owned by m_pAssembly)
- CLRPrivAssemblyReflectionOnlyWinRT * m_pAssembly;
- };
-
- class FileNameToAssemblyMapTraits : public DefaultSHashTraits<FileNameToAssemblyMapEntry>
- {
- public:
- typedef PCWSTR key_t;
- static const FileNameToAssemblyMapEntry Null() { FileNameToAssemblyMapEntry e; e.m_wszFileName = NULL; return e; }
- static bool IsNull(const FileNameToAssemblyMapEntry &e) { return e.m_wszFileName == NULL; }
- static const FileNameToAssemblyMapEntry Deleted() { FileNameToAssemblyMapEntry e; e.m_wszFileName = (PCWSTR)-1; return e; }
- static bool IsDeleted(const FileNameToAssemblyMapEntry & e) { return e.m_wszFileName == (PCWSTR)-1; }
- static PCWSTR GetKey(const FileNameToAssemblyMapEntry & e) { return e.m_wszFileName; }
- static count_t Hash(PCWSTR str) { return HashString(str); }
- static BOOL Equals(PCWSTR lhs, PCWSTR rhs) { LIMITED_METHOD_CONTRACT; return (wcscmp(lhs, rhs) == 0); }
- };
-
- typedef SHash<FileNameToAssemblyMapTraits> FileNameToAssemblyMap;
-
-public:
- //=============================================================================================
- // ICLRPrivBinder interface methods
-
- STDMETHOD(BindAssemblyByName)(
- IAssemblyName * pAssemblyName,
- ICLRPrivAssembly ** ppAssembly);
-
- // Implements interface method code:ICLRPrivBinder::VerifyBind.
- STDMETHOD(VerifyBind)(
- IAssemblyName * pAssemblyName,
- ICLRPrivAssembly * pAssembly,
- ICLRPrivAssemblyInfo * pAssemblyInfo);
-
- // Implements interface method code:ICLRPrivBinder::GetBinderFlags
- STDMETHOD(GetBinderFlags)(
- DWORD *pBinderFlags)
- {
- LIMITED_METHOD_CONTRACT;
- *pBinderFlags = BINDER_NONE;
- return S_OK;
- }
-
- // Implements interface method code:ICLRPrivBinder::GetBinderID.
- STDMETHOD(GetBinderID)(
- UINT_PTR * pBinderId);
-
- // FindAssemblyBySpec is not supported by this binder.
- STDMETHOD(FindAssemblyBySpec)(
- LPVOID pvAppDomain,
- LPVOID pvAssemblySpec,
- HRESULT * pResult,
- ICLRPrivAssembly ** ppAssembly)
- { STATIC_CONTRACT_WRAPPER; return E_FAIL; }
-
- //=============================================================================================
- // Class methods
-
- CLRPrivBinderReflectionOnlyWinRT(
- CLRPrivTypeCacheReflectionOnlyWinRT * pTypeCache);
-
- ~CLRPrivBinderReflectionOnlyWinRT();
-
- HRESULT BindAssemblyExplicit(
- const WCHAR * wszFileName,
- ICLRPrivAssembly ** ppAssembly);
-
- HRESULT BindWinRtType(
- LPCSTR szTypeNamespace,
- LPCSTR szTypeClassName,
- DomainAssembly * pParentAssembly,
- ICLRPrivAssembly ** ppPrivAssembly);
-
-private:
- //=============================================================================================
- // Accessors for FileName -> CLRPrivAssemblyReflectionOnlyWinRT * map
-
- ReleaseHolder<CLRPrivAssemblyReflectionOnlyWinRT> FindAssemblyByFileName(
- LPCWSTR wzsFileName);
-
- ReleaseHolder<CLRPrivAssemblyReflectionOnlyWinRT> AddFileNameToAssemblyMapping(
- LPCWSTR wszFileName,
- CLRPrivAssemblyReflectionOnlyWinRT * pAssembly);
-
- void RemoveFileNameToAssemblyMapping(
- LPCWSTR wszFileName);
-
- ReleaseHolder<CLRPrivAssemblyReflectionOnlyWinRT> FindOrCreateAssemblyByFileName(
- LPCWSTR wzsFileName);
-
- //=============================================================================================
- // Internal methods
-
- // Returns list of file names from code:m_NamespaceToFileNameListMap for the namespace.
- void GetFileNameListForNamespace(
- LPCWSTR wszNamespace,
- DomainAssembly * pParentAssembly,
- CLRPrivBinderUtil::WStringList ** ppFileNameList);
-
- // Adds (thread-safe) list of file names to code:m_NamespaceToFileNameListMap for the namespace - returns the cached value.
- BOOL AddFileNameListForNamespace(
- LPCWSTR wszNamespace,
- CLRPrivBinderUtil::WStringList * pFileNameList,
- CLRPrivBinderUtil::WStringList ** ppFileNameList);
-
- HRESULT BindWinRtType_Internal(
- LPCSTR szTypeNamespace,
- LPCSTR szTypeClassName,
- DomainAssembly * pParentAssembly,
- CLRPrivAssemblyReflectionOnlyWinRT ** ppAssembly);
-
-private:
- //=============================================================================================
-
- // Namespace -> FileName list map ... items are never removed
- NamespaceToFileNameListMap m_NamespaceToFileNameListMap;
- // FileName -> CLRPrivAssemblyReflectionOnlyWinRT * map ... items can be removed when CLRPrivAssemblyReflectionOnlyWinRT dies
- FileNameToAssemblyMap m_FileNameToAssemblyMap;
-
- // Lock for the above maps
- Crst m_MapsLock;
-
- //=============================================================================================
- CLRPrivTypeCacheReflectionOnlyWinRT * m_pTypeCache;
-
-}; // class CLRPrivBinderReflectionOnlyWinRT
-
-
-//=====================================================================================================================
-//=====================================================================================================================
-//=====================================================================================================================
-class CLRPrivAssemblyReflectionOnlyWinRT :
- public IUnknownCommon<ICLRPrivAssembly>
-{
- friend class CLRPrivBinderReflectionOnlyWinRT;
-
-public:
- //=============================================================================================
- // Class methods
-
- CLRPrivAssemblyReflectionOnlyWinRT(
- LPCWSTR wzFullTypeName,
- CLRPrivBinderReflectionOnlyWinRT * pBinder,
- CLRPrivBinderUtil::CLRPrivResourcePathImpl * pResourceIL);
-
- //=============================================================================================
- // IUnknown interface methods
-
- // Overridden to implement self-removal from assembly map code:CLRPrivBinderReflectionOnlyWinRT::m_FileNameToAssemblyMap.
- STDMETHOD_(ULONG, Release)();
-
- //=============================================================================================
- // ICLRPrivBinder interface methods
-
- STDMETHOD(BindAssemblyByName)(
- IAssemblyName * pAssemblyName,
- ICLRPrivAssembly ** ppAssembly)
- {
- STATIC_CONTRACT_WRAPPER;
- return m_pBinder->BindAssemblyByName(pAssemblyName, ppAssembly);
- }
-
- // Implements interface method code:ICLRPrivBinder::VerifyBind.
- STDMETHOD(VerifyBind)(
- IAssemblyName * pAssemblyName,
- ICLRPrivAssembly * pAssembly,
- ICLRPrivAssemblyInfo * pAssemblyInfo)
- {
- STATIC_CONTRACT_WRAPPER;
- return m_pBinder->VerifyBind(pAssemblyName, pAssembly, pAssemblyInfo);
- }
-
- //---------------------------------------------------------------------------------------------
- // Implements interface method code:ICLRPrivBinder::GetBinderFlags
- STDMETHOD(GetBinderFlags)(
- DWORD *pBinderFlags)
- {
- STATIC_CONTRACT_WRAPPER;
- return m_pBinder->GetBinderFlags(pBinderFlags);
- }
-
- // Implements interface method code:ICLRPrivBinder::GetBinderID.
- STDMETHOD(GetBinderID)(
- UINT_PTR * pBinderId)
- {
- STATIC_CONTRACT_WRAPPER;
- return m_pBinder->GetBinderID(pBinderId);
- }
-
- //=============================================================================================
- // ICLRPrivAssembly interface methods
-
- // Implements interface method code:ICLRPrivAssembly::IsShareable.
- STDMETHOD(IsShareable)(
- BOOL * pbIsShareable);
-
- // Implements interface method code:ICLRPrivAssembly::GetAvailableImageTypes.
- STDMETHOD(GetAvailableImageTypes)(
- LPDWORD pdwImageTypes);
-
- // Implements interface method code:ICLRPrivAssembly::GetImageResource.
- STDMETHOD(GetImageResource)(
- DWORD dwImageType,
- DWORD * pdwImageType,
- ICLRPrivResource ** ppIResource);
-
- // Implements code:ICLRPrivBinder::FindAssemblyBySpec
- STDMETHOD(FindAssemblyBySpec)(
- LPVOID pvAppDomain,
- LPVOID pvAssemblySpec,
- HRESULT * pResult,
- ICLRPrivAssembly ** ppAssembly)
- { STATIC_CONTRACT_WRAPPER; return m_pBinder->FindAssemblyBySpec(pvAppDomain, pvAssemblySpec, pResult, ppAssembly); }
-
-private:
- //=============================================================================================
-
- ReleaseHolder<CLRPrivBinderReflectionOnlyWinRT> m_pBinder;
- ReleaseHolder<CLRPrivBinderUtil::CLRPrivResourcePathImpl> m_pResourceIL;
-
-}; // class CLRPrivAssemblyReflectionOnlyWinRT
-
-#endif //FEATURE_REFLECTION_ONLY_LOAD
diff --git a/src/vm/clrprivtypecachereflectiononlywinrt.cpp b/src/vm/clrprivtypecachereflectiononlywinrt.cpp
deleted file mode 100644
index 40f90dfe3f..0000000000
--- a/src/vm/clrprivtypecachereflectiononlywinrt.cpp
+++ /dev/null
@@ -1,260 +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.
-//
-
-//
-// Contains VM implementation of WinRT type cache for code:CLRPrivBinderReflectionOnlyWinRT binder.
-//
-//=====================================================================================================================
-
-#include "common.h" // precompiled header
-
-#ifndef DACCESS_COMPILE
-#ifdef FEATURE_REFLECTION_ONLY_LOAD
-
-#include "clrprivtypecachereflectiononlywinrt.h"
-#include <typeresolution.h>
-
-//=====================================================================================================================
-// S_OK - pAssembly contains type wszTypeName
-// S_FALSE - pAssembly does not contain type wszTypeName
-//
-HRESULT
-CLRPrivTypeCacheReflectionOnlyWinRT::ContainsType(
- ICLRPrivAssembly * pPrivAssembly,
- LPCWSTR wszTypeName)
-{
- STANDARD_VM_CONTRACT;
-
- HRESULT hr = S_OK;
-
- AppDomain * pAppDomain = AppDomain::GetCurrentDomain();
-
- ReleaseHolder<PEAssembly> pPEAssembly;
- IfFailGo(pAppDomain->BindHostedPrivAssembly(nullptr, pPrivAssembly, nullptr, &pPEAssembly, TRUE));
- _ASSERTE(pPEAssembly != nullptr);
-
- {
- // Find DomainAssembly * (can be cached if this is too slow to call always)
- DomainAssembly * pDomainAssembly = pAppDomain->LoadDomainAssembly(
- nullptr, // pIdentity
- pPEAssembly,
- FILE_LOADED,
- nullptr); // pLoadSecurity
-
- // Convert the type name into namespace and type names in UTF8
- StackSString ssTypeNameWCHAR(wszTypeName);
-
- StackSString ssTypeName;
- ssTypeNameWCHAR.ConvertToUTF8(ssTypeName);
- LPUTF8 szTypeName = (LPUTF8)ssTypeName.GetUTF8NoConvert();
-
- LPCUTF8 szNamespace;
- LPCUTF8 szClassName;
- ns::SplitInline(szTypeName, szNamespace, szClassName);
-
- NameHandle typeName(szNamespace, szClassName);
-
- // Find the type in the assembly (use existing hash of all type names defined in the assembly)
- TypeHandle thType;
- mdToken tkType;
- Module * pTypeModule;
- mdToken tkExportedType;
- if (pDomainAssembly->GetAssembly()->GetLoader()->FindClassModuleThrowing(
- &typeName,
- &thType,
- &tkType,
- &pTypeModule,
- &tkExportedType,
- nullptr, // ppClassHashEntry
- nullptr, // pLookInThisModuleOnly
- Loader::DontLoad))
- { // The type is present in the assembly
- hr = S_OK;
- }
- else
- { // The type is not present in the assembly
- hr = S_FALSE;
- }
- }
-
-ErrExit:
- return hr;
-} // CLRPrivTypeCacheReflectionOnlyWinRT::ContainsType
-
-//=====================================================================================================================
-// Raises user event NamespaceResolveEvent to get a list of files for this namespace.
-//
-void
-CLRPrivTypeCacheReflectionOnlyWinRT::RaiseNamespaceResolveEvent(
- LPCWSTR wszNamespace,
- DomainAssembly * pParentAssembly,
- CLRPrivBinderUtil::WStringListHolder * pFileNameList)
-{
- STANDARD_VM_CONTRACT;
-
- _ASSERTE(pFileNameList != nullptr);
-
- AppDomain * pAppDomain = AppDomain::GetCurrentDomain();
-
- GCX_COOP();
-
- struct _gc {
- OBJECTREF AppDomainRef;
- OBJECTREF AssemblyRef;
- STRINGREF str;
- } gc;
- ZeroMemory(&gc, sizeof(gc));
-
- GCPROTECT_BEGIN(gc);
- if ((gc.AppDomainRef = pAppDomain->GetRawExposedObject()) != NULL)
- {
- if (pParentAssembly != nullptr)
- {
- gc.AssemblyRef = pParentAssembly->GetExposedAssemblyObject();
- }
-
- MethodDescCallSite onNamespaceResolve(METHOD__APP_DOMAIN__ON_REFLECTION_ONLY_NAMESPACE_RESOLVE, &gc.AppDomainRef);
- gc.str = StringObject::NewString(wszNamespace);
- ARG_SLOT args[3] =
- {
- ObjToArgSlot(gc.AppDomainRef),
- ObjToArgSlot(gc.AssemblyRef),
- ObjToArgSlot(gc.str)
- };
- PTRARRAYREF ResultingAssemblyArrayRef = (PTRARRAYREF) onNamespaceResolve.Call_RetOBJECTREF(args);
- if (ResultingAssemblyArrayRef != NULL)
- {
- for (DWORD i = 0; i < ResultingAssemblyArrayRef->GetNumComponents(); i++)
- {
- ASSEMBLYREF ResultingAssemblyRef = (ASSEMBLYREF) ResultingAssemblyArrayRef->GetAt(i);
- Assembly * pAssembly = ResultingAssemblyRef->GetAssembly();
-
- if (pAssembly->IsCollectible())
- {
- COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleAssemblyResolve"));
- }
-
- PEAssembly * pPEAssembly = pAssembly->GetManifestFile();
-
- ICLRPrivAssembly * pPrivAssembly = pPEAssembly->GetHostAssembly();
- if ((pPrivAssembly == NULL) || !IsAfContentType_WindowsRuntime(pPEAssembly->GetFlags()))
- {
- COMPlusThrow(kNotSupportedException, IDS_EE_REFLECTIONONLY_WINRT_INVALIDASSEMBLY);
- }
-
- pFileNameList->InsertTail(pPEAssembly->GetILimage()->GetPath());
- }
- }
- }
- GCPROTECT_END();
-} // CLRPrivTypeCacheReflectionOnlyWinRT::RaiseNamespaceResolveEvent
-
-//=====================================================================================================================
-// Implementation of QCall System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeMetadata.nResolveNamespace
-// It's basically a PInvoke wrapper into Win8 API RoResolveNamespace
-//
-void
-QCALLTYPE
-CLRPrivTypeCacheReflectionOnlyWinRT::ResolveNamespace(
- LPCWSTR wszNamespace,
- LPCWSTR wszWindowsSdkPath,
- LPCWSTR * rgPackageGraphPaths,
- INT32 cPackageGraphPaths,
- QCall::ObjectHandleOnStack retFileNames)
-{
- QCALL_CONTRACT;
-
- _ASSERTE(wszNamespace != nullptr);
-
- BEGIN_QCALL;
-
- CoTaskMemHSTRINGArrayHolder hFileNames;
-
- if (!WinRTSupported())
- {
- IfFailThrow(COR_E_PLATFORMNOTSUPPORTED);
- }
-
- {
- CLRPrivBinderUtil::HSTRINGArrayHolder rgPackageGraph;
- rgPackageGraph.Allocate(cPackageGraphPaths);
-
- LPCWSTR wszNamespaceRoResolve = wszNamespace;
-
- for (INT32 i = 0; i < cPackageGraphPaths; i++)
- {
- _ASSERTE(rgPackageGraph.GetRawArray()[i] == nullptr);
- WinRtString hsPackageGraphPath;
- IfFailThrow(hsPackageGraphPath.Initialize(rgPackageGraphPaths[i]));
- hsPackageGraphPath.Detach(&rgPackageGraph.GetRawArray()[i]);
- }
-
- UINT32 cchNamespace, cchWindowsSdkPath;
- IfFailThrow(StringCchLength(wszNamespace, &cchNamespace));
- IfFailThrow(StringCchLength(wszWindowsSdkPath, &cchWindowsSdkPath));
-
- DWORD cFileNames = 0;
- HSTRING * rgFileNames = nullptr;
- HRESULT hr = RoResolveNamespace(
- WinRtStringRef(wszNamespace, cchNamespace),
- WinRtStringRef(wszWindowsSdkPath, cchWindowsSdkPath),
- rgPackageGraph.GetCount(),
- rgPackageGraph.GetRawArray(),
- &cFileNames,
- &rgFileNames,
- nullptr, // pcDirectNamespaceChildren
- nullptr); // rgDirectNamespaceChildren
- hFileNames.Init(rgFileNames, cFileNames);
-
- if (hr == HRESULT_FROM_WIN32(APPMODEL_ERROR_NO_PACKAGE))
- { // User tried to resolve 3rd party namespace without passing package graph - throw InvalidOperationException with custom message
- _ASSERTE(cPackageGraphPaths == 0);
- COMPlusThrow(kInvalidOperationException, IDS_EE_REFLECTIONONLY_WINRT_LOADFAILURE_THIRDPARTY);
- }
- IfFailThrow(hr);
- if (hr != S_OK)
- {
- IfFailThrow(E_UNEXPECTED);
- }
- }
-
- {
- GCX_COOP();
-
- PTRARRAYREF orFileNames = NULL;
- GCPROTECT_BEGIN(orFileNames);
-
- orFileNames = (PTRARRAYREF) AllocateObjectArray(hFileNames.GetCount(), g_pStringClass);
-
- for (DWORD i = 0; i < hFileNames.GetCount(); i++)
- {
- UINT32 cchFileName = 0;
-
- HSTRING hsFileName = hFileNames.GetAt(i);
- LPCWSTR wszFileName;
-
- if (hsFileName != nullptr)
- {
- wszFileName = WindowsGetStringRawBuffer(
- hsFileName,
- &cchFileName);
-
- STRINGREF str = StringObject::NewString(wszFileName);
- orFileNames->SetAt(i, str);
- }
- }
-
- retFileNames.Set(orFileNames);
-
- GCPROTECT_END();
- }
-
- END_QCALL;
-} // CLRPrivTypeCacheReflectionOnlyWinRT::ResolveNamespace
-
-//=====================================================================================================================
-
-#endif //FEATURE_REFLECTION_ONLY_LOAD
-#endif //!DACCESS_COMPILE
diff --git a/src/vm/clrprivtypecachereflectiononlywinrt.h b/src/vm/clrprivtypecachereflectiononlywinrt.h
deleted file mode 100644
index a605c3dc2e..0000000000
--- a/src/vm/clrprivtypecachereflectiononlywinrt.h
+++ /dev/null
@@ -1,58 +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.
-//
-
-//
-// Contains VM implementation of code:ICLRPrivTypeCacheReflectionOnlyWinRT for code:CLRPrivBinderReflectionOnlyWinRT binder.
-//
-//=====================================================================================================================
-
-#ifdef FEATURE_REFLECTION_ONLY_LOAD
-
-#pragma once
-
-#include "internalunknownimpl.h"
-#include "clrprivbinding.h"
-
-//=====================================================================================================================
-// Forward declarations
-class DomainAssembly;
-
-//=====================================================================================================================
-class CLRPrivTypeCacheReflectionOnlyWinRT :
- public IUnknownCommon<IUnknown>
-{
-public:
- //=============================================================================================
- // Class methods
-
- // S_OK - pAssembly contains type wszTypeName
- // S_FALSE - pAssembly does not contain type wszTypeName
- STDMETHOD(ContainsType)(
- ICLRPrivAssembly * pAssembly,
- LPCWSTR wszTypeName);
-
-#ifndef DACCESS_COMPILE
-
- // Raises user event NamespaceResolveEvent to get a list of files for this namespace.
- void RaiseNamespaceResolveEvent(
- LPCWSTR wszNamespace,
- DomainAssembly * pParentAssembly,
- CLRPrivBinderUtil::WStringListHolder * pFileNameList);
-
-#endif //!DACCESS_COMPILE
-
- // Implementation of QCall System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeMetadata.nResolveNamespace
- // It's basically a PInvoke wrapper into Win8 API RoResolveNamespace
- static
- void QCALLTYPE ResolveNamespace(
- LPCWSTR wszNamespace,
- LPCWSTR wszWindowsSdkPath,
- LPCWSTR * rgPackageGraphPaths,
- INT32 cPackageGraphPaths,
- QCall::ObjectHandleOnStack retFileNames);
-
-}; // class CLRPrivTypeCaheReflectionOnlyWinRT
-
-#endif //FEATURE_REFLECTION_ONLY_LOAD
diff --git a/src/vm/cominterfacemarshaler.cpp b/src/vm/cominterfacemarshaler.cpp
index 0bd22a028b..58dd504d6a 100644
--- a/src/vm/cominterfacemarshaler.cpp
+++ b/src/vm/cominterfacemarshaler.cpp
@@ -20,7 +20,6 @@
#include "interopconverter.h"
#ifdef FEATURE_REMOTING
#include "remoting.h"
-#include "appdomainhelper.h"
#include "crossdomaincalls.h"
#endif
#include "notifyexternals.h"
diff --git a/src/vm/commethodrental.cpp b/src/vm/commethodrental.cpp
deleted file mode 100644
index 0a5c011270..0000000000
--- a/src/vm/commethodrental.cpp
+++ /dev/null
@@ -1,120 +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.
-////////////////////////////////////////////////////////////////////////////////
-
-
-
-#include "common.h"
-#include "commethodrental.h"
-#include "corerror.h"
-
-#ifdef FEATURE_METHOD_RENTAL
-// SwapMethodBody
-// This method will take the rgMethod as the new function body for a given method.
-//
-
-void QCALLTYPE COMMethodRental::SwapMethodBody(EnregisteredTypeHandle cls, INT32 tkMethod, LPVOID rgMethod, INT32 iSize, INT32 flags, QCall::StackCrawlMarkHandle stackMark)
-{
- QCALL_CONTRACT;
-
- BEGIN_QCALL;
-
- BYTE *pNewCode = NULL;
- MethodDesc *pMethodDesc;
- ReflectionModule *module;
- ICeeGen* pGen;
- ULONG methodRVA;
- HRESULT hr;
-
- if ( cls == NULL)
- {
- COMPlusThrowArgumentNull(W("cls"));
- }
-
- MethodTable *pMethodTable = TypeHandle::FromPtr(cls).GetMethodTable();
- PREFIX_ASSUME(pMethodTable != NULL);
- module = (ReflectionModule *) pMethodTable->GetModule();
- pGen = module->GetCeeGen();
-
- Assembly* caller = SystemDomain::GetCallersAssembly( stackMark );
-
- _ASSERTE( caller != NULL && "Unable to get calling assembly" );
- _ASSERTE( module->GetCreatingAssembly() != NULL && "ReflectionModule must have a creating assembly to be used with method rental" );
-
- if (module->GetCreatingAssembly() != caller)
- {
- COMPlusThrow(kSecurityException);
- }
-
- // Find the methoddesc given the method token
- pMethodDesc = MemberLoader::FindMethod(pMethodTable, tkMethod);
- if (pMethodDesc == NULL)
- {
- COMPlusThrowArgumentException(W("methodtoken"), NULL);
- }
- if (pMethodDesc->GetMethodTable() != pMethodTable || pMethodDesc->GetNumGenericClassArgs() != 0 || pMethodDesc->GetNumGenericMethodArgs() != 0)
- {
- COMPlusThrowArgumentException(W("methodtoken"), W("Argument_TypeDoesNotContainMethod"));
- }
- hr = pGen->AllocateMethodBuffer(iSize, &pNewCode, &methodRVA);
- if (FAILED(hr))
- COMPlusThrowHR(hr);
-
- if (pNewCode == NULL)
- {
- COMPlusThrowOM();
- }
-
- // <TODO>
- // if method desc is pointing to the post-jitted native code block,
- // we want to recycle this code block
-
- // @todo: SEH handling. Will we need to support a method that can throw exception
- // If not, add an assertion to make sure that there is no SEH contains in the method header.
-
- // @todo: figure out a way not to copy the code block.
-
- // @todo: add link time security check. This function can be executed only if fully trusted.</TODO>
-
- // copy the new function body to the buffer
- memcpy(pNewCode, (void *) rgMethod, iSize);
-
- // add the starting address of the il blob to the il blob hash table
- // we need to find this information from out of process for debugger inspection
- // APIs so we have to store this information where we can get it later
- module->SetDynamicIL(mdToken(tkMethod), TADDR(pNewCode), FALSE);
-
- // Reset the methoddesc back to unjited state
- pMethodDesc->Reset();
-
- if (flags)
- {
- // JITImmediate
-#if _DEBUG
- COR_ILMETHOD* ilHeader = pMethodDesc->GetILHeader(TRUE);
- _ASSERTE(((BYTE *)ilHeader) == pNewCode);
-#endif
- COR_ILMETHOD_DECODER header((COR_ILMETHOD *)pNewCode, pMethodDesc->GetMDImport(), NULL);
-
- // minimum validation on the correctness of method header
- if (header.GetCode() == NULL)
- COMPlusThrowHR(VLDTR_E_MD_BADHEADER);
-
-#ifdef FEATURE_INTERPRETER
- pMethodDesc->MakeJitWorker(&header, CORJIT_FLAGS(CORJIT_FLAGS::CORJIT_FLAG_MAKEFINALCODE));
-#else // !FEATURE_INTERPRETER
- pMethodDesc->MakeJitWorker(&header, CORJIT_FLAGS());
-#endif // !FEATURE_INTERPRETER
- }
-
- // add feature::
- // If SQL is generating class with inheritance hierarchy, we may need to
- // check the whole vtable to find duplicate entries.
-
- END_QCALL;
-
-} // COMMethodRental::SwapMethodBody
-
-
-#endif // FEATURE_METHOD_RENTAL
diff --git a/src/vm/commethodrental.h b/src/vm/commethodrental.h
deleted file mode 100644
index 0523af274e..0000000000
--- a/src/vm/commethodrental.h
+++ /dev/null
@@ -1,29 +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.
-////////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef _COMMETHODRENTAL_H_
-#define _COMMETHODRENTAL_H_
-
-#include "excep.h"
-#include "fcall.h"
-
-#ifdef FEATURE_METHOD_RENTAL
-// COMMethodRental
-// This class implements SwapMethodBody for our MethodRenting story
-class COMMethodRental
-{
-public:
-
- // COMMethodRental.SwapMethodBody -- this function will swap an existing method body with
- // a new method body
- //
- static
- void QCALLTYPE SwapMethodBody(EnregisteredTypeHandle cls, INT32 tkMethod, LPVOID rgMethod, INT32 iSize, INT32 flags, QCall::StackCrawlMarkHandle stackMark);
-};
-#endif // FEATURE_METHOD_RENTAL
-
-#endif //_COMMETHODRENTAL_H_
diff --git a/src/vm/compile.cpp b/src/vm/compile.cpp
index 8aca2ad6df..09925cd219 100644
--- a/src/vm/compile.cpp
+++ b/src/vm/compile.cpp
@@ -68,6 +68,7 @@
#include "argdestination.h"
#include "versionresilienthashcode.h"
+#include "inlinetracking.h"
#ifdef CROSSGEN_COMPILE
CompilationDomain * theDomain;
@@ -6841,6 +6842,12 @@ ULONG CEEPreloader::Release()
return 0;
}
+void CEEPreloader::GetSerializedInlineTrackingMap(SBuffer* pBuffer)
+{
+ InlineTrackingMap * pInlineTrackingMap = m_image->GetInlineTrackingMap();
+ PersistentInlineTrackingMapR2R::Save(m_image->GetHeap(), pBuffer, pInlineTrackingMap);
+}
+
void CEEPreloader::Error(mdToken token, Exception * pException)
{
STANDARD_VM_CONTRACT;
diff --git a/src/vm/compile.h b/src/vm/compile.h
index 7aeef31b6c..8fdd383dfe 100644
--- a/src/vm/compile.h
+++ b/src/vm/compile.h
@@ -654,6 +654,8 @@ public:
ULONG Release();
+ void GetSerializedInlineTrackingMap(SBuffer* pBuffer);
+
void Error(mdToken token, Exception * pException);
};
diff --git a/src/vm/comsynchronizable.cpp b/src/vm/comsynchronizable.cpp
index e042c8effe..3a395235e6 100644
--- a/src/vm/comsynchronizable.cpp
+++ b/src/vm/comsynchronizable.cpp
@@ -29,7 +29,6 @@
#endif
#include "eeconfig.h"
#ifdef FEATURE_REMOTING
-#include "appdomainhelper.h"
#include "objectclone.h"
#else
#include "callhelpers.h"
diff --git a/src/vm/constrainedexecutionregion.cpp b/src/vm/constrainedexecutionregion.cpp
deleted file mode 100644
index 0745bd5e1b..0000000000
--- a/src/vm/constrainedexecutionregion.cpp
+++ /dev/null
@@ -1,2264 +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.
-//
-// Methods to support the implementation of Constrained Execution Regions (CERs). This includes logic to walk the IL of methods to
-// determine the statically determinable call graph and prepare each submethod (jit, prepopulate generic dictionaries etc.,
-// everything needed to ensure that the runtime won't generate implicit failure points during the execution of said call graph).
-//
-
-//
-
-
-#include "common.h"
-#include <openum.h>
-#include <mdaassistants.h>
-#include <ecmakey.h>
-#include <typestring.h>
-#include <jitinterface.h>
-
-#ifdef FEATURE_PREJIT
-#include <compile.h>
-#endif
-
-
-// Internal debugging support. Would be nice to use the common logging code but we've run out of unique facility codes and the debug
-// info we spew out is of interest to a limited audience anyhow.
-#ifdef _DEBUG
-
-#define CER_NOISY_PREPARE 0x00000001
-#define CER_NOISY_RESTORE 0x00000002
-#define CER_NOISY_CONTRACTS 0x00000004
-#define CER_NOISY_WARNINGS 0x00000008
-#define CER_NOISY_NGEN_STATS 0x00000010
-
-DWORD g_dwCerLogActions = 0xffffffff;
-DWORD GetCerLoggingOptions()
-{
- WRAPPER_NO_CONTRACT;
- if (g_dwCerLogActions != 0xffffffff)
- return g_dwCerLogActions;
- return g_dwCerLogActions = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_CerLogging);
-}
-
-#define CER_LOG(_reason, _msg) do { if (GetCerLoggingOptions() & CER_NOISY_##_reason) printf _msg; } while (false)
-#else
-#define CER_LOG(_reason, _msg)
-#endif
-
-
-// Enumeration used to determine the number of inline data bytes included inside a given IL instruction (except for the case of a
-// SWITCH instruction, where a dynamic calculation is required).
-enum
-{
- ArgBytes_InlineNone = 0, // no inline args
- ArgBytes_InlineVar = 2, // local variable (U2 (U1 if Short on))
- ArgBytes_InlineI = 4, // an signed integer (I4 (I1 if Short on))
- ArgBytes_InlineR = 8, // a real number (R8 (R4 if Short on))
- ArgBytes_InlineBrTarget = 4, // branch target (I4 (I1 if Short on))
- ArgBytes_InlineI8 = 8,
- ArgBytes_InlineMethod = 4, // method token (U4)
- ArgBytes_InlineField = 4, // field token (U4)
- ArgBytes_InlineType = 4, // type token (U4)
- ArgBytes_InlineString = 4, // string TOKEN (U4)
- ArgBytes_InlineSig = 4, // signature tok (U4)
- ArgBytes_InlineRVA = 4, // ldptr token (U4)
- ArgBytes_InlineTok = 4, // a meta-data token of unknown type (U4)
- ArgBytes_InlineSwitch = 4, // count (U4), pcrel1 (U4) .... pcrelN (U4)
- ArgBytes_ShortInlineVar = 1,
- ArgBytes_ShortInlineI = 1,
- ArgBytes_ShortInlineR = 4,
- ArgBytes_ShortInlineBrTarget = 1
-};
-
-// Build an array of argument byte counts as described above by extracting the 'args' field of each entry in opcode.def.
-#define OPDEF(c, s, pop, push, args, type, l, s1, s2, ctrl) ArgBytes_##args,
-const BYTE g_rOpArgs[] = {
-#include <opcode.def>
-};
-#undef OPDEF
-
-
-// Global cache of methods and their reliability contract state.
-PtrHashCache *g_pMethodContractCache = NULL;
-
-
-// Private method forward references.
-bool IsPcrReference(Module *pModule, mdToken tkMethod);
-MethodContext *TokenToMethodDesc(Module *pModule, mdToken tokMethod, SigTypeContext *pTypeContext);
-TypeHandle GetTypeFromMemberDefOrRefOrSpecThrowing(Module *pModule,
- mdToken tokMethod,
- SigTypeContext *pTypeContext);
-
-bool MethodCallGraphPreparer::ShouldGatherExplicitCERCallInfo()
-{
- LIMITED_METHOD_CONTRACT;
-
- // If we're partially processing a method body (at the top of the call graph), we need to fetch exception handling
- // information to determine possible ranges of interesting IL (potentially each finally and catch clause).
- //
- // And if we are probing for stack overflow, we need to know if the explicit CER region contains any calls out, in
- // which case we want to probe in the call to PrepareConstrainedExecutionRegions. This will ensure that we don't
- // take an SO in boundary code and not be able to call the CER. When stack probing is disabled, we rip the process
- // if we take an SO anywhere but managed, or if we take an SO with a CER on the stack. For NGEN images, we need
- // to always probe because stack probing may be enabled in the runtime, but if we haven't probed in the NGEN image
- // then we could take an SO in boundary code and not be able to crawl the stack to know that we've skipped a CER and
- // need to tear the process.
- //
- // Additionally, if the MDA for illegal PrepareConstrainedRegions call positioning is enabled we gather this information for
- // all methods in the graph.
- return !m_fEntireMethod
-#ifdef MDA_SUPPORTED
- || MDA_GET_ASSISTANT(IllegalPrepareConstrainedRegion)
-#endif
-#ifdef FEATURE_NATIVE_IMAGE_GENERATION
- || m_fNgen
-#endif
- || g_pConfig->ProbeForStackOverflow();
-}
-
-MethodCallGraphPreparer::MethodCallGraphPreparer(MethodDesc *pRootMD, SigTypeContext *pRootTypeContext, bool fEntireMethod, bool fExactTypeContext, bool fIgnoreVirtualCERCallMDA)
-{
- CONTRACTL {
- STANDARD_VM_CHECK;
- PRECONDITION(CheckPointer(pRootMD));
- PRECONDITION(CheckPointer(pRootTypeContext));
- } CONTRACTL_END;
-
- // Canonicalize value type unboxing stubs into their underlying method desc.
- if (pRootMD->IsUnboxingStub())
- pRootMD = pRootMD->GetWrappedMethodDesc();
-
- m_pRootMD = pRootMD;
- m_pRootTypeContext = pRootTypeContext;
- m_fEntireMethod = fEntireMethod;
- m_fExactTypeContext = fExactTypeContext;
- m_fIgnoreVirtualCERCallMDA = fIgnoreVirtualCERCallMDA;
-
- m_pEHClauses = NULL;
- m_cEHClauses = 0;
- m_pCerPrepInfo = NULL;
- m_pMethodDecoder = NULL;
-
-#ifdef FEATURE_NATIVE_IMAGE_GENERATION
- m_fNgen = false;
-#endif
-
- m_pThread = GetThread();
- m_fPartialPreparation = false;
- m_fMethodHasCallsWithinExplicitCer = false;
-}
-
-// Walk the call graph of the method given by pRootMD (and type context in pRootTypeContext which provides instantiation information
-// for generic methods/classes).
-//
-// If fEntireMethod is true then the entire body of pRootMD is scanned for callsites, otherwise we assume that one or more CER
-// exception handlers exist in the method and only the finally and catch blocks of such handlers are scanned for graph roots.
-//
-// Each method we come across in the call graph (excluding late bound invocation destinations precipitated by virtual or interface
-// calls) is jitted and has any generic dictionary information we can determine at jit time prepopulated. This includes implicit
-// cctor invocations. If this method is called at ngen time we will attach extra fixup information to the affected method to ensure
-// that fixing up the root method of the graph will cause all methods in the graph to be fixed up at that point also.
-//
-// Some generic dictionary entries may not be prepopulated if unbound type variables exist at the root of the call tree. Such cases
-// will be ignored (as for the virtual/interface dispatch case we assume the caller will use an out-of-band mechanism to pre-prepare
-// these entries explicitly).
-bool MethodCallGraphPreparer::Run()
-{
- STANDARD_VM_CONTRACT;
-
- // Avoid recursion while jitting methods for another preparation.
- if (!m_pThread->GetCerPreparationState()->CanPreparationProceed(m_pRootMD, m_pRootTypeContext))
- return TRUE; // Assume the worst
-
-#ifdef FEATURE_NATIVE_IMAGE_GENERATION
- // Determine if we're being called in order to provide an ngen image. This impacts whether we actually prepare methods and the
- // type of tracking data we produce. Ideally we'd call GetAppDomain()->IsCompilationDomain() here, but we have to deal with the
- // problem of ngen'ing mscorlib. Mscorlib code is always shared and some of it is run before the compilation domain is fully
- // created (so we'd end up with some methods being prepared without saving any ngen metadata to that effect). So instead we
- // check to see whether this is an ngen process. This will catch those first few mscorlib methods.
- m_fNgen = IsCompilationProcess() != FALSE;
-
- // We keep a hash table of CERs we've processed on the module object of the root method. See if any work has been done on this
- // CER before. We store different data for ngen and non-ngen cases.
- if (m_fNgen) {
-
- // Pretty simple in ngen case -- if we've stored a context record for this method at all then we've already processed it.
- if (m_pRootMD->GetModule()->IsNgenCerRootMethod(m_pRootMD)) {
- m_pCerPrepInfo = m_pRootMD->GetModule()->GetCerPrepInfo(m_pRootMD);
-
- // We always store CerPrepInfo if the method has calls, so if we haven't stored
- // anything then we know it doesn't have any calls
- return (m_pCerPrepInfo && m_pCerPrepInfo->m_fMethodHasCallsWithinExplicitCer);
- }
- } else
-#endif
- {
- // The non-ngen case (normal jit, call to PrepareMethod etc).
- m_pCerPrepInfo = m_pRootMD->GetModule()->GetCerPrepInfo(m_pRootMD);
- if (m_pCerPrepInfo) {
-
- // Check for the "everything's done" case.
- if (m_pCerPrepInfo->m_fFullyPrepared)
- return m_pCerPrepInfo->m_fMethodHasCallsWithinExplicitCer;
-
- // Check for the "we can't do anything" case (see below for descriptions of that).
- if (m_pCerPrepInfo->m_fRequiresInstantiation && !m_fExactTypeContext)
- return m_pCerPrepInfo->m_fMethodHasCallsWithinExplicitCer;
-
- // Check for the "need to prepare per-instantiation, but we've already done this one" case.
- if (m_pCerPrepInfo->m_fRequiresInstantiation) {
- HashDatum sDatum;
- if (m_pCerPrepInfo->m_sIsInitAtInstHash.GetValue(m_pRootTypeContext, &sDatum))
- return m_pCerPrepInfo->m_fMethodHasCallsWithinExplicitCer;
- }
- }
- }
-
- // We can't deal with generic methods or methods on generic types that may have some representative type parameters in their
- // instantiation (i.e. some reference types indicated by Object rather than the exact type). The jit will tend to pass us these
- // since it shares code between instantiations over reference types. We can't prepare methods like these completely -- even
- // though we can jit all the method bodies the code might require generic dictionary information at the class or method level
- // that is populated at runtime and can introduce failure points. So we reject such methods immediately (they will need to be
- // prepared at non-jit time by an explicit call to PrepareMethod with a fully instantiated method).
- //
- // In the case where the type context is marked as suspect (m_fExactTypeContext == false) there are a number of possibilites for
- // bad methods the jit will pass us:
- // 1) We're passed a MethodDesc that shared between instantiations (bogus because exact method descs are never shared).
- // 2) We're passed a MethodDesc that's an instantiating stub (bogus because non-shared methods don't need this).
- // 3) We're passed a MethodDesc that has generic variables in its instantiations (I've seen this during ngen).
- //
- // Technically we could do a little better than this -- we could determine whether any of the representative type parameters are
- // actually used within the CER call graph itself. But this would require us to understand the IL at a much deeper level (i.e.
- // parse every instruction that could take a type or member spec and pull apart those specs to see if a type var is used). Plus
- // we couldn't make this determination until we've prepared the entire region and the result is rather brittle from the code
- // author's point of view (i.e. we might prepare a CER automatically one day but stop doing after some relatively subtle changes
- // in the source code).
- m_fPartialPreparation = m_pRootMD->IsSharedByGenericInstantiations() || m_pRootMD->IsInstantiatingStub() || m_pRootMD->ContainsGenericVariables();
- if (!m_fExactTypeContext && m_fPartialPreparation) {
-#ifdef MDA_SUPPORTED
- MDA_TRIGGER_ASSISTANT(OpenGenericCERCall, ReportViolation(m_pRootMD));
-#endif
- CER_LOG(WARNINGS, ("CER: %s has open type parameters and can't be pre-prepared\n", m_pRootMD->m_pszDebugMethodName));
-
-
-#ifdef FEATURE_NATIVE_IMAGE_GENERATION
- if (!m_fNgen)
-#endif
- {
- // Set up a prep info structure for this method if it's not there already (the create method takes care of races).
- if (m_pCerPrepInfo == NULL)
- m_pCerPrepInfo = m_pRootMD->GetModule()->CreateCerPrepInfo(m_pRootMD);
-
- // We may be racing to update the structure at this point but that's OK since the flag we're setting is never cleared once
- // it's set and is always guaranteed to be set before we rely on its value (setting it here is just a performance thing,
- // letting us early-out on multiple attempts to prepare this CER from the jit).
- m_pCerPrepInfo->m_fRequiresInstantiation = true;
- }
-
- if (! g_pConfig->ProbeForStackOverflow())
- {
- return FALSE;
- }
- m_pCerPrepInfo = m_pRootMD->GetModule()->GetCerPrepInfo(m_pRootMD);
-
- // We always store CerPrepInfo if the method has calls, so if we haven't stored
- // anything then we know it doesn't have any calls
- return (m_pCerPrepInfo && m_pCerPrepInfo->m_fMethodHasCallsWithinExplicitCer);
-
- }
-
-#ifdef FEATURE_NATIVE_IMAGE_GENERATION
- // If we've been called for a shared generic root method and the exact instantiation (this can happen because ngen lets code
- // execute under some circumstances) we don't currently support saving this information in the ngen image (we don't have a
- // format for the instantiation info). We just ignore the preparation in this case (it will be prepared at runtime).
- if (m_fNgen && m_fPartialPreparation)
- return TRUE;
-#endif
-
- // Prevent inlining of the root method (otherwise it's hard to tell where ThreadAbort exceptions should be delayed). Note that
- // MethodDesc::SetNotInline is thread safe.
- m_pRootMD->SetNotInline(true);
-
- // Remember the checkpoint for all of our allocations. Keep it in a holder so they'll be unwound if we throw an exception past
- // here.
- CheckPointHolder sCheckpoint(m_pThread->m_MarshalAlloc.GetCheckpoint());
-
- // Push the current method as the one and only method to process so far.
- m_sLeftToProcess.Push(MethodContext::PerThreadAllocate(m_pRootMD, m_pRootTypeContext));
-
- MethodContext *pContext = NULL; // The current MethodContext we're processing
-
- // Iterate until we run out of methods to process.
- while ((pContext = m_sLeftToProcess.Pop()) != NULL) {
-
- // Restore the MD if necessary. In particular, if this is an instantiating stub and the wrapped MethodDesc could
- // not be hard bound, then we'll need to restore that pointer before getting it.
- pContext->m_pMethodDesc->CheckRestore();
-
- // Transfer the method to the already seen stack immediately (we don't want to loop infinitely in the case of method
- // recursion).
- m_sAlreadySeen.Push(pContext);
-
- // Check if the enclosing class requires a static class constructor to be run. If so, we need to prepare that method as
- // though it were any other call.
- if (pContext->m_pMethodDesc->GetMethodTable()->HasClassConstructor()) {
-
- // Decode target method into MethodDesc and new SigTypeContext.
- // The type context is easy to derive here : .cctors never have any method type parameters and the class instantiations
- // are those of the method we're currently parsing, so can be simply copied down.
- MethodDesc *pCctor = pContext->m_pMethodDesc->GetCanonicalMethodTable()->GetClassConstructor();
- SigTypeContext sCctorTypeContext(pCctor, pContext->m_sTypeContext.m_classInst, Instantiation());
- MethodContext *pCctorContext = MethodContext::PerThreadAllocate(pCctor, &sCctorTypeContext);
-
- // Only process this cctor the first time we find it in this call graph.
- if (!m_sAlreadySeen.IsInStack(pCctorContext) && !m_sLeftToProcess.IsInStack(pCctorContext))
- m_sLeftToProcess.Push(pCctorContext);
- }
-
- // Skip further processing if this method doesn't have an IL body (note that we assume the method we entered with was IL, so
- // we don't need to bother with partial method processing).
- if (!pContext->m_pMethodDesc->IsIL()) {
- _ASSERTE(m_fEntireMethod);
- continue;
- }
-
- // Locate the IL body of the current method. May have to account for the fact that the current method desc is an
- // instantiating stub and burrow down for the real method desc.
- MethodDesc *pRealMethod = pContext->m_pMethodDesc;
- if (pRealMethod->IsInstantiatingStub()) {
- _ASSERTE(!pRealMethod->ContainsGenericVariables());
- pRealMethod = pRealMethod->GetWrappedMethodDesc();
- }
-
- COR_ILMETHOD* pILHeader = pRealMethod->GetILHeader();
-
- // Skip malformed methods. (We should always have method with IL for well-formed images here.)
- if (pILHeader == NULL) {
- continue;
- }
-
- COR_ILMETHOD_DECODER method(pILHeader);
- m_pMethodDecoder = &method;
-
- // We want to reget the EH clauses for the current method so that we can scan its handlers
- GetEHClauses();
-
- LookForInterestingCallsites(pContext);
-
- // Whatever we've done, we're definitely not processing the top-level method at this point (so we'll be processing full
- // method bodies from now on).
- m_fEntireMethod = true;
- }
-
-#ifdef FEATURE_NATIVE_IMAGE_GENERATION
- if (!m_fNgen)
-#endif
- {
- // Set up a prep info structure for this method if it's not there already (the create method takes care of races).
- // This needs to happen before we start JITing the methods as part of preparation. The JIT needs to know
- // about the CER root in CEEInfo::canTailCall.
- if (m_pCerPrepInfo == NULL)
- m_pCerPrepInfo = m_pRootMD->GetModule()->CreateCerPrepInfo(m_pRootMD);
- }
-
- // Prevent infinite recursion by recording on the thread which roots we're currently preparing.
- ThreadPreparingCerHolder sCerHolder(this);
-
- // Once we get here we've run out of methods to process and have recorded each method we visited in the m_sAlreadySeen stack. Now
- // it's time to prepare each of these methods (jit, prepopulate generic dictionaries etc.).
- PrepareMethods();
-
- return RecordResults();
-}
-
-
-// Determine whether a CER preparation for the given root method (with type context for generic instantiation
-// if necessary) can go ahead given any current preparation already being performed on the current thread.
-BOOL MethodCallGraphPreparer::CanPreparationProceed(MethodDesc * pMD, SigTypeContext * pTypeContext)
-{
- WRAPPER_NO_CONTRACT;
- MethodCallGraphPreparer * pCurrPrep = this;
- while (pCurrPrep)
- {
- // Is the prepartion request for the root method of the current preparer?
- if (pMD == pCurrPrep->m_pRootMD && SigTypeContext::Equal(pTypeContext, pCurrPrep->m_pRootTypeContext))
- {
- // We're already preparing this root, return FALSE to turn the request into a no-op and avoid
- // infinite recursion.
- return FALSE;
- }
-
- pCurrPrep = pCurrPrep->m_pNext;
- }
-
- // We found no previous preparation for the same root, so the request can proceed.
- return TRUE;
-}
-
-// Methods that push and pop thread local state used to determine if a re-entrant preparation request should
-// complete immediately as a no-op (because it would lead to an infinite recursion) or should proceed
-// recursively.
-
-//static
-void MethodCallGraphPreparer::BeginPrepareCerForHolder(MethodCallGraphPreparer * pPrepState)
-{
- LIMITED_METHOD_CONTRACT;
-
- Thread * pThread = pPrepState->m_pThread;
- pPrepState->m_pNext = pThread->GetCerPreparationState();
- pThread->SetCerPreparationState(pPrepState);
-}
-
-//static
-void MethodCallGraphPreparer::EndPrepareCerForHolder(MethodCallGraphPreparer * pPrepState)
-{
- LIMITED_METHOD_CONTRACT;
-
- Thread * pThread = pPrepState->m_pThread;
- _ASSERTE(pThread && pThread->GetCerPreparationState() == pPrepState);
- pThread->SetCerPreparationState(pPrepState->m_pNext);
-}
-
-
-void MethodCallGraphPreparer::GetEHClauses()
-{
- STANDARD_VM_CONTRACT;
-
- if (! ShouldGatherExplicitCERCallInfo())
- {
- return;
- }
-
- m_cEHClauses = 0;
- m_pEHClauses = NULL; // we use the StackingAllocator, so don't have to delete the previous storage
-
- COR_ILMETHOD_SECT_EH const * pEH = m_pMethodDecoder->EH;
- if (pEH == NULL ||pEH->EHCount() == 0)
- {
- return;
- }
-
- m_cEHClauses = pEH->EHCount();
- m_pEHClauses = new (&m_pThread->m_MarshalAlloc) EHClauseRange[m_cEHClauses];
-
- for (DWORD i = 0; i < m_cEHClauses; i++)
- {
- COR_ILMETHOD_SECT_EH_CLAUSE_FAT sEHClauseBuffer;
- const COR_ILMETHOD_SECT_EH_CLAUSE_FAT *pEHClause;
-
- pEHClause = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)pEH->EHClause(i, &sEHClauseBuffer);
-
- // The algorithm below assumes handlers are located after their associated try blocks. If this turns out to be a
- // false assumption we need to move to a two pass technique (or defer callsite handling in some other fashion until
- // we've scanned the IL for all calls to our preparation marker method).
- if (!(pEHClause->GetTryOffset() < pEHClause->GetHandlerOffset()))
- {
- COMPlusThrowHR(COR_E_NOTSUPPORTED, IDS_EE_NOTSUPPORTED_CATCHBEFORETRY);
- }
-
- m_pEHClauses[i].m_dwTryOffset = pEHClause->GetTryOffset();
- m_pEHClauses[i].m_dwHandlerOffset = pEHClause->GetHandlerOffset();
- m_pEHClauses[i].m_dwHandlerLength = pEHClause->GetHandlerLength();
- m_pEHClauses[i].m_fActive = false;
-
- //printf("Try: %u Handler: %u -> %u\n", pEHClause->GetTryOffset(), pEHClause->GetHandlerOffset(), pEHClause->GetHandlerOffset() + pEHClause->GetHandlerLength() - 1);
- }
-
-}
-
-void MethodCallGraphPreparer::MarkEHClauseActivatedByCERCall(MethodContext *pContext, BYTE *pbIL, DWORD cbIL)
-{
- STANDARD_VM_CONTRACT;
-
- DWORD dwOffset = (DWORD)(SIZE_T)((pbIL + ArgBytes_InlineTok) - (BYTE*)m_pMethodDecoder->Code);
-
- // Additionally we need to cope with the fact that VB and C# (for debug builds) can generate NOP instructions
- // between the PCR call and the beginning of the try block. So we're potentially looking for the
- // intersection of the try with a range of instructions. Count the number of consecutive NOP instructions
- // which follow the call.
- DWORD dwLength = 0;
- BYTE *pbTmpIL = pbIL + ArgBytes_InlineTok;
- while (pbTmpIL < (pbIL + cbIL) && *pbTmpIL++ == CEE_NOP)
- {
- dwLength++;
- }
-
- bool fMatched = false;
- for (DWORD i = 0; i < m_cEHClauses; i++)
- {
- if (m_pEHClauses[i].m_dwTryOffset >= dwOffset &&
- m_pEHClauses[i].m_dwTryOffset <= (dwOffset + dwLength))
- {
- fMatched = true;
- m_pEHClauses[i].m_fActive = true;
- }
- }
- if (!fMatched)
- {
-#if defined(_DEBUG) || defined(MDA_SUPPORTED)
- DWORD dwPCROffset = (DWORD)(SIZE_T)((pbIL - 1) - (BYTE*)m_pMethodDecoder->Code);
-#endif // defined(_DEBUG) || defined(MDA_SUPPORTED)
-#ifdef MDA_SUPPORTED
- MDA_TRIGGER_ASSISTANT(IllegalPrepareConstrainedRegion, ReportViolation(pContext->m_pMethodDesc, dwPCROffset));
-#endif
- CER_LOG(WARNINGS, ("CER: %s: Invalid call to PrepareConstrainedRegions() at IL +%04X\n",
- pContext->m_pMethodDesc->m_pszDebugMethodName, dwPCROffset));
- }
-}
-
-bool MethodCallGraphPreparer::CheckIfCallsiteWithinCER(DWORD dwOffset)
-{
- STANDARD_VM_CONTRACT;
-
- //printf("Found: %s at %u\n", pCallTarget->m_pMethodDesc->m_pszDebugMethodName, dwOffset);
-
- // Search all the EH regions we know about.
- for (DWORD i = 0; i < m_cEHClauses; i++)
- {
- bool fCallsiteWithinCER = false;
- if (! m_pEHClauses[i].m_fActive)
- {
- // clause not CER-active so skip it
- continue;
- }
- if (dwOffset >= (m_pEHClauses[i].m_dwHandlerOffset + m_pEHClauses[i].m_dwHandlerLength))
- {
- // offset beyond clause, so skip it
- continue;
- }
- if (dwOffset >= m_pEHClauses[i].m_dwTryOffset)
- {
- // For stack probing optimization, we care if either the try or the handler has a call. If neither
- // does, then we can optimize the probe out.
- m_fMethodHasCallsWithinExplicitCer = true;
- if (dwOffset >= m_pEHClauses[i].m_dwHandlerOffset)
- {
- fCallsiteWithinCER = true;
- }
- }
- // Only terminate if we got a positive result (i.e. the calliste is within a hardened clause).
- // We can't terminate early in the negative case because the callsite could be nested
- // in another EH region which may be hardened.
- if (fCallsiteWithinCER == true)
- {
- return true;
- }
- }
-
- return false;
-}
-
-
-// Iterate through the body of the method looking for interesting call sites.
-void MethodCallGraphPreparer::LookForInterestingCallsites(MethodContext *pContext)
-{
- STANDARD_VM_CONTRACT;
-
- BYTE *pbIL = (BYTE*)m_pMethodDecoder->Code;
- DWORD cbIL = m_pMethodDecoder->GetCodeSize();
-
- while (cbIL) {
-
- // Read the IL op.
- DWORD dwOp = *pbIL++; cbIL--;
-
- // Handle prefix codes (only CEE_PREFIX1 is legal so far).
- if (dwOp == CEE_PREFIX1) {
- if (!cbIL)
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
- dwOp = 256 + *pbIL++; cbIL--;
- } else if (dwOp >= CEE_PREFIX7)
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
-
- // We're interested in NEWOBJ, JMP, CALL and CALLVIRT (can't trace through CALLI). We include CALLVIRT becase C#
- // routinely calls non-virtual instance methods this way in order to get this pointer null checking. We prepare NEWOBJ
- // because that covers the corner case of value types which can be constructed with no failure path.
- if (dwOp == CEE_CALL || dwOp == CEE_CALLVIRT || dwOp == CEE_NEWOBJ || dwOp == CEE_JMP) {
-
- if (cbIL < sizeof(DWORD))
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
-
- // Decode target method into MethodDesc and new SigTypeContext.
- mdToken tkCallTarget = (mdToken)GET_UNALIGNED_VAL32(pbIL);
- MethodContext *pCallTarget = TokenToMethodDesc(pContext->m_pMethodDesc->GetModule(), tkCallTarget, &pContext->m_sTypeContext);
-
- // Check whether we've found a call to our own preparation marker method.
- if (pCallTarget->m_pMethodDesc == g_pPrepareConstrainedRegionsMethod) {
-
- if (ShouldGatherExplicitCERCallInfo()) {
- // If we're preparing a partial method these callsites are significant (we mark which EH clauses are now
- // 'activated' by proximity to this marker method call). Look for EH regions that are 'activated' by the call to
- // PrepareConstrainedRegions by comparing the IL offset of the start of the try to the offset immediately after
- // the callsite (remember to account for the rest of the CALLVIRT instruction we haven't skipped yet).
- MarkEHClauseActivatedByCERCall(pContext, pbIL, cbIL);
- }
-
- // Record the fact that we found a method in the CER which is the root of a sub-CER. This is important since the
- // rude thread abort protection algorithm relies on root CER methods being marked as such.
- pContext->m_fRoot = true;
- }
-
- // Determine if this was really a virtual call (we discard those since we can't reliably determine the call target).
- bool fNonVirtualCall = dwOp == CEE_CALL || !pCallTarget->m_pMethodDesc->IsVirtual() || pCallTarget->m_pMethodDesc->IsFinal();
-
- // When we're only processing qualified catch / finally handlers then we need to compute whether this call site
- // lands in one of them. The callsite is always within a cer if we are processing the full method.
- // If we have stackoverflow probing on, also call to determine if the CER try or finally makes any calls
- bool fCallsiteWithinCerInThisFunction = false;
- if (!m_fEntireMethod || g_pConfig->ProbeForStackOverflow()) {
- DWORD dwOffset = (DWORD)(SIZE_T)((pbIL - 1) - (BYTE*)m_pMethodDecoder->Code);
- fCallsiteWithinCerInThisFunction = CheckIfCallsiteWithinCER(dwOffset);
- }
- bool fCallsiteWithinCer = m_fEntireMethod || fCallsiteWithinCerInThisFunction;
-
- // Check for the presence of some sort of reliability contract (on the method, class or assembly). This will
- // determine whether we log an error, ignore the method or treat it as part of the prepared call graph.
- ReliabilityContractLevel eLevel = RCL_UNKNOWN;
- if (fNonVirtualCall && // Ignore virtual calls
- fCallsiteWithinCer && // And calls outside CERs
- !m_sAlreadySeen.IsInStack(pCallTarget) && // And methods we've seen before
- !m_sLeftToProcess.IsInStack(pCallTarget) && // And methods we've already queued for processing
- (eLevel = CheckForReliabilityContract(pCallTarget->m_pMethodDesc)) >= RCL_PREPARE_CONTRACT) // And unreliable methods
- m_sLeftToProcess.Push(pCallTarget); // Otherwise add this method to the list to process
- else if (fCallsiteWithinCer) {
-#if defined(_DEBUG) || defined(MDA_SUPPORTED)
- DWORD dwOffset = (DWORD)(SIZE_T)((pbIL - 1) - (BYTE*)m_pMethodDecoder->Code);
-#endif // defined(_DEBUG) || defined(MDA_SUPPORTED)
- if (eLevel == RCL_NO_CONTRACT) {
- // Method was sufficiently unreliable for us to warn interested users that something may be amiss. Do this
- // through MDA logging.
-#ifdef MDA_SUPPORTED
- MDA_TRIGGER_ASSISTANT(InvalidCERCall, ReportViolation(pContext->m_pMethodDesc, pCallTarget->m_pMethodDesc, dwOffset));
-#endif
- CER_LOG(WARNINGS, ("CER: %s +%04X -> %s: weak contract\n", pContext->ToString(), dwOffset, pCallTarget->ToString()));
- } else if (!fNonVirtualCall && !m_fIgnoreVirtualCERCallMDA) {
- // Warn users about virtual calls in CERs (so they can go back and consider which target methods need to be
- // prepared ahead of time).
-#ifdef MDA_SUPPORTED
- MDA_TRIGGER_ASSISTANT(VirtualCERCall, ReportViolation(pContext->m_pMethodDesc, pCallTarget->m_pMethodDesc, dwOffset));
-#endif
- CER_LOG(WARNINGS, ("CER: %s +%04X -> %s: virtual call\n", pContext->ToString(), dwOffset, pCallTarget->ToString()));
- }
- }
- }
-
- // Skip the rest of the current IL instruction. Look up the table built statically at the top of this module for most
- // instructions, but CEE_SWITCH requires special processing (the length of that instruction depends on a count DWORD
- // embedded right after the opcode).
- if (dwOp == CEE_SWITCH) {
- DWORD dwTargets = GET_UNALIGNED_VAL32(pbIL);
- if (dwTargets >= (MAXDWORD / sizeof(DWORD)))
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT); // multiplication below would overflow
- DWORD cbSwitch = (1 + dwTargets) * sizeof(DWORD);
- if (cbIL < cbSwitch)
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
- pbIL += cbSwitch;
- cbIL -= cbSwitch;
- } else {
- if (dwOp >= _countof(g_rOpArgs))
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
- DWORD cbOp = g_rOpArgs[dwOp];
- if (cbIL < cbOp)
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
- pbIL += cbOp;
- cbIL -= cbOp;
- }
-
- } // End of IL parsing loop
-}
-
-void MethodCallGraphPreparer::PrepareMethods()
-{
- STANDARD_VM_CONTRACT;
-
-#ifdef _DEBUG
- DWORD dwCount = 0;
- if (GetCerLoggingOptions())
- {
- CER_LOG(PREPARE, ("---------------------------------------------------------------\n"));
- SString ssMethod;
- TypeString::AppendMethodInternal(ssMethod, m_pRootMD, TypeString::FormatNamespace | TypeString::FormatStubInfo);
- CER_LOG(PREPARE, ("Preparing from %S\n", ssMethod.GetUnicode()));
- }
-#endif
-
- MethodContext *pContext; // The current MethodContext we're processing
-
- while ((pContext = m_sAlreadySeen.Pop()) != NULL) {
- MethodDesc *pMD = pContext->m_pMethodDesc;
-
-#ifndef CROSSGEN_COMPILE
- // Jitting. Don't need to do this for the ngen case.
-#ifdef FEATURE_NATIVE_IMAGE_GENERATION
- if (!m_fNgen)
-#endif
- {
- // Also skip the jit for the root method in the activated from jit case (where this would result in a recursive
- // jit). We'd cope with this just fine, the main reason for this logic is to avoid unbalancing some profiler event
- // counts that upset some of our test cases. This is safe in the face of multiple instantiations of the same method
- // because in the jit activated case (where we're told the root type context is not exact) we early exit if the root
- // method desc isn't 'unique' (i.e. independent of the type context).
- if (m_fExactTypeContext || pMD != m_pRootMD) {
-
- // Jit the method we traced.
- if (pMD->IsPointingToPrestub())
- {
- pMD->EnsureActive();
- pMD->DoPrestub(NULL);
- }
-
- // If we traced an instantiating stub we need to jit the wrapped (real) method as well.
- if (pMD->IsInstantiatingStub()) {
- _ASSERTE(!pMD->ContainsGenericVariables());
- MethodDesc *pRealMD = pMD->GetWrappedMethodDesc();
- if (pRealMD->IsPointingToPrestub())
- {
- pMD->EnsureActive();
- pRealMD->DoPrestub(NULL);
- }
- }
- }
-
- // Remember sub-CER root methods for further processing in RecordResults. We need to build CerPrepInfo structures for
- // these just the same as top-level CERs since we may wander in to them by a route that doesn't include the top-level CER
- // and the thread abort deflection algorithm relies on each CER root method being marked by a CerPrepInfo. Defer this
- // processing to RecordResults since we aren't guaranteed to have prepared all the methods of the sub-graph at this
- // point.
- if (pContext->m_fRoot && pMD != m_pRootMD)
- m_sPersist.Push(pContext);
- }
-#endif // CROSSGEN_COMPILE
-
- // Prepare generic dictionaries (both class and method as needed). We do this even in the ngen scenario, trying to get
- // as many slots filled as possible. By the looks of it, it's possible that not all of these entries will make it across
- // to runtime (the fixup code seems to give up on some of the more complex entries, not sure of the details). But we'll
- // do as best we can here to hopefully minimize any real work on the other side.
-
- // Don't use the direct PrepopulateDictionary method on MethodTable here, it takes binding considerations into account
- // (which we don't care about).
- DictionaryLayout *pClassDictLayout = pMD->GetClass()->GetDictionaryLayout();
- if (pClassDictLayout) {
- // Translate the representative method table we can find from our method desc into an exact instantiation using the
- // type context we have.
- MethodTable *pMT = TypeHandle(pMD->GetMethodTable()).Instantiate(pContext->m_sTypeContext.m_classInst).AsMethodTable();
-
- pMT->GetDictionary()->PrepopulateDictionary(NULL, pMT, false);
-
- // The dictionary may have overflowed in which case we need to prepopulate the jit's lookup cache as well.
- PrepopulateGenericHandleCache(pClassDictLayout, NULL, pMT);
- }
-
- // Don't use the direct PrepopulateDictionary method on MethodDesc here, it appears to use a representative class
- // instantiation (and we have the exact one handy).
- DictionaryLayout *pMethDictLayout = pMD->GetDictionaryLayout();
- if (pMethDictLayout) {
- pMD->GetMethodDictionary()->PrepopulateDictionary(pMD, NULL, false);
-
- // The dictionary may have overflowed in which case we need to prepopulate the jit's lookup cache as well.
- PrepopulateGenericHandleCache(pMethDictLayout, pMD, NULL);
- }
-
-#ifdef FEATURE_NATIVE_IMAGE_GENERATION
- // Keep some of the method contexts around for the ngen case (the ones that might still need fixup at runtime). We'll
- // write them into a persisted data structure in the next step.
- // @todo: We use a horrible workaround here to get round the fact that while ngen'ing mscorlib we may prepare some of its
- // methods before we've had a chance to start up the compilation domain (mscorlib code is shared and used by the ngen
- // process itself). So we can't blindly call NeedsRestore() on an mscorlib method since that code asserts we're in the
- // compilation domain. Instead, if we're in the ngen process and we're outside the compilation domain we're going to
- // assume that the method doesn't need restoration. This only affects a handful of methods (six at last count, all to do
- // with security safe handles or some CERs in remoting).
- if (m_fNgen) {
- if (GetAppDomain() == NULL ||
- !GetAppDomain()->IsCompilationDomain() ||
- !(GetAppDomain()->ToCompilationDomain()->canCallNeedsRestore()) ||
- !(GetAppDomain()->ToCompilationDomain()->GetTargetImage()->CanPrerestoreEagerBindToMethodDesc(pMD, NULL))||
- pMD->HasClassOrMethodInstantiation() ||
- pMD->IsNDirect() ||
- pMD->IsComPlusCall() ||
- pMD->IsFCall() ||
- pContext->m_fRoot)
- m_sPersist.Push(pContext);
- }
-#endif
-
-#ifdef _DEBUG
- CER_LOG(PREPARE, (" %s\n", pContext->ToString()));
- dwCount++;
-#endif
- }
-
-#ifdef _DEBUG
- CER_LOG(PREPARE, ("Prepared a total of %u methods\n", dwCount));
-#ifdef FEATURE_NATIVE_IMAGE_GENERATION
- if (m_fNgen)
- CER_LOG(PREPARE, ("Saved data for %u of them in the ngen image\n", m_sPersist.GetCount()));
-#endif
- CER_LOG(PREPARE, ("---------------------------------------------------------------\n"));
-#endif
-}
-
-// Common code used in creating/looking up a CerPrepInfo and initializing/updating it.
-void InitPrepInfo(MethodDesc *pMD, SigTypeContext *pTypeContext, bool fMethodHasCallsWithinExplicitCer)
-{
- CONTRACTL {
- STANDARD_VM_CHECK;
- PRECONDITION(CheckPointer(pMD));
- } CONTRACTL_END;
-
- // Lookup or allocate the CerPrepInfo.
- CerPrepInfo *pInfo = pMD->GetModule()->CreateCerPrepInfo(pMD);
-
- pInfo->m_fMethodHasCallsWithinExplicitCer = fMethodHasCallsWithinExplicitCer;
-
- // Work out if this was a partial preparation.
- bool fPartialPreparation = pMD->IsSharedByGenericInstantiations() ||
- pMD->IsInstantiatingStub() ||
- pMD->ContainsGenericVariables();
-
- // Simple case first: if this isn't a partial preparation (no pesky unbound type vars to worry about), then the method is
- // now fully prepared.
- if (!fPartialPreparation) {
- pInfo->m_fFullyPrepared = true;
- return;
- }
-
- // Else we know we require per-instantiation initialization. We need to update a hash table to record the preparation we did
- // in this case, and that requires taking a mutex. We could check that nobody beat us to it first, but that will hardly ever
- // happen, so it's not really worth it. So just acquire the mutex right away.
- CrstHolder sHolder(pMD->GetModule()->GetCerCrst());
-
- pInfo->m_fRequiresInstantiation = true;
-
- // Add an entry to a hash that records which instantiations we've prep'd for (again, only if someone hasn't beaten us).
- HashDatum sDatum;
- if (!pInfo->m_sIsInitAtInstHash.GetValue(pTypeContext, &sDatum))
- {
- pInfo->m_sIsInitAtInstHash.InsertKeyAsValue(pTypeContext);
- }
-}
-
-bool MethodCallGraphPreparer::RecordResults()
-{
- STANDARD_VM_CONTRACT;
-
- // Preparation has been successful, record what we've done in a manner consistent with whether we're ngen'ing or running for
- // real.
-
-#ifdef FEATURE_NATIVE_IMAGE_GENERATION
- // If we're ngen'ing an image we save our progess as a list of method contexts that might need restoration at runtime (since
- // even with prejitting there are some things that need to be prepared at runtime). This list goes into a per module table (the
- // module in question being that of the root method in the CER).
- if (m_fNgen) {
-
- // We have the list of MethodContexts ready, but they're in cheap storage that will go away once we exit this method.
- // Not only do we have to copy them to heap memory, but we also know exactly how many there are. So we can allocate a
- // single array with a more compact form of MethodContext for each element. We allocate an extra sentinel value for the end
- // of the list. This means we can store just a pointer to the list without a count (the code that accesses this list cares
- // about keeping the list heads compact and densely packed and doesn't care about counting the elements in the list).
- DWORD cContexts = m_sPersist.GetCount();
- LoaderHeap *pHeap = m_pRootMD->GetAssembly()->GetLowFrequencyHeap();
- MethodContextElement *pContexts = (MethodContextElement*)(void*)pHeap->AllocMem(S_SIZE_T(sizeof(MethodContextElement)) * (S_SIZE_T(cContexts) + S_SIZE_T(1)));
- DWORD i = 0;
-
- MethodContext *pContext; // The current MethodContext we're processing
- while ((pContext = m_sPersist.Pop()) != NULL) {
- pContexts[i].m_pMethodDesc.SetValue(pContext->m_pMethodDesc);
-
- MethodTable * pExactMT = NULL;
- if (!pContext->m_sTypeContext.m_classInst.IsEmpty())
- {
- pExactMT = TypeHandle(pContext->m_pMethodDesc->GetMethodTable()).Instantiate(pContext->m_sTypeContext.m_classInst).AsMethodTable();
- _ASSERTE(pExactMT->HasInstantiation());
- }
- else
- {
- _ASSERTE(!pContext->m_pMethodDesc->GetMethodTable()->HasInstantiation());
- }
- pContexts[i].m_pExactMT.SetValue(pExactMT);
-
- i++;
-
- // Keep the context round for a little longer if the method in question was the root of a sub-CER.
- if (pContext->m_fRoot)
- m_sRootMethods.Push(pContext);
- }
-
- // Write sentinel entry terminating list.
- _ASSERTE(i == cContexts);
-
- // Add list representing this CER to the per-module table (keyed by root method desc).
- m_pRootMD->GetModule()->AddCerListToRootTable(m_pRootMD, pContexts);
-
- // If this did have an call from an explicit PCER range, create a PrepInfo for it so that we can
- // quickly grab that information later when we jit that method. This allows us to optimize the probe
- // away if there are no calls from the PCER range. This is an issue when we've prepared a method
- // as part of a CER call from another method, but haven't ngened that method yet. When we get
- // around to finally ngening that method, we want to be able to optimize the CER probe out if
- // we can, but don't want to reprepare the method.
- if (g_pConfig->ProbeForStackOverflow() && m_fMethodHasCallsWithinExplicitCer)
- {
- if (m_pCerPrepInfo == NULL)
- m_pCerPrepInfo = m_pRootMD->GetModule()->CreateCerPrepInfo(m_pRootMD);
- m_pCerPrepInfo->m_fMethodHasCallsWithinExplicitCer = TRUE;
- }
-
-
- // We need to be careful with sub-CERs in the ngen case. In the jit case they're dealt with automatically (preparing a
- // super-CER always completely prepares a sub-CER). But in the ngen case we potentially need to run further preparation
- // steps at the point that a CER root is executed for the first time. If the sub-root is encountered before the super-root
- // then the sub-CER won't have been prepared correctly.
- // We solve this simply by recursively running this routine over the methods we noted were sub-roots earlier (this list
- // doesn't include the main root). We could potentially do a little better than this given that we've calculated the
- // super-graph, but this is complicated somewhat by the fact that we don't retain the graph structure (i.e. we can't extract
- // sub-graphs easily) and the effort seems wasted just to avoid a little CPU time and stack space just for the ngen creation
- // scenario.
- while ((pContext = m_sRootMethods.Pop()) != NULL)
- {
- MethodCallGraphPreparer mgcp(pContext->m_pMethodDesc, &pContext->m_sTypeContext, false, false);
- mgcp.Run();
- }
-
- return m_fMethodHasCallsWithinExplicitCer;
- }
-#endif // FEATURE_NATIVE_IMAGE_GENERATION
-
- // This is the runtime (non-ngen case). Record our progress in an info structure placed in a hash table hung off the module
- // which owns the root method desc in the CER. The methods which create this info structure handle race conditions (to
- // ensure we don't leak memory or data), but the updates to the info structure itself might not require any serialization
- // (the values are 'latched' -- recomputation should yield the same result). The exception is any update to a more complex
- // data fields (lists and hash tables) that require serialization to prevent corruption of the basic data structure.
-
- // Process sub-CER roots first. We need to build CerPrepInfo structures for these just as same as top-level CERs since we may
- // wander in to them by a route that doesn't include the top-level CER and the thread abort deflection algorithm relies on each
- // CER root method being marked by a CerPrepInfo.
- MethodContext *pContext;
- while ((pContext = m_sPersist.Pop()) != NULL) {
- _ASSERTE(pContext->m_fRoot);
-
- // @todo: need to flow fMethodHasCallsWithinExplicitCer information through method contexts. For now just make a
- // conservative, safe choice.
- InitPrepInfo(pContext->m_pMethodDesc, &pContext->m_sTypeContext, true);
- }
-
- // Now process the top-level CER.
- InitPrepInfo(m_pRootMD, m_pRootTypeContext, m_fMethodHasCallsWithinExplicitCer);
-
- return m_fMethodHasCallsWithinExplicitCer;
-}
-
-// Determines whether the given method contains a CER root that can be pre-prepared (i.e. prepared at jit time).
-bool ContainsPrePreparableCerRoot(MethodDesc *pMD)
-{
- CONTRACTL {
- STANDARD_VM_CHECK;
- PRECONDITION(CheckPointer(pMD));
- } CONTRACTL_END;
-
- // Deal with exotic cases (non-IL methods and the like).
- if (!pMD->IsIL() || pMD->IsAbstract())
- return false;
-
- // And cases where we can't jit prepare (because the code is shared between instantiations).
- if (pMD->IsSharedByGenericInstantiations() || pMD->IsInstantiatingStub() || pMD->ContainsGenericVariables())
- return false;
-
- // Otherwise we have a trickier calculation. We don't want to force the jit of the method at this point (may cause infinite
- // recursion problems when we're called from the jit in the presence of call cycles). Instead we walk the top-level of the
- // method IL using the same algorithm as PrepareMethodCallGraph.
-
- // Locate the IL body of the current method. May have to account for the fact that the current method desc is an
- // instantiating stub and burrow down for the real method desc.
- MethodDesc *pRealMethod = pMD;
- if (pRealMethod->IsInstantiatingStub()) {
- _ASSERTE(!pRealMethod->ContainsGenericVariables());
- pRealMethod = pRealMethod->GetWrappedMethodDesc();
- }
- COR_ILMETHOD_DECODER method(pRealMethod->GetILHeader());
- BYTE *pbIL = (BYTE*)method.Code;
- DWORD cbIL = method.GetCodeSize();
-
- // Look for exception handling information for the method. If there isn't any then we know there can't be a CER rooted here.
- COR_ILMETHOD_SECT_EH const * pEH = method.EH;
- if (pEH == NULL || pEH->EHCount() == 0)
- return false;
-
- // Iterate through the body of the method looking for interesting call sites.
- while (cbIL) {
-
- // Read the IL op.
- DWORD dwOp = *pbIL++; cbIL--;
-
- // Handle prefix codes (only CEE_PREFIX1 is legal so far).
- if (dwOp == CEE_PREFIX1) {
- if (!cbIL)
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
- dwOp = 256 + *pbIL++; cbIL--;
- if (dwOp >= CEE_ILLEGAL)
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
- } else if (dwOp >= CEE_PREFIX7)
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
-
- // We'll only ever see CALL instructions targeting PrepareConstrainedRegions (well those are the ones we're interested in
- // anyway).
- if (dwOp == CEE_CALL)
- {
- if (cbIL < sizeof(DWORD))
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
- if (IsPcrReference(pMD->GetModule(), (mdToken)GET_UNALIGNED_VAL32(pbIL)))
- return true;
- }
-
- // Skip the rest of the current IL instruction. Look up the table built statically at the top of this module for most
- // instructions, but CEE_SWITCH requires special processing (the length of that instruction depends on a count DWORD
- // embedded right after the opcode).
- if (dwOp == CEE_SWITCH) {
- if (cbIL < sizeof(DWORD))
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
- DWORD dwTargets = GET_UNALIGNED_VAL32(pbIL);
- if (dwTargets >= (MAXDWORD / sizeof(DWORD)))
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT); // multiplication below would overflow
- DWORD cbSwitch = (1 + dwTargets) * sizeof(DWORD);
- if (cbIL < cbSwitch)
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
- pbIL += cbSwitch;
- cbIL -= cbSwitch;
- } else {
- if (dwOp >= _countof(g_rOpArgs))
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
- DWORD cbOp = g_rOpArgs[dwOp];
- if (cbIL < cbOp)
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
- pbIL += cbOp;
- cbIL -= cbOp;
- }
-
- } // End of IL parsing loop
-
- // If we get here then there was no CER-root.
- return false;
-}
-
-// The name of the PrepareConstrainedRegions method, broken down into its components (the code below scans for these directly in the
-// metadata).
-#define PCR_METHOD "PrepareConstrainedRegions"
-#define PCR_TYPE "RuntimeHelpers"
-#define PCR_NAMESPACE "System.Runtime.CompilerServices"
-
-// Given a token and a module scoping it, determine if that token is a reference to PrepareConstrainedRegions. We want to do this
-// without loading any random types since we're called in a context where type loading is prohibited.
-bool IsPcrReference(Module *pModule, mdToken tkMethod)
-{
- CONTRACTL {
- STANDARD_VM_CHECK;
- PRECONDITION(CheckPointer(pModule));
- } CONTRACTL_END;
-
- IMDInternalImport *pImport = pModule->GetMDImport();
-
- // Validate that the token is one that we can handle.
- if (!pImport->IsValidToken(tkMethod) || (TypeFromToken(tkMethod) != mdtMethodDef &&
- TypeFromToken(tkMethod) != mdtMethodSpec &&
- TypeFromToken(tkMethod) != mdtMemberRef))
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_METHOD_TOKEN);
-
- // No reason to see a method spec for a call to something as simple as PrepareConstrainedRegions.
- if (TypeFromToken(tkMethod) == mdtMethodSpec)
- return false;
-
- // If it's a method def then the module had better be mscorlib.
- if (TypeFromToken(tkMethod) == mdtMethodDef) {
- if (pModule->GetAssembly()->GetManifestModule() == SystemDomain::SystemAssembly()->GetManifestModule())
- return tkMethod == g_pPrepareConstrainedRegionsMethod->GetMemberDef();
- else
- return false;
- }
-
- // That leaves the cross module reference case.
- _ASSERTE(TypeFromToken(tkMethod) == mdtMemberRef);
-
- // First get the method name and signature and validate it.
- PCCOR_SIGNATURE pSig;
- DWORD cbSig;
- LPCSTR szMethod;
- IfFailThrow(pImport->GetNameAndSigOfMemberRef(tkMethod, &pSig, &cbSig, &szMethod));
-
- {
- SigParser sig(pSig, cbSig);
- ULONG nCallingConvention;
- ULONG nArgumentsCount;
- BYTE bReturnType;
-
- // Signature is easy: void PCR().
- // Must be a static method signature.
- if (FAILED(sig.GetCallingConvInfo(&nCallingConvention)))
- return false;
- if (nCallingConvention != IMAGE_CEE_CS_CALLCONV_DEFAULT)
- return false;
- // With no arguments.
- if (FAILED(sig.GetData(&nArgumentsCount)))
- return false;
- if (nArgumentsCount != 0)
- return false;
- // And a void return type.
- if (FAILED(sig.GetByte(&bReturnType)))
- return false;
- if (bReturnType != (BYTE)ELEMENT_TYPE_VOID)
- return false;
- }
-
- // Validate the name.
- if (strcmp(szMethod, PCR_METHOD) != 0)
- return false;
-
- // The method looks OK, move up to the type and validate that.
- mdToken tkType;
- IfFailThrow(pImport->GetParentOfMemberRef(tkMethod, &tkType));
-
- if (!pImport->IsValidToken(tkType))
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_TOKEN);
-
- // If the parent is not a type ref then this isn't our target (we assume that mscorlib never uses a member ref to target
- // PrepareConstrainedRegions, check that with the assert below, if it ever fails we need to add some additional logic below).
- _ASSERTE(TypeFromToken(tkType) != mdtTypeDef ||
- pModule->GetAssembly()->GetManifestModule() != SystemDomain::SystemAssembly()->GetManifestModule());
- if (TypeFromToken(tkType) != mdtTypeRef)
- return false;
-
- // Get the type name and validate it.
- LPCSTR szNamespace;
- LPCSTR szType;
- IfFailThrow(pImport->GetNameOfTypeRef(tkType, &szNamespace, &szType));
-
- if (strcmp(szType, PCR_TYPE) != 0)
- return false;
- if (strcmp(szNamespace, PCR_NAMESPACE) != 0)
- return false;
-
- // Type is OK as well. Check the assembly reference.
- mdToken tkScope;
- IfFailThrow(pImport->GetResolutionScopeOfTypeRef(tkType, &tkScope));
-
- if (TypeFromToken(tkScope) != mdtAssemblyRef)
- return false;
- if (!pImport->IsValidToken(tkScope))
- {
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_TOKEN);
- }
-
- // Fetch the name and public key or public key token.
- BYTE *pbPublicKeyOrToken;
- DWORD cbPublicKeyOrToken;
- LPCSTR szAssembly;
- DWORD dwAssemblyFlags;
- IfFailThrow(pImport->GetAssemblyRefProps(
- tkScope,
- (const void**)&pbPublicKeyOrToken,
- &cbPublicKeyOrToken,
- &szAssembly,
- NULL, // AssemblyMetaDataInternal: we don't care about version, culture etc.
- NULL, // Hash value pointer, obsolete information
- NULL, // Byte count for above
- &dwAssemblyFlags));
-
- // Validate the name.
- if (stricmpUTF8(szAssembly, g_psBaseLibraryName) != 0)
- return false;
-
- // And the public key or token, which ever was burned into the reference by the compiler. For mscorlib this is the ECMA key or
- // token.
- if (IsAfPublicKeyToken(dwAssemblyFlags)) {
- if (cbPublicKeyOrToken != sizeof(g_rbNeutralPublicKeyToken) ||
- memcmp(pbPublicKeyOrToken, g_rbNeutralPublicKeyToken, cbPublicKeyOrToken) != 0)
- return false;
- } else {
- if (cbPublicKeyOrToken != sizeof(g_rbNeutralPublicKey) ||
- memcmp(pbPublicKeyOrToken, g_rbNeutralPublicKey, cbPublicKeyOrToken) != 0)
- return false;
- }
-
- // If we get here we've finally proved the call target was indeed PrepareConstrainedRegions. Whew.
- return true;
-}
-
-// Prepares a method as a CER root. In some scenarios we set
-// fIgnoreVirtualCERCallMDA=TRUE, this happens when we want to ignore firing a
-// VirtualCERCall MDA because we know for sure that the virtual methods are
-// already prepared. A good example of this case is preparing
-// g_pExecuteBackoutCodeHelperMethod method.
-void PrepareMethodDesc(MethodDesc* pMD, Instantiation classInst, Instantiation methodInst, BOOL onlyContractedMethod, BOOL fIgnoreVirtualCERCallMDA)
-{
- CONTRACTL
- {
- THROWS;
- DISABLED(GC_TRIGGERS);
- MODE_ANY;
- }
- CONTRACTL_END;
-
- GCX_PREEMP();
-
-#ifdef FEATURE_PREJIT
- // This method may have some ngen fixup information provided, in which case we just check that it's been restored and can
- // dispense with the preparation altogether.
- Module *pModule = pMD->GetModule();
- if (pModule->IsNgenCerRootMethod(pMD))
- {
- pMD->CheckRestore();
- pModule->RestoreCer(pMD);
- return;
- }
-#endif
-
- // If we are only going to prepare contracted methods and this method does
- // not have a contract then we just return.
- if (onlyContractedMethod && CheckForReliabilityContract(pMD) < RCL_BASIC_CONTRACT)
- {
- return;
- }
-
- SigTypeContext sTypeContext(pMD, classInst, methodInst);
- MethodCallGraphPreparer mcgp(pMD, &sTypeContext, true, true, fIgnoreVirtualCERCallMDA == TRUE);
- mcgp.Run();
-}
-
-// Prepares the critical finalizer call graph for the given object type (which
-// must derive from CriticalFinalizerObject). This involves preparing at least
-// the finalizer method and possibly some others (for SafeHandle and
-// CriticalHandle derivations). If a module pointer is supplied then only the
-// critical methods introduced in that module are prepared (this is used at
-// ngen time to ensure that we're only generating ngen preparation info for the
-// targetted module).
-void PrepareCriticalFinalizerObject(MethodTable *pMT, Module *pModule)
-{
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(pMT));
- } CONTRACTL_END;
-
- // Have we prepared this type before?
- if (pMT->CriticalTypeHasBeenPrepared())
- return;
-
- GCX_PREEMP();
-
- // Restore the method table if necessary.
- pMT->CheckRestore();
-
- // Determine the interesting parent class (either SafeHandle, CriticalHandle or CriticalFinalizerObject).
- MethodTable *pSafeHandleClass = MscorlibBinder::GetClass(CLASS__SAFE_HANDLE);
- MethodTable *pCriticalHandleClass = MscorlibBinder::GetClass(CLASS__CRITICAL_HANDLE);
- MethodTable *pParent = pMT;
- while (pParent) {
- if (pParent == g_pCriticalFinalizerObjectClass ||
- pParent == pSafeHandleClass ||
- pParent == pCriticalHandleClass) {
- break;
- }
- pParent = pParent->GetParentMethodTable();
- }
- _ASSERTE(pParent != NULL);
-
- BinderMethodID rgMethods[5];
- int nMethods;
-
- // Prepare the method or methods based on the parent class.
- if (pParent == pSafeHandleClass) {
- rgMethods[0] = METHOD__CRITICAL_FINALIZER_OBJECT__FINALIZE;
- rgMethods[1] = METHOD__SAFE_HANDLE__RELEASE_HANDLE;
- rgMethods[2] = METHOD__SAFE_HANDLE__GET_IS_INVALID;
- rgMethods[3] = METHOD__SAFE_HANDLE__DISPOSE;
- rgMethods[4] = METHOD__SAFE_HANDLE__DISPOSE_BOOL;
- nMethods = 5;
- } else if (pParent == pCriticalHandleClass) {
- rgMethods[0] = METHOD__CRITICAL_FINALIZER_OBJECT__FINALIZE;
- rgMethods[1] = METHOD__CRITICAL_HANDLE__RELEASE_HANDLE;
- rgMethods[2] = METHOD__CRITICAL_HANDLE__GET_IS_INVALID;
- rgMethods[3] = METHOD__CRITICAL_HANDLE__DISPOSE;
- rgMethods[4] = METHOD__CRITICAL_HANDLE__DISPOSE_BOOL;
- nMethods = 5;
- } else {
- _ASSERTE(pParent == g_pCriticalFinalizerObjectClass);
- rgMethods[0] = METHOD__CRITICAL_FINALIZER_OBJECT__FINALIZE;
- nMethods = 1;
- }
-
- for (int iMethod = 0; iMethod < nMethods; iMethod++)
- {
- // Prepare a (possibly virtual) method on an instance. The method is identified via a binder ID, so the initial
- // declaration of the method must reside within mscorlib. We might have ngen fixup information for the method and can avoid direct
- // preparation as well.
-
- MethodDesc *pPrepMethod = pMT->GetMethodDescForSlot(MscorlibBinder::GetMethod(rgMethods[iMethod])->GetSlot());
-#ifdef FEATURE_PREJIT
- if (pPrepMethod->GetModule()->IsNgenCerRootMethod(pPrepMethod)) {
- pPrepMethod->GetModule()->RestoreCer(pPrepMethod);
- }
- else
- if (IsCompilationProcess() && pPrepMethod->IsAbstract()) {
- // Skip abstract methods during NGen (we should not ever get abstract methods here at runtime)
- }
- else
-#endif
- {
- if (pModule == NULL || pPrepMethod->GetModule() == pModule) {
- SigTypeContext _sTypeContext(pPrepMethod, TypeHandle(pMT));
- MethodCallGraphPreparer mcgp(pPrepMethod, &_sTypeContext, true, true);
- mcgp.Run();
- }
- }
- }
-
- // Note the fact that we've prepared this type before to prevent repetition of the work above. (Though repetition is harmless in
- // all other respects, so there's no need to worry about the race setting this flag).
- pMT->SetCriticalTypeHasBeenPrepared();
-}
-
-#ifdef _DEBUG
-
-static const char * const g_rszContractNames[] = { "RCL_NO_CONTRACT", "RCL_BASIC_CONTRACT", "RCL_PREPARE_CONTRACT" };
-static DWORD g_dwContractChecks = 0;
-
-#define ReturnContractLevel(_level) do { \
- g_dwContractChecks++; \
- if ((g_dwContractChecks % 100) == 0 && g_pMethodContractCache) \
- g_pMethodContractCache->DbgDumpStats(); \
- ReliabilityContractLevel __level = (_level); \
- CER_LOG(CONTRACTS, ("%s -- %s\n", pMD->m_pszDebugMethodName, g_rszContractNames[__level])); \
- return __level; \
-} while (false)
-#else
-#define ReturnContractLevel(_level) return (_level)
-#endif
-
-// Look for reliability contracts at the method, class and assembly level and parse them to extract the information we're interested
-// in from a runtime preparation viewpoint. This information is abstracted in the form of the ReliabilityContractLevel enumeration.
-ReliabilityContractLevel CheckForReliabilityContract(MethodDesc *pMD)
-{
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pMD));
- } CONTRACTL_END;
-
- // We are attempting to abstract reliability contracts for the given method into three different buckets: those methods that
- // will cause an error (or a MDA report at least) during preparation (RCL_NO_CONTRACT), those we allow but don't prepare
- // (RCL_BASIC_CONTRACT) and those we allow and prepare (RCL_PREPARE_CONTRACT).
- //
- // We place methods into the first bucket below that matches:
- // RCL_NO_CONTRACT -- Methods with no consistency or whose consistency states they may corrupt the appdomain or process.
- // RCL_BASIC_CONTRACT -- Methods that state CER.None (or don't specify a CER attribute)
- // RCL_PREPARE_CONTRACT -- Methods that state CER.MayFail or CER.Success
- //
- // We look for reliability contracts at three levels: method, class and assembly. Definitions found at the method level override
- // those at the class and assembly level and those at the class level override assembly settings.
- //
- // In the interests of efficiency we cache contract information in a number of ways. Firstly we look at a hash of recently
- // queried MethodDescs. This contains authoritative answers (assembly/class/method information has already been composed so on a
- // hit we don't need to look anywhere else). This cache is allocated lazily, never grows (newer items eventually displace older
- // ones), is global, requires no locks and is never freed. The idea is to limit the amount of working set we ever occupy while
- // keeping the CPU usage as low as possible. Typical usages of this method involve querying a small number of methods in a stack
- // walk, possibly multiple times, so a small hash cache should work reasonably well here.
- //
- // On a miss we're going to have to bite the bullet and look at the assembly, class and method. The assembly and class cache
- // this information at load (ngen) time though, so they're not so expensive (class level data is cached on the EEClass, so it's
- // cold data, but the most performance sensitive scenario in which we're called here, ThreadAbort, isn't all that hot).
-
- // Check the cache first, it contains a raw contract level.
- ReliabilityContractLevel eLevel;
- if (g_pMethodContractCache && g_pMethodContractCache->Lookup(pMD, (DWORD*)&eLevel))
- ReturnContractLevel(eLevel);
-
- // Start at the method level and work up until we've found enough information to make a decision. The contract level is composed
- // in an encoded DWORD form that lets us track both parts of the state (consistency and cer) and whether each has been supplied
- // yet. See the RC_* macros for encoding details.
- DWORD dwMethodContractInfo = GetReliabilityContract(pMD->GetMDImport(), pMD->GetMemberDef());
- if (RC_INCOMPLETE(dwMethodContractInfo)) {
- DWORD dwClassContractInfo = pMD->GetClass()->GetReliabilityContract();
- dwMethodContractInfo = RC_MERGE(dwMethodContractInfo, dwClassContractInfo);
- if (RC_INCOMPLETE(dwMethodContractInfo)) {
- DWORD dwAssemblyContractInfo = pMD->GetModule()->GetReliabilityContract();
- dwMethodContractInfo = RC_MERGE(dwMethodContractInfo, dwAssemblyContractInfo);
- }
- }
-
- // We've got an answer, so attempt to cache it for the next time.
-
- // First check we have a cache (we allocate it lazily).
- if (g_pMethodContractCache == NULL) {
- PtrHashCache *pCache = new (nothrow) PtrHashCache();
- if (pCache)
- if (FastInterlockCompareExchangePointer(&g_pMethodContractCache, pCache, NULL) != NULL)
- delete pCache;
- }
-
- // We still might not have a cache in low memory situations. That's OK.
- if (g_pMethodContractCache)
- g_pMethodContractCache->Add(pMD, RC_ENCODED_TO_LEVEL(dwMethodContractInfo));
-
- ReturnContractLevel(RC_ENCODED_TO_LEVEL(dwMethodContractInfo));
-}
-
-
-// Macro used to handle failures in the routine below.
-#define IfFailRetRcNull(_hr) do { if (FAILED(_hr)) return RC_NULL; } while (false)
-
-// Look for a reliability contract attached to the given metadata token in the given scope. Return the result as an encoded DWORD
-// (see the RC_ENCODE macro).
-DWORD GetReliabilityContract(IMDInternalImport *pImport, mdToken tkParent)
-{
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pImport));
- } CONTRACTL_END;
-
- HRESULT hr;
- DWORD dwResult = RC_NULL;
-
- // Sadly we only have two unmanaged APIs available to us for looking at custom attributes. One looks up attributes by name but
- // only returns the byte blob, not the attribute ctor information (which we need to parse the blob) while the other returns
- // everything but requires us to enumerate all attributes on a given token looking for the one we're interested in. To keep the
- // cost down we probe for the existence of the attribute using the first API and then use the enumeration method if we get a
- // hit.
- hr = pImport->GetCustomAttributeByName(tkParent, RELIABILITY_CONTRACT_NAME, NULL, NULL);
- if (hr == S_FALSE)
- return RC_NULL;
-
- IfFailRetRcNull(hr);
-
- // Got at least one contract against this parent. Enumerate them all (filtering by name).
- MDEnumHolder hEnum(pImport);
- hr = pImport->SafeAndSlowEnumCustomAttributeByNameInit(tkParent, RELIABILITY_CONTRACT_NAME, &hEnum);
- _ASSERTE(hr != S_FALSE);
- IfFailRetRcNull(hr);
-
- // Enumerate over all the contracts.
- mdToken tkContract;
- while (S_OK == pImport->SafeAndSlowEnumCustomAttributeByNameNext(tkParent, RELIABILITY_CONTRACT_NAME, &hEnum, &tkContract)) {
-
- // Get the attribute type (token of the ctor used) since we need this information in order to parse the blob we'll find
- // next.
- mdToken tkAttrType;
- IfFailRetRcNull(pImport->GetCustomAttributeProps(tkContract, &tkAttrType));
- if (!pImport->IsValidToken(tkAttrType))
- continue;
-
- // The token should be a member ref or method def.
- // Get the signature of the ctor so we know which version has been called.
- PCCOR_SIGNATURE pSig;
- DWORD cbSig;
- LPCSTR szName_Ignore;
- if (TypeFromToken(tkAttrType) == mdtMemberRef)
- {
- IfFailRetRcNull(pImport->GetNameAndSigOfMemberRef(tkAttrType, &pSig, &cbSig, &szName_Ignore));
- }
- else
- {
- if (TypeFromToken(tkAttrType) != mdtMethodDef)
- continue;
- IfFailRetRcNull(pImport->GetNameAndSigOfMethodDef(tkAttrType, &pSig, &cbSig, &szName_Ignore));
- }
-
- // Only two signatures are supported: the null sig '()' and the full sig '(Consistency, CER)'.
- // Set a boolean based on which one was provided.
- bool fNullCtor;
- ULONG eCallConv;
-
- SigPointer sig(pSig, cbSig);
-
- // Check the calling convention is what we expect (default convention on an instance method).
- IfFailRetRcNull(sig.GetCallingConvInfo(&eCallConv));
- _ASSERTE(eCallConv == (IMAGE_CEE_CS_CALLCONV_DEFAULT | IMAGE_CEE_CS_CALLCONV_HASTHIS));
- if (eCallConv != (IMAGE_CEE_CS_CALLCONV_DEFAULT | IMAGE_CEE_CS_CALLCONV_HASTHIS))
- IfFailRetRcNull(COR_E_BADIMAGEFORMAT);
-
- // If so, the next datum is the count of arguments, and this is all we need to determine which ctor has been used.
- ULONG dwArgs;
- IfFailRetRcNull(sig.GetData(&dwArgs));
- _ASSERTE(dwArgs == 0 || dwArgs == 2);
- if (dwArgs != 0 && dwArgs != 2)
- IfFailRetRcNull(COR_E_BADIMAGEFORMAT);
-
- fNullCtor = dwArgs == 0;
-
- // Now we know how to parse the blob, let's fetch a pointer to it.
- BYTE const *pbData;
- DWORD cbData;
- IfFailRetRcNull(pImport->GetCustomAttributeAsBlob(tkContract, (const void **)&pbData, &cbData));
-
- // Check serialization format (we support version 1 only).
- if (cbData < sizeof(WORD) || GET_UNALIGNED_VAL16(pbData) != 1)
- IfFailRetRcNull(COR_E_BADIMAGEFORMAT);
- pbData += sizeof(WORD);
- cbData -= sizeof(WORD);
-
- // Parse ctor arguments if we have any.
- if (!fNullCtor) {
-
- // We assume the enums are based on DWORDS.
- if (cbData < (sizeof(DWORD) * 2))
- IfFailRetRcNull(COR_E_BADIMAGEFORMAT);
-
- // Consistency first.
- DWORD dwConsistency = GET_UNALIGNED_VAL32(pbData);
- pbData += sizeof(DWORD);
- cbData -= sizeof(DWORD);
- if (dwConsistency > RC_CONSISTENCY_CORRUPT_NOTHING)
- IfFailRetRcNull(COR_E_BADIMAGEFORMAT);
-
- // Followed by Cer.
- DWORD dwCer = GET_UNALIGNED_VAL32(pbData);
- pbData += sizeof(DWORD);
- cbData -= sizeof(DWORD);
- if (dwCer > RC_CER_SUCCESS)
- IfFailRetRcNull(COR_E_BADIMAGEFORMAT);
-
- dwResult = RC_MERGE(dwResult, RC_ENCODE(dwConsistency, dwCer));
- }
-
- // Get the count of field/property, value pairs.
- if (cbData < sizeof(WORD))
- IfFailRetRcNull(COR_E_BADIMAGEFORMAT);
- WORD cPairs = GET_UNALIGNED_VAL16(pbData);
- pbData += sizeof(WORD);
- cbData -= sizeof(WORD);
-
- // Iterate over any such pairs, looking for values we haven't picked up yet.
- for (DWORD i = 0 ; i < cPairs; i++) {
-
- // First is a field vs property selector. We expect only properties.
- if (cbData < sizeof(BYTE) || *(BYTE*)pbData != SERIALIZATION_TYPE_PROPERTY)
- IfFailRetRcNull(COR_E_BADIMAGEFORMAT);
- pbData += sizeof(BYTE);
- cbData -= sizeof(BYTE);
-
- // Next is the type of the property. It had better be an enum.
- if (cbData < sizeof(BYTE) || *(BYTE*)pbData != SERIALIZATION_TYPE_ENUM)
- IfFailRetRcNull(COR_E_BADIMAGEFORMAT);
- pbData += sizeof(BYTE);
- cbData -= sizeof(BYTE);
-
- // Next we have the assembly qualified enum type name. This is preceded by a metadata style packed byte length (the
- // string itself is 8-bit and not null terminated). Ignore it (just skip across) and we'll key off the property name
- // (coming up) instead.
- DWORD cbName;
- BYTE const * pbPostEncodedLength;
- IfFailRetRcNull(CPackedLen::SafeGetData(pbData, cbData, &cbName, &pbPostEncodedLength));
- DWORD cbEncodedLength = static_cast<DWORD>(pbPostEncodedLength - pbData);
- pbData += cbEncodedLength + cbName;
- cbData -= cbEncodedLength + cbName;
-
- // Now we have the name of the property (in a similar format to above).
- IfFailRetRcNull(CPackedLen::SafeGetData(pbData, cbData, &cbName, &pbPostEncodedLength));
- cbEncodedLength = static_cast<DWORD>(pbPostEncodedLength - pbData);
- pbData += cbEncodedLength;
- cbData -= cbEncodedLength;
-
- bool fConsistencyProp = false;
- if (cbName == strlen(RC_CONSISTENCY_PROP_NAME) && strncmp((const char*)pbData, RC_CONSISTENCY_PROP_NAME, cbName) == 0)
- fConsistencyProp = true;
- else if (cbName == strlen(RC_CER_PROP_NAME) && strncmp((const char*)pbData, RC_CER_PROP_NAME, cbName) == 0)
- fConsistencyProp = false;
- else
- IfFailRetRcNull(COR_E_BADIMAGEFORMAT);
- pbData += cbName;
- cbData -= cbName;
-
- // And finally the actual enum value (again, we assume the underlying type is a DWORD).
- if (cbData < sizeof(DWORD))
- IfFailRetRcNull(COR_E_BADIMAGEFORMAT);
- DWORD dwValue = GET_UNALIGNED_VAL32(pbData);
- pbData += sizeof(DWORD);
- cbData -= sizeof(DWORD);
-
- if (fConsistencyProp) {
- if (dwValue > RC_CONSISTENCY_CORRUPT_NOTHING)
- IfFailRetRcNull(COR_E_BADIMAGEFORMAT);
- dwResult = RC_MERGE(dwResult, RC_ENCODE(dwValue, RC_CER_UNDEFINED));
- } else {
- if (dwValue > RC_CER_SUCCESS)
- IfFailRetRcNull(COR_E_BADIMAGEFORMAT);
- dwResult = RC_MERGE(dwResult, RC_ENCODE(RC_CONSISTENCY_UNDEFINED, dwValue));
- }
- }
-
- // Shouldn't have any bytes left in the blob at this stage.
- _ASSERTE(cbData == 0);
- }
-
- // Return the result encoded and packed into the 2 low order bits of a DWORD.
- return dwResult;
-}
-
-// Given a metadata token, a scoping module and a type context, look up the appropriate MethodDesc (and recomputed accompanying type
-// context).
-MethodContext *TokenToMethodDesc(Module *pModule, mdToken tokMethod, SigTypeContext *pTypeContext)
-{
- STANDARD_VM_CONTRACT;
-
- // Validate that the token is one that we can handle.
- if (!pModule->GetMDImport()->IsValidToken(tokMethod) || (TypeFromToken(tokMethod) != mdtMethodDef &&
- TypeFromToken(tokMethod) != mdtMethodSpec &&
- TypeFromToken(tokMethod) != mdtMemberRef)) {
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_METHOD_TOKEN);
- }
-
- // Look up the MethodDesc based on the token and type context.
- MethodDesc *pMD = MemberLoader::GetMethodDescFromMemberDefOrRefOrSpec(pModule,
- tokMethod,
- pTypeContext,
- TRUE,
- FALSE);
-
- // The MethodDesc we get might be shared between several types. If so we'll need to do extra work to locate the exact
- // class instantiation instead of the default representative one.
- SigTypeContext sNewTypeContext;
- if (pMD->IsSharedByGenericInstantiations()) {
- TypeHandle th = GetTypeFromMemberDefOrRefOrSpecThrowing(pModule,
- tokMethod,
- pTypeContext);
- SigTypeContext::InitTypeContext(pMD, th,&sNewTypeContext);
- } else
- SigTypeContext::InitTypeContext(pMD, pMD->GetClassInstantiation(), pMD->GetMethodInstantiation(),&sNewTypeContext);
-
- return MethodContext::PerThreadAllocate(pMD, &sNewTypeContext);
-}
-
-// Locate an exact type definition given a method token and the type context in which it can be resolved.
-TypeHandle GetTypeFromMemberDefOrRefOrSpecThrowing(Module *pModule,
- mdToken tokMethod,
- SigTypeContext *pTypeContext)
-{
- STANDARD_VM_CONTRACT;
-
- IMDInternalImport *pImport = pModule->GetMDImport();
-
- // Convert method specs into the underlying member ref.
- if (TypeFromToken(tokMethod) == mdtMethodSpec)
- {
- PCCOR_SIGNATURE pSig;
- ULONG cSig;
- mdMemberRef tkGenericMemberRef;
-
- IfFailThrow(pImport->GetMethodSpecProps(tokMethod, &tkGenericMemberRef, &pSig, &cSig));
-
- if (!pImport->IsValidToken(tkGenericMemberRef) ||
- (TypeFromToken(tkGenericMemberRef) != mdtMethodDef &&
- TypeFromToken(tkGenericMemberRef) != mdtMemberRef))
- {
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_TOKEN_TYPE);
- }
-
- tokMethod = tkGenericMemberRef;
- }
-
- // Follow the member ref/def back up to the type def/ref/spec or module (for global methods).
- if (TypeFromToken(tokMethod) == mdtMemberRef)
- {
- IfFailThrow(pImport->GetParentOfMemberRef(tokMethod, &tokMethod));
-
- // For varargs, a memberref can point to a methodDef
- if (TypeFromToken(tokMethod) == mdtMethodDef)
- {
- if (!pImport->IsValidToken(tokMethod))
- {
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_TOKEN);
- }
- IfFailThrow(pImport->GetParentToken(tokMethod, &tokMethod));
- }
- }
- else if (TypeFromToken(tokMethod) == mdtMethodDef)
- {
- IfFailThrow(pImport->GetParentToken(tokMethod, &tokMethod));
- }
-
- if (!pImport->IsValidToken(tokMethod) || (TypeFromToken(tokMethod) != mdtTypeDef &&
- TypeFromToken(tokMethod) != mdtTypeRef &&
- TypeFromToken(tokMethod) != mdtTypeSpec &&
- TypeFromToken(tokMethod) != mdtModuleRef))
- {
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_TOKEN);
- }
-
- // Load the type in question, using a type context if necessary to get an exact representation.
- TypeHandle th;
- if (TypeFromToken(tokMethod) == mdtModuleRef) {
- DomainFile *pNewModule = pModule->LoadModule(GetAppDomain(), tokMethod, FALSE);
- if (pNewModule != NULL)
- th = TypeHandle(pNewModule->GetModule()->GetGlobalMethodTable());
- } else {
- th = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pModule,
- tokMethod,
- pTypeContext);
- }
-
- if (th.IsNull())
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
-
- return th;
-}
-
-// Determine whether the method given as a parameter is the root of a CER.
-// @todo: Need an x86 offset as well and logic to determine whether we're actually in a root-CER portion of the method (if the whole
-// thing isn't the root).
-bool IsCerRootMethod(MethodDesc *pMD)
-{
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pMD));
- SO_TOLERANT;
- } CONTRACTL_END;
-
- // Treat IL stubs as CER roots (marshaling code needs to string together operations without being interruped by thread aborts).
- if (pMD->IsILStub())
- return true;
-
- // There are some well defined root methods defined by the system.
- if (pMD == g_pExecuteBackoutCodeHelperMethod)
- return true;
-
- // For now we just look to see whether there is some prep or fixup info stored for this method.
- Module *pModule = pMD->GetModule();
-
- if (pModule->GetCerPrepInfo(pMD) != NULL)
- return true;
-
-#ifdef FEATURE_PREJIT
- if (pModule->IsNgenCerRootMethod(pMD))
- return true;
-#endif
-
- return false;
-}
-
-// Fill the cache of overflowed generic dictionary entries that the jit maintains with all the overflow slots stored so far in the
-// dictionary layout.
-void PrepopulateGenericHandleCache(DictionaryLayout *pDictionaryLayout,
- MethodDesc *pMD,
- MethodTable *pMT)
-{
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- } CONTRACTL_END;
-
- // Dictionary overflow entries are recorded starting in the second bucket of the dictionary layout.
- DictionaryLayout *pOverflows = pDictionaryLayout->GetNextLayout();
-
- while (pOverflows) {
- for (DWORD i = 0; i < pOverflows->GetMaxSlots(); i++) {
- DictionaryEntryLayout *pEntry = pOverflows->GetEntryLayout(i);
-
- // We've finished as soon as we find the first unused slot.
- if (!pEntry->m_signature)
- return;
-
- // We have a valid overflow entry. Determine the handle value given the type context we have and push it into the JIT's
- // cache.
- JIT_GenericHandleWorker(pMD, pMT, pEntry->m_signature);
- }
- pOverflows = pOverflows->GetNextLayout();
- }
-}
-
-#ifdef FEATURE_PREJIT
-
-// Prepare the CER rooted at the given method (it's OK to pass a MethodDesc* that doesn't root a CER, in which case the method
-// is a no-op).
-void CerNgenRootTable::Restore(MethodDesc *pRootMD)
-{
-#ifndef CROSSGEN_COMPILE
- STANDARD_VM_CONTRACT;
-
- // We don't have a restoration bitmap at ngen time. No matter, we just always claim everything is restored.
- if (m_pRestoreBitmap == NULL)
- return;
-
- // Locate the root index from the table. Failure indicates there's no work to do.
- DWORD dwIndex = FindIndex(pRootMD);
- if (dwIndex == NoSuchRoot)
- return;
-
- _ASSERTE(m_pRoots[dwIndex].m_pRootMD == pRootMD);
-
- // Check then mark the fact that we're preparing (to prevent potential recursion).
- SigTypeContext typeContext;
- if (!GetThread()->GetCerPreparationState()->CanPreparationProceed(pRootMD, &typeContext))
- return;
-
- MethodCallGraphPreparer sPrep(pRootMD, &typeContext, true, true);
- MethodCallGraphPreparer::ThreadPreparingCerHolder sCerHolder(&sPrep);
-
-#ifdef _DEBUG
- if (GetCerLoggingOptions())
- {
- CER_LOG(RESTORE, ("---------------------------------------------------------------\n"));
- SString ssRootMethod;
- TypeString::AppendMethodInternal(ssRootMethod, pRootMD, TypeString::FormatNamespace | TypeString::FormatStubInfo);
- CER_LOG(RESTORE, ("Restoring CER graph from %S\n", ssRootMethod.GetUnicode()));
- }
-#endif
-
- g_IBCLogger.LogCerMethodListReadAccess(pRootMD);
-
- // Retrieve the CerRoot structure.
- CerRoot *pRoot = &m_pRoots[dwIndex];
- _ASSERTE(pRoot->m_pRootMD == pRootMD);
-
- // Scan the list of methods in the CER (the last one is a sentinel with a NULL MethodDesc*). Restore each method as we go.
- MethodContextElement *pEntry = pRoot->m_pList;
- while (pEntry->GetMethodDesc())
- {
- // Method desc and type handle pointers may still be tokenized at this point.
- Module::RestoreMethodDescPointer(&pEntry->m_pMethodDesc);
- Module::RestoreMethodTablePointer(&pEntry->m_pExactMT);
-
- g_IBCLogger.LogCerMethodListReadAccess(pEntry->GetMethodDesc());
-
- MethodDesc * pMD = pEntry->GetMethodDesc();
-
- // Check whether there are generic dictionaries that need to be pre-populated.
-
- // Don't use the direct PrepopulateDictionary method here for MethodTable/MethodDesc
- // - MethodTable: Takes binding considerations into account (which we don't care about)
- // - MethodDesc: Appears to use a representative class instantiation (and we have the exact one handy)
- //
- // Additionally, avoid touching EE Class if we don't need to
- MethodTable * pMT = pEntry->GetExactMT();
- if (pMT != NULL)
- {
- // MethodTable
- DictionaryLayout *pClassDictLayout = pMT->GetClass()->GetDictionaryLayout();
- if (pClassDictLayout)
- {
- pMT->GetDictionary()->PrepopulateDictionary(NULL, pMT, false);
-
- // The dictionary may have overflowed in which case we need to prepopulate the jit's lookup cache as well.
- PrepopulateGenericHandleCache(pClassDictLayout, NULL, pMT);
- }
-
- // MethodDesc
- DictionaryLayout *pMethDictLayout = pMD->GetDictionaryLayout();
- if (pMethDictLayout)
- {
- pMD->GetMethodDictionary()->PrepopulateDictionary(pMD, NULL, false);
-
- // The dictionary may have overflowed in which case we need to prepopulate the jit's lookup cache as well.
- PrepopulateGenericHandleCache(pMethDictLayout, pMD, NULL);
- }
- }
-
- // Recreate stubs used by P/Invoke, COM calls, or FCalls by exercising the prestub.
- if (pMD->IsPointingToPrestub() && (pMD->IsNDirect() || pMD->IsComPlusCall() || pMD->IsFCall()))
- {
- pMD->EnsureActive();
- pMD->DoPrestub(NULL);
- }
-
-#ifdef _DEBUG
- if (GetCerLoggingOptions())
- {
- SString ssMethod;
- TypeString::AppendMethodInternal(ssMethod, pMD, TypeString::FormatNamespace | TypeString::FormatStubInfo);
- CER_LOG(RESTORE, (" %S\n", ssMethod.GetUnicode()));
- }
-#endif
-
- // Move to next entry.
- pEntry++;
- }
-
- CER_LOG(RESTORE, ("---------------------------------------------------------------\n"));
-
- // Mark this whole CER region as fixed up by setting a flag in the restore bitmap (kept separate so we can cluster all our page
- // writes).
- // Compute the DWORD offset into the flag array and then the mask for the specific bit in that DWORD.
- DWORD dwOffset = dwIndex / (sizeof(DWORD) * 8);
- DWORD dwMask = 1 << (dwIndex % (sizeof(DWORD) * 8));
- EnsureWritablePages(m_pRestoreBitmap, sizeof(DWORD) * SizeOfRestoreBitmap());
- FastInterlockOr(&m_pRestoreBitmap[dwOffset], dwMask);
-
- // If we fixed up any methods with their own CERs then we will have implicitly fixed up those too. Mark their fixup records as
- // completed as well to avoid further unecessary work.
- pEntry = pRoot->m_pList;
- while (pEntry->GetMethodDesc()) {
- dwIndex = FindIndex(pEntry->GetMethodDesc());
- if (dwIndex != NoSuchRoot) {
- dwOffset = dwIndex / (sizeof(DWORD) * 8);
- dwMask = 1 << (dwIndex % (sizeof(DWORD) * 8));
- FastInterlockOr(&m_pRestoreBitmap[dwOffset], dwMask);
- }
- pEntry++;
- }
-#endif // CROSSGEN_COMPILE
-}
-
-#ifdef FEATURE_NATIVE_IMAGE_GENERATION
-// Add a new root to the table, expanding it as necessary. Note that this method must be called with the CerCrst already held.
-void CerNgenRootTable::AddRoot(MethodDesc *pRootMD, MethodContextElement *pList)
-{
- CONTRACTL {
- STANDARD_VM_CHECK;
- PRECONDITION(IsOwnerOfCrst(pRootMD->GetModule()->GetCerCrst()));
- } CONTRACTL_END;
-
- // Ensure we have enough space first.
- if (m_cRoots == m_cSlots) {
- DWORD cNewSize = m_cSlots + 16;
- CerRoot *pNewArray = new CerRoot[cNewSize];
- memcpyNoGCRefs(pNewArray, m_pRoots, m_cRoots * sizeof(CerRoot));
- MethodContextElement **pNewRootsInCompilationOrder = new MethodContextElement*[cNewSize];
- memcpyNoGCRefs(pNewRootsInCompilationOrder, m_pRootsInCompilationOrder, m_cRoots * sizeof(MethodContextElement*) );
- m_cSlots = cNewSize;
- delete m_pRoots;
- m_pRoots = pNewArray;
- delete m_pRootsInCompilationOrder;
- m_pRootsInCompilationOrder = pNewRootsInCompilationOrder;
- }
-
- // Fill in the new entry in sorted order.
- DWORD i;
- for (i = 0; i < m_cRoots; i++)
- if ((UPTR) m_pRoots[i].m_pRootMD > (UPTR) pRootMD)
- break;
- if (i < m_cRoots)
- memmove(&m_pRoots[i + 1], &m_pRoots[i], (m_cRoots - i) * sizeof(CerRoot));
- m_pRoots[i].m_pRootMD = pRootMD;
- m_pRoots[i].m_pList = pList;
-
- m_pRootsInCompilationOrder[m_cRoots] = pList;
-
- m_cRoots++;
-}
-
-// Ngen callouts to help serialize this structure and its children to storage.
-void CerNgenRootTable::Save(DataImage *image, CorProfileData *profileData)
-{
- STANDARD_VM_CONTRACT;
-
-#ifdef _DEBUG
- DWORD dwMaxEntries = 0;
- DWORD dwTotalEntries = 0;
-#endif
-
- image->StoreStructure(this, sizeof(CerNgenRootTable), DataImage::ITEM_CER_ROOT_TABLE);
- image->StoreStructure(m_pRoots, m_cRoots * sizeof(CerRoot), DataImage::ITEM_CER_ROOT_TABLE);
-
- // Create a bitmap of boolean flags (1 bit per flag) indicating whether the CER at a given index in the array has been restored.
- // This is initially all zero and only filled in at runtime (keep all the flags together this way because they're the only
- // things we have to write at runtime and we want to keep them as dense as possible).
- _ASSERTE((SizeOfRestoreBitmap() % sizeof(DWORD)) == 0);
- m_pRestoreBitmap = new DWORD[SizeOfRestoreBitmap() / sizeof(DWORD)];
- memset(m_pRestoreBitmap, 0xff, SizeOfRestoreBitmap());
-
- image->StoreStructure(m_pRestoreBitmap,
- SizeOfRestoreBitmap(),
- DataImage::ITEM_CER_RESTORE_FLAGS);
-
- // Next save off the list of MethodContextElements associated with each root.
- for (DWORD i = 0; i < m_cRoots; i++) {
- MethodContextElement *pEntry = m_pRootsInCompilationOrder[i];
-
- // Count entries in list.
- DWORD cEntries = 0;
- while (pEntry->GetMethodDesc()) {
- cEntries++;
- pEntry++;
- }
-
- // Plus one for the sentinel value.
- cEntries++;
-
-#ifdef _DEBUG
- dwTotalEntries += cEntries;
- if (cEntries > dwMaxEntries)
- dwMaxEntries = cEntries;
-#endif
-
- // Store this list.
- image->StoreStructure(m_pRootsInCompilationOrder[i],
- cEntries * sizeof(MethodContextElement),
- DataImage::ITEM_CER_METHOD_LIST);
- }
-
-#ifdef _DEBUG
- if (m_cRoots > 0) {
- CER_LOG(NGEN_STATS, ("Saving %u CER roots in ngen image\n", m_cRoots));
- CER_LOG(NGEN_STATS, (" Max methods in CER: %u\n", dwMaxEntries));
- CER_LOG(NGEN_STATS, (" Avg methods in CER: %.1f\n", (float)((float)dwTotalEntries / (float)m_cRoots)));
- } else
- CER_LOG(NGEN_STATS, ("No CER roots in ngen image\n"));
-#endif
-}
-
-void CerNgenRootTable::Fixup(DataImage *image)
-{
- STANDARD_VM_CONTRACT;
-
- DWORD i;
-
- // We still use the point to the root array even though at runtime the two structures will be adjacent.
- image->FixupPointerField(this, offsetof(CerNgenRootTable, m_pRoots));
-
- // Restoration flags are used only at runtime and must start off zeroed.
- image->FixupPointerField(this, offsetof(CerNgenRootTable, m_pRestoreBitmap));
- image->ZeroField(m_pRestoreBitmap, 0, SizeOfRestoreBitmap());
-
- // The root list in compilation order is only used at ngen time, and is not written into native image.
- image->ZeroPointerField(this, offsetof(CerNgenRootTable, m_pRootsInCompilationOrder));
-
- // Fixup all the pointers in the individual CERs.
- for (i = 0; i < m_cRoots; i++) {
-
- // For each MethodContextElement in the list we need to fixup a pointer to a MethodDesc and two array pointers (one for any
- // class instantiation and one for any method instantiation). The actual MethodDescs and TypeHandles themselves are already
- // fixed up as are the instantiation arrays we point to (they're the ones inside the generic dictionaries of the class/method
- // concerned).
- MethodContextElement *pList = m_pRootsInCompilationOrder[i];
- MethodContextElement *pEntry = pList;
- while (pEntry->GetMethodDesc()) {
- image->FixupMethodDescPointer(pList, &pEntry->m_pMethodDesc);
- image->FixupMethodTablePointer(pList, &pEntry->m_pExactMT);
- pEntry++;
- }
- }
-}
-
-void CerNgenRootTable::FixupRVAs(DataImage *image)
-{
- STANDARD_VM_CONTRACT;
-
- DWORD i, j;
-
- // Now we go back through the root table and sort the entries based on the locations of the root method descs in the new image
- // (they may be rearranged due to IBC profiling).
- CerRoot *pNewRoots = (CerRoot*)image->GetImagePointer(m_pRoots);
- PREFIX_ASSUME(pNewRoots != NULL);
-
- // Simple insertion sort. Starting at the second element insert a candidate into its correct location in the sub-list
- // preceding it (which by definition will already be sorted).
- for (i = 1; i < m_cRoots; i++)
- {
- // Look at all of the preceding elements for the first that is larger than the candidate (i.e. should succeed the
- // candidate in sorted order). If we don't find one then the candidate is already in place and we can proceed to the
- // next candidate.
- for (j = 0; j < i; j++)
- if (image->GetRVA(pNewRoots[j].m_pRootMD) > image->GetRVA(pNewRoots[i].m_pRootMD)) {
-
- // Need to move candidate element up. Cache its value because we're about to overwrite it.
- MethodDesc *pTmpRootMD = pNewRoots[i].m_pRootMD;
- MethodContextElement *pTmpList = pNewRoots[i].m_pList;
-
- // Shuffle the sorted list one up to make room for the candidate.
- memmove(&pNewRoots[j + 1], &pNewRoots[j], (i - j) * sizeof(CerRoot));
-
- // Insert the candidate into position.
- pNewRoots[j].m_pRootMD = pTmpRootMD;
- pNewRoots[j].m_pList = pTmpList;
-
- // Sorted the candidate, move onto the next.
- break;
- }
- }
-
- // Fixup all the pointers in the individual CERs.
- for (i = 0; i < m_cRoots; i++) {
- // Fix up the pointer to the root method and the list of methods in the CER.
- image->FixupField(m_pRoots, sizeof(CerRoot) * i + offsetof(CerRoot, m_pRootMD),
- pNewRoots[i].m_pRootMD);
- image->FixupField(m_pRoots, sizeof(CerRoot) * i + offsetof(CerRoot, m_pList),
- pNewRoots[i].m_pList);
- }
-}
-#endif // FEATURE_NATIVE_IMAGE_GENERATION
-
-// Locate the index of a given CerRoot record in the array given the root method. This is used to access the array and to locate the
-// restored flag for the entry in the restored bitmap. NoSuchRoot is returned if the root cannot be found.
-DWORD CerNgenRootTable::FindIndex(MethodDesc *pRootMD)
-{
- CONTRACTL {
- NOTHROW;
- MODE_ANY;
- GC_NOTRIGGER;
- PRECONDITION(CheckPointer(pRootMD));
- SO_TOLERANT;
- } CONTRACTL_END;
-
- // The table is guaranteed to be sorted, so we can lookup our target with a binary search.
- DWORD dwLow = 0;
- DWORD dwHigh = m_cRoots - 1;
- while (true) {
-
- // Take out the simple cases first.
-
- // The range has only one entry.
- if (dwLow == dwHigh) {
- if (m_pRoots[dwLow].m_pRootMD == pRootMD)
- return dwLow;
-#ifdef _DEBUG
- for (DWORD i = 0; i < m_cRoots; i++)
- _ASSERTE(m_pRoots[i].m_pRootMD != pRootMD);
-#endif
- return NoSuchRoot;
- }
-
- // The range has only two entries.
- if (dwLow == dwHigh - 1) {
- if (m_pRoots[dwLow].m_pRootMD == pRootMD)
- return dwLow;
- if (m_pRoots[dwHigh].m_pRootMD == pRootMD)
- return dwHigh;
-#ifdef _DEBUG
- for (DWORD i = 0; i < m_cRoots; i++)
- _ASSERTE(m_pRoots[i].m_pRootMD != pRootMD);
-#endif
- return NoSuchRoot;
- }
-
- // Now we can compute a midpoint that is definitely distinct and in-between the endpoints.
- DWORD dwMid = dwLow + ((dwHigh - dwLow) / 2);
-
- // Did we nail it?
- if (m_pRoots[dwMid].m_pRootMD == pRootMD)
- return dwMid;
-
- // Otherwise adjust our range to be the bit we haven't looked at and iterate.
- if ((UPTR)m_pRoots[dwMid].m_pRootMD < (UPTR)pRootMD)
- dwLow = dwMid + 1;
- else
- dwHigh = dwMid - 1;
- }
-}
-
-// Prepare the class if it is derived from CriticalFinalizerObject. This is used at ngen time since such classes are normally
-// prepared at runtime (at instantiation) and would therefore miss the ngen image.
-void PrepareCriticalType(MethodTable * pMT)
-{
- STANDARD_VM_CONTRACT;
-
- // Prepare any class that satisfies the criteria. Pass a pointer to this module so that we'll only prepare any overrides of
- // the critical methods that were actually introduced here.
- if (pMT->HasCriticalFinalizer())
- PrepareCriticalFinalizerObject(pMT, pMT->GetLoaderModule());
-}
-
-// Prepare a method and its statically determinable call graph if a hint attribute has been applied. This is only called at ngen
-// time to save additional preparation information into the ngen image that wouldn't normally be there (and thus lower runtime
-// overheads).
-void PrePrepareMethodIfNecessary(CORINFO_METHOD_HANDLE hMethod)
-{
- STANDARD_VM_CONTRACT;
-
- EX_TRY {
-
- // Translate jit-style method handle into method desc.
- MethodDesc *pMD = GetMethod(hMethod);
-
- // Check for the existance of the attribute.
- IMDInternalImport *pImport = pMD->GetMDImport();
- mdToken tkMethod = pMD->GetMemberDef();
- HRESULT hr = pImport->GetCustomAttributeByName(tkMethod,
- "System.Runtime.ConstrainedExecution.PrePrepareMethodAttribute",
- NULL, NULL);
-
- // TODO: We should add IBC probes which indicate that methods need to be preprepared
- // which can then be reflected in the IBC data, we can add an additional check
- // here to cover that case, then we can get around this problem with profiling
- // instead of manual programmer effort.
-
- // Only prepare if we definitely saw the attribute.
- if (hr == S_OK) {
- // Prepare the method and its graph. There should never be any open type parameters (we can't do much at ngen time with these),
- // so we can pass a null type context.
- SigTypeContext sTypeContext;
- MethodCallGraphPreparer mcgp(pMD, &sTypeContext, true, true);
- mcgp.Run();
- }
-
- } EX_CATCH {
- } EX_END_CATCH(SwallowAllExceptions);
-}
-
-#endif // FEATURE_PREJIT
-
-PtrHashCache::PtrHashCache()
-{
- LIMITED_METHOD_CONTRACT;
- ZeroMemory(this, sizeof(*this));
-
- // First entry in each bucket is a chain index used to evenly distribute inserts within a bucket.
- _ASSERTE(PHC_CHAIN > 1);
-}
-
-bool PtrHashCache::Lookup(void *pKey, DWORD *pdwValue)
-{
- LIMITED_METHOD_CONTRACT;
- _ASSERTE(((UINT_PTR)pKey & PHC_DATA_MASK) == 0);
-
- DWORD dwBucket = GetHash(pKey);
-
- // Skip first entry in bucket, it's a sequence number used for insertions.
- for (DWORD i = 1; i < PHC_CHAIN; i++) {
- UINT_PTR uipEntry = VolatileLoad<UINT_PTR>(&m_rEntries[(dwBucket * PHC_CHAIN) + i]);
- if ((uipEntry & ~PHC_DATA_MASK) == (UINT_PTR)pKey) {
-#ifdef _DEBUG
- FastInterlockIncrement((LONG*)&m_dwHits);
-#endif
- *pdwValue = uipEntry & PHC_DATA_MASK;
- return true;
- }
- }
-
-#ifdef _DEBUG
- FastInterlockIncrement((LONG*)&m_dwMisses);
-#endif
- return false;
-}
-
-void PtrHashCache::Add(void *pKey, DWORD dwValue)
-{
- LIMITED_METHOD_CONTRACT;
- _ASSERTE(((UINT_PTR)pKey & PHC_DATA_MASK) == 0);
- _ASSERTE((dwValue & ~PHC_DATA_MASK) == 0);
-
- DWORD dwBucket = GetHash(pKey);
-
- // We keep a sequence number in the first entry of the bucket so that we distribute insertions within the bucket evenly. We're
- // racing when we update this value, but it doesn't matter if we lose an update (we're a cache after all). We don't bother being
- // careful to avoid overflowing the value here (we just keep incrementing); we'll do the modulo logic when we insert our value
- // instead.
- DWORD dwIndex = static_cast<DWORD>(m_rEntries[dwBucket * PHC_CHAIN]++);
- dwIndex = (dwIndex % (PHC_CHAIN - 1)) + 1;
- m_rEntries[(dwBucket * PHC_CHAIN) + dwIndex] = ((UINT_PTR)pKey & ~PHC_DATA_MASK) | dwValue;
-}
-
-DWORD PtrHashCache::GetHash(void *pKey)
-{
- LIMITED_METHOD_CONTRACT;
-
- return (DWORD)(((UINT_PTR)pKey >> 4) % PHC_BUCKETS);
-}
-
-#ifdef _DEBUG
-void PtrHashCache::DbgDumpStats()
-{
-#if 0
- if ((m_dwHits + m_dwMisses) == 0)
- return;
-
- printf("Dumping stats for PtrHashCache %08X\n", this);
- printf(" %u hits, %u misses (%u%% hit rate)\n", m_dwHits, m_dwMisses, (m_dwHits * 100) / (m_dwHits + m_dwMisses));
- for (DWORD i = 0; i < PHC_BUCKETS; i++)
- printf(" [%2u] : %u insertions\n", i, m_rEntries[i * PHC_CHAIN]);
- printf("\n");
-#endif
-}
-#endif
diff --git a/src/vm/crossdomaincalls.cpp b/src/vm/crossdomaincalls.cpp
deleted file mode 100644
index b528915a54..0000000000
--- a/src/vm/crossdomaincalls.cpp
+++ /dev/null
@@ -1,2587 +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.
-//
-// File: CrossDomainCalls.cpp
-//
-
-//
-// The CrossDomainCall class provides a fast path of execution for qualifying
-// cross domain calls. Asynch calls, one way calls, calls on context bound objects
-// etc dont qualify.
-//
-
-
-#include "common.h"
-
-#ifdef FEATURE_REMOTING
-
-#include "crossdomaincalls.h"
-#include "callhelpers.h"
-#include "remoting.h"
-#include "objectclone.h"
-#include "dbginterface.h"
-#include "stackprobe.h"
-#include "virtualcallstub.h"
-#include "typeparse.h"
-#include "typestring.h"
-#include "appdomain.inl"
-#include "callingconvention.h"
-
-// See explanation of flags in crossdomaincalls.h
-RemotableMethodInfo::XADOptimizationType
-RemotableMethodInfo::IsCrossAppDomainOptimizable(MethodDesc *pMeth, DWORD *pNumStackSlotsToCopy)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
-
- // This method table might be representative, but that's OK for the kinds of analysis we're about to do.
- MethodTable *pMT = pMeth->GetMethodTable()->GetCanonicalMethodTable();
-
- _ASSERTE(pMT->HasRemotableMethodInfo());
- _ASSERTE(pMT->GetRemotableMethodInfo());
-
- if (pMT->IsContextful())
- return XAD_NOT_OPTIMIZABLE;
-
- DWORD flags;
-
- // If this method is generic then we can't used cached analysis data stored on the method table and keyed by slot -- the same
- // slot is shared by methods with very different characteristics (such as whether the return type is a GC ref etc.).
- if (pMeth->GetNumGenericMethodArgs() > 0)
- {
- flags = DoStaticAnalysis(pMeth);
- }
- else
- {
- _ASSERTE(pMeth->GetSlot() < pMeth->GetMethodTable()->GetNumVtableSlots());
- RemotableMethodInfo *pRMI = &(pMT->GetRemotableMethodInfo()->GetRemotableMethodInfo()[pMeth->GetSlot()]);
- flags = pRMI->m_OptFlags;
-
- if (!(flags & XAD_FLAGS_INITIALIZED))
- {
- flags = DoStaticAnalysis(pMeth);
- pRMI->m_OptFlags = flags;
- }
- }
-
- *pNumStackSlotsToCopy = flags & XAD_ARG_COUNT_MASK;
-
- return (XADOptimizationType) (flags & XAD_FLAG_MASK);
-}
-
-// This method is not synchronized because the operation is idempotent
-DWORD
-RemotableMethodInfo::DoStaticAnalysis(MethodDesc *pMeth)
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- THROWS;
- PRECONDITION(CheckPointer(pMeth));
- }
- CONTRACTL_END
-
- BOOL bCallArgsBlittable = TRUE;
- BOOL bRetArgBlittable = TRUE;
- BOOL bOptimizable = TRUE;
- BOOL bMethodIsVirtual = FALSE;
- BOOL bArgsHaveAFloat = FALSE;
-
- DWORD numStackBytes = 0;
- DWORD numStackSlots = 0;
- DWORD returnTypeFlags = 0;
-
- if (pMeth->ContainsGenericVariables())
- {
- bOptimizable = FALSE;
- }
- else
- {
- MetaSig mSig(pMeth);
- ArgIterator argit(&mSig);
-
- SigPointer spRet;
- CorElementType retElem;
-
- IMDInternalImport *pMDImport = pMeth->GetModule()->GetMDImport();
- MDEnumHolder ePm(pMDImport); // For enumerating params.
- mdParamDef tkPm; // A param token.
- DWORD dwFlags; // Param flags.
- USHORT usSeq; // Sequence of a parameter.
-
- if (pMeth->IsOneWay())
- {
- bOptimizable = FALSE;
- goto SetFlags;
- }
-
- if (pMeth->IsVirtual())
- {
- bMethodIsVirtual = TRUE;
- }
-
- numStackBytes = argit.SizeOfFrameArgumentArray();
-
- _ASSERTE(numStackBytes % sizeof(SIZE_T) == 0);
- numStackSlots = numStackBytes / sizeof(SIZE_T);
-
- if (numStackSlots > XAD_ARG_COUNT_MASK)
- {
- bOptimizable = FALSE;
- goto SetFlags;
- }
-
- // Check if there are any [Out] args. If there are, skip the fast path
- IfFailThrow(pMDImport->EnumInit(mdtParamDef, pMeth->GetMemberDef(), &ePm));
-
- // Enumerate through the params and check the flags.
- while (pMDImport->EnumNext(&ePm, &tkPm))
- {
- LPCSTR szParamName_Ignore;
- IfFailThrow(pMDImport->GetParamDefProps(tkPm, &usSeq, &dwFlags, &szParamName_Ignore));
- if (usSeq == 0) // Skip return type flags.
- continue;
- // If the param has Out attribute, do not use fast path for this method
- if (IsPdOut(dwFlags))
- {
- bOptimizable = FALSE;
- goto SetFlags;
- }
- }
-
- // We're getting SigPointer first because this way we can differentiate E_T_STRING and E_T_CLASS
- spRet = mSig.GetReturnProps();
- IfFailThrow(spRet.GetElemType(&retElem));
- if (retElem > ELEMENT_TYPE_PTR &&
- retElem != ELEMENT_TYPE_I &&
- retElem != ELEMENT_TYPE_U &&
- retElem != ELEMENT_TYPE_FNPTR)
- {
- bRetArgBlittable = FALSE;
- }
-
- // Now we can normalize the return type so as to get rid of any generic type variables and the like.
- retElem = mSig.GetReturnType();
-
- if (retElem == ELEMENT_TYPE_VALUETYPE)
- {
- // Make a note that we have a struct in the signature. This way we wont blit the contents
- // and end up in a situation where we have data, but the type isnt loaded yet
- bCallArgsBlittable = FALSE;
-
- // Do some further inspection
- TypeHandle retTypeHandle = mSig.GetRetTypeHandleThrowing();
-
- // Currently we don't handle the special unbox handling for ret values of Nullable<T> in MarshalAndCall
- if (Nullable::IsNullableType(retTypeHandle))
- {
- bOptimizable = FALSE;
- }
-
- retElem = retTypeHandle.GetInternalCorElementType();
- if ((retElem <= ELEMENT_TYPE_PTR || retElem == ELEMENT_TYPE_I || retElem == ELEMENT_TYPE_U) &&
- !retTypeHandle.AsMethodTable()->CannotBeBlittedByObjectCloner())
- bRetArgBlittable = TRUE;
- }
-
- // Check if the return type is a GC ref
- if (gElementTypeInfo[retElem].m_gc == TYPE_GC_REF)
- {
- returnTypeFlags = XAD_RET_GC_REF;
- }
- else
- {
- returnTypeFlags = GetRetTypeFlagsFromFPReturnSize(argit.GetFPReturnSize());
- }
-
- CorElementType currType;
- while ((currType = mSig.NextArg()) != ELEMENT_TYPE_END)
- {
- SigPointer sp = mSig.GetArgProps();
- CorElementType retTy;
- IfFailThrow(sp.GetElemType(&retTy));
- if (retTy > ELEMENT_TYPE_PTR &&
- retTy != ELEMENT_TYPE_VALUETYPE &&
- retTy != ELEMENT_TYPE_I &&
- retTy != ELEMENT_TYPE_U &&
- retTy != ELEMENT_TYPE_FNPTR)
- {
- bCallArgsBlittable = FALSE;
- }
-
- // Currently we don't handle the special unbox handling for Nullable<T> for byrefs in MarshalAndCall
- if (currType == ELEMENT_TYPE_BYREF)
- {
- TypeHandle refType;
- if (mSig.GetByRefType(&refType) == ELEMENT_TYPE_VALUETYPE)
- if (Nullable::IsNullableType(refType))
- {
- bOptimizable = FALSE;
- }
- }
- else if (currType == ELEMENT_TYPE_VALUETYPE)
- {
-#if ENREGISTERED_PARAMTYPE_MAXSIZE
- // Since we also do implict ByRef in some cases, we also have to probit the optimization there too
- TypeHandle argType = mSig.GetLastTypeHandleThrowing();
- if (Nullable::IsNullableType(argType))
- {
- if (ArgIterator::IsArgPassedByRef(argType))
- bOptimizable = FALSE;
- }
-#endif
- bCallArgsBlittable = FALSE;
- }
- else if (currType == ELEMENT_TYPE_R4 || currType == ELEMENT_TYPE_R8)
- {
- bArgsHaveAFloat = TRUE;
- }
- }
- }
-
-SetFlags:
- DWORD optimizationFlags = 0;
- if (!bOptimizable)
- {
- optimizationFlags |= XAD_NOT_OPTIMIZABLE;
- }
- else
- {
- optimizationFlags |= returnTypeFlags;
-
- if (bCallArgsBlittable)
- {
- optimizationFlags |= XAD_BLITTABLE_ARGS;
- }
- if (bRetArgBlittable)
- {
- optimizationFlags |= XAD_BLITTABLE_RET;
- }
- if (bMethodIsVirtual)
- {
- optimizationFlags |= XAD_METHOD_IS_VIRTUAL;
- }
- if (bArgsHaveAFloat)
- {
- optimizationFlags |= XAD_ARGS_HAVE_A_FLOAT;
- }
- }
- optimizationFlags |= numStackSlots;
- optimizationFlags |= XAD_FLAGS_INITIALIZED;
-
- return optimizationFlags;
-}
-
-#ifndef CROSSGEN_COMPILE
-
-BOOL RemotableMethodInfo::TypeIsConduciveToBlitting(MethodTable *pFromMT, MethodTable *pToMT)
-{
- LIMITED_METHOD_CONTRACT;
- // Presence of GC fields or certain atributes, rules out blittability
- if (pFromMT->CannotBeBlittedByObjectCloner() ||
- pToMT->CannotBeBlittedByObjectCloner())
- return FALSE;
-
- // Shared types are okay to blit
- if (pFromMT == pToMT)
- return TRUE;
-
- if (pFromMT->IsEnum() && pToMT->IsEnum()
- && pFromMT->GetBaseSize() == pToMT->GetBaseSize())
- return TRUE;
-
- return FALSE;
-}
-
-PtrHashMap *CrossDomainTypeMap::s_crossDomainMTMap = NULL;
-SimpleRWLock *CrossDomainTypeMap::s_MTMapLock = NULL;
-
-BOOL CrossDomainTypeMap::CompareMTMapEntry (UPTR val1, UPTR val2)
-{
- CONTRACTL {
- MODE_ANY;
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- CrossDomainTypeMap::MTMapEntry *entry1 = (CrossDomainTypeMap::MTMapEntry *)(val1 << 1);
- CrossDomainTypeMap::MTMapEntry *entry2 = (CrossDomainTypeMap::MTMapEntry *)val2;
-
- if (entry1->m_pFromMT == entry2->m_pFromMT &&
- entry1->m_dwFromDomain == entry2->m_dwFromDomain &&
- entry1->m_dwToDomain == entry2->m_dwToDomain)
- return TRUE;
-
- return FALSE;
-}
-
-CrossDomainTypeMap::MTMapEntry::MTMapEntry(AppDomain *pFromDomain, MethodTable *pFromMT, AppDomain *pToDomain, MethodTable *pToMT)
-{
- WRAPPER_NO_CONTRACT;
-
- m_dwFromDomain = pFromDomain->GetId();
- m_dwToDomain = pToDomain->GetId();
- m_pFromMT = pFromMT;
- m_pToMT = pToMT;
-}
-
-static BOOL IsOwnerOfRWLock(LPVOID lock)
-{
- // @TODO - SimpleRWLock does not have knowledge of which thread gets the writer
- // lock, so no way to verify
- return TRUE;
-}
-
-/*static*/
-PtrHashMap *CrossDomainTypeMap::GetTypeMap()
-{
- CONTRACTL
- {
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END
-
- if (s_MTMapLock == NULL)
- {
- void *tempLockSpace = SystemDomain::GetGlobalLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(SimpleRWLock)));
- SimpleRWLock *tempLock = new (tempLockSpace) SimpleRWLock(COOPERATIVE_OR_PREEMPTIVE, LOCK_TYPE_DEFAULT);
-
- if (FastInterlockCompareExchangePointer(&s_MTMapLock,
- tempLock,
- NULL) != NULL)
- {
- // We lost the race
- SystemDomain::GetGlobalLoaderAllocator()->GetLowFrequencyHeap()->BackoutMem(tempLockSpace, sizeof(SimpleRWLock));
- }
- }
-
- // Now we have a Crst we can use to synchronize the remainder of the init.
- if (s_crossDomainMTMap == NULL)
- {
- SimpleWriteLockHolder swlh(s_MTMapLock);
-
- if (s_crossDomainMTMap == NULL)
- {
- PtrHashMap *map = new (SystemDomain::GetGlobalLoaderAllocator()->GetLowFrequencyHeap()) PtrHashMap ();
- LockOwner lock = {s_MTMapLock, IsOwnerOfRWLock};
- map->Init (32, CompareMTMapEntry, TRUE, &lock);
- s_crossDomainMTMap = map;
- }
- }
-
- return s_crossDomainMTMap;
-}
-
-MethodTable *
-CrossDomainTypeMap::GetMethodTableForDomain(MethodTable *pMT, AppDomain *pFromDomain, AppDomain *pToDomain)
-{
- CONTRACTL
- {
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END
- PtrHashMap *map = GetTypeMap();
-
- MTMapEntry admt(pFromDomain, pMT, pToDomain, NULL);
-
- SimpleReadLockHolder srlh(s_MTMapLock);
- MTMapEntry *pFound = (MTMapEntry *) map->LookupValue(admt.GetHash(), (LPVOID) &admt);
- if ((MTMapEntry *)INVALIDENTRY == pFound)
- return NULL;
-
- return pFound->m_pToMT;
-}
-
-void
-CrossDomainTypeMap::SetMethodTableForDomain(MethodTable *pFromMT, AppDomain *pFromDomain, MethodTable *pToMT, AppDomain *pToDomain)
-{
- CONTRACTL
- {
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END
- PtrHashMap *map = GetTypeMap();
-
- NewHolder<MTMapEntry> admt(new MTMapEntry(pFromDomain, pFromMT, pToDomain, pToMT));
- PREFIX_ASSUME(admt != NULL);
-
- SimpleWriteLockHolder swlh(s_MTMapLock);
-
- UPTR key = admt->GetHash();
-
- MTMapEntry *pFound = (MTMapEntry *) map->LookupValue(key, (LPVOID) admt);
- if ((MTMapEntry *)INVALIDENTRY == pFound)
- {
- map->InsertValue(key, (LPVOID) admt);
- admt.SuppressRelease();
- }
-}
-
-// Remove any entries in the table that refer to an appdomain that is no longer live.
-void CrossDomainTypeMap::FlushStaleEntries()
-{
- CONTRACTL
- {
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- NOTHROW;
- }
- CONTRACTL_END
-
- if (s_MTMapLock == NULL || s_crossDomainMTMap == NULL)
- return;
-
- SimpleWriteLockHolder swlh(s_MTMapLock);
-
- bool fDeletedEntry = false;
- PtrHashMap::PtrIterator iter = s_crossDomainMTMap->begin();
- while (!iter.end())
- {
- MTMapEntry *pEntry = (MTMapEntry *)iter.GetValue();
- AppDomainFromIDHolder adFrom(pEntry->m_dwFromDomain, TRUE);
- AppDomainFromIDHolder adTo(pEntry->m_dwToDomain, TRUE);
- if (adFrom.IsUnloaded() ||
- adTo.IsUnloaded())
- {
-#ifdef _DEBUG
- LPVOID pDeletedEntry =
-#endif
- s_crossDomainMTMap->DeleteValue(pEntry->GetHash(), pEntry);
- _ASSERTE(pDeletedEntry == pEntry);
- delete pEntry;
- fDeletedEntry = true;
- }
- ++iter;
- }
-
- if (fDeletedEntry)
- s_crossDomainMTMap->Compact();
-}
-
-
-
-// Before a cross appdomain call, we read the principal on the thread and set it aside, so that it can
-// be restored when the call returns.
-// In addition, we let the principal flow thru to the called appdomain, if the principal is serializable
-OBJECTREF CrossDomainChannel::ReadPrincipal()
-{
- CONTRACTL
- {
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END
-
- THREADBASEREF ref = (THREADBASEREF) GetThread()->GetExposedObjectRaw();
- _ASSERTE(ref != NULL);
-
- EXECUTIONCONTEXTREF refExecCtx = (EXECUTIONCONTEXTREF )ref->GetExecutionContext();
- if (refExecCtx == NULL)
- return NULL;
-
- LOGICALCALLCONTEXTREF refCallContext = refExecCtx->GetLogicalCallContext();
- if (refCallContext == NULL)
- return NULL;
-
- CCSECURITYDATAREF refSecurityData = refCallContext->GetSecurityData();
- if (refSecurityData == NULL)
- return NULL;
-
- OBJECTREF refPrincipal = refSecurityData->GetPrincipal();
- if (refPrincipal != NULL)
- {
- MethodTable *pPrincipalType = refPrincipal->GetMethodTable();
- if (!pPrincipalType->IsSerializable())
- {
- refSecurityData->SetPrincipal(NULL);
- }
- }
-
- return refPrincipal;
-}
-
-// Principal never flows from called appdomain back to caller domain.
-VOID CrossDomainChannel::ResetPrincipal()
-{
- CONTRACTL
- {
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END
-
- THREADBASEREF ref = (THREADBASEREF) GetThread()->GetExposedObjectRaw();
- _ASSERTE(ref != NULL);
-
- EXECUTIONCONTEXTREF refExecCtx = (EXECUTIONCONTEXTREF )ref->GetExecutionContext();
- if (refExecCtx == NULL)
- return;
-
- LOGICALCALLCONTEXTREF refCallContext = refExecCtx->GetLogicalCallContext();
- if (refCallContext == NULL)
- return;
-
- CCSECURITYDATAREF refSecurityData = refCallContext->GetSecurityData();
- if (refSecurityData == NULL)
- return;
-
- refSecurityData->SetPrincipal(NULL);
-
-}
-
-// At the end of a cross-appdomain call, we restore whatever principal was on the thread at the beginning of the call
-VOID CrossDomainChannel::RestorePrincipal(OBJECTREF *prefPrincipal)
-{
- CONTRACTL
- {
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END
-
- THREADBASEREF ref = (THREADBASEREF) GetThread()->GetExposedObjectRaw();
- if (ref == NULL)
- return;
-
- EXECUTIONCONTEXTREF refExecCtx = (EXECUTIONCONTEXTREF )ref->GetExecutionContext();
- _ASSERTE(*prefPrincipal == NULL || refExecCtx != NULL);
-
- if (refExecCtx == NULL)
- return;
-
- LOGICALCALLCONTEXTREF refCallContext = refExecCtx->GetLogicalCallContext();
- if (refCallContext == NULL)
- return;
-
- CCSECURITYDATAREF refSecurityData = refCallContext->GetSecurityData();
- _ASSERTE(*prefPrincipal == NULL || refSecurityData != NULL);
-
- if (refSecurityData == NULL)
- return;
-
- refSecurityData->SetPrincipal(*prefPrincipal);
-
-}
-
-// This method mimics the Lease renewal mechanism of the managed CrossDomainChannel
-// The lease object for the server can be accessed via its ServerIdentity.
-VOID CrossDomainChannel::RenewLease()
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END
- // Check if lease needs to be renewed
- OBJECTREF refSrvIdentity = ObjectFromHandle(m_refSrvIdentity);
- if (refSrvIdentity == NULL)
- return;
-
- OBJECTREF refLease = ObjectToOBJECTREF((Object *)refSrvIdentity->GetPtrOffset(CRemotingServices::GetOffsetOfLeaseInIdentity()));
- if (refLease != NULL)
- {
- GCPROTECT_BEGIN(refLease);
- MethodDesc *pLeaseMeth = CRemotingServices::MDofRenewLeaseOnCall();
- PCODE pCode = (PCODE)pLeaseMeth->GetCallTarget(&refLease);
-
- PREPARE_NONVIRTUAL_CALLSITE_USING_CODE(pCode);
-
- DECLARE_ARGHOLDER_ARRAY(args, 2);
-
- args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(refLease);
- args[ARGNUM_1] = NULL;
-
- CATCH_HANDLER_FOUND_NOTIFICATION_CALLSITE;
- CALL_MANAGED_METHOD_NORET(args);
-
- GCPROTECT_END();
- }
-}
-
-// Given a client side instantiated method desc and a server side generic definition method desc extract the instantiation,
-// translate all the types involved into the server domain and return the fully instantiated server method desc. Note that the
-// client and server method descs might not represent the same type -- the client method might be from an interface, whereas the
-// server method will always be on the real class.
-MethodDesc *InstantiateMethod(MethodDesc *pClientMD, MethodDesc *pServerMD, MethodTable *pServerMT)
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- THROWS;
- PRECONDITION(CheckPointer(pClientMD));
- PRECONDITION(pClientMD->HasMethodInstantiation());
- PRECONDITION(CheckPointer(pServerMD));
- PRECONDITION(pServerMD->HasMethodInstantiation());
- PRECONDITION(pClientMD->GetNumGenericMethodArgs() == pServerMD->GetNumGenericMethodArgs());
- }
- CONTRACTL_END;
-
- Instantiation clientInst = pClientMD->GetMethodInstantiation();
-
- DWORD dwAllocaSize;
- if (!ClrSafeInt<DWORD>::multiply(clientInst.GetNumArgs(), sizeof(TypeHandle), dwAllocaSize))
- COMPlusThrowHR(COR_E_OVERFLOW);
-
- CQuickBytes qbServerInst;
- TypeHandle *pServerInst = reinterpret_cast<TypeHandle*>(qbServerInst.AllocThrows(dwAllocaSize));
-
- for (DWORD dwArgNum = 0; dwArgNum < clientInst.GetNumArgs(); dwArgNum++)
- {
- SString thName;
- TypeString::AppendType(thName, clientInst[dwArgNum], TypeString::FormatNamespace|TypeString::FormatFullInst|TypeString::FormatAssembly);
-
- pServerInst[dwArgNum] = TypeName::GetTypeFromAsmQualifiedName(thName.GetUnicode(), pClientMD->IsIntrospectionOnly());
-
- _ASSERTE(!pServerInst[dwArgNum].IsNull());
-
- // Check that the type is actually visible on the server side. This prevents a malicious client from luring a trusted server
- // into manipulating types that would be normally invisible to it.
- if (!pServerInst[dwArgNum].IsExternallyVisible())
- COMPlusThrow(kRemotingException, W("Remoting_NonPublicOrStaticCantBeCalledRemotely"));
- }
-
- // Find or create the method will the full instantiation.
- return MethodDesc::FindOrCreateAssociatedMethodDesc(pServerMD,
- pServerMT,
- FALSE,
- Instantiation(pServerInst, clientInst.GetNumArgs()),
- FALSE);
-}
-
-BOOL CrossDomainChannel::GetGenericMethodAddress(MethodTable *pServerType)
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END;
-
- m_pSrvMD = InstantiateMethod(m_pCliMD, pServerType->GetMethodDescForSlot(m_pCliMD->GetSlot()), pServerType);
-
- OBJECTREF thisObj = GetServerObject();
- m_pTargetAddress = m_pSrvMD->GetCallTarget(&thisObj);
-
- return TRUE;
-}
-
-// We use this method to find the target address when we are convinced that the most derived type the proxy is cast
-// to on the client side is equivalent to the corresponding type on the server side, in the sense the method table
-// layouts are similar. This fact can be used to look up method addresses faster
-BOOL CrossDomainChannel::GetTargetAddressFast(DWORD optFlags, MethodTable *pSrvMT, BOOL bFindServerMD)
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END
- _ASSERTE(m_pCliMD);
- _ASSERTE(m_pSrvDomain == SystemDomain::GetCurrentDomain()->GetId());
-
- MethodTable *pCliMT = m_pCliMD->GetMethodTable();
- _ASSERTE(!pCliMT->IsInterface());
-
- m_pSrvMD = NULL;
-
- DWORD dwMethodSlot = m_pCliMD->GetSlot();
- if (!RemotableMethodInfo::IsMethodVirtual(m_xret))
- {
- // This is a non-virtual method. Find the matching MT on the
- // server side, dereference the slot and get the method address
-
- MethodTable *pSrvSideMT = pSrvMT;
-
- // We now need to walk the server type hierarchy till we find the type that
- // declared the method we're going to call
-
- // First find how far is the type declaring the called method, from System.Object
- DWORD cliDepth = 0;
- MethodTable *pCurrLevel = pCliMT;
- while (pCurrLevel != NULL)
- {
- _ASSERTE(pCurrLevel);
- pCurrLevel = pCurrLevel->GetParentMethodTable();
- cliDepth++;
- };
-
- // Next find how deep is the server type from System.Object
- DWORD srvDepth = 0;
- pCurrLevel = pSrvMT;
- while (pCurrLevel != NULL)
- {
- _ASSERTE(pCurrLevel);
- pCurrLevel = pCurrLevel->GetParentMethodTable();
- srvDepth++;
- };
-
- _ASSERTE(srvDepth >= cliDepth);
-
- while (srvDepth > cliDepth)
- {
- _ASSERTE(pSrvSideMT);
- _ASSERTE(srvDepth != 0);
- pSrvSideMT = pSrvSideMT->GetParentMethodTable();
- srvDepth--;
- };
-
- if (m_pCliMD->HasMethodInstantiation())
- {
- GetGenericMethodAddress(pSrvSideMT);
- }
- else
- {
- m_pTargetAddress = pSrvSideMT->GetRestoredSlot(dwMethodSlot);
-
-#ifndef _DEBUG
- if (bFindServerMD)
-#endif
- m_pSrvMD = pSrvSideMT->GetMethodDescForSlot(dwMethodSlot);
- }
- }
- else
- {
- if (m_pCliMD->HasMethodInstantiation())
- GetGenericMethodAddress(pSrvMT);
- else
- {
- m_pTargetAddress = pSrvMT->GetRestoredSlot(dwMethodSlot);
-
-#ifndef _DEBUG
- if (bFindServerMD)
-#endif
- m_pSrvMD = pSrvMT->GetMethodDescForSlot(dwMethodSlot);
- }
- }
-
- _ASSERTE(m_pTargetAddress);
-#ifdef _DEBUG
- _ASSERTE(!strcmp(m_pSrvMD->GetName(), m_pCliMD->GetName()));
- DefineFullyQualifiedNameForClass();
- LPCUTF8 szSrvTypeName = GetFullyQualifiedNameForClassNestedAware(pSrvMT);
- LPCUTF8 pszMethodName = m_pCliMD->GetName();
- LOG((LF_REMOTING, LL_INFO100, "GetTargetAddressFast. Address of %s::%s is 0x%x\n", &szSrvTypeName[0], pszMethodName, m_pTargetAddress));
-#endif // _DEBUG
- return TRUE;
-}
-
-BOOL
-CrossDomainChannel::GetInterfaceMethodAddressFast(DWORD optFlags, MethodTable *pSrvMT, BOOL bFindServerMD)
-{
- CONTRACTL
- {
- THROWS;
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- }
- CONTRACTL_END;
-
- _ASSERTE(m_pCliMD);
-
- MethodTable *pCliItfMT = m_pCliMD->GetMethodTable();
- _ASSERTE(pCliItfMT->IsInterface());
-
- // Only use the fast path if the interface is shared. If the interface isnt shared, then we'll have to search the
- // interface map on server type using name as key and then deref the slot # etc. I think shared interfaces will
- // be the common pattern. If not they should be.
- // Note that it's not enough to check that the client interface is shared, it must also be loaded in the server appdomain (since
- // it's now possible to have more than one instance of a shared assembly in a process).
- _ASSERTE(pCliItfMT->IsDomainNeutral());
- AppDomain* ad = SystemDomain::GetAppDomainFromId(m_pSrvDomain,ADV_RUNNINGIN);
- if (ad->FindDomainAssembly(pCliItfMT->GetAssembly()) == NULL)
- return FALSE;
-
- m_pSrvMD = NULL;
-
- OBJECTREF thisObj = GetServerObject();
-
-#ifdef FEATURE_COMINTEROP
- // Check for a COM interop server.
- if (thisObj->GetMethodTable()->IsComObjectType())
- {
-#if 0
- // We don't have all the logic in place to deal with COM interop yet. The following code is taken from the regular remoting
- // invocation path in CStackBuilderSink::PrivateProcessMessage, but I think we still need some work on the actual invocation
- // itself (leastways we didn't end up invoking the method correctly when I tried it).
- // For now we'll just bail back to the regular remoting path for COM interop.
- m_pSrvMD = thisObj->GetMethodTable()->GetMethodDescForComInterfaceMethod(m_pCliMD, false);
- if (m_pSrvMD == NULL)
- return FALSE;
-#endif
- return FALSE;
- }
-#endif // FEATURE_COMINTEROP
-
- GCPROTECT_BEGIN(thisObj);
-
- DispatchSlot impl(pSrvMT->FindDispatchSlotForInterfaceMD(m_pCliMD));
- CONSISTENCY_CHECK(!impl.IsNull());
- m_pSrvMD = impl.GetMethodDesc();
-
- _ASSERTE(m_pSrvMD);
-
- // If the method called has a generic instantiation then the server method desc we've just received doesn't contain that
- // information (generic method slots are filled with generic definition method descs). We need to build the exact method desc by
- // copying the instantiation from the client method (translating each type into the new domain of course).
- if (m_pSrvMD->HasMethodInstantiation())
- m_pSrvMD = InstantiateMethod(m_pCliMD, m_pSrvMD, pSrvMT);
-
- m_pTargetAddress = m_pSrvMD->GetCallTarget(&thisObj);
-
- GCPROTECT_END();
-
- return TRUE;
-}
-
-
-// Here we check whether the remote call is a cross domain call, if so, does it qualify
-BOOL
-CrossDomainChannel::CheckCrossDomainCall(TPMethodFrame *pFrame)
-{
- CONTRACTL
- {
- THROWS;
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- }
- CONTRACTL_END;
-
- m_pFrame = pFrame;
- m_pCliMD = m_pFrame->GetFunction();
-
- MethodTable *pCliMT = m_pCliMD->GetMethodTable();
-
- // Check if this is an async delegate call
- if (pCliMT->IsDelegate())
- return FALSE;
-
- // Only use the fast path if the interface is shared. If the interface isnt shared, then we'll have to search the
- // interface map on server type using name as key and then deref the slot # etc. I think shared interfaces will
- // be the common pattern.
- if (pCliMT->IsInterface() && !pCliMT->IsDomainNeutral())
- return FALSE;
-
- OBJECTREF refTP = pFrame->GetThis();
- REALPROXYREF refRP = CTPMethodTable::GetRP(refTP);
-
- // Check if this is a x-domain call
- DWORD domainID = refRP->GetDomainID();
- if (domainID == 0)
- return FALSE; // Not x-appdomain call, or proxy not initted for optimization
-
- // Check if we are in a context different from default. If so, we may need to run context
- // policies etc. Use regular path.
- if (GetThread()->GetContext() != SystemDomain::GetCurrentDomain()->GetDefaultContext())
- return FALSE;
-
- // Check if method call args can be blitted (or not optimizable at all)
- m_xret = RemotableMethodInfo::IsCrossAppDomainOptimizable(m_pCliMD, &m_numStackSlotsToCopy);
- if (RemotableMethodInfo::IsCallNotOptimizable(m_xret))
- {
-#ifdef _DEBUG
- DefineFullyQualifiedNameForClass();
- LPCUTF8 szSrvTypeName = GetFullyQualifiedNameForClassNestedAware(m_pCliMD->GetMethodTable());
- LOG((LF_REMOTING, LL_INFO100, "CheckCrossDomainCall. Call to %s::%s is not optimizable\n",
- &szSrvTypeName[0], m_pCliMD->GetName()));
-#endif // _DEBUG
- return FALSE;
- }
-
- m_pCliDomain = SystemDomain::GetCurrentDomain();
- m_pSrvDomain = ADID(domainID);
-
- return ExecuteCrossDomainCall();
-}
-
-// Dereference the server identity handle, to reach the server object
-// If the handle is null, someone either called Disconnect on the server
-// or the server's lease ran out
-OBJECTREF CrossDomainChannel::GetServerObject()
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- THROWS;
- GC_TRIGGERS;
- }
- CONTRACTL_END
-
- _ASSERTE(m_pSrvDomain == SystemDomain::GetCurrentDomain()->GetId());
-
- OBJECTREF refSrvIdentity = ObjectFromHandle(m_refSrvIdentity);
- if (refSrvIdentity == NULL)
- {
- OBJECTREF refTP = m_pFrame->GetThis();
- REALPROXYREF refRP = CTPMethodTable::GetRP(refTP);
- OBJECTREF refIdentity = ObjectToOBJECTREF((Object *)refRP->GetPtrOffset(CRemotingServices::GetOffsetOfCliIdentityInRP()));
- STRINGREF refURI = (STRINGREF)ObjectToOBJECTREF((Object *)refIdentity->GetPtrOffset(CRemotingServices::GetOffsetOfURIInIdentity()));
- SString sURI;
- refURI->GetSString(sURI);
-
- COMPlusThrow(kRemotingException,
- IDS_REMOTING_SERVER_DISCONNECTED,
- sURI.GetUnicode());
- }
- OBJECTREF srvObject = ObjectToOBJECTREF((Object *)refSrvIdentity->GetPtrOffset(CRemotingServices::GetOffsetOfTPOrObjInIdentity()));
- return srvObject;
-}
-
-// Here the we find the target method address, make a decision whether to
-// execute the call locally, if remote whether to blit the arguments or to marshal them,
-BOOL CrossDomainChannel::ExecuteCrossDomainCall()
-{
- STATIC_CONTRACT_THROWS;
- STATIC_CONTRACT_GC_TRIGGERS;
- STATIC_CONTRACT_MODE_COOPERATIVE;
-
- BOOL bOptimizable = TRUE;
-
- {
- ProfilerRemotingClientCallbackHolder profilerHolder;
-
- // Short circuit calls to Object::GetType and run them locally
- if (m_pCliMD == CRemotingServices::MDofObjectGetType())
- {
- LOG((LF_REMOTING, LL_INFO100, "ExecuteCrossDomainCall. Short circuiting call to Object::GetType and running it locally.\n"));
- OBJECTREF refTP = m_pFrame->GetThis();
- OBJECTREF refType = CRemotingServices::GetClass(refTP);
- LPVOID pReturnValuePtr = m_pFrame->GetReturnValuePtr();
- *(Object **)pReturnValuePtr = OBJECTREFToObject(refType);
- }
- else if (RemotableMethodInfo::AreArgsBlittable(m_xret))
- {
- bOptimizable = BlitAndCall();
- }
- else
- {
- bOptimizable = MarshalAndCall();
- }
- }
-
- if (!bOptimizable)
- return FALSE;
-
- // Check for the need to trip thread
- if (GetThread()->CatchAtSafePointOpportunistic())
- {
- // There is no need to GC protect the return object as
- // TPFrame is GC protecting it
- CommonTripThread();
- }
-
-#ifdef _TARGET_X86_
- // Set the number of bytes to pop for x86
- m_pFrame->SetCbStackPop(m_numStackSlotsToCopy * sizeof(SIZE_T));
-#endif // _TARGET_X86_
-
- return TRUE;
-}
-
-BOOL
-CrossDomainChannel::InitServerInfo()
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- THROWS;
- GC_TRIGGERS;
- }
- CONTRACTL_END
-
- _ASSERTE(m_pFrame);
- _ASSERTE(m_pSrvDomain == SystemDomain::GetCurrentDomain()->GetId());
-
- // Get the server object
- OBJECTREF refTP = m_pFrame->GetThis();
- REALPROXYREF refRP = CTPMethodTable::GetRP(refTP);
- m_refSrvIdentity = (OBJECTHANDLE)refRP->GetPtrOffset(CRemotingServices::GetOffsetOfSrvIdentityInRP());
- OBJECTREF srvObject = GetServerObject();
-
- MethodTable *pSrvMT = srvObject->GetMethodTable();
-
- // Find the target address
- DWORD optFlag = refRP->GetOptFlags();
-
- // If we are cloning some arguments to server domain, we want to do a type check
- // on the cloned objects against the expected type. To find the expected type, we need to
- // know the method signature on the server side, which in turn is obtainable if we know
- // the server MethodDesc. Finding MethodDesc from a slot isnt cheap, so we do it only if we need it
- BOOL bFindServerMD = (RemotableMethodInfo::AreArgsBlittable(m_xret)) ? FALSE : TRUE;
- BOOL bResultOfAddressLookup = FALSE;
-
- if (m_pCliMD->GetMethodTable()->IsInterface())
- {
- bResultOfAddressLookup = GetInterfaceMethodAddressFast(optFlag, pSrvMT, bFindServerMD);
- }
- else if ((optFlag & OPTIMIZATION_FLAG_INITTED) && (optFlag & OPTIMIZATION_FLAG_PROXY_EQUIVALENT))
- {
- bResultOfAddressLookup = GetTargetAddressFast(optFlag, pSrvMT, bFindServerMD);
- }
- else
- {
- // If the proxy is not cast to an equivalent type, do not perform any optimizations
- bResultOfAddressLookup = FALSE;
- }
-
-#ifdef _DEBUG
- if (!bResultOfAddressLookup)
- LOG((LF_REMOTING, LL_INFO100, "InitServerInfo. Skipping fast path because failed to find target address.\n"));
-#endif // _DEBUG
-
- _ASSERTE(!bResultOfAddressLookup || !bFindServerMD || m_pSrvMD);
- return bResultOfAddressLookup;
-}
-
-// A macro used to help calculate the exact declaring type of a method (this may not be as simple as calling GetMethodTable on the
-// method desc if the type is generic and not an interface). We get the additional information from the instance (which provides an
-// exact method table, though not necessarily the one the method is actually _declared_ on). We don't compute the instance or the
-// method table from that instance in this macro since the logic varies greatly from client to server (the client has to adjust for
-// the fact that the instance is a TP).
-// We assume a variable called thDeclaringType has already been declared in the current scope.
-#define CDC_DETERMINE_DECLARING_TYPE(_pMD, _thInst) \
- if (!(_pMD)->HasClassInstantiation() || (_pMD)->IsInterface()) \
- { \
- thDeclaringType = TypeHandle((_pMD)->GetMethodTable()); \
- } \
- else \
- { \
- Instantiation inst = (_pMD)->GetExactClassInstantiation(_thInst); \
- MethodTable *pApproxDeclaringMT = (_pMD)->GetMethodTable(); \
- thDeclaringType = ClassLoader::LoadGenericInstantiationThrowing(pApproxDeclaringMT->GetModule(), \
- pApproxDeclaringMT->GetCl(), \
- inst); \
- }
-
-// We have decided the arguments are blittable. We may still need to marshal
-// call context if any.
-BOOL
-CrossDomainChannel::BlitAndCall()
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END
-
- SIZE_T *pRegArgs = NULL;
- SIZE_T *pStackArgs = NULL;
-#ifdef CALLDESCR_ARGREGS
- ArgumentRegisters RegArgs = {0};
- pRegArgs = (SIZE_T*)&RegArgs;
-#endif
-#ifdef CALLDESCR_FPARGREGS
- FloatArgumentRegisters *pFloatArgumentRegisters = NULL;
-#endif
-
- BOOL bOptimizable = TRUE;
- BOOL bHasObjRefReturnVal = FALSE;
-
- Thread *pCurThread = GetThread();
-
-#ifdef _DEBUG
- LPCUTF8 pszMethodName;
- pszMethodName = m_pCliMD->GetName();
- LOG((LF_REMOTING, LL_INFO100, "BlitAndCall. Blitting arguments to method %s\n", pszMethodName));
-#endif // _DEBUG
-
- // Collect all client domain GC references together in a single GC frame.
- // refReturnValue contains the returned object.
- // It can also contain a boxed object when the return is a value type and needs marshalling
- struct _gc {
- OBJECTREF refReturnValue;
- OBJECTREF refException;
- OBJECTREF refExecutionContext;
- OBJECTREF refPrincipal;
- } ClientGC;
- ZeroMemory(&ClientGC, sizeof(ClientGC));
- GCPROTECT_BEGIN(ClientGC);
-
- _ASSERTE(RemotableMethodInfo::IsReturnBlittable(m_xret));
-
- // Check for any logical call context that contains data
- BOOL bMarshalCallContext = FALSE;
- BOOL bMarshalReturnCallContext = FALSE;
- if (pCurThread->IsExposedObjectSet())
- {
- THREADBASEREF ref = (THREADBASEREF) pCurThread->GetExposedObjectRaw();
- _ASSERTE(ref != NULL);
-
- EXECUTIONCONTEXTREF refExecCtx = (EXECUTIONCONTEXTREF) ref->GetExecutionContext();
- if (refExecCtx != NULL)
- {
- ClientGC.refExecutionContext = refExecCtx;
- ClientGC.refPrincipal = ReadPrincipal();
-
- LOGICALCALLCONTEXTREF refLogCallCtx = refExecCtx->GetLogicalCallContext();
- if (refLogCallCtx != NULL)
- {
- if (refLogCallCtx->ContainsDataForSerialization())
- {
- bMarshalCallContext = TRUE;
- }
- }
- }
- }
-
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // Assume that exception at server was NotCorrupting
- CorruptionSeverity severity = NotCorrupting;
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
- // Push the frame
- ENTER_DOMAIN_ID(m_pSrvDomain);
-
- // Now create a server domain GC frame for all server side GC references.
- struct _gc {
- OBJECTREF refReturnValue;
- OBJECTREF refException;
- OBJECTREF refExecutionContext;
- } ServerGC;
- ZeroMemory(&ServerGC, sizeof(ServerGC));
- GCPROTECT_BEGIN(ServerGC);
-
- // Initialize server side info, such as method address etc
- bOptimizable = InitServerInfo();
-
- if (!bOptimizable)
- goto LeaveDomain;
-
- RenewLease();
-
- if (bMarshalCallContext)
- {
- LOG((LF_REMOTING, LL_INFO100, "BlitAndCall. Marshalling call context\n", pszMethodName));
- CrossAppDomainClonerCallback cadcc;
- ObjectClone Marshaller(&cadcc, CrossAppDomain, FALSE);
- ServerGC.refExecutionContext = Marshaller.Clone(ClientGC.refExecutionContext,
- m_pCliDomain,
- GetAppDomain(),
- ClientGC.refExecutionContext);
- THREADBASEREF ref = (THREADBASEREF) pCurThread->GetExposedObjectRaw();
- _ASSERTE(ref != NULL);
-
- ref->SetExecutionContext(ServerGC.refExecutionContext);
-
- Marshaller.RemoveGCFrames();
- }
- else if (pCurThread->IsExposedObjectSet())
- {
- THREADBASEREF ref = (THREADBASEREF) pCurThread->GetExposedObjectRaw();
- _ASSERTE(ref != NULL);
-
- ref->SetExecutionContext(NULL);
- }
-
-#ifdef PROFILING_SUPPORTED
- // If we're profiling, notify the profiler that we're about to invoke the remoting target
- {
- BEGIN_PIN_PROFILER(CORProfilerTrackRemoting());
- GCX_PREEMP();
- g_profControlBlock.pProfInterface->RemotingServerInvocationStarted();
- END_PIN_PROFILER();
- }
-#endif // PROFILING_SUPPORTED
-
- {
- GCX_COOP();
- UINT64 uRegTypeMap = 0;
- pStackArgs = (SIZE_T *)(m_pFrame->GetTransitionBlock() + TransitionBlock::GetOffsetOfArgs());
-
- // Get the 'this' object
- OBJECTREF srvObject = GetServerObject();
-
-#if defined(_TARGET_X86_)
- pRegArgs[0] = *((SIZE_T*)(m_pFrame->GetTransitionBlock() + TransitionBlock::GetOffsetOfArgumentRegisters()));
- pRegArgs[1] = (SIZE_T) OBJECTREFToObject(srvObject);
-#elif defined(CALLDESCR_ARGREGS)
- // Have to buffer argument registers since we're going to overwrite the this object with the server
- // version and the frame owning the registers is in the wrong domain to report that object.
- pRegArgs[0] = (SIZE_T) OBJECTREFToObject(srvObject);
- memcpy(pRegArgs + 1,
- (SIZE_T*)(m_pFrame->GetTransitionBlock() + TransitionBlock::GetOffsetOfArgumentRegisters()) + 1,
- sizeof(ArgumentRegisters) - sizeof(SIZE_T));
-
-#ifdef CALLDESCR_FPARGREGS
- // Only provide a pointer to the floating point area of the stack frame if there any any floating
- // point arguments (passing NULL optimizes the CallDescr thunk by omitting the initialization of
- // floating point argument registers).
- if (RemotableMethodInfo::DoArgsContainAFloat(m_xret))
- pFloatArgumentRegisters = (FloatArgumentRegisters*)(m_pFrame->GetTransitionBlock() + TransitionBlock::GetOffsetOfFloatArgumentRegisters());
-#endif // CALLDESCR_FPARGREGS
-
-#else // CALLDESCR_ARGREGS
-
- // It's a pity that we have to allocate a buffer for the arguments on the stack even in BlitAndCall().
- // The problem is we can't use the portion of the stack protected by m_pFrame to store the srvObject,
- // since the srvObject is in the server domain and the TPMethodFrame m_pFrame is in the client domain.
- // I don't think we need to protect the srvOjbect in this case, since it's reachable from the transparent
- // proxy, which is protected by the TPMethodFrame.
- SIZE_T* pTmpStackArgs = (SIZE_T*)_alloca(m_numStackSlotsToCopy * sizeof(SIZE_T));
- memcpy(pTmpStackArgs, pStackArgs, m_numStackSlotsToCopy * sizeof(SIZE_T));
- pStackArgs = pTmpStackArgs;
-
- pStackArgs[0] = (SIZE_T)OBJECTREFToObject(srvObject);
-#endif // CALLDESCR_ARGREGS
-
-#if defined(CALLDESCR_REGTYPEMAP) || defined(COM_STUBS_SEPARATE_FP_LOCATIONS)
- // We have to copy the floating point registers from a different stack location to the portion of
- // the stack used to save the general registers. Since this is expensive, we only do this if
- // we have some floating point arguments.
- if (RemotableMethodInfo::DoArgsContainAFloat(m_xret))
- {
- // When computing the method signature we need to take special care if the call is on a non-interface class with a
- // generic instantiation (since in that case we may have a representative method with a non-concrete signature).
- TypeHandle thDeclaringType;
- CDC_DETERMINE_DECLARING_TYPE(m_pCliMD, TypeHandle(CTPMethodTable::GetMethodTableBeingProxied(m_pFrame->GetThis())));
- MetaSig mSig(m_pCliMD, thDeclaringType);
- ArgIterator argit(&mSig);
-
- int offset;
- while (TransitionBlock::InvalidOffset != (offset = argit.GetNextOffset()))
- {
- int regArgNum = TransitionBlock::GetArgumentIndexFromOffset(offset);
-
- if (regArgNum >= NUM_ARGUMENT_REGISTERS)
- break;
-
- CorElementType argTyp = argit.GetArgType();
-
-#ifdef CALLDESCR_REGTYPEMAP
- FillInRegTypeMap(offset, argTyp, (BYTE*)&uRegTypeMap);
-#endif
-
-#ifdef COM_STUBS_SEPARATE_FP_LOCATIONS
- if (argTyp == ELEMENT_TYPE_R4 || argTyp == ELEMENT_TYPE_R8)
- {
- PVOID pSrc = (PVOID)(m_pFrame->GetTransitionBlock() + m_pFrame->GetFPArgOffset(regArgNum));
-
- ARG_SLOT val;
- if (argTyp == ELEMENT_TYPE_R4)
- val = FPSpillToR4(pSrc);
- else
- val = FPSpillToR8(pSrc);
-
- *(ARG_SLOT*)(&pStackArgs[regArgNum]) = val;
- }
-#endif
- }
- }
-#endif // CALLDESCR_REGTYPEMAP || COM_STUBS_SEPARATE_FP_LOCATIONS
-
- CallDescrData callDescrData;
-
- callDescrData.pSrc = pStackArgs;
- callDescrData.numStackSlots = m_numStackSlotsToCopy,
-#ifdef CALLDESCR_ARGREGS
- callDescrData.pArgumentRegisters = (ArgumentRegisters *)pRegArgs;
-#endif
-#ifdef CALLDESCR_FPARGREGS
- callDescrData.pFloatArgumentRegisters = pFloatArgumentRegisters;
-#endif
-#ifdef CALLDESCR_REGTYPEMAP
- callDescrData.dwRegTypeMap = uRegTypeMap;
-#endif
- callDescrData.fpReturnSize = GetFPReturnSize();
- callDescrData.pTarget = m_pTargetAddress;
-
- DispatchCall(
- &callDescrData,
- &ServerGC.refException,
- GET_CTX_TRANSITION_FRAME()
- COMMA_CORRUPTING_EXCEPTIONS_ONLY(&severity)
- );
-
- // If the return value is a GC ref, store it in a protected place
- if (ServerGC.refException != NULL)
- {
- // Return value is invalid if there was exception thrown
- }
- else
- if (RemotableMethodInfo::IsReturnGCRef(m_xret))
- {
- ServerGC.refReturnValue = ObjectToOBJECTREF(*(Object **)(&callDescrData.returnValue));
- bHasObjRefReturnVal = TRUE;
- }
- else
- {
- memcpyNoGCRefs(m_pFrame->GetReturnValuePtr(), &callDescrData.returnValue, sizeof(callDescrData.returnValue));
- }
- }
-
-#ifdef PROFILING_SUPPORTED
- {
- BEGIN_PIN_PROFILER(CORProfilerTrackRemoting());
- GCX_PREEMP();
- g_profControlBlock.pProfInterface->RemotingServerInvocationReturned();
- END_PIN_PROFILER();
- }
-#endif // PROFILING_SUPPORTED
-
- // Propagate any logical call context changes except those to the principal
- if (pCurThread->IsExposedObjectSet())
- {
- THREADBASEREF ref = (THREADBASEREF) pCurThread->GetExposedObjectRaw();
- _ASSERTE(ref != NULL);
-
- EXECUTIONCONTEXTREF refExecCtx = (EXECUTIONCONTEXTREF) ref->GetExecutionContext();
- if (refExecCtx != NULL)
- {
- LOGICALCALLCONTEXTREF refLogCallCtx = refExecCtx->GetLogicalCallContext();
- if (bMarshalCallContext ||
- (refLogCallCtx != NULL && refLogCallCtx->ContainsNonSecurityDataForSerialization()))
- {
- ServerGC.refExecutionContext = ref->GetExecutionContext();
- bMarshalReturnCallContext = TRUE;
- LOG((LF_REMOTING, LL_INFO100, "BlitAndCall. Marshalling return call context\n", pszMethodName));
- CrossAppDomainClonerCallback cadcc;
- ObjectClone Marshaller(&cadcc, CrossAppDomain, FALSE);
-
- ResetPrincipal();
-
- EXECUTIONCONTEXTREF ecref = (EXECUTIONCONTEXTREF)Marshaller.Clone(ServerGC.refExecutionContext,
- GetAppDomain(),
- m_pCliDomain,
- ServerGC.refExecutionContext);
- if (ClientGC.refExecutionContext != NULL)
- ((EXECUTIONCONTEXTREF)ClientGC.refExecutionContext)->SetLogicalCallContext(ecref->GetLogicalCallContext());
- else
- ClientGC.refExecutionContext = (OBJECTREF)ecref;
-
- Marshaller.RemoveGCFrames();
- }
- }
- }
-
- if (ServerGC.refException != NULL)
- {
- LOG((LF_REMOTING, LL_INFO100, "BlitAndCall. Exception thrown ! Marshalling exception. \n", pszMethodName));
-
- // Save Watson buckets before the exception object is changed
- if (GetThread() != NULL)
- {
- // Ensure that we have the buckets for the exception in question.
- // For preallocated exceptions, we capture the buckets in the
- // UE WatsonBucket Tracker in AppDomainTransitionExceptionFilter.
- //
- // When the exception is reraised in the returning AppDomain,
- // StackTraceInfo::AppendElement will copy over the buckets
- // to the EHtracker corresponding to the raised exception.
- if (!CLRException::IsPreallocatedExceptionObject(ServerGC.refException))
- {
- // For non-preallocated exception objects, the throwable
- // is expected have the buckets in it, assuming that
- // CLR's personality routine for managed code was notified
- // of the exception before returning from the AD transition.
- //
- // There are scenarios where few managed frames, post AD transition,
- // may get optimized away by the JIT. If a managed exception is
- // thrown from within the VM at a later time, the personality routine
- // for managed will not be invoked if there are no managed frames present
- // between the AD Transition frame and the frame where VM raised the managed
- // exception.
- //
- // When such an exception comes back to the calling AppDomain, we will
- // come here and look for watson buckets and may not find them. In such
- // a case, simply log it.
- if(!((EXCEPTIONREF)ServerGC.refException)->AreWatsonBucketsPresent())
- {
- LOG((LF_EH, LL_INFO100, "CrossDomainChannel::BlitAndCall: Watson buckets not found in regular exception object. Exception likely raised in native code.\n"));
- }
- }
- }
-
- CrossAppDomainClonerCallback cadcc;
- ObjectClone Marshaller(&cadcc, CrossAppDomain, FALSE);
- ClientGC.refException = Marshaller.Clone(ServerGC.refException, GetAppDomain(), m_pCliDomain, ServerGC.refExecutionContext);
-
- Marshaller.RemoveGCFrames();
-
- // We have to be in the right domain before we throw the exception
- goto LeaveDomain;
- }
-
- if (bHasObjRefReturnVal)
- {
- // Must be a domain agile GC ref. We can just copy the reference into the client GC frame.
- ClientGC.refReturnValue = ServerGC.refReturnValue;
- }
-
-LeaveDomain: ;
-
- GCPROTECT_END(); // ServerGC
-
- END_DOMAIN_TRANSITION;
-
- if (ClientGC.refException != NULL)
- {
- RestorePrincipal(&ClientGC.refPrincipal);
- COMPlusThrow(ClientGC.refException
- COMMA_CORRUPTING_EXCEPTIONS_ONLY(severity)
- );
- }
-
- if (pCurThread->IsExposedObjectSet())
- {
- THREADBASEREF ref = (THREADBASEREF) pCurThread->GetExposedObjectRaw();
- _ASSERTE(ref != NULL);
-
- ref->SetExecutionContext(ClientGC.refExecutionContext);
- }
-
- RestorePrincipal(&ClientGC.refPrincipal);
-
- // If the return type is an object, take it out of the protected ref
- if (bHasObjRefReturnVal)
- {
- *(Object **)m_pFrame->GetReturnValuePtr() = OBJECTREFToObject(ClientGC.refReturnValue);
- }
-
- GCPROTECT_END(); // ClientGC
-
- return bOptimizable;
-}
-
-// Argument attributes
-#define ARG_NEEDS_UNBOX 0x80000000
-#define ARG_GOES_IN_EDX 0x40000000
-#define ARG_IS_BYREF 0x20000000
-#define ARG_OFFSET_MASK 0x00FFFFFF
-
-// Structure to hold arguments for MarshalAndCall
-struct MarshalAndCallArgs : public CtxTransitionBaseArgs
-{
- MarshalAndCallArgs() : Marshaller(&cadcc, CrossAppDomain, FALSE)
- {
- STATIC_CONTRACT_SO_INTOLERANT;
- }
-
- CrossDomainChannel * pThis;
-
- struct _gc {
- OBJECTREF refReturnValue;
- OBJECTREF refException;
- OBJECTREF refExecutionContext;
- OBJECTREF refPrincipal;
- } ClientGC;
-
- BOOL bOptimizable;
-
- ObjectClone Marshaller;
- CrossAppDomainClonerCallback cadcc;
-
- MetaSig *mSig;
- ArgIterator *argit;
-
- DWORD dwNumArgs;
-#ifdef CALLDESCR_ARGREGS
- SIZE_T *pRegArgs;
-#endif
-#ifdef CALLDESCR_FPARGREGS
- FloatArgumentRegisters *pFloatArgumentRegisters;
-#endif
- SIZE_T *pStackArgs;
- DWORD *pArgAttribs;
-
- DWORD dwNumObjectsMarshalled;
- BOOL *bMarshalledArgs;
- OBJECTREF *pClientArgArray;
-
- BOOL bHasByRefArgsToMarshal;
- int *pByRefArgAttribs;
- TypeHandle *pThByRefs;
-
- TypeHandle retTh;
- BOOL bHasObjRefReturnVal;
- BOOL bHasRetBuffArg;
- BOOL bHasValueTypeReturnValToMarshal;
-
- BOOL bMarshalCallContext;
- BOOL bMarshalReturnCallContext;
-
-#ifdef CALLDESCR_REGTYPEMAP
- UINT64 uRegTypeMap;
-#endif
-
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- CorruptionSeverity severity;
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-};
-
-// Simple wrapper to go from C to C++.
-void MarshalAndCall_Wrapper2(MarshalAndCallArgs * pArgs)
-{
- WRAPPER_NO_CONTRACT;
-
- pArgs->pThis->MarshalAndCall_Wrapper(pArgs);
-}
-
-void CrossDomainChannel::MarshalAndCall_Wrapper(MarshalAndCallArgs * pArgs)
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END;
-
- // Set up a rip-cord that will immediately stop us reporting GC references we're keeping alive in the Marshaller that was passed
- // to us in the event that this appdomain is unloaded underneath our feet. This avoids us keeping any server objects alive after
- // their domain has unloaded.
- ReportClonerRefsHolder sHolder(&pArgs->Marshaller);
-
- Thread* pCurThread = GetThread();
- AppDomain* pCurAppDomain = GetAppDomain();
-
- // Now create a server domain GC frame for all non-arg server side GC references.
- struct _gc {
- OBJECTREF refReturnValue;
- OBJECTREF refException;
- OBJECTREF refExecutionContext;
- } ServerGC;
- ZeroMemory(&ServerGC, sizeof(ServerGC));
- GCPROTECT_BEGIN(ServerGC);
-
- // And a variable sized array and frame of marshaled arg GC references.
- OBJECTREF *pServerArgArray = NULL;
- pServerArgArray = (OBJECTREF *) _alloca(pArgs->dwNumObjectsMarshalled * sizeof(OBJECTREF));
- ZeroMemory(pServerArgArray, sizeof(OBJECTREF) * pArgs->dwNumObjectsMarshalled);
-
- TypeHandle* pServerArgTH = (TypeHandle *) _alloca(pArgs->dwNumObjectsMarshalled * sizeof(TypeHandle));
- GCPROTECT_ARRAY_BEGIN(pServerArgArray[0], pArgs->dwNumObjectsMarshalled);
-
- // Initialize server side info, such as method address etc
- pArgs->bOptimizable = InitServerInfo();
-
- if (!pArgs->bOptimizable)
- goto LeaveDomain;
-
- RenewLease();
-
- // First clone objref arguments into the called domain
- if (!RemotableMethodInfo::AreArgsBlittable(m_xret))
- {
- // When computing the method signature we need to take special care if the call is on a non-interface class with a
- // generic instantiation (since in that case we may have a representative method with a non-concrete signature).
- TypeHandle thDeclaringType;
- CDC_DETERMINE_DECLARING_TYPE(m_pSrvMD, TypeHandle(GetServerObject()->GetTypeHandle()));
- MetaSig mSrvSideSig(m_pSrvMD, thDeclaringType);
- DWORD dwMarshalledArg = 0;
- for (DWORD i = 0; i < pArgs->dwNumArgs; i++)
- {
- CorElementType cType = mSrvSideSig.NextArg();
- if (pArgs->bMarshalledArgs[i] != TRUE)
- {
- // Make sure argument type is loaded
- if (cType == ELEMENT_TYPE_VALUETYPE)
- {
- mSrvSideSig.GetLastTypeHandleThrowing();
- }
- continue;
- }
-
- TypeHandle argTh;
- if (cType == ELEMENT_TYPE_BYREF)
- mSrvSideSig.GetByRefType(&argTh);
- else
- argTh = mSrvSideSig.GetLastTypeHandleThrowing();
-
- pServerArgTH[dwMarshalledArg] = argTh;
- pServerArgArray[dwMarshalledArg] = pArgs->Marshaller.Clone(pArgs->pClientArgArray[dwMarshalledArg],
- argTh,
- m_pCliDomain,
- pCurAppDomain,
- pArgs->ClientGC.refExecutionContext);
- dwMarshalledArg++;
- }
-
- // Make sure return type is loaded
- TypeHandle thReturn = mSrvSideSig.GetRetTypeHandleThrowing();
- _ASSERTE(!thReturn.IsNull());
-
- if (pArgs->bHasValueTypeReturnValToMarshal)
- {
- // The return is a value type which could have GC ref fields. Allocate a boxed value type so that the
- // return value goes into that. During return from call we'll clone it and copy it onto the stack
- ServerGC.refReturnValue = thReturn.AsMethodTable()->Allocate();
- }
- }
-
- // Then clone the call context if any
- if (pArgs->bMarshalCallContext)
- {
-#ifdef _DEBUG
- LOG((LF_REMOTING, LL_INFO100, "MarshalAndCall. Marshalling call context\n"));
-#endif
- ServerGC.refExecutionContext = pArgs->Marshaller.Clone(pArgs->ClientGC.refExecutionContext,
- m_pCliDomain,
- pCurAppDomain,
- pArgs->ClientGC.refExecutionContext);
- THREADBASEREF ref = (THREADBASEREF) pCurThread->GetExposedObjectRaw();
- _ASSERTE(ref != NULL);
-
- ref->SetExecutionContext(ServerGC.refExecutionContext);
- }
- else if (pCurThread->IsExposedObjectSet())
- {
- THREADBASEREF ref = (THREADBASEREF) pCurThread->GetExposedObjectRaw();
- _ASSERTE(ref != NULL);
-
- ref->SetExecutionContext(NULL);
- }
-
-#ifdef PROFILING_SUPPORTED
- // If we're profiling, notify the profiler that we're about to invoke the remoting target
- {
- BEGIN_PIN_PROFILER(CORProfilerTrackRemoting());
- GCX_PREEMP();
- g_profControlBlock.pProfInterface->RemotingServerInvocationStarted();
- END_PIN_PROFILER();
- }
-#endif // PROFILING_SUPPORTED
-
- {
- GCX_COOP();
- if (!RemotableMethodInfo::AreArgsBlittable(m_xret))
- {
- // Next place arguments into the destination array
- // No GC should occur between now and call dispatch
- for (DWORD i = 0 ; i < pArgs->dwNumObjectsMarshalled; i++)
- {
- BOOL bNeedUnbox = pArgs->pArgAttribs[i] & ARG_NEEDS_UNBOX;
- BOOL bGoesInEDX = pArgs->pArgAttribs[i] & ARG_GOES_IN_EDX;
- BOOL bIsByRef = pArgs->pArgAttribs[i] & ARG_IS_BYREF;
- DWORD dwOffset = pArgs->pArgAttribs[i] & ARG_OFFSET_MASK;
-
- SIZE_T *pDest = NULL;
-
-#if defined(_TARGET_X86_)
- if (bGoesInEDX)
- {
- // This has to be EDX for this platform.
- pDest = pArgs->pRegArgs;
- }
- else
- {
- pDest = (SIZE_T *)((BYTE *)(pArgs->pStackArgs) + dwOffset);
- }
-#elif defined(CALLDESCR_ARGREGS)
- // To help deal with the fact that a single argument can span both registers and stack
- // we've ensured that the register and stack buffers are contiguous and encoded all offsets
- // from the beginning of the register buffer.
- pDest = (SIZE_T *)((BYTE *)(pArgs->pRegArgs) + dwOffset);
-#else
- pDest = (SIZE_T *)((BYTE *)(pArgs->pStackArgs) + dwOffset);
-#endif
-
- if (bNeedUnbox && !bIsByRef)
- {
- pServerArgTH[i].GetMethodTable()->UnBoxIntoUnchecked(pDest, pServerArgArray[i]);
- }
- else if (bIsByRef)
- {
- if (bNeedUnbox)
- {
- // We don't use the fast path for byref nullables, so UnBox() can be used
- *pDest = (SIZE_T)pServerArgArray[i]->UnBox();
- }
- else
- {
- // Point to the OBJECTREF
- *pDest = (SIZE_T)&pServerArgArray[i];
- }
- }
- else
- {
- *pDest = (SIZE_T)OBJECTREFToObject(pServerArgArray[i]);
- }
- }
- }
-
- // Get the 'this' object
- OBJECTREF srvObject = GetServerObject();
- LPVOID pvRetBuff = NULL;
-
- FrameWithCookie<ProtectValueClassFrame>* pProtectValueClassFrame = NULL;
- ValueClassInfo* pValueClasses = NULL;
-
- if (pArgs->bHasRetBuffArg)
- {
- // Need some sort of check here that retTH has been initialized?
- MethodTable* pMT = pArgs->retTh.GetMethodTable();
- _ASSERTE_MSG(pMT != NULL, "GetRetType failed?");
- if (pMT->IsStructRequiringStackAllocRetBuf())
- {
- SIZE_T sz = pMT->GetNumInstanceFieldBytes();
- pvRetBuff = _alloca(sz);
- memset(pvRetBuff, 0, sz);
- pValueClasses = new (_alloca(sizeof(ValueClassInfo))) ValueClassInfo(pvRetBuff, pMT, pValueClasses);
- }
- else
- {
- // We don't use the fast path for values that return nullables, so UnBox() can be used
- pvRetBuff = (PVOID)ServerGC.refReturnValue->UnBox();
- }
- }
-#if defined(_TARGET_X86_)
- // Check if EDX should point to a return buffer (either stack- or heap-allocated).
- if (pArgs->bHasValueTypeReturnValToMarshal && pArgs->bHasRetBuffArg)
- {
- *(pArgs->pRegArgs) = (SIZE_T)pvRetBuff;
- }
- (pArgs->pRegArgs)[1] = (SIZE_T)OBJECTREFToObject(srvObject);
-#elif defined(CALLDESCR_ARGREGS)
- // On ARM the this pointer goes in r0 and any return buffer argument pointer in r1.
- pArgs->pRegArgs[0] = (SIZE_T)OBJECTREFToObject(srvObject);
- if (pArgs->bHasRetBuffArg)
- {
- pArgs->pRegArgs[1] = (SIZE_T)pvRetBuff;
- }
-#else // CALLDESCR_ARGREGS
-
- if (pArgs->bHasRetBuffArg)
- {
- (pArgs->pStackArgs)[0] = (SIZE_T)OBJECTREFToObject(srvObject);
- (pArgs->pStackArgs)[1] = (SIZE_T)pvRetBuff;
- }
- else
- {
- (pArgs->pStackArgs)[0] = (SIZE_T)OBJECTREFToObject(srvObject);
- }
-
-#endif // CALLDESCR_ARGREGS
-
- CallDescrData callDescrData;
-
-
- callDescrData.pSrc = pArgs->pStackArgs;
- callDescrData.numStackSlots = m_numStackSlotsToCopy,
-#ifdef CALLDESCR_ARGREGS
- callDescrData.pArgumentRegisters = (ArgumentRegisters *)pArgs->pRegArgs;
-#endif
-#ifdef CALLDESCR_FPARGREGS
- callDescrData.pFloatArgumentRegisters = pArgs->pFloatArgumentRegisters;
-#endif
-#ifdef CALLDESCR_REGTYPEMAP
- callDescrData.dwRegTypeMap = pArgs->uRegTypeMap;
-#endif
- callDescrData.fpReturnSize = GetFPReturnSize();
- callDescrData.pTarget = m_pTargetAddress;
-
- if (pValueClasses != NULL)
- {
- pProtectValueClassFrame = new (_alloca (sizeof (FrameWithCookie<ProtectValueClassFrame>)))
- FrameWithCookie<ProtectValueClassFrame>(pCurThread, pValueClasses);
- }
-
- DispatchCall(&callDescrData,
- &ServerGC.refException,
- pArgs->GetCtxTransitionFrame()
- COMMA_CORRUPTING_EXCEPTIONS_ONLY(&(pArgs->severity))
- );
-
- // If the return value is a GC ref, store it in a protected place
- if (ServerGC.refException != NULL)
- {
- // Return value is invalid if there was exception thrown
- }
- else
- if (RemotableMethodInfo::IsReturnGCRef(m_xret))
- {
- ServerGC.refReturnValue = ObjectToOBJECTREF(*(Object **)(&callDescrData.returnValue));
- pArgs->bHasObjRefReturnVal = TRUE;
- }
- else
- if (pArgs->bHasValueTypeReturnValToMarshal)
- {
- if (!pArgs->bHasRetBuffArg)
- {
- //
- // The value type return value is returned by value in this case.
- // We have to copy it back into our server object.
- //
- // We don't use the fast path for values that return nullables, so UnBox() can be used
- //
- CopyValueClass(ServerGC.refReturnValue->UnBox(), &callDescrData.returnValue, ServerGC.refReturnValue->GetMethodTable(), pCurAppDomain);
- }
- else if (pValueClasses != NULL)
- {
- // We passed a stack allocated ret buff. Copy back into the allocated server object.
- // We don't use the fast path for values that return nullables, so UnBox() can be used
- CopyValueClass(ServerGC.refReturnValue->UnBox(), pvRetBuff, ServerGC.refReturnValue->GetMethodTable(), pCurAppDomain);
- }
- // In all other cases, the return value should be in the server object already.
- }
- else
- {
- memcpyNoGCRefs(m_pFrame->GetReturnValuePtr(), &callDescrData.returnValue, sizeof(callDescrData.returnValue));
- }
-
- if (pProtectValueClassFrame != NULL)
- pProtectValueClassFrame->Pop(pCurThread);
- }
-
-#ifdef PROFILING_SUPPORTED
- {
- BEGIN_PIN_PROFILER(CORProfilerTrackRemoting());
- GCX_PREEMP();
- g_profControlBlock.pProfInterface->RemotingServerInvocationReturned();
- END_PIN_PROFILER();
- }
-#endif // PROFILING_SUPPORTED
-
- if (pCurThread->IsExposedObjectSet())
- {
- THREADBASEREF ref = (THREADBASEREF) pCurThread->GetExposedObjectRaw();
- _ASSERTE(ref != NULL);
-
- EXECUTIONCONTEXTREF refExecCtx = (EXECUTIONCONTEXTREF) ref->GetExecutionContext();
- if (refExecCtx != NULL)
- {
- LOGICALCALLCONTEXTREF refLogCallCtx = refExecCtx->GetLogicalCallContext();
- if (pArgs->bMarshalCallContext ||
- (refLogCallCtx != NULL && refLogCallCtx->ContainsNonSecurityDataForSerialization()))
- {
- ServerGC.refExecutionContext = ref->GetExecutionContext();
- pArgs->bMarshalReturnCallContext = TRUE;
-#ifdef _DEBUG
- LOG((LF_REMOTING, LL_INFO100, "MarshalAndCall. Marshalling return call context\n"));
-#endif
- ResetPrincipal();
- EXECUTIONCONTEXTREF ecref = (EXECUTIONCONTEXTREF)pArgs->Marshaller.Clone(ServerGC.refExecutionContext,
- pCurAppDomain,
- m_pCliDomain,
- ServerGC.refExecutionContext);
- if (pArgs->ClientGC.refExecutionContext != NULL)
- {
- ((EXECUTIONCONTEXTREF)pArgs->ClientGC.refExecutionContext)->SetLogicalCallContext(ecref->GetLogicalCallContext());
- }
- else
- {
- pArgs->ClientGC.refExecutionContext = (OBJECTREF)ecref;
- }
- }
- }
- }
-
-
- if (ServerGC.refException != NULL)
- {
-#ifdef _DEBUG
- LOG((LF_REMOTING, LL_INFO100, "MarshalAndCall. Exception thrown ! Marshalling exception. \n"));
-#endif
-
- // Save Watson buckets before the exception object is changed
- if (GetThread() != NULL)
- {
- // Ensure that we have the buckets for the exception in question.
- // For preallocated exceptions, we capture the buckets in the
- // UE WatsonBucket Tracker in AppDomainTransitionExceptionFilter.
- //
- // When the exception is reraised in the returning AppDomain,
- // StackTraceInfo::AppendElement will copy over the buckets
- // to the EHtracker corresponding to the raised exception.
- if (!CLRException::IsPreallocatedExceptionObject(ServerGC.refException))
- {
- // For non-preallocated exception objects, the throwable
- // should already have the buckets in it, unless it was raised in VM native code
- // and reached here before CLR's managed code exception handler could see it.
- if(!((EXCEPTIONREF)ServerGC.refException)->AreWatsonBucketsPresent())
- {
- LOG((LF_EH, LL_INFO1000, "MarshalAndCall - Regular exception object received (%p) does not contain watson buckets.\n",
- OBJECTREFToObject(ServerGC.refException)));
- }
- }
- }
-
- pArgs->ClientGC.refException = pArgs->Marshaller.Clone(ServerGC.refException,
- pCurAppDomain,
- m_pCliDomain,
- ServerGC.refExecutionContext);
- goto LeaveDomain;
- }
-
- if (!RemotableMethodInfo::IsReturnBlittable(m_xret))
- {
- LOG((LF_REMOTING, LL_INFO100, "MarshalAndCall. Marshalling return object\n"));
- // Need to marshal the return object
-
- pArgs->ClientGC.refReturnValue = pArgs->Marshaller.Clone(ServerGC.refReturnValue,
- pArgs->retTh,
- pCurAppDomain,
- m_pCliDomain,
- ServerGC.refExecutionContext);
-
- if (pArgs->bHasValueTypeReturnValToMarshal)
- {
- // Need to copy contents from temp return buffer to the original return buffer
- void *pDest;
- if (!pArgs->bHasRetBuffArg)
- {
- pDest = m_pFrame->GetReturnValuePtr();
- }
- else
- {
- pDest = *(void **)(m_pFrame->GetTransitionBlock() + pArgs->argit->GetRetBuffArgOffset());
- }
- // We don't use the fast path for values that return nullables, so UnBox() can be used
- CopyValueClass(pDest, pArgs->ClientGC.refReturnValue->UnBox(), pArgs->ClientGC.refReturnValue->GetMethodTable(), m_pCliDomain);
- }
- }
- else if (pArgs->bHasObjRefReturnVal)
- {
- // Must be a domain agile GC ref. We can just copy the reference into the client GC frame.
- pArgs->ClientGC.refReturnValue = ServerGC.refReturnValue;
- }
-
- // Marshal any by-ref args into calling domain
- if (pArgs->bHasByRefArgsToMarshal)
- {
-#ifdef _DEBUG
- LOG((LF_REMOTING, LL_INFO100, "MarshalAndCall. Marshalling by-ref args\n"));
-#endif
- int iMarshalledArg = -1;
- // Look for by ref args
- for (DWORD i = 0; i < pArgs->dwNumArgs; i++)
- {
- if (pArgs->bMarshalledArgs[i] != TRUE)
- continue;
-
- iMarshalledArg++;
-
- BOOL bNeedUnbox = pArgs->pArgAttribs[iMarshalledArg] & ARG_NEEDS_UNBOX;
- BOOL bIsByRef = pArgs->pArgAttribs[iMarshalledArg] & ARG_IS_BYREF;
-
- if (!bIsByRef)
- continue;
-
- TypeHandle argTh = pArgs->pThByRefs[iMarshalledArg];
- int offset = pArgs->pByRefArgAttribs[iMarshalledArg];
- OBJECTREF refReturn = pServerArgArray[iMarshalledArg];
- GCPROTECT_BEGIN(refReturn);
-
- refReturn = pArgs->Marshaller.Clone(refReturn,
- argTh,
- pCurAppDomain,
- m_pCliDomain,
- ServerGC.refExecutionContext);
- if (bNeedUnbox)
- {
- // We don't use the fast path for byref nullables, so UnBox() can be used
- BYTE *pTargetAddress = *((BYTE **)(m_pFrame->GetTransitionBlock() + offset));
- CopyValueClass(pTargetAddress, refReturn->UnBox(), refReturn->GetMethodTable(), m_pCliDomain);
- }
- else
- {
- SetObjectReference(*((OBJECTREF **)(m_pFrame->GetTransitionBlock() + offset)), refReturn, m_pCliDomain);
- }
- GCPROTECT_END();
- }
- }
-
- LeaveDomain:;
-
- GCPROTECT_END(); // pServerArgArray
- GCPROTECT_END(); // ServerGC
-}
-
-
-// Arguments need to be marshalled before dispatch. We walk thru each argument,
-// inspect its type, make a list of objects that need to be marshalled, cross over to the new domain,
-// marshal the objects and dispatch the call. Upon return, we marshal the return object if any and
-// by ref objects if any. Call contexts flows either way
-#ifdef _PREFAST_
-#pragma warning(push)
-#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
-#endif
-BOOL
-CrossDomainChannel::MarshalAndCall()
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END
-
- MarshalAndCallArgs args;
-
- args.bHasByRefArgsToMarshal = FALSE;
-
- args.bHasObjRefReturnVal = FALSE;
- args.bHasRetBuffArg = FALSE;
- args.bHasValueTypeReturnValToMarshal = FALSE;
-
- DWORD dwNumArgs = 0;
- DWORD dwNumObjectsMarshalled = 0;
-
- DWORD *pArgAttribs = NULL;
- BOOL *bMarshalledArgs = NULL;
- int *pByRefArgAttribs = NULL;
- TypeHandle *pThByRefs = NULL;
-
- Thread *pCurThread = GetThread();
-
-#ifdef _DEBUG
- LPCUTF8 pszMethodName;
- pszMethodName = m_pCliMD->GetName();
- LOG((LF_REMOTING, LL_INFO100, "MarshalAndCall. Marshalling arguments to method %s\n", pszMethodName));
-#endif // _DEBUG
-
- // Collect all client domain GC references together in a single GC frame.
- // refReturnValue contains the returned object when its a value type and needs marshalling
- ZeroMemory(&args.ClientGC, sizeof(args.ClientGC));
- GCPROTECT_BEGIN(args.ClientGC);
-
- // When computing the method signature we need to take special care if the call is on a non-interface class with a
- // generic instantiation (since in that case we may have a representative method with a non-concrete signature).
- TypeHandle thDeclaringType;
- CDC_DETERMINE_DECLARING_TYPE(m_pCliMD, TypeHandle(CTPMethodTable::GetMethodTableBeingProxied(m_pFrame->GetThis())));
- MetaSig mSig(m_pCliMD, thDeclaringType);
- ArgIterator argit(&mSig);
- int ofs;
-
- // NumFixedArgs() doesn't count the "this" object, but SizeOfFrameArgumentArray() does.
- dwNumArgs = mSig.NumFixedArgs();
- m_numStackSlotsToCopy = argit.SizeOfFrameArgumentArray() / sizeof(SIZE_T);
-
- // Ensure none of the following _alloca's are subject to integer overflow problems.
- DWORD dwMaxEntries = dwNumArgs > m_numStackSlotsToCopy ? dwNumArgs : m_numStackSlotsToCopy;
- DWORD dwResult;
- if (!ClrSafeInt<DWORD>::multiply(dwMaxEntries, sizeof(SIZE_T), dwResult))
- COMPlusThrowOM();
-#ifdef _PREFAST_
-#pragma warning(push)
-#pragma warning(disable:26000) // "Suppress PREFast warning about integer overflow (we're doing an umbrella check)"
-#endif
-
- args.bHasRetBuffArg = argit.HasRetBuffArg();
-
-#ifdef _TARGET_X86_
- BOOL bArgumentRegisterUsed = FALSE;
- if (args.bHasRetBuffArg)
- {
- bArgumentRegisterUsed = TRUE;
- }
-#endif // _TARGET_X86_
-
- // pArgAttribs tell where the marshalled objects should go, where they need unboxing etc
- pArgAttribs = (DWORD*) _alloca(dwNumArgs * sizeof(DWORD));
- ZeroMemory(pArgAttribs, sizeof(DWORD) * dwNumArgs);
- // pThByRefs has the typehandles of the by-ref args
- pThByRefs = (TypeHandle *)_alloca(dwNumArgs * sizeof(TypeHandle));
- ZeroMemory(pThByRefs, sizeof(TypeHandle) *dwNumArgs);
- // pByRefArgAttribs tell where the by-ref args should go, after the call
- pByRefArgAttribs = (int*) _alloca(dwNumArgs * sizeof(int));
- ZeroMemory(pByRefArgAttribs, sizeof(int) * dwNumArgs);
- // bMarshalledArgs is a bunch of flags that tell which args were marshalled
- bMarshalledArgs = (BOOL*) _alloca(dwNumArgs * sizeof(BOOL));
- ZeroMemory(bMarshalledArgs, sizeof(BOOL) * dwNumArgs);
-
- // pArgArray contains marshalled objects on the client side
- OBJECTREF *pClientArgArray = NULL;
- pClientArgArray = (OBJECTREF *) _alloca(dwNumArgs * sizeof(OBJECTREF));
- ZeroMemory(pClientArgArray, sizeof(OBJECTREF) * dwNumArgs);
- GCPROTECT_ARRAY_BEGIN(pClientArgArray[0], dwNumArgs);
-
- // pStackArgs will finally contain the arguments that'll be fed to Dispatch call. The Marshalled objects
- // are not placed directly into pStackArgs because its not possible to GCPROTECT an array that can contain
- // both GC refs and primitives.
- DWORD cbStackArgs = m_numStackSlotsToCopy * sizeof (SIZE_T);
-#ifdef CALLDESCR_ARGREGS
- // Allocate enough space to put ArgumentRegisters at the front of the buffer so we can ensure
- // register and stack arguments are stored contiguously and simply the case of unboxing a value type that
- // spans registers and the stack.
- cbStackArgs += sizeof(ArgumentRegisters);
-#endif
- SIZE_T *pStackArgs = (SIZE_T*)_alloca(cbStackArgs);
- ZeroMemory(pStackArgs, cbStackArgs);
-#ifdef CALLDESCR_ARGREGS
- SIZE_T *pRegArgs = pStackArgs;
- pStackArgs += sizeof(ArgumentRegisters) / sizeof(SIZE_T);
-#endif
-#ifdef CALLDESCR_FPARGREGS
- FloatArgumentRegisters *pFloatArgumentRegisters = NULL;
-#endif
-
-#if defined(CALLDESCR_REGTYPEMAP)
- UINT64 uRegTypeMap = 0;
- BYTE* pMap = (BYTE*)&uRegTypeMap;
-#endif
-
- TADDR pTransitionBlock = m_pFrame->GetTransitionBlock();
-
- for (int argNum = 0;
- TransitionBlock::InvalidOffset != (ofs = argit.GetNextOffset());
- argNum++
- )
- {
- DWORD dwOffsetOfArg = 0;
-
-#if defined(CALLDESCR_REGTYPEMAP)
- int regArgNum = TransitionBlock::GetArgumentIndexFromOffset(ofs);
-
- FillInRegTypeMap(ofs, argit.GetArgType(), pMap);
-#endif // defined(CALLDESCR_REGTYPEMAP)
-
- SIZE_T *pDestToCopy = NULL;
-
-#if defined(_TARGET_ARM_)
-
- // On ARM there are ranges of offset that can be returned from ArgIterator::GetNextOffset() (where R
- // == TransitionBlock::GetOffsetOfArgumentRegisters() and S == sizeof(TransitionBlock)):
- //
- // * ofs < 0 : arg is in a floating point register
- // * ofs >= R && ofs < S : arg is in a general register
- // * ofs >= S : arg is on the stack at offset (ofs - X)
- //
- // Arguments can be split between general registers and the stack on ARM and as a result both
- // FramedMethodFrame and this method ensure the storage for register and stack locations is
- // contiguous.
- int iInitialRegOffset = TransitionBlock::GetOffsetOfArgumentRegisters();
- int iInitialStackOffset = sizeof(TransitionBlock);
- _ASSERTE(iInitialStackOffset == (iInitialRegOffset + sizeof(ArgumentRegisters)));
- if (ofs < 0)
- {
- // Floating point register case. Since these registers can never hold a GC reference we can just
- // pass through a pointer to the spilled FP reg area in the frame. But we don't do this unless we
- // see at least one FP arg: passing NULL for pFloatArgumentRegisters enables an optimization in
- // the call thunk.
- if (pFloatArgumentRegisters == NULL)
- pFloatArgumentRegisters = (FloatArgumentRegisters*) (pTransitionBlock + TransitionBlock::GetOffsetOfFloatArgumentRegisters());
-
- // No arg to copy in this case.
- continue;
- }
-
- _ASSERTE(ofs >= iInitialRegOffset);
-
- // We've ensured our registers and stack locations are contiguous so treat both types of arguments
- // identically (i.e. compute a destination offset from the base of the register save area and it will
- // work for arguments that span from registers to stack or live entirely on the stack).
- dwOffsetOfArg = ofs - TransitionBlock::GetOffsetOfArgumentRegisters();
- pDestToCopy = (SIZE_T*)((BYTE *)pRegArgs + dwOffsetOfArg);
-
-#else // _TARGET_ARM_
-
- dwOffsetOfArg = ofs - TransitionBlock::GetOffsetOfArgs();
-
-#ifdef _TARGET_X86_
- if (!bArgumentRegisterUsed && gElementTypeInfo[argit.GetArgType()].m_enregister)
- {
- pDestToCopy = pRegArgs;
- bArgumentRegisterUsed = TRUE;
- }
- else
-#endif // _TARGET_X86_
- {
- _ASSERTE(dwOffsetOfArg < (m_numStackSlotsToCopy * sizeof(SIZE_T)));
- pDestToCopy = (SIZE_T*)((BYTE *)pStackArgs + dwOffsetOfArg);
- }
-
-#endif // _TARGET_ARM_
-
- CorElementType origTyp = argit.GetArgType();
-
- // Get the signature type of the argument (For ex. enum will be E_T_VT, not E_T_I4 etc)
- SigPointer sp = mSig.GetArgProps();
- CorElementType typ;
- IfFailThrow(sp.GetElemType(&typ));
-
- if (typ == ELEMENT_TYPE_VAR ||
- typ == ELEMENT_TYPE_MVAR ||
- typ == ELEMENT_TYPE_GENERICINST)
- {
- typ = origTyp;
- }
-
- switch (typ)
- {
- case ELEMENT_TYPE_BOOLEAN:
- case ELEMENT_TYPE_I1:
- case ELEMENT_TYPE_U1:
- case ELEMENT_TYPE_I2:
- case ELEMENT_TYPE_U2:
- case ELEMENT_TYPE_CHAR:
- case ELEMENT_TYPE_I4:
- case ELEMENT_TYPE_U4:
-#if !defined(COM_STUBS_SEPARATE_FP_LOCATIONS)
- case ELEMENT_TYPE_R4:
-#endif
-
-#if defined(_TARGET_X86_) || defined(_TARGET_ARM_)
- *(pDestToCopy) = *((SIZE_T*) (pTransitionBlock + ofs));
-#elif defined(_WIN64)
- switch (GetSizeForCorElementType((CorElementType)typ))
- {
- case 1:
- *(BYTE*)(pDestToCopy) = *(BYTE*)(pTransitionBlock + ofs);
- break;
-
- case 2:
- *(USHORT*)(pDestToCopy) = *(USHORT*)(pTransitionBlock + ofs);
- break;
-
- case 4:
- *(UINT*)(pDestToCopy) = *(UINT*)(pTransitionBlock + ofs);
- break;
-
- case 8:
- *(SIZE_T*)(pDestToCopy) = *(SIZE_T*)(pTransitionBlock + ofs);
- break;
-
- default:
- _ASSERTE(!"MarshalAndCall() - unexpected size");
- }
-#else // !defined(_WIN64)
- PORTABILITY_ASSERT("MarshalAndCall() - NYI on this platform");
-#endif // !defined(_WIN64)
- break;
-
- case ELEMENT_TYPE_I:
- case ELEMENT_TYPE_U:
- case ELEMENT_TYPE_PTR:
- case ELEMENT_TYPE_FNPTR:
-
- *((SIZE_T*)((BYTE *)pDestToCopy)) = *((SIZE_T*)(pTransitionBlock + ofs));
- break;
-
- case ELEMENT_TYPE_I8:
- case ELEMENT_TYPE_U8:
-#if !defined(COM_STUBS_SEPARATE_FP_LOCATIONS)
- case ELEMENT_TYPE_R8:
-#endif
-
- *((INT64*)((BYTE *)pDestToCopy)) = *((INT64 *)(pTransitionBlock + ofs));
- break;
-
-#if defined(COM_STUBS_SEPARATE_FP_LOCATIONS)
- case ELEMENT_TYPE_R4:
-
- if (regArgNum < NUM_ARGUMENT_REGISTERS)
- {
- *(ARG_SLOT*)pDestToCopy = FPSpillToR4( (LPVOID)(pTransitionBlock + m_pFrame->GetFPArgOffset(regArgNum)) );
- }
- else
- {
- *(UINT*)(pDestToCopy) = *(UINT*)(pTransitionBlock + ofs);
- }
- break;
-
- case ELEMENT_TYPE_R8:
-
- if (regArgNum < NUM_ARGUMENT_REGISTERS)
- {
- *(ARG_SLOT*)pDestToCopy = FPSpillToR8( (LPVOID)(pTransitionBlock + m_pFrame->GetFPArgOffset(regArgNum)) );
- }
- else
- {
- *(SIZE_T*)(pDestToCopy) = *(SIZE_T*)(pTransitionBlock + ofs);
- }
- break;
-#endif // defined(COM_STUBS_SEPARATE_FP_LOCATIONS)
-
- case ELEMENT_TYPE_BYREF:
- {
- // Check if this is a by-ref primitive
- OBJECTREF refTmpBox = NULL;
- TypeHandle ty = TypeHandle();
- CorElementType brType = mSig.GetByRefType(&ty);
- if (CorIsPrimitiveType(brType) || ty.IsValueType())
- {
-
- // Needs marshalling
- MethodTable *pMT = NULL;
- if (CorIsPrimitiveType(brType))
- pMT = MscorlibBinder::GetElementType(brType);
- else
- pMT = ty.GetMethodTable();
- refTmpBox = pMT->Box(*((SIZE_T**)(pTransitionBlock + ofs)));
- pArgAttribs[dwNumObjectsMarshalled] |= ARG_NEEDS_UNBOX;
- }
- else
- {
- OBJECTREF *refRefObj = *((OBJECTREF **)(pTransitionBlock + ofs));
- refTmpBox = (refRefObj == NULL ? NULL : *refRefObj);
- }
-
- pByRefArgAttribs[dwNumObjectsMarshalled] = ofs;
- pThByRefs[dwNumObjectsMarshalled] = ty;
-
- // we should have stopped nullables before we got here in DoStaticAnalysis
- _ASSERTE(ty.IsNull() || !Nullable::IsNullableType(ty));
- pArgAttribs[dwNumObjectsMarshalled] |= ARG_IS_BYREF;
-
- args.bHasByRefArgsToMarshal = TRUE;
-
- pClientArgArray[dwNumObjectsMarshalled] = refTmpBox;
- bMarshalledArgs[argNum] = TRUE;
-
-#if defined(_TARGET_X86_)
- if (pDestToCopy == pRegArgs)
- {
- pArgAttribs[dwNumObjectsMarshalled] |= ARG_GOES_IN_EDX; // Indicate that this goes in EDX
- }
- else
-#endif // _TARGET_X86_
- {
- // @TODO - Use QWORD for attribs
- _ASSERTE(dwOffsetOfArg < ARG_OFFSET_MASK);
- pArgAttribs[dwNumObjectsMarshalled] |= dwOffsetOfArg;
- }
- dwNumObjectsMarshalled++;
- }
- break;
-
- case ELEMENT_TYPE_VALUETYPE:
- {
-#if defined(COM_STUBS_SEPARATE_FP_LOCATIONS)
- if (regArgNum < NUM_ARGUMENT_REGISTERS)
- {
-
- // We have to copy the floating point registers from a different stack location to the portion of
- // the stack used to save the general registers.
- if (origTyp == ELEMENT_TYPE_R4)
- {
- LPVOID pDest = (LPVOID)(pTransitionBlock + ofs);
- *(ARG_SLOT*)pDest = FPSpillToR4( (LPVOID)(pTransitionBlock + m_pFrame->GetFPArgOffset(regArgNum)) );
- }
- else if (origTyp == ELEMENT_TYPE_R8)
- {
- LPVOID pDest = (LPVOID)(pTransitionBlock + ofs);
- *(ARG_SLOT*)pDest = FPSpillToR8( (LPVOID)(pTransitionBlock + m_pFrame->GetFPArgOffset(regArgNum)) );
- }
- }
-#endif // defined(COM_STUBS_SEPARATE_FP_LOCATIONS)
-
- TypeHandle th = mSig.GetLastTypeHandleThrowing();
-
-#ifdef _DEBUG
- {
- DefineFullyQualifiedNameForClass()
- LPCUTF8 szTypeName = GetFullyQualifiedNameForClassNestedAware(th.GetMethodTable());
- LOG((LF_REMOTING, LL_INFO100, "MarshalAndCall. Boxing a value type argument of type %s.\n", &szTypeName[0]));
- }
-#endif // _DEBUG
-
- OBJECTREF refTmpBox;
-#if defined(ENREGISTERED_PARAMTYPE_MAXSIZE)
- if (argit.IsArgPassedByRef())
- {
- refTmpBox = th.GetMethodTable()->Box(*(LPVOID*)(pTransitionBlock + ofs));
-
- // we should have stopped nullables before we got here in DoStaticAnalysis
- _ASSERTE(!Nullable::IsNullableType(th));
- pArgAttribs[dwNumObjectsMarshalled] |= ARG_IS_BYREF;
-
- pByRefArgAttribs[dwNumObjectsMarshalled] = ofs;
- pThByRefs[dwNumObjectsMarshalled] = th;
- }
- else
-#endif // defined(ENREGISTERED_PARAMTYPE_MAXSIZE)
- {
- refTmpBox = th.GetMethodTable()->Box((void *)(pTransitionBlock + ofs));
- }
- pClientArgArray[dwNumObjectsMarshalled] = refTmpBox;
- bMarshalledArgs[argNum] = TRUE;
-
-#if defined(_TARGET_X86_)
- if (pDestToCopy == pRegArgs)
- {
- pArgAttribs[dwNumObjectsMarshalled] |= ARG_GOES_IN_EDX; // Indicate that this goes in EDX
- }
- else
-#endif // _TARGET_X86_
- {
- // @TODO - Use QWORD for attribs
- _ASSERTE(dwOffsetOfArg < ARG_OFFSET_MASK);
- pArgAttribs[dwNumObjectsMarshalled] |= dwOffsetOfArg;
- }
- pArgAttribs[dwNumObjectsMarshalled] |= ARG_NEEDS_UNBOX; // Indicate that an unboxing is required
- dwNumObjectsMarshalled++;
- }
- break;
-
- case ELEMENT_TYPE_SZARRAY: // Single Dim
- case ELEMENT_TYPE_ARRAY: // General Array
- case ELEMENT_TYPE_CLASS: // Class
- case ELEMENT_TYPE_OBJECT:
- case ELEMENT_TYPE_STRING: // System.String
- case ELEMENT_TYPE_VAR:
- {
- OBJECTREF *refRefObj = (OBJECTREF *)(pTransitionBlock + ofs);
- // The frame does protect this object, so mark it as such to avoid asserts
- INDEBUG(Thread::ObjectRefNew(refRefObj);)
- INDEBUG(Thread::ObjectRefProtected(refRefObj);)
-
- pClientArgArray[dwNumObjectsMarshalled] = *refRefObj;
- bMarshalledArgs[argNum] = TRUE;
-
-#ifdef _TARGET_X86_
- if (pDestToCopy == pRegArgs)
- {
- pArgAttribs[dwNumObjectsMarshalled] |= ARG_GOES_IN_EDX; // Indicate that this goes in EDX
- }
- else
-#endif // _TARGET_X86_
- {
- // @TODO - Use QWORD for attribs
- _ASSERTE(dwOffsetOfArg < ARG_OFFSET_MASK);
- pArgAttribs[dwNumObjectsMarshalled] |= dwOffsetOfArg;
- }
- dwNumObjectsMarshalled++;
- }
- break;
-
- default:
- _ASSERTE(!"Unknown Element type in MarshalAndCall" );
- }
- }
-
- if (!RemotableMethodInfo::IsReturnBlittable(m_xret))
- {
- CorElementType retType = mSig.GetReturnType();
- if (retType == ELEMENT_TYPE_VALUETYPE)
- {
- args.retTh = mSig.GetRetTypeHandleThrowing();
- args.bHasValueTypeReturnValToMarshal = TRUE;
- }
- else
- {
- args.retTh = mSig.GetRetTypeHandleThrowing();
- }
- }
-
- // Check for any call context
- BOOL bMarshalCallContext = FALSE;
- args.bMarshalReturnCallContext = FALSE;
- if (pCurThread->IsExposedObjectSet())
- {
- THREADBASEREF ref = (THREADBASEREF) pCurThread->GetExposedObjectRaw();
- _ASSERTE(ref != NULL);
-
- EXECUTIONCONTEXTREF refExecCtx = (EXECUTIONCONTEXTREF) ref->GetExecutionContext();
- if (refExecCtx != NULL)
- {
- args.ClientGC.refExecutionContext = refExecCtx;
- args.ClientGC.refPrincipal = ReadPrincipal();
-
- LOGICALCALLCONTEXTREF refLogCallCtx = refExecCtx->GetLogicalCallContext();
- if (refLogCallCtx != NULL)
- {
- if (refLogCallCtx->ContainsDataForSerialization())
- {
- bMarshalCallContext = TRUE;
- }
- }
- }
- }
-
-#ifdef _PREFAST_
-#pragma warning(pop)
-#endif
-
- // Make the Cross-AppDomain call
- {
- args.pThis = this;
-
- args.bOptimizable = TRUE;
-
- args.mSig = &mSig;
- args.argit = &argit;
-
- args.dwNumArgs = dwNumArgs;
- args.pStackArgs = pStackArgs;
-#ifdef CALLDESCR_ARGREGS
- args.pRegArgs = pRegArgs;
-#endif
-#ifdef CALLDESCR_FPARGREGS
- args.pFloatArgumentRegisters = pFloatArgumentRegisters;
-#endif
- args.pArgAttribs = pArgAttribs;
-
- args.dwNumObjectsMarshalled = dwNumObjectsMarshalled;
- args.bMarshalledArgs = bMarshalledArgs;
- args.pClientArgArray = pClientArgArray;
-
- args.pByRefArgAttribs = pByRefArgAttribs;
- args.pThByRefs = pThByRefs;
-
- args.bMarshalCallContext = bMarshalCallContext;
-
-#ifdef CALLDESCR_REGTYPEMAP
- args.uRegTypeMap = *(UINT64*)pMap;
-#endif
-
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // By default assume that exception thrown across the cross-AD call is NotCorrupting.
- args.severity = NotCorrupting;
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
- MakeCallWithPossibleAppDomainTransition(m_pSrvDomain, (FPAPPDOMAINCALLBACK) MarshalAndCall_Wrapper2, &args);
- }
-
- if (args.ClientGC.refException != NULL)
- {
- RestorePrincipal(&args.ClientGC.refPrincipal);
- COMPlusThrow(args.ClientGC.refException
- COMMA_CORRUPTING_EXCEPTIONS_ONLY(args.severity)
- );
- }
-
- if (pCurThread->IsExposedObjectSet())
- {
- THREADBASEREF ref = (THREADBASEREF) pCurThread->GetExposedObjectRaw();
- _ASSERTE(ref != NULL);
-
- ref->SetExecutionContext(args.ClientGC.refExecutionContext);
- }
-
- RestorePrincipal(&args.ClientGC.refPrincipal);
-
- // If the return type is an object, take it out of the protected ref
- if (args.bHasObjRefReturnVal)
- {
- *(Object **)m_pFrame->GetReturnValuePtr() = OBJECTREFToObject(args.ClientGC.refReturnValue);
- }
-
- GCPROTECT_END(); // pClientArgArray
- GCPROTECT_END(); // args.ClientGC
-
- args.Marshaller.RemoveGCFrames();
-
- return args.bOptimizable;
-}
-#ifdef _PREFAST_
-#pragma warning(pop)
-#endif
-
-#endif // CROSSGEN_COMPILE
-
-#endif // FEATURE_REMOTING
diff --git a/src/vm/dataimage.cpp b/src/vm/dataimage.cpp
index f6b8337b7c..fc584d7b39 100644
--- a/src/vm/dataimage.cpp
+++ b/src/vm/dataimage.cpp
@@ -126,8 +126,7 @@ DataImage::DataImage(Module *module, CEEPreloader *preloader)
m_pZapImage->m_pDataImage = this;
m_pInternedStructures = new InternedStructureHashTable();
-
- m_inlineTrackingMap = NULL;
+ m_inlineTrackingMap = new InlineTrackingMap();
}
DataImage::~DataImage()
diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h
index abf79802b5..261d5f455f 100644
--- a/src/vm/ecalllist.h
+++ b/src/vm/ecalllist.h
@@ -1028,8 +1028,6 @@ FCFuncStart(gCultureInfoFuncs)
QCFuncElement("InternalGetUserDefaultUILanguage", COMNlsInfo::InternalGetUserDefaultUILanguage)
QCFuncElement("InternalGetSystemDefaultUILanguage", COMNlsInfo::InternalGetSystemDefaultUILanguage)
-// Added but disabled from desktop in .NET 4.0, stayed disabled in .NET 4.5
- FCFuncElement("nativeGetResourceFallbackArray", COMNlsInfo::nativeGetResourceFallbackArray)
FCFuncEnd()
FCFuncStart(gTextInfoFuncs)
diff --git a/src/vm/eeconfigfactory.cpp b/src/vm/eeconfigfactory.cpp
deleted file mode 100644
index a0eb927ce9..0000000000
--- a/src/vm/eeconfigfactory.cpp
+++ /dev/null
@@ -1,398 +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.
-// EEConfigFactory.cpp
-//
-
-//
-// Factory used to with the XML parser to read configuration files
-//
-
-#include "common.h"
-#include "ngenoptout.h"
-#include "eeconfigfactory.h"
-
-
-#define ISWHITE(ch) ((ch) >= 0x09 && (ch) <= 0x0D || (ch) == 0x20)
-
-#define CONST_STRING_AND_LEN(str) str, NumItems(str)-1
-
-
-int EEXMLStringCompare(const WCHAR *pStr1,
- DWORD cchStr1,
- const WCHAR *pStr2,
- DWORD cchStr2)
-{
- LIMITED_METHOD_CONTRACT;
- if (cchStr1 != cchStr2)
- return -1;
-
- return wcsncmp(pStr1, pStr2, cchStr1);
-}// EEXMLStringCompare
-
-
-int EEXMLStringComparei(const WCHAR *pStr1,
- DWORD cchStr1,
- const WCHAR *pStr2,
- DWORD cchStr2)
-{
- WRAPPER_NO_CONTRACT;
- if (cchStr1 != cchStr2)
- return -1;
-
- return SString::_wcsnicmp(pStr1, pStr2, cchStr1);
-}// EEXMLStringCompare
-
-
-
-EEConfigFactory::EEConfigFactory(
- ConfigStringHashtable* pTable,
- LPCWSTR pString,
- ParseCtl parseCtl)
-{
- LIMITED_METHOD_CONTRACT;
- m_pTable = pTable;
- m_pVersion = pString;
- m_dwDepth = 0;
- m_fUnderRuntimeElement = FALSE;
- m_fDeveloperSettings = FALSE;
- m_fVersionedRuntime= FALSE;
- m_fOnEnabledAttribute = FALSE;
- m_fOnValueAttribute = FALSE;
- m_pCurrentRuntimeElement = m_pBuffer;
- m_dwCurrentRuntimeElement = 0;
- m_dwSize = CONFIG_KEY_SIZE;
- m_parseCtl = parseCtl;
- m_pActiveFactory = NULL;
-}
-
-EEConfigFactory::~EEConfigFactory()
-{
- LIMITED_METHOD_CONTRACT;
- DeleteKey();
-}
-
-HRESULT STDMETHODCALLTYPE EEConfigFactory::NotifyEvent(
- /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
- /* [in] */ XML_NODEFACTORY_EVENT iEvt)
-{
- LIMITED_METHOD_CONTRACT;
- if(iEvt == XMLNF_ENDDOCUMENT) {
- // <TODO> add error handling.</TODO>
- }
- if(m_pActiveFactory != NULL)
- return m_pActiveFactory->NotifyEvent(pSource, iEvt);
-
- return S_OK;
-}
-//---------------------------------------------------------------------------
-HRESULT STDMETHODCALLTYPE EEConfigFactory::BeginChildren(
- /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
- /* [in] */ XML_NODE_INFO __RPC_FAR *pNodeInfo)
-{
- LIMITED_METHOD_CONTRACT;
-
- m_dwDepth++;
- if(m_pActiveFactory != NULL)
- return m_pActiveFactory->BeginChildren(pSource, pNodeInfo);
- return S_OK;
-
-}
-//---------------------------------------------------------------------------
-HRESULT STDMETHODCALLTYPE EEConfigFactory::EndChildren(
- /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
- /* [in] */ BOOL fEmptyNode,
- /* [in] */ XML_NODE_INFO __RPC_FAR *pNodeInfo)
-{
- LIMITED_METHOD_CONTRACT;
- if ( fEmptyNode ) {
- m_fDeveloperSettings = FALSE;
- }
- else {
- m_dwDepth--;
- }
-
- if (m_pActiveFactory != NULL)
- {
- HRESULT hr = S_OK;
- IfFailRet(m_pActiveFactory->EndChildren(pSource, fEmptyNode, pNodeInfo));
-
-
- if(m_dwDepth == 2) // when generalizing: use the current active factory depth
- {
- m_pActiveFactory = NULL;
- }
-
- }
-
- if (m_fUnderRuntimeElement && wcscmp(pNodeInfo->pwcText, W("runtime")) == 0) {
- m_fUnderRuntimeElement = FALSE;
- m_fVersionedRuntime = FALSE;
- ClearKey();
- // CLR_STARTUP_OPT:
- // Early out if we only need to read <runtime> section.
- //
- if (m_parseCtl == stopAfterRuntimeSection)
- pSource->Abort(NULL/*unused*/);
- }
-
- return S_OK;
-}
-//---------------------------------------------------------------------------
-HRESULT STDMETHODCALLTYPE EEConfigFactory::CreateNode(
- /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
- /* [in] */ PVOID pNode,
- /* [in] */ USHORT cNumRecs,
- /* [in] */ XML_NODE_INFO* __RPC_FAR * __RPC_FAR apNodeInfo)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- INJECT_FAULT(return E_OUTOFMEMORY;);
- }
- CONTRACTL_END;
-
- if(m_pActiveFactory != NULL)
- return m_pActiveFactory->CreateNode(pSource, pNode, cNumRecs, apNodeInfo);
-
- if(m_dwDepth > 3)
- {
-
- return S_OK;
- }
-
- HRESULT hr = S_OK;
- DWORD dwStringSize = 0;
- WCHAR* pszString = NULL;
- DWORD i;
- BOOL fRuntimeKey = FALSE;
- BOOL fVersion = FALSE;
-
- for( i = 0; i < cNumRecs; i++) {
- CONTRACT_VIOLATION(ThrowsViolation); // Lots of stuff in here throws!
-
- if(apNodeInfo[i]->dwType == XML_ELEMENT ||
- apNodeInfo[i]->dwType == XML_ATTRIBUTE ||
- apNodeInfo[i]->dwType == XML_PCDATA) {
-
- dwStringSize = apNodeInfo[i]->ulLen;
- pszString = (WCHAR*) apNodeInfo[i]->pwcText;
- // Trim the value
-
- // we should never decrement lgth if it's 0, because it's unsigned
-
- for(;*pszString && ISWHITE(*pszString) && dwStringSize>0; pszString++, dwStringSize--);
- while( dwStringSize > 0 && ISWHITE(pszString[dwStringSize-1]))
- dwStringSize--;
-
- // NOTE: pszString is not guaranteed to be null terminated. Use EEXMLStringCompare to do
- // string comparisions on it
-
- switch(apNodeInfo[i]->dwType) {
- case XML_ELEMENT :
- fRuntimeKey = FALSE;
- ClearKey();
-
- if (m_dwDepth == 1 && EEXMLStringCompare(pszString, dwStringSize, CONST_STRING_AND_LEN(W("runtime"))) == 0) {
- m_fUnderRuntimeElement = TRUE;
- fRuntimeKey = TRUE;
- }
-
- if(m_dwDepth == 2 && m_fUnderRuntimeElement) {
-
- // Developer settings can look like
- // <runtime>
- // <developerSettings installationVersion="v2.0.40223.0" />
- //
- // or
- //
- // <developmentMode developerInstallation="true" />
- //
- // Neither one is your standard config setting.
- if (!EEXMLStringCompare(pszString, dwStringSize, CONST_STRING_AND_LEN(W("developerSettings"))) ||
- !EEXMLStringCompare(pszString, dwStringSize, CONST_STRING_AND_LEN(W("developmentMode"))))
- {
- m_fDeveloperSettings = TRUE;
- }
- else
- // when generalizing: use map of (string, depth) -> class
- if (!EEXMLStringCompare(pszString, dwStringSize, CONST_STRING_AND_LEN(W("disableNativeImageLoad"))))
- {
- m_pActiveFactory = new NativeImageOptOutConfigFactory();
- m_pActiveFactory->AddRef();
- }
- else
- {
- // This is a standard element under the runtime node.... it could look like this
- // <runtime>
- // <pszString enabled="1" />
-
- hr = CopyToKey(pszString, dwStringSize);
- if(FAILED(hr)) return hr;
- }
- }
- // If our depth isn't 2, and we're not under the runtime element....
- else
- ClearKey();
-
- break ;
-
- case XML_ATTRIBUTE :
- if(fRuntimeKey && EEXMLStringCompare(pszString, dwStringSize, CONST_STRING_AND_LEN(W("version"))) == 0) {
- fVersion = TRUE;
- }
- else
- {
- if (m_dwDepth == 2 && m_fUnderRuntimeElement)
- {
- if (!m_fDeveloperSettings)
- {
- _ASSERTE(m_dwCurrentRuntimeElement > 0);
-
- // The standard model for runtime config settings is as follows
- //
- // <runtime>
- // <m_pCurrentRuntimeElement enabled="true|false" />
- // or
- // <m_pCurrentRuntimeElement enabled="1|0" />
- // or
- // <m_pCurrentRuntimeElement value="string" />
-
- m_fOnEnabledAttribute = (EEXMLStringComparei(pszString, dwStringSize, CONST_STRING_AND_LEN(W("enabled"))) == 0);
- m_fOnValueAttribute = (EEXMLStringComparei(pszString, dwStringSize, CONST_STRING_AND_LEN(W("value"))) == 0);
- }
- else // We're looking at developer settings
- {
- // Developer settings look like
- // <developerSettings installationVersion="v2.0.40223.0" />
- //
- // or
- //
- // <developmentMode developerInstallation="true" />
- //
-
- // The key name will actually be the attribute name
-
- hr = CopyToKey(pszString, dwStringSize);
- if(FAILED(hr)) return hr;
- m_fOnEnabledAttribute = FALSE;
- m_fOnValueAttribute = FALSE;
- }
- }
- }
- break;
- case XML_PCDATA:
- if(fVersion) {
- // if this is not the right version
- // then we are not interested
- if(EEXMLStringCompare(pszString, dwStringSize, m_pVersion, (DWORD)wcslen(m_pVersion))) {
- m_fUnderRuntimeElement = FALSE;
- }
- else {
- // if it is the right version then overwrite
- // all entries that exist in the hash table
- m_fVersionedRuntime = TRUE;
- }
-
- fVersion = FALSE;
- }
- else if(fRuntimeKey) {
- break; // Ignore all other attributes on <runtime>
- }
-
- // m_dwCurrentRuntimeElement is set when we called CopyToKey in the XML_ELEMENT case
- // section above.
- else if(m_dwCurrentRuntimeElement > 0 && (m_fDeveloperSettings || m_fOnEnabledAttribute || m_fOnValueAttribute)) {
-
- // This means that, either we are working on attribute values for the developer settings,
- // or we've got what "enabled" is equal to, or we're reading a string for a value setting.
- //
- // <runtime>
- // <m_pwzCurrentElementUnderRuntimeElement m_pLastKey=pString />
-
- if (m_fOnEnabledAttribute) {
- // For the enabled settings, let's convert all trues to 1s and the falses to 0s
- if (EEXMLStringComparei(pszString, dwStringSize, CONST_STRING_AND_LEN(W("false"))) == 0) {
- pszString = W("0");
- dwStringSize = 1;
- }
- else if (EEXMLStringComparei(pszString, dwStringSize, CONST_STRING_AND_LEN(W("true"))) == 0) {
- pszString = W("1");
- dwStringSize = 1;
- }
-
- // <TODO> Right now, if pString isn't 0 or 1, then the XML schema is bad.
- // If we were to ever do schema validation, this would be a place to put it.
- // </TODO>
- }
-
- hr = AddKeyValuePair(pszString, dwStringSize, m_pCurrentRuntimeElement, m_dwCurrentRuntimeElement);
- if(FAILED(hr)) { return hr; }
- }
-
- break ;
- default:
- ;
- } // end of switch
- }
- }
- return hr;
-}
-
-HRESULT STDMETHODCALLTYPE EEConfigFactory::AddKeyValuePair(
- __in_ecount(dwStringSize) WCHAR * pszString,
- /* [in] */ DWORD dwStringSize,
- __in_ecount(m_dwCurrentRuntimeElement) WCHAR * m_pCurrentRuntimeElement,
- /* [in] */ DWORD m_dwCurrentRuntimeElement
- )
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- INJECT_FAULT(return E_OUTOFMEMORY;);
- }
- CONTRACTL_END;
-
- HRESULT hr = S_OK;
-
- // verify we the size fields don't overflow
- if (dwStringSize + 1 < dwStringSize) { return E_FAIL; }
- if (m_dwCurrentRuntimeElement < m_dwCurrentRuntimeElement - 1) { return E_FAIL; }
-
- EX_TRY
- {
- // Allocate memory that can store this setting
- NewArrayHolder<WCHAR> pStringToKeep(new WCHAR[dwStringSize+1]);
- wcsncpy_s(pStringToKeep, dwStringSize + 1, pszString, dwStringSize);
-
- // See if we've already picked up a value for this setting
- ConfigStringKeyValuePair * pair = m_pTable->Lookup(m_pCurrentRuntimeElement);
- if(pair != NULL) {
- // If this is a config section for this runtime version, then it's allowed to overwrite
- // previous settings that we've picked up
- if(m_fVersionedRuntime) {
- delete[] pair->value;
- pair->value = pStringToKeep;
- pStringToKeep.SuppressRelease();
- }
- }
- else {
- // We're adding a new config item
- NewArrayHolder<WCHAR> pKeyToKeep (new WCHAR[m_dwCurrentRuntimeElement]);
- wcsncpy_s(pKeyToKeep, m_dwCurrentRuntimeElement, m_pCurrentRuntimeElement, m_dwCurrentRuntimeElement - 1);
-
- ConfigStringKeyValuePair * newPair = new ConfigStringKeyValuePair();
- newPair->key = pKeyToKeep;
- newPair->value = pStringToKeep;
- m_pTable->Add(newPair);
- pKeyToKeep.SuppressRelease();
- pStringToKeep.SuppressRelease();
- }
- }
- EX_CATCH_HRESULT(hr);
-
- return hr;
-}
-
diff --git a/src/vm/eeconfigfactory.h b/src/vm/eeconfigfactory.h
deleted file mode 100644
index 2554295268..0000000000
--- a/src/vm/eeconfigfactory.h
+++ /dev/null
@@ -1,149 +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.
-// EEConfigFactory.h
-//
-
-//
-// Parses XML files and adding runtime entries to the EEConfig list
-//
-
-
-#ifndef EECONFIGFACTORY_H
-#define EECONFIGFACTORY_H
-
-#include <xmlparser.h>
-#include <objbase.h>
-#include "unknwn.h"
-#include "../xmlparser/_reference.h"
-#include "../xmlparser/_unknown.h"
-#include "eehash.h"
-#include "eeconfig.h"
-
-#define CONFIG_KEY_SIZE 128
-
-class EEConfigFactory : public _unknown<IXMLNodeFactory, &IID_IXMLNodeFactory>
-{
-
-public:
- EEConfigFactory(
- ConfigStringHashtable* pTable,
- LPCWSTR,
- ParseCtl parseCtl = parseAll);
- ~EEConfigFactory();
- HRESULT STDMETHODCALLTYPE NotifyEvent(
- /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
- /* [in] */ XML_NODEFACTORY_EVENT iEvt);
-
- HRESULT STDMETHODCALLTYPE BeginChildren(
- /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
- /* [in] */ XML_NODE_INFO* __RPC_FAR pNodeInfo);
-
- HRESULT STDMETHODCALLTYPE EndChildren(
- /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
- /* [in] */ BOOL fEmptyNode,
- /* [in] */ XML_NODE_INFO* __RPC_FAR pNodeInfo);
-
- HRESULT STDMETHODCALLTYPE Error(
- /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
- /* [in] */ HRESULT hrErrorCode,
- /* [in] */ USHORT cNumRecs,
- /* [in] */ XML_NODE_INFO* __RPC_FAR * __RPC_FAR apNodeInfo)
- {
- LIMITED_METHOD_CONTRACT;
- /*
- UNUSED(pSource);
- UNUSED(hrErrorCode);
- UNUSED(cNumRecs);
- UNUSED(apNodeInfo);
- */
- return hrErrorCode;
- }
-
- HRESULT STDMETHODCALLTYPE CreateNode(
- /* [in] */ IXMLNodeSource __RPC_FAR *pSource,
- /* [in] */ PVOID pNodeParent,
- /* [in] */ USHORT cNumRecs,
- /* [in] */ XML_NODE_INFO* __RPC_FAR * __RPC_FAR apNodeInfo);
-
-private:
-
- HRESULT GrowKey(DWORD dwSize)
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- INJECT_FAULT(return E_OUTOFMEMORY);
- }
- CONTRACTL_END;
-
- if(dwSize > m_dwSize) {
- DeleteKey();
- m_pCurrentRuntimeElement = new(nothrow) WCHAR[dwSize];
- if(m_pCurrentRuntimeElement == NULL) return E_OUTOFMEMORY;
- m_dwSize = dwSize;
- }
- return S_OK;
- }
-
- void ClearKey()
- {
- LIMITED_METHOD_CONTRACT;
-
- *m_pCurrentRuntimeElement = 0;
- m_dwCurrentRuntimeElement = 0;
- }
-
- void DeleteKey()
- {
- WRAPPER_NO_CONTRACT;
- if(m_pCurrentRuntimeElement != NULL && m_pCurrentRuntimeElement != m_pBuffer)
- delete [] m_pCurrentRuntimeElement;
- m_dwSize = 0;
- m_dwCurrentRuntimeElement = 0;
- }
-
- HRESULT CopyToKey(__in_z LPCWSTR pString, DWORD dwString)
- {
- WRAPPER_NO_CONTRACT;
- dwString++; // add in the null
- HRESULT hr = GrowKey(dwString);
- if(FAILED(hr)) return hr;
- wcsncpy_s(m_pCurrentRuntimeElement, m_dwSize, pString, dwString-1);
-
- m_dwCurrentRuntimeElement = dwString;
- return S_OK;
- }
-
- HRESULT STDMETHODCALLTYPE AddKeyValuePair(
- __in_ecount(dwStringSize) WCHAR * pszString,
- /* [in] */ DWORD dwStringSize,
- __in_ecount(m_dwCurrentRuntimeElement) WCHAR * m_pCurrentRuntimeElement,
- /* [in] */ DWORD m_dwCurrentRuntimeElement);
-
- HRESULT CopyVersion(LPCWSTR version, DWORD dwVersion);
-
- ConfigStringHashtable* m_pTable;
- BOOL m_fUnderRuntimeElement;
- BOOL m_fOnEnabledAttribute;
- BOOL m_fOnValueAttribute;
- BOOL m_fVersionedRuntime;
- BOOL m_fDeveloperSettings;
-
- LPCWSTR m_pVersion;
- LPWSTR m_pCurrentRuntimeElement;
- DWORD m_dwCurrentRuntimeElement;
-
- WCHAR m_pBuffer[CONFIG_KEY_SIZE];
- DWORD m_dwSize;
-
- DWORD m_dwDepth;
-
- bool m_bSafeMode; // If true, will ignore any settings that may compromise security
- ParseCtl m_parseCtl; // usually parseAll, sometimes stopAfterRuntimeSection
-
- ReleaseHolder<IXMLNodeFactory> m_pActiveFactory; // hold a factory responsible for parsing subnode
-};
-
-#endif
diff --git a/src/vm/exceptionhandling.cpp b/src/vm/exceptionhandling.cpp
index ba7a68dba7..a6c7651004 100644
--- a/src/vm/exceptionhandling.cpp
+++ b/src/vm/exceptionhandling.cpp
@@ -2680,7 +2680,7 @@ CLRUnwindStatus ExceptionTracker::ProcessManagedCallFrame(
EE_ILEXCEPTION_CLAUSE EHClause;
PTR_EXCEPTION_CLAUSE_TOKEN pEHClauseToken = pJitMan->GetNextEHClause(&EnumState, &EHClause);
- EH_LOG((LL_INFO100, " considering %s clause [%x,%x], ControlPc is %s clause (offset %x)",
+ EH_LOG((LL_INFO100, " considering %s clause [%x,%x), ControlPc is %s clause (offset %x)",
(IsFault(&EHClause) ? "fault" :
(IsFinally(&EHClause) ? "finally" :
(IsFilterHandler(&EHClause) ? "filter" :
@@ -4698,29 +4698,7 @@ Return value :
--*/
VOID* GetRegisterAddressByIndex(PCONTEXT pContext, UINT index)
{
-#if defined(_TARGET_AMD64_)
- _ASSERTE(index < 16);
- return &((&pContext->Rax)[index]);
-#elif defined(_TARGET_X86_)
- _ASSERTE(index < 8);
-
- static const SIZE_T OFFSET_OF_REGISTERS[] =
- {
- offsetof(CONTEXT, Eax),
- offsetof(CONTEXT, Ecx),
- offsetof(CONTEXT, Edx),
- offsetof(CONTEXT, Ebx),
- offsetof(CONTEXT, Esp),
- offsetof(CONTEXT, Ebp),
- offsetof(CONTEXT, Esi),
- offsetof(CONTEXT, Edi),
- };
-
- return (VOID*)(PBYTE(pContext) + OFFSET_OF_REGISTERS[index]);
-#else
- PORTABILITY_ASSERT("GetRegisterAddressByIndex");
- return NULL;
-#endif
+ return getRegAddr(index, pContext);
}
/*++
diff --git a/src/vm/gchost.cpp b/src/vm/gchost.cpp
deleted file mode 100644
index af213c27be..0000000000
--- a/src/vm/gchost.cpp
+++ /dev/null
@@ -1,28 +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.
-//*****************************************************************************
-// gchost.cpp
-//
-// This module contains the implementation for the IGCController interface.
-// This interface is published through the gchost.idl file. It allows a host
-// environment to set config values for the GC.
-//
-
-//
-//*****************************************************************************
-
-//********** Includes *********************************************************
-
-#include "common.h"
-#include "vars.hpp"
-#include "eeconfig.h"
-#include "perfcounters.h"
-#include "gchost.h"
-#include "corhost.h"
-#include "excep.h"
-#include "field.h"
-#include "gcheaputilities.h"
-
-
-
diff --git a/src/vm/i386/cgenx86.cpp b/src/vm/i386/cgenx86.cpp
index 528629c3a2..105b05823e 100644
--- a/src/vm/i386/cgenx86.cpp
+++ b/src/vm/i386/cgenx86.cpp
@@ -802,6 +802,7 @@ void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
}
// The HijackFrame has to know the registers that are pushed by OnHijackTripThread
+// -> HijackFrame::UpdateRegDisplay should restore all the registers pushed by OnHijackTripThread
void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
{
CONTRACTL {
@@ -822,19 +823,15 @@ void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
pRD->pCurrentContext->Eip = *PTR_PCODE(pRD->PCTAddr);
pRD->pCurrentContext->Esp = (DWORD)(pRD->PCTAddr + sizeof(TADDR));
-#define CALLEE_SAVED_REGISTER(reg) pRD->pCurrentContext->reg = m_Args->reg;
+#define RESTORE_REG(reg) { pRD->pCurrentContext->reg = m_Args->reg; pRD->pCurrentContextPointers->reg = &m_Args->reg; }
+#define CALLEE_SAVED_REGISTER(reg) RESTORE_REG(reg)
ENUM_CALLEE_SAVED_REGISTERS();
#undef CALLEE_SAVED_REGISTER
-#define CALLEE_SAVED_REGISTER(reg) pRD->pCurrentContextPointers->reg = NULL;
- ENUM_CALLEE_SAVED_REGISTERS();
-#undef CALLEE_SAVED_REGISTER
-
-#define ARGUMENT_AND_SCRATCH_REGISTER(reg) pRD->pCurrentContextPointers->reg = NULL;
+#define ARGUMENT_AND_SCRATCH_REGISTER(reg) RESTORE_REG(reg)
ENUM_ARGUMENT_AND_SCRATCH_REGISTERS();
#undef ARGUMENT_AND_SCRATCH_REGISTER
-
- pRD->pCurrentContextPointers->Eax = (PDWORD) &m_Args->Eax;
+#undef RESTORE_REG
SyncRegDisplayToCurrentContext(pRD);
@@ -843,14 +840,16 @@ void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
// This only describes the top-most frame
pRD->pContext = NULL;
- pRD->pEdi = &m_Args->Edi;
- pRD->pEsi = &m_Args->Esi;
- pRD->pEbx = &m_Args->Ebx;
- pRD->pEdx = &m_Args->Edx;
- pRD->pEcx = &m_Args->Ecx;
- pRD->pEax = &m_Args->Eax;
+#define RESTORE_REG(reg) { pRD->p##reg = &m_Args->reg; }
+#define CALLEE_SAVED_REGISTER(reg) RESTORE_REG(reg)
+ ENUM_CALLEE_SAVED_REGISTERS();
+#undef CALLEE_SAVED_REGISTER
+
+#define ARGUMENT_AND_SCRATCH_REGISTER(reg) RESTORE_REG(reg)
+ ENUM_ARGUMENT_AND_SCRATCH_REGISTERS();
+#undef ARGUMENT_AND_SCRATCH_REGISTER
+#undef RESTORE_REG
- pRD->pEbp = &m_Args->Ebp;
pRD->ControlPC = *PTR_PCODE(pRD->PCTAddr);
pRD->SP = (DWORD)(pRD->PCTAddr + sizeof(TADDR));
diff --git a/src/vm/i386/excepx86.cpp b/src/vm/i386/excepx86.cpp
index 10f68a9fbf..2997c5784f 100644
--- a/src/vm/i386/excepx86.cpp
+++ b/src/vm/i386/excepx86.cpp
@@ -28,7 +28,6 @@
#include "dllimportcallback.h"
#include "threads.h"
#ifdef FEATURE_REMOTING
-#include "appdomainhelper.h"
#endif
#include "eeconfig.h"
#include "vars.hpp"
diff --git a/src/vm/i386/remotingx86.cpp b/src/vm/i386/remotingx86.cpp
deleted file mode 100644
index 3a9e891267..0000000000
--- a/src/vm/i386/remotingx86.cpp
+++ /dev/null
@@ -1,225 +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.
-//
-//
-//
-// File: remotingx86.cpp
-//
-
-//
-//
-// Purpose: Defines various remoting related functions for the x86 architecture
-//
-
-//
-//
-
-//
-
-#include "common.h"
-
-#ifdef FEATURE_REMOTING
-
-#include "excep.h"
-#include "comdelegate.h"
-#include "remoting.h"
-#include "field.h"
-#include "siginfo.hpp"
-#include "stackbuildersink.h"
-#include "threads.h"
-#include "method.hpp"
-#include "asmconstants.h"
-#include "interoputil.h"
-#include "virtualcallstub.h"
-
-#ifdef FEATURE_COMINTEROP
-#include "comcallablewrapper.h"
-#include "comcache.h"
-#endif // FEATURE_COMINTEROP
-
-//+----------------------------------------------------------------------------
-//
-// Method: CTPMethodTable::CreateThunkForVirtualMethod private
-//
-// Synopsis: Creates the thunk that pushes the supplied slot number and jumps
-// to TP Stub
-//
-//+----------------------------------------------------------------------------
-PCODE CTPMethodTable::CreateThunkForVirtualMethod(DWORD dwSlot, BYTE *startaddr)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(startaddr));
- }
- CONTRACTL_END;
-
- BYTE *pCode = startaddr;
-
- // 0000 B8 67 45 23 01 MOV EAX, dwSlot
- // 0005 E9 ?? ?? ?? ?? JMP TransparentProxyStub
- *pCode++ = 0xB8;
- *((DWORD *) pCode) = dwSlot;
- pCode += sizeof(DWORD);
- *pCode++ = 0xE9;
- // self-relative call, based on the start of the next instruction.
- *((LONG *) pCode) = (LONG)((size_t)GetTPStubEntryPoint() - (size_t) (pCode + sizeof(LONG)));
-
- _ASSERTE(CVirtualThunkMgr::IsThunkByASM((PCODE)startaddr));
-
- return (PCODE)startaddr;
-}
-
-
-//+----------------------------------------------------------------------------
-//
-// Method: CTPMethodTable::ActivatePrecodeRemotingThunk private
-//
-// Synopsis: Patch the precode remoting thunk to begin interception
-//
-//+----------------------------------------------------------------------------
-void CTPMethodTable::ActivatePrecodeRemotingThunk()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- // Before activation:
- // 0000 C3 ret
- // 0001 90 nop
-
- // After activation:
- // 0000 85 C9 test ecx,ecx
-
- // 0002 74 XX je RemotingDone
- // 0004 81 39 XX XX XX XX cmp dword ptr [ecx],11111111h
- // 000A 74 XX je RemotingCheck
-
- // Switch offset and size of patch based on the jump opcode used.
- BYTE* pCode = (BYTE*)PrecodeRemotingThunk;
-
- SIZE_T mtOffset = 0x0006;
- SIZE_T size = 0x000A;
-
- // Patch "ret + nop" to "test ecx,ecx"
- *(UINT16 *)pCode = 0xC985;
-
- // Replace placeholder value with the actual address of TP method table
- _ASSERTE(*(PVOID*)(pCode+mtOffset) == (PVOID*)0x11111111);
- *(PVOID*)(pCode+mtOffset) = GetMethodTable();
-
- FlushInstructionCache(GetCurrentProcess(), pCode, size);
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CVirtualThunkMgr::DoTraceStub public
-//
-// Synopsis: Traces the stub given the starting address
-//
-//+----------------------------------------------------------------------------
-BOOL CVirtualThunkMgr::DoTraceStub(PCODE stubStartAddress, TraceDestination *trace)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(stubStartAddress != NULL);
- PRECONDITION(CheckPointer(trace));
- }
- CONTRACTL_END;
-
- BOOL bIsStub = FALSE;
-
- // Find a thunk whose code address matching the starting address
- LPBYTE pThunk = FindThunk((LPBYTE)stubStartAddress);
- if(NULL != pThunk)
- {
- LPBYTE pbAddr = NULL;
- LONG destAddress = 0;
- if((LPBYTE)stubStartAddress == pThunk)
- {
-
- // Extract the long which gives the self relative address
- // of the destination
- pbAddr = pThunk + sizeof(BYTE) + sizeof(DWORD) + sizeof(BYTE);
- destAddress = *(LONG *)pbAddr;
-
- // Calculate the absolute address by adding the offset of the next
- // instruction after the call instruction
- destAddress += (LONG)(size_t)(pbAddr + sizeof(LONG));
-
- }
-
- // We cannot tell where the stub will end up until OnCall is reached.
- // So we tell the debugger to run till OnCall is reached and then
- // come back and ask us again for the actual destination address of
- // the call
-
- Stub *stub = Stub::RecoverStub((TADDR)destAddress);
-
- trace->InitForFramePush(stub->GetPatchAddress());
- bIsStub = TRUE;
- }
-
- return bIsStub;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CVirtualThunkMgr::IsThunkByASM public
-//
-// Synopsis: Check assembly to see if this one of our thunks
-//
-//+----------------------------------------------------------------------------
-BOOL CVirtualThunkMgr::IsThunkByASM(PCODE startaddr)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(startaddr != NULL);
- }
- CONTRACTL_END;
-
- PTR_BYTE pbCode = PTR_BYTE(startaddr);
-
- return ((pbCode[0] == 0xB8) &&
- (pbCode[5] == 0xe9) &&
- (rel32Decode((TADDR)(pbCode + 6)) == CTPMethodTable::GetTPStubEntryPoint()));
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CVirtualThunkMgr::GetMethodDescByASM public
-//
-// Synopsis: Parses MethodDesc out of assembly code
-//
-//+----------------------------------------------------------------------------
-MethodDesc *CVirtualThunkMgr::GetMethodDescByASM(PCODE startaddr, MethodTable *pMT)
-{
- CONTRACT (MethodDesc*)
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(startaddr != NULL);
- PRECONDITION(CheckPointer(pMT));
- POSTCONDITION(CheckPointer(RETVAL));
- }
- CONTRACT_END;
-
- RETURN (pMT->GetMethodDescForSlot(*((DWORD *) (startaddr + 1))));
-}
-
-#endif// FEATURE_REMOTING
-
diff --git a/src/vm/inlinetracking.cpp b/src/vm/inlinetracking.cpp
index 02e2a7cea6..c4bfe0734c 100644
--- a/src/vm/inlinetracking.cpp
+++ b/src/vm/inlinetracking.cpp
@@ -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.
// =============================================================================================
-// Code for tracking method inlinings in NGen images.
+// Code for tracking method inlinings in NGen and R2R images.
// The only information stored is "who" got inlined "where", no offsets or inlining depth tracking.
// (No good for debugger yet.)
// This information is later exposed to profilers and can be useful for ReJIT.
@@ -12,6 +12,8 @@
#include "inlinetracking.h"
#include "ceeload.h"
+#ifndef DACCESS_COMPILE
+
bool MethodInModule::operator <(const MethodInModule& other) const
{
STANDARD_VM_CONTRACT;
@@ -123,9 +125,86 @@ InlineTrackingEntry & InlineTrackingEntry::operator = (const InlineTrackingEntry
return *this;
}
+void InlineTrackingEntry::Add(PTR_MethodDesc inliner)
+{
+ STANDARD_VM_CONTRACT;
-#ifndef DACCESS_COMPILE
-COUNT_T PersistentInlineTrackingMap::GetInliners(PTR_Module inlineeOwnerMod, mdMethodDef inlineeTkn, COUNT_T inlinersSize, MethodInModule inliners[], BOOL *incompleteData)
+ MethodInModule method(inliner->GetModule(), inliner->GetMemberDef());
+
+ // Going through last 10 inliners to check if a given inliner has recently been registered.
+ // It allows to filter out most duplicates without having to scan through hundreds of inliners
+ // for methods like Object.ctor or Monitor.Enter.
+ // We are OK to keep occasional duplicates in m_inliners, we'll get rid of them
+ // in SortAndDeduplicate() anyway.
+ int count = static_cast<int>(m_inliners.GetCount());
+ int start = max(0, count - 10);
+ for (int i = count - 1; i >= start; i--)
+ {
+ if (m_inliners[i] == method)
+ return;
+ }
+
+ //look like we see this inliner for the first time, add it to the collection
+ m_inliners.Append(method);
+}
+
+InlineTrackingMap::InlineTrackingMap()
+ : m_mapCrst(CrstInlineTrackingMap)
+{
+ STANDARD_VM_CONTRACT;
+}
+
+void InlineTrackingMap::AddInlining(MethodDesc *inliner, MethodDesc *inlinee)
+{
+ STANDARD_VM_CONTRACT;
+ _ASSERTE(inliner != NULL);
+ _ASSERTE(inlinee != NULL);
+
+ MethodInModule inlineeMnM(inlinee->GetModule(), inlinee->GetMemberDef());
+
+ if (RidFromToken(inlineeMnM.m_methodDef) == 0 || RidFromToken(inliner->GetMemberDef()) == 0)
+ {
+ // Sometimes we do see methods that don't have valid tokens (stubs etc)
+ // we just ignore them.
+ return;
+ }
+
+ CrstHolder lock(&m_mapCrst);
+ InlineTrackingEntry *existingEntry = const_cast<InlineTrackingEntry *>(LookupPtr(inlineeMnM));
+ if (existingEntry)
+ {
+ // We saw this inlinee before, just add one more inliner
+ existingEntry->Add(inliner);
+ }
+ else
+ {
+ // We haven't seen this inlinee before, create a new record in the hashtable
+ // and add a first inliner to it.
+ InlineTrackingEntry newEntry;
+ newEntry.m_inlinee = inlineeMnM;
+ newEntry.Add(inliner);
+ Add(newEntry);
+ }
+}
+
+#endif //!DACCESS_COMPILE
+
+void ZapInlineeRecord::InitForNGen(RID rid, LPCUTF8 simpleName)
+{
+ LIMITED_METHOD_CONTRACT;
+ //XOR of up to first 24 bytes in module name
+ DWORD hash = 0;
+ for (int i = 0; simpleName[i] && i < 24; i++)
+ hash ^= (BYTE)simpleName[i];
+
+ // This key contains 24 bits of RID and 8 bits from module name.
+ // Since RID can't be longer than 24 bits, we can't have method RID collistions,
+ // that's why PersistentInlineTrackingMap::GetInliners only deals with module collisions.
+ m_key = (hash << 24) | rid;
+}
+
+
+COUNT_T PersistentInlineTrackingMapNGen::GetInliners(PTR_Module inlineeOwnerMod, mdMethodDef inlineeTkn, COUNT_T inlinersSize, MethodInModule inliners[], BOOL *incompleteData)
{
CONTRACTL
{
@@ -149,10 +228,11 @@ COUNT_T PersistentInlineTrackingMap::GetInliners(PTR_Module inlineeOwnerMod, mdM
}
// Binary search to find all records matching (inlineeTkn/inlineeOwnerMod)
- InlineeRecord probeRecord(RidFromToken(inlineeTkn), inlineeOwnerMod->GetSimpleName());
- InlineeRecord *begin = m_inlineeIndex;
- InlineeRecord *end = m_inlineeIndex + m_inlineeIndexSize;
- InlineeRecord *foundRecord = util::lower_bound(begin, end, probeRecord);
+ ZapInlineeRecord probeRecord;
+ probeRecord.InitForNGen(RidFromToken(inlineeTkn), inlineeOwnerMod->GetSimpleName());
+ ZapInlineeRecord *begin = m_inlineeIndex;
+ ZapInlineeRecord *end = m_inlineeIndex + m_inlineeIndexSize;
+ ZapInlineeRecord *foundRecord = util::lower_bound(begin, end, probeRecord);
DWORD result = 0;
DWORD outputIndex = 0;
@@ -204,7 +284,9 @@ COUNT_T PersistentInlineTrackingMap::GetInliners(PTR_Module inlineeOwnerMod, mdM
return result;
}
-Module *PersistentInlineTrackingMap::GetModuleByIndex(DWORD index)
+
+
+Module *PersistentInlineTrackingMapNGen::GetModuleByIndex(DWORD index)
{
CONTRACTL
{
@@ -222,106 +304,42 @@ Module *PersistentInlineTrackingMap::GetModuleByIndex(DWORD index)
return m_module->GetModuleFromIndexIfLoaded(index);
}
-PersistentInlineTrackingMap::InlineeRecord::InlineeRecord(RID rid, LPCUTF8 simpleName)
-{
- LIMITED_METHOD_CONTRACT;
- //XOR of up to first 24 bytes in module name
- DWORD hash = 0;
- for (int i = 0; simpleName[i] && i < 24; i++)
- hash ^= (BYTE)simpleName[i];
-
- // This key contains 24 bits of RID and 8 bits from module name.
- // Since RID can't be longer than 24 bits, we can't have method RID collistions,
- // that's why PersistentInlineTrackingMap::GetInliners only deals with module collisions.
- m_key = (hash << 24) | rid;
-}
-InlineTrackingMap::InlineTrackingMap()
- : m_mapCrst(CrstInlineTrackingMap)
-{
- STANDARD_VM_CONTRACT;
-}
-
-void InlineTrackingMap::AddInlining(MethodDesc *inliner, MethodDesc *inlinee)
-{
- STANDARD_VM_CONTRACT;
- _ASSERTE(inliner != NULL);
- _ASSERTE(inlinee != NULL);
-
- MethodInModule inlineeMnM(inlinee->GetModule(), inlinee->GetMemberDef());
-
- if (RidFromToken(inlineeMnM.m_methodDef) == 0 || RidFromToken(inliner->GetMemberDef()) == 0)
- {
- // Sometimes we do see methods that don't have valid tokens (stubs etc)
- // we just ignore them.
- return;
- }
-
- CrstHolder lock(&m_mapCrst);
- InlineTrackingEntry *existingEntry = const_cast<InlineTrackingEntry *>(LookupPtr(inlineeMnM));
- if (existingEntry)
- {
- // We saw this inlinee before, just add one more inliner
- existingEntry->Add(inliner);
- }
- else
- {
- // We haven't seen this inlinee before, create a new record in the hashtable
- // and add a first inliner to it.
- InlineTrackingEntry newEntry;
- newEntry.m_inlinee = inlineeMnM;
- newEntry.Add(inliner);
- Add(newEntry);
- }
-}
-
-void InlineTrackingEntry::Add(PTR_MethodDesc inliner)
-{
- STANDARD_VM_CONTRACT;
-
- MethodInModule method(inliner->GetModule(), inliner->GetMemberDef());
-
- // Going through last 10 inliners to check if a given inliner has recently been registered.
- // It allows to filter out most duplicates without having to scan through hundreds of inliners
- // for methods like Object.ctor or Monitor.Enter.
- // We are OK to keep occasional duplicates in m_inliners, we'll get rid of them
- // in SortAndDeduplicate() anyway.
- int count = static_cast<int>(m_inliners.GetCount());
- int start = max(0, count - 10);
- for (int i = count - 1; i >= start; i--)
- {
- if (m_inliners[i] == method)
- return;
- }
-
- //look like we see this inliner for the first time, add it to the collection
- m_inliners.Append(method);
-}
+#ifndef DACCESS_COMPILE
#ifdef FEATURE_NATIVE_IMAGE_GENERATION
-void PersistentInlineTrackingMap::ProcessInlineTrackingEntry(DataImage *image, SBuffer *inlinersBuffer, SArray<InlineeRecord> *inlineeIndex, InlineTrackingEntry *entry)
+// This is a shared serialization routine used for both NGEN and R2R formats. If image != NULL the NGEN format is generated, otherwise the R2R format
+void SerializeInlineTrackingEntry(DataImage* image, SBuffer *inlinersBuffer, SArray<ZapInlineeRecord> *inlineeIndex, InlineTrackingEntry *entry)
{
STANDARD_VM_CONTRACT;
// This call removes duplicates from inliners and makes sure they are sorted by module
entry->SortAndDeduplicate();
MethodInModule inlinee = entry->m_inlinee;
- DWORD inlineeModuleZapIndex = image->GetModuleImportIndex(inlinee.m_module);
+ DWORD inlineeModuleZapIndex = 0;
+ if (image != NULL)
+ {
+ inlineeModuleZapIndex = image->GetModuleImportIndex(inlinee.m_module);
+ }
InlineSArray<MethodInModule, 3> &inliners = entry->m_inliners;
- COUNT_T tatalInlinersCount = inliners.GetCount();
- _ASSERTE(tatalInlinersCount > 0);
+ COUNT_T totalInlinersCount = inliners.GetCount();
+ _ASSERTE(totalInlinersCount > 0);
COUNT_T sameModuleCount;
// Going through all inliners and grouping them by their module, for each module we'll create
- // InlineeRecord and encode inliners as bytes in inlinersBuffer.
- for (COUNT_T thisModuleBegin = 0; thisModuleBegin < tatalInlinersCount; thisModuleBegin += sameModuleCount)
+ // an ZapInlineeRecord and encode inliners as bytes in inlinersBuffer.
+ for (COUNT_T thisModuleBegin = 0; thisModuleBegin < totalInlinersCount; thisModuleBegin += sameModuleCount)
{
Module *lastInlinerModule = inliners[thisModuleBegin].m_module;
- DWORD lastInlinerModuleZapIndex = image->GetModuleImportIndex(lastInlinerModule);
-
+ DWORD lastInlinerModuleZapIndex = 0;
+ if (image != NULL)
+ {
+ lastInlinerModuleZapIndex = image->GetModuleImportIndex(lastInlinerModule);
+ }
+
// Counting how many inliners belong to this module
sameModuleCount = 1;
- while (thisModuleBegin + sameModuleCount < tatalInlinersCount &&
+ while (thisModuleBegin + sameModuleCount < totalInlinersCount &&
inliners[thisModuleBegin + sameModuleCount].m_module == lastInlinerModule)
{
sameModuleCount++;
@@ -329,8 +347,11 @@ void PersistentInlineTrackingMap::ProcessInlineTrackingEntry(DataImage *image, S
// Saving module indexes and number of inliners
NibbleWriter inlinersStream;
- inlinersStream.WriteEncodedU32(inlineeModuleZapIndex);
- inlinersStream.WriteEncodedU32(lastInlinerModuleZapIndex);
+ if (image != NULL)
+ {
+ inlinersStream.WriteEncodedU32(inlineeModuleZapIndex);
+ inlinersStream.WriteEncodedU32(lastInlinerModuleZapIndex);
+ }
inlinersStream.WriteEncodedU32(sameModuleCount);
// Saving inliners RIDs, each new RID is represented as an adjustment (diff) to the previous one
@@ -343,15 +364,22 @@ void PersistentInlineTrackingMap::ProcessInlineTrackingEntry(DataImage *image, S
prevMethodRid = methodRid;
}
inlinersStream.Flush();
-
+
// Copy output of NibbleWriter into a big buffer (inlinersBuffer) for inliners from the same module
// and create an InlineeRecord with correct offset
- InlineeRecord record(RidFromToken(inlinee.m_methodDef), inlinee.m_module->GetSimpleName());
DWORD inlinersStreamSize;
const BYTE *inlinersStreamPtr = (const BYTE *)inlinersStream.GetBlob(&inlinersStreamSize);
+ ZapInlineeRecord record;
+ if (image != NULL)
+ {
+ record.InitForNGen(RidFromToken(inlinee.m_methodDef), inlinee.m_module->GetSimpleName());
+ }
+ else
+ {
+ record.InitForR2R(RidFromToken(inlinee.m_methodDef));
+ }
record.m_offset = inlinersBuffer->GetSize();
inlinersBuffer->Insert(inlinersBuffer->End(), SBuffer(SBuffer::Immutable, inlinersStreamPtr, inlinersStreamSize));
-
inlineeIndex->Append(record);
}
}
@@ -361,20 +389,16 @@ bool compare_entry(const InlineTrackingEntry* first, const InlineTrackingEntry*
return first->m_inlinee < second->m_inlinee;
}
-void PersistentInlineTrackingMap::Save(DataImage *image, InlineTrackingMap* runtimeMap)
+// This is a shared serialization routine used for both NGEN and R2R formats. If image != NULL the NGEN format is generated, otherwise the R2R format
+void SerializeTrackingMapBuffers(ZapHeap* heap, DataImage *image, SBuffer *inlinersBuffer, SArray<ZapInlineeRecord> *inlineeIndex, InlineTrackingMap* runtimeMap)
{
STANDARD_VM_CONTRACT;
- _ASSERTE(image != NULL);
_ASSERTE(runtimeMap != NULL);
- SArray<InlineeRecord> inlineeIndex;
- SBuffer inlinersBuffer;
-
// Sort records from runtimeMap, because we need to make sure
// we save everything in deterministic order. Hashtable iteration is not deterministic.
COUNT_T runtimeMapCount = runtimeMap->GetCount();
- InlineTrackingEntry **inlinees = new InlineTrackingEntry *[runtimeMapCount];
- NewArrayHolder<InlineTrackingEntry *>inlineesHolder(inlinees);
+ InlineTrackingEntry **inlinees = new (heap) InlineTrackingEntry *[runtimeMapCount];
int index = 0;
for (auto iter = runtimeMap->Begin(), end = runtimeMap->End(); iter != end; ++iter)
{
@@ -387,8 +411,22 @@ void PersistentInlineTrackingMap::Save(DataImage *image, InlineTrackingMap* runt
// and write corresponding records into inlineeIndex and inlinersBuffer
for (COUNT_T i = 0; i < runtimeMapCount; i++)
{
- ProcessInlineTrackingEntry(image, &inlinersBuffer, &inlineeIndex, inlinees[i]);
+ SerializeInlineTrackingEntry(image, inlinersBuffer, inlineeIndex, inlinees[i]);
}
+}
+
+
+
+void PersistentInlineTrackingMapNGen::Save(DataImage *image, InlineTrackingMap* runtimeMap)
+{
+ STANDARD_VM_CONTRACT;
+ _ASSERTE(image != NULL);
+ _ASSERTE(runtimeMap != NULL);
+
+ SArray<ZapInlineeRecord> inlineeIndex;
+ SBuffer inlinersBuffer;
+
+ SerializeTrackingMapBuffers(image->GetHeap(), image, &inlinersBuffer, &inlineeIndex, runtimeMap);
m_inlineeIndexSize = inlineeIndex.GetCount();
m_inlinersBufferSize = inlinersBuffer.GetSize();
@@ -398,7 +436,7 @@ void PersistentInlineTrackingMap::Save(DataImage *image, InlineTrackingMap* runt
{
// Copy everything to the class fields, we didn't use the class fields for addition
// because we want to make sure we don't waste memory for buffer's amortized growth
- m_inlineeIndex = new (image->GetHeap()) InlineeRecord[m_inlineeIndexSize];
+ m_inlineeIndex = new (image->GetHeap()) ZapInlineeRecord[m_inlineeIndexSize];
inlineeIndex.Copy(m_inlineeIndex, inlineeIndex.Begin(), m_inlineeIndexSize);
m_inlinersBuffer = new (image->GetHeap()) BYTE[m_inlinersBufferSize];
@@ -418,12 +456,146 @@ void PersistentInlineTrackingMap::Save(DataImage *image, InlineTrackingMap* runt
m_inlineeIndexSize * sizeof(m_inlineeIndex[0]), m_inlinersBufferSize));
}
-void PersistentInlineTrackingMap::Fixup(DataImage *image)
+void PersistentInlineTrackingMapNGen::Fixup(DataImage *image)
+{
+ STANDARD_VM_CONTRACT;
+ image->FixupPointerField(this, offsetof(PersistentInlineTrackingMapNGen, m_module));
+ image->FixupPointerField(this, offsetof(PersistentInlineTrackingMapNGen, m_inlineeIndex));
+ image->FixupPointerField(this, offsetof(PersistentInlineTrackingMapNGen, m_inlinersBuffer));
+}
+
+#endif //FEATURE_NATIVE_IMAGE_GENERATION
+#endif //!DACCESS_COMPILE
+
+#ifdef FEATURE_READYTORUN
+
+struct InliningHeader
+{
+ int SizeOfInlineeIndex;
+};
+
+#ifndef DACCESS_COMPILE
+#ifdef FEATURE_NATIVE_IMAGE_GENERATION
+
+
+
+void PersistentInlineTrackingMapR2R::Save(ZapHeap* pHeap, SBuffer* pSaveTarget, InlineTrackingMap* runtimeMap)
{
STANDARD_VM_CONTRACT;
- image->FixupPointerField(this, offsetof(PersistentInlineTrackingMap, m_module));
- image->FixupPointerField(this, offsetof(PersistentInlineTrackingMap, m_inlineeIndex));
- image->FixupPointerField(this, offsetof(PersistentInlineTrackingMap, m_inlinersBuffer));
+ _ASSERTE(pSaveTarget != NULL);
+ _ASSERTE(runtimeMap != NULL);
+
+ SArray<ZapInlineeRecord> inlineeIndex;
+ SBuffer inlinersBuffer;
+
+ SerializeTrackingMapBuffers(pHeap, NULL, &inlinersBuffer, &inlineeIndex, runtimeMap);
+
+ InliningHeader header;
+ header.SizeOfInlineeIndex = inlineeIndex.GetCount() * sizeof(ZapInlineeRecord);
+
+ pSaveTarget->Insert(pSaveTarget->End(), SBuffer(SBuffer::Immutable, (const BYTE*) &header, sizeof(header)));
+ DWORD unused = 0;
+ pSaveTarget->Insert(pSaveTarget->End(), SBuffer(SBuffer::Immutable, (const BYTE*) inlineeIndex.GetElements(), header.SizeOfInlineeIndex));
+ pSaveTarget->Insert(pSaveTarget->End(), SBuffer(SBuffer::Immutable, (const BYTE*) inlinersBuffer, inlinersBuffer.GetSize()));
+
+ LOG((LF_ZAP, LL_INFO100000,
+ "PersistentInlineTrackingMap saved. InlineeIndexSize: %d bytes, InlinersBufferSize: %d bytes\n",
+ header.SizeOfInlineeIndex, inlinersBuffer.GetSize()));
}
+
#endif //FEATURE_NATIVE_IMAGE_GENERATION
+
+BOOL PersistentInlineTrackingMapR2R::TryLoad(Module* pModule, const BYTE* pBuffer, DWORD cbBuffer,
+ AllocMemTracker *pamTracker, PersistentInlineTrackingMapR2R** ppLoadedMap)
+{
+ InliningHeader* pHeader = (InliningHeader*)pBuffer;
+ if (pHeader->SizeOfInlineeIndex > (int)(cbBuffer - sizeof(InliningHeader)))
+ {
+ //invalid serialized data, the index can't be larger the entire block
+ _ASSERTE(!"R2R image is invalid or there is a bug in the R2R parser");
+ return FALSE;
+ }
+
+ //NOTE: Error checking on the format is very limited at this point.
+ //We trust the image format is valid and this initial check is a cheap
+ //verification that may help catch simple bugs. It does not secure against
+ //a deliberately maliciously formed binary.
+
+ LoaderHeap *pHeap = pModule->GetLoaderAllocator()->GetHighFrequencyHeap();
+ void * pMemory = pamTracker->Track(pHeap->AllocMem((S_SIZE_T)sizeof(PersistentInlineTrackingMapR2R)));
+ PersistentInlineTrackingMapR2R* pMap = new (pMemory) PersistentInlineTrackingMapR2R();
+
+ pMap->m_module = pModule;
+ pMap->m_inlineeIndex = (PTR_ZapInlineeRecord)(pHeader + 1);
+ pMap->m_inlineeIndexSize = pHeader->SizeOfInlineeIndex / sizeof(ZapInlineeRecord);
+ pMap->m_inlinersBuffer = ((PTR_BYTE)(pHeader+1)) + pHeader->SizeOfInlineeIndex;
+ pMap->m_inlinersBufferSize = cbBuffer - sizeof(InliningHeader) - pMap->m_inlineeIndexSize;
+ *ppLoadedMap = pMap;
+ return TRUE;
+}
+
#endif //!DACCESS_COMPILE
+
+COUNT_T PersistentInlineTrackingMapR2R::GetInliners(PTR_Module inlineeOwnerMod, mdMethodDef inlineeTkn, COUNT_T inlinersSize, MethodInModule inliners[], BOOL *incompleteData)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ _ASSERTE(inlineeOwnerMod);
+ _ASSERTE(inliners);
+
+ if (incompleteData)
+ {
+ *incompleteData = FALSE;
+ }
+ if (m_inlineeIndex == NULL || m_inlinersBuffer == NULL)
+ {
+ //No inlines saved in this image.
+ return 0;
+ }
+ if(inlineeOwnerMod != m_module)
+ {
+ // no cross module inlining (yet?)
+ return 0;
+ }
+
+ // Binary search to find all records matching (inlineeTkn)
+ ZapInlineeRecord probeRecord;
+ probeRecord.InitForR2R(RidFromToken(inlineeTkn));
+ ZapInlineeRecord *begin = m_inlineeIndex;
+ ZapInlineeRecord *end = m_inlineeIndex + m_inlineeIndexSize;
+ ZapInlineeRecord *foundRecord = util::lower_bound(begin, end, probeRecord);
+ DWORD result = 0;
+ DWORD outputIndex = 0;
+
+ // Go through all matching records
+ for (; foundRecord < end && *foundRecord == probeRecord; foundRecord++)
+ {
+ DWORD offset = foundRecord->m_offset;
+ NibbleReader stream(m_inlinersBuffer + offset, m_inlinersBufferSize - offset);
+ Module *inlinerModule = m_module;
+
+ DWORD inlinersCount = stream.ReadEncodedU32();
+ _ASSERTE(inlinersCount > 0);
+
+ RID inlinerRid = 0;
+ // Reading inliner RIDs one by one, each RID is represented as an adjustment (diff) to the previous one.
+ // Adding inliners module and coping to the output buffer
+ for (DWORD i = 0; i < inlinersCount && outputIndex < inlinersSize; i++)
+ {
+ inlinerRid += stream.ReadEncodedU32();
+ mdMethodDef inlinerTkn = TokenFromRid(inlinerRid, mdtMethodDef);
+ inliners[outputIndex++] = MethodInModule(inlinerModule, inlinerTkn);
+ }
+ result += inlinersCount;
+ }
+
+ return result;
+}
+
+#endif //FEATURE_READYTORUN \ No newline at end of file
diff --git a/src/vm/inlinetracking.h b/src/vm/inlinetracking.h
index cf05027785..2cfb35bd50 100644
--- a/src/vm/inlinetracking.h
+++ b/src/vm/inlinetracking.h
@@ -2,12 +2,26 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// =============================================================================================
-// Definitions for tracking method inlinings in NGen images.
+// Definitions for tracking method inlinings in NGen and R2R images.
// The only information stored is "who" got inlined "where", no offsets or inlining depth tracking.
// (No good for debugger yet.)
// This information is later exposed to profilers and can be useful for ReJIT.
// Runtime inlining is not being tracked because profilers can deduce it via callbacks anyway.
+//
+// This file is made of two major component groups:
+// a) InlineTrackingMap - This is a compilation time datastructure that holds an uncompressed
+// version of the inline tracking information. It is appended to as methods are compiled.
+// MethodInModule, InlineTrackingEntry, InlineTrackingMapTraits are all support infratsructure
+// in this group.
+//
+// b) PersistentInlineTrackingMap[R2R/NGen] - These are the types that understand the image persistence
+// formats. At the end of image compilation one of them consumes all the data from an
+// InlineTrackingMap to encode it. At runtime an instance will be constructed to read back
+// the encoded data on demand. PersistantInlineTrackingMapR2R and PersistantInlineTrackingMapNGen
+// would nominally use a common base type or interface, but due to ngen binary serialization vtables
+// were avoided. See farther below for the different format descriptions.
// =============================================================================================
+
#ifndef INLINETRACKING_H_
#define INLINETRACKING_H_
#include "corhdr.h"
@@ -16,6 +30,10 @@
#include "crsttypes.h"
#include "daccess.h"
+
+
+// ---------------------------------- Compile time support ----------------------------------------------
+
class MethodDesc;
typedef DPTR(class MethodDesc) PTR_MethodDesc;
@@ -128,6 +146,17 @@ public:
typedef DPTR(InlineTrackingMap) PTR_InlineTrackingMap;
+
+
+
+// ------------------------------------ Persistance support ----------------------------------------------------------
+
+
+
+
+
+// NGEN format
+//
// This is a persistent map that is stored inside each NGen-ed module image and is used to track
// inlines in the NGEN-ed code inside this module.
// At runtime this map is used by profiler to track methods that inline a given method,
@@ -135,25 +164,25 @@ typedef DPTR(InlineTrackingMap) PTR_InlineTrackingMap;
// It doesn't require any load time unpacking and serves requests directly from NGEN image.
//
// It is composed of two arrays:
-// m_inlineeIndex - sorted (by InlineeRecord.key i.e. by module then token) array of InlineeRecords, given an inlinee module name hash (8 bits)
+// m_inlineeIndex - sorted (by ZapInlineeRecord.key i.e. by module then token) array of ZapInlineeRecords, given an inlinee module name hash (8 bits)
// and a method token (24 bits) we use binary search to find if this method has ever been inlined in NGen-ed code of this image.
// Each record has m_offset, which is an offset inside m_inlinersBuffer, it has more data on where the method got inlined.
//
-// It is totally possible to have more than one InlineeRecords with the same key, not only due hash collision, but also due to
+// It is totally possible to have more than one ZapInlineeRecords with the same key, not only due hash collision, but also due to
// the fact that we create one record for each (inlinee module / inliner module) pair.
// For example: we have MyModule!MyType that uses mscorlib!List<T>. Let's say List<T>.ctor got inlined into
// MyType.GetAllThinds() and into List<MyType>.FindAll. In this case we'll have two InlineeRecords for mscorlib!List<T>.ctor
// one for MyModule and another one for mscorlib.
-// PersistentInlineTrackingMap.GetInliners() always reads all InlineeRecords as long as they have the same key, few of them filtered out as hash collisions
-// others provide legitimate inlining information for methods from different modules.
+// PersistentInlineTrackingMap.GetInliners() always reads all ZapInlineeRecords as long as they have the same key, few of them filtered out
+// as hash collisions others provide legitimate inlining information for methods from different modules.
//
-// m_inlinersBuffer - byte array compressed by NibbleWriter. At any valid offset taken from InlineeRecord from m_inlineeIndex, there is a compressed chunk
+// m_inlinersBuffer - byte array compressed by NibbleWriter. At any valid offset taken from ZapInlineeRecord from m_inlineeIndex, there is a compressed chunk
// of this format:
// [InlineeModuleZapIndex][InlinerModuleZapIndex] [N - # of following inliners] [#1 inliner method RID] ... [#N inliner method RID]
// [InlineeModuleZapIndex] is used to verify that we actually found a desired inlinee module (not just a name hash collision).
// [InlinerModuleZapIndex] is an index of a module that owns following method tokens (inliners)
// [1..N inliner RID] are the sorted diff compressed method RIDs from the module specified by InlinerModuleZapIndex,
-// those methods directly or indirectly inlined code from inlinee method specified by InlineeRecord.
+// those methods directly or indirectly inlined code from inlinee method specified by ZapInlineeRecord.
// Since all the RIDs are sorted we'are actually able to save some space by using diffs instead of values, because NibbleWriter
// is good at saving small numbers.
// For example for RIDs: 5, 6, 19, 25, 30, we'll write: 5, 1 (=6-5), 13 (=19-6), 6 (=25-19), 5 (=30-25)
@@ -170,39 +199,111 @@ typedef DPTR(InlineTrackingMap) PTR_InlineTrackingMap;
// | - - - | InlineeModuleZapIndex | InlinerModuleZapIndex | SavedInlinersCount (N) | rid1 | rid2 | ...... | ridN | - - - |
// +-----------------+-----------------------+------------------------+------------------------+------+------+--------+------+-------------+
//
-class PersistentInlineTrackingMap
+
+
+
+
+
+
+
+
+
+// R2R encoding variation for the map
+//
+// It has several differences from the NGEN encoding. NGEN refers to methods outside the current assembly via module index + foreign module's token
+// but R2R can't take those fragile dependencies. Instead we refer to all methods via MethodDef tokens in the current assembly's metadata. This
+// is sufficient for everything we need to track now but in the future we may need to upgrade to a more expressive encoding. Currently NonVersionable
+// attributed methods may be inlined but will not be tracked. This shows up as a known limitation in the profiler APIs that expose this data.
+//
+// The format changes from NGEN:
+// a) The InlineIndex uses a MethodDef RID token as the key.
+// b) InlineeModuleZapIndex is omitted because the module is always the current one being compiled.
+// c) InlinerModuleZapIndex is similarly omitted.
+// d) (a), (b) and (c) together imply there is at most one entry in the inlineeIndex for any given key
+// e) A trivial header is now explicitly described
+//
+//
+// The resulting serialized format is a sequence of blobs:
+// 1) Header (4 byte aligned)
+// short MajorVersion - currently set to 1, increment on breaking change
+// short MinorVersion - currently set to 0, increment on non-breaking format addition
+// int SizeOfInlineIndex - size in bytes of the inline index
+//
+// 2) InlineIndex - Immediately following header. This is a sorted (by ZapInlineeRecord.key) array of ZapInlineeRecords, given a method token (32 bits)
+// we use binary search to find if this method has ever been inlined in R2R code of this image. Each record has m_offset, which is
+// an offset inside InlinersBuffer, it has more data on where the method got inlined. There is at most one ZapInlineeRecord with the
+// same key.
+//
+// 3) InlinersBuffer - Located immediately following the InlineIndex (Header RVA + sizeof(Header) + header.SizeOfInlineIndex)
+// This is a byte array compressed by NibbleWriter. At any valid offset taken from ZapInlineeRecord from InlineeIndex, there is a
+// compressed chunk of this format:
+// [N - # of following inliners] [#1 inliner method RID] ... [#N inliner method RID]
+// [1..N inliner RID] are the sorted diff compressed method RIDs interpreted as MethodDefs in this assembly's metadata,
+// Those methods directly or indirectly inlined code from inlinee method specified by ZapInlineeRecord.
+// Since all the RIDs are sorted we'are actually able to save some space by using diffs instead of values, because NibbleWriter
+// is good at saving small numbers.
+// For example for RIDs: 5, 6, 19, 25, 30, we'll write: 5, 1 (=6-5), 13 (=19-6), 6 (=25-19), 5 (=30-25)
+//
+// InlineeIndex
+// +-----+-----+---------------------------------------+-----+-----+
+// | - | - | m_key {MethodDefToken); m_offset | - | - |
+// +-----+-----+---------------------------------|-----+-----+-----+
+// |
+// +--------------------------+
+// |
+// InlinersBuffer \-/
+// +-----------------+------------------------+------+------+--------+------+-------------+
+// | - - - | SavedInlinersCount (N) | rid1 | rid2 | ...... | ridN | - - - |
+// +-----------------+------------------------+------+------+--------+------+-------------+
+//
+
+
+
+//A common key format for R2R and NGEN. If the formats
+//diverge further this might become irrelevant
+struct ZapInlineeRecord
{
-private:
- struct InlineeRecord
+ DWORD m_key;
+ DWORD m_offset;
+
+ ZapInlineeRecord()
+ : m_key(0)
+ {
+ LIMITED_METHOD_CONTRACT;
+ }
+
+ void InitForR2R(RID rid)
+ {
+ LIMITED_METHOD_CONTRACT;
+ m_key = rid;
+ }
+
+ void InitForNGen(RID rid, LPCUTF8 simpleName);
+
+ bool operator <(const ZapInlineeRecord& other) const
{
- DWORD m_key;
- DWORD m_offset;
-
- InlineeRecord()
- : m_key(0)
- {
- LIMITED_METHOD_CONTRACT;
- }
-
- InlineeRecord(RID rid, LPCUTF8 simpleName);
-
- bool operator <(const InlineeRecord& other) const
- {
- LIMITED_METHOD_DAC_CONTRACT;
- return m_key < other.m_key;
- }
-
- bool operator ==(const InlineeRecord& other) const
- {
- LIMITED_METHOD_DAC_CONTRACT;
- return m_key == other.m_key;
- }
- };
- typedef DPTR(InlineeRecord) PTR_InlineeRecord;
+ LIMITED_METHOD_DAC_CONTRACT;
+ return m_key < other.m_key;
+ }
+
+ bool operator ==(const ZapInlineeRecord& other) const
+ {
+ LIMITED_METHOD_DAC_CONTRACT;
+ return m_key == other.m_key;
+ }
+};
+typedef DPTR(ZapInlineeRecord) PTR_ZapInlineeRecord;
+
+
+// This type knows how to serialize and deserialize the inline tracking map format within an NGEN image. See
+// above for a description of the format.
+class PersistentInlineTrackingMapNGen
+{
+private:
PTR_Module m_module;
- PTR_InlineeRecord m_inlineeIndex;
+ PTR_ZapInlineeRecord m_inlineeIndex;
DWORD m_inlineeIndexSize;
PTR_BYTE m_inlinersBuffer;
@@ -210,23 +311,63 @@ private:
public:
- PersistentInlineTrackingMap(Module *module)
+ PersistentInlineTrackingMapNGen(Module *module)
: m_module(dac_cast<PTR_Module>(module))
{
LIMITED_METHOD_CONTRACT;
_ASSERTE(module != NULL);
}
+ // runtime deserialization
+ COUNT_T GetInliners(PTR_Module inlineeOwnerMod, mdMethodDef inlineeTkn, COUNT_T inlinersSize, MethodInModule inliners[], BOOL *incompleteData);
+
+ // compile-time serialization
+#ifndef DACCESS_COMPILE
void Save(DataImage *image, InlineTrackingMap* runtimeMap);
void Fixup(DataImage *image);
- COUNT_T GetInliners(PTR_Module inlineeOwnerMod, mdMethodDef inlineeTkn, COUNT_T inlinersSize, MethodInModule inliners[], BOOL *incompleteData);
-
private:
- void ProcessInlineTrackingEntry(DataImage *image, SBuffer *inlinersBuffer, SArray<InlineeRecord> *inlineeIndex, InlineTrackingEntry *entry);
+#endif
+
Module *GetModuleByIndex(DWORD index);
+
};
-typedef DPTR(PersistentInlineTrackingMap) PTR_PersistentInlineTrackingMap;
+typedef DPTR(PersistentInlineTrackingMapNGen) PTR_PersistentInlineTrackingMapNGen;
+
+
+// This type knows how to serialize and deserialize the inline tracking map format within an R2R image. See
+// above for a description of the format.
+#ifdef FEATURE_READYTORUN
+class PersistentInlineTrackingMapR2R
+{
+private:
+ PTR_Module m_module;
+
+ PTR_ZapInlineeRecord m_inlineeIndex;
+ DWORD m_inlineeIndexSize;
+
+ PTR_BYTE m_inlinersBuffer;
+ DWORD m_inlinersBufferSize;
+
+public:
+
+ // runtime deserialization
+#ifndef DACCESS_COMPILE
+ static BOOL TryLoad(Module* pModule, const BYTE* pBuffer, DWORD cbBuffer, AllocMemTracker *pamTracker, PersistentInlineTrackingMapR2R** ppLoadedMap);
+#endif
+ COUNT_T GetInliners(PTR_Module inlineeOwnerMod, mdMethodDef inlineeTkn, COUNT_T inlinersSize, MethodInModule inliners[], BOOL *incompleteData);
+
+
+ // compile time serialization
+#ifndef DACCESS_COMPILE
+ static void Save(ZapHeap* pHeap, SBuffer *saveTarget, InlineTrackingMap* runtimeMap);
+#endif
+
+};
+
+typedef DPTR(PersistentInlineTrackingMapR2R) PTR_PersistentInlineTrackingMapR2R;
+#endif //FEATURE_READYTORUN
+
#endif //INLINETRACKING_H_
diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp
index 64471249fc..b05b891951 100644
--- a/src/vm/jitinterface.cpp
+++ b/src/vm/jitinterface.cpp
@@ -725,11 +725,31 @@ BOOL CEEInfo::shouldEnforceCallvirtRestriction(
// If the need arises (i.e. performance issues) we will define sets of assemblies (e.g. all app assemblies)
// The main point is that all this logic is concentrated in one place.
+// NOTICE: If you change this logic to allow multi-assembly version bubbles you
+// need to consider the impact on diagnostic tools. Currently there is an inlining
+// table which tracks inliner/inlinee relationships in R2R images but it is not
+// yet capable of encoding cross-assembly inlines. The scenario where this
+// may show are instrumenting profilers that want to instrument a given method A
+// using the ReJit APIs. If method A happens to inlined within method B in another
+// assembly then the profiler needs to know that so it can rejit B too.
+// The recommended approach is to upgrade the inlining table (vm\inlinetracking.h\.cpp)
+// now that presumably R2R images have some way to refer to methods in other
+// assemblies in their version bubble. Chat with the diagnostics team if you need more
+// details.
+//
+// There already is a case where cross-assembly inlining occurs in an
+// unreported fashion for methods marked NonVersionable. There is a specific
+// exemption called out for this on ICorProfilerInfo6::EnumNgenModuleMethodsInliningThisMethod
+// and the impact of the cut was vetted with partners. It would not be appropriate
+// to increase that unreported set without additional review.
+
+
bool IsInSameVersionBubble(Assembly * current, Assembly * target)
{
LIMITED_METHOD_CONTRACT;
// trivial case: current and target are identical
+ // DO NOT change this without reading the notice above
if (current == target)
return true;
@@ -740,6 +760,7 @@ bool IsInSameVersionBubble(Assembly * current, Assembly * target)
static bool IsInSameVersionBubble(MethodDesc* pCurMD, MethodDesc *pTargetMD)
{
LIMITED_METHOD_CONTRACT;
+ // DO NOT change this without reading the notice above
if (IsInSameVersionBubble(pCurMD->GetModule()->GetAssembly(),
pTargetMD->GetModule()->GetAssembly()))
{
diff --git a/src/vm/mda.cpp b/src/vm/mda.cpp
deleted file mode 100644
index 77c26a993e..0000000000
--- a/src/vm/mda.cpp
+++ /dev/null
@@ -1,4017 +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.
-
-
-#include "common.h"
-#include "eeconfig.h"
-#include "eeconfigfactory.h"
-#include "corhlpr.h"
-#include <xmlparser.h>
-#include <mscorcfg.h>
-#include <holder.h>
-#include <dbginterface.h>
-#include "wrappers.h"
-#include "mda.h"
-#include "mdaassistants.h"
-#include "sstring.h"
-#include "util.hpp"
-#include "debugdebugger.h"
-
-#ifdef MDA_SUPPORTED
-
-//
-// MdaHashtable
-//
-
-BOOL MdaLockOwner(LPVOID) { LIMITED_METHOD_CONTRACT; return TRUE; }
-
-BOOL IsJustMyCode(MethodDesc* pMethodDesc)
-{
- CONTRACT(BOOL)
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACT_END;
-
- if (!ManagedDebuggingAssistants::IsManagedDebuggerAttached())
- return TRUE;
-
- BOOL bIsJMC = FALSE;
-
- EX_TRY
- {
- if (g_pDebugInterface && g_pDebugInterface->IsJMCMethod(pMethodDesc->GetModule(), pMethodDesc->GetMemberDef()))
- bIsJMC = TRUE;
- }
- EX_CATCH
- {
- }
- EX_END_CATCH(SwallowAllExceptions);
-
- RETURN bIsJMC;
-}
-
-
-//
-// ManagedDebuggingAssistants
-//
-
-const bool g_mdaAssistantIsSwitch[] =
-{
-#define MDA_ASSISTANT_IS_SWITCH
-#include "mdaschema.inl"
-#undef MDA_ASSISTANT_IS_SWITCH
- false
-};
-
-void ManagedDebuggingAssistants::Initialize()
-{
- CONTRACT_VOID
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACT_END;
-
- EX_TRY
- {
- //
- // Initialize
- //
- m_pSwitchActivationXml = NULL;
- m_pMdaXmlIndustry = new MdaXmlIndustry();
-
- MdaSchema::Initialize();
-
- //
- // Create AssistantSchema
- //
- m_pAssistantSchema = new MdaAssistantSchema();
-
- //
- // Create AssistantMsgSchema
- //
- m_pAssistantMsgSchema = new MdaAssistantMsgSchema();
-
- //
- // Create SchemaSchema
- //
- m_pSchemaSchema = new MdaSchemaSchema();
-
- //
- // InvalidConfigFile
- //
- g_mdaStaticHeap.m_mdaInvalidConfigFile.Enable();
-
-#ifdef _DEBUG
- StackSString sszValidateFramework(CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MDAValidateFramework));
- if (!sszValidateFramework.IsEmpty() && sszValidateFramework.Equals(W("1")))
- DebugInitialize();
-#endif
- }
- EX_CATCH
- {
- // MDA State corrupted, unable to initialize, runtime still OK
- }
- EX_END_CATCH(SwallowAllExceptions);
-
- RETURN;
-}
-
-MdaEnvironment::~MdaEnvironment()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (m_pStringFactory)
- delete m_pStringFactory;
-
- if (m_pGroups)
- delete m_pGroups;
-
- if (m_szMda)
- delete m_szMda;
-}
-
-MdaEnvironment::MdaEnvironment()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- m_bDisable = TRUE;
- m_szMda = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_MDA);
- m_pStringFactory = NULL;
- m_pGroups = NULL;
-
- if (ManagedDebuggingAssistants::IsManagedDebuggerAttached())
- {
- if (m_pStringFactory == NULL)
- m_pStringFactory = new MdaFactory<StackSString>();
-
- if (m_pGroups == NULL)
- m_pGroups = new SArray<SString*>();
-
- SString* pStr = m_pStringFactory->Create();
- pStr->Set(W("managedDebugger"));
- m_pGroups->Append(pStr);
- m_bDisable = FALSE;
- }
-
- if (ManagedDebuggingAssistants::IsUnmanagedDebuggerAttached())
- {
- if (m_pStringFactory == NULL)
- m_pStringFactory = new MdaFactory<StackSString>();
-
- if (m_pGroups == NULL)
- m_pGroups = new SArray<SString*>();
-
- SString* pStr = m_pStringFactory->Create();
- pStr->Set(W("unmanagedDebugger"));
- m_pGroups->Append(pStr);
- m_bDisable = FALSE;
- }
-
- if (m_szMda)
- {
- if (m_pStringFactory == NULL)
- m_pStringFactory = new MdaFactory<StackSString>();
-
- if (m_pGroups == NULL)
- m_pGroups = new SArray<SString*>();
-
- StackSString sszMda(m_szMda);
- SString::Iterator s = sszMda.Begin();
- SString::Iterator e = s;
-
- while (true)
- {
- if (!sszMda.Find(e, W(';')))
- e = sszMda.End();
- SString* psszGroup = m_pStringFactory->Create();
- psszGroup->Set(sszMda, s, e);
-
- if (psszGroup->Equals(W("0")))
- {
- m_pGroups->Clear();
- m_bDisable = TRUE;
- }
- else
- {
- m_pGroups->Append(psszGroup);
-
- m_bDisable = FALSE;
- }
-
- if (e == sszMda.End())
- break;
- s = ++e;
- }
- }
-
- if (m_bDisable == FALSE)
- {
- // If we get here, m_pStringFactory should already have been created.
- _ASSERTE(m_pStringFactory != NULL);
-
- WCHAR szExe[_MAX_PATH];
- if (!WszGetModuleFileName(NULL, szExe, _MAX_PATH))
- return;
-
- // Construct file name of the config file
- m_psszConfigFile = m_pStringFactory->Create();
- m_psszConfigFile->Set(szExe);
- m_psszConfigFile->Append(W(".config"));
-
- // Construct file name of mda config file
- m_psszMdaConfigFile = m_pStringFactory->Create();
- m_psszMdaConfigFile->Set(szExe);
- m_psszMdaConfigFile->Append(W(".mda.config"));
- }
-}
-
-void ManagedDebuggingAssistants::EEStartupActivation()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- //
- // Read environment variable, then registry settings
- //
- MdaEnvironment env;
-
- if (env.IsDisabled())
- return;
-
- AllocateManagedDebuggingAssistants();
-
- //
- // ConfigFile Activation
- //
- g_mdaStaticHeap.m_pMda->EnvironmentActivation(&env);
-}
-
-#ifdef _DEBUG
-void ManagedDebuggingAssistants::DebugInitialize()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- SO_INTOLERANT;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- //
- // Validate MDA output on Debug builds
- //
- m_bValidateOutput = TRUE;
-
- //
- // XmlValidationError
- //
- g_mdaStaticHeap.m_mdaXmlValidationError.Enable();
-
- MdaSchema::ValidationResult validationResult;
-
- //
- // Validate SchemaScheam
- //
- MdaXmlElement* pXmlSchemaSchema = m_pSchemaSchema->ToXml(m_pMdaXmlIndustry);
- if (m_pSchemaSchema->Validate(pXmlSchemaSchema, &validationResult)->ValidationFailed())
- {
- MDA_TRIGGER_ASSISTANT(XmlValidationError, ReportError(&validationResult));
- UNREACHABLE();
- }
-
- //
- // Validate AssistantSchema
- //
- MdaXmlElement* pXmlAssistantSchema = m_pAssistantSchema->ToXml(m_pMdaXmlIndustry);
- if (m_pSchemaSchema->Validate(pXmlAssistantSchema, &validationResult)->ValidationFailed())
- {
- MDA_TRIGGER_ASSISTANT(XmlValidationError, ReportError(&validationResult));
- ASSERT(!W("You're modifications to MdaAssistantSchema for assistant input don't conform to XSD"));
- }
-
- //
- // Validate AssistantMsgSchema
- //
- MdaXmlElement* pXmlAssistantMsgSchema = m_pAssistantMsgSchema->ToXml(m_pMdaXmlIndustry);
- if (m_pSchemaSchema->Validate(pXmlAssistantMsgSchema, &validationResult)->ValidationFailed())
- {
- MDA_TRIGGER_ASSISTANT(XmlValidationError, ReportError(&validationResult));
- ASSERT(!W("You're modifications to MdaAssistantSchema for assistant output don't conform to XSD"));
- }
-}
-#endif
-
-void ManagedDebuggingAssistants::ConfigFileActivation(LPCWSTR szConfigFile, MdaXmlIndustry* pXmlIndustry, MdaHashtable<MdaXmlElement*>* pMdaXmlPairs)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- // Parse
- MdaSchema::ValidationResult validationResult;
- MdaXmlElement* pMdaConfig = MdaConfigFactory::ParseXmlStream(pXmlIndustry, szConfigFile);
- if (!pMdaConfig)
- return;
-
- // Validate
- if (m_pAssistantSchema->Validate(pMdaConfig, &validationResult)->ValidationFailed())
- {
- MDA_TRIGGER_ASSISTANT(InvalidConfigFile, ReportError(MdaElemDef(MdaConfig)));
- g_mdaStaticHeap.DisableAll();
- return;
- }
-
- // Activate
- InlineSArray<MdaXmlElement*, MdaElemDef(Max)> xmlMdaConfigs;
- MdaXPath::FindElements(pMdaConfig, W("/mdaConfig/assistants/*"), &xmlMdaConfigs);
- for(COUNT_T i = 0; i < xmlMdaConfigs.GetCount(); i ++)
- {
- MdaXmlElement* pXmlMdaConfig = xmlMdaConfigs[i];
- if (pXmlMdaConfig->GetAttribute(MdaAttrDecl(Enable))->GetValueAsBool())
- {
- pMdaXmlPairs->Set(pXmlMdaConfig->GetName(), xmlMdaConfigs[i]);
- }
- else
- {
- if (pMdaXmlPairs->HasKey(pXmlMdaConfig->GetName()))
- pMdaXmlPairs->DeleteValue(pXmlMdaConfig->GetName());
- }
- }
-}
-
-MdaXmlElement* ManagedDebuggingAssistants::GetSwitchActivationXml(MdaElemDeclDef mda)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (g_mdaAssistantIsSwitch[mda])
- {
- MdaXmlElement* pXml = m_pMdaXmlIndustry->CreateElement()->SetDeclDef(mda);
- pXml->AddAttributeBool(MdaAttrDecl(Enable), TRUE);
- return pXml;
- }
- else
- {
- if (!m_pSwitchActivationXml)
- {
- MdaXmlElement* pXmlMdaConfig = m_pMdaXmlIndustry->CreateElement()->SetDeclDef(MdaElemDef(MdaConfig));
- m_pSwitchActivationXml = pXmlMdaConfig->AddChild(MdaElemDecl(Assistants));
-
- for (COUNT_T i = 0; i < MdaElemDef(AssistantMax); i ++)
- m_pSwitchActivationXml->AddChild((MdaElemDeclDef)i);
-
- MdaSchema::ValidationResult validationResult;
-
- // Validating the schema has the side-effect of initializing the default XML attributes
- if (m_pAssistantSchema->Validate(pXmlMdaConfig, &validationResult)->ValidationFailed())
- ASSERT(!W("MDA Assistant must allow <Assistant /> form."));
- }
-
- return m_pSwitchActivationXml->GetChild(mda);
- }
-}
-
-void ManagedDebuggingAssistants::ActivateGroup(LPCWSTR groupName, SArray<MdaElemDeclDef>* pGroupMdaXmlParis, MdaHashtable<MdaXmlElement*>* pActivationMdaXmlPairs)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- StackSString sszGroupName(groupName);
- BOOL bIsManagedDebuggerSet = sszGroupName.EqualsCaseInsensitive(W("managedDebugger"));
-
- SArray<MdaElemDeclDef>& groupMdaXmlParis = *pGroupMdaXmlParis;
-
- for (COUNT_T i = 0; i < groupMdaXmlParis.GetCount(); i++)
- {
- MdaElemDeclDef mda = groupMdaXmlParis[i];
- MdaXmlElement* pSwitchActivationXml = GetSwitchActivationXml(mda);
-
- PREFIX_ASSUME(pSwitchActivationXml != NULL);
-
- pSwitchActivationXml->AddAttributeBool(MdaAttrDecl(SuppressDialog), bIsManagedDebuggerSet);
-
- pActivationMdaXmlPairs->Set(MdaSchema::g_arElementNames[mda], pSwitchActivationXml);
- }
-}
-
-LPCWSTR ToLowerFirstChar(LPCWSTR name, MdaFactory<SString>* pSstringFactory)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- ASSERT(*name >= 'A' && *name <= 'Z');
-
- SString* pOutput = pSstringFactory->Create();
- pOutput->Clear();
- pOutput->Append(*name - W('A') + W('a'));
- pOutput->Append(&name[1]);
- return pOutput->GetUnicode();
-}
-
-void ManagedDebuggingAssistants::EnvironmentActivation(MdaEnvironment* pEnvironment)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (pEnvironment->GetActivationMechanisms().GetCount() == 0)
- return;
-
- MdaFactory<StackSArray<MdaElemDeclDef> > arrayFactory;
- MdaFactory<SString> sstringFactory;
- MdaHashtable<MdaXmlElement*> mdaXmlPairs;
-
- // Activate
- SArray<SString*>& aActivationMechanisms = pEnvironment->GetActivationMechanisms();
- SArray<MdaElemDeclDef>* pGroup = NULL;
- StackSArray<SArray<MdaElemDeclDef>* > aGroups;
-
-#define MDA_DEFINE_GROUPS
-#include "mdaschema.inl"
-#undef MDA_DEFINE_GROUPS
-
- // Match COMPlus_MDA env var to group
- for (COUNT_T i = 0; i < aActivationMechanisms.GetCount(); i++)
- {
- SString& sszActivationMechanism = *aActivationMechanisms[i];
-
- if (sszActivationMechanism.EqualsCaseInsensitive(W("ConfigFile")) || sszActivationMechanism.EqualsCaseInsensitive(W("1")))
- {
- ConfigFileActivation(pEnvironment->GetMdaConfigFile(), m_pMdaXmlIndustry, &mdaXmlPairs);
- }
- else
- {
- COUNT_T cGroup = 0;
-
-#define MDA_ACTIVATE_GROUPS
-#include "mdaschema.inl"
-#undef MDA_ACTIVATE_GROUPS
-
-#define MDA_ACTIVATE_SINGLTON_GROUPS
-#include "mdaschema.inl"
-#undef MDA_ACTIVATE_SINGLTON_GROUPS
-
- }
- }
-
- if (mdaXmlPairs.GetCount() == 0)
- return;
-
- // Create
- MdaXmlElement* pXmlAssistant = NULL;
-
-#define MDA_ASSISTANT_CREATION
-#include "mdaschema.inl"
-#undef MDA_ASSISTANT_CREATION
-}
-
-typedef enum
-{
- MDA_MSGBOX_NONE = 0,
- MDA_MSGBOX_RETRY = 4,
- MDA_MSGBOX_CANCLE = 2,
-} MsgBoxResult;
-
-BOOL ManagedDebuggingAssistants::IsUnmanagedDebuggerAttached()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (IsDebuggerPresent())
- return TRUE;
-
- return FALSE;
-}
-
-BOOL ManagedDebuggingAssistants::IsManagedDebuggerAttached()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
-#if DEBUGGING_SUPPORTED
- if (CORDebuggerAttached())
- return TRUE;
-#endif
-
- return FALSE;
-}
-
-BOOL ManagedDebuggingAssistants::IsDebuggerAttached()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- return IsUnmanagedDebuggerAttached() || IsManagedDebuggerAttached();
-}
-
-MdaXmlElement* ManagedDebuggingAssistants::GetRootElement(MdaXmlElement* pMdaXmlRoot)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- pMdaXmlRoot->SetDeclDef(MdaElemDef(Msg));
- pMdaXmlRoot->AddAttributeSz(MdaAttrDecl(Xmlns), MDA_TARGET_NAMESPACE)->SetNs(W("mda"));
- return pMdaXmlRoot;
-}
-
-
-
-//
-// MdaXmlMessage
-//
-BOOL IsFormatChar(WCHAR c) { LIMITED_METHOD_CONTRACT; return (c == W('\\') || c == W('!') || c == W('+') || c == W('.') || c == W(':') || c == W('-')); }
-
-// Logic copied from /fx/src/Xml/System/Xml/Core/XmlRawTextWriterGenerator.cxx::WriteAttributeTextBlock
-SString& MdaXmlEscape(SString& sszBuffer, const SString& sszXml, BOOL bEscapeComment = FALSE)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- sszBuffer.Clear();
-
- SString::CIterator itr = sszXml.Begin();
- SString::CIterator end = sszXml.End();
-
- while (itr != end)
- {
- WCHAR c = *itr;
-
- switch(c)
- {
- case W('-'):
- if (*(itr+1) == W('-') && bEscapeComment)
- sszBuffer.Append(W("- "));
- else
- sszBuffer.Append(W("-"));
- break;
- case W('&'):
- sszBuffer.Append(W("&amp;"));
- break;
- case W('<'):
- sszBuffer.Append(W("&lt;"));
- break;
- case W('>'):
- sszBuffer.Append(W("&gt;"));
- break;
- case W('"'):
- sszBuffer.Append(W("&quote;"));
- break;
- default:
- sszBuffer.Append(c);
- }
-
- itr++;
- }
-
- return sszBuffer;
-}
-
-SString* WrapString(SString& buffer, SString& sszString, SCOUNT_T cWidth, SCOUNT_T cIndent = 0, SCOUNT_T cPostIndent = 0)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- StackSString sszEscapedString;
- MdaXmlEscape(sszEscapedString, sszString, TRUE);
-
- StackSString sszIndent;
- for (SCOUNT_T i = 0; i < cIndent; i ++)
- sszIndent.Append(W(" "));
-
- StackSString sszPostIndent;
- for (SCOUNT_T i = 0; i < cPostIndent; i ++)
- sszPostIndent.Append(W(" "));
-
- buffer.Append(sszIndent);
-
- SString::CIterator itr = sszEscapedString.Begin();
- SString::CIterator lineStart = sszEscapedString.Begin();
- SString::CIterator lineEnd = sszEscapedString.Begin();
- SString::CIterator lastFormatChar = sszEscapedString.Begin();
- SString::CIterator end = sszEscapedString.End();
-
- while (itr != end)
- {
- if (*itr == W(' '))
- lineEnd = itr;
-
- // Keep track of reasonable breaks in member and file names...
- if (IsFormatChar(*itr) && itr - lineStart < cWidth)
- lastFormatChar = itr;
-
- if (itr - lineStart >= cWidth || *itr == W('\n'))
- {
- if (*itr == W('\n'))
- lineEnd = itr;
-
- // If we didn't find a space or wrapping at found space wraps less than 3/5 of the line...
- else if (lineEnd == end || itr - lineEnd > cWidth * 3 / 5)
- {
- // ...then if we found a format char, start the wrap there...
- if (lastFormatChar != end)
- lineEnd = lastFormatChar + 1;
- // ...else just do a simple wrap...
- else
- lineEnd = itr;
- }
-
- SString sszLine(sszEscapedString, lineStart, lineEnd);
- buffer.Append(sszLine);
- buffer.Append(sszPostIndent);
- buffer.Append(W("\n"));
- buffer.Append(sszIndent);
-
- lineStart = lineEnd;
-
- // If we wrapped on a space or a return than skip over that character as we already replaced it with a \n.
- if (*lineEnd == W(' ') || *lineEnd == W('\n'))
- lineStart++;
-
- lineEnd = end;
- lastFormatChar = end;
- }
-
- itr++;
- }
-
- SString sszLine(sszEscapedString, lineStart, itr);
- buffer.Append(sszLine);
-
- return &buffer;
-}
-
-LPCWSTR ToUpperFirstChar(SString& buffer, LPCWSTR name)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- ASSERT(*name >= 'a' && *name <= 'z');
-
- buffer.Clear();
- buffer.Append(*name - W('a') + W('A'));
- buffer.Append(&name[1]);
- return buffer.GetUnicode();
-}
-
-MdaXmlMessage::MdaXmlMessage(MdaAssistant* pAssistant, BOOL bBreak, MdaXmlElement** ppMdaXmlRoot)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(g_mdaStaticHeap.m_pMda));
- }
- CONTRACTL_END;
-
- m_pMdaAssistant = pAssistant;
- m_bBreak = (pAssistant->GetSuppressDialog()) ? FALSE : bBreak;
- m_pMdaXmlRoot = g_mdaStaticHeap.m_pMda->GetRootElement(m_mdaXmlIndustry.CreateElement());
- *ppMdaXmlRoot = m_pAssistantXmlRoot = pAssistant->GetRootElement(m_mdaXmlIndustry.CreateElement(), bBreak);
-}
-
-MdaXmlMessage::MdaXmlMessage(MdaXmlElement** ppMdaXmlRoot) : m_bBreak(FALSE)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(g_mdaStaticHeap.m_pMda));
- }
- CONTRACTL_END;
-
- *ppMdaXmlRoot = m_pMdaXmlRoot = g_mdaStaticHeap.m_pMda->GetRootElement(m_mdaXmlIndustry.CreateElement());
-}
-
-BOOL MdaXmlMessage::ShouldLogToManagedDebugger()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- BOOL bUnmanagedDebuggerAttached = FALSE;
- BOOL bManagedDebuggerAttached = FALSE;
- BOOL bManagedDebugLoggingEnabled = FALSE;
-
- bUnmanagedDebuggerAttached = IsUnmanagedDebuggerAttached();
-
-#if DEBUGGING_SUPPORTED
- bManagedDebuggerAttached = IsManagedDebuggerAttached();
- bManagedDebugLoggingEnabled = (g_pDebugInterface && g_pDebugInterface->IsLoggingEnabled());
-#endif
-
- return (!bUnmanagedDebuggerAttached && bManagedDebuggerAttached && bManagedDebugLoggingEnabled);
-}
-
-// Send an event for this MDA.
-void MdaXmlMessage::SendEvent()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (IsHostRegisteredForEvent(Event_MDAFired))
- {
- // A host is registered for the MDA fired event so let's start by notifying the
- // debugger is on is attached.
- if (IsManagedDebuggerAttached() || IsUnmanagedDebuggerAttached())
- {
- SendDebugEvent();
- }
-
- // Now that the debugger has been notified and continued, let's notify the host
- // so it can take any action it deems neccessary based on the MDA that fired.
- SendHostEvent();
- }
- else
- {
- // We aren't hosted or no host registered for the MDA fired event so let's simply
- // send the MDA to the debubber. Note that as opposed to the hosted case, we
- // will force a JIT attach if no debugger is present.
- SendDebugEvent();
- }
-}
-
-// Send an event for this MDA.
-void MdaXmlMessage::SendHostEvent()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- MDAInfo info;
- SString strStackTrace;
-
- EX_TRY
- {
- // Retrieve the textual representation of the managed stack trace and add it to
- // the MDA information we give the host.
- GetManagedStackTraceString(TRUE, strStackTrace);
- }
- EX_CATCH
- {
- // We failed to get the stack trace string. This isn't fatal, we will simply not be
- // able to provide this information as part of the notification.
- }
- EX_END_CATCH(SwallowAllExceptions);
-
- // Set up the information and invoke the host to process the MDA fired event.
- info.lpMDACaption = m_pMdaAssistant->GetName();
- info.lpStackTrace = strStackTrace;
- info.lpMDAMessage = m_localizedMessage;
- ProcessEventForHost(Event_MDAFired, &info);
-
- // If the host initiated a thread abort, we want to raise it immediatly to
- // prevent any further code inside the VM from running and potentially
- // crashing the process.
- Thread *pThread = GetThread();
- TESTHOOKCALL(AppDomainCanBeUnloaded(pThread->GetDomain()->GetId().m_dwId,FALSE));
-
- if (pThread && pThread->IsAbortInitiated())
- pThread->HandleThreadAbort(TRUE);
-}
-
-// Send a managed debug event for this MDA.
-// This will block until the debugger continues us. This means the debugger could to things like run callstacks
-// and change debuggee state.
-void MdaXmlMessage::SendDebugEvent()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(g_mdaStaticHeap.m_pMda));
- }
- CONTRACTL_END;
-
- // Simple check to avoid getting XML string if we're not going to actually use it.
- if (!IsManagedDebuggerAttached() && !IsUnmanagedDebuggerAttached() && !m_bBreak)
- {
- return;
- }
-
- EX_TRY
- {
- StackSString sszXml;
- LPCWSTR ns = NULL;
-
- MdaSchema * pSchema = g_mdaStaticHeap.m_pMda->m_pAssistantSchema;
- ns = pSchema->SetRootAttributes(m_pMdaXmlRoot);
- m_pMdaXmlRoot->ToXml(&sszXml, ns);
-
- // For managed + interop cases, send a managed debug event.
- // If m_bBreak is true and no unmanaged debugger is attached trigger a jit-attach.
- if (IsManagedDebuggerAttached() || (m_bBreak && !IsUnmanagedDebuggerAttached()))
- {
- // Get MDA name (this is the type)
- StackSString sszMdaName;
- ToUpperFirstChar(sszMdaName, m_pMdaAssistant->GetName());
- // SendMDANotification needs to be called in preemptive GC mode.
- GCX_PREEMP();
-
- // This will do two things:
- // 1. If a managed debugger is attached, it will send the managed debug event for the MDA.
- // 2. If it's a m_bBreak, we'll try to do a managed jit-attach.
- // This blocks until continued. Since we're not slipping, we don't need the MDA_FLAG_SLIP flag.
- g_pDebugInterface->SendMDANotification(
- GetThread(),
- &sszMdaName,
- &m_localizedMessage,
- &sszXml,
- ((CorDebugMDAFlags) 0 ),
- RunningInteractive() ? m_bBreak : FALSE);
- }
-
- if (IsUnmanagedDebuggerAttached() && !IsManagedDebuggerAttached())
- {
- // For native case, sent native debug event for logging.
- WszOutputDebugString(sszXml.GetUnicode());
-
- if (m_bBreak)
- RetailBreak();
- }
- }
- EX_CATCH
- {
- // No global MDA state modified in TRY
- }
- EX_END_CATCH(SwallowAllExceptions);
-}
-
-void MdaXmlMessage::SendMessagef(int resourceID, ...)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- StackSString sszResourcef;
- sszResourcef.LoadResource(CCompRC::DesktopCLR, resourceID );
- ASSERT(!sszResourcef.IsEmpty());
-
- va_list argItr;
- va_start(argItr, resourceID);
- m_localizedMessage.PVPrintf(sszResourcef, argItr);
- va_end(argItr);
-
- SendMessage();
-}
-
-
-void MdaXmlMessage::SendMessage(int resourceID)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- SendMessagef(resourceID);
-}
-
-void MdaXmlMessage::SendMessage(LPCWSTR szMessage)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- m_localizedMessage.Set(szMessage);
-
- SendMessage();
-}
-
-void MdaXmlMessage::SendMessage()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(g_mdaStaticHeap.m_pMda));
- }
- CONTRACTL_END;
-
-#if _DEBUG
- if (g_mdaStaticHeap.m_pMda->m_bValidateOutput)
- {
- MdaSchema::ValidationResult validationResult;
- if (g_mdaStaticHeap.m_pMda->m_pAssistantMsgSchema->Validate(m_pAssistantXmlRoot, &validationResult)->ValidationFailed())
- {
- MDA_TRIGGER_ASSISTANT(XmlValidationError, ReportError(&validationResult));
- ASSERT(W("Your MDA assistant's output did not match its output schema."));
- }
- }
-#endif
-
- if (!m_localizedMessage.IsEmpty())
- {
- StackSString sszComment(m_localizedMessage);
- StackSString sszWrappedComment(W("\n"));
- WrapString(sszWrappedComment, sszComment, 80, 7);
- sszWrappedComment.Append(W("\n "));
- m_pMdaXmlRoot->AddChildComment(sszWrappedComment.GetUnicode());
- }
-
- m_pMdaXmlRoot->AddChild(m_pAssistantXmlRoot);
-
- // Send applicable debug event (managed, native, interop) for this MDA.
- // If this is a severe probe, it may trigger a jit-attach
- SendEvent();
-}
-
-
-//
-// MdaXPath::FindXXX
-//
-
-void MdaXPath::Find(SArray<MdaXPathVariable>& args, SString* pWildCard, va_list argItr)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- for (COUNT_T i = 0; i < GetArgCount(); i ++)
- {
- XPathVarType varType = m_argTypes[i];
-
- if (varType == XPathVarElemDeclDef)
- args[i].m_u.m_elemDeclDef = va_arg(argItr, MdaElemDeclDef);
-
- else if (varType == XPathVarAttrDeclDef)
- args[i].m_u.m_attrDeclDef = va_arg(argItr, MdaAttrDeclDef);
-
- else if (varType == XPathVarAttrBool)
- args[i].m_u.m_bool = va_arg(argItr, BOOL);
-
- else if (varType == XPathVarAttrINT32)
- args[i].m_u.m_int32 = va_arg(argItr, INT32);
-
- else if (varType == XPathVarAttrSString)
- {
- SString* pSString = va_arg(argItr, SString*);
- ASSERT(CheckPointer(pSString, NULL_OK));
- if (!pSString)
- pSString = pWildCard;
- args[i].m_u.m_pSstr = pSString;
- }
-
- else { UNREACHABLE(); }
- }
-}
-
-MdaXmlElement* MdaXPath::FindElement(MdaXmlElement* pRoot, ...)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (!pRoot)
- return NULL;
-
- va_list argItr;
- va_start(argItr, pRoot);
-
- SString wildCard;
- InlineSArray<MdaXPathVariable, 20> args;
- Find(args, &wildCard, argItr);
-
- MdaXPathResult result(&args);
- m_pCompiledQuery->Run(pRoot, &result);
-
- va_end(argItr);
- return result.GetXmlElement();
-}
-
-MdaXmlAttribute* MdaXPath::FindAttribute(MdaXmlElement* pRoot, ...)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (!pRoot)
- return NULL;
-
- va_list argItr;
- va_start(argItr, pRoot);
-
- SString wildCard;
- InlineSArray<MdaXPathVariable, 20> args;
- Find(args, &wildCard, argItr);
-
- MdaXPathResult result(&args);
- m_pCompiledQuery->Run(pRoot, &result);
-
- va_end(argItr);
- return result.GetXmlAttribute();
-}
-
-SArray<MdaXmlElement*>* MdaXPath::FindElements(MdaXmlElement* pRoot, SArray<MdaXmlElement*>* pResult, ...)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (!pRoot)
- return NULL;
-
- va_list argItr;
- va_start(argItr, pResult);
-
- SString wildCard;
- InlineSArray<MdaXPathVariable, 20> args;
- Find(args, &wildCard, argItr);
-
- MdaXPathResult result(pResult, &args);
- m_pCompiledQuery->Run(pRoot, &result);
-
- va_end(argItr);
- return pResult;
-}
-
-SArray<MdaXmlAttribute*>* MdaXPath::FindAttributes(MdaXmlElement* pRoot, SArray<MdaXmlAttribute*>* pResult, ...)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (!pRoot)
- return NULL;
-
- va_list argItr;
- va_start(argItr, pResult);
-
- SString wildCard;
- InlineSArray<MdaXPathVariable, 20> args;
- Find(args, &wildCard, argItr);
-
- MdaXPathResult result(pResult, &args);
- m_pCompiledQuery->Run(pRoot, &result);
-
- va_end(argItr);
- return pResult;
-}
-
-
-//
-// MdaXPath::MdaXPathCompiler -- Lexifier
-//
-
-#define ISWHITE(ch) (ch == W(' ') || ch == W('\t') || ch == W('\n'))
-#define ISRESERVED(ch) (wcschr(W("./()[]&|=@*?':"), ch) != NULL)
-#define ISMDAID(ch) (!ISWHITE(ch) && !ISRESERVED(ch))
-
-MdaXPath::MdaXPathCompiler::MdaXPathTokens MdaXPath::MdaXPathCompiler::LexAToken()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (*m_itr == W('\0'))
- return MdaXPathEnd;
-
- if (ISWHITE(*m_itr))
- {
- m_itr++;
- return LexAToken();
- }
-
- if (ISMDAID(*m_itr))
- {
- m_identifier.Clear();
-
- do
- {
- m_identifier.Append(*m_itr);
- m_itr++;
- }
- while(ISMDAID(*m_itr));
-
- m_identifier.Append(W("\0"));
- return MdaXPathIdentifier;
- }
-
- if (*m_itr == W('\''))
- {
- m_identifier.Clear();
-
- m_itr++;
-
- while(*m_itr != W('\''))
- {
- m_identifier.Append(*m_itr);
- m_itr++;
- }
-
- m_identifier.Append(W("\0"));
-
- m_itr++;
- return MdaXPathQuotedString;
- }
-
- WCHAR c = *m_itr;
- m_itr++;
- switch(c)
- {
- case W('.'): return MdaXPathDot;
- case W('/'): return MdaXPathSlash;
- case W('('): return MdaXPathOpenParen;
- case W(')'): return MdaXPathCloseParen;
- case W('['): return MdaXPathOpenSqBracket;
- case W(']'): return MdaXPathCloseSqBracket;
- case W('&'): return MdaXPathLogicalAnd;
- case W('|'): return MdaXPathLogicalOr;
- case W('='): return MdaXPathEquals;
- case W('@'): return MdaXPathAtSign;
- case W('*'): return MdaXPathAstrix;
- case W('?'): return MdaXPathQMark;
- }
-
- UNREACHABLE();
-}
-
-
-//
-// MdaXPath::MdaXPathCompiler -- Parser
-//
-
-// XPATH
-// '/' ELEMENT_EXPR end
-// '/' ELEMENT_EXPR XPATH
-// '/' ATTRIBUTE end
-MdaXPath::MdaXPathBase* MdaXPath::MdaXPathCompiler::XPATH()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
- PRECONDITION(TokenIs(MdaXPathXPATH));
-
- MdaXPathElement* pElementExpr = NULL;
-
- NextToken();
- if (TokenIs(MdaXPathELEMENT_EXPR))
- pElementExpr = ELEMENT_EXPR();
-
- else if (TokenIs(MdaXPathATTRIBUTE))
- {
- MdaXPathAttribute* pAttr = ATTRIBUTE();
- pAttr->MarkAsTarget();
- NextToken();
- ASSERT(TokenIs(MdaXPathEnd));
- return pAttr;
- }
-
- else { UNREACHABLE(); }
-
-
- if (TokenIs(MdaXPathEnd))
- return pElementExpr->MarkAsTarget();
-
- else if (TokenIs(MdaXPathXPATH))
- return pElementExpr->SetChild(XPATH());
-
- else { UNREACHABLE(); }
-}
-
-// ATTRIBUTE
-// '@' id
-// '@' '?'
-MdaXPath::MdaXPathAttribute* MdaXPath::MdaXPathCompiler::ATTRIBUTE()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
- PRECONDITION(TokenIs(MdaXPathATTRIBUTE));
-
- MdaXPathAttribute* pAttr = NULL;
-
- NextToken();
- if (TokenIs(MdaXPathQMark))
- {
- pAttr = m_pXPath->m_attrFactory.Create()->SetName(++m_pXPath->m_cArgs);
- *m_pXPath->m_argTypes.Append() = XPathVarAttrDeclDef;
- }
-
- else if (TokenIs(MdaXPathIdentifier))
- {
- pAttr = m_pXPath->m_attrFactory.Create()->SetName(MdaSchema::GetAttributeType(GetIdentifier()));
- }
-
- else { UNREACHABLE(); }
-
- NextToken();
- return pAttr;
-}
-
-// ELEMENT_EXPR
-// ELEMENT '[' FILTER_EXPR ']'
-// ELEMENT
-MdaXPath::MdaXPathElement* MdaXPath::MdaXPathCompiler::ELEMENT_EXPR()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
- PRECONDITION(TokenIs(MdaXPathELEMENT_EXPR));
-
- MdaXPathElement* pElement = ELEMENT();
-
- if (TokenIs(MdaXPathOpenSqBracket))
- {
- NextToken();
- pElement->SetQualifier(FILTER_EXPR());
- ASSERT(TokenIs(MdaXPathCloseSqBracket));
-
- NextToken();
- }
-
- return pElement;
-}
-
-// FILTER_EXPR
-// FILTER
-// '(' FILTER ')'
-// FILTER '&' FILTER
-// FILTER '|' FILTER
-MdaXPath::MdaXPathBase* MdaXPath::MdaXPathCompiler::FILTER_EXPR()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
- PRECONDITION(TokenIs(MdaXPathFILTER_EXPR));
-
- // '(' FILTER ')'
- if (TokenIs(MdaXPathOpenParen))
- {
- MdaXPath::MdaXPathBase* pFilter = FILTER();
- ASSERT(TokenIs(MdaXPathCloseParen));
-
- NextToken();
- return pFilter;
- }
-
- if (TokenIs(MdaXPathFILTER))
- {
- MdaXPath::MdaXPathBase* pFilter = FILTER();
-
- // FILTER '&' FILTER
- if (TokenIs(MdaXPathLogicalAnd))
- {
- NextToken();
- return m_pXPath->m_logicalOpFactory.Create()->Initialize(TRUE, pFilter, FILTER());
- }
-
- // FILTER '|' FILTER
- if (TokenIs(MdaXPathLogicalOr))
- {
- NextToken();
- return m_pXPath->m_logicalOpFactory.Create()->Initialize(FALSE, pFilter, FILTER());
- }
-
- // FILTER
- return pFilter;
- }
-
- UNREACHABLE();
-}
-
-// FILTER
-// ELEMENT_EXPR
-// ATTRIBUTE_FILTER
-// ELEMENT_EXPR ATTRIBUTE_FILTER
-MdaXPath::MdaXPathBase* MdaXPath::MdaXPathCompiler::FILTER()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
- PRECONDITION(TokenIs(MdaXPathFILTER));
-
- if (TokenIs(MdaXPathELEMENT_EXPR))
- {
- MdaXPathElement* pElementExpr = ELEMENT_EXPR();
-
- if (TokenIs(MdaXPathATTRIBUTE_FILTER))
- pElementExpr->SetQualifier(ATTRIBUTE_FILTER());
-
- return pElementExpr;
- }
-
- if (TokenIs(MdaXPathATTRIBUTE_FILTER))
- return ATTRIBUTE_FILTER();
-
- UNREACHABLE();
-}
-
-// ELEMENT
-// id
-// '*'
-// '?'
-MdaXPath::MdaXPathElement* MdaXPath::MdaXPathCompiler::ELEMENT()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
- PRECONDITION(TokenIs(MdaXPathELEMENT));
-
- MdaXPathElement* pElement = m_pXPath->m_elementFactory.Create();
-
- if (TokenIs(MdaXPathAstrix))
- pElement->Initialize();
-
- else if (TokenIs(MdaXPathIdentifier))
- pElement->Initialize(MdaSchema::GetElementType(GetIdentifier()));
-
- else if (TokenIs(MdaXPathQMark))
- {
- pElement->Initialize(++m_pXPath->m_cArgs);
- *m_pXPath->m_argTypes.Append() = XPathVarElemDeclDef;
- }
-
- else { UNREACHABLE(); }
-
- NextToken();
- return pElement;
-}
-
-// ATTRIBUTE_FILTER();
-// ATTRIBUTE
-// ATTRIBUTE '=' ''' id '''
-// ATTRIBUTE '=' '?'
-MdaXPath::MdaXPathAttribute* MdaXPath::MdaXPathCompiler::ATTRIBUTE_FILTER()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
- PRECONDITION(TokenIs(MdaXPathATTRIBUTE_FILTER));
-
- MdaXPathAttribute* pAttr = ATTRIBUTE();
-
- if (TokenIs(MdaXPathEquals))
- {
- NextToken();
-
- if (TokenIs(MdaXPathQuotedString))
- {
- NextToken();
- pAttr->SetValue(GetIdentifier());
-
- NextToken();
- ASSERT(TokenIs(MdaXPathQuotedString));
- }
- else if (TokenIs(MdaXPathQMark))
- {
- pAttr->SetValue(++m_pXPath->m_cArgs);
- *m_pXPath->m_argTypes.Append() = XPathVarAttrSString;
- }
- else { UNREACHABLE(); }
- }
-
- NextToken();
- return pAttr;
-}
-
-
-//
-// MdaXPath::Elements::Run() -- The search engine
-//
-
-BOOL MdaXPath::MdaXPathElement::Run(MdaXmlElement* pElement, MdaXPathResult* pResult)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- BOOL bAnyPass = FALSE;
- if (pResult->IsRoot())
- {
- bAnyPass |= RunOnChild(pElement, pResult);
- }
- else
- {
- SArray<MdaXmlElement*>& children = pElement->GetChildren();
-
- for (UINT32 i = 0; i < children.GetCount(); i ++)
- {
- bAnyPass |= RunOnChild(children[i], pResult);
- }
- }
-
- return bAnyPass;
-}
-
-BOOL MdaXPath::MdaXPathElement::RunOnChild(MdaXmlElement* pElement, MdaXPathResult* pResult)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- MdaElemDeclDef name = m_nameArg == NOT_VARIABLE ? m_name : pResult->GetArgs()[m_nameArg].m_u.m_elemDeclDef;
-
- if (name != MdaElemUndefined && name != pElement->GetDeclDef())
- return FALSE;
-
- if (m_pQualifier && !m_pQualifier->Run(pElement, pResult))
- return FALSE;
-
- if (m_pChild && !m_pChild->Run(pElement, pResult))
- return FALSE;
-
- if (m_bIsTarget)
- {
- ASSERT(!m_pChild);
- pResult->AddMatch(pElement);
- }
-
- return TRUE;
-}
-
-BOOL MdaXPath::MdaXPathAttribute::Run(MdaXmlElement* pElement, MdaXPathResult* pResult)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- MdaAttrDeclDef name = m_nameArg == NOT_VARIABLE ? m_name : pResult->GetArgs()[m_nameArg].m_u.m_attrDeclDef;
- SString& value = m_valueArg == NOT_VARIABLE ? m_value : *pResult->GetArgs()[m_valueArg].m_u.m_pSstr;
-
- MdaXmlAttribute* pAttr = pElement->GetAttribute(name);
- if (!pAttr)
- return FALSE;
-
- LPCWSTR szAttrValue = pAttr->GetValue();
- if (!value.IsEmpty() && *szAttrValue != W('*') && !value.Equals(szAttrValue))
- return FALSE;
-
- if (m_bIsTarget)
- pResult->AddMatch(pElement);
-
- return TRUE;
-}
-
-BOOL MdaXPath::MdaXPathLogicalOp::Run(MdaXmlElement* pParent, MdaXPathResult* pResult)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (m_andOp)
- return m_pLhs->Run(pParent, pResult) && m_pRhs->Run(pParent, pResult);
-
- return m_pLhs->Run(pParent, pResult) || m_pRhs->Run(pParent, pResult);
-}
-
-
-//
-// MdaSchema
-//
-
-MdaHashtable<MdaElemDeclDef>* MdaSchema::g_pHtElementType;
-MdaHashtable<MdaAttrDeclDef>* MdaSchema::g_pHtAttributeType;
-LPCWSTR MdaSchema::g_arElementNames[MdaElemEnd];
-LPCWSTR MdaSchema::g_arAttributeNames[MdaAttrEnd];
-MdaFactory<SString>* MdaSchema::g_pSstringFactory;
-MdaElemDeclDef MdaSchema::MdaSchemaTypeToElemDef[MdaSchema::MdaSchemaTypeEnd];
-MdaSchema::MdaSchemaMetaType MdaSchema::MdaSchemaTypeToMetaType[MdaSchema::MdaSchemaTypeEnd];
-
-LPCWSTR MdaSchema::ToLowerFirstChar(LPCWSTR name)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- return ::ToLowerFirstChar(name, g_pSstringFactory);
-}
-
-void MdaSchema::Initialize()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- g_pHtElementType = new MdaHashtable<MdaElemDeclDef>();
- g_pHtAttributeType = new MdaHashtable<MdaAttrDeclDef>();
- g_pSstringFactory = new MdaFactory<SString>();
-
- COUNT_T i = 0;
- MdaSchemaTypeToElemDef[i++] = MdaElemDef(Sequence); // MdaSchemaSequenceType
- MdaSchemaTypeToElemDef[i++] = MdaElemDef(Choice); // MdaSchemaChoiceType
- MdaSchemaTypeToElemDef[i++] = MdaElemDef(Group); // MdaSchemaGroupType
- MdaSchemaTypeToElemDef[i++] = MdaElemDef(Group); // MdaSchemaGroupRefType
- MdaSchemaTypeToElemDef[i++] = MdaElemDef(Schema); // MdaSchemaRootType
- MdaSchemaTypeToElemDef[i++] = MdaElemDef(Attribute); // MdaSchemaAttributeType
- MdaSchemaTypeToElemDef[i++] = MdaElemDef(Element); // MdaSchemaElementType
- MdaSchemaTypeToElemDef[i++] = MdaElemDef(ComplexType); // MdaSchemaComplexTypeType
- MdaSchemaTypeToElemDef[i++] = MdaElemDef(ComplexType); // MdaSchemaComplexTypeDefType
- MdaSchemaTypeToElemDef[i++] = MdaElemDef(Element); // MdaSchemaElementRefTyp
- MdaSchemaTypeToElemDef[i++] = MdaElemDef(Extension); // MdaSchemaExtensionType
- MdaSchemaTypeToElemDef[i++] = MdaElemDef(Element); // MdaSchemaElementRefTypeType
- MdaSchemaTypeToElemDef[i++] = MdaElemDef(ComplexContent); // MdaSchemaComplexContentType
- MdaSchemaTypeToElemDef[i++] = MdaElemDef(Element); // MdaSchemaElementAnyType
-
- i = 0;
- MdaSchemaTypeToMetaType[i++] = MdaSchemaMataTypePattern; // MdaSchemaSequenceType
- MdaSchemaTypeToMetaType[i++] = MdaSchemaMataTypePattern; // MdaSchemaChoiceType
- MdaSchemaTypeToMetaType[i++] = (MdaSchemaMetaType)(MdaSchemaMataTypePattern | MdaSchemaMataTypeDeclDef); // MdaSchemaGroupType
- MdaSchemaTypeToMetaType[i++] = (MdaSchemaMetaType)(MdaSchemaMataTypePattern | MdaSchemaMataTypeRef); // MdaSchemaGroupRefType
- MdaSchemaTypeToMetaType[i++] = MdaSchemaMataNone; // MdaSchemaRootType
- MdaSchemaTypeToMetaType[i++] = MdaSchemaMataNone; // MdaSchemaAttributeType
- MdaSchemaTypeToMetaType[i++] = MdaSchemaMataTypeDeclDef; // MdaSchemaElementType
- MdaSchemaTypeToMetaType[i++] = (MdaSchemaMetaType)(MdaSchemaMataNone | MdaSchemaMataMayHaveAttributes); // MdaSchemaComplexTypeType
- MdaSchemaTypeToMetaType[i++] = (MdaSchemaMetaType)(MdaSchemaMataTypeDeclDef | MdaSchemaMataMayHaveAttributes); // MdaSchemaComplexTypeDefType
- MdaSchemaTypeToMetaType[i++] = MdaSchemaMataTypeRef; // MdaSchemaElementRefTyp
- MdaSchemaTypeToMetaType[i++] = (MdaSchemaMetaType)(MdaSchemaMataTypeRef | MdaSchemaMataMayHaveAttributes); // MdaSchemaExtensionType
- MdaSchemaTypeToMetaType[i++] = (MdaSchemaMetaType)(MdaSchemaMataTypeDeclDef | MdaSchemaMataTypeRef); // MdaSchemaElementRefTypeType
- MdaSchemaTypeToMetaType[i++] = MdaSchemaMataNone; // MdaSchemaComplexContentType
- MdaSchemaTypeToMetaType[i++] = MdaSchemaMataTypeDeclDef; // MdaSchemaElementAnyType
-
- i = 0;
-#define MDA_MAP_ASSISTANT_DEFINITION_TO_NAME
-#include "mdaschema.inl"
-#undef MDA_MAP_ASSISTANT_DEFINITION_TO_NAME
- g_arElementNames[i++] = NULL;
-#define MDA_MAP_ELEMENT_DEFINITION_TO_NAME
-#include "mdaschema.inl"
-#undef MDA_MAP_ELEMENT_DEFINITION_TO_NAME
- g_arElementNames[i++] = NULL;
-#define MDA_MAP_ELEMENT_DECLARATION_TO_NAME
-#include "mdaschema.inl"
-#undef MDA_MAP_ELEMENT_DECLARATION_TO_NAME
- g_arElementNames[i++] = NULL; // Max
- g_arElementNames[i++] = W("!--"); // Comment
- g_arElementNames[i++] = NULL; // Undefined
-
- i = 0;
-#define MDA_MAP_ATTRIBUTE_DECLARATION_TO_NAME
-#include "mdaschema.inl"
-#undef MDA_MAP_ATTRIBUTE_DECLARATION_TO_NAME
-
-#define MDA_MAP_ASSISTANT_NAME_TO_DEFINITION
-#include "mdaschema.inl"
-#undef MDA_MAP_ASSISTANT_NAME_TO_DEFINITION
-
-#define MDA_MAP_ELEMENT_NAME_TO_DEFINITION
-#include "mdaschema.inl"
-#undef MDA_MAP_ELEMENT_NAME_TO_DEFINITION
-
-#define MDA_MAP_ELEMENT_NAME_TO_DECLARATION
-#include "mdaschema.inl"
-#undef MDA_MAP_ELEMENT_NAME_TO_DECLARATION
-
-#define MDA_MAP_ATTRIBUTE_NAME_TO_DECLARATION
-#include "mdaschema.inl"
-#undef MDA_MAP_ATTRIBUTE_NAME_TO_DECLARATION
-}
-
-MdaElemDeclDef MdaSchema::GetElementType(LPCWSTR name, BOOL bAssertDefined)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- MdaElemDeclDef type;
-
- if (!g_pHtElementType->Get(name, &type))
- {
- ASSERT(!bAssertDefined);
- return MdaElemUndefined;
- }
-
- return type;
-}
-
-LPCWSTR MdaSchema::GetElementName(MdaElemDeclDef type)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- PRECONDITION(type >= 0 && type < MdaElemUndefined);
- return g_arElementNames[type];
-}
-
-MdaAttrDeclDef MdaSchema::GetAttributeType(LPCWSTR name, BOOL bAssertDefined)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- MdaAttrDeclDef type;
-
- if (!g_pHtAttributeType->Get(name, &type))
- {
- ASSERT(!bAssertDefined);
- return MdaAttrUndefined;
- }
-
- return type;
-}
-
-LPCWSTR MdaSchema::GetAttributeName(MdaAttrDeclDef type)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- return g_arAttributeNames[type];
-}
-
-// TODO: Validation error reporting needs work
-MdaSchema::ValidationResult* MdaSchema::Validate(MdaXmlElement* pRoot, ValidationResult* pResult)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- pResult->Initialize(this, pRoot);
-
- MdaSchemaBase* pXsd = *GetDef(pRoot->GetDeclDef());
- ASSERT((CheckPointer(pXsd) || (pRoot->GetDeclDef() > MdaElemDecl(Max))) && W("You likley did not include a MDA_DEFINE_OUTPUT section in your schema!"));
-
- BOOL bValidationSucceeded = pXsd ? pXsd->Validate(pRoot, pResult) : FALSE;
-
- if (bValidationSucceeded)
- pResult->ResetResult();
- else
- pResult->SetError();
-
- ASSERT(pResult->ValidationFailed() == !bValidationSucceeded);
- return pResult;
-}
-
-MdaSchema::MdaSchema()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- for(COUNT_T i = 0; i < MdaElemEnd; i ++)
- m_definitions[i] = NULL;
-}
-
-
-//
-// MdaAssistantSchema
-//
-
-MdaAssistantSchema::MdaAssistantSchema()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
-#define MDA_DEFINE_ASSISTANT_SCHEMA
-#include "mdaschema.inl"
-#undef MDA_DEFINE_ASSISTANT_SCHEMA
-
-#define MDA_DEFINE_MDA_ASSISTANT_CONFIG_GROUP
-#include "mdaschema.inl"
-#undef MDA_DEFINE_MDA_ASSISTANT_CONFIG_GROUP
-}
-
-LPCWSTR MdaAssistantSchema::SetRootAttributes(MdaXmlElement* pXml)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- //pXml->AddAttribute(W("xmlns:") MDA_SCHEMA_PREFIX, MDA_TARGET_NAMESPACE);
- //pXml->AddAttribute(W("xmlns:xsi"), W("http://www.w3.org/2001/XMLSchema-instance"));
- return MDA_SCHEMA_PREFIX;
-}
-
-
-//
-// MdaAssistantMsgSchema
-//
-
-MdaAssistantMsgSchema::MdaAssistantMsgSchema()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
-#define MDA_DEFINE_ASSISTANT_MSG_SCHEMA
-#include "mdaschema.inl"
-#undef MDA_DEFINE_ASSISTANT_MSG_SCHEMA
-
-#define MDA_DEFINE_MDA_ASSISTANT_MSG_GROUP
-#include "mdaschema.inl"
-#undef MDA_DEFINE_MDA_ASSISTANT_MSG_GROUP
-}
-
-LPCWSTR MdaAssistantMsgSchema::SetRootAttributes(MdaXmlElement* pXml)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- //pXml->AddAttribute(W("xmlns:") MDA_SCHEMA_PREFIX, MDA_TARGET_NAMESPACE);
- //pXml->AddAttribute(W("xmlns:xsi"), W("http://www.w3.org/2001/XMLSchema-instance"));
- return MDA_SCHEMA_PREFIX;
-}
-
-
-//
-// MdaSchemaSchema
-//
-
-MdaSchemaSchema::MdaSchemaSchema()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
-#define MDA_DEFINE_SCHEMA_SCHEMA
-#include "mdaschema.inl"
-#undef MDA_DEFINE_SCHEMA_SCHEMA
-}
-
-LPCWSTR MdaSchemaSchema::SetRootAttributes(MdaXmlElement* pXml)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- pXml->AddAttributeSz(MdaAttrDecl(TargetNamespace), MDA_TARGET_NAMESPACE);
- pXml->AddAttributeSz(MdaAttrDecl(Xmlns), W("http://www.w3.org/2001/XMLSchema"))->SetNs(W("xs"));
- pXml->AddAttributeSz(MdaAttrDecl(Xmlns), MDA_TARGET_NAMESPACE);
- return W("xs");
-}
-
-
-//
-// MdaSchema::MdaSchemaXXX
-//
-MdaXmlElement* MdaSchema::MdaSchemaBase::ToXml(MdaXmlIndustry* pMdaXmlIndustry, MdaSchemaBase* pViolation)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- return ToXml(pMdaXmlIndustry->CreateElement(), pViolation);
-}
-
-MdaXmlElement* MdaSchema::MdaSchemaBase::ToXml(MdaXmlElement* pXmlRoot, MdaSchemaBase* pViolation)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- LPCWSTR debugName = GetName();
-
- MdaXmlElement* pXml = pXmlRoot->AddChild(GetSchemaDeclDef());
- SetAttributes(pXml);
-
-// if (this == pViolation)
-// pXml->AddAttributeSz(MdaAttrDecl(Violated), W("---- THIS XSD ELEMENT VIOLATED -----"));
-
- if (m_children.GetCount() == 1 &&
- m_children[0]->GetSchemaDeclDef() == MdaElemDef(ComplexType) &&
- m_children[0]->m_children.GetCount() == 0 &&
- (!MayHaveAttr(m_children[0]) ||
- m_children[0]->GetAttributes().GetCount() == 0))
- {
- // Convert <Element><ComplexType/><Element> to <Element/>
- return pXml;
- }
-
- for(COUNT_T i = 0; i < m_children.GetCount(); i ++)
- {
- debugName = m_children[i]->GetName();
- m_children[i]->ToXml(pXml, pViolation);
- }
-
- if (MayHaveAttr(this))
- {
- SArray<MdaSchemaAttribute*>& attributes = GetAttributes();
- for(COUNT_T j = 0; j < attributes.GetCount(); j ++)
- {
- debugName = attributes[j]->GetName();
- attributes[j]->ToXml(pXml, pViolation);
- }
- }
-
- return pXml;
-}
-
-
-void MdaSchema::MdaSchemaBase::AddChild(MdaSchemaBase* pElement)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (pElement->GetSchemaDeclDef() == MdaElemDef(Attribute))
- *GetAttributes().Append() = (MdaSchemaAttribute*)pElement;
- else
- *m_children.Append() = pElement;
-}
-
-//
-// Validation
-//
-
-#define CpdXsdIfFailGo(EXPR) do { if (!(EXPR)) { goto Fail; } } while (0)
-#define CpdXsdTest(EXPR) do { if (!(EXPR)) { pResult->SetError(this, pElement); goto Fail; } } while (0)
-#define MDA_XSD_VERIFY_OK return TRUE;
-#define MDA_XSD_VERIFY_FAIL Fail: return FALSE;
-
-BOOL MdaSchema::MdaSchemaElement::Validate(MdaXmlElement* pElement, ValidationResult* pResult)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- StackSString buffer;
- LPCWSTR debug = pElement->DebugToString(&buffer);
-
- CpdXsdTest(pElement->GetDeclDef() == GetDeclDef());
-
- for(COUNT_T i = 0; i < m_children.GetCount(); i++)
- CpdXsdIfFailGo(m_children[i]->Validate(pElement, pResult));
-
- MDA_XSD_VERIFY_OK;
- MDA_XSD_VERIFY_FAIL;
-}
-
-BOOL MdaSchema::MdaSchemaSequence::ValidatePattern(MdaXmlElement* pElement, ValidationResult* pResult, COUNT_T* pCount)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- StackSString buffer;
- LPCWSTR debug = pElement->DebugToString(&buffer);
-
- COUNT_T cPeriod = m_children.GetCount();
- COUNT_T cChildren = pElement->GetChildren().GetCount();
- COUNT_T cCurrent = *pCount;
- COUNT_T cCount = cCurrent;
- COUNT_T cMatches = 0;
-
- if (cPeriod == 0)
- return TRUE;
-
- while(cCurrent <= cChildren)
- {
- MdaSchemaBase* pXsd = m_children[cMatches % cPeriod];
- if (pXsd->GetSchemaDeclDef() == MdaElemDef(Element))
- {
- if (cCurrent == cChildren)
- break;
-
- if (!pXsd->Validate(pElement->GetChildren()[cCurrent], pResult))
- break;
-
- cCurrent++;
- }
- else
- {
- ASSERT(IsPattern(pXsd));
- if (!pXsd->ValidatePattern(pElement, pResult, &cCurrent))
- break;
- }
-
- cMatches++;
-
- // One period matched
- if (cMatches % cPeriod == 0)
- cCount = cCurrent;
-
- // Maximum periods matcheds
- if (cMatches / cPeriod == m_max)
- break;
- }
-
- // Test if the minumum number periods have been matched
- if (cMatches / cPeriod < m_min)
- return FALSE;
-
- // Update the position past the matched elements
- *pCount = cCount;
-
- return TRUE;
-}
-
-BOOL MdaSchema::MdaSchemaChoice::ValidatePattern(MdaXmlElement* pElement, ValidationResult* pResult, COUNT_T* pCount)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- StackSString buffer;
- LPCWSTR debug = pElement->DebugToString(&buffer);
-
- BOOL bFound = FALSE;
- COUNT_T cCurrent = *pCount;
- COUNT_T cChildren = pElement->GetChildren().GetCount();
-
- for(COUNT_T cXsd = 0; cXsd < m_children.GetCount(); cXsd++)
- {
- MdaSchemaBase* pXsd = m_children[cXsd];
-
- if (IsPattern(pXsd))
- {
- COUNT_T cOldCurrent = cCurrent;
- if (pXsd->ValidatePattern(pElement, pResult, &cCurrent))
- {
- // "Empty matches" only allowed in choice pattern if there are no children to match
- if (cOldCurrent != cCurrent || cChildren == 0)
- {
- bFound = TRUE;
- break;
- }
- }
- }
- else
- {
- if (cCurrent == cChildren)
- break;
-
- if (pXsd->Validate(pElement->GetChildren()[cCurrent], pResult))
- {
- cCurrent++;
- bFound = TRUE;
- break;
- }
- }
- }
-
- CpdXsdIfFailGo(bFound);
-
- *pCount = cCurrent;
-
- MDA_XSD_VERIFY_OK;
- MDA_XSD_VERIFY_FAIL;
-}
-
-#define this pThis
-BOOL MdaSchema::Validate(MdaSchemaAttribute* pThis, MdaXmlElement* pElement, ValidationResult* pResult)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- StackSString sszValue;
- MdaXmlAttribute* pAttr = (MdaXmlAttribute*)pElement->GetAttribute(pThis->m_declDef);
-
- if (!pAttr && !pThis->m_szDefault.IsEmpty())
- {
- pAttr = pElement->AddDefaultAttribute(pThis->m_declDef, pThis->m_szDefault.GetUnicode());
- }
-
- if (!pAttr)
- {
- CpdXsdTest(!pThis->m_bRequired);
- return TRUE;
- }
-
-#ifdef _DEBUG
- // Only necessary for validation of assistant output
- if (pAttr->m_type != MdaSchemaPrimitiveUnknown)
- {
- CpdXsdTest(pAttr->m_type == pThis->m_type);
- return TRUE;
- }
-#endif
-
- LPCWSTR szValue = pAttr->GetValue();
- sszValue.Set(szValue);
-
- if (pThis->m_type == MdaSchemaPrimitiveSString)
- {
- /* accept all strings? */
- }
- else if (pThis->m_type == MdaSchemaPrimitiveINT32)
- {
- CpdXsdTest(!sszValue.IsEmpty() && sszValue.GetCount() != 0);
-
- for (COUNT_T i = 0; i < sszValue.GetCount(); i ++)
- {
- if (i == 0 && *szValue == W('-') && sszValue.GetCount() > 1)
- continue;
-
- CpdXsdTest(IS_DIGIT(szValue[i]));
- }
-
- pAttr->SetINT32(_wtoi(szValue));
- }
- else if (pThis->m_type == MdaSchemaPrimitiveBOOL)
- {
- CpdXsdTest(!sszValue.IsEmpty() && sszValue.GetCount() != 0);
-
- if (sszValue.Equals(W("true")))
- pAttr->SetBOOL(true);
- else if (sszValue.Equals(W("false")))
- pAttr->SetBOOL(false);
- else
- CpdXsdTest(FALSE);
- }
-
- MDA_XSD_VERIFY_OK;
- MDA_XSD_VERIFY_FAIL;
-}
-#undef this
-
-BOOL MdaSchema::MdaSchemaBase::Validate(MdaXmlElement* pElement, ValidationResult* pResult)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- COUNT_T count = 0;
-
- CpdXsdTest(ValidatePattern(pElement, pResult, &count));
-
- CpdXsdTest(count == pElement->GetChildren().GetCount());
-
- MDA_XSD_VERIFY_OK;
- MDA_XSD_VERIFY_FAIL;
-}
-
-BOOL MdaSchema::MdaSchemaRoot::Validate(MdaXmlElement* pElement, ValidationResult* pResult)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- for(COUNT_T i = 0; i < m_children.GetCount(); i++)
- CpdXsdIfFailGo(m_children[i]->Validate(pElement, pResult));
-
- MDA_XSD_VERIFY_OK;
- MDA_XSD_VERIFY_FAIL;
-}
-
-BOOL MdaSchema::MdaSchemaComplexType::Validate(MdaXmlElement* pElement, ValidationResult* pResult)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- for(COUNT_T i = 0; i < m_children.GetCount(); i++)
- CpdXsdIfFailGo(m_children[i]->Validate(pElement, pResult));
-
- for(COUNT_T i = 0; i < m_attributes.GetCount(); i++)
- CpdXsdIfFailGo(m_attributes[i]->Validate(pElement, pResult));
-
- MDA_XSD_VERIFY_OK;
- MDA_XSD_VERIFY_FAIL;
-}
-
-BOOL MdaSchema::MdaSchemaComplexTypeDef::Validate(MdaXmlElement* pElement, ValidationResult* pResult)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- for(COUNT_T i = 0; i < m_children.GetCount(); i++)
- CpdXsdIfFailGo(m_children[i]->Validate(pElement, pResult));
-
- for(COUNT_T i = 0; i < m_attributes.GetCount(); i++)
- CpdXsdIfFailGo(m_attributes[i]->Validate(pElement, pResult));
-
- MDA_XSD_VERIFY_OK;
- MDA_XSD_VERIFY_FAIL;
-}
-
-BOOL MdaSchema::MdaSchemaComplexContent::Validate(MdaXmlElement* pElement, ValidationResult* pResult)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- for(COUNT_T i = 0; i < m_children.GetCount(); i++)
- CpdXsdIfFailGo(m_children[i]->Validate(pElement, pResult));
-
- MDA_XSD_VERIFY_OK;
- MDA_XSD_VERIFY_FAIL;
-}
-
-BOOL MdaSchema::MdaSchemaGroup::ValidatePattern(MdaXmlElement* pElement, ValidationResult* pResult, COUNT_T* pCount)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- for(COUNT_T i = 0; i < m_children.GetCount(); i++)
- {
- ASSERT(IsPattern(m_children[i]));
- CpdXsdIfFailGo(m_children[i]->ValidatePattern(pElement, pResult, pCount));
- }
-
- MDA_XSD_VERIFY_OK;
- MDA_XSD_VERIFY_FAIL;
-}
-
-BOOL MdaSchema::MdaSchemaGroupRef::ValidatePattern(MdaXmlElement* pElement, ValidationResult* pResult, COUNT_T* pCount)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- MdaSchemaBase* pReference = GetRef();
- LPCWSTR debug = GetRefName();
- ASSERT(IsPattern(this));
- return pReference->ValidatePattern(pElement, pResult, pCount);
-}
-
-BOOL MdaSchema::MdaSchemaExtension::Validate(MdaXmlElement* pElement, ValidationResult* pResult)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- ASSERT(GetRef()->GetSchemaType() == MdaSchemaComplexTypeDefType);
- MdaSchemaComplexTypeDef* pReference = (MdaSchemaComplexTypeDef*)GetRef();
-
- MdaSchemaSequence sequence;
- sequence.Initialize(1, 1);
-
- MdaSchemaBase* pXsd = pReference;
- while(true)
- {
- if (MayHaveAttr(pXsd))
- {
- for(COUNT_T i = 0; i < pXsd->GetAttributes().GetCount(); i++)
- CpdXsdIfFailGo(pXsd->GetAttributes()[i]->Validate(pElement, pResult));
- }
-
- if (pXsd->GetSchemaType() == MdaSchemaExtensionType)
- {
- pXsd = ((MdaSchemaComplexTypeDef*)pXsd)->GetRef();
- continue;
- }
-
- if (pXsd->m_children.GetCount() == 0)
- break;
-
- pXsd = pXsd->m_children[0];
-
- if (IsPattern(pXsd))
- {
- sequence.AddChild(pXsd);
- break;
- }
- }
-
- if (m_children.GetCount() == 1)
- {
- ASSERT(IsPattern(m_children[0]));
- sequence.AddChild(m_children[0]);
- }
-
- CpdXsdIfFailGo(sequence.Validate(pElement, pResult));
-
- for(COUNT_T i = 0; i < m_attributes.GetCount(); i++)
- CpdXsdIfFailGo(m_attributes[i]->Validate(pElement, pResult));
-
- MDA_XSD_VERIFY_OK;
- MDA_XSD_VERIFY_FAIL;
-}
-
-BOOL MdaSchema::MdaSchemaElementRefType::Validate(MdaXmlElement* pElement, ValidationResult* pResult)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- CpdXsdIfFailGo(GetRef()->Validate(pElement, pResult));
-
- MDA_XSD_VERIFY_OK;
- MDA_XSD_VERIFY_FAIL;
-}
-
-BOOL MdaSchema::MdaSchemaElementAny::Validate(MdaXmlElement* pElement, ValidationResult* pResult)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- StackSString buffer;
- LPCWSTR debug = pElement->DebugToString(&buffer);
-
- CpdXsdTest(pElement->GetDeclDef() == GetDeclDef());
-
- MDA_XSD_VERIFY_OK;
- MDA_XSD_VERIFY_FAIL;
-}
-
-BOOL MdaSchema::MdaSchemaElementRef::Validate(MdaXmlElement* pElement, ValidationResult* pResult)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- LPCWSTR debug = GetRefName();
- CpdXsdIfFailGo(GetRef()->Validate(pElement, pResult));
-
- MDA_XSD_VERIFY_OK;
- MDA_XSD_VERIFY_FAIL;
-}
-
-
-//
-// MdaSchema::XXX::SetAttributes()
-//
-
-void MdaSchema::MdaSchemaSequence::SetAttributes(MdaXmlElement* pXml)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- SmallStackSString ssBound;
-
- ssBound.Printf(W("%d"), m_min);
- pXml->AddAttributeSz(MdaAttrDecl(MinOccurs), ssBound.GetUnicode());
-
- if (m_max == -1)
- {
- pXml->AddAttributeSz(MdaAttrDecl(MaxOccurs), W("unbounded"));
- }
- else
- {
- ssBound.Printf(W("%d"), m_max);
- pXml->AddAttributeSz(MdaAttrDecl(MaxOccurs), ssBound.GetUnicode());
- }
-}
-
-void MdaSchema::MdaSchemaAttribute::SetAttributes(MdaXmlElement* pXml)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- pXml->AddAttributeSz(MdaAttrDecl(Name), GetAttributeName(m_declDef));
-
- LPCWSTR szType = NULL;
- if (m_type == MdaSchemaPrimitiveBOOL)
- szType = W("xs:boolean");
- else if (m_type == MdaSchemaPrimitiveINT32)
- szType = W("xs:int");
- else if (m_type == MdaSchemaPrimitiveSString)
- szType = W("xs:string");
- else { UNREACHABLE(); }
-
- pXml->AddAttributeSz(MdaAttrDecl(Type), szType);
- pXml->AddAttributeSz(MdaAttrDecl(Use), m_bRequired ? W("required") : W("optional"));
-
- if (!m_szDefault.IsEmpty())
- pXml->AddAttributeSz(MdaAttrDecl(Default), m_szDefault);
-}
-
-void MdaSchema::MdaSchemaDeclDefRef::SetAttributes(MdaXmlElement* pXml)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- LPCWSTR szDeclDef = NULL;
- LPCWSTR szRef = NULL;
-
- if (IsDeclDef(this))
- szDeclDef = GetDeclDefName();
-
- if (IsRef(this))
- szRef = GetRefName();
-
- switch (GetSchemaType())
- {
- case MdaSchemaGroupRefType:
- case MdaSchemaElementRefTyp:
- pXml->AddAttributeSz(MdaAttrDecl(Ref), szRef);
- break;
-
- case MdaSchemaExtensionType:
- pXml->AddAttributeSz(MdaAttrDecl(Base), szRef);
- break;
-
- case MdaSchemaElementRefTypeType:
- pXml->AddAttributeSz(MdaAttrDecl(Name), szDeclDef);
- pXml->AddAttributeSz(MdaAttrDecl(Type), szRef);
- break;
-
- case MdaSchemaElementAnyType:
- pXml->AddAttributeSz(MdaAttrDecl(Name), szDeclDef);
- pXml->AddAttributeSz(MdaAttrDecl(Type), W("xs:anyType"));
- break;
-
- case MdaSchemaGroupType:
- case MdaSchemaElementType:
- case MdaSchemaComplexTypeDefType:
- pXml->AddAttributeSz(MdaAttrDecl(Name), szDeclDef);
- break;
-
- default:
- UNREACHABLE();
- }
-}
-
-//
-// MdaAssistant
-//
-void MdaAssistant::Initialize(MdaXmlElement* pXmlInput)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (pXmlInput->GetAttribute(MdaAttrDecl(SuppressDialog)))
- m_bSuppressDialog = !!pXmlInput->GetAttributeValueAsBool(MdaAttrDecl(SuppressDialog));
-}
-
-LPCWSTR MdaAssistant::GetName()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- return MdaSchema::GetElementName(m_assistantDeclDef);
-}
-
-MdaXmlElement* MdaAssistant::GetRootElement(MdaXmlElement* pRoot, BOOL bBreak)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- MdaXmlElement* pXmlAssistant = pRoot->AddChild(GetAssistantMsgDeclDef());
-
- if (bBreak)
- pXmlAssistant->AddAttributeSz(MdaAttrDecl(Break), W("true"));
-
- return pXmlAssistant;
-}
-
-BOOL MdaAssistant::IsAssistantActive(MdaXmlElement* pXml)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- return TRUE;
-}
-
-MdaXmlElement* MdaAssistant::OutputThread(Thread* pThread, MdaXmlElement* pXml)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- _ASSERTE(pThread);
- pXml->AddAttributeInt(MdaAttrDecl(OsId), pThread->GetOSThreadId());
- pXml->AddAttributeInt(MdaAttrDecl(ManagedId), pThread->GetThreadId());
-
- return pXml;
-}
-
-MdaXmlElement* MdaAssistant::OutputMethodTable(MethodTable* pMT, MdaXmlElement* pXml)
-{
- CONTRACT (MdaXmlElement*)
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(pMT));
- PRECONDITION(CheckPointer(pXml));
- POSTCONDITION(CheckPointer(RETVAL));
- }
- CONTRACT_END;
-
- static WCHAR szTemplateMsg[] = {W("Failed to QI for interface %s because it does not have a COM proxy stub registered.")};
-
- DefineFullyQualifiedNameForClassWOnStack();
- pXml->AddAttributeSz(MdaAttrDecl(Name), GetFullyQualifiedNameForClassW(pMT));
-
- RETURN pXml;
-}
-
-void MdaAssistant::ToString(TypeHandle typeHandle, SString* psszFullname, SString* psszNamespace)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- StackSString ssz;;
-
- psszFullname->Clear();
-
- LPCSTR szDeclTypeName, szNamespace;
- InlineSArray<mdTypeDef, 32> nesting;
-
- mdTypeDef tkTypeDef = typeHandle.GetCl();
- Module* pModule = typeHandle.GetModule();
- IMDInternalImport* pImport = pModule->GetMDImport();
-
- // Get tkTypeDef tokens for declaring type and its nested classes
- nesting.Append(tkTypeDef);
- while (S_OK == pImport->GetNestedClassProps(tkTypeDef, &tkTypeDef))
- nesting.Append(tkTypeDef);
-
- // Append the namespace
- COUNT_T i = nesting.GetCount() - 1;
- if (FAILED(pImport->GetNameOfTypeDef(nesting[i], &szDeclTypeName, &szNamespace)))
- {
- szNamespace = NULL;
- szDeclTypeName = NULL;
- }
- if (szNamespace && *szNamespace != W('\0'))
- {
- if (psszNamespace)
- psszNamespace->SetUTF8(szNamespace);
-
- psszFullname->SetUTF8(szNamespace);
- psszFullname->Append(W("."));
- }
-
- // Append the nested classes
- for(; i > 0; i --)
- {
- IfFailThrow(pImport->GetNameOfTypeDef(nesting[i], &szDeclTypeName, &szNamespace));
- ssz.SetUTF8(szDeclTypeName);
- psszFullname->Append(ssz);
- psszFullname->Append(W("+"));
- }
-
- // Append the declaring type name
- IfFailThrow(pImport->GetNameOfTypeDef(nesting[i], &szDeclTypeName, &szNamespace));
- ssz.SetUTF8(szDeclTypeName);
- psszFullname->Append(ssz);
-}
-
-SString& MdaAssistant::ToString(SString& sszBuffer, Module* pModule)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- sszBuffer.AppendUTF8(pModule->GetSimpleName());
- return sszBuffer;
-}
-
-SString& MdaAssistant::ToString(SString& sszBuffer, TypeHandle typeHandle)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- StackSString sszScratch;
- ToString(sszBuffer, typeHandle.GetModule()).GetUnicode();
- sszBuffer.Append(W("!"));
- ToString(typeHandle, &sszScratch, NULL);
- sszBuffer.Append(sszScratch);
- return sszBuffer;
-}
-
-SString& MdaAssistant::ToString(SString& sszBuffer, MethodDesc* pMethodDesc)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- ToString(sszBuffer, pMethodDesc->GetMethodTable()).GetUnicode();
- sszBuffer.Append(W("::"));
- StackSString ssz;
- ssz.SetUTF8(pMethodDesc->GetName());
- sszBuffer.Append(ssz);
- return sszBuffer;
-}
-
-SString& MdaAssistant::ToString(SString& sszBuffer, FieldDesc* pFieldDesc)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- ToString(sszBuffer, pFieldDesc->GetEnclosingMethodTable()).GetUnicode();
- sszBuffer.Append(W("::"));
- StackSString ssz;
- ssz.SetUTF8(pFieldDesc->GetName());
- sszBuffer.Append(ssz);
- return sszBuffer;
-}
-
-MdaXmlElement* MdaAssistant::OutputParameter(SString parameterName, USHORT sequence, MethodDesc* pMethodDesc, MdaXmlElement* pXml)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- TypeHandle declType(pMethodDesc->GetMethodTable());
- Module* pDeclModule = declType.GetModule();
-
- pXml->AddAttributeSz(MdaAttrDecl(Name), parameterName);
- pXml->AddAttributeInt(MdaAttrDecl(Index), sequence);
-
- OutputMethodDesc(pMethodDesc, pXml->AddChild(MdaElemDecl(DeclaringMethod)));
-
- return pXml;
-}
-
-MdaXmlElement* MdaAssistant::OutputMethodDesc(MethodDesc* pMethodDesc, MdaXmlElement* pXml)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- TypeHandle declType(pMethodDesc->GetMethodTable());
- Module* pDeclModule = declType.GetModule();
-
- StackSString sszMethod;
-
- pXml->AddAttributeSz(MdaAttrDecl(Name), ToString(sszMethod, pMethodDesc).GetUnicode());
-
- return pXml;
-}
-
-MdaXmlElement* MdaAssistant::OutputFieldDesc(FieldDesc* pFieldDesc, MdaXmlElement* pXml)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- StackSString sszField;
-
- pXml->AddAttributeSz(MdaAttrDecl(Name), ToString(sszField, pFieldDesc).GetUnicode());
-
- return pXml;
-}
-
-MdaXmlElement* MdaAssistant::OutputTypeHandle(TypeHandle typeHandle, MdaXmlElement* pXml)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- StackSString sszTypeName;
-
- // Set Attribute
- pXml->AddAttributeSz(MdaAttrDecl(Name), ToString(sszTypeName, typeHandle.GetMethodTable()).GetUnicode());
-
- return pXml;
-}
-
-MdaXmlElement* MdaAssistant::OutputModule(Module* pModule, MdaXmlElement* pXml)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- pXml->AddAttributeSz(MdaAttrDecl(Name), pModule->GetSimpleName());
-
- return pXml;
-}
-
-MdaXmlElement* MdaAssistant::OutputCallsite(MethodDesc *pMethodDesc, DWORD dwOffset, MdaXmlElement* pXml)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- StackSString sszMethod;
- pXml->AddAttributeSz(MdaAttrDecl(Name), ToString(sszMethod, pMethodDesc).GetUnicode());
-
- StackSString sszOffset;
- sszOffset.Printf(W("0x%04X"), dwOffset);
- pXml->AddAttributeSz(MdaAttrDecl(Offset), sszOffset.GetUnicode());
-
- return pXml;
-}
-
-MdaXmlElement* MdaAssistant::OutputException(OBJECTREF *pExceptionObj, MdaXmlElement* pXml)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- OutputTypeHandle((*pExceptionObj)->GetTypeHandle(), pXml->AddChild(MdaElemDecl(Type)));
-
- StackSString message;
- GetExceptionMessage(*pExceptionObj, message);
-
- pXml->AddAttributeSz(MdaAttrDecl(Message), message);
-
- return pXml;
-}
-
-//
-// MdaQuery::CompiledQueries
-//
-BOOL MdaQuery::CompiledQueries::Test(MethodDesc* pMethodDesc)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- for (COUNT_T i = 0; i < m_queries.GetCount(); i ++)
- {
- if (m_queries[i]->Test(pMethodDesc))
- return TRUE;
- }
-
- return FALSE;
-}
-
-BOOL MdaQuery::CompiledQueries::Test(FieldDesc* pFieldDesc)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- for (COUNT_T i = 0; i < m_queries.GetCount(); i ++)
- {
- if (m_queries[i]->Test(pFieldDesc))
- return TRUE;
- }
-
- return FALSE;
-}
-
-BOOL MdaQuery::CompiledQueries::Test(MethodTable* pMethodTable)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- for (COUNT_T i = 0; i < m_queries.GetCount(); i ++)
- {
- if (m_queries[i]->Test(pMethodTable))
- return TRUE;
- }
-
- return FALSE;
-}
-
-MdaQuery::CompiledQuery* MdaQuery::CompiledQueries::AddQuery()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- CompiledQuery* pQuery = m_factory.Create();
- m_queries.Append(pQuery);
- return pQuery;
-}
-
-
-//
-// MdaQuery::CompiledQuery
-//
-void MdaQuery::Compile(MdaXmlElement* pXmlFilters, CompiledQueries* pCompiledQueries)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- SArray<MdaXmlElement*>& children = pXmlFilters->GetChildren();
- BOOL bJmc = pXmlFilters->GetAttribute(MdaAttrDecl(JustMyCode))->GetValueAsBool();
-
- for (COUNT_T i = 0; i < children.GetCount(); i ++)
- {
- MdaXmlElement* pXmlFilter = children[i];
- SString* psszName = pXmlFilter->GetAttribute(MdaAttrDecl(Name))->GetValueAsCSString();
- MdaXmlAttribute* pJmcOptAttr = pXmlFilter->GetAttribute(MdaAttrDecl(JustMyCode));
- if (pJmcOptAttr)
- bJmc = pJmcOptAttr->GetValueAsBool();
- Compiler compiler;
- CompiledQuery* pQuery = pCompiledQueries->AddQuery();
- compiler.Compile(psszName, pQuery);
- if (bJmc)
- pQuery->SetJustMyCode();
- }
-}
-
-MdaQuery::CompiledQuery::CompiledQuery()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- m_bJustMyCode = FALSE;
- m_bAnyMember = FALSE;
- m_bAnyType = FALSE;
- m_sszFullname.Clear();
- m_sszMember.Clear();
-}
-
-BOOL StartsWith(SString* psszString, SString* psszSubstring)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- StackSString sszString(*psszString);
- if (psszString->GetCount() < psszSubstring->GetCount())
- return FALSE;
- sszString.Truncate(sszString.Begin() + psszSubstring->GetCount());
- return sszString.Equals(*psszSubstring);
-}
-
-BOOL MdaQuery::CompiledQuery::Test(MethodDesc* pMethodDesc)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- StackSString sszName(SString::Utf8, pMethodDesc->GetName());
-
- if (pMethodDesc->IsLCGMethod() || pMethodDesc->IsILStub())
- return FALSE;
-
- if (!Test(&sszName, pMethodDesc->GetMethodTable()))
- return FALSE;
-
- if (!m_bJustMyCode)
- return TRUE;
-
- if (IsJustMyCode(pMethodDesc))
- return TRUE;
-
- return FALSE;
-}
-
-BOOL MdaQuery::CompiledQuery::Test(FieldDesc* pFieldDesc)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- StackSString sszName(SString::Utf8, pFieldDesc->GetName());
- if (!Test(&sszName, pFieldDesc->GetApproxEnclosingMethodTable()))
- return FALSE;
-
- if (!m_bJustMyCode)
- return TRUE;
-
- return TRUE;
-}
-
-BOOL MdaQuery::CompiledQuery::Test(SString* psszName, MethodTable* pMethodTable)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (!m_sszMember.IsEmpty())
- {
- if (!m_sszMember.Equals(*psszName))
- return FALSE;
-
- if (m_sszMember.GetCount() == m_sszFullname.GetCount())
- return TRUE;
- }
- else if (!m_bAnyMember)
- return FALSE;
-
- return Test(pMethodTable);
-}
-
-BOOL MdaQuery::CompiledQuery::Test(MethodTable* pMethodTable)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (!pMethodTable)
- return FALSE;
-
- if (m_sszFullname.IsEmpty())
- return TRUE;
-
- StackSString sszNamespace, sszFullName;
- MdaAssistant::ToString(pMethodTable, &sszFullName, &sszNamespace);
-
- if (m_bAnyType && StartsWith(&m_sszFullname, &sszNamespace))
- return TRUE;
-
- if (m_bAnyMember && StartsWith(&m_sszFullname, &sszFullName))
- return TRUE;
-
- return m_sszFullname.Equals(sszFullName);
-}
-
-void MdaQuery::CompiledQuery::SetName(LPCWSTR name)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (!m_sszFullname.IsEmpty())
- {
- m_sszFullname.Append(W("."));
- m_sszMember.Clear();
- }
- else
- {
- m_sszMember.Set(name);
- }
-
- m_sszFullname.Append(name);
-
-}
-
-void MdaQuery::CompiledQuery::SetNestedTypeName(LPCWSTR name)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- m_sszMember.Clear();
-
- if (!m_sszFullname.IsEmpty())
- m_sszFullname.Append(W("+"));
-
- m_sszFullname.Append(name);
-}
-
-void MdaQuery::CompiledQuery::SetAnyMember()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- m_bAnyMember = TRUE;
- m_sszMember.Clear();
-}
-
-void MdaQuery::CompiledQuery::SetAnyType()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- m_bAnyType = TRUE;
- m_sszMember.Clear();
-
- if (m_sszFullname.IsEmpty())
- m_bAnyMember = TRUE;
-}
-
-
-//
-// MdaQuery::CompiledQuery
-//
-
-MdaQuery::Compiler::Token MdaQuery::Compiler::LexAToken()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (*m_itr == W('\0'))
- return MdaFilterEnd;
-
- if (ISWHITE(*m_itr))
- {
- m_itr++;
- return LexAToken();
- }
-
- if (ISMDAID(*m_itr))
- {
- m_identifier.Clear();
-
- do
- {
- m_identifier.Append(*m_itr);
- m_itr++;
- }
- while(ISMDAID(*m_itr));
-
- m_identifier.Append(W("\0"));
- return MdaFilterIdentifier;
- }
-
- WCHAR c = *m_itr;
- m_itr++;
- switch(c)
- {
- case W('.'): return MdaFilterDot;
- case W(':'): return MdaFilterColon;
- case W('*'): return MdaFilterAstrix;
- case W('+'): return MdaFilterPlus;
- }
-
- return MdaFilterEnd;
-}
-
-//
-// MdaXPath::MdaXPathCompiler -- Parser
-//
-BOOL MdaQuery::Compiler::Compile(SString* sszQuery, CompiledQuery* pAst)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- m_itr = sszQuery->Begin();
-
- NextToken();
- BOOL bResult = NAME(pAst);
-
- return bResult;
-}
-
-// NAME
-// '*'
-// id
-// id '.' NAME
-// id '+' NESTNAME
-// id ':' ':' NESTNAME
-BOOL MdaQuery::Compiler::NAME(CompiledQuery* pAst)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (TokenIs(MdaFilterIdentifier))
- {
- pAst->SetName(GetIdentifier());
-
- NextToken();
- if (TokenIs(MdaFilterDot))
- {
- NextToken();
- return NAME(pAst);
- }
- else if (TokenIs(MdaFilterPlus))
- {
- NextToken();
- return NESTNAME(pAst);
- }
- else if (TokenIs(MdaFilterColon))
- {
- NextToken();
- if (!TokenIs(MdaFilterColon))
- return FALSE;
-
- NextToken();
- return MEMBERNAME(pAst);
- }
- }
- else if (TokenIs(MdaFilterAstrix))
- {
- pAst->SetAnyType();
- NextToken();
- }
- else return FALSE;
-
- return TRUE;
-}
-
-// NESTNAME
-// id '+' NESTNAME
-// id ':' ':' NESTNAME
-BOOL MdaQuery::Compiler::NESTNAME(CompiledQuery* pAst)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (!TokenIs(MdaFilterIdentifier))
- return FALSE;
-
- pAst->SetNestedTypeName(GetIdentifier());
-
- NextToken();
-
- if (TokenIs(MdaFilterPlus))
- {
- NextToken();
- return NESTNAME(pAst);
- }
- else if (TokenIs(MdaFilterColon))
- {
- NextToken();
- if (!TokenIs(MdaFilterColon))
- return FALSE;
-
- NextToken();
- return MEMBERNAME(pAst);
- }
- else return FALSE;
-}
-
-// MEMBERNAME
-// '*'
-// id
-BOOL MdaQuery::Compiler::MEMBERNAME(CompiledQuery* pAst)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (TokenIs(MdaFilterIdentifier))
- pAst->SetMemberName(GetIdentifier());
-
- else if (TokenIs(MdaFilterAstrix))
- pAst->SetAnyMember();
-
- else return FALSE;
-
- NextToken();
- return TRUE;
-}
-
-
-//
-// MdaXmlElement
-//
-MdaXmlElement* MdaXmlElement::GetChild(MdaElemDeclDef declDef)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- for(COUNT_T i = 0; i < m_children.GetCount(); i ++)
- {
- if (m_children[i]->GetDeclDef() == declDef)
- return m_children[i];
- }
-
- return NULL;
-}
-
-SString* MdaXmlElement::ToXml(SString* pXml, LPCWSTR ns, INT32 depth)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(depth < 60); // Trap for recursion
- }
- CONTRACTL_END;
-
- // Indent
- for (INT32 i = 0; i < depth; i ++)
- pXml->Append(W(" "));
-
- pXml->Append(W("<"));
- if (ns && IsDefinition()) { pXml->Append(ns); pXml->Append(W(":")); }
- pXml->Append(GetName());
-
- if (m_attributes.GetCount() != 0)
- {
- for (COUNT_T i = 0; i < m_defaultAttrIndex && i < m_attributes.GetCount(); i ++)
- {
- pXml->Append(W(" "));
- m_attributes[i]->ToXml(pXml);
- }
- }
-
- if (m_children.GetCount() == 0)
- {
- if (GetDeclDef() == MdaElemComment)
- {
- pXml->Append(W(" "));
- pXml->Append(m_szName.GetUnicode());
- pXml->Append(W(" -->\n"));
- }
- else
- pXml->Append(W("/>\n"));
- }
- else
- {
- pXml->Append(W(">"));
-
- SArray<MdaXmlElement*>::Iterator itr = m_children.Begin();
- SArray<MdaXmlElement*>::Iterator end = m_children.End();
-
- pXml->Append(W("\n"));
- while (itr != end)
- {
- (*itr)->ToXml(pXml, ns, depth + 1);
- itr++;
- }
-
- // Indent
- for (INT32 i = 0; i < depth; i ++)
- pXml->Append(W(" "));
-
- pXml->Append(W("</"));
- if (ns && IsDefinition()) { pXml->Append(ns); pXml->Append(W(":")); }
- pXml->Append(GetName());
- pXml->Append(W(">\n"));
- }
-
-
- return pXml;
-}
-
-LPCWSTR MdaXmlElement::DebugToString(SString* pBuffer)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- pBuffer->Append(W("<"));
- pBuffer->Append(GetName());
-
- for(COUNT_T i = 0; i < GetAttributes().GetCount(); i++)
- {
- pBuffer->Append(W(" "));
- GetAttributes()[i]->ToXml(pBuffer);
- }
-
- pBuffer->Append(W("/>"));
- return pBuffer->GetUnicode();
-}
-
-MdaXmlElement* MdaXmlElement::SetName(LPCWSTR name, BOOL bAssertDefined)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- SetDeclDef(MdaSchema::GetElementType(name, bAssertDefined));
-
- if (GetDeclDef() == MdaElemUndefined)
- m_szName.Set(name);
-
- return this;
-}
-
-MdaXmlAttribute* MdaXmlElement::AddAttribute(MdaAttrDeclDef declDef)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- return AddAttribute(m_pXmlIndustry->CreateAttribute()->SetDeclDef(declDef));
-}
-
-MdaXmlAttribute* MdaXmlElement::AddAttribute(LPCWSTR szName, LPCWSTR szValue)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- return AddAttribute(m_pXmlIndustry->CreateAttribute()->Initialize(szName, szValue));
-}
-
-MdaXmlAttribute* MdaXmlElement::AddDefaultAttribute(MdaAttrDeclDef attrDeclDef, LPCWSTR szValue)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (m_defaultAttrIndex == -1)
- m_defaultAttrIndex = m_attributes.GetCount();
- MdaXmlAttribute* pAttr = AddAttribute(attrDeclDef)->SetSString(szValue);
- pAttr->m_type = MdaSchemaPrimitiveUnknown;
- return pAttr;
-}
-
-MdaXmlElement* MdaXmlElement::AddChild(MdaXmlElement* pChild)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- //PRECONDITION(m_elemDeclDef != MdaElemUndefined);
- PRECONDITION(CheckPointer(pChild));
- PRECONDITION(CheckPointer(pChild->m_pXmlIndustry));
-
- *m_children.Append() = pChild;
- return pChild;
-}
-
-MdaXmlElement* MdaXmlElement::AddChild(LPCWSTR name, BOOL bAssertDefined)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- return AddChild(m_pXmlIndustry->CreateElement())->SetName(name, bAssertDefined);
-}
-
-MdaXmlElement* MdaXmlElement::AddChild(MdaElemDeclDef type)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- return AddChild(m_pXmlIndustry->CreateElement()->SetDeclDef(type));
-}
-
-LPCWSTR MdaXmlElement::GetName()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (GetDeclDef() == MdaElemUndefined)
- return m_szName.GetUnicode();
-
- return MdaSchema::GetElementName(m_elemDeclDef);
-}
-
-MdaXmlAttribute* MdaXmlElement::GetAttribute(MdaAttrDeclDef attrDeclDef)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
-
- for(UINT32 i = 0; i < m_attributes.GetCount(); i++)
- {
- if (attrDeclDef == m_attributes[i]->GetDeclDef())
- return m_attributes[i];
- }
-
- return NULL;
-}
-
-BOOL MdaXmlElement::GetAttributeValueAsBool(MdaAttrDeclDef attrDeclDef, BOOL bDefault)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- MdaXmlAttribute* pAttr = GetAttribute(attrDeclDef);
-
- if (!pAttr)
- return bDefault;
-
- return pAttr->GetValueAsBool();
-}
-
-BOOL MdaXmlElement::GetAttributeValueAsBool(MdaAttrDeclDef attrDeclDef)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- MdaXmlAttribute* pAttr = GetAttribute(attrDeclDef);
- PREFIX_ASSUME(pAttr != NULL);
- ASSERT(pAttr);
- return pAttr->GetValueAsBool();
-}
-
-//
-// MdaXmlAttribute
-//
-
-SString* MdaXmlAttribute::ToXml(SString* xml)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- SString sszBuffer;
-
- xml->Append(GetName());
- if (!m_szNs.IsEmpty())
- {
- xml->Append(W(":"));
- xml->Append(m_szNs.GetUnicode());
- }
-
- xml->Append(W("=\""));
- if (m_type == MdaSchemaPrimitiveSString)
- xml->Append(MdaXmlEscape(sszBuffer, m_value));
- else if (m_type == MdaSchemaPrimitiveBOOL)
- xml->Append(m_bool ? W("true") : W("false"));
- else if (m_type == MdaSchemaPrimitiveINT32)
- {
- StackSString sszOutput;
- sszOutput.Printf(W("%d"), m_int);
- xml->Append(sszOutput);
- }
- xml->Append(W("\""));
- return xml;
-}
-
-LPCWSTR MdaXmlAttribute::GetName()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (m_declDef != MdaAttrUndefined)
- return MdaSchema::GetAttributeName(m_declDef);
-
- return m_szName.GetUnicode();
-}
-
-MdaXmlAttribute* MdaXmlAttribute::Initialize(LPCWSTR szName, LPCWSTR szValue)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- m_type = MdaSchemaPrimitiveUnknown;
- m_value.Set(szValue);
-
- SetDeclDef(MdaSchema::GetAttributeType(szName, FALSE));
- if (m_declDef == MdaAttrUndefined)
- m_szName.Set(szName);
-
- return this;
-}
-
-
-//
-// MdaConfigFactory
-//
-STDAPI GetXMLObjectEx(IXMLParser **ppv);
-
-MdaXmlElement* MdaConfigFactory::ParseXmlStream(MdaXmlIndustry* pXmlIndustry, LPCWSTR pszFileName)
-{
- CONTRACT(MdaXmlElement*)
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACT_END;
-
- HRESULT hr = S_OK;
- MdaXmlElement* pRoot = NULL;
-
- EX_TRY
- {
- {
- if (!pszFileName)
- goto Exit;
-
- NonVMComHolder<IXMLParser> pIXMLParser(NULL);
- NonVMComHolder<IStream> pFile(NULL);
-
- hr = CreateConfigStream(pszFileName, &pFile);
- if(FAILED(hr)) goto Exit;
-
- hr = GetXMLObjectEx(&pIXMLParser);
- if(FAILED(hr)) goto Exit;
-
- hr = pIXMLParser->SetInput(pFile); // filestream's RefCount=2
- if ( ! SUCCEEDED(hr))
- goto Exit;
-
- pRoot = pXmlIndustry->CreateElement()->SetDeclDef(MdaElemDef(Dummy));
- MdaConfigFactory mdaConfigFactory(pRoot);
-
- hr = pIXMLParser->SetFactory(&mdaConfigFactory); // factory's RefCount=2
- if (!SUCCEEDED(hr))
- goto Exit;
-
- hr = pIXMLParser->Run(-1);
-
- if (pRoot->GetChildren().GetCount() == 1)
- pRoot = pRoot->GetChildren()[0];
- else
- pRoot = NULL;
- }
- Exit: ;
- }
- EX_CATCH
- {
- }
- EX_END_CATCH(SwallowAllExceptions);
-
- if (hr == (HRESULT)XML_E_MISSINGROOT)
- hr = S_OK;
- else if (Assembly::FileNotFound(hr))
- hr = S_FALSE;
-
- RETURN pRoot;
-}
-
-HRESULT STDMETHODCALLTYPE MdaConfigFactory::CreateNode(
- IXMLNodeSource* pSource,
- PVOID pNodeParent,
- USHORT cNumRecs,
- XML_NODE_INFO** apNodeInfo)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- m_pMdaXmlElement = NULL;
-
- for(INT32 i = 0; i < cNumRecs; i++)
- {
- DWORD dwType = apNodeInfo[i]->dwType;
-
- if(dwType == XML_ELEMENT || dwType == XML_ATTRIBUTE)
- {
- StackSString sszName((WCHAR*)apNodeInfo[i]->pwcText, apNodeInfo[i]->ulLen);
-
- if (dwType == XML_ELEMENT)
- {
- m_pMdaXmlElement = m_stack.Tos()->AddChild(sszName, FALSE);
- }
- else if (dwType == XML_ATTRIBUTE)
- {
- i++;
- InlineSString<MDA_BUFFER_SIZE> szValue((WCHAR*)apNodeInfo[i]->pwcText, apNodeInfo[i]->ulLen);
-
- if (m_pMdaXmlElement)
- m_pMdaXmlElement->AddAttribute(sszName.GetUnicode(), szValue);
- }
- }
- }
-
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE MdaConfigFactory::BeginChildren(
- IXMLNodeSource* pSource,
- XML_NODE_INFO* pNodeInfo)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- m_stack.Push(m_pMdaXmlElement);
-
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE MdaConfigFactory::EndChildren(
- IXMLNodeSource* pSource,
- BOOL fEmptyNode,
- XML_NODE_INFO* pNodeInfo)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
-
- if (fEmptyNode)
- return S_OK;
-
- m_stack.Pop();
-
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE MdaConfigFactory::NotifyEvent(
- IXMLNodeSource* pSource,
- XML_NODEFACTORY_EVENT iEvt)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE MdaConfigFactory::Error(
- IXMLNodeSource* pSource,
- HRESULT hrErrorCode,
- USHORT cNumRecs,
- XML_NODE_INFO** apNodeInfo)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- return E_FAIL;
-}
-
-#endif
diff --git a/src/vm/mda.h b/src/vm/mda.h
index b52bd00d42..c711e8ae7f 100644
--- a/src/vm/mda.h
+++ b/src/vm/mda.h
@@ -295,7 +295,6 @@ private:
friend class MdaXmlMessage;
friend class MdaXmlIndustry;
friend class MdaConfigFactory;
- friend class EEConfigFactory;
friend class MdaFramework;
friend void EEStartupHelper(COINITIEE fFlags);
diff --git a/src/vm/mdadac.cpp b/src/vm/mdadac.cpp
deleted file mode 100644
index 95be6bff60..0000000000
--- a/src/vm/mdadac.cpp
+++ /dev/null
@@ -1,48 +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.
-
-
-#include "common.h"
-#include "mda.h"
-#include "mdaassistants.h"
-#include "sstring.h"
-#include "daccess.h"
-
-#ifdef MDA_SUPPORTED
-MdaStaticHeap g_mdaStaticHeap =
-{
- { 0 }, // m_assistants[]
- 0, // m_pMda
- { 0 }, // m_mda[]
-
-#define MDA_ASSISTANT_STATIC_INIT
-#include "mdaschema.inl"
-#undef MDA_ASSISTANT_STATIC_INIT
-};
-
-
-//
-// MdaManagedDebuggingAssistants
-//
-void ManagedDebuggingAssistants::AllocateManagedDebuggingAssistants()
-{
- WRAPPER_NO_CONTRACT;
- g_mdaStaticHeap.m_pMda = new (&g_mdaStaticHeap.m_mda) ManagedDebuggingAssistants();
-}
-
-ManagedDebuggingAssistants::ManagedDebuggingAssistants()
-{
- WRAPPER_NO_CONTRACT;
-
-#ifndef DACCESS_COMPILE
- Initialize();
-#endif
-}
-#endif // MDA_SUPPORTED
-
-
-
-
-
-
diff --git a/src/vm/message.cpp b/src/vm/message.cpp
deleted file mode 100644
index 093f9a2629..0000000000
--- a/src/vm/message.cpp
+++ /dev/null
@@ -1,1171 +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.
-
-/*============================================================
-**
-** File: message.cpp
-**
-** Purpose: Encapsulates a function call frame into a message
-** object with an interface that can enumerate the
-** arguments of the message
-**
-**
-
-===========================================================*/
-#include "common.h"
-
-#ifdef FEATURE_REMOTING
-
-#include "comdelegate.h"
-#include "excep.h"
-#include "message.h"
-#include "remoting.h"
-#include "field.h"
-#include "eeconfig.h"
-#include "invokeutil.h"
-#include "callingconvention.h"
-
-//+----------------------------------------------------------------------------
-//
-// Method: CMessage::GetArgCount public
-//
-// Synopsis: Returns number of arguments in the method call
-//
-//+----------------------------------------------------------------------------
-FCIMPL1(INT32, CMessage::GetArgCount, MessageObject * pMessage)
-{
- CONTRACTL
- {
- FCALL_CHECK;
- PRECONDITION(CheckPointer(pMessage));
- }
- CONTRACTL_END;
-
- LOG((LF_REMOTING, LL_INFO10, "CMessage::GetArgCount IN pMsg:0x%x\n", pMessage));
-
- // Get the frame pointer from the object
- MetaSig *pSig = pMessage->GetResetMetaSig();
-
- // scan the sig for the argument count
- INT32 ret = pSig->NumFixedArgs();
-
- if (pMessage->GetDelegateMD())
- ret -= 2;
-
- LOG((LF_REMOTING, LL_INFO10, "CMessage::GetArgCount OUT ret:0x%x\n", ret));
- return ret;
-}
-FCIMPLEND
-
-//+----------------------------------------------------------------------------
-//
-// Method: CMessage::GetArg public
-//
-// Synopsis: Use to enumerate a call's arguments
-//
-//+----------------------------------------------------------------------------
-FCIMPL2(Object*, CMessage::GetArg, MessageObject* pMessageUNSAFE, INT32 argNum)
-{
- CONTRACTL
- {
- FCALL_CHECK;
- PRECONDITION(pMessageUNSAFE != NULL);
- }
- CONTRACTL_END;
-
- struct _gc {
- OBJECTREF refRetVal;
- MESSAGEREF pMessage;
- } gc;
-
- gc.refRetVal = NULL;
- gc.pMessage = (MESSAGEREF) pMessageUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
-
- LOG((LF_REMOTING, LL_INFO10, "CMessage::GetArgCount IN\n"));
-
- MetaSig *pSig = gc.pMessage->GetResetMetaSig();
-
- if ((UINT)argNum >= pSig->NumFixedArgs())
- COMPlusThrow(kTargetParameterCountException);
-
- for (INT32 i = 0; i < argNum; i++)
- pSig->NextArg();
-
- BOOL fIsByRef = FALSE;
- CorElementType eType = pSig->NextArg();
- TypeHandle ty = TypeHandle();
- if (eType == ELEMENT_TYPE_BYREF)
- {
- fIsByRef = TRUE;
- TypeHandle tycopy;
- eType = pSig->GetByRefType(&tycopy);
- if (eType == ELEMENT_TYPE_VALUETYPE)
- ty = tycopy;
- }
- else
- {
- if (eType == ELEMENT_TYPE_VALUETYPE)
- {
- ty = pSig->GetLastTypeHandleThrowing();
-
-#ifdef ENREGISTERED_PARAMTYPE_MAXSIZE
- if (ArgIterator::IsArgPassedByRef(ty))
- fIsByRef = TRUE;
-#endif
- }
- }
-
- if (eType == ELEMENT_TYPE_PTR)
- COMPlusThrow(kRemotingException, W("Remoting_CantRemotePointerType"));
-
- GetObjectFromStack(&gc.refRetVal,
- GetStackPtr(argNum, gc.pMessage->GetFrame(), gc.pMessage->GetResetMetaSig()),
- eType,
- ty,
- fIsByRef,
- gc.pMessage->GetFrame());
-
- LOG((LF_REMOTING, LL_INFO10, "CMessage::GetArg OUT\n"));
-
- HELPER_METHOD_FRAME_END();
- return OBJECTREFToObject(gc.refRetVal);
-}
-FCIMPLEND
-
-FCIMPL1(Object*, CMessage::GetArgs, MessageObject* pMessageUNSAFE)
-{
- CONTRACTL
- {
- FCALL_CHECK;
- PRECONDITION(pMessageUNSAFE != NULL);
- }
- CONTRACTL_END;
-
- struct _gc {
- PTRARRAYREF refRetVal;
- MESSAGEREF pMessage;
- OBJECTREF arg;
- } gc;
-
- gc.refRetVal = NULL;
- gc.pMessage = (MESSAGEREF) pMessageUNSAFE;
- gc.arg = NULL;
-
- HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
-
- LOG((LF_REMOTING, LL_INFO10, "CMessage::GetArgCount IN\n"));
-
- MetaSig *pSig = gc.pMessage->GetResetMetaSig();
-
- // scan the sig for the argument count
- INT32 numArgs = pSig->NumFixedArgs();
- if (gc.pMessage->GetDelegateMD())
- numArgs -= 2;
-
- // Allocate an object array
- gc.refRetVal = (PTRARRAYREF) AllocateObjectArray(numArgs, g_pObjectClass);
-
- ArgIterator iter(pSig);
-
- for (int index = 0; index < numArgs; index++)
- {
- BOOL fIsByRef = FALSE;
- CorElementType eType;
- PVOID addr;
- eType = pSig->PeekArg();
- addr = (LPBYTE) gc.pMessage->GetFrame()->GetTransitionBlock() + GetStackOffset(gc.pMessage->GetFrame(), &iter, pSig);
-
- TypeHandle ty = TypeHandle();
- if (eType == ELEMENT_TYPE_BYREF)
- {
- fIsByRef = TRUE;
- TypeHandle tycopy;
- // If this is a by-ref arg, GetObjectFromStack() will dereference "addr" to
- // get the real argument address. Dereferencing now will open a gc hole if "addr"
- // points into the gc heap, and we trigger gc between here and the point where
- // we return the arguments.
- //addr = *((PVOID *) addr);
- eType = pSig->GetByRefType(&tycopy);
- if (eType == ELEMENT_TYPE_VALUETYPE)
- ty = tycopy;
- }
- else
- {
- if (eType == ELEMENT_TYPE_VALUETYPE)
- {
- ty = pSig->GetLastTypeHandleThrowing();
-
-#ifdef ENREGISTERED_PARAMTYPE_MAXSIZE
- if (ArgIterator::IsArgPassedByRef(ty))
- fIsByRef = TRUE;
-#endif
- }
- }
-
- if (eType == ELEMENT_TYPE_PTR)
- COMPlusThrow(kRemotingException, W("Remoting_CantRemotePointerType"));
-
- GetObjectFromStack(&gc.arg,
- addr,
- eType,
- ty,
- fIsByRef,
- gc.pMessage->GetFrame());
-
- gc.refRetVal->SetAt(index, gc.arg);
- }
-
- LOG((LF_REMOTING, LL_INFO10, "CMessage::GetArgs OUT\n"));
-
- HELPER_METHOD_FRAME_END();
- return OBJECTREFToObject(gc.refRetVal);
-}
-FCIMPLEND
-
-//static
-void CMessage::GetObjectFromStack(OBJECTREF* ppDest, PVOID val, const CorElementType eType, TypeHandle ty, BOOL fIsByRef, FramedMethodFrame *pFrame)
-{
- CONTRACT_VOID
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(ppDest));
- PRECONDITION(CheckPointer(val));
- }
- CONTRACT_END;
-
- // Value types like Nullable<T> have special unboxing semantics,
- //
- if (eType == ELEMENT_TYPE_VALUETYPE)
- {
- //
- // box the value class
- //
-
- _ASSERTE(ty.GetMethodTable()->IsValueType() || ty.GetMethodTable()->IsEnum());
-
- _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsHeapPointer((BYTE *) ppDest) ||
- !"(pDest) can not point to GC Heap");
- MethodTable* pMT = ty.GetMethodTable();
-
- if (pMT->IsByRefLike())
- COMPlusThrow(kRemotingException, W("Remoting_TypeCantBeRemoted"));
-
- PVOID* pVal;
- if (fIsByRef)
- pVal = (PVOID *)val;
- else {
- val = StackElemEndianessFixup(val, pMT->GetNumInstanceFieldBytes());
- pVal = &val;
- }
-
- *ppDest = pMT->FastBox(pVal);
- RETURN;
- }
-
- switch (CorTypeInfo::GetGCType(eType))
- {
- case TYPE_GC_NONE:
- {
- if(ELEMENT_TYPE_PTR == eType)
- {
- COMPlusThrow(kNotSupportedException);
- }
-
- MethodTable *pMT = MscorlibBinder::GetElementType(eType);
-
- OBJECTREF pObj = pMT->Allocate();
- if (fIsByRef)
- val = *((PVOID *)val);
- else
- val = StackElemEndianessFixup(val, CorTypeInfo::Size(eType));
-
- void *pDest = pObj->UnBox();
-
-#ifdef COM_STUBS_SEPARATE_FP_LOCATIONS
- if ( !fIsByRef
- && ( ELEMENT_TYPE_R4 == eType
- || ELEMENT_TYPE_R8 == eType)
- && pFrame
- && !TransitionBlock::IsStackArgumentOffset(static_cast<int>((TADDR) val - pFrame->GetTransitionBlock())))
- {
- if (ELEMENT_TYPE_R4 == eType)
- *(UINT32*)pDest = (UINT32)FPSpillToR4(val);
- else
- *(UINT64*)pDest = (UINT64)FPSpillToR8(val);
- }
- else
-#endif // COM_STUBS_SEPARATE_FP_LOCATIONS
- {
- memcpyNoGCRefs(pDest, val, CorTypeInfo::Size(eType));
- }
-
- *ppDest = pObj;
- }
- break;
- case TYPE_GC_REF:
- if (fIsByRef)
- val = *((PVOID *)val);
- *ppDest = ObjectToOBJECTREF(*(Object **)val);
- break;
- default:
- COMPlusThrow(kRemotingException, W("Remoting_TypeCantBeRemoted"));
- }
-
- RETURN;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CMessage::PropagateOutParameters private
-//
-// Synopsis: Copy back data for in/out parameters and the return value
-//
-//+----------------------------------------------------------------------------
-FCIMPL3(void, CMessage::PropagateOutParameters, MessageObject* pMessageUNSAFE, ArrayBase* pOutPrmsUNSAFE, Object* RetValUNSAFE)
-{
- CONTRACTL
- {
- FCALL_CHECK;
- PRECONDITION(pMessageUNSAFE != NULL);
- }
- CONTRACTL_END;
-
- struct _gc
- {
- MESSAGEREF pMessage;
- BASEARRAYREF pOutPrms;
- OBJECTREF RetVal;
- OBJECTREF param;
- } gc;
- gc.pMessage = (MESSAGEREF) pMessageUNSAFE;
- gc.pOutPrms = (BASEARRAYREF) pOutPrmsUNSAFE;
- gc.RetVal = (OBJECTREF) RetValUNSAFE;
- gc.param = NULL;
- HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
-
- LOG((LF_REMOTING, LL_INFO10, "CMessage::PropogateOutParameters IN\n"));
-
- // Retrieve the message's flags.
- INT32 flags = gc.pMessage->GetFlags();
-
- // Construct an ArgIterator from the message's frame and sig.
- MetaSig *pSig = gc.pMessage->GetResetMetaSig();
- FramedMethodFrame *pFrame = gc.pMessage->GetFrame();
- ArgIterator argit(pSig);
-
- // move into object to return to client
-
- // Propagate the return value only if the pMsg is not a Ctor message
- // Check if the return type has a return buffer associated with it
- if ((flags& MSGFLG_CTOR) == 0 && pSig->GetReturnType() != ELEMENT_TYPE_VOID)
- {
- if (argit.HasRetBuffArg())
- {
- // Copy from RetVal into the retBuff.
- INT64 retVal = CopyOBJECTREFToStack(
- *(void**)(pFrame->GetTransitionBlock() + argit.GetRetBuffArgOffset()),
- &gc.RetVal,
- pSig->GetReturnType(),
- TypeHandle(),
- pSig,
- TRUE); // copy class contents
-
- // Copy the return value
- *(ARG_SLOT *)(gc.pMessage->GetFrame()->GetReturnValuePtr()) = retVal;
- }
- else
- {
-#ifdef ENREGISTERED_RETURNTYPE_MAXSIZE
- if (argit.HasNonStandardByvalReturn())
- {
- //
- // in these cases, we put the pointer to the return buffer into the frame's
- // return value slot
- //
- CopyOBJECTREFToStack(gc.pMessage->GetFrame()->GetReturnValuePtr(),
- &gc.RetVal,
- pSig->GetReturnType(),
- TypeHandle(),
- pSig,
- TRUE); // copy class contents
- }
- else
-#endif // ENREGISTERED_RETURNTYPE_MAXSIZE
- {
- // There is no separate return buffer, the retVal should fit in
- // an INT64.
- INT64 retVal = CopyOBJECTREFToStack(
- NULL, //no return buff
- &gc.RetVal,
- pSig->GetReturnType(),
- TypeHandle(),
- pSig,
- FALSE); //don't copy class contents
-
- // Copy the return value
- *(ARG_SLOT *)(gc.pMessage->GetFrame()->GetReturnValuePtr()) = retVal;
- }
- }
- }
-
- // Refetch all the variables as GC could have happened after call to
- // CopyOBJECTREFToStack
- UINT32 cOutParams = (gc.pOutPrms != NULL) ? gc.pOutPrms->GetNumComponents() : 0;
- if (cOutParams > 0)
- {
- PVOID *argAddr;
- UINT32 i = 0;
- MetaSig syncSig(gc.pMessage->GetMethodDesc());
- MetaSig *pSyncSig = NULL;
-
- if (flags & MSGFLG_ENDINVOKE)
- {
- pSyncSig = &syncSig;
- }
-
- for (i=0; i<cOutParams; i++)
- {
- if (pSyncSig)
- {
- CorElementType typ = pSyncSig->NextArg();
- if (typ == ELEMENT_TYPE_END)
- {
- break;
- }
-
- if (typ != ELEMENT_TYPE_BYREF)
- {
- continue;
- }
-
- argAddr = (PVOID *)(pFrame->GetTransitionBlock() + argit.GetNextOffset());
- }
- else
- {
- int ofs = argit.GetNextOffset();
- if (ofs == TransitionBlock::InvalidOffset)
- {
- break;
- }
-
- if (argit.GetArgType() != ELEMENT_TYPE_BYREF)
- {
- continue;
- }
-
- argAddr = (PVOID *)(pFrame->GetTransitionBlock() + ofs);
- }
-
- TypeHandle ty = TypeHandle();
- CorElementType brType = pSig->GetByRefType(&ty);
-
- gc.param = ((OBJECTREF *) gc.pOutPrms->GetDataPtr())[i];
-
- CopyOBJECTREFToStack(
- *argAddr,
- &gc.param,
- brType,
- ty,
- pSig,
- ty.IsNull() ? FALSE : ty.IsValueType());
- }
-
- }
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-INT64 CMessage::CopyOBJECTREFToStack(PVOID pvDest, OBJECTREF *pSrc, CorElementType typ, TypeHandle ty, MetaSig *pSig, BOOL fCopyClassContents)
-{
- INT64 ret = 0;
-
- CONTRACT(INT64)
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pvDest, NULL_OK));
- PRECONDITION(CheckPointer(pSrc));
- PRECONDITION(typ != ELEMENT_TYPE_VOID);
- PRECONDITION(CheckPointer(pSig));
- }
- CONTRACT_END;
-
- if (fCopyClassContents)
- {
- // We have to copy the contents of a value class to pvDest
-
- // write unboxed version back to memory provided by the client
- if (pvDest)
- {
- if (ty.IsNull())
- ty = pSig->GetRetTypeHandleThrowing();
-
- if (*pSrc == NULL && !Nullable::IsNullableType(ty))
- COMPlusThrow(kRemotingException, W("Remoting_Message_BadRetValOrOutArg"));
-
- ty.GetMethodTable()->UnBoxIntoUnchecked(pvDest, *pSrc);
-
- // return the object so it can be stored in the frame and
- // propagated to the root set
- // pSrc may not be doubleword aligned!
- *(OBJECTREF*)&ret = *pSrc;
- }
- }
- else
- {
- // We have either a real OBJECTREF or something that does not have
- // a return buffer associated
-
- // Check if it is an ObjectRef (from the GC heap)
- if (CorTypeInfo::IsObjRef(typ))
- {
- if ((*pSrc!=NULL) && ((*pSrc)->IsTransparentProxy()))
- {
- if (ty.IsNull())
- ty = pSig->GetRetTypeHandleThrowing();
-
- // CheckCast ensures that the returned object (proxy) gets
- // refined to the level expected by the caller of the method
- if (!CRemotingServices::CheckCast(*pSrc, ty))
- COMPlusThrow(kInvalidCastException, W("Arg_ObjObj"));
- }
- if (pvDest)
- SetObjectReferenceUnchecked((OBJECTREF *)pvDest, *pSrc);
-
- // pSrc may not be double-word aligned!
- *(OBJECTREF*)&ret = *pSrc;
- }
- else
- {
- // Note: this assert includes VALUETYPE because for Enums
- // HasRetBuffArg() returns false since the normalized type is I4
- // so we end up here ... but GetReturnType() returns VALUETYPE
- // Almost all VALUETYPEs will go through the fCopyClassContents
- // codepath instead of here.
- // Also, IsPrimitiveType() does not check for IntPtr, UIntPtr etc
- // there is a note in siginfo.hpp about that ... hence we have
- // ELEMENT_TYPE_I, ELEMENT_TYPE_U.
- _ASSERTE(
- CorTypeInfo::IsPrimitiveType(typ)
- || (typ == ELEMENT_TYPE_VALUETYPE)
- || (typ == ELEMENT_TYPE_I)
- || (typ == ELEMENT_TYPE_U)
- || (typ == ELEMENT_TYPE_FNPTR)
- );
-
- // REVIEW: For a "ref int" arg, if a nasty sink replaces the boxed
- // int with a null OBJECTREF, this is where we check. We need to be
- // uniform in our policy w.r.t. this (throw v/s ignore)
- // The 'if' block above throws, CallFieldAccessor also has this
- // problem.
- if (*pSrc != NULL)
- {
- PVOID pvSrcData = (*pSrc)->GetData();
- int cbsize = gElementTypeInfo[typ].m_cbSize;
- INT64 retBuff;
-
- // ElementTypeInfo.m_cbSize can be less that zero for cases that need
- // special handling (e.g. value types) to be sure of size (see
- // siginfo.cpp). Luckily, the type handle has the actual byte count,
- // so we look there for such cases.
- if (cbsize < 0)
- {
- if (ty.IsNull())
- ty = pSig->GetRetTypeHandleThrowing();
-
- _ASSERTE(!ty.IsNull());
- cbsize = ty.GetSize();
-
- // we are returning this value class in an INT64 so it better be small enough
- _ASSERTE(cbsize <= (int) sizeof(INT64));
- // Unbox it into a local buffer, This coveres the Nullable<T> case
- // then do the endianness morph below
- ty.GetMethodTable()->UnBoxIntoUnchecked(&retBuff, *pSrc);
-
- pvSrcData = &retBuff;
- }
-
- if (pvDest)
- {
- memcpyNoGCRefs(pvDest, pvSrcData, cbsize);
- }
-
- // need to sign-extend signed types
- bool fEndianessFixup = false;
- switch (typ) {
- case ELEMENT_TYPE_I1:
- ret = *(INT8*)pvSrcData;
- fEndianessFixup = true;
- break;
- case ELEMENT_TYPE_I2:
- ret = *(INT16*)pvSrcData;
- fEndianessFixup = true;
- break;
- case ELEMENT_TYPE_I4:
- ret = *(INT32*)pvSrcData;
- fEndianessFixup = true;
- break;
- default:
- memcpyNoGCRefs(StackElemEndianessFixup(&ret, cbsize), pvSrcData, cbsize);
- break;
- }
-
-#if !defined(_WIN64) && BIGENDIAN
- if (fEndianessFixup)
- ret <<= 32;
-#endif
- }
- }
- }
-
- RETURN(ret);
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CMessage::GetReturnValue
-//
-// Synopsis: Pull return value off the stack
-//
-//+----------------------------------------------------------------------------
-FCIMPL1(Object*, CMessage::GetReturnValue, MessageObject* pMessageUNSAFE)
-{
- CONTRACTL
- {
- FCALL_CHECK;
- PRECONDITION(pMessageUNSAFE != NULL);
- }
- CONTRACTL_END;
-
- struct _gc {
- OBJECTREF refRetVal;
- MESSAGEREF pMessage;
- } gc;
-
- gc.refRetVal = NULL;
- gc.pMessage = (MESSAGEREF) pMessageUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
-
- MetaSig* pSig = gc.pMessage->GetResetMetaSig();
- FramedMethodFrame* pFrame = gc.pMessage->GetFrame();
-
- ArgIterator argit(pSig);
-
- PVOID pvRet;
- if (argit.HasRetBuffArg())
- {
- pvRet = *(PVOID *)(pFrame->GetTransitionBlock() + argit.GetRetBuffArgOffset());
- }
- else
- {
- pvRet = pFrame->GetReturnValuePtr();
- }
-
- CorElementType eType = pSig->GetReturnType();
- TypeHandle ty;
- if (eType == ELEMENT_TYPE_VALUETYPE)
- {
- ty = pSig->GetRetTypeHandleThrowing();
- }
- else
- {
- ty = TypeHandle();
- }
-
- GetObjectFromStack(&gc.refRetVal,
- pvRet,
- eType,
- ty);
-
- HELPER_METHOD_FRAME_END();
- return OBJECTREFToObject(gc.refRetVal);
-}
-FCIMPLEND
-
-
-
-FCIMPL2(FC_BOOL_RET, CMessage::Dispatch, MessageObject* pMessageUNSAFE, Object* pServerUNSAFE)
-{
- CONTRACTL
- {
- FCALL_CHECK;
- PRECONDITION(pMessageUNSAFE != NULL);
- PRECONDITION(pServerUNSAFE != NULL);
- }
- CONTRACTL_END;
-
- BOOL fDispatched = FALSE;
- MESSAGEREF pMessage = (MESSAGEREF) pMessageUNSAFE;
- OBJECTREF pServer = (OBJECTREF) pServerUNSAFE;
- HELPER_METHOD_FRAME_BEGIN_RET_2(pMessage, pServer);
-
- MetaSig *pSig = pMessage->GetResetMetaSig();
-
- if (pMessage->GetFlags() & (MSGFLG_BEGININVOKE | MSGFLG_ENDINVOKE | MSGFLG_ONEWAY))
- {
- fDispatched = FALSE;
- goto lExit;
- }
-
- {
- ArgIterator argit(pSig);
-
- UINT nStackBytes;
- MethodDesc *pMD;
- PCODE pTarget;
-
- nStackBytes = argit.SizeOfFrameArgumentArray();
- pMD = pMessage->GetMethodDesc();
-
- // Get the address of the code
- pTarget = pMD->GetCallTarget(&(pServer));
-
-#ifdef PROFILING_SUPPORTED
- // If we're profiling, notify the profiler that we're about to invoke the remoting target
- {
- BEGIN_PIN_PROFILER(CORProfilerTrackRemoting());
- GCX_PREEMP();
- g_profControlBlock.pProfInterface->RemotingServerInvocationStarted();
- END_PIN_PROFILER();
- }
-#endif // PROFILING_SUPPORTED
-
-#ifdef CALLDESCR_FPARGREGS
- // @TODO: This code badly needs refactorization. It's largely shared with MethodDesc::CallDescr in
- // method.cpp and CallDescrWithObjectArray in stackbuildersync.cpp.
-
- FloatArgumentRegisters *pFloatArgumentRegisters = NULL;
-
- // Iterate through all the args looking for floating point values that will be passed in (FP) argument
- // registers.
- int ofs;
- while ((ofs = argit.GetNextOffset()) != TransitionBlock::InvalidOffset)
- {
- if (TransitionBlock::HasFloatRegister(ofs, argit.GetArgLocDescForStructInRegs()))
- {
- // Found a floating point argument register. The first time we find this we point
- // pFloatArgumentRegisters to the part of the frame where these values were spilled (we don't do
- // this unconditionally since the call worker can optimize out the copy of the floating point
- // registers if none are involved at all.
- pFloatArgumentRegisters = (FloatArgumentRegisters*)(pMessage->GetFrame()->GetTransitionBlock() +
- TransitionBlock::GetOffsetOfFloatArgumentRegisters());
-
- // That's all we need to do, CallDescrWorkerWithHandler will automatically pick up all the
- // floating point argument values now.
- break;
- }
- }
-#endif // CALLDESCR_FPARGREGS
-
-#if defined(CALLDESCR_REGTYPEMAP) || defined(COM_STUBS_SEPARATE_FP_LOCATIONS)
- DWORD_PTR dwRegTypeMap = 0;
-
- {
- int ofs;
- while ((ofs = argit.GetNextOffset()) != TransitionBlock::InvalidOffset)
- {
- int regArgNum = TransitionBlock::GetArgumentIndexFromOffset(ofs);
-
- if (regArgNum >= NUM_ARGUMENT_REGISTERS)
- break;
-
- CorElementType argTyp = argit.GetArgType();
-
-#ifdef CALLDESCR_REGTYPEMAP
- FillInRegTypeMap(ofs, argTyp, (BYTE*)&dwRegTypeMap);
-#endif
-
-#ifdef COM_STUBS_SEPARATE_FP_LOCATIONS
- // If this is a floating point argument, it was stored in a
- // separate area of the frame. Copy it into the argument array.
- if (ELEMENT_TYPE_R4 == argTyp || ELEMENT_TYPE_R8 == argTyp)
- {
- TADDR pTransitionBlock = pMessage->GetFrame()->GetTransitionBlock();
-
- PVOID pDest = (PVOID)(pTransitionBlock + ofs);
- PVOID pSrc = (PVOID)(pTransitionBlock + pMessage->GetFrame()->GetFPArgOffset(regArgNum));
-
- ARG_SLOT val;
- if (ELEMENT_TYPE_R4 == argTyp)
- val = FPSpillToR4(pSrc);
- else
- val = FPSpillToR8(pSrc);
-
- *(ARG_SLOT*)pDest = val;
- }
-#endif
- }
- }
-#endif // CALLDESCR_REGTYPEMAP || COM_STUBS_SEPARATE_FP_LOCATIONS
-
- CallDescrData callDescrData;
-
- callDescrData.pSrc = (BYTE*)pMessage->GetFrame()->GetTransitionBlock() + sizeof(TransitionBlock);
- callDescrData.numStackSlots = nStackBytes / STACK_ELEM_SIZE;
-#ifdef CALLDESCR_ARGREGS
- callDescrData.pArgumentRegisters = (ArgumentRegisters*)(pMessage->GetFrame()->GetTransitionBlock() + TransitionBlock::GetOffsetOfArgumentRegisters());
-#endif
-#ifdef CALLDESCR_FPARGREGS
- callDescrData.pFloatArgumentRegisters = pFloatArgumentRegisters;
-#endif
-#ifdef CALLDESCR_REGTYPEMAP
- callDescrData.dwRegTypeMap = dwRegTypeMap;
-#endif
- callDescrData.fpReturnSize = argit.GetFPReturnSize();
- callDescrData.pTarget = pTarget;
-
- CallDescrWorkerWithHandler(&callDescrData);
-
-#ifdef PROFILING_SUPPORTED
- // If we're profiling, notify the profiler that we're about to invoke the remoting target
- {
- BEGIN_PIN_PROFILER(CORProfilerTrackRemoting());
- GCX_PREEMP();
- g_profControlBlock.pProfInterface->RemotingServerInvocationReturned();
- END_PIN_PROFILER();
- }
-#endif // PROFILING_SUPPORTED
-
- memcpyNoGCRefs(pMessage->GetFrame()->GetReturnValuePtr(), &callDescrData.returnValue, sizeof(callDescrData.returnValue));
-
- fDispatched = TRUE;
- }
-
-lExit: ;
- HELPER_METHOD_FRAME_END();
- FC_RETURN_BOOL(fDispatched);
-}
-FCIMPLEND
-
-void CMessage::AppendAssemblyName(CQuickBytes &out, const CHAR* str)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(str));
- }
- CONTRACTL_END;
-
- SIZE_T len = strlen(str) * sizeof(CHAR);
- SIZE_T oldSize = out.Size();
- out.ReSizeThrows(oldSize + len + 2);
- CHAR * cur = (CHAR *) ((BYTE *) out.Ptr() + oldSize - 1);
- if (*cur)
- cur++;
-
- *cur = ASSEMBLY_SEPARATOR_CHAR;
- memcpy(cur + 1, str, len);
- cur += (len + 1);
- *cur = '\0';
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CMessage::GetAsyncBeginInfo
-//
-// Synopsis: Pull the AsyncBeginInfo object from an async call
-//
-//+----------------------------------------------------------------------------
-FCIMPL3(void, CMessage::GetAsyncBeginInfo, MessageObject* pMessageUNSAFE, OBJECTREF* ppACBD, OBJECTREF* ppState)
-{
- CONTRACTL
- {
- FCALL_CHECK;
- PRECONDITION(pMessageUNSAFE != NULL);
- }
- CONTRACTL_END;
-
- MESSAGEREF pMessage = (MESSAGEREF) pMessageUNSAFE;
- _ASSERTE(pMessage->GetFlags() & MSGFLG_BEGININVOKE);
-
- HELPER_METHOD_FRAME_BEGIN_1(pMessage);
-
- LOG((LF_REMOTING, LL_INFO10, "CMessage::GetAsyncBeginInfo IN\n"));
-
- if (pMessage == NULL)
- COMPlusThrow(kNullReferenceException, W("NullReference_This"));
-
- MetaSig *pSig = pMessage->GetResetMetaSig();
-
- FramedMethodFrame * pFrame = pMessage->GetFrame();
- ArgIterator argit(pSig);
-
- if ((ppACBD != NULL) || (ppState != NULL))
- {
- int ofs;
- int last = TransitionBlock::InvalidOffset, secondtolast = TransitionBlock::InvalidOffset;
- while ((ofs = argit.GetNextOffset()) != TransitionBlock::InvalidOffset)
- {
- secondtolast = last;
- last = ofs;
- }
- _ASSERTE(secondtolast != TransitionBlock::InvalidOffset);
- if (secondtolast != TransitionBlock::InvalidOffset && ppACBD != NULL)
- SetObjectReferenceUnchecked(ppACBD, ObjectToOBJECTREF(*(Object **)(pFrame->GetTransitionBlock() + secondtolast)));
- PREFIX_ASSUME(last != TransitionBlock::InvalidOffset);
- if (ppState != NULL)
- SetObjectReferenceUnchecked(ppState, ObjectToOBJECTREF(*(Object **)(pFrame->GetTransitionBlock() + last)));
- }
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-//+----------------------------------------------------------------------------
-//
-// Method: CMessage::GetAsyncResult
-//
-// Synopsis: Pull the AsyncResult from an async call
-//
-//+----------------------------------------------------------------------------
-FCIMPL1(LPVOID, CMessage::GetAsyncResult, MessageObject* pMessageUNSAFE)
-{
- CONTRACTL
- {
- FCALL_CHECK;
- PRECONDITION(pMessageUNSAFE != NULL);
- }
- CONTRACTL_END;
-
- LPVOID retVal = NULL;
- MESSAGEREF pMessage = (MESSAGEREF) pMessageUNSAFE;
- _ASSERTE(pMessage->GetFlags() & MSGFLG_ENDINVOKE);
-
- HELPER_METHOD_FRAME_BEGIN_RET_1(pMessage);
-
- LOG((LF_REMOTING, LL_INFO10, "CMessage::GetAsyncResult IN\n"));
-
- retVal = GetLastArgument(&pMessage);
-
- HELPER_METHOD_FRAME_END();
- return retVal;
-}
-FCIMPLEND
-
-//+----------------------------------------------------------------------------
-//
-// Method: CMessage::GetAsyncObject
-//
-// Synopsis: Pull the AsyncObject from an async call
-//
-//+----------------------------------------------------------------------------
-FCIMPL1(Object*, CMessage::GetAsyncObject, MessageObject* pMessageUNSAFE)
-{
- CONTRACTL
- {
- FCALL_CHECK;
- PRECONDITION(pMessageUNSAFE != NULL);
- }
- CONTRACTL_END;
-
- Object* pobjRetVal = NULL;
- MESSAGEREF pMessage = (MESSAGEREF) pMessageUNSAFE;
- HELPER_METHOD_FRAME_BEGIN_RET_1(pMessage);
-
- LOG((LF_REMOTING, LL_INFO10, "CMessage::GetAsyncObject IN\n"));
-
- FramedMethodFrame *pFrame = pMessage->GetFrame();
- MetaSig *pSig = pMessage->GetResetMetaSig();
- ArgIterator argit(pSig);
-
- pobjRetVal = *(Object**)(pFrame->GetTransitionBlock() + argit.GetThisOffset());
-
- HELPER_METHOD_FRAME_END();
- return pobjRetVal;
-}
-FCIMPLEND
-
-//+----------------------------------------------------------------------------
-//
-// Method: CMessage::GetLastArgument private
-//
-// Synopsis: Pull the last argument of 4 bytes off the stack
-//
-//+----------------------------------------------------------------------------
-LPVOID CMessage::GetLastArgument(MESSAGEREF *pMsg)
-{
- CONTRACT(LPVOID)
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pMsg));
- POSTCONDITION(*pMsg != NULL); // CheckPointer doesn't seem to work here.
- POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
- }
- CONTRACT_END;
-
- FramedMethodFrame *pFrame = (*pMsg)->GetFrame();
- MetaSig *pSig = (*pMsg)->GetResetMetaSig();
-
- ArgIterator argit(pSig);
- int arg;
- int backadder = TransitionBlock::InvalidOffset;
- while ((arg = argit.GetNextOffset()) != TransitionBlock::InvalidOffset)
- backadder = arg;
-
- _ASSERTE(backadder != TransitionBlock::InvalidOffset);
-
- RETURN *(LPVOID *)(pFrame->GetTransitionBlock() + backadder);
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CMessage::DebugOut public
-//
-// Synopsis: temp Debug out until the classlibs have one.
-//
-//+----------------------------------------------------------------------------
-FCIMPL1(void, CMessage::DebugOut, StringObject* pOutUNSAFE)
-{
- CONTRACTL
- {
- FCALL_CHECK;
- PRECONDITION(pOutUNSAFE != NULL);
- }
- CONTRACTL_END;
-
-#ifdef _DEBUG
- STRINGREF pOut = (STRINGREF) pOutUNSAFE;
- HELPER_METHOD_FRAME_BEGIN_1(pOut);
-
- static int fMessageDebugOut = 0;
-
- if (fMessageDebugOut == 0)
- fMessageDebugOut = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MessageDebugOut) ? 1 : -1;
-
- if (fMessageDebugOut == 1)
- WszOutputDebugString(pOut->GetBuffer());
-
- HELPER_METHOD_FRAME_END();
-#endif
-
- FCUnique(0x76);
-}
-FCIMPLEND
-
-//+----------------------------------------------------------------------------
-//
-// Method: CMessage::HasVarArgs public
-//
-// Synopsis: Return TRUE if the method is a VarArgs Method
-//
-//+----------------------------------------------------------------------------
-FCIMPL1(FC_BOOL_RET, CMessage::HasVarArgs, MessageObject * pMessage)
-{
- CONTRACTL
- {
- FCALL_CHECK;
- PRECONDITION(CheckPointer(pMessage));
- }
- CONTRACTL_END;
-
- BOOL result;
-
- // Need entire path to be SO_TOLERANT or put a Hard SO probe here as
- // no failure path.
- CONTRACT_VIOLATION(SOToleranceViolation);
-
- result = pMessage->GetMethodDesc()->IsVarArg();
-
- FC_RETURN_BOOL(result);
-}
-FCIMPLEND
-
-
-//static
-int CMessage::GetStackOffset (FramedMethodFrame *pFrame, ArgIterator *pArgIter, MetaSig *pSig)
-{
- CONTRACT(int)
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pFrame));
- PRECONDITION(CheckPointer(pArgIter));
- PRECONDITION(CheckPointer(pSig));
- }
- CONTRACT_END;
-
- LOG((LF_REMOTING, LL_INFO100,
- "CMessage::GetStackOffset pFrame:0x%x, pArgIter:0x%x\n",
- pFrame, pArgIter));
-
- int ret = pArgIter->GetNextOffset();
-
-#ifdef COM_STUBS_SEPARATE_FP_LOCATIONS
- int typ = pArgIter->GetArgType();
- // REVISIT_TODO do we need to handle this?
- if ((ELEMENT_TYPE_R4 == typ || ELEMENT_TYPE_R8 == typ) &&
- TransitionBlock::IsArgumentRegisterOffset(ret))
- {
- int iFPArg = TransitionBlock::GetArgumentIndexFromOffset(ret);
-
- ret = static_cast<int>(pFrame->GetFPArgOffset(iFPArg));
- }
-#endif // COM_STUBS_SEPARATE_FP_LOCATIONS
-
- RETURN ret;
-}
-
-
-//+----------------------------------------------------------------------------
-//
-// Method: CMessage::GetStackPtr private
-//
-// Synopsis: Figure out where on the stack a parameter is stored
-//
-// Parameters: ndx - the parameter index (zero-based)
-// pFrame - stack frame pointer (FramedMethodFrame)
-// pSig - method signature, used to determine parameter sizes
-//
-//
-//<REVISIT_TODO>
-// CODEWORK: Currently we assume all parameters to be 32-bit intrinsics
-// or 32-bit pointers. Value classes are not handled correctly.
-//</REVISIT_TODO>
-//+----------------------------------------------------------------------------
-PVOID CMessage::GetStackPtr(INT32 ndx, FramedMethodFrame *pFrame, MetaSig *pSig)
-{
- CONTRACT(PVOID)
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pFrame));
- PRECONDITION(CheckPointer(pSig));
- POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
- }
- CONTRACT_END;
-
- LOG((LF_REMOTING, LL_INFO100,
- "CMessage::GetStackPtr IN ndx:0x%x, pFrame:0x%x, pSig:0x%x\n",
- ndx, pFrame, pSig));
-
- ArgIterator iter(pSig);
- PVOID ret = NULL;
-
- // <REVISIT_TODO>CODEWORK:: detect and optimize for sequential access</REVISIT_TODO>
- _ASSERTE((UINT)ndx < pSig->NumFixedArgs());
- for (int i=0; i<=ndx; i++)
- ret = (BYTE*)pFrame->GetTransitionBlock() + GetStackOffset(pFrame, &iter, pSig);
-
- RETURN ret;
-}
-
-#endif //FEATURE_REMOTING
diff --git a/src/vm/mixedmode.cpp b/src/vm/mixedmode.cpp
deleted file mode 100644
index 32d4368363..0000000000
--- a/src/vm/mixedmode.cpp
+++ /dev/null
@@ -1,236 +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.
-// ===========================================================================
-// File: MIXEDMODE.CPP
-//
-
-//
-
-// MIXEDMODE deals with mixed-mode binaries support
-// ===========================================================================
-
-
-
-#include "common.h"
-
-#include "mixedmode.hpp"
-
-#include "dllimportcallback.h"
-
-#ifdef FEATURE_MIXEDMODE
-
-
-IJWNOADThunk::IJWNOADThunk(HMODULE pModulebase, DWORD dwIndex, mdToken Token)
-{
- LIMITED_METHOD_CONTRACT;
- m_pModulebase=pModulebase;
- m_dwIndex=dwIndex;
- m_Token=Token;
- m_fAccessingCache = 0;
-
- for (int i=0; i < IJWNOADThunkStubCacheSize; i++)
- {
- m_cache[i].m_AppDomainID = (ADID)-1;
- m_cache[i].m_CodeAddr = 0;
- }
-
-#ifdef _TARGET_X86_
- m_code.Encode((BYTE*)GetEEFuncEntryPoint(IJWNOADThunkJumpTarget), this);
-#else // !_TARGET_X86_
- m_code.Encode((BYTE*)GetEEFuncEntryPoint(MakeCall), this);
-#endif // !_TARGET_X86_
-};
-
-#define E_PROCESS_SHUTDOWN_REENTRY HRESULT_FROM_WIN32(ERROR_PROCESS_ABORTED)
-
-
-#ifdef _TARGET_X86_
-// Slow path lookup...called from stub
-extern "C" LPCVOID __stdcall IJWNOADThunkJumpTargetHelper(IJWNOADThunk* pThunk)
-{
- WRAPPER_NO_CONTRACT;
-
- return pThunk->FindThunkTarget();
-}
-#endif // _TARGET_X86_
-
-LPCVOID IJWNOADThunk::FindThunkTarget()
-{
- CONTRACT(LPCVOID)
- {
- INSTANCE_CHECK;
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- SO_TOLERANT;
- POSTCONDITION(CheckPointer(RETVAL));
- }
- CONTRACT_END;
-
- // We don't plan on fixing this in Whidbey...the IJW scenario has always assumed throwing is "ok" here.
- CONTRACT_VIOLATION(ThrowsViolation);
-
- LPCVOID pvTargetCode = NULL;
-
- AppDomain* pDomain;
-
- Thread* pThread = SetupThread();
-
- // Ensure that we're in preemptive mode.
- // We only need this check for a newly created
- // CLR thread - it defaults to COOP mode from here.
- GCX_PREEMP_NO_DTOR();
-
- pDomain = GetAppDomain();
-
- if (NULL == pDomain)
- {
- _ASSERTE(!"Appdomain should've been set up by SetupThread");
- pDomain = SystemDomain::System()->DefaultDomain();
- }
-
-
- if (NULL != pDomain)
- {
- // Get a local copy so we don't have to deal with a race condition.
- LPCVOID pCacheTarget = NULL;
- GetCachedInfo(pDomain->GetId(), &pvTargetCode);
-
- // Cache miss.
- if (pvTargetCode==NULL)
- {
- INSTALL_UNWIND_AND_CONTINUE_HANDLER;
- BEGIN_SO_INTOLERANT_CODE(pThread);
- {
- Module* pModule;
-
- pModule = pDomain->GetIJWModule(m_pModulebase);
- if (NULL == pModule)
- {
- // New for Whidbey: In V1.1, we just gave up and raised an exception if the target assembly wasn't already loaded
- // into the current appdomain. We now force-inject the assembly.
-
- PEAssemblyHolder pFile(pDomain->BindExplicitAssembly(m_pModulebase, FALSE));
- pDomain->LoadAssembly(NULL, pFile, FILE_ACTIVE);
-
- // Now, try the lookup again. The LoadAssembly() either worked or it didn't. If it didn't, it is probably
- // due to lack of memory and all we can do is raise an exception and hope the IJW caller does something reasonable.
- // Otherwise, we should now succeed in finding the current domain's instantiation of the target module.
- pModule = pDomain->GetIJWModule(m_pModulebase);
- }
-
- if (NULL != pModule)
- {
- pModule->EnsureActive();
-
- UMEntryThunk* pThunkTable;
-
- pThunkTable = pModule->GetADThunkTable();
- pvTargetCode = (LPVOID)GetEEFuncEntryPoint((LPVOID)pThunkTable[m_dwIndex].GetCode());
-
- // Populate the cache with our latest info.
- SetCachedInfo(pDomain->GetId(), pvTargetCode);
- }
- }
- END_SO_INTOLERANT_CODE;
- UNINSTALL_UNWIND_AND_CONTINUE_HANDLER;
- }
- }
-
- if(pvTargetCode==NULL)
- pvTargetCode=(LPVOID)GetEEFuncEntryPoint(SafeNoModule);
-
- RETURN (LPCVOID)pvTargetCode;
-}
-
-#ifdef _TARGET_X86_
-
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning (disable : 4740) // There is inline asm code in this function, which disables
- // global optimizations.
-#endif // _MSC_VER
-
-__declspec(naked) void _cdecl IJWNOADThunk::MakeCall()
-{
- WRAPPER_NO_CONTRACT;
- struct
- {
- LPVOID This;
- LPCVOID RetAddr;
- } Vars;
- #define LocalsSize 8
-
- _asm enter LocalsSize+4,0;
- _asm push ebx;
- _asm push ecx;
- _asm push edx;
- _asm push esi;
- _asm push edi;
-
- _asm mov Vars.This, eax;
-
- //careful above this point
- _ASSERTE(sizeof(Vars)<=LocalsSize);
-
- Vars.RetAddr = ((IJWNOADThunk*)Vars.This)->FindThunkTarget();
-
- _ASSERTE(NULL != Vars.RetAddr);
-
- _asm pop edi;
- _asm pop esi;
- _asm pop edx;
- _asm pop ecx;
- _asm pop ebx;
- _asm mov eax,Vars.RetAddr;
- _asm leave;
- _asm jmp eax;
-};
-
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif
-
-#elif defined(_TARGET_AMD64_)
-// Implemented in AMD64\UMThunkStub.asm
-#elif defined(_TARGET_ARM_)
-// Implemented in Arm\asmhelpers.asm
-#else
-void __cdecl IJWNOADThunk::MakeCall()
-{
- LIMITED_METHOD_CONTRACT;
- PORTABILITY_ASSERT("IJWNOADThunk::MakeCall");
-}
-#endif
-
-void IJWNOADThunk::SafeNoModule()
-{
- STATIC_CONTRACT_THROWS;
- STATIC_CONTRACT_GC_TRIGGERS;
-
- if (!CanRunManagedCode())
- {
- Thread* pThread=GetThread();
-
- // DO NOT IMPROVE THIS EXCEPTION! It cannot be a managed exception. It
- // cannot be a real exception object because we cannot execute any managed
- // code here.
- if(pThread)
- pThread->m_fPreemptiveGCDisabled = 0;
- COMPlusThrowBoot(E_PROCESS_SHUTDOWN_REENTRY);
- }
- NoModule();
-}
-
-void IJWNOADThunk::NoModule()
-{
- WRAPPER_NO_CONTRACT;
- INSTALL_UNWIND_AND_CONTINUE_HANDLER;
- //<TODO>This should give the file name as part of the exception message!</TODO>
- COMPlusThrowHR(COR_E_DLLNOTFOUND);
- UNINSTALL_UNWIND_AND_CONTINUE_HANDLER;
-}
-
-#endif // FEATURE_MIXEDMODE
-
diff --git a/src/vm/mixedmode.hpp b/src/vm/mixedmode.hpp
index 9d5037af8d..0010410f36 100644
--- a/src/vm/mixedmode.hpp
+++ b/src/vm/mixedmode.hpp
@@ -2,11 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ===========================================================================
-// File: mixedmode.H
+// File: mixedmode.hpp
//
//
-// MIXEDMODE.H defines classes to support mixed mode dlls
+// MIXEDMODE.HPP defines classes to support mixed mode dlls
// ===========================================================================
diff --git a/src/vm/mscorlib.cpp b/src/vm/mscorlib.cpp
index 5d8531ec56..53a9ec6fc1 100644
--- a/src/vm/mscorlib.cpp
+++ b/src/vm/mscorlib.cpp
@@ -31,7 +31,8 @@
#include "comdelegate.h"
#include "customattribute.h"
#include "comdynamic.h"
-#include "commethodrental.h"
+#include "excep.h"
+#include "fcall.h"
#include "nlsinfo.h"
#include "calendardata.h"
#include "commodule.h"
@@ -95,7 +96,7 @@
#include "multicorejit.h"
#endif
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) && defined(FEATURE_REFLECTION_ONLY_LOAD)
#include "clrprivtypecachereflectiononlywinrt.h"
#endif
diff --git a/src/vm/ngenoptout.cpp b/src/vm/ngenoptout.cpp
deleted file mode 100644
index 50b47782a9..0000000000
--- a/src/vm/ngenoptout.cpp
+++ /dev/null
@@ -1,12 +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.
-// ngenoptout.cpp
-//
-
-//
-//
-// Contains functionality to reject native images at runtime
-
-
-#include "common.h"
diff --git a/src/vm/ngenoptout.h b/src/vm/ngenoptout.h
deleted file mode 100644
index dbcc9b1f90..0000000000
--- a/src/vm/ngenoptout.h
+++ /dev/null
@@ -1,34 +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.
-// ngenoptout.h
-//
-
-//
-//
-// Contains functionality to reject native images at runtime
-
-
-#ifndef NGENOPTOUT_H
-#define NGENOPTOUT_H
-
-#include "assemblynamesconfigfactory.h"
-
-// throwing
-BOOL IsNativeImageOptedOut(IAssemblyName* pName);
-void AddNativeImageOptOut(IAssemblyName* pName);
-
-// HRESULT
-HRESULT RuntimeIsNativeImageOptedOut(IAssemblyName* pName);
-
-
-class NativeImageOptOutConfigFactory : public AssemblyNamesConfigFactory
-{
- virtual void AddAssemblyName(IAssemblyName* pName)
- {
- WRAPPER_NO_CONTRACT;
- AddNativeImageOptOut(pName);
- }
-};
-
-#endif // NGENOPTOUT_H
diff --git a/src/vm/objectclone.cpp b/src/vm/objectclone.cpp
deleted file mode 100644
index 93c9d3c30f..0000000000
--- a/src/vm/objectclone.cpp
+++ /dev/null
@@ -1,3861 +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.
-//
-// File: ObjectClone.cpp
-//
-
-//
-
-
-#include "common.h"
-
-#ifdef FEATURE_REMOTING
-#include "objectclone.h"
-#include "frames.h"
-#include "assembly.hpp"
-#include "field.h"
-#include "security.h"
-#include "virtualcallstub.h"
-#include "crossdomaincalls.h"
-#include "callhelpers.h"
-#include "jitinterface.h"
-#include "typestring.h"
-#include "typeparse.h"
-#include "runtimehandles.h"
-#include "appdomain.inl"
-
-// Define the following to re-enable object cloner strict mode (where we require source fields for non-optional destination fields
-// and don't attempt to load assemblies we can't find via display via partial names instead).
-//#define OBJECT_CLONER_STRICT_MODE
-
-void MakeIDeserializationCallback(OBJECTREF refTarget);
-
-MethodDesc *GetInterfaceMethodImpl(MethodTable *pMT, MethodTable *pItfMT, WORD wSlot)
-{
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- } CONTRACTL_END;
-
- MethodDesc *pMeth = NULL;
- DispatchSlot slot(pMT->FindDispatchSlot(pItfMT->GetTypeID(), (UINT32)wSlot));
- CONSISTENCY_CHECK(!slot.IsNull());
- pMeth = slot.GetMethodDesc();
- return pMeth;
-}
-
-// Given a FieldDesc which may be representative and an object which contains said field, return the actual type of the field. This
-// works even when called from a different appdomain from which the type was loaded (though naturally it is the caller's
-// responsbility to ensure such an appdomain cannot be unloaded during the processing of this method).
-TypeHandle LoadExactFieldType(FieldDesc *pFD, OBJECTREF orefParent, AppDomain *pDomain)
-{
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- } CONTRACTL_END;
-
- MethodTable *pEnclosingMT = orefParent->GetMethodTable();
-
- // Set up a field signature with the owning type providing a type context for any type variables.
- MetaSig sig(pFD, TypeHandle(pEnclosingMT));
- sig.NextArg();
-
- // If the enclosing type is resident to this domain or domain neutral and loaded in this domain then we can simply go get it.
- // The logic is trickier (and more expensive to calculate) for generic types, so skip the optimization there.
- if (pEnclosingMT->GetDomain() == GetAppDomain() ||
- (pEnclosingMT->IsDomainNeutral() &&
- !pEnclosingMT->HasInstantiation() &&
- pEnclosingMT->GetAssembly()->FindDomainAssembly(GetAppDomain())))
- return sig.GetLastTypeHandleThrowing();
-
- TypeHandle retTH;
-
- // Otherwise we have to do this the expensive way -- switch to the home domain for the type lookup.
- ENTER_DOMAIN_PTR(pDomain, ADV_RUNNINGIN);
- retTH = sig.GetLastTypeHandleThrowing();
- END_DOMAIN_TRANSITION;
-
- return retTH;
-}
-
-extern TypeHandle GetTypeByName( _In_opt_z_ LPUTF8 szFullClassName,
- BOOL bThrowOnError,
- BOOL bIgnoreCase,
- StackCrawlMark *stackMark,
- BOOL *pbAssemblyIsLoading);
-
-#ifndef DACCESS_COMPILE
-#define CUSTOM_GCPROTECT_BEGIN(context) do { \
- FrameWithCookie<GCSafeCollectionFrame> __gcframe(context); \
- /* work around unreachable code warning */ \
- if (true) { DEBUG_ASSURE_NO_RETURN_BEGIN(GCPROTECT)
-
-#define CUSTOM_GCPROTECT_END() \
- DEBUG_ASSURE_NO_RETURN_END(GCPROTECT) } \
- __gcframe.Pop(); } while(0)
-
-#else // #ifndef DACCESS_COMPILE
-
-#define CUSTOM_GCPROTECT_BEGIN(context)
-#define CUSTOM_GCPROTECT_END()
-
-#endif // #ifndef DACCESS_COMPILE
-
-int GCSafeObjectHashTable::HasID(OBJECTREF refObj, OBJECTREF *newObj)
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- THROWS;
- GC_NOTRIGGER;
- }
- CONTRACTL_END
-
- BOOL seenBefore = FALSE;
- *newObj = NULL;
- int index = FindElement(refObj, seenBefore);
-
- if (seenBefore)
- {
- _ASSERTE(index < (int)m_currArraySize);
- *newObj = m_newObjects[index];
- return m_ids[index];
- }
-
- return -1;
-}
-
-// returns the object id
-int GCSafeObjectHashTable::AddObject(OBJECTREF refObj, OBJECTREF newObj)
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- THROWS;
- GC_NOTRIGGER;
- }
- CONTRACTL_END
-
- int index = -1;
- GCPROTECT_BEGIN(refObj);
- GCPROTECT_BEGIN(newObj);
-
- if (m_count > m_currArraySize / 2)
- {
- Resize();
- }
-
- BOOL seenBefore = FALSE;
- index = FindElement(refObj, seenBefore);
-
- _ASSERTE(index >= 0 && index < (int)m_currArraySize);
- if (seenBefore)
- {
- _ASSERTE(!"Adding an object thats already present");
- }
- else
- {
- m_objects[index] = refObj;
- m_newObjects[index] = newObj;
- m_ids[index] = ++m_count;
- }
-
- GCPROTECT_END();
- GCPROTECT_END();
-
- return m_ids[index];
-}
-
-// returns the object id
-int GCSafeObjectHashTable::UpdateObject(OBJECTREF refObj, OBJECTREF newObj)
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- THROWS;
- GC_NOTRIGGER;
- }
- CONTRACTL_END
-
- int index = -1;
- GCPROTECT_BEGIN(refObj);
- GCPROTECT_BEGIN(newObj);
-
- BOOL seenBefore = FALSE;
- index = FindElement(refObj, seenBefore);
-
- _ASSERTE(index >= 0 && index < (int)m_currArraySize);
- if (!seenBefore)
- {
- _ASSERTE(!"An object has to exist in the table, to update it");
- }
- else
- {
- _ASSERTE(m_objects[index] == refObj);
- m_newObjects[index] = newObj;
- }
-
- GCPROTECT_END();
- GCPROTECT_END();
-
- return m_ids[index];
-}
-
-// returns index into array where obj was found or will fit in
-int GCSafeObjectHashTable::FindElement(OBJECTREF refObj, BOOL &seenBefore)
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- THROWS;
- GC_NOTRIGGER;
- }
- CONTRACTL_END
-
- int currentNumBuckets = m_currArraySize / NUM_SLOTS_PER_BUCKET;
- int hashcode = 0;
- GCPROTECT_BEGIN(refObj);
- hashcode = refObj->GetHashCodeEx();
- GCPROTECT_END();
-
- hashcode &= 0x7FFFFFFF; // ignore sign bit
- int hashIncrement = (1+((hashcode)%(currentNumBuckets-2)));
-#ifdef _DEBUG
- int numLoops = 0;
-#endif
-
- do
- {
- int index = ((unsigned)hashcode % currentNumBuckets) * NUM_SLOTS_PER_BUCKET;
- _ASSERTE(index >= 0 && index < (int)m_currArraySize);
- for (int i = index; i < index + NUM_SLOTS_PER_BUCKET; i++)
- {
- if (m_objects[i] == refObj)
- {
- seenBefore = TRUE;
- return i;
- }
-
- if (m_objects[i] == NULL)
- {
- seenBefore = FALSE;
- return i;
- }
- }
- hashcode += hashIncrement;
-#ifdef _DEBUG
- if (++numLoops > currentNumBuckets)
- _ASSERTE(!"Looped too many times, trying to find object in hashtable. If hitting ignore doesnt seem to help, then contact Ashok");
-#endif
- }while (true);
-
- _ASSERTE(!"Not expected to reach here in GCSafeObjectHashTable::FindElement");
- return -1;
-}
-
-void GCSafeObjectHashTable::Resize()
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- THROWS;
- GC_NOTRIGGER;
- }
- CONTRACTL_END
- // Allocate new space
- DWORD newSize = m_currArraySize * 2;
- for (int i = 0; (DWORD) i < sizeof(g_rgPrimes)/sizeof(DWORD); i++)
- {
- if (g_rgPrimes[i] > newSize)
- {
- newSize = g_rgPrimes[i];
- break;
- }
- }
-
- newSize *= NUM_SLOTS_PER_BUCKET;
- NewArrayHolder<OBJECTREF> refTemp (new OBJECTREF[newSize]);
- ZeroMemory((void *)refTemp, sizeof(OBJECTREF) * newSize);
-
- NewArrayHolder<OBJECTREF> refTempNewObj (new OBJECTREF[newSize]);
-#ifdef USE_CHECKED_OBJECTREFS
- ZeroMemory((void *)refTempNewObj, sizeof(OBJECTREF) * newSize);
-#endif
-
- NewArrayHolder<int> bTemp (new int[newSize]);
- ZeroMemory((void *)bTemp, sizeof(int) * newSize);
-
- // Copy over objects and data
- NewArrayHolder<OBJECTREF> refOldObj (m_objects);
- NewArrayHolder<OBJECTREF> refOldNewObj (m_newObjects);
- NewArrayHolder<int> oldIds (m_ids);
- DWORD oldArrSize = m_currArraySize;
-
- if (oldIds == (int *)&m_dataOnStack[0])
- {
- refOldObj.SuppressRelease();
- refOldNewObj.SuppressRelease();
- oldIds.SuppressRelease();
- }
-
- refTemp.SuppressRelease();
- refTempNewObj.SuppressRelease();
- bTemp.SuppressRelease();
-
- m_ids = bTemp;
- m_objects = refTemp;
- m_newObjects = refTempNewObj;
- m_currArraySize = newSize;
-
- for (DWORD i = 0; i < oldArrSize; i++)
- {
- if (refOldObj[i] == NULL)
- continue;
-
- BOOL seenBefore = FALSE;
- int newIndex = FindElement(refOldObj[i], seenBefore);
-
- if (!seenBefore)
- {
- _ASSERTE(newIndex < (int)m_currArraySize);
- m_objects[newIndex] = refOldObj[i];
- m_newObjects[newIndex] = refOldNewObj[i];
- m_ids[newIndex] = oldIds[i];
- }
- else
- _ASSERTE(!"Object seen twice while rehashing");
- }
-
-#ifdef USE_CHECKED_OBJECTREFS
- for(DWORD i = 0; i < m_currArraySize; i++)
- Thread::ObjectRefProtected(&m_objects[i]);
- for(DWORD i = 0; i < m_currArraySize; i++)
- Thread::ObjectRefProtected(&m_newObjects[i]);
-#endif
-
-}
-
-void GCSafeObjectTable::Push(OBJECTREF refObj, OBJECTREF refParent, OBJECTREF refAux, QueuedObjectInfo * pQOI)
-{
- CONTRACTL
- {
- THROWS;
- MODE_COOPERATIVE;
- GC_NOTRIGGER;
- }
- CONTRACTL_END
- _ASSERTE(refObj != NULL);
- _ASSERTE(m_QueueType == LIFO_QUEUE);
- _ASSERTE(m_head == 0 && m_dataHead == 0);
-
- // First find the size of the object info
- DWORD size = pQOI->GetSize();
-
- // Check if resize is needed
- EnsureSize(size);
-
- // Push on the stack, first the objects
- DWORD index = m_count;
- if (m_Objects1)
- m_Objects1[index] = refObj;
-#ifdef _DEBUG
- else
- _ASSERTE(refObj == NULL);
-#endif
- if (m_Objects2)
- m_Objects2[index] = refParent;
-#ifdef _DEBUG
- else
- _ASSERTE(refParent == NULL);
-#endif
- if (m_Objects3)
- m_Objects3[index] = refAux;
-#ifdef _DEBUG
- else
- _ASSERTE(refAux == NULL);
-#endif
-
- // then the info
- if (m_dataIndices)
- m_dataIndices[index] = m_numDataBytes;
- BYTE *pData = &m_data[m_numDataBytes];
- memcpy(pData, (VOID*)pQOI, size);
-
- m_numDataBytes += size;
- m_count++;
-}
-
-OBJECTREF GCSafeObjectTable::Pop(OBJECTREF *refParent, OBJECTREF *refAux, QueuedObjectInfo ** pQOI)
-{
- LIMITED_METHOD_CONTRACT;
- _ASSERTE(m_QueueType == LIFO_QUEUE);
- _ASSERTE(m_head == 0 && m_dataHead == 0);
- _ASSERTE(m_dataIndices != NULL);
-
- *pQOI = NULL;
- OBJECTREF refRet = NULL;
- *refParent = NULL;
- *refAux = NULL;
- if (m_count == 0)
- return NULL;
-
- m_count--;
- refRet = m_Objects1[m_count];
- if (m_Objects2)
- *refParent = m_Objects2[m_count];
- if (m_Objects3)
- *refAux = m_Objects3[m_count];
- *pQOI = (QueuedObjectInfo *) &m_data[m_dataIndices[m_count]];
-
- m_numDataBytes -= (*pQOI)->GetSize();
- return refRet;
-}
-
-void GCSafeObjectTable::SetAt(DWORD index, OBJECTREF refObj, OBJECTREF refParent, OBJECTREF refAux, QueuedObjectInfo * pQOI)
-{
- CONTRACTL
- {
- THROWS;
- MODE_COOPERATIVE;
- GC_NOTRIGGER;
- }
- CONTRACTL_END
- _ASSERTE(refObj != NULL);
-#ifdef _DEBUG
- if (m_QueueType == LIFO_QUEUE)
- _ASSERTE(index >= 0 && index < m_count);
- else
- _ASSERTE(index < m_currArraySize);
-#endif
-
- // First find the size of the object info
- DWORD size = pQOI->GetSize();
-
- // Push on the stack, first the objects
- m_Objects1[index] = refObj;
- if (m_Objects2)
- m_Objects2[index] = refParent;
- if (m_Objects3)
- m_Objects3[index] = refAux;
-
- // then the info
- _ASSERTE(m_dataIndices != NULL);
-
- QueuedObjectInfo *pData = (QueuedObjectInfo *)&m_data[m_dataIndices[index]];
- _ASSERTE(pData->GetSize() == size);
-
- memcpy(pData, (VOID*)pQOI, size);
-}
-
-OBJECTREF GCSafeObjectTable::GetAt(DWORD index, OBJECTREF *refParent, OBJECTREF *refAux, QueuedObjectInfo ** pQOI)
-{
- LIMITED_METHOD_CONTRACT;
-#ifdef _DEBUG
- if (m_QueueType == LIFO_QUEUE)
- _ASSERTE(index >= 0 && index < m_count);
- else
- _ASSERTE(index < m_currArraySize);
-#endif
-
- OBJECTREF refRet = m_Objects1[index];
- if (m_Objects2)
- *refParent = m_Objects2[index];
- else
- *refParent = NULL;
- if (m_Objects3)
- *refAux = m_Objects3[index];
- else
- *refAux = NULL;
-
- _ASSERTE(m_dataIndices != NULL);
-
- *pQOI = (QueuedObjectInfo *) &m_data[m_dataIndices[index]];
-
- return refRet;
-}
-
-void GCSafeObjectTable::Enqueue(OBJECTREF refObj, OBJECTREF refParent, OBJECTREF refAux, QueuedObjectInfo *pQOI)
-{
- CONTRACTL
- {
- THROWS;
- MODE_COOPERATIVE;
- GC_NOTRIGGER;
- }
- CONTRACTL_END
-
- _ASSERTE(refObj != NULL);
- _ASSERTE(m_QueueType == FIFO_QUEUE);
-
- // First find the size of the object info
- DWORD size = pQOI ? pQOI->GetSize() : 0;
-
- // Check if resize is needed
- EnsureSize(size);
-
- // Append to queue, first the objects
- DWORD index = (m_head + m_count) % m_currArraySize;
- m_Objects1[index] = refObj;
- if (m_Objects2)
- m_Objects2[index] = refParent;
- if (m_Objects3)
- m_Objects3[index] = refAux;
-
- // then the info
- if (pQOI)
- {
- DWORD dataIndex = (m_dataHead + m_numDataBytes) % (m_currArraySize * MAGIC_FACTOR);
- BYTE *pData = &m_data[dataIndex];
- memcpy(pData, (VOID*)pQOI, size);
-
- if (m_dataIndices)
- m_dataIndices[index] = dataIndex;
- m_numDataBytes += size;
- }
-
- m_count++;
-}
-
-OBJECTREF GCSafeObjectTable::Dequeue(OBJECTREF *refParent, OBJECTREF *refAux, QueuedObjectInfo ** pQOI)
-{
- LIMITED_METHOD_CONTRACT;
-
- _ASSERTE(m_QueueType == FIFO_QUEUE);
-
- if (pQOI)
- *pQOI = NULL;
- OBJECTREF refRet = NULL;
- *refParent = NULL;
- *refAux = NULL;
- if (m_count == 0)
- return NULL;
-
- refRet = m_Objects1[m_head];
- if (m_Objects2)
- *refParent = m_Objects2[m_head];
- if (m_Objects3)
- *refAux = m_Objects3[m_head];
-
- if (pQOI)
- {
- *pQOI = (QueuedObjectInfo *) &m_data[m_dataHead];
-
- m_dataHead = (m_dataHead + (*pQOI)->GetSize()) % (m_currArraySize * MAGIC_FACTOR);
-
- m_numDataBytes -= (*pQOI)->GetSize();
- }
-
- m_head = (m_head + 1) % m_currArraySize;
- m_count--;
- return refRet;
-}
-
-OBJECTREF GCSafeObjectTable::Peek(OBJECTREF *refParent, OBJECTREF *refAux, QueuedObjectInfo **pQOI)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
-
- *pQOI = NULL;
- *refParent = NULL;
- *refAux = NULL;
- if (m_count == 0)
- return NULL;
-
- DWORD indexToPeek;
- if (m_QueueType == LIFO_QUEUE)
- {
- indexToPeek = m_count;
- return GetAt(indexToPeek, refParent, refAux, pQOI);
- }
- else
- {
- indexToPeek = m_head;
- if (m_Objects2)
- *refParent = m_Objects2[m_head];
- if (m_Objects3)
- *refParent = m_Objects3[m_head];
- *pQOI = (QueuedObjectInfo *) &m_data[m_dataHead];
- return m_Objects1[m_head];
- }
-
-}
-
-void GCSafeObjectTable::EnsureSize(DWORD requiredDataSize)
-{
- CONTRACTL
- {
- THROWS;
- MODE_COOPERATIVE;
- GC_NOTRIGGER;
- }
- CONTRACTL_END
- // Check if the object queue is sized enough
- if (m_count == m_currArraySize)
- {
- Resize();
- return;
- }
-
- // Check if the data array size is enough
- if (m_numDataBytes + requiredDataSize > m_currArraySize * MAGIC_FACTOR)
- {
- Resize();
- return;
- }
-
- if (m_QueueType == FIFO_QUEUE)
- {
- // Will current QueuedObjectInfo go beyond the edge of the array ?
- if (m_dataHead + m_numDataBytes + requiredDataSize > m_currArraySize * MAGIC_FACTOR)
- {
- Resize();
- return;
- }
- }
-}
-
-void GCSafeObjectTable::Resize()
-{
- CONTRACTL
- {
- THROWS;
- MODE_COOPERATIVE;
- GC_NOTRIGGER;
- }
- CONTRACTL_END
- // Allocate new space
- DWORD newSize = m_currArraySize * 2;
- NewArrayHolder<OBJECTREF> refTemp (NULL);
- NewArrayHolder<OBJECTREF> refParentTemp (NULL);
- NewArrayHolder<OBJECTREF> refAuxTemp (NULL);
-
- refTemp = new OBJECTREF[newSize];
- if (m_Objects2)
- refParentTemp = new OBJECTREF[newSize];
- if (m_Objects3)
- refAuxTemp = new OBJECTREF[newSize];
-
-#ifdef USE_CHECKED_OBJECTREFS
- ZeroMemory((void *)refTemp, sizeof(OBJECTREF) * newSize);
- if (m_Objects2)
- ZeroMemory((void *)refParentTemp, sizeof(OBJECTREF) * newSize);
- if (m_Objects3)
- ZeroMemory((void *)refAuxTemp, sizeof(OBJECTREF) * newSize);
-#endif
-
- NewArrayHolder<BYTE> bTemp (NULL);
- NewArrayHolder<DWORD> dwIndicesTemp (NULL);
-
- bTemp = new BYTE[newSize * MAGIC_FACTOR];
- if (m_dataIndices)
- dwIndicesTemp = new DWORD[newSize];
-
- // Copy over objects and data
- if (m_QueueType == LIFO_QUEUE || (m_QueueType == FIFO_QUEUE && m_head == 0))
- {
- void *pSrc = (void *)&m_Objects1[0];
- void *pDest = (void *)&refTemp[0];
- memcpyUnsafe(pDest, pSrc, m_count * sizeof(OBJECTREF));
-
- if (m_Objects2)
- {
- pSrc = (void *)&m_Objects2[0];
- pDest = (void *)&refParentTemp[0];
- memcpyUnsafe(pDest, pSrc, m_count * sizeof(OBJECTREF));
- }
-
- if (m_Objects3)
- {
- pSrc = (void *)&m_Objects3[0];
- pDest = (void *)&refAuxTemp[0];
- memcpyUnsafe(pDest, pSrc, m_count * sizeof(OBJECTREF));
- }
-
- pSrc = (void *)&m_data[0];
- pDest = (void *)&bTemp[0];
- memcpyNoGCRefs(pDest, pSrc, m_numDataBytes);
-
- if (m_dataIndices)
- {
- pSrc = (void *)&m_dataIndices[0];
- pDest = (void *)&dwIndicesTemp[0];
- memcpyNoGCRefs(pDest, pSrc, m_count * sizeof(DWORD));
- }
-
- }
- else
- {
- _ASSERTE(m_QueueType == FIFO_QUEUE && m_head != 0);
- _ASSERTE(m_currArraySize > m_head);
- DWORD numObjRefsToCopy = (m_count > m_currArraySize - m_head ? m_currArraySize - m_head : m_count);
-
- void *pSrc = (void *)&m_Objects1[m_head];
- void *pDest = (void *)&refTemp[0];
- memcpyUnsafe(pDest, pSrc, numObjRefsToCopy * sizeof(OBJECTREF));
- pSrc = (void *)&m_Objects1[0];
- pDest = (void *)&refTemp[numObjRefsToCopy];
- memcpyUnsafe(pDest, pSrc, (m_count - numObjRefsToCopy) * sizeof(OBJECTREF));
-
- if (m_Objects2)
- {
- pSrc = (void *)&m_Objects2[m_head];
- pDest = (void *)&refParentTemp[0];
- memcpyUnsafe(pDest, pSrc, numObjRefsToCopy * sizeof(OBJECTREF));
- pSrc = (void *)&m_Objects2[0];
- pDest = (void *)&refParentTemp[numObjRefsToCopy];
- memcpyUnsafe(pDest, pSrc, (m_count - numObjRefsToCopy) * sizeof(OBJECTREF));
- }
-
- if (m_Objects3)
- {
- pSrc = (void *)&m_Objects3[m_head];
- pDest = (void *)&refAuxTemp[0];
- memcpyUnsafe(pDest, pSrc, numObjRefsToCopy * sizeof(OBJECTREF));
- pSrc = (void *)&m_Objects3[0];
- pDest = (void *)&refAuxTemp[numObjRefsToCopy];
- memcpyUnsafe(pDest, pSrc, (m_count - numObjRefsToCopy) * sizeof(OBJECTREF));
- }
-
- if (m_dataIndices)
- {
- pSrc = (void *)&m_dataIndices[m_head];
- pDest = (void *)&dwIndicesTemp[0];
- memcpyUnsafe(pDest, pSrc, numObjRefsToCopy * sizeof(DWORD));
- pSrc = (void *)&m_dataIndices[0];
- pDest = (void *)&dwIndicesTemp[numObjRefsToCopy];
- memcpyUnsafe(pDest, pSrc, (m_count - numObjRefsToCopy) * sizeof(DWORD));
- }
-
- DWORD numBytesToCopy = (m_numDataBytes > ((m_currArraySize * MAGIC_FACTOR) - m_dataHead) ? ((m_currArraySize * MAGIC_FACTOR) - m_dataHead) : m_numDataBytes);//(m_currArraySize * MAGIC_FACTOR) - m_dataHead;
- memcpyNoGCRefs((void *)bTemp, (void *) &m_data[m_dataHead], numBytesToCopy);
- memcpyNoGCRefs((void *) &bTemp[numBytesToCopy], (void *)m_data, (m_numDataBytes - numBytesToCopy));
- }
-
- // Delete old allocation
- if (m_usingHeap)
- {
- delete[] m_data;
- delete[] m_Objects1;
- delete[] m_Objects2;
- delete[] m_Objects3;
- delete[] m_dataIndices;
- }
-
- refTemp.SuppressRelease();
- refParentTemp.SuppressRelease();
- refAuxTemp.SuppressRelease();
- dwIndicesTemp.SuppressRelease();
- bTemp.SuppressRelease();
-
- m_currArraySize = newSize;
- m_Objects1 = refTemp;
- m_Objects2 = refParentTemp;
- m_Objects3 = refAuxTemp;
- m_dataIndices = dwIndicesTemp;
- m_data = bTemp;
- m_head = 0;
- m_dataHead = 0;
-
- m_usingHeap = TRUE;
-#ifdef USE_CHECKED_OBJECTREFS
- for(DWORD i = 0; i < m_currArraySize; i++)
- {
- Thread::ObjectRefProtected(&m_Objects1[i]);
- if (m_Objects2)
- Thread::ObjectRefProtected(&m_Objects2[i]);
- if (m_Objects3)
- Thread::ObjectRefProtected(&m_Objects3[i]);
- }
-#endif
-}
-
-
-VOID GCScanRootsInCollection(promote_func *fn, ScanContext* sc, void *context)
-{
- STATIC_CONTRACT_SO_TOLERANT;
- GCSafeCollection *pObjCollection = (GCSafeCollection *)context;
- pObjCollection->ReportGCRefs(fn, sc);
-}
-
-VOID
-BeginCloning(ObjectClone *pOC)
-{
- pOC->Init(FALSE);
-}
-
-VOID
-EndCloning(ObjectClone *pOC)
-{
- pOC->Cleanup(FALSE);
-}
-
-typedef Holder<ObjectClone*, BeginCloning, EndCloning> ObjectCloneHolder;
-
-
-OBJECTREF ObjectClone::Clone(OBJECTREF refObj, TypeHandle expectedType, AppDomain* fromDomain, AppDomain* toDomain, OBJECTREF refExecutionContext)
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- THROWS;
- GC_TRIGGERS;
- }
- CONTRACTL_END
-
- if (refObj == NULL)
- return NULL;
-
- if (m_context != ObjectFreezer && refObj->GetMethodTable() == g_pStringClass)
- return refObj;
-
- ObjectCloneHolder ocHolder(this);
-
- m_fromDomain = fromDomain;
- m_toDomain = toDomain;
-
- m_currObject = refObj;
- GCPROTECT_BEGIN(m_currObject);
- m_topObject = NULL;
- GCPROTECT_BEGIN(m_topObject);
- m_fromExecutionContext = refExecutionContext;
- GCPROTECT_BEGIN(m_fromExecutionContext);
-
- // Enter the domain we're cloning into, if we're not already there
- ENTER_DOMAIN_PTR(toDomain,ADV_RUNNINGIN);
-
- if (!m_securityChecked)
- {
- Security::SpecialDemand(SSWT_DEMAND_FROM_NATIVE, SECURITY_SERIALIZATION);
- m_securityChecked = TRUE;
- }
-
-#ifdef _DEBUG
- DefineFullyQualifiedNameForClass();
- LOG((LF_REMOTING, LL_INFO100, "Clone. Cloning instance of type %s.\n",
- GetFullyQualifiedNameForClassNestedAware(m_currObject->GetMethodTable())));
-#endif
-
- m_newObject = NULL;
- GCPROTECT_BEGIN(m_newObject);
- PTRARRAYREF refValues = NULL;
- GCPROTECT_BEGIN(refValues);
- OBJECTREF refParent = NULL;
- GCPROTECT_BEGIN(refParent);
-
- QueuedObjectInfo *currObjFixupInfo = NULL;
- // For some dynamically sized stack objects
- void *pTempStackSpace = NULL;
- DWORD dwCurrStackSpaceSize = 0;
-
- // Initialize QOM
- QueuedObjectInfo topObj;
- OBJECTREF dummy1, dummy2;
- QOM.Enqueue(m_currObject, NULL, NULL, (QueuedObjectInfo *)&topObj);
-
- while ((m_currObject = QOM.Dequeue(&dummy1, &dummy2, &currObjFixupInfo)) != NULL)
- {
- m_newObject = NULL;
- MethodTable *newMT = NULL;
-
- BOOL repeatObject = FALSE;
- BOOL isISerializable = FALSE, isIObjRef = FALSE, isBoxed = FALSE;
- DWORD ISerializableTSOIndex = (DWORD) -1;
- DWORD IObjRefTSOIndex = (DWORD) -1;
- DWORD BoxedValTSOIndex = (DWORD) -1;
- m_skipFieldScan = FALSE;
-
- // ALLOCATE PHASE
-
- // Was currObject seen before ?
- int currID = TOS.HasID(m_currObject, &m_newObject);
- if (currID != -1)
- {
- // Yes
- repeatObject = TRUE;
- m_skipFieldScan = TRUE;
- newMT = m_newObject->GetMethodTable();
-
- if (m_cbInterface->IsISerializableType(newMT))
- {
- currObjFixupInfo->SetIsISerializableInstance();
- isISerializable = TRUE;
- ISerializableTSOIndex = FindObjectInTSO(currID, ISerializable);
- }
-
-#ifdef _DEBUG
- LOG((LF_REMOTING, LL_INFO1000, "Clone. Object of type %s with id %d seen before.\n",
- GetFullyQualifiedNameForClassNestedAware(m_currObject->GetMethodTable()), currID));
-#endif
- }
- else
- {
-#ifdef _DEBUG
- LOG((LF_REMOTING, LL_INFO1000, "Clone. Object of type %s not seen before.\n",
- GetFullyQualifiedNameForClassNestedAware(m_currObject->GetMethodTable())));
-#endif
- // No
- MethodTable *currMT = m_currObject->GetMethodTable();
-
- // Check whether object is serializable
- m_cbInterface->ValidateFromType(currMT);
-
- // Add current object to table of seen objects and get an id
- currID = TOS.AddObject(m_currObject, m_newObject);
- LOG((LF_REMOTING, LL_INFO1000, "Clone. Current object added to Table of Objects Seen. Given id %d.\n", currID));
-
- if ( m_cbInterface->IsRemotedType(currMT, m_fromDomain, m_toDomain))
- {
- refValues = AllocateISerializable(currID, TRUE);
- isISerializable = TRUE;
- ISerializableTSOIndex = TSO.GetCount() - 1;
- currObjFixupInfo->SetIsISerializableInstance();
- if (refValues == NULL)
- {
- // We found a smugglable objref. No field scanning needed
- m_skipFieldScan = TRUE;
- }
- }
- else if( m_cbInterface->IsISerializableType(currMT))
- {
- InvokeVtsCallbacks(m_currObject, RemotingVtsInfo::VTS_CALLBACK_ON_SERIALIZING, fromDomain);
- if (HasVtsCallbacks(m_currObject->GetMethodTable(), RemotingVtsInfo::VTS_CALLBACK_ON_SERIALIZED))
- VSC.Enqueue(m_currObject, NULL, NULL, NULL);
-
- refValues = AllocateISerializable(currID, FALSE);
- isISerializable = TRUE;
- ISerializableTSOIndex = TSO.GetCount() - 1;
- currObjFixupInfo->SetIsISerializableInstance();
- }
- else if (currMT->IsArray())
- {
- AllocateArray();
- }
- else
- {
- // This is a regular object
- InvokeVtsCallbacks(m_currObject, RemotingVtsInfo::VTS_CALLBACK_ON_SERIALIZING, fromDomain);
- if (HasVtsCallbacks(m_currObject->GetMethodTable(), RemotingVtsInfo::VTS_CALLBACK_ON_SERIALIZED))
- VSC.Enqueue(m_currObject, NULL, NULL, NULL);
-
- AllocateObject();
-
- if (m_cbInterface->IsISerializableType(m_newObject->GetMethodTable()))
- {
- // We have a situation where the serialized instnce was not ISerializable,
- // but the target instance is. So we make the from object look like a ISerializable
- refValues = MakeObjectLookLikeISerializable(currID);
- isISerializable = TRUE;
- ISerializableTSOIndex = TSO.GetCount() - 1;
- currObjFixupInfo->SetIsISerializableInstance();
- }
- }
-
- _ASSERTE(m_newObject != NULL);
- newMT = m_newObject->GetMethodTable();
-
- // Check whether new object is serializable
- m_cbInterface->ValidateToType(newMT);
-
- // Update the TOS, to include the new object
- int retId;
- retId = TOS.UpdateObject(m_currObject, m_newObject);
- _ASSERTE(retId == currID);
- }
- _ASSERTE(m_newObject != NULL);
-
- // FIXUP PHASE
- // Get parent to be fixed up
- ParentInfo *parentInfo;
- refParent = QOF.Peek(&dummy1, &dummy2, (QueuedObjectInfo **)&parentInfo);
- MethodTable *pParentMT = NULL;
-
- if (refParent == NULL)
- {
- LOG((LF_REMOTING, LL_INFO1000, "Clone. No parent found. This is the top object.\n"));
- // This is the top object
- _ASSERTE(m_topObject == NULL);
- m_topObject = m_newObject;
- }
- else
- {
-#ifdef _DEBUG
- LOG((LF_REMOTING, LL_INFO1000, "Clone. Parent is of type %s.\n",
- GetFullyQualifiedNameForClassNestedAware(m_currObject->GetMethodTable())));
-#endif
- pParentMT = refParent->GetMethodTable();
- }
-
- if (IsDelayedFixup(newMT, currObjFixupInfo))
- {
- // New object is IObjRef or a boxed object
- if (m_cbInterface->IsIObjectReferenceType(newMT))
- {
- LOG((LF_REMOTING, LL_INFO1000, "Clone. This is an IObjectReference. Delaying fixup.\n"));
- DWORD size = sizeof(IObjRefInstanceInfo) + (currObjFixupInfo ? currObjFixupInfo->GetSize() : 0);
- if (size > dwCurrStackSpaceSize)
- {
- pTempStackSpace = _alloca(size);
- dwCurrStackSpaceSize = size;
- }
- IObjRefInstanceInfo *pIORInfo = new (pTempStackSpace) IObjRefInstanceInfo(currID, 0, 0);
- if (currObjFixupInfo)
- pIORInfo->SetFixupInfo(currObjFixupInfo);
- // Check if this instance is ISerializable also
- if (isISerializable)
- {
- LOG((LF_REMOTING, LL_INFO1000, "Clone. This is also an ISerializable type at index %d in TSO.\n", ISerializableTSOIndex));
- _ASSERTE(ISerializableTSOIndex != (DWORD) -1);
- pIORInfo->SetISerTSOIndex(ISerializableTSOIndex);
- }
-
- if (repeatObject)
- pIORInfo->SetIsRepeatObject();
-
- // Add to TSO
- TSO.Push(m_newObject, m_currObject, refParent, pIORInfo);
-
- isIObjRef = TRUE;
- IObjRefTSOIndex = TSO.GetCount() - 1;
-
- LOG((LF_REMOTING, LL_INFO1000, "Clone. Added to TSO at index %d.\n", IObjRefTSOIndex));
- // Any special object parent, would wait till the current object is resolved
- if (parentInfo)
- {
- parentInfo->IncrementSpecialMembers();
- TMappings.Add(IObjRefTSOIndex);
- }
-
- }
- if (currObjFixupInfo->NeedsUnboxing())
- {
- LOG((LF_REMOTING, LL_INFO1000, "Clone. This is a boxed value type. Delaying fixup.\n"));
- DWORD size = sizeof(ValueTypeInfo) + currObjFixupInfo->GetSize();
- if (size > dwCurrStackSpaceSize)
- {
- pTempStackSpace = _alloca(size);
- dwCurrStackSpaceSize = size;
- }
- ValueTypeInfo *valInfo = new (pTempStackSpace) ValueTypeInfo(currID, currObjFixupInfo);
- // If the value type is also ISer or IObj, then it has to wait till those interfaces are addressed
- if (isISerializable)
- {
- LOG((LF_REMOTING, LL_INFO1000, "Clone. This is also an ISerializable type at index %d in TSO.\n", ISerializableTSOIndex));
- valInfo->SetISerTSOIndex(ISerializableTSOIndex);
- }
- if (isIObjRef)
- {
- LOG((LF_REMOTING, LL_INFO1000, "Clone. This is also an IObjectReference type at index %d in TSO.\n", IObjRefTSOIndex));
- valInfo->SetIObjRefTSOIndex(IObjRefTSOIndex);
- }
-
- // Add to TSO
- TSO.Push(m_newObject, refParent, NULL, valInfo);
-
- isBoxed = TRUE;
- BoxedValTSOIndex = TSO.GetCount() - 1;
-
- LOG((LF_REMOTING, LL_INFO1000, "Clone. Added to TSO at index %d.\n", BoxedValTSOIndex));
- // An IObjRef parent, or a parent itself boxed, would wait till the current object is resolved
- if (parentInfo && (parentInfo->NeedsUnboxing() || parentInfo->IsIObjRefInstance()))
- {
- parentInfo->IncrementSpecialMembers();
- TMappings.Add(BoxedValTSOIndex);
- }
- }
- }
-
- if (refParent != NULL)
- {
- if (!IsDelayedFixup(newMT, currObjFixupInfo))
- Fixup(m_newObject, refParent, currObjFixupInfo);
-
- // If currObj is ISer, then an IObjRef parent would wait till the current object is resolved
- if (currObjFixupInfo->IsISerializableInstance() &&
- parentInfo->IsIObjRefInstance())
- {
- parentInfo->IncrementSpecialMembers();
- TMappings.Add(ISerializableTSOIndex);
- }
- }
-
- // If we are done with this parent, remove it from QOF
- if (parentInfo && parentInfo->DecrementFixupCount() == 0)
- {
- LOG((LF_REMOTING, LL_INFO1000, "Clone. All children fixed up. Removing parent from QOF.\n", BoxedValTSOIndex));
- LOG((LF_REMOTING, LL_INFO1000, "Clone. Parent has %d special member objects.\n", parentInfo->GetNumSpecialMembers()));
- OBJECTREF refTemp;
- ParentInfo *pFITemp;
- refTemp = QOF.Dequeue(&dummy1, &dummy2, (QueuedObjectInfo **)&pFITemp);
- _ASSERTE(refTemp == refParent);
- _ASSERTE(pFITemp == parentInfo);
-
- // If parent is a special object, then we need to know how many special members it has
- if ((parentInfo->IsIObjRefInstance() ||
- parentInfo->IsISerializableInstance() ||
- parentInfo->NeedsUnboxing())
- && parentInfo->GetNumSpecialMembers() > 0)
- {
- // Make a note in TSO that this parent has non-zero special members
- DWORD index[3];
- index[0] = parentInfo->GetIObjRefIndexIntoTSO();
- index[1] = parentInfo->GetISerIndexIntoTSO();
- index[2] = parentInfo->GetBoxedValIndexIntoTSO();
-
- for (DWORD count = 0; count < 3; count++)
- {
- OBJECTREF refIser, refNames, refValuesTemp;
- SpecialObjectInfo *pISerInfo;
-
- if (index[count] == (DWORD) -1)
- continue;
-
- refIser = TSO.GetAt(index[count], &refNames, &refValuesTemp, (QueuedObjectInfo **)&pISerInfo);
- _ASSERTE(refIser == refParent);
-
- DWORD numSpecialObjects = parentInfo->GetNumSpecialMembers();
- pISerInfo->SetNumSpecialMembers(numSpecialObjects);
-
- _ASSERTE(TMappings.GetCount() >= numSpecialObjects);
- pISerInfo->SetMappingTableIndex(TMappings.GetCount() - numSpecialObjects);
- }
- }
- }
-
- // FIELD SCAN PHASE
- if (!m_skipFieldScan)
- {
- if (m_currObject->GetMethodTable()->IsArray())
- ScanArrayMembers();
- else if (isISerializable)
- ScanISerializableMembers(IObjRefTSOIndex, ISerializableTSOIndex, BoxedValTSOIndex, refValues);
- else
- ScanMemberFields(IObjRefTSOIndex, BoxedValTSOIndex);
- }
-
- } // While there are objects in QOM
-
- // OBJECT COMPLETION PHASE
- CompleteSpecialObjects();
-
- // Deliver VTS OnDeserialized callbacks.
- CompleteVtsOnDeserializedCallbacks();
-
- CompleteIDeserializationCallbacks();
-
- _ASSERTE(m_topObject != NULL);
- // If a type check was requested, see if the returned object is of the expected type
- if (!expectedType.IsNull()
- && !ObjIsInstanceOf(OBJECTREFToObject(m_topObject), expectedType))
- COMPlusThrow(kArgumentException,W("Arg_ObjObj"));
-
- GCPROTECT_END(); // refParent
- GCPROTECT_END(); // refValues
-
- GCPROTECT_END(); // m_newObject
-
- END_DOMAIN_TRANSITION;
-
- // Deliver VTS OnSerialized callbacks.
- CompleteVtsOnSerializedCallbacks();
-
- GCPROTECT_END(); // m_fromExecutionContext
- GCPROTECT_END(); // m_topObject
- GCPROTECT_END(); // m_currObject
-
- return m_topObject;
-}
-
-// IObjRef and value types boxed by us, need to be fixed up towards the end
-BOOL ObjectClone::IsDelayedFixup(MethodTable *newMT, QueuedObjectInfo *pCurrInfo)
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END
- if (m_cbInterface->IsIObjectReferenceType(newMT) ||
- pCurrInfo->NeedsUnboxing())
- return TRUE;
- else
- return FALSE;
-}
-
-void ObjectClone::Fixup(OBJECTREF newObj, OBJECTREF refParent, QueuedObjectInfo *pFixupInfo)
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END
- MethodTable *pParentMT = refParent->GetMethodTable();
-
- if (pFixupInfo->IsISerializableMember())
- {
- HandleISerializableFixup(refParent, pFixupInfo);
- }
- else if (pParentMT->IsArray())
- {
- HandleArrayFixup(refParent, pFixupInfo);
- }
- else
- {
- HandleObjectFixup(refParent, pFixupInfo);
- }
-}
-
-PTRARRAYREF ObjectClone::MakeObjectLookLikeISerializable(int objectId)
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- THROWS;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END
-
- _ASSERTE(m_context != ObjectFreezer);
-
- LOG((LF_REMOTING, LL_INFO1000, "MakeObjectLookLikeISerializable. Target object is ISerializable, so making from object look ISerializable\n"));
- MethodTable *pCurrMT = m_currObject->GetMethodTable();
- DWORD numFields = pCurrMT->GetNumInstanceFields();
-
- PTRARRAYREF fieldNames = NULL;
- PTRARRAYREF fieldValues = NULL;
-
- GCPROTECT_BEGIN(fieldNames);
- GCPROTECT_BEGIN(fieldValues);
-
- // Go back to from domain
- ENTER_DOMAIN_PTR(m_fromDomain,ADV_RUNNINGIN);
-
- // Reset the execution context to the original state it was in when we first
- // left the from domain (this will automatically be popped once we return
- // from this domain again).
- Thread *pThread = GetThread();
- if (pThread->IsExposedObjectSet())
- {
- THREADBASEREF refThread = (THREADBASEREF)pThread->GetExposedObjectRaw();
- refThread->SetExecutionContext(m_fromExecutionContext);
- }
-
- fieldNames = (PTRARRAYREF)AllocateObjectArray(numFields, g_pStringClass, FALSE);
- fieldValues = (PTRARRAYREF)AllocateObjectArray(numFields, g_pObjectClass, FALSE);
-
- DWORD fieldIndex = 0;
- while (pCurrMT)
- {
-
- DWORD numInstanceFields = pCurrMT->GetNumIntroducedInstanceFields();
-
- FieldDesc *pFields = pCurrMT->GetApproxFieldDescListRaw();
-
- for (DWORD i = 0; i < numInstanceFields; i++)
- {
- if (pFields[i].IsNotSerialized())
- {
- LOG((LF_REMOTING, LL_INFO1000, "MakeObjectLookLikeISerializable. Field %s is marked NonSerialized. Skipping.\n", pFields[i].GetName()));
- continue;
- }
-
- CorElementType typ = pFields[i].GetFieldType();
- DWORD offset = pFields[i].GetOffset();
-
- LPCUTF8 szFieldName = pFields[i].GetName();
- STRINGREF refName = StringObject::NewString(szFieldName);
- _ASSERTE(refName != NULL);
-
- fieldNames->SetAt(fieldIndex, refName);
-
- switch (typ)
- {
- case ELEMENT_TYPE_BOOLEAN:
- case ELEMENT_TYPE_I1:
- case ELEMENT_TYPE_U1:
- case ELEMENT_TYPE_I2:
- case ELEMENT_TYPE_U2:
- case ELEMENT_TYPE_CHAR:
- case ELEMENT_TYPE_I4:
- case ELEMENT_TYPE_U4:
- case ELEMENT_TYPE_I8:
- case ELEMENT_TYPE_U8:
- case ELEMENT_TYPE_I:
- case ELEMENT_TYPE_U:
- case ELEMENT_TYPE_R4:
- case ELEMENT_TYPE_R8:
- {
- MethodTable *pFldMT = MscorlibBinder::GetElementType(typ);
- void *pData = m_currObject->GetData() + offset;
- OBJECTREF refBoxed = pFldMT->Box(pData);
-
- fieldValues->SetAt(fieldIndex, refBoxed);
- break;
- }
- case ELEMENT_TYPE_VALUETYPE:
- case ELEMENT_TYPE_PTR:
- case ELEMENT_TYPE_FNPTR:
- {
- TypeHandle th = LoadExactFieldType(&pFields[i], m_currObject, m_fromDomain);
- _ASSERTE(!th.AsMethodTable()->IsByRefLike() && "Field types cannot contain stack pointers.");
-
- OBJECTREF refBoxed = BoxValueTypeInWrongDomain(m_currObject, offset, th.AsMethodTable());
-
- fieldValues->SetAt(fieldIndex, refBoxed);
- break;
- }
- case ELEMENT_TYPE_SZARRAY: // Single Dim
- case ELEMENT_TYPE_ARRAY: // General Array
- case ELEMENT_TYPE_CLASS: // Class
- case ELEMENT_TYPE_OBJECT:
- case ELEMENT_TYPE_STRING: // System.String
- case ELEMENT_TYPE_VAR:
- {
- OBJECTREF refField = *((OBJECTREF *) m_currObject->GetData() + offset);
- fieldValues->SetAt(fieldIndex, refField);
- break;
- }
- default:
- _ASSERTE(!"Unknown element type in MakeObjectLookLikeISerializalbe");
- }
-
- fieldIndex++;
- }
-
- pCurrMT = pCurrMT->GetParentMethodTable();
- }
-
- // Back to original domain
- END_DOMAIN_TRANSITION;
-
- // Add object to TSO
- ISerializableInstanceInfo iserInfo(objectId, 0);
- TSO.Push(m_newObject, fieldNames, NULL, (QueuedObjectInfo *)&iserInfo);
-
- LOG((LF_REMOTING, LL_INFO1000, "MakeObjectLookLikeISerializable. Added to TSO at index %d.\n", TSO.GetCount() - 1));
- GCPROTECT_END();
- GCPROTECT_END();
-
- return fieldValues;
-}
-
-PTRARRAYREF ObjectClone::AllocateISerializable(int objectId, BOOL bIsRemotingObject)
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- THROWS;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END
-
- _ASSERTE(m_context != ObjectFreezer);
-
- // Go back to from domain
- StackSString ssAssemName;
- StackSString ssTypeName;
-
- struct _gc {
- STRINGREF typeName;
- STRINGREF assemblyName;
- PTRARRAYREF fieldNames;
- PTRARRAYREF fieldValues;
- OBJECTREF refObjRef;
- } gc;
- ZeroMemory(&gc, sizeof(gc));
-
- GCPROTECT_BEGIN(gc);
-
- ENTER_DOMAIN_PTR(m_fromDomain,ADV_RUNNINGIN);
-
- // Reset the execution context to the original state it was in when we first
- // left the from domain (this will automatically be popped once we return
- // from this domain again).
- Thread *pThread = GetThread();
- if (pThread->IsExposedObjectSet())
- {
- THREADBASEREF refThread = (THREADBASEREF)pThread->GetExposedObjectRaw();
- refThread->SetExecutionContext(m_fromExecutionContext);
- }
-
- // Call GetObjectData on the interface
-
- LOG((LF_REMOTING, LL_INFO1000, "AllocateISerializable. Instance is ISerializable type. Calling GetObjectData.\n"));
-
- PREPARE_NONVIRTUAL_CALLSITE(METHOD__OBJECTCLONEHELPER__GET_OBJECT_DATA);
-
- DECLARE_ARGHOLDER_ARRAY(args, 5);
-
- args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(m_currObject);
- args[ARGNUM_1] = PTR_TO_ARGHOLDER(&gc.typeName);
- args[ARGNUM_2] = PTR_TO_ARGHOLDER(&gc.assemblyName);
- args[ARGNUM_3] = PTR_TO_ARGHOLDER(&gc.fieldNames);
- args[ARGNUM_4] = PTR_TO_ARGHOLDER(&gc.fieldValues);
-
- CATCH_HANDLER_FOUND_NOTIFICATION_CALLSITE;
- CALL_MANAGED_METHOD_RETREF(gc.refObjRef, OBJECTREF, args);
-
- if (!bIsRemotingObject || gc.refObjRef == NULL)
- {
- ssAssemName.Set(gc.assemblyName->GetBuffer());
- ssTypeName.Set(gc.typeName->GetBuffer());
- }
-
- // Back to original domain
- END_DOMAIN_TRANSITION;
-
- // if its a remoting object we are dealing with, we may already have the smugglable objref
- if (bIsRemotingObject && gc.refObjRef != NULL)
- {
- m_newObject = gc.refObjRef;
- // Add object to TSO. We dont need a ISerializable record, because we are smuggling the ObjRef
- // and so, technically the ISerializable ctor can be considered already called. But we still make an entry in
- // TSO and mark it "processed", so repeat references to the same remoting object work correctly
- ISerializableInstanceInfo iserInfo(objectId, 0);
- iserInfo.SetHasBeenProcessed();
- TSO.Push(m_newObject, NULL, NULL, (QueuedObjectInfo *)&iserInfo);
-
- LOG((LF_REMOTING, LL_INFO1000, "AllocateISerializable. GetObjectData returned smugglable ObjRef. Added dummy record to TSO at index %d.\n", TSO.GetCount() - 1));
- }
- else
- {
- // Find the type (and choke on any exotics such as arrays, function pointers or generic type definitions).
- TypeHandle th = GetType(ssTypeName, ssAssemName);
- if (th.IsTypeDesc() || th.ContainsGenericVariables())
- {
- StackSString ssBeforeTypeName, ssAfterTypeName;
- TypeString::AppendType(ssBeforeTypeName, m_currObject->GetTypeHandle(), TypeString::FormatNamespace | TypeString::FormatFullInst);
- TypeString::AppendType(ssAfterTypeName, th, TypeString::FormatNamespace | TypeString::FormatFullInst);
- COMPlusThrow(kSerializationException, IDS_SERIALIZATION_BAD_ISER_TYPE, ssBeforeTypeName.GetUnicode(), ssAfterTypeName.GetUnicode());
- }
- MethodTable *pSrvMT = th.AsMethodTable();
- _ASSERTE(pSrvMT);
-
-#ifdef _DEBUG
- {
- DefineFullyQualifiedNameForClass();
- LPCUTF8 __szTypeName = GetFullyQualifiedNameForClassNestedAware(pSrvMT);
- LOG((LF_REMOTING, LL_INFO1000, "AllocateISerializable. Allocating instance of type %s.\n", &__szTypeName[0]));
- }
-#endif
- // Allocate the object
- m_newObject = m_cbInterface->AllocateObject(m_currObject, pSrvMT);
-
- // Add object to TSO
- ISerializableInstanceInfo iserInfo(objectId, 0);
-
- // Check if the target object is ISerializable. If not, we need to treat construction of this object differently
- if (!m_cbInterface->IsISerializableType(pSrvMT))
- {
- iserInfo.SetTargetNotISerializable();
- }
- TSO.Push(m_newObject, gc.fieldNames, NULL, (QueuedObjectInfo *)&iserInfo);
-
- LOG((LF_REMOTING, LL_INFO1000, "AllocateISerializable. Added to TSO at index %d.\n", TSO.GetCount() - 1));
- }
- GCPROTECT_END();
-
- return gc.fieldValues;
-}
-
-void ObjectClone::AllocateArray()
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- THROWS;
- }
- CONTRACTL_END
-
- LOG((LF_REMOTING, LL_INFO1000, "AllocateArray. Instance is an array type.\n"));
- MethodTable *pCurrMT = m_currObject->GetMethodTable();
- _ASSERTE(pCurrMT->IsArray());
-
- BASEARRAYREF refArray = (BASEARRAYREF)m_currObject;
- GCPROTECT_BEGIN(refArray);
-
- TypeHandle elemTh = refArray->GetArrayElementTypeHandle();
- CorElementType elemType = refArray->GetArrayElementType();
- DWORD numComponents = refArray->GetNumComponents();
-
- TypeHandle __elemTh = GetCorrespondingTypeForTargetDomain(elemTh);
- _ASSERTE(!__elemTh.IsNull());
-
- unsigned __rank = pCurrMT->GetRank();
- TypeHandle __arrayTh = ClassLoader::LoadArrayTypeThrowing(__elemTh, __rank == 1 ? ELEMENT_TYPE_SZARRAY : ELEMENT_TYPE_ARRAY, __rank);
-
- DWORD __numArgs = __rank*2;
- INT32* __args = (INT32*) _alloca(sizeof(INT32)*__numArgs);
-
- if (__arrayTh.AsArray()->GetInternalCorElementType() == ELEMENT_TYPE_ARRAY)
- {
- const INT32* bounds = refArray->GetBoundsPtr();
- const INT32* lowerBounds = refArray->GetLowerBoundsPtr();
- for(unsigned int i=0; i < __rank; i++)
- {
- __args[2*i] = lowerBounds[i];
- __args[2*i+1] = bounds[i];
- }
- }
- else
- {
- __numArgs = 1;
- __args[0] = numComponents;
- }
- m_newObject = m_cbInterface->AllocateArray(m_currObject, __arrayTh, __args, __numArgs, FALSE);
-
- // Treat pointer as a primitive type (we shallow copy the bits).
- if (CorTypeInfo::IsPrimitiveType(elemType) || elemType == ELEMENT_TYPE_PTR)
- {
- LOG((LF_REMOTING, LL_INFO1000, "AllocateArray. Instance is an array of primitive type. Copying contents.\n"));
- // Copy contents.
- SIZE_T numBytesToCopy = refArray->GetComponentSize() * numComponents;
- I1ARRAYREF refI1Arr = (I1ARRAYREF)m_newObject;
- BYTE *pDest = (BYTE *)refI1Arr->GetDirectPointerToNonObjectElements();
- I1ARRAYREF refFromArr = (I1ARRAYREF)refArray;
- BYTE *pSrc = (BYTE *)refFromArr->GetDirectPointerToNonObjectElements();
-
- memcpyNoGCRefs(pDest, pSrc, numBytesToCopy);
- m_skipFieldScan = TRUE;
- }
- else if (elemType == ELEMENT_TYPE_VALUETYPE)
- {
- if (!__elemTh.GetMethodTable()->HasFieldsWhichMustBeInited() && RemotableMethodInfo::TypeIsConduciveToBlitting(elemTh.AsMethodTable(), __elemTh.GetMethodTable()))
- {
- LOG((LF_REMOTING, LL_INFO1000, "AllocateArray. Instance is an array of value type with no embedded GC type. Copying contents.\n"));
- // Copy contents.
- SIZE_T numBytesToCopy = refArray->GetComponentSize() * numComponents;
- I1ARRAYREF refI1Arr = (I1ARRAYREF)m_newObject;
- BYTE *pDest = (BYTE *)refI1Arr->GetDirectPointerToNonObjectElements();
- I1ARRAYREF refFromArr = (I1ARRAYREF)refArray;
- BYTE *pSrc = (BYTE *)refFromArr->GetDirectPointerToNonObjectElements();
-
- memcpyNoGCRefs(pDest, pSrc, numBytesToCopy);
- m_skipFieldScan = TRUE;
- }
- }
- GCPROTECT_END();
-}
-
-void ObjectClone::AllocateObject()
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- THROWS;
- }
- CONTRACTL_END
-
- LOG((LF_REMOTING, LL_INFO1000, "AllocateObject. Instance is a regular object.\n"));
- MethodTable *pCurrMT = m_currObject->GetMethodTable();
- _ASSERTE(!pCurrMT->IsArray());
- _ASSERTE(!pCurrMT->IsMarshaledByRef() && !pCurrMT->IsTransparentProxy());
- _ASSERTE(!m_cbInterface->IsISerializableType(pCurrMT));
-
- MethodTable *pCorrespondingMT = GetCorrespondingTypeForTargetDomain(pCurrMT);
- _ASSERTE(pCorrespondingMT);
-
- pCorrespondingMT->EnsureInstanceActive();
-
- m_newObject = m_cbInterface->AllocateObject(m_currObject, pCorrespondingMT);
-
- InvokeVtsCallbacks(m_newObject, RemotingVtsInfo::VTS_CALLBACK_ON_DESERIALIZING, m_toDomain);
-}
-
-// Use this wrapper when the type handle can't be represented as a raw MethodTable (i.e. it's a pointer or array type).
-TypeHandle ObjectClone::GetCorrespondingTypeForTargetDomain(TypeHandle thCli)
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- THROWS;
- }
- CONTRACTL_END
-
- TypeHandle thBaseType = thCli;
- TypeHandle thSrvType;
-
- // Strip off any pointer information (and record the depth). We'll put this back later (when we've translated the base type).
- DWORD dwPointerDepth = 0;
- while (thBaseType.IsPointer())
- {
- dwPointerDepth++;
- thBaseType = thBaseType.AsTypeDesc()->GetTypeParam();
- }
-
- // If we hit an array then we'll recursively translate the element type then build an array type out of it.
- if (thBaseType.IsArray())
- {
- ArrayTypeDesc *atd = (ArrayTypeDesc *)thBaseType.AsTypeDesc();
- thSrvType = GetCorrespondingTypeForTargetDomain(atd->GetArrayElementTypeHandle());
-
- thSrvType = ClassLoader::LoadArrayTypeThrowing(thSrvType, atd->GetInternalCorElementType(), atd->GetRank());
- }
- else
- {
- // We should have only unshared types if we get here.
- _ASSERTE(!thBaseType.IsTypeDesc());
- thSrvType = GetCorrespondingTypeForTargetDomain(thBaseType.AsMethodTable());
- }
-
- // Match the level of pointer indirection from the original client type.
- while (dwPointerDepth--)
- {
- thSrvType = thSrvType.MakePointer();
- }
-
- return thSrvType;
-}
-
-MethodTable * ObjectClone::GetCorrespondingTypeForTargetDomain(MethodTable *pCliMT)
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- THROWS;
- }
- CONTRACTL_END
-
- MethodTable *pSrvMT = NULL;
- if (m_fromDomain == m_toDomain)
- return pCliMT;
-
- _ASSERTE(m_context != ObjectFreezer);
-#ifdef _DEBUG
- SString __ssTypeName;
- StackScratchBuffer __scratchBuf;
- if (pCliMT->IsArray())
- pCliMT->_GetFullyQualifiedNameForClass(__ssTypeName);
- else
- pCliMT->_GetFullyQualifiedNameForClassNestedAware(__ssTypeName);
-#endif
-
- // Take benefit of shared types. If a type is shared, and its assembly has been loaded
- // in the target domain, go ahead and use the same MT ptr.
- // The logic is trickier (and more expensive to calculate) for generic types, so skip the optimization there.
- if (pCliMT->IsDomainNeutral() && !pCliMT->HasInstantiation())
- {
- if (pCliMT->GetAssembly()->FindDomainAssembly(m_toDomain))
- {
- LOG((LF_REMOTING, LL_INFO1000,
- "GetCorrespondingTypeForTargetDomain. Type %s is shared. Using same MethodTable.\n", __ssTypeName.GetUTF8(__scratchBuf)));
- return pCliMT;
- }
- }
-
- pSrvMT = CrossDomainTypeMap::GetMethodTableForDomain(pCliMT, m_fromDomain, m_toDomain);
- if (pSrvMT)
- {
- LOG((LF_REMOTING, LL_INFO1000,
- "GetCorrespondingTypeForTargetDomain. Found matching type for %s in domain %d from cache.\n", __ssTypeName.GetUTF8(__scratchBuf), m_toDomain));
- return pSrvMT;
- }
-
- // Need to find the name and lookup in target domain
- SString ssCliTypeName;
- if (pCliMT->IsArray())
- {
- pCliMT->_GetFullyQualifiedNameForClass(ssCliTypeName);
- }
- else if (pCliMT->HasInstantiation())
- {
- TypeString::AppendType(ssCliTypeName, TypeHandle(pCliMT), TypeString::FormatNamespace | TypeString::FormatFullInst);
- }
- else
- {
- pCliMT->_GetFullyQualifiedNameForClassNestedAware(ssCliTypeName);
- }
-
-
- SString ssAssemblyName;
- pCliMT->GetAssembly()->GetDisplayName(ssAssemblyName);
-
- // Get the assembly
- TypeHandle th = GetType(ssCliTypeName, ssAssemblyName);
-
- if (!pCliMT->IsArray())
- {
- pSrvMT = th.AsMethodTable();
- }
- else
- {
- _ASSERTE(th.IsArray());
- TypeDesc *td = th.AsTypeDesc();
- pSrvMT = td->GetMethodTable();
- }
- CrossDomainTypeMap::SetMethodTableForDomain(pCliMT, m_fromDomain, pSrvMT, m_toDomain);
- LOG((LF_REMOTING, LL_INFO1000,
- "GetCorrespondingTypeForTargetDomain. Loaded matching type for %s in domain %d. Added to cache.\n", __ssTypeName.GetUTF8(__scratchBuf), m_toDomain));
- return pSrvMT;
-}
-
-TypeHandle ObjectClone::GetType(const SString &ssTypeName, const SString &ssAssemName)
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END;
-
- Assembly *pAssembly = NULL;
-
-#ifndef OBJECT_CLONER_STRICT_MODE
- EX_TRY
-#endif
- {
- AssemblySpec spec;
- StackScratchBuffer scratchBuf;
- HRESULT hr = spec.Init(ssAssemName.GetUTF8(scratchBuf));
- if (SUCCEEDED(hr))
- {
- pAssembly = spec.LoadAssembly(FILE_ACTIVE);
- }
- else
- {
- COMPlusThrowHR(hr);
- }
- }
-#ifndef OBJECT_CLONER_STRICT_MODE
- EX_CATCH
- {
- if (GET_EXCEPTION()->IsTransient())
- {
- EX_RETHROW;
- }
-
- DomainAssembly *pDomainAssembly = NULL;
- if (pDomainAssembly == NULL)
- COMPlusThrow(kSerializationException, IDS_SERIALIZATION_UNRESOLVED_TYPE,
- ssTypeName.GetUnicode(), ssAssemName.GetUnicode());
- else
- pAssembly = pDomainAssembly->GetAssembly();
- }
- EX_END_CATCH(SwallowAllExceptions);
-#endif
-
- _ASSERTE(pAssembly);
-
- TypeHandle th = TypeName::GetTypeFromAssembly(ssTypeName.GetUnicode(), pAssembly);
-
- if (th.IsNull())
- {
- COMPlusThrow(kSerializationException, IDS_SERIALIZATION_UNRESOLVED_TYPE,
- ssTypeName.GetUnicode(), ssAssemName.GetUnicode());
- }
-
- LOG((LF_REMOTING, LL_INFO1000, "GetType. Loaded type %S from assembly %S in domain %d. \n",
- ssTypeName.GetUnicode(), ssAssemName.GetUnicode(), m_toDomain->GetId().m_dwId));
-
- return th;
-}
-
-void ObjectClone::HandleISerializableFixup(OBJECTREF refParent, QueuedObjectInfo *currObjFixupInfo)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
-
- _ASSERTE(m_context != ObjectFreezer);
-
- ISerializableMemberInfo *pIsInfo = (ISerializableMemberInfo *)currObjFixupInfo;
- OBJECTREF refNames, refValues;
- ISerializableInstanceInfo *dummy;
- OBJECTREF parent;
- parent = TSO.GetAt(pIsInfo->GetTableIndex(), &refNames, &refValues, (QueuedObjectInfo **)&dummy);
- _ASSERTE(parent == refParent);
- _ASSERTE(dummy->IsISerializableInstance());
-
- PTRARRAYREF refFields = (PTRARRAYREF)refValues;
- _ASSERTE(pIsInfo->GetFieldIndex() < refFields->GetNumComponents());
- refFields->SetAt(pIsInfo->GetFieldIndex(), m_newObject);
-
- LOG((LF_REMOTING, LL_INFO1000, "HandleISerializableFixup. Parent is ISerializable. Added field #%d to TSO record at index %d\n", pIsInfo->GetFieldIndex(), pIsInfo->GetTableIndex()));
-}
-
-void ObjectClone::HandleArrayFixup(OBJECTREF refParent, QueuedObjectInfo *currObjFixupInfo)
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- THROWS;
- GC_TRIGGERS;
- }
- CONTRACTL_END
-
- _ASSERTE(refParent->GetMethodTable()->IsArray());
- BASEARRAYREF refParentArray = (BASEARRAYREF) refParent;
- GCPROTECT_BEGIN(refParentArray);
-
- NDimArrayMemberInfo *pArrInfo = (NDimArrayMemberInfo *)currObjFixupInfo;
- DWORD *pIndices = pArrInfo->GetIndices();
-
- TypeHandle arrayElementType = refParentArray->GetArrayElementTypeHandle();
- MethodTable *pArrayMT = refParentArray->GetMethodTable();
-
- DWORD Rank = pArrayMT->GetRank();
- SIZE_T Offset = 0;
- SIZE_T Multiplier = 1;
-
- _ASSERTE(Rank == pArrInfo->GetNumDimensions());
-
- for (int i = Rank-1; i >= 0; i--) {
- INT32 curIndex = pIndices[i];
- const INT32 *pBoundsPtr = refParentArray->GetBoundsPtr();
-
- // Bounds check each index
- // Casting to unsigned allows us to use one compare for [0..limit-1]
- _ASSERTE((UINT32) curIndex < (UINT32) pBoundsPtr[i]);
-
- Offset += curIndex * Multiplier;
- Multiplier *= pBoundsPtr[i];
- }
-
- // The follwing code is loosely based on COMArrayInfo::SetValue
-
- if (!arrayElementType.IsValueType())
- {
- if (!ObjIsInstanceOf(OBJECTREFToObject(m_newObject), arrayElementType))
- COMPlusThrow(kInvalidCastException,W("InvalidCast_StoreArrayElement"));
-
- OBJECTREF* pElem = (OBJECTREF*)(refParentArray->GetDataPtr() + (Offset * pArrayMT->GetComponentSize()));
- SetObjectReference(pElem,m_newObject,GetAppDomain());
- }
- else
- {
- // value class or primitive type
- OBJECTREF* pElem = (OBJECTREF*)(refParentArray->GetDataPtr() + (Offset * pArrayMT->GetComponentSize()));
- if (!arrayElementType.GetMethodTable()->UnBoxInto(pElem, m_newObject))
- COMPlusThrow(kInvalidCastException, W("InvalidCast_StoreArrayElement"));
- }
-
- LOG((LF_REMOTING, LL_INFO1000, "HandleArrayFixup. Parent is an array. Added element at offset %d\n", Offset));
- GCPROTECT_END();
-}
-
-void ObjectClone::HandleObjectFixup(OBJECTREF refParent, QueuedObjectInfo *currObjFixupInfo)
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- THROWS;
- }
- CONTRACTL_END
- ObjectMemberInfo *pObjInfo = (ObjectMemberInfo *)currObjFixupInfo;
- FieldDesc *pTargetField = pObjInfo->GetFieldDesc();
- DWORD offset = pTargetField->GetOffset();
-
-#ifdef _DEBUG
- MethodTable *pTemp = refParent->GetMethodTable();
- _ASSERTE(offset < pTemp->GetBaseSize());
-#endif
-
- GCPROTECT_BEGIN(refParent);
-
- TypeHandle fldType = LoadExactFieldType(pTargetField, refParent, m_toDomain);
-
- if (!ObjIsInstanceOf(OBJECTREFToObject(m_newObject), fldType))
- COMPlusThrow(kArgumentException,W("Arg_ObjObj"));
-
- OBJECTREF *pDest = (OBJECTREF *) (refParent->GetData() + offset);
- _ASSERTE(GetAppDomain()==m_toDomain);
- SetObjectReference(pDest, m_newObject, GetAppDomain());
-
- GCPROTECT_END();
-
- LOG((LF_REMOTING, LL_INFO1000, "HandleObjectFixup. Parent is a regular object. Added field at offset %d\n", offset));
-}
-
-#ifdef OBJECT_CLONER_STRICT_MODE
-static void DECLSPEC_NORETURN ThrowMissingFieldException(FieldDesc *pFD)
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- THROWS;
- }
- CONTRACTL_END;
-
- StackSString szField(SString::Utf8, pFD->GetName());
-
- StackSString szType;
- TypeString::AppendType(szType, TypeHandle(pFD->GetApproxEnclosingMethodTable()));
-
- COMPlusThrow(kSerializationException,
- IDS_SERIALIZATION_MISSING_FIELD,
- szField.GetUnicode(),
- szType.GetUnicode());
-}
-#endif
-
-void ObjectClone::ScanMemberFields(DWORD IObjRefTSOIndex, DWORD BoxedValTSOIndex)
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- THROWS;
- }
- CONTRACTL_END
- _ASSERTE(m_currObject != NULL);
- _ASSERTE(m_newObject != NULL);
-
- MethodTable *pMT = m_currObject->GetMethodTable();
- _ASSERTE(!pMT->IsMarshaledByRef() && !pMT->IsTransparentProxy());
- _ASSERTE(!pMT->IsArray());
- MethodTable *pTargetMT = m_newObject->GetMethodTable();
-
- DWORD numFixupsNeeded = 0;
-
- if (RemotableMethodInfo::TypeIsConduciveToBlitting(pMT, pTargetMT))
- {
- _ASSERTE(pMT->GetAlignedNumInstanceFieldBytes() == pTargetMT->GetAlignedNumInstanceFieldBytes());
- DWORD numBytes = pMT->GetNumInstanceFieldBytes();
- BYTE *pFrom = m_currObject->GetData();
- BYTE *pTo = m_newObject->GetData();
- memcpyNoGCRefs(pTo, pFrom, numBytes);
- LOG((LF_REMOTING, LL_INFO1000, "ScanMemberFields. Object has no reference type fields. Blitting contents.\n"));
- }
- else if (AreTypesEmittedIdentically(pMT, pTargetMT))
- {
- LOG((LF_REMOTING, LL_INFO1000, "ScanMemberFields. Object not blittable but types are layed out for easy cloning .\n"));
- MethodTable *pCurrMT = pMT;
- MethodTable *pCurrTargetMT = pTargetMT;
- while (pCurrMT)
- {
- DWORD numInstanceFields = pCurrMT->GetNumIntroducedInstanceFields();
- _ASSERTE(pCurrTargetMT->GetNumIntroducedInstanceFields() == numInstanceFields);
-
- FieldDesc *pFields = pCurrMT->GetApproxFieldDescListRaw();
- FieldDesc *pTargetFields = pCurrTargetMT->GetApproxFieldDescListRaw();
-
- for (DWORD i = 0; i < numInstanceFields; i++)
- {
- if (pFields[i].IsNotSerialized())
- {
- LOG((LF_REMOTING, LL_INFO1000, "ScanMemberFields. Field %s is marked NonSerialized. Skipping.\n", pFields[i].GetName()));
- continue;
- }
-
- numFixupsNeeded += CloneField(&pFields[i], &pTargetFields[i]);
- }
-
- pCurrMT = pCurrMT->GetParentMethodTable();
- pCurrTargetMT = pCurrTargetMT->GetParentMethodTable();
- }
- }
- else
- {
- LOG((LF_REMOTING, LL_INFO1000, "ScanMemberFields. Object type layout is different.\n"));
-
- // The object types between source and destination have significant differences (some fields may be added, removed or
- // re-ordered, the type hierarchy may have had layers added or removed). We can still clone the object if every non-optional
- // field in the destination object can be found and serialized in a type with the same name in the source object. We ignore
- // fields and entire type layers that have been added in the source object and also any fields or layers that have been
- // removed as long as they don't include any fields that are mandatory in the destination object. We allow the fields within
- // a type layer to move around (we key the field by name only, the latter stage of cloning will check type equivalency and
- // as above we will widen primitive types if necessary). Since it requires significant effort to calculate whether the
- // objects can be cloned (and then locate corresponding fields in order to do so) we cache a mapping of source object fields
- // to destination object fields.
-
- // The following call will return such a mapping (it's an array where each entry is a pointer to a source object field desc
- // and the entries are in destination field index order, most derived type first, followed by second most derived type
- // etc.). If a mapping is impossible the method will throw.
- FieldDesc **pFieldMap = CrossDomainFieldMap::LookupOrCreateFieldMapping(pTargetMT, pMT);
- DWORD dwMapIndex = 0;
-
- MethodTable *pDstMT = pTargetMT;
- while (pDstMT)
- {
- FieldDesc *pDstFields = pDstMT->GetApproxFieldDescListRaw();
- DWORD numInstanceFields = pDstMT->GetNumIntroducedInstanceFields();
-
- for (DWORD i = 0; i < numInstanceFields; i++)
- {
- FieldDesc *pSrcField = pFieldMap[dwMapIndex++];
-
- // Non-serialized fields in the destination type (or optional fields where the source type doesn't have an
- // equivalent) don't have a source field desc.
- if (pSrcField == NULL)
- continue;
-
- numFixupsNeeded += CloneField(pSrcField, &pDstFields[i]);
- }
-
- pDstMT = pDstMT->GetParentMethodTable();
- }
-
- _ASSERTE(dwMapIndex == pTargetMT->GetNumInstanceFields());
- }
-
- if (numFixupsNeeded > 0)
- {
- ParentInfo fxInfo(numFixupsNeeded);
- if (IObjRefTSOIndex != (DWORD) -1)
- {
- _ASSERTE(m_cbInterface->IsIObjectReferenceType(pMT));
- fxInfo.SetIsIObjRefInstance();
- fxInfo.SetIObjRefIndexIntoTSO(IObjRefTSOIndex);
- }
- if (BoxedValTSOIndex != (DWORD) -1)
- {
- _ASSERTE(pMT->IsValueType());
- fxInfo.SetNeedsUnboxing();
- fxInfo.SetBoxedValIndexIntoTSO(BoxedValTSOIndex);
- }
- QOF.Enqueue(m_newObject, NULL, NULL, (QueuedObjectInfo *)&fxInfo);
- LOG((LF_REMOTING, LL_INFO1000, "ScanMemberFields. Current object had total of %d reference type fields. Adding to QOF.\n", numFixupsNeeded));
- // Delay calling any OnDeserialized callbacks until the end of the cloning operation (it's difficult to tell when all the
- // children have been deserialized).
- if (HasVtsCallbacks(m_newObject->GetMethodTable(), RemotingVtsInfo::VTS_CALLBACK_ON_DESERIALIZED))
- VDC.Enqueue(m_newObject, NULL, NULL, NULL);
- if (m_cbInterface->RequiresDeserializationCallback(m_newObject->GetMethodTable()))
- {
- LOG((LF_REMOTING, LL_INFO1000, "ScanMemberFields. Adding object to Table of IDeserialization Callbacks\n"));
- QueuedObjectInfo noInfo;
- TDC.Enqueue(m_newObject, NULL, NULL, &noInfo);
- }
- }
- else
- {
- // This is effectively a leaf node (no complex children) so if the type has a callback for OnDeserialized we'll deliver it
- // now. This fixes callback ordering for a few more edge cases (e.g. VSW 415611) and is reasonably cheap. We can never do a
- // perfect job (in the presence of object graph cycles) and a near perfect job (intuitively ordered callbacks for acyclic
- // object graphs) is prohibitively expensive; so we're stuck with workarounds like this.
- InvokeVtsCallbacks(m_newObject, RemotingVtsInfo::VTS_CALLBACK_ON_DESERIALIZED, m_toDomain);
- if (m_cbInterface->RequiresDeserializationCallback(m_newObject->GetMethodTable()))
- MakeIDeserializationCallback(m_newObject);
- }
-}
-
-DWORD ObjectClone::CloneField(FieldDesc *pSrcField, FieldDesc *pDstField)
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- THROWS;
- }
- CONTRACTL_END;
-
- BOOL bFixupNeeded = FALSE;
-
- CorElementType srcType = pSrcField->GetFieldType();
- CorElementType dstType = pDstField->GetFieldType();
- DWORD srcOffset = pSrcField->GetOffset();
- DWORD dstOffset = pDstField->GetOffset();
-
- BOOL bUseWidenedValue = FALSE;
- ARG_SLOT fieldData = 0;
- if (srcType != dstType)
- {
- void *pData = m_currObject->GetData() + srcOffset;
-
- MethodTable *pSrcFieldMT = NULL;
- if (CorTypeInfo::IsPrimitiveType(srcType))
- pSrcFieldMT = MscorlibBinder::GetElementType(srcType);
- else
- pSrcFieldMT = LoadExactFieldType(pSrcField, m_currObject, m_fromDomain).AsMethodTable();
-
- LOG((LF_REMOTING, LL_INFO1000, "ScanMemberFields. Field %s has differing types at source and destination. Will try to convert.\n", pSrcField->GetName()));
- fieldData = HandleFieldTypeMismatch(dstType, srcType, pData, pSrcFieldMT);
- bUseWidenedValue = TRUE;
- }
-
- switch (dstType)
- {
- case ELEMENT_TYPE_I1:
- case ELEMENT_TYPE_U1:
- case ELEMENT_TYPE_BOOLEAN:
- {
- BYTE *pDest = m_newObject->GetData() + dstOffset;
- if (bUseWidenedValue)
- *pDest = (unsigned char) fieldData;
- else
- {
- BYTE *pByte = m_currObject->GetData() + srcOffset;
- *pDest = *pByte;
- }
- }
- break;
- case ELEMENT_TYPE_I2:
- case ELEMENT_TYPE_U2:
- case ELEMENT_TYPE_CHAR:
- {
- WORD *pDest = (WORD*)(m_newObject->GetData() + dstOffset);
- if (bUseWidenedValue)
- *pDest = (short) fieldData;
- else
- {
- WORD *pWord = (WORD*)(m_currObject->GetData() + srcOffset);
- *(pDest) = *pWord;
- }
- }
- break;
- case ELEMENT_TYPE_I4:
- case ELEMENT_TYPE_U4:
- case ELEMENT_TYPE_R4:
- IN_WIN32(case ELEMENT_TYPE_FNPTR:)
- IN_WIN32(case ELEMENT_TYPE_I:)
- IN_WIN32(case ELEMENT_TYPE_U:)
- {
- DWORD *pDest = (DWORD*)(m_newObject->GetData() + dstOffset);
- if (bUseWidenedValue)
- *pDest = (int) fieldData;
- else
- {
- DWORD *pDword = (DWORD*)(m_currObject->GetData() + srcOffset);
- *(pDest) = *pDword;
- }
- }
- break;
- case ELEMENT_TYPE_R8:
- case ELEMENT_TYPE_I8:
- case ELEMENT_TYPE_U8:
- IN_WIN64(case ELEMENT_TYPE_FNPTR:)
- IN_WIN64(case ELEMENT_TYPE_I:)
- IN_WIN64(case ELEMENT_TYPE_U:)
- {
- INT64 *pDest = (INT64*)(m_newObject->GetData() + dstOffset);
- if (bUseWidenedValue)
- *pDest = fieldData;
- else
- {
- INT64 *pLong = (INT64*)(m_currObject->GetData() + srcOffset);
- *(pDest) = *pLong;
- }
- }
- break;
- case ELEMENT_TYPE_PTR:
- {
- void **pDest = (void**)(m_newObject->GetData() + dstOffset);
- void **pPtr = (void**)(m_currObject->GetData() + srcOffset);
- *(pDest) = *pPtr;
- }
- break;
- case ELEMENT_TYPE_STRING:
- case ELEMENT_TYPE_CLASS: // objectrefs
- case ELEMENT_TYPE_OBJECT:
- case ELEMENT_TYPE_SZARRAY: // single dim, zero
- case ELEMENT_TYPE_ARRAY: // all other arrays
- {
- OBJECTREF *pSrc = (OBJECTREF *)(m_currObject->GetData() + srcOffset);
- OBJECTREF *pDest = (OBJECTREF *)(m_newObject->GetData() + dstOffset);
-
- if ((*pSrc) == NULL)
- break;
-
- // If no deep copy is required, just copy the reference
- if (!m_cbInterface->RequiresDeepCopy(*pSrc))
- {
- _ASSERTE(GetAppDomain()==m_toDomain);
- SetObjectReference(pDest, *pSrc, GetAppDomain());
- break;
- }
-
- // Special case String
- if ((*pSrc)->GetMethodTable() == g_pStringClass)
- {
- // Better check the destination really expects a string (or maybe an object).
- TypeHandle thDstField = LoadExactFieldType(pDstField, m_newObject, m_toDomain);
- if (thDstField != TypeHandle(g_pStringClass) && thDstField != TypeHandle(g_pObjectClass))
- COMPlusThrow(kArgumentException, W("Arg_ObjObj"));
-
- STRINGREF refStr = (STRINGREF) *pSrc;
- refStr = m_cbInterface->AllocateString(refStr);
- // Get dest addr again, as a GC might have occurred
- pDest = (OBJECTREF *)(m_newObject->GetData() + dstOffset);
- _ASSERTE(GetAppDomain()==m_toDomain);
- SetObjectReference(pDest, refStr, GetAppDomain());
-
- break;
- }
-
- // Add the object to QOM
- LOG((LF_REMOTING, LL_INFO1000, "ScanMemberFields. Adding object in field %s to Queue of Objects to be Marshalled.\n", pSrcField->GetName()));
- ObjectMemberInfo objInfo(pDstField);
- bFixupNeeded = TRUE;
- QOM.Enqueue(*pSrc, NULL, NULL, (QueuedObjectInfo *)&objInfo);
- }
- break;
-
- case ELEMENT_TYPE_VALUETYPE:
- {
- TypeHandle th = LoadExactFieldType(pSrcField, m_currObject, m_fromDomain);
- _ASSERTE(!th.AsMethodTable()->IsByRefLike() && "Field types cannot contain stack pointers.");
-
- TypeHandle thTarget = LoadExactFieldType(pDstField, m_newObject, m_toDomain);
-
- MethodTable *pValueClassMT = th.AsMethodTable();
- MethodTable *pValueClassTargetMT = thTarget.AsMethodTable();
- if (!RemotableMethodInfo::TypeIsConduciveToBlitting(pValueClassMT, pValueClassTargetMT))
- {
- // Needs marshalling
- // We're allocating an object in the "to" domain
- // using a type from the "from" domain.
- OBJECTREF refTmpBox = BoxValueTypeInWrongDomain(m_currObject, srcOffset, pValueClassMT);
-
- // Nullable<T> might return null here. In that case we don't need to do anything
- // and the null value otherwise confuxes the fixup queue.
- if (refTmpBox != NULL)
- {
- // Add the object to QOM
- ObjectMemberInfo objInfo(pDstField);
- objInfo.SetNeedsUnboxing();
- bFixupNeeded = TRUE;
- QOM.Enqueue(refTmpBox, NULL, NULL, (QueuedObjectInfo *)&objInfo);
- LOG((LF_REMOTING, LL_INFO1000, "ScanMemberFields. Value type field %s has reference type contents. Boxing and adding to QOM.\n", pSrcField->GetName()));
- }
- }
- else
- {
- DWORD numBytesToCopy = th.AsMethodTable()->GetNumInstanceFieldBytes();
- BYTE *pByte = m_currObject->GetData() + srcOffset;
- BYTE *pDest = m_newObject->GetData() + dstOffset;
- memcpyNoGCRefs(pDest, pByte, numBytesToCopy);
- LOG((LF_REMOTING, LL_INFO1000, "ScanMemberFields. Value type field %s has no reference type contents. Blitting.\n", pSrcField->GetName()));
- }
- }
- break;
- default:
- _ASSERTE(!"Unknown element type seen in ObjectClone::ScanMemberFields");
- break;
- }
-
- return bFixupNeeded ? 1 : 0;
-}
-
-BOOL ObjectClone::AreTypesEmittedIdentically(MethodTable *pMT1, MethodTable *pMT2)
-{
- LIMITED_METHOD_CONTRACT;
-
- // Identical here means that both types have the same hierarchy (depth and names match) and that each level of the hierarchy has
- // the same fields (by name) at the same index.
- // We're going to be called quite frequently (once per call to ScanMemberFields) so until we're convinced that caching this
- // information is worth it we'll just compute the fast cases here and let the rest fall through to the slower technique. The
- // fast check is that the types are shared and identical or that they're loaded from the same file (in which case we have to be
- // a little more paranoid and check up the hierarchy).
- if (pMT1 == pMT2)
- return TRUE;
-
- // While the current level of the type is loaded from the same file...
- // Note that we used to check that the assemblies were the same; now we're more paranoid and check the actual modules scoping
- // the type are identical. This closes a security hole where identically named types in different modules of the same assembly
- // could cause the wrong type to be loaded in the server context allowing violation of the type system.
- while (pMT1->GetModule()->GetFile()->Equals(pMT2->GetModule()->GetFile()))
- {
- // Inspect the parents.
- pMT1 = pMT1->GetParentMethodTable();
- pMT2 = pMT2->GetParentMethodTable();
-
- // If the parents are the same shared type (e.g. Object), then we've found a match.
- if (pMT1 == pMT2)
- return TRUE;
-
- // Else check if one of the hierarchies has run out before the other (and therefore can't be equivalent).
- if (pMT1 == NULL || pMT2 == NULL)
- return FALSE;
- }
-
- return FALSE;
-}
-
-BOOL AreTypesEquivalent(MethodTable *pMT1, MethodTable *pMT2)
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- THROWS;
- }
- CONTRACTL_END;
-
- // Equivalent here is quite a weak predicate. All it means is that the types have the same (fully assembly qualified) name. The
- // derivation hierarchy is not inspected at all.
- StackSString szType1;
- StackSString szType2;
-
- TypeString::AppendType(szType1, TypeHandle(pMT1), TypeString::FormatNamespace |
- TypeString::FormatFullInst |
- TypeString::FormatAssembly |
- TypeString::FormatNoVersion);
- TypeString::AppendType(szType2, TypeHandle(pMT2), TypeString::FormatNamespace |
- TypeString::FormatFullInst |
- TypeString::FormatAssembly |
- TypeString::FormatNoVersion);
-
- return szType1.Equals(szType2);
-}
-
-PtrHashMap *CrossDomainFieldMap::s_pFieldMap = NULL;
-SimpleRWLock *CrossDomainFieldMap::s_pFieldMapLock = NULL;
-
-BOOL CrossDomainFieldMap::CompareFieldMapEntry(UPTR val1, UPTR val2)
-{
- CONTRACTL {
- MODE_ANY;
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- CrossDomainFieldMap::FieldMapEntry *pEntry1 = (CrossDomainFieldMap::FieldMapEntry *)(val1 << 1);
- CrossDomainFieldMap::FieldMapEntry *pEntry2 = (CrossDomainFieldMap::FieldMapEntry *)val2;
-
- if (pEntry1->m_pSrcMT == pEntry2->m_pSrcMT &&
- pEntry1->m_pDstMT == pEntry2->m_pDstMT)
- return TRUE;
-
- return FALSE;
-}
-
-CrossDomainFieldMap::FieldMapEntry::FieldMapEntry(MethodTable *pSrcMT, MethodTable *pDstMT, FieldDesc **pFieldMap)
-{
- WRAPPER_NO_CONTRACT;
-
- m_pSrcMT = pSrcMT;
- m_pDstMT = pDstMT;
- m_pFieldMap = pFieldMap;
- BaseDomain *pSrcDomain = pSrcMT->GetDomain();
- m_dwSrcDomain = pSrcDomain->IsAppDomain() ? ((AppDomain*)pSrcDomain)->GetId() : ADID(0);
- BaseDomain *pDstDomain = pDstMT->GetDomain();
- m_dwDstDomain = pDstDomain->IsAppDomain() ? ((AppDomain*)pDstDomain)->GetId() : ADID(0);
-}
-
-static BOOL IsOwnerOfRWLock(LPVOID lock)
-{
- // @TODO - SimpleRWLock does not have knowledge of which thread gets the writer
- // lock, so no way to verify
- return TRUE;
-}
-
-// Remove any entries in the table that refer to an appdomain that is no longer live.
-void CrossDomainFieldMap::FlushStaleEntries()
-{
- if (s_pFieldMapLock == NULL || s_pFieldMap == NULL)
- return;
-
- SimpleWriteLockHolder swlh(s_pFieldMapLock);
-
- bool fDeletedEntry = false;
- PtrHashMap::PtrIterator iter = s_pFieldMap->begin();
- while (!iter.end())
- {
- FieldMapEntry *pEntry = (FieldMapEntry *)iter.GetValue();
- AppDomainFromIDHolder adFrom(pEntry->m_dwSrcDomain, TRUE);
- AppDomainFromIDHolder adTo(pEntry->m_dwDstDomain, TRUE);
- if (adFrom.IsUnloaded() ||
- adTo.IsUnloaded()) //we do not use ptr for anything
- {
-#ifdef _DEBUG
- LPVOID pDeletedEntry =
-#endif
- s_pFieldMap->DeleteValue(pEntry->GetHash(), pEntry);
- _ASSERTE(pDeletedEntry == pEntry);
- delete pEntry;
- fDeletedEntry = true;
- }
- ++iter;
- }
-
- if (fDeletedEntry)
- s_pFieldMap->Compact();
-}
-
-FieldDesc **CrossDomainFieldMap::LookupOrCreateFieldMapping(MethodTable *pDstMT, MethodTable *pSrcMT)
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- THROWS;
- }
- CONTRACTL_END;
-
- // We lazily allocate the reader/writer lock we synchronize access to the hash with.
- if (s_pFieldMapLock == NULL)
- {
- void *pLockSpace = SystemDomain::GetGlobalLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(SimpleRWLock)));
- SimpleRWLock *pLock = new (pLockSpace) SimpleRWLock(COOPERATIVE_OR_PREEMPTIVE, LOCK_TYPE_DEFAULT);
-
- if (FastInterlockCompareExchangePointer(&s_pFieldMapLock, pLock, NULL) != NULL)
- // We lost the race, give up our copy.
- SystemDomain::GetGlobalLoaderAllocator()->GetLowFrequencyHeap()->BackoutMem(pLockSpace, sizeof(SimpleRWLock));
- }
-
- // Now we have a lock we can use to synchronize the remainder of the init.
- if (s_pFieldMap == NULL)
- {
- SimpleWriteLockHolder swlh(s_pFieldMapLock);
-
- if (s_pFieldMap == NULL)
- {
- PtrHashMap *pMap = new (SystemDomain::GetGlobalLoaderAllocator()->GetLowFrequencyHeap()) PtrHashMap();
- LockOwner lock = {s_pFieldMapLock, IsOwnerOfRWLock};
- pMap->Init(32, CompareFieldMapEntry, TRUE, &lock);
- s_pFieldMap = pMap;
- }
- }
- else
- {
- // Try getting an existing value first.
-
- FieldMapEntry sEntry(pSrcMT, pDstMT, NULL);
-
- SimpleReadLockHolder srlh(s_pFieldMapLock);
- FieldMapEntry *pFound = (FieldMapEntry *)s_pFieldMap->LookupValue(sEntry.GetHash(), (LPVOID)&sEntry);
- if (pFound != (FieldMapEntry *)INVALIDENTRY)
- return pFound->m_pFieldMap;
- }
-
- // We couldn't find an existing entry in the hash. Now we must go through the painstaking process of matching fields in the
- // destination object to their counterparts in the source object. We build an array of pointers to source field descs ordered by
- // destination type field index (all the fields for the most derived type first, then all the fields for the second most derived
- // type etc.).
- NewArrayHolder<FieldDesc*> pFieldMap(new FieldDesc*[pDstMT->GetNumInstanceFields()]);
- DWORD dwMapIndex = 0;
-
- // We start with the source and destination types for the object (which we know are equivalent at least in type name). For each
- // layer of the type hierarchy for the destination object (from the instance type through to Object) we attempt to locate the
- // corresponding source type in the hierarchy. This is non-trivial since either source or destination type hierarchies may have
- // added or removed layers. We ignore extra type layers in the source hierarchy and just concentrate on destination type layers
- // that introduce instance fields that are not marked NotSerializable. For each such layer we first locate the corresponding
- // source layer (via fully qualified type name) and then map each serialized (and possibly optional) destination field to the
- // corresponding source field (again by name). We don't allow a field to move around the type hierarchy (i.e. a field defined in
- // the base class in one version can't move to a derived type in later versions and be recognized as the original field).
- // Allowing this would introduce all sorts of ambiguity problems (consider the case of private fields all with the same name
- // implemented at every layer of the type hierarchy).
-
- bool fFirstPass = true;
- MethodTable *pCurrDstMT = pDstMT;
- MethodTable *pCurrSrcMT = pSrcMT;
- while (pCurrDstMT)
- {
- DWORD numInstanceFields = pCurrDstMT->GetNumIntroducedInstanceFields();
-
- // Skip destination types with no instance fields to clone.
- if (numInstanceFields == 0)
- {
- pCurrDstMT = pCurrDstMT->GetParentMethodTable();
- // Only safe to skip the source type as well on the first pass (the source version may have eliminated this level of
- // the type hierarchy).
- if (fFirstPass)
- pCurrSrcMT = pCurrSrcMT->GetParentMethodTable();
- fFirstPass = false;
- continue;
- }
-
- // We need to synchronize the source type with the destination type. This means skipping any source types in the
- // hierarchy that the destination doesn't know about.
- MethodTable *pCandidateMT = pCurrSrcMT;
- while (pCandidateMT)
- {
- if (fFirstPass || pCandidateMT == pCurrDstMT || AreTypesEquivalent(pCandidateMT, pCurrDstMT))
- {
- // Skip intermediate source types (the destination type didn't know anything about them, so they're surplus
- // to requirements).
- pCurrSrcMT = pCandidateMT;
- break;
- }
-
- pCandidateMT = pCandidateMT->GetParentMethodTable();
- }
-
-#ifdef OBJECT_CLONER_STRICT_MODE
- // If there's no candidate source type equivalent to the current destination type we need to prove that the destination
- // type has no mandatory instance fields or throw an exception (since there's no place to fetch the field values from).
- if (pCandidateMT == NULL)
- {
- FieldDesc *pFields = pCurrDstMT->GetApproxFieldDescListRaw();
-
- for (DWORD i = 0; i < numInstanceFields; i++)
- {
- if (pFields[i].IsNotSerialized() || pFields[i].IsOptionallySerialized())
- {
- pFieldMap[dwMapIndex++] = NULL;
- continue;
- }
-
- // We've found a field that must be cloned but have no corresponding source-side type to clone it from. Raise an
- // exception.
- ThrowMissingFieldException(&pFields[i]);
- }
-
- // If we get here we know the current destination type level was effectively a no-op. Move onto the next level.
- pCurrDstMT = pCurrDstMT->GetParentMethodTable();
- fFirstPass = false;
- continue;
- }
-#else
- // In lax matching mode we can ignore all fields, even those not marked optional. So the lack of an equivalent type in the
- // source hierarchy doesn't bother us. Mark all fields as having a default value and then move onto the next level in the
- // type hierarchy.
- if (pCandidateMT == NULL)
- {
- for (DWORD i = 0; i < numInstanceFields; i++)
- pFieldMap[dwMapIndex++] = NULL;
-
- pCurrDstMT = pCurrDstMT->GetParentMethodTable();
- fFirstPass = false;
- continue;
- }
-#endif
-
- // If we get here we have equivalent types in pCurrDstMT and pCurrSrcMT. Now we need to locate the source field desc
- // corresponding to every mandatory (and possibly optional) field in the destination type and record it in the field map.
- DWORD numSrcFields = pCurrSrcMT->GetNumIntroducedInstanceFields();
- DWORD numDstFields = pCurrDstMT->GetNumIntroducedInstanceFields();
-
- FieldDesc *pDstFields = pCurrDstMT->GetApproxFieldDescListRaw();
- FieldDesc *pSrcFields = pCurrSrcMT->GetApproxFieldDescListRaw();
-
- for (DWORD i = 0; i < numDstFields; i++)
- {
- // Non-serialized destination fields aren't filled in from source types.
- if (pDstFields[i].IsNotSerialized())
- {
- pFieldMap[dwMapIndex++] = NULL;
- continue;
- }
-
- // Go look for a field in the source type with the same name.
- LPCUTF8 szDstFieldName = pDstFields[i].GetName();
- DWORD j;
- for (j = 0; j < numSrcFields; j++)
- {
- LPCUTF8 szSrcFieldName = pSrcFields[j].GetName();
- if (strcmp(szDstFieldName, szSrcFieldName) == 0)
- {
- // Check that the field isn't marked NotSerialized (if it is then it's invisible to the cloner).
- if (pSrcFields[j].IsNotSerialized())
- j = numSrcFields;
- break;
- }
- }
-
-#ifdef OBJECT_CLONER_STRICT_MODE
- // If we didn't find a corresponding field it might not be fatal; the field could be optionally serializable from the
- // destination type's point of view.
- if (j == numSrcFields)
- {
- if (pDstFields[i].IsOptionallySerialized())
- {
- pFieldMap[dwMapIndex++] = NULL;
- continue;
- }
- // The field was required. Throw an exception.
- ThrowMissingFieldException(&pDstFields[i]);
- }
-#else
- // In lax matching mode we can ignore all fields, even those not marked optional. Simply mark this field as having the
- // default value.
- if (j == numSrcFields)
- {
- pFieldMap[dwMapIndex++] = NULL;
- continue;
- }
-#endif
-
- // Otherwise we found matching fields (in name at least, type processing is done later).
- pFieldMap[dwMapIndex++] = &pSrcFields[j];
- }
-
- pCurrDstMT = pCurrDstMT->GetParentMethodTable();
- pCurrSrcMT = pCurrSrcMT->GetParentMethodTable();
- fFirstPass = false;
- }
-
- _ASSERTE(dwMapIndex == pDstMT->GetNumInstanceFields());
-
- // Now we have a field map we should insert it into the hash.
- NewHolder<FieldMapEntry> pEntry(new FieldMapEntry(pSrcMT, pDstMT, pFieldMap));
- PREFIX_ASSUME(pEntry != NULL);
- pFieldMap.SuppressRelease();
-
- SimpleWriteLockHolder swlh(s_pFieldMapLock);
-
- UPTR key = pEntry->GetHash();
-
- FieldMapEntry *pFound = (FieldMapEntry *)s_pFieldMap->LookupValue(key, (LPVOID)pEntry);
- if (pFound == (FieldMapEntry *)INVALIDENTRY)
- {
- s_pFieldMap->InsertValue(key, (LPVOID)pEntry);
- pEntry.SuppressRelease();
- return pFieldMap;
- }
- else
- return pFound->m_pFieldMap;
-}
-
-ARG_SLOT ObjectClone::HandleFieldTypeMismatch(CorElementType dstType, CorElementType srcType, void *pData, MethodTable *pSrcMT)
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- THROWS;
- }
- CONTRACTL_END
- _ASSERTE(m_context != ObjectFreezer);
- ARG_SLOT data = 0;
- InvokeUtil::CreatePrimitiveValue(dstType, srcType, pData, pSrcMT, &data);
- return data;
-}
-
-void ObjectClone::ScanISerializableMembers(DWORD IObjRefTSOIndex, DWORD ISerTSOIndex, DWORD BoxedValTSOIndex, PTRARRAYREF refValues)
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- THROWS;
- }
- CONTRACTL_END
-
- _ASSERTE(m_context != ObjectFreezer);
- // Queue the non-primitive types
- DWORD numFieldsToBeMarshalled = 0;
- PTRARRAYREF refNewValues = NULL;
-
- LOG((LF_REMOTING, LL_INFO1000, "ScanISerializableMembers. Scanning members of ISerializable type object.\n"));
- GCPROTECT_BEGIN(refValues);
-
- refNewValues = (PTRARRAYREF) AllocateObjectArray(refValues->GetNumComponents(), g_pObjectClass, FALSE);
-
- _ASSERTE(refNewValues != NULL);
-
- for (DWORD index = 0; index < refValues->GetNumComponents(); index++)
- {
- OBJECTREF refField = refValues->GetAt(index);
- if (refField == NULL)
- continue;
-
- if (CorTypeInfo::IsPrimitiveType(refField->GetTypeHandle().GetSignatureCorElementType()) ||
- refField->GetMethodTable() == g_pStringClass)
- {
- refNewValues->SetAt(index, refField);
- continue;
- }
-
- ISerializableMemberInfo isInfo(ISerTSOIndex, index);
- QOM.Enqueue(refField, NULL, NULL, (QueuedObjectInfo *) &isInfo);
- numFieldsToBeMarshalled++;
- refNewValues->SetAt(index, NULL);
- LOG((LF_REMOTING, LL_INFO1000, "ScanISerializableMembers. Member at index %d is reference type. Adding to QOM.\n", index));
- }
- GCPROTECT_END();
-
- // Update TSO
- OBJECTREF refNames = NULL, refFields = NULL;
- QueuedObjectInfo *pDummy;
- OBJECTREF newObj;
- newObj = TSO.GetAt(ISerTSOIndex, &refNames, &refFields, &pDummy);
- _ASSERTE(newObj == m_newObject);
-
- TSO.SetAt(ISerTSOIndex, m_newObject, refNames, refNewValues, pDummy);
-
- if (numFieldsToBeMarshalled > 0)
- {
- ParentInfo fxInfo(numFieldsToBeMarshalled);
- fxInfo.SetIsISerializableInstance();
- fxInfo.SetIObjRefIndexIntoTSO(IObjRefTSOIndex);
- fxInfo.SetISerIndexIntoTSO(ISerTSOIndex);
- fxInfo.SetBoxedValIndexIntoTSO(BoxedValTSOIndex);
- QOF.Enqueue(m_newObject, NULL, NULL, (QueuedObjectInfo *) &fxInfo);
- LOG((LF_REMOTING, LL_INFO1000, "ScanISerializableMembers. Current object had total of %d reference type fields. Adding to QOF.\n", numFieldsToBeMarshalled));
- // Delay calling any OnDeserialized callbacks until the end of the cloning operation (it's difficult to tell when all the
- // children have been deserialized).
- if (HasVtsCallbacks(m_newObject->GetMethodTable(), RemotingVtsInfo::VTS_CALLBACK_ON_DESERIALIZED))
- VDC.Enqueue(m_newObject, NULL, NULL, NULL);
- if (m_cbInterface->RequiresDeserializationCallback(m_newObject->GetMethodTable()))
- {
- LOG((LF_REMOTING, LL_INFO1000, "ScanISerializableMembers. Adding object to Table of IDeserialization Callbacks\n"));
- QueuedObjectInfo noInfo;
- TDC.Enqueue(m_newObject, NULL, NULL, &noInfo);
- }
- }
- else
- {
- // This is effectively a leaf node (no complex children) so if the type has a callback for OnDeserialized we'll deliver it
- // now. This fixes callback ordering for a few more edge cases (e.g. VSW 415611) and is reasonably cheap. We can never do a
- // perfect job (in the presence of object graph cycles) and a near perfect job (intuitively ordered callbacks for acyclic
- // object graphs) is prohibitively expensive; so we're stuck with workarounds like this.
- InvokeVtsCallbacks(m_newObject, RemotingVtsInfo::VTS_CALLBACK_ON_DESERIALIZED, m_toDomain);
- if (m_cbInterface->RequiresDeserializationCallback(m_newObject->GetMethodTable()))
- MakeIDeserializationCallback(m_newObject);
- }
-}
-
-void ObjectClone::ScanArrayMembers()
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- THROWS;
- }
- CONTRACTL_END
-#ifdef _DEBUG
- MethodTable *pCurrMT = m_currObject->GetMethodTable();
- _ASSERTE(pCurrMT && pCurrMT->IsArray());
- MethodTable *pNewMT = m_newObject->GetMethodTable();
- _ASSERTE(pNewMT && pNewMT->IsArray());
-#endif
-
- LOG((LF_REMOTING, LL_INFO1000, "ScanArrayMembers. Scanning members of array object.\n"));
- BASEARRAYREF refFromArray = (BASEARRAYREF) m_currObject;
- BASEARRAYREF refToArray = (BASEARRAYREF) m_newObject;
-
- GCPROTECT_BEGIN(refFromArray);
- GCPROTECT_BEGIN(refToArray);
-
- TypeHandle toArrayElementType = refToArray->GetArrayElementTypeHandle();
- DWORD numComponents = refFromArray->GetNumComponents();
- MethodTable *pArrayMT = refFromArray->GetMethodTable();
-
- DWORD rank = pArrayMT->GetRank();
- DWORD dwOffset = 0;
-
- DWORD *pIndices = (DWORD*) _alloca(sizeof(DWORD) * rank);
- VOID *pTemp = _alloca(sizeof(NDimArrayMemberInfo) + rank * sizeof(DWORD));
- NDimArrayMemberInfo *pArrInfo = new (pTemp) NDimArrayMemberInfo(rank);
-
- bool boxingObjects = (pArrayMT->GetArrayElementType() == ELEMENT_TYPE_VALUETYPE);
-
- // Must enter the from domain if we are going to be allocating any non-agile boxes
- ENTER_DOMAIN_PTR_PREDICATED(m_fromDomain,ADV_RUNNINGIN,boxingObjects);
-
- if (boxingObjects)
- {
- pArrInfo->SetNeedsUnboxing();
-
- // We may be required to activate value types of array elements, since we
- // are going to box them. Hoist out the required domain transition and
- // activation.
-
- MethodTable *pMT = ((BASEARRAYREF)m_currObject)->GetArrayElementTypeHandle().GetMethodTable();
- pMT->EnsureInstanceActive();
- }
-
- DWORD numFixupsNeeded = 0;
- for (DWORD i = 0; i < numComponents; i++)
- {
- // The array could be huge. To avoid keeping a pending GC waiting (and maybe timing out) we're going to pulse the GC mode
- // every so often. Do this more freqeuntly in debug builds, where each iteration through this loop takes considerably
- // longer.
-#ifdef _DEBUG
-#define COPY_CYCLES 1024
-#else
-#define COPY_CYCLES 8192
-#endif
- if ((i % COPY_CYCLES) == (COPY_CYCLES - 1))
- GetThread()->PulseGCMode();
-
- const INT32 *pBoundsPtr = refFromArray->GetBoundsPtr();
- DWORD findIndices = i;
- for (DWORD rankIndex = rank; rankIndex > 0; rankIndex--)
- {
- DWORD numElementsInDimension = pBoundsPtr[rankIndex - 1];
- DWORD quotient = findIndices / numElementsInDimension;
- DWORD remainder = findIndices % numElementsInDimension;
- pIndices[rankIndex - 1] = remainder;
- findIndices = quotient;
- }
-
- pArrInfo->SetIndices(pIndices);
-
- Object *rv = GetObjectFromArray((BASEARRAYREF *)&m_currObject, dwOffset);
- if (rv != NULL)
- {
- OBJECTREF oRef = ObjectToOBJECTREF(rv);
-
- if (oRef->GetMethodTable() == g_pStringClass && m_context != ObjectFreezer)
- {
- OBJECTREF* pElem = (OBJECTREF*)(refToArray->GetDataPtr() + (dwOffset * pArrayMT->GetComponentSize()));
- SetObjectReference(pElem,oRef,GetAppDomain());
- }
- else
- {
- // Add the object to QOM
- numFixupsNeeded++;
- QOM.Enqueue(oRef, NULL, NULL, pArrInfo);
- LOG((LF_REMOTING, LL_INFO1000, "ScanArrayMembers. Element at offset %d is reference type. Adding to QOM.\n", dwOffset));
- }
- }
- dwOffset ++;
- }
-
- if (numFixupsNeeded > 0)
- {
- ParentInfo fxInfo(numFixupsNeeded);
- QOF.Enqueue(m_newObject, NULL, NULL, (QueuedObjectInfo *)&fxInfo);
- LOG((LF_REMOTING, LL_INFO1000, "ScanArrayMembers. Current object had total of %d reference type fields. Adding to QOF.\n", numFixupsNeeded));
- }
-
- END_DOMAIN_TRANSITION;
-
- GCPROTECT_END();
- GCPROTECT_END();
-}
-
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable:4244)
-#endif // _MSC_VER
-Object *ObjectClone::GetObjectFromArray(BASEARRAYREF* arrObj, DWORD dwOffset)
-{
- CONTRACTL {
- THROWS;
- if ((*arrObj)->GetArrayElementTypeHandle().GetMethodTable()->IsValueType()) GC_TRIGGERS; else GC_NOTRIGGER;
- } CONTRACTL_END;
-
- // Get the type of the element...
- switch ((*arrObj)->GetArrayElementType()) {
-
- case ELEMENT_TYPE_VOID:
- return NULL;
-
- case ELEMENT_TYPE_CLASS: // Class
- case ELEMENT_TYPE_SZARRAY: // Single Dim, Zero
- case ELEMENT_TYPE_ARRAY: // General Array
- case ELEMENT_TYPE_STRING:
- case ELEMENT_TYPE_OBJECT:
- {
- _ASSERTE((*arrObj)->GetComponentSize() == sizeof(OBJECTREF));
- BYTE* pData = ((BYTE*)(*arrObj)->GetDataPtr()) + (dwOffset * sizeof(OBJECTREF));
- return *(Object **)pData;
- }
-
- case ELEMENT_TYPE_VALUETYPE:
- {
- MethodTable *pMT = (*arrObj)->GetArrayElementTypeHandle().GetMethodTable();
- WORD wComponentSize = (*arrObj)->GetComponentSize();
- BYTE* pData = ((BYTE*)(*arrObj)->GetDataPtr()) + (dwOffset * wComponentSize);
- return OBJECTREFToObject(pMT->Box(pData));
- }
- case ELEMENT_TYPE_BOOLEAN: // boolean
- case ELEMENT_TYPE_I1: // sbyte
- case ELEMENT_TYPE_U1:
- case ELEMENT_TYPE_I2: // short
- case ELEMENT_TYPE_U2:
- case ELEMENT_TYPE_CHAR: // char
- case ELEMENT_TYPE_I4: // int
- case ELEMENT_TYPE_I:
- case ELEMENT_TYPE_U:
- case ELEMENT_TYPE_U4:
- case ELEMENT_TYPE_I8: // long
- case ELEMENT_TYPE_U8:
- case ELEMENT_TYPE_R4: // float
- case ELEMENT_TYPE_R8: // double
- case ELEMENT_TYPE_PTR:
- {
- // Note that this is a cloned version of the value class case above for performance
-
- // Watch for GC here. We allocate the object and then
- // grab the void* to the data we are going to copy.
- MethodTable *pMT = (*arrObj)->GetArrayElementTypeHandle().GetMethodTable();
- OBJECTREF obj = ::AllocateObject(pMT);
- WORD wComponentSize = (*arrObj)->GetComponentSize();
- BYTE* pData = ((BYTE*)(*arrObj)->GetDataPtr()) + (dwOffset * wComponentSize);
- CopyValueClassUnchecked(obj->UnBox(), pData, (*arrObj)->GetArrayElementTypeHandle().GetMethodTable());
- return OBJECTREFToObject(obj);
- }
-
- case ELEMENT_TYPE_END:
- default:
- _ASSERTE(!"Unknown array element type");
- }
-
- _ASSERTE(!"Should never get here");
- return NULL;
-}
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif // _MSC_VER: warning C4244
-
-
-void ObjectClone::CompleteValueTypeFields(OBJECTREF newObj, OBJECTREF refParent, QueuedObjectInfo *objInfo)
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- THROWS;
- }
- CONTRACTL_END
-
-#ifdef _DEBUG
- {
- SString ssTypeName;
- SString ssParentTypeName;
- newObj->GetMethodTable()->_GetFullyQualifiedNameForClassNestedAware(ssTypeName);
- refParent->GetMethodTable()->_GetFullyQualifiedNameForClassNestedAware(ssParentTypeName);
- LOG((LF_REMOTING, LL_INFO1000, "CompleteValueTypeFields. Fixing up value type field of type %S into parent of type %S.\n",
- ssTypeName.GetUnicode(), ssParentTypeName.GetUnicode()));
- }
-#endif
-
- ValueTypeInfo *pValTypeInfo = (ValueTypeInfo *)objInfo;
- QueuedObjectInfo *pFixupInfo = pValTypeInfo->GetFixupInfo();
- PREFIX_ASSUME(pFixupInfo != NULL);
-
- _ASSERTE(pFixupInfo->NeedsUnboxing());
- if (pFixupInfo->IsArray())
- {
- m_newObject = newObj;
- HandleArrayFixup(refParent, pFixupInfo);
- }
- else
- {
- GCPROTECT_BEGIN(refParent);
- GCPROTECT_BEGIN(newObj);
- ObjectMemberInfo *pObjInfo = (ObjectMemberInfo *)pFixupInfo;
- FieldDesc *pTargetField = pObjInfo->GetFieldDesc();
-
- TypeHandle fldType = LoadExactFieldType(pTargetField, refParent, m_toDomain);
- void *pDest = refParent->GetData() + pTargetField->GetOffset();
- _ASSERTE(GetAppDomain()==m_toDomain);
-
- if (!fldType.GetMethodTable()->UnBoxInto(pDest, newObj))
- COMPlusThrow(kArgumentException,W("Arg_ObjObj"));
-
- GCPROTECT_END();
- GCPROTECT_END();
- }
- pValTypeInfo->SetHasBeenProcessed();
-}
-
-void ObjectClone::CompleteSpecialObjects()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
-
- OBJECTREF nextObj = NULL;
- OBJECTREF refNames = NULL;
- OBJECTREF refValues = NULL;
- SpecialObjectInfo *pObjInfo = NULL;
-
- GCPROTECT_BEGIN(refNames);
- GCPROTECT_BEGIN(refValues);
-
- DWORD skippedObjects = 0;
- DWORD numLoops = 0;
-
- if (TSO.GetCount() == 0)
- goto EarlyExit;
-
- LOG((LF_REMOTING, LL_INFO1000, "CompleteSpecialObjects. Beginning.\n"));
- do
- {
- skippedObjects = 0;
- numLoops++;
- DWORD index = 0;
- TSO.BeginEnumeration(&index);
- while((nextObj = TSO.GetNext(&index, &refNames, &refValues, (QueuedObjectInfo **)&pObjInfo)) != NULL)
- {
- if (pObjInfo->HasBeenProcessed())
- continue;
-
- if (pObjInfo->IsISerializableInstance())
- {
- _ASSERTE(m_context != ObjectFreezer);
-
- LOG((LF_REMOTING, LL_INFO1000, "CompleteSpecialObjects. ISerializable instance at index %d.\n", index));
- ISerializableInstanceInfo *iserInfo = (ISerializableInstanceInfo *)pObjInfo;
- if (iserInfo->GetNumSpecialMembers() > 0)
- {
- if (CheckForUnresolvedMembers(iserInfo))
- {
- LOG((LF_REMOTING, LL_INFO1000, "CompleteSpecialObjects. Skipping ISerializable instance due to unresolved members.\n"));
- skippedObjects++;
- continue;
- }
- }
- CompleteISerializableObject(nextObj, refNames, refValues, iserInfo);
- }
- else if (pObjInfo->IsIObjRefInstance())
- {
- _ASSERTE(m_context != ObjectFreezer);
-
- LOG((LF_REMOTING, LL_INFO1000, "CompleteSpecialObjects. IObjectReference instance at index %d.\n", index));
- IObjRefInstanceInfo *iorInfo = (IObjRefInstanceInfo *)pObjInfo;
- if (iorInfo->GetNumSpecialMembers() > 0 ||
- iorInfo->GetISerTSOIndex() != (DWORD) -1)
- {
- if (CheckForUnresolvedMembers(iorInfo))
- {
- LOG((LF_REMOTING, LL_INFO1000, "CompleteSpecialObjects. Skipping IObjectReference instance due to unresolved members.\n"));
- skippedObjects++;
- continue;
- }
- }
- if (!CompleteIObjRefObject(nextObj, index, iorInfo))
- skippedObjects++;
- }
- else
- {
- _ASSERTE(pObjInfo->IsBoxedObject());
- LOG((LF_REMOTING, LL_INFO1000, "CompleteSpecialObjects. Boxed valuetype instance at index %d.\n", index));
- ValueTypeInfo *valTypeInfo = (ValueTypeInfo *)pObjInfo;
- if (valTypeInfo->GetNumSpecialMembers() > 0 ||
- valTypeInfo->GetISerTSOIndex() != (DWORD) -1 ||
- valTypeInfo->GetIObjRefTSOIndex() != (DWORD) -1)
- {
- if (CheckForUnresolvedMembers(valTypeInfo))
- {
- LOG((LF_REMOTING, LL_INFO1000, "CompleteSpecialObjects. Skipping boxed value instance due to unresolved members.\n"));
- skippedObjects++;
- continue;
- }
- }
- // If we were waiting on an IObjRef fixup then the target object will have changed.
- if (valTypeInfo->GetIObjRefTSOIndex() != (DWORD) -1)
- {
- OBJECTREF dummy1, dummy2;
- QueuedObjectInfo *dummy3;
- nextObj = TSO.GetAt(valTypeInfo->GetIObjRefTSOIndex(), &dummy1, &dummy2, &dummy3);
- }
- CompleteValueTypeFields(nextObj, refNames, valTypeInfo);
- }
-
- };
- } while (skippedObjects > 0 && numLoops < 100);
-
- if (skippedObjects > 0 && numLoops >= 100)
- {
- COMPlusThrow(kSerializationException, IDS_SERIALIZATION_UNRESOLVED_SPECIAL_OBJECT);
- }
-EarlyExit: ;
- GCPROTECT_END();
- GCPROTECT_END();
-}
-
-BOOL ObjectClone::CheckForUnresolvedMembers(SpecialObjectInfo *splInfo)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
-
- BOOL foundUnresolvedMember = FALSE;
-
- DWORD mappingIndex = splInfo->GetMappingTableIndex();
- for (DWORD count = 0; count < splInfo->GetNumSpecialMembers(); count++)
- {
- DWORD memberIndex = TMappings.GetAt(mappingIndex++);
- SpecialObjectInfo *pMemberInfo;
- OBJECTREF dummy1, dummy2, dummy3;
- dummy1 = TSO.GetAt(memberIndex, &dummy2, &dummy3, (QueuedObjectInfo **)&pMemberInfo);
- // An unresolved IObjRef member is a blocker for any special object parent
- if (pMemberInfo->IsIObjRefInstance() && !pMemberInfo->HasBeenProcessed())
- {
- LOG((LF_REMOTING, LL_INFO1000, "CheckForUnresolvedMembers. Found unresolved IObjectReference member at index %d.\n", memberIndex));
- foundUnresolvedMember = TRUE;
- break;
- }
-
- // An unresolved ISer member is a blocker for IObjRef parent
- if (pMemberInfo->IsISerializableInstance() &&
- !pMemberInfo->HasBeenProcessed() &&
- splInfo->IsIObjRefInstance())
- {
- LOG((LF_REMOTING, LL_INFO1000, "CheckForUnresolvedMembers. Found unresolved ISerializable member at index %d.\n", memberIndex));
- foundUnresolvedMember = TRUE;
- break;
- }
-
- // An unresolved boxed object is a blocker for a boxed parent or an IObjRef parent
- if (pMemberInfo->IsBoxedObject() &&
- !pMemberInfo->HasBeenProcessed() &&
- (splInfo->IsIObjRefInstance() || splInfo->IsBoxedObject()))
- {
- LOG((LF_REMOTING, LL_INFO1000, "CheckForUnresolvedMembers. Found unresolved boxed valuetype member at index %d.\n", memberIndex));
- foundUnresolvedMember = TRUE;
- break;
- }
- }
-
- // Done checking members. Now check if this instance itself needs some processing
- // If an instance is both ISer and IObj, then ISer should be processed before IObjRef
- if (!foundUnresolvedMember && splInfo->IsIObjRefInstance())
- {
- IObjRefInstanceInfo *pObjRefInfo = (IObjRefInstanceInfo *)splInfo;
- if (pObjRefInfo->GetISerTSOIndex() != (DWORD) -1)
- {
- // Check if the ISer requirements have been met
- SpecialObjectInfo *pMemberInfo;
- OBJECTREF dummy1, dummy2, dummy3;
- dummy1 = TSO.GetAt(pObjRefInfo->GetISerTSOIndex(), &dummy2, &dummy3, (QueuedObjectInfo **)&pMemberInfo);
- if (!pMemberInfo->HasBeenProcessed())
- {
- LOG((LF_REMOTING, LL_INFO1000, "CheckForUnresolvedMembers. This instance is also ISerializable at index %d. Not resolved yet.\n", pObjRefInfo->GetISerTSOIndex()));
- foundUnresolvedMember = TRUE;
- }
- }
- }
-
- // If an instance is ISer, IObj and a boxed value type, then ISer,IObj should be processed before unboxing
- if (!foundUnresolvedMember && splInfo->IsBoxedObject())
- {
- ValueTypeInfo *pValTypeInfo = (ValueTypeInfo *)splInfo;
- if (pValTypeInfo->GetISerTSOIndex() != (DWORD) -1)
- {
- // Check if the ISer requirements have been met
- SpecialObjectInfo *pMemberInfo;
- OBJECTREF dummy1, dummy2, dummy3;
- dummy1 = TSO.GetAt(pValTypeInfo->GetISerTSOIndex(), &dummy2, &dummy3, (QueuedObjectInfo **)&pMemberInfo);
- if (!pMemberInfo->HasBeenProcessed())
- {
- LOG((LF_REMOTING, LL_INFO1000, "CheckForUnresolvedMembers. This instance is also ISerializable at index %d. Not resolved yet.\n", pValTypeInfo->GetISerTSOIndex()));
- foundUnresolvedMember = TRUE;
- }
- }
- if (!foundUnresolvedMember && pValTypeInfo->GetIObjRefTSOIndex() != (DWORD) -1)
- {
- // Check if the ISer requirements have been met
- SpecialObjectInfo *pMemberInfo;
- OBJECTREF dummy1, dummy2, dummy3;
- dummy1 = TSO.GetAt(pValTypeInfo->GetIObjRefTSOIndex(), &dummy2, &dummy3, (QueuedObjectInfo **)&pMemberInfo);
- if (!pMemberInfo->HasBeenProcessed())
- {
- LOG((LF_REMOTING, LL_INFO1000, "CheckForUnresolvedMembers. This instance is also IObjectReference at index %d. Not resolved yet.\n", pValTypeInfo->GetIObjRefTSOIndex()));
- foundUnresolvedMember = TRUE;
- }
- }
- }
- return foundUnresolvedMember;
-}
-
-void ObjectClone::CompleteISerializableObject(OBJECTREF IserObj, OBJECTREF refNames, OBJECTREF refValues, ISerializableInstanceInfo *iserInfo)
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END
-
- _ASSERTE(m_context != ObjectFreezer);
-
- struct _gc {
- OBJECTREF IserObj;
- OBJECTREF refNames;
- OBJECTREF refValues;
- OBJECTREF refSerInfo;
- } gc;
-
- gc.IserObj = IserObj;
- gc.refNames = refNames;
- gc.refValues = refValues;
- gc.refSerInfo = NULL;
-
- GCPROTECT_BEGIN(gc);
-
-#ifdef _DEBUG
- {
- DefineFullyQualifiedNameForClass();
- LOG((LF_REMOTING, LL_INFO1000, "CompleteISerializableObject. Completing ISerializable object of type %s.\n",
- GetFullyQualifiedNameForClassNestedAware(gc.IserObj->GetMethodTable())));
- }
-#endif
-
- BOOL bIsBoxed = gc.IserObj->GetMethodTable()->IsValueType();
-
- // StreamingContextData is an out parameter of the managed callback, so it's passed by reference on all platforms.
- RuntimeMethodHandle::StreamingContextData context = {0};
-
- PREPARE_NONVIRTUAL_CALLSITE(METHOD__OBJECTCLONEHELPER__PREPARE_DATA);
-
- DECLARE_ARGHOLDER_ARRAY(args, 4);
-
- args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(gc.IserObj);
- args[ARGNUM_1] = OBJECTREF_TO_ARGHOLDER(gc.refNames);
- args[ARGNUM_2] = OBJECTREF_TO_ARGHOLDER(gc.refValues);
- args[ARGNUM_3] = PTR_TO_ARGHOLDER(&context);
-
- CATCH_HANDLER_FOUND_NOTIFICATION_CALLSITE;
- CALL_MANAGED_METHOD_RETREF(gc.refSerInfo, OBJECTREF, args);
-
- if (iserInfo->IsTargetNotISerializable())
- {
- // Prepare data would have constructed the object already
- _ASSERTE(gc.refSerInfo == NULL);
- }
- else
- {
- _ASSERTE(gc.refSerInfo != NULL);
- MethodTable *pMT = gc.IserObj->GetMethodTable();
- _ASSERTE(pMT);
-
- MethodDesc * pCtor;
-
-#ifdef FEATURE_IMPERSONATION
- // Deal with the WindowsIdentity class specially by calling an internal
- // serialization constructor; the public one has a security demand that
- // breaks partial trust scenarios and is too expensive to assert for.
- if (MscorlibBinder::IsClass(pMT, CLASS__WINDOWS_IDENTITY))
- pCtor = MscorlibBinder::GetMethod(METHOD__WINDOWS_IDENTITY__SERIALIZATION_CTOR);
- else
-#endif
- pCtor = MemberLoader::FindConstructor(pMT, &gsig_IM_SerInfo_StrContext_RetVoid);
-
- if (pCtor == NULL)
- {
- DefineFullyQualifiedNameForClassW();
- COMPlusThrow(kSerializationException, IDS_SERIALIZATION_CTOR_NOT_FOUND,
- GetFullyQualifiedNameForClassNestedAwareW(pMT));
- }
-
- MethodDescCallSite ctor(pCtor);
-
- ARG_SLOT argSlots[3];
- // Nullable<T> does not implement ISerializable.
- _ASSERTE(!Nullable::IsNullableType(gc.IserObj->GetMethodTable()));
- argSlots[0] = (bIsBoxed ? (ARG_SLOT)(SIZE_T)(gc.IserObj->UnBox()) : ObjToArgSlot(gc.IserObj));
- argSlots[1] = ObjToArgSlot(gc.refSerInfo);
-#if defined(_TARGET_X86_) || defined(_TARGET_ARM_)
- static_assert_no_msg(sizeof(context) == sizeof(ARG_SLOT));
- argSlots[2] = *(ARG_SLOT*)(&context); // StreamingContext is passed by value on x86 and ARM
-#elif defined(_WIN64)
- static_assert_no_msg(sizeof(context) > sizeof(ARG_SLOT));
- argSlots[2] = PtrToArgSlot(&context); // StreamingContext is passed by reference on WIN64
-#else // !_TARGET_X86_ && !_WIN64 && !_TARGET_ARM_
- PORTABILITY_ASSERT("ObjectClone::CompleteISerializableObject() - NYI on this platform");
-#endif // !_TARGET_X86_ && !_WIN64 && !_TARGET_ARM_
- ctor.CallWithValueTypes(&argSlots[0]);
- }
- iserInfo->SetHasBeenProcessed();
-
- GCPROTECT_END();
-
-}
-
-// FALSE means the object could not be resolved and need to perform more iterations
-BOOL ObjectClone::CompleteIObjRefObject(OBJECTREF IObjRef, DWORD tsoIndex, IObjRefInstanceInfo *iorInfo)
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END
-
- BOOL bResult = FALSE;
-
- struct _gc {
- OBJECTREF IObjRef;
- OBJECTREF newObj;
- OBJECTREF refParent;
- OBJECTREF refFromObj;
- OBJECTREF resolvedObject;
- } gc;
-
- gc.IObjRef = IObjRef;
- gc.newObj = NULL;
- gc.refParent = NULL;
- gc.refFromObj = NULL;
- gc.resolvedObject = NULL;
-
- GCPROTECT_BEGIN(gc);
-
- _ASSERTE(m_context != ObjectFreezer);
- // First check if this is a repeat object
- if (iorInfo->IsRepeatObject())
- {
- OBJECTREF dummy;
- dummy = TSO.GetAt(tsoIndex, &gc.refFromObj, &gc.refParent, (QueuedObjectInfo **)&iorInfo);
- PREFIX_ASSUME(gc.refFromObj != NULL);
-
- // Look in the Table of Seen objects whether this IObjRef has been resolved
- int currId;
- currId = TOS.HasID(gc.refFromObj, &gc.resolvedObject);
- _ASSERTE(currId != -1);
-
- MethodTable *pResolvedMT = gc.resolvedObject->GetMethodTable();
- if (!pResolvedMT->IsTransparentProxy() &&
- m_cbInterface->IsIObjectReferenceType(pResolvedMT))
- {
- bResult = FALSE;
- }
- else
- {
-#ifdef _DEBUG
- {
- DefineFullyQualifiedNameForClass();
- LOG((LF_REMOTING, LL_INFO1000, "CompleteIObjRefObject. Found IObjectReference object of type %s already resolved.\n",
- GetFullyQualifiedNameForClassNestedAware(gc.IObjRef->GetMethodTable())));
- }
-#endif
-
- // Yes, its been resolved.
- // Fix the object into its parent (unless it requires unboxing, in which case there's another entry in the TSO ready to
- // do that).
- QueuedObjectInfo *pFixupInfo = (QueuedObjectInfo *)iorInfo->GetFixupInfo();
- PREFIX_ASSUME(pFixupInfo != NULL);
- if (pFixupInfo->NeedsUnboxing())
- {
- TSO.SetAt(tsoIndex, gc.resolvedObject, gc.refFromObj, gc.refParent, iorInfo);
- iorInfo->SetHasBeenProcessed();
- bResult = TRUE;
- }
- else
- {
- if (gc.refParent == NULL)
- m_topObject = gc.resolvedObject;
- else
- {
- m_newObject = gc.resolvedObject;
- if (pFixupInfo->NeedsUnboxing())
- CompleteValueTypeFields(gc.resolvedObject, gc.refParent, pFixupInfo);
- else
- Fixup(gc.resolvedObject, gc.refParent, pFixupInfo);
- }
- iorInfo->SetHasBeenProcessed();
- bResult = TRUE;
- }
- }
- }
- else
- {
- MethodTable *pMT = gc.IObjRef->GetMethodTable();
- _ASSERTE(pMT);
-
- MethodTable *pItf = MscorlibBinder::GetClass(CLASS__IOBJECTREFERENCE);
- MethodDesc *pMeth = GetInterfaceMethodImpl(pMT, pItf, 0);
- MethodDescCallSite method(pMeth, &gc.IObjRef);
-
- // Ensure Streamingcontext type is loaded. Do not delete this line
- MethodTable *pMTStreamingContext;
- pMTStreamingContext = MscorlibBinder::GetClass(CLASS__STREAMING_CONTEXT);
- _ASSERTE(pMTStreamingContext);
-
- ARG_SLOT arg[2];
- arg[0] = ObjToArgSlot(gc.IObjRef);
-
- RuntimeMethodHandle::StreamingContextData context = { NULL, GetStreamingContextState() };
-#ifdef _WIN64
- static_assert_no_msg(sizeof(context) > sizeof(ARG_SLOT));
- arg[1] = PtrToArgSlot(&context);
-#else
- static_assert_no_msg(sizeof(context) <= sizeof(ARG_SLOT));
- arg[1] = *(ARG_SLOT*)(&context);
-#endif
-
- gc.newObj = method.CallWithValueTypes_RetOBJECTREF(&arg[0]);
-
- INDEBUG(DefineFullyQualifiedNameForClass();)
-
- _ASSERTE(gc.newObj != NULL);
- MethodTable *pNewMT = gc.newObj->GetMethodTable();
- if (!pNewMT->IsTransparentProxy() &&
- gc.newObj != gc.IObjRef &&
- m_cbInterface->IsIObjectReferenceType(pNewMT))
- {
-#ifdef _DEBUG
- LOG((LF_REMOTING, LL_INFO1000,
- "CompleteIObjRefObject. GetRealObject on object of type %s returned another IObjectReference. Adding back to TSO.\n",
- GetFullyQualifiedNameForClassNestedAware(gc.IObjRef->GetMethodTable())));
-#endif
-
- // Put this back into the table
- OBJECTREF dummy;
- dummy = TSO.GetAt(tsoIndex, &gc.refFromObj, &gc.refParent, (QueuedObjectInfo **)&iorInfo);
- TSO.SetAt(tsoIndex, gc.newObj, gc.refFromObj, gc.refParent, iorInfo);
- bResult = FALSE;
- }
- else
- {
-#ifdef _DEBUG
- LOG((LF_REMOTING, LL_INFO1000,
- "CompleteIObjRefObject. Called GetRealObject on object of type %s. Fixing it up into its parent.\n",
- GetFullyQualifiedNameForClassNestedAware(gc.IObjRef->GetMethodTable())));
-#endif
- // Fix the object into its parent (unless it requires unboxing, in which case there's another entry in the TSO ready to
- // do that).
- QueuedObjectInfo *pFixupInfo = (QueuedObjectInfo *)iorInfo->GetFixupInfo();
- OBJECTREF dummy;
- dummy = TSO.GetAt(tsoIndex, &gc.refFromObj, &gc.refParent, (QueuedObjectInfo **)&iorInfo);
- if (pFixupInfo->NeedsUnboxing())
- {
- TSO.SetAt(tsoIndex, gc.newObj, gc.refFromObj, gc.refParent, iorInfo);
- iorInfo->SetHasBeenProcessed();
- bResult = TRUE;
- }
- else
- {
- if (gc.refParent == NULL)
- m_topObject = gc.newObj;
- else
- {
- m_newObject = gc.newObj;
- Fixup(gc.newObj, gc.refParent, pFixupInfo);
- }
-
- // Update Table of Seen objects, so that any repeat objects can be updated too
- TOS.UpdateObject(gc.refFromObj, gc.newObj);
- iorInfo->SetHasBeenProcessed();
- bResult = TRUE;
- }
- }
- }
-
- GCPROTECT_END();
- return bResult;
-}
-
-void MakeIDeserializationCallback(OBJECTREF refTarget)
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END;
-
- struct _gc {
- OBJECTREF refTarget;
- } gc;
- gc.refTarget = refTarget;
-
- GCPROTECT_BEGIN(gc);
-
- MethodTable *pMT = gc.refTarget->GetMethodTable();
- _ASSERTE(pMT);
-
- MethodTable *pItf = MscorlibBinder::GetClass(CLASS__IDESERIALIZATIONCB);
- MethodDesc *pMeth = GetInterfaceMethodImpl(pMT, pItf, 0);
- PCODE pCode = pMeth->GetSingleCallableAddrOfCode();
-
- PREPARE_NONVIRTUAL_CALLSITE_USING_CODE(pCode);
-
- DECLARE_ARGHOLDER_ARRAY(args, 2);
-
- args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(gc.refTarget);
- args[ARGNUM_1] = NULL;
-
- CATCH_HANDLER_FOUND_NOTIFICATION_CALLSITE;
- CALL_MANAGED_METHOD_NORET(args);
-
- GCPROTECT_END();
-}
-
-void ObjectClone::CompleteIDeserializationCallbacks()
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END
- OBJECTREF Dummy1 = NULL, Dummy2 = NULL;
- QueuedObjectInfo *pObjInfo = NULL;
-
- if (TDC.GetCount() == 0)
- return;
-
- LOG((LF_REMOTING, LL_INFO1000, "CompleteIDeserializationCallbacks. Beginning.\n"));
-
- OBJECTREF nextObj;
- while ((nextObj = TDC.Dequeue(&Dummy1, &Dummy2, &pObjInfo)) != NULL)
- {
- MakeIDeserializationCallback(nextObj);
- }
-}
-
-void ObjectClone::CompleteVtsOnDeserializedCallbacks()
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END;
-
- OBJECTREF nextObj = NULL, Dummy1 = NULL, Dummy2 = NULL;
-
- if (VDC.GetCount() == 0)
- return;
-
- LOG((LF_REMOTING, LL_INFO1000, "CompleteVtsOnDeserializedCallbacks. Beginning.\n"));
-
- GCPROTECT_BEGIN(nextObj);
-
- while ((nextObj = VDC.Dequeue(&Dummy1, &Dummy2, NULL)) != NULL)
- InvokeVtsCallbacks(nextObj, RemotingVtsInfo::VTS_CALLBACK_ON_DESERIALIZED, m_toDomain);
-
- GCPROTECT_END();
-}
-
-void ObjectClone::CompleteVtsOnSerializedCallbacks()
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END;
-
- OBJECTREF nextObj = NULL, Dummy1 = NULL, Dummy2 = NULL;
-
- if (VSC.GetCount() == 0)
- return;
-
- LOG((LF_REMOTING, LL_INFO1000, "CompleteVtsOnSerializedCallbacks. Beginning.\n"));
-
- GCPROTECT_BEGIN(nextObj);
-
- while ((nextObj = VSC.Dequeue(&Dummy1, &Dummy2, NULL)) != NULL)
- InvokeVtsCallbacks(nextObj, RemotingVtsInfo::VTS_CALLBACK_ON_SERIALIZED, m_fromDomain);
-
- GCPROTECT_END();
-}
-
-// Does a binary search to find the object with given id, and record of given kind
-DWORD ObjectClone::FindObjectInTSO(int objId, SpecialObjects kind)
-{
- CONTRACTL
- {
- MODE_COOPERATIVE;
- GC_NOTRIGGER;
- NOTHROW;
- }
- CONTRACTL_END
-
- DWORD lowIndex = 0;
- DWORD highIndex = TSO.GetCount();
- DWORD midIndex = highIndex / 2;
- DWORD firstMatch;
-
- if (highIndex == 0)
- {
- _ASSERTE(!"Special Object unexpectedly not found for given object id\n");
- return 0; // throw ?
- }
-
- SpecialObjectInfo *splInfo = NULL;
- while (true)
- {
- OBJECTREF refParent, refFromObj;
- OBJECTREF dummy;
- dummy = TSO.GetAt(midIndex, &refFromObj, &refParent, (QueuedObjectInfo **)&splInfo);
-
- if (objId < splInfo->GetObjectId())
- {
- highIndex = midIndex;
- }
- else
- {
- if (objId == splInfo->GetObjectId())
- break;
- lowIndex = midIndex;
- }
-
- DWORD oldIndex = midIndex;
- midIndex = lowIndex + (highIndex - lowIndex)/2;
- if (oldIndex == midIndex)
- {
- // Binary search failed. See comments below
- goto LinearSearch;
- }
- }
-
- // Found match at midIndex
- // Find the first record for this obj id
- firstMatch = midIndex;
- while(midIndex != 0)
- {
- midIndex -= 1;
- SpecialObjectInfo *pTemp;
- OBJECTREF refParent, refFromObj;
- OBJECTREF dummy;
- dummy = TSO.GetAt(midIndex, &refFromObj, &refParent, (QueuedObjectInfo **)&pTemp);
- if (pTemp->GetObjectId() != objId)
- break;
- else
- firstMatch = midIndex;
- };
-
- // Now look for the right kind of record
- do
- {
- OBJECTREF refParent, refFromObj;
- OBJECTREF dummy;
- dummy = TSO.GetAt(firstMatch, &refFromObj, &refParent, (QueuedObjectInfo **)&splInfo);
-
- if (splInfo->GetObjectId() == objId)
- {
- switch(kind)
- {
- case ISerializable:
- if (splInfo->IsISerializableInstance())
- return firstMatch;
- break;
- case IObjectReference:
- if (splInfo->IsIObjRefInstance())
- return firstMatch;
- break;
- case BoxedValueType:
- if (splInfo->IsBoxedObject())
- return firstMatch;
- break;
- default:
- _ASSERTE(!"Unknown enum value in FindObjectInTSO");
- };
- }
-
- firstMatch++;
-
- }while(firstMatch < TSO.GetCount());
-
-LinearSearch:
- // If there are multiple objects that are ISer/IObj, and some of them repeat in a certain fashion,
- // then the entries in TSO are not in sorted order. In such a case binary search will fail. Lets do a linear search
- // in such a case for now. This is probably reasonable since the TSO should usually be short and in-order (and presumably
- // cheaper than trying to keep the list in sorted order at all times).
- DWORD currIndex = 0;
- for (; currIndex < TSO.GetCount(); currIndex++)
- {
- OBJECTREF refParent, refFromObj;
- OBJECTREF dummy;
- dummy = TSO.GetAt(currIndex, &refFromObj, &refParent, (QueuedObjectInfo **)&splInfo);
-
- SpecialObjects foundKind = ISerializable;
- if (splInfo->IsIObjRefInstance())
- foundKind = IObjectReference;
- else if (splInfo->IsBoxedObject())
- foundKind = BoxedValueType;
- else
- _ASSERTE(splInfo->IsISerializableInstance());
-
- if (objId == splInfo->GetObjectId()
- && kind == foundKind)
- return currIndex;
- }
-
-
- _ASSERTE(!"Special Object unexpectedly not found for given object id\n");
- return 0; // throw ?
-}
-
-// This function is effectively a replica of MethodTable::Box. Its replicated to avoid "GCPROTECT_INTERIOR" that Box uses
-// and causes some leak detection asserts to go off. This is a controlled leak situation, where we know we're leaking stuff
-// and dont want the asserts.
-OBJECTREF ObjectClone::BoxValueTypeInWrongDomain(OBJECTREF refParent, DWORD offset, MethodTable *pValueTypeMT)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(pValueTypeMT->IsValueType());
- PRECONDITION(!pValueTypeMT->IsByRefLike());
- }
- CONTRACTL_END;
-
- OBJECTREF ref = NULL;
- void* pSrc = refParent->GetData() + offset;
- GCPROTECT_BEGININTERIOR(pSrc);
-
- // We must enter the target domain if we are boxing a non-agile type. This of course has some overhead
- // so we want to avoid it if possible. GetLoaderModule() == mscorlib && CanBeBlittedByObjectCloner is a
- // conservative first approximation of agile types.
- ENTER_DOMAIN_PTR_PREDICATED(m_fromDomain, ADV_RUNNINGIN,
- !pValueTypeMT->GetLoaderModule()->IsSystem() || pValueTypeMT->GetClass()->CannotBeBlittedByObjectCloner());
-
- ref = pValueTypeMT->FastBox(&pSrc);
-
- END_DOMAIN_TRANSITION;
-
- GCPROTECT_END();
- return ref;
-}
-
-// Returns whether or not a given type requires VTS callbacks of the specified kind.
-BOOL ObjectClone::HasVtsCallbacks(MethodTable *pMT, RemotingVtsInfo::VtsCallbackType eCallbackType)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- while (pMT)
- {
- if (pMT->HasRemotingVtsInfo())
- {
- PTR_RemotingVtsInfo pVtsInfo = pMT->GetRemotingVtsInfo();
- _ASSERTE(pVtsInfo != NULL);
-
- if (!pVtsInfo->m_pCallbacks[eCallbackType].IsNull())
- return TRUE;
- }
- pMT = pMT->GetParentMethodTable();
- }
-
- return FALSE;
-}
-
-// Calls all of the VTS event methods for a given callback type on the object instance provided (starting at the base class).
-void ObjectClone::InvokeVtsCallbacks(OBJECTREF refTarget, RemotingVtsInfo::VtsCallbackType eCallbackType, AppDomain* pDomain)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
-
- GCPROTECT_BEGIN(refTarget);
-
- // Quickly walk the target's type hierarchy and determine the number of methods we'll need to call.
- DWORD cMethods = 0;
- MethodDesc *pLastCallback;
- MethodTable *pMT = refTarget->GetMethodTable();
- while (pMT)
- {
- if (pMT->HasRemotingVtsInfo())
- {
- PTR_RemotingVtsInfo pVtsInfo = pMT->GetRemotingVtsInfo();
- _ASSERTE(pVtsInfo != NULL);
-
- if (!pVtsInfo->m_pCallbacks[eCallbackType].IsNull())
- {
- cMethods++;
-
-#ifdef FEATURE_PREJIT
- // Might have to restore cross module method pointers.
- Module::RestoreMethodDescPointer(&pVtsInfo->m_pCallbacks[eCallbackType]);
-#endif
-
- pLastCallback = pVtsInfo->m_pCallbacks[eCallbackType].GetValue();
- }
- }
- pMT = pMT->GetParentMethodTable();
- }
-
- // Maybe there's no work to do.
- if (cMethods == 0)
- goto Done;
-
- // Allocate an array to hold the methods to invoke (we do this because the invocation order is the opposite way round from the
- // way we can easily scan for the methods). We can easily optimize this for the single callback case though.
- MethodDesc **pCallbacks = cMethods == 1 ? &pLastCallback : (MethodDesc**)_alloca(cMethods * sizeof(MethodDesc*));
-
- if (cMethods > 1)
- {
- // Walk the type hierarchy again, and this time fill in the methods to call in the correct slot of our callback table.
- DWORD dwSlotIndex = cMethods;
- pMT = refTarget->GetMethodTable();
- while (pMT)
- {
- if (pMT->HasRemotingVtsInfo())
- {
- PTR_RemotingVtsInfo pVtsInfo = pMT->GetRemotingVtsInfo();
- _ASSERTE(pVtsInfo != NULL);
-
- if (!pVtsInfo->m_pCallbacks[eCallbackType].IsNull())
- pCallbacks[--dwSlotIndex] = pVtsInfo->m_pCallbacks[eCallbackType].GetValue();
- }
- pMT = pMT->GetParentMethodTable();
- }
- _ASSERTE(dwSlotIndex == 0);
- }
-
- bool fSwitchDomains = pDomain != GetAppDomain();
-
- ENTER_DOMAIN_PTR(pDomain,ADV_RUNNINGIN);
-
- // If we're calling back into the from domain then reset the execution context to its original state (this will automatically be
- // popped once we return from this domain again).
- if (pDomain == m_fromDomain && fSwitchDomains)
- {
- Thread *pThread = GetThread();
- if (pThread->IsExposedObjectSet())
- {
- THREADBASEREF refThread = (THREADBASEREF)pThread->GetExposedObjectRaw();
- refThread->SetExecutionContext(m_fromExecutionContext);
- }
- }
-
- // Remember to adjust this pointer for boxed value types.
- BOOL bIsBoxed = refTarget->GetMethodTable()->IsValueType();
-
- RuntimeMethodHandle::StreamingContextData sContext = { NULL, GetStreamingContextState() };
-
- // Ensure Streamingcontext type is loaded. Do not delete this line
- MethodTable *pMTStreamingContext;
- pMTStreamingContext = MscorlibBinder::GetClass(CLASS__STREAMING_CONTEXT);
- _ASSERTE(pMTStreamingContext);
-
- // Now go and call each method in order.
- for (DWORD i = 0; i < cMethods; i++)
- {
- MethodDescCallSite callback(pCallbacks[i], &refTarget);
-
- ARG_SLOT argSlots[2];
-
- // Nullable<T> does not have any VTS functions
- _ASSERTE(!Nullable::IsNullableType(refTarget->GetMethodTable()));
-
- argSlots[0] = (bIsBoxed ? (ARG_SLOT)(SIZE_T)(refTarget->UnBox()) : ObjToArgSlot(refTarget));
-#if defined(_TARGET_X86_) || defined(_TARGET_ARM_)
- static_assert_no_msg(sizeof(sContext) == sizeof(ARG_SLOT));
- argSlots[1] = *(ARG_SLOT*)(&sContext); // StreamingContext is passed by value on x86 and ARM
-#elif defined(_WIN64)
- static_assert_no_msg(sizeof(sContext) > sizeof(ARG_SLOT));
- argSlots[1] = PtrToArgSlot(&sContext); // StreamingContext is passed by reference on WIN64
-#else // !_TARGET_X86_ && !_WIN64 && !_TARGET_ARM_
- PORTABILITY_ASSERT("ObjectClone::InvokeVtsCallbacks() - NYI on this platform");
-#endif // !_TARGET_X86_ && !_WIN64 && !_TARGET_ARM_
-
- callback.CallWithValueTypes(&argSlots[0]);
- }
-
- END_DOMAIN_TRANSITION;
-
-Done: ;
- GCPROTECT_END();
-}
-
-#endif // FEATURE_REMOTING
diff --git a/src/vm/pefile.h b/src/vm/pefile.h
index 2f244732e9..697ce03749 100644
--- a/src/vm/pefile.h
+++ b/src/vm/pefile.h
@@ -642,9 +642,7 @@ protected:
protected:
- friend class CLRPrivBinderFusion;
#ifndef DACCESS_COMPILE
- // CLRPrivBinderFusion calls this for Fusion-bound assemblies in AppX processes.
void SetHostAssembly(ICLRPrivAssembly * pHostAssembly)
{ LIMITED_METHOD_CONTRACT; m_pHostAssembly = clr::SafeAddRef(pHostAssembly); }
#endif //DACCESS_COMPILE
diff --git a/src/vm/prestub.cpp b/src/vm/prestub.cpp
index 723e6b68f2..67a184f4af 100644
--- a/src/vm/prestub.cpp
+++ b/src/vm/prestub.cpp
@@ -731,14 +731,22 @@ Stub * CreateUnboxingILStubForSharedGenericValueTypeMethods(MethodDesc* pTargetM
// 2. Emit the method body
mdToken tokPinningHelper = pCode->GetToken(MscorlibBinder::GetField(FIELD__PINNING_HELPER__M_DATA));
-
+
// 2.1 Push the thisptr
// We need to skip over the MethodTable*
- // The trick below will do that.
+ // The trick below will do that.
pCode->EmitLoadThis();
pCode->EmitLDFLDA(tokPinningHelper);
- // 2.2 Push the hidden context param
+#if defined(_TARGET_X86_)
+ // 2.2 Push the rest of the arguments for x86
+ for (unsigned i = 0; i < msig.NumFixedArgs();i++)
+ {
+ pCode->EmitLDARG(i);
+ }
+#endif
+
+ // 2.3 Push the hidden context param
// The context is going to be captured from the thisptr
pCode->EmitLoadThis();
pCode->EmitLDFLDA(tokPinningHelper);
@@ -746,16 +754,18 @@ Stub * CreateUnboxingILStubForSharedGenericValueTypeMethods(MethodDesc* pTargetM
pCode->EmitSUB();
pCode->EmitLDIND_I();
- // 2.3 Push the rest of the arguments
+#if !defined(_TARGET_X86_)
+ // 2.4 Push the rest of the arguments for not x86
for (unsigned i = 0; i < msig.NumFixedArgs();i++)
{
pCode->EmitLDARG(i);
}
+#endif
- // 2.4 Push the target address
+ // 2.5 Push the target address
pCode->EmitLDC((TADDR)pTargetMD->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY));
- // 2.5 Do the calli
+ // 2.6 Do the calli
pCode->EmitCALLI(TOKEN_ILSTUB_TARGET_SIG, msig.NumFixedArgs() + 1, msig.IsReturnTypeVoid() ? 0 : 1);
pCode->EmitRET();
@@ -828,39 +838,31 @@ Stub * CreateInstantiatingILStub(MethodDesc* pTargetMD, void* pHiddenArg)
CreateInstantiatingILStubTargetSig(pTargetMD, typeContext, &stubSigBuilder);
// 2. Emit the method body
- unsigned int numArgs = msig.NumFixedArgs();
if (msig.HasThis())
{
// 2.1 Push the thisptr
pCode->EmitLoadThis();
- numArgs++;
}
#if defined(_TARGET_X86_)
- if (numArgs < NUM_ARGUMENT_REGISTERS)
+ // 2.2 Push the rest of the arguments for x86
+ for (unsigned i = 0; i < msig.NumFixedArgs();i++)
{
-#endif // _TARGET_X86_
- // 2.2 Push the hidden context param
- // InstantiatingStub
- pCode->EmitLDC((TADDR)pHiddenArg);
-#if defined(_TARGET_X86_)
+ pCode->EmitLDARG(i);
}
#endif // _TARGET_X86_
- // 2.3 Push the rest of the arguments
+ // 2.3 Push the hidden context param
+ // InstantiatingStub
+ pCode->EmitLDC((TADDR)pHiddenArg);
+
+#if !defined(_TARGET_X86_)
+ // 2.4 Push the rest of the arguments for not x86
for (unsigned i = 0; i < msig.NumFixedArgs();i++)
{
pCode->EmitLDARG(i);
}
-
-#if defined(_TARGET_X86_)
- if (numArgs >= NUM_ARGUMENT_REGISTERS)
- {
- // 2.4 Push the hidden context param
- // InstantiatingStub
- pCode->EmitLDC((TADDR)pHiddenArg);
- }
-#endif // _TARGET_X86_
+#endif // !_TARGET_X86_
// 2.5 Push the target address
pCode->EmitLDC((TADDR)pTargetMD->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY));
@@ -1619,6 +1621,7 @@ PCODE MethodDesc::DoPrestub(MethodTable *pDispatchingMT)
else
#endif // FEATURE_INTERPRETER
{
+ ReJitPublishMethodHolder publishWorker(this, pCode);
SetStableEntryPointInterlocked(pCode);
}
}
diff --git a/src/vm/proftoeeinterfaceimpl.cpp b/src/vm/proftoeeinterfaceimpl.cpp
index 18702d7b60..b7a0eb75e6 100644
--- a/src/vm/proftoeeinterfaceimpl.cpp
+++ b/src/vm/proftoeeinterfaceimpl.cpp
@@ -9397,8 +9397,7 @@ HRESULT ProfToEEInterfaceImpl::EnumNgenModuleMethodsInliningThisMethod(
return CORPROF_E_DATAINCOMPLETE;
}
- PersistentInlineTrackingMap *inliningMap = inlinersModule->GetNgenInlineTrackingMap();
- if (inliningMap == NULL)
+ if (!inlinersModule->HasInlineTrackingMap())
{
return CORPROF_E_DATAINCOMPLETE;
}
@@ -9411,14 +9410,14 @@ HRESULT ProfToEEInterfaceImpl::EnumNgenModuleMethodsInliningThisMethod(
EX_TRY
{
// Trying to use static buffer
- COUNT_T methodsAvailable = inliningMap->GetInliners(inlineeOwnerModule, inlineeMethodId, staticBufferSize, staticBuffer, incompleteData);
+ COUNT_T methodsAvailable = inlinersModule->GetInliners(inlineeOwnerModule, inlineeMethodId, staticBufferSize, staticBuffer, incompleteData);
// If static buffer is not enough, allocate an array.
if (methodsAvailable > staticBufferSize)
{
DWORD dynamicBufferSize = methodsAvailable;
dynamicBuffer = methodsBuffer = new MethodInModule[dynamicBufferSize];
- methodsAvailable = inliningMap->GetInliners(inlineeOwnerModule, inlineeMethodId, dynamicBufferSize, dynamicBuffer, incompleteData);
+ methodsAvailable = inlinersModule->GetInliners(inlineeOwnerModule, inlineeMethodId, dynamicBufferSize, dynamicBuffer, incompleteData);
if (methodsAvailable > dynamicBufferSize)
{
_ASSERTE(!"Ngen image inlining info changed, this shouldn't be possible.");
diff --git a/src/vm/readytoruninfo.cpp b/src/vm/readytoruninfo.cpp
index b1be026a6c..6a47aa8f4c 100644
--- a/src/vm/readytoruninfo.cpp
+++ b/src/vm/readytoruninfo.cpp
@@ -533,11 +533,11 @@ PTR_ReadyToRunInfo ReadyToRunInfo::Initialize(Module * pModule, AllocMemTracker
DoLog("Ready to Run initialized successfully");
- return new (pMemory) ReadyToRunInfo(pModule, pLayout, pHeader);
+ return new (pMemory) ReadyToRunInfo(pModule, pLayout, pHeader, pamTracker);
}
-ReadyToRunInfo::ReadyToRunInfo(Module * pModule, PEImageLayout * pLayout, READYTORUN_HEADER * pHeader)
- : m_pModule(pModule), m_pLayout(pLayout), m_pHeader(pHeader), m_Crst(CrstLeafLock)
+ReadyToRunInfo::ReadyToRunInfo(Module * pModule, PEImageLayout * pLayout, READYTORUN_HEADER * pHeader, AllocMemTracker *pamTracker)
+ : m_pModule(pModule), m_pLayout(pLayout), m_pHeader(pHeader), m_Crst(CrstLeafLock), m_pPersistentInlineTrackingMap(NULL)
{
STANDARD_VM_CONTRACT;
@@ -589,6 +589,18 @@ ReadyToRunInfo::ReadyToRunInfo(Module * pModule, PEImageLayout * pLayout, READYT
LockOwner lock = {&m_Crst, IsOwnerOfCrst};
m_entryPointToMethodDescMap.Init(TRUE, &lock);
}
+
+ //In format version >= 2.1 there is an optional inlining table
+ if (IsImageVersionAtLeast(2, 1))
+ {
+ IMAGE_DATA_DIRECTORY * pInlineTrackingInfoDir = FindSection(READYTORUN_SECTION_INLINING_INFO);
+ if (pInlineTrackingInfoDir != NULL)
+ {
+ const BYTE* pInlineTrackingMapData = (const BYTE*)GetImage()->GetDirectoryData(pInlineTrackingInfoDir);
+ PersistentInlineTrackingMapR2R::TryLoad(pModule, pInlineTrackingMapData, pInlineTrackingInfoDir->Size,
+ pamTracker, &m_pPersistentInlineTrackingMap);
+ }
+ }
}
static bool SigMatchesMethodDesc(MethodDesc* pMD, SigPointer &sig, Module * pModule)
@@ -854,4 +866,12 @@ DWORD ReadyToRunInfo::GetFieldBaseOffset(MethodTable * pMT)
return (DWORD)sizeof(Object) + dwCumulativeInstanceFieldPos - dwOffsetBias;
}
+BOOL ReadyToRunInfo::IsImageVersionAtLeast(int majorVersion, int minorVersion)
+{
+ LIMITED_METHOD_CONTRACT;
+ return (m_pHeader->MajorVersion == majorVersion && m_pHeader->MinorVersion >= minorVersion) ||
+ (m_pHeader->MajorVersion > majorVersion);
+
+}
+
#endif // DACCESS_COMPILE
diff --git a/src/vm/readytoruninfo.h b/src/vm/readytoruninfo.h
index 28efe01e8d..2266e9c119 100644
--- a/src/vm/readytoruninfo.h
+++ b/src/vm/readytoruninfo.h
@@ -13,6 +13,7 @@
#define _READYTORUNINFO_H_
#include "nativeformatreader.h"
+#include "inlinetracking.h"
typedef DPTR(struct READYTORUN_SECTION) PTR_READYTORUN_SECTION;
@@ -40,7 +41,9 @@ class ReadyToRunInfo
Crst m_Crst;
PtrHashMap m_entryPointToMethodDescMap;
- ReadyToRunInfo(Module * pModule, PEImageLayout * pLayout, READYTORUN_HEADER * pHeader);
+ PTR_PersistentInlineTrackingMapR2R m_pPersistentInlineTrackingMap;
+
+ ReadyToRunInfo(Module * pModule, PEImageLayout * pLayout, READYTORUN_HEADER * pHeader, AllocMemTracker *pamTracker);
public:
static BOOL IsReadyToRunEnabled();
@@ -118,10 +121,16 @@ public:
static DWORD GetFieldBaseOffset(MethodTable * pMT);
+ PTR_PersistentInlineTrackingMapR2R GetInlineTrackingMap()
+ {
+ return m_pPersistentInlineTrackingMap;
+ }
+
private:
BOOL GetTypeNameFromToken(IMDInternalImport * pImport, mdToken mdType, LPCUTF8 * ppszName, LPCUTF8 * ppszNameSpace);
BOOL GetEnclosingToken(IMDInternalImport * pImport, mdToken mdType, mdToken * pEnclosingToken);
BOOL CompareTypeNameOfTokens(mdToken mdToken1, IMDInternalImport * pImport1, mdToken mdToken2, IMDInternalImport * pImport2);
+ BOOL IsImageVersionAtLeast(int majorVersion, int minorVersion);
};
class DynamicHelpers
diff --git a/src/vm/remoting.cpp b/src/vm/remoting.cpp
deleted file mode 100644
index 1b65323bb6..0000000000
--- a/src/vm/remoting.cpp
+++ /dev/null
@@ -1,3773 +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.
-//
-// File: remoting.cpp
-//
-
-//
-// Purpose: Defines various remoting related objects such as
-// proxies
-//
-
-//
-
-
-#include "common.h"
-
-#ifdef FEATURE_REMOTING
-#include "virtualcallstub.h"
-#include "excep.h"
-#include "comdelegate.h"
-#include "remoting.h"
-#include "field.h"
-#include "siginfo.hpp"
-#include "stackbuildersink.h"
-#include "eehash.h"
-#include "profilepriv.h"
-#include "message.h"
-#include "eeconfig.h"
-#include "comcallablewrapper.h"
-#include "interopconverter.h"
-#include "asmconstants.h"
-#include "crossdomaincalls.h"
-#include "contractimpl.h"
-#include "typestring.h"
-#include "generics.h"
-#include "appdomain.inl"
-#include "dbginterface.h"
-
-#ifndef DACCESS_COMPILE
-
-// These hold label offsets into non-virtual thunks. They are used by
-// CNonVirtualThunkMgr::DoTraceStub and ::TraceManager to help the
-// debugger figure out where the thunk is going to go.
-DWORD g_dwNonVirtualThunkRemotingLabelOffset = 0;
-DWORD g_dwNonVirtualThunkReCheckLabelOffset = 0;
-
-// Statics
-
-MethodTable *CRemotingServices::s_pMarshalByRefObjectClass;
-MethodTable *CRemotingServices::s_pServerIdentityClass;
-
-MethodDesc *CRemotingServices::s_pRPPrivateInvoke;
-MethodDesc *CRemotingServices::s_pRPInvokeStatic;
-MethodDesc *CRemotingServices::s_pWrapMethodDesc;
-MethodDesc *CRemotingServices::s_pIsCurrentContextOK;
-MethodDesc *CRemotingServices::s_pCheckCast;
-MethodDesc *CRemotingServices::s_pFieldSetterDesc;
-MethodDesc *CRemotingServices::s_pFieldGetterDesc;
-MethodDesc *CRemotingServices::s_pObjectGetTypeDesc;
-MethodDesc *CRemotingServices::s_pGetTypeDesc;
-MethodDesc *CRemotingServices::s_pProxyForDomainDesc;
-MethodDesc *CRemotingServices::s_pServerContextForProxyDesc;
-MethodDesc *CRemotingServices::s_pServerDomainIdForProxyDesc;
-DWORD CRemotingServices::s_dwServerOffsetInRealProxy;
-DWORD CRemotingServices::s_dwSrvIdentityOffsetInRealProxy;
-DWORD CRemotingServices::s_dwIdOffset;
-DWORD CRemotingServices::s_dwTPOrObjOffsetInIdentity;
-DWORD CRemotingServices::s_dwMBRIDOffset;
-DWORD CRemotingServices::s_dwLeaseOffsetInIdentity;
-DWORD CRemotingServices::s_dwURIOffsetInIdentity;
-CrstStatic CRemotingServices::s_RemotingCrst;
-BOOL CRemotingServices::s_fRemotingStarted;
-MethodDesc *CRemotingServices::s_pRenewLeaseOnCallDesc;
-
-
-#ifdef FEATURE_COMINTEROP
-MethodDesc *CRemotingServices::s_pCreateObjectForCom;
-#endif
-
-// CTPMethodTable Statics
-DWORD CTPMethodTable::s_dwCommitedTPSlots;
-DWORD CTPMethodTable::s_dwReservedTPSlots;
-DWORD CTPMethodTable::s_dwReservedTPIndirectionSlotSize;
-DWORD CTPMethodTable::s_dwGCInfoBytes;
-DWORD CTPMethodTable::s_dwMTDataSlots;
-MethodTable *CTPMethodTable::s_pRemotingProxyClass;
-CrstStatic CTPMethodTable::s_TPMethodTableCrst;
-EEThunkHashTable *CTPMethodTable::s_pThunkHashTable;
-BOOL CTPMethodTable::s_fTPTableFieldsInitialized;
-
-#endif // !DACCESS_COMPILE
-
-
-SPTR_IMPL(MethodTable, CTPMethodTable, s_pThunkTable);
-
-#ifndef DACCESS_COMPILE
-
-// CVirtualThunks statics
-CVirtualThunks *CVirtualThunks::s_pVirtualThunks;
-
-// CVirtualThunkMgr statics
-CVirtualThunkMgr *CVirtualThunkMgr::s_pVirtualThunkMgr;
-
-#ifndef HAS_REMOTING_PRECODE
-// CNonVirtualThunk statics
-CNonVirtualThunk *CNonVirtualThunk::s_pNonVirtualThunks;
-SimpleRWLock* CNonVirtualThunk::s_pNonVirtualThunksListLock;
-
-// CNonVirtualThunkMgr statics
-CNonVirtualThunkMgr *CNonVirtualThunkMgr::s_pNonVirtualThunkMgr;
-#endif
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::Initialize public
-//
-// Synopsis: Initialized remoting state
-//
-//+----------------------------------------------------------------------------
-VOID CRemotingServices::Initialize()
-{
- STANDARD_VM_CONTRACT;
-
- // Initialize the remoting services critical section
- s_RemotingCrst.Init(CrstRemoting, CrstFlags(CRST_REENTRANCY|CRST_HOST_BREAKABLE));
-
- CTPMethodTable::Initialize();
-}
-
-INT32 CRemotingServices::IsTransparentProxy(Object* orTP)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- INT32 fIsTPMT = FALSE;
-
- if(orTP != NULL)
- {
- // Check if the supplied object has transparent proxy method table
- MethodTable *pMT = orTP->GetMethodTable();
- fIsTPMT = pMT->IsTransparentProxy() ? TRUE : FALSE;
- }
-
- LOG((LF_REMOTING, LL_EVERYTHING, "!IsTransparentProxyEx(0x%x) returning %s",
- orTP, fIsTPMT ? "TRUE" : "FALSE"));
-
- return(fIsTPMT);
-}
-
-
-Object* CRemotingServices::GetRealProxy(Object* objTP)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- OBJECTREF rv = NULL;
-
- if ((objTP != NULL) && (IsTransparentProxy(objTP)))
- {
- _ASSERTE(s_fRemotingStarted);
- rv = CTPMethodTable::GetRP(OBJECTREF(objTP));
- }
-
- LOG((LF_REMOTING, LL_INFO100, "!GetRealProxy(0x%x) returning 0x%x\n", objTP, OBJECTREFToObject(rv)));
-
- return OBJECTREFToObject(rv);
-}
-
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::EnsureRemotingStarted
-//
-// Synopsis: Startup the remoting services.
-//
-//
-//+----------------------------------------------------------------------------
-VOID CRemotingServices::EnsureRemotingStarted()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (!CRemotingServices::s_fRemotingStarted)
- CRemotingServices::StartRemoting();
-
- if (!CTPMethodTable::s_fTPTableFieldsInitialized)
- CTPMethodTable::EnsureFieldsInitialized();
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::StartRemoting private
-//
-// Synopsis: Initialize the static fields of CRemotingServices class
-//
-//
-//+----------------------------------------------------------------------------
-VOID CRemotingServices::StartRemoting()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- // Acquire the remoting lock before initializing fields
- GCX_PREEMP();
-
- CrstHolder ch(&s_RemotingCrst);
-
- // Make sure that no other thread has initialized the fields
- if (!s_fRemotingStarted)
- {
- InitActivationServicesClass();
- InitRealProxyClass();
- InitRemotingProxyClass();
- InitIdentityClass();
- InitServerIdentityClass();
- InitMarshalByRefObjectClass();
- InitRemotingServicesClass();
- InitObjectClass();
- InitLeaseClass();
-
- // ********* NOTE ************
- // This must always be the last statement in this block to prevent races
- //
- VolatileStore(&s_fRemotingStarted, TRUE);
- // ********* END NOTE ************
- }
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::InitActivationServicesClass private
-//
-// Synopsis: Extract the method descriptors and fields of ActivationServices class
-//
-//
-//+----------------------------------------------------------------------------
-VOID CRemotingServices::InitActivationServicesClass()
-{
- STANDARD_VM_CONTRACT;
-
- s_pIsCurrentContextOK = MscorlibBinder::GetMethod(METHOD__ACTIVATION_SERVICES__IS_CURRENT_CONTEXT_OK);
-#ifdef FEATURE_COMINTEROP
- s_pCreateObjectForCom = MscorlibBinder::GetMethod(METHOD__ACTIVATION_SERVICES__CREATE_OBJECT_FOR_COM);
-#endif
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::InitRealProxyClass private
-//
-// Synopsis: Extract the method descriptors and fields of Real Proxy class
-//
-//
-//+----------------------------------------------------------------------------
-VOID CRemotingServices::InitRealProxyClass()
-{
- STANDARD_VM_CONTRACT;
-
- // Now store the methoddesc of the PrivateInvoke method on the RealProxy class
- s_pRPPrivateInvoke = MscorlibBinder::GetMethod(METHOD__REAL_PROXY__PRIVATE_INVOKE);
-
- // Now find the offset to the _identity field inside the
- // RealProxy class
- s_dwIdOffset = RealProxyObject::GetOffsetOfIdentity() - Object::GetOffsetOfFirstField();
-
- s_dwServerOffsetInRealProxy = RealProxyObject::GetOffsetOfServerObject() - Object::GetOffsetOfFirstField();
-
- s_dwSrvIdentityOffsetInRealProxy = RealProxyObject::GetOffsetOfServerIdentity() - Object::GetOffsetOfFirstField();
-
- return;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::InitRemotingProxyClass private
-//
-// Synopsis: Extract the method descriptors and fields of RemotingProxy class
-//
-//
-//+----------------------------------------------------------------------------
-VOID CRemotingServices::InitRemotingProxyClass()
-{
- STANDARD_VM_CONTRACT;
-
- s_pRPInvokeStatic = MscorlibBinder::GetMethod(METHOD__REMOTING_PROXY__INVOKE);
-
- // Note: We cannot do this inside TPMethodTable::InitializeFields ..
- // that causes recursions if in some situation only the latter is called
- // If you do this you will see Asserts when running any process under CorDbg
- // This is because jitting of NV methods on MBR objects calls
- // InitializeFields and when actually doing that we should not need to
- // JIT another NV method on some MBR object.
- CTPMethodTable::s_pRemotingProxyClass = MscorlibBinder::GetClass(CLASS__REMOTING_PROXY);
- _ASSERTE(CTPMethodTable::s_pRemotingProxyClass);
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::InitServerIdentityClass private
-//
-// Synopsis: Extract the method descriptors and fields of ServerIdentity class
-//
-//
-//+----------------------------------------------------------------------------
-VOID CRemotingServices::InitServerIdentityClass()
-{
- STANDARD_VM_CONTRACT;
-
- s_pServerIdentityClass = MscorlibBinder::GetClass(CLASS__SERVER_IDENTITY);
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::InitIdentityClass private
-//
-// Synopsis: Extract the method descriptors and fields of Identity class
-//
-//
-//+----------------------------------------------------------------------------
-VOID CRemotingServices::InitIdentityClass()
-{
- STANDARD_VM_CONTRACT;
-
- s_dwTPOrObjOffsetInIdentity = MscorlibBinder::GetFieldOffset(FIELD__IDENTITY__TP_OR_OBJECT);
-
- s_dwLeaseOffsetInIdentity = MscorlibBinder::GetFieldOffset(FIELD__IDENTITY__LEASE);
-
- s_dwURIOffsetInIdentity = MscorlibBinder::GetFieldOffset(FIELD__IDENTITY__OBJURI);
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::InitMarshalByRefObjectClass private
-//
-// Synopsis: Extract the method descriptors and fields of MarshalByRefObject class
-//
-//
-//+----------------------------------------------------------------------------
-VOID CRemotingServices::InitMarshalByRefObjectClass()
-{
- STANDARD_VM_CONTRACT;
-
- s_pMarshalByRefObjectClass = MscorlibBinder::GetClass(CLASS__MARSHAL_BY_REF_OBJECT);
- s_dwMBRIDOffset = MarshalByRefObjectBaseObject::GetOffsetOfServerIdentity() - Object::GetOffsetOfFirstField();
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::InitRemotingServicesClass private
-//
-// Synopsis: Extract the method descriptors and fields of RemotingServices class
-//
-//
-//+----------------------------------------------------------------------------
-VOID CRemotingServices::InitRemotingServicesClass()
-{
- STANDARD_VM_CONTRACT;
-
- s_pCheckCast = MscorlibBinder::GetMethod(METHOD__REMOTING_SERVICES__CHECK_CAST);
-
- // Need these to call wrap/unwrap from the VM (message.cpp).
- // Also used by JIT helpers to wrap/unwrap
- s_pWrapMethodDesc = MscorlibBinder::GetMethod(METHOD__REMOTING_SERVICES__WRAP);
- s_pProxyForDomainDesc = MscorlibBinder::GetMethod(METHOD__REMOTING_SERVICES__CREATE_PROXY_FOR_DOMAIN);
- s_pServerContextForProxyDesc = MscorlibBinder::GetMethod(METHOD__REMOTING_SERVICES__GET_SERVER_CONTEXT_FOR_PROXY);
- s_pServerDomainIdForProxyDesc = MscorlibBinder::GetMethod(METHOD__REMOTING_SERVICES__GET_SERVER_DOMAIN_ID_FOR_PROXY);
- s_pGetTypeDesc = MscorlibBinder::GetMethod(METHOD__REMOTING_SERVICES__GET_TYPE);
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::InitObjectClass private
-//
-// Synopsis: Extract the method descriptors and fields of Object class
-//
-//
-//+----------------------------------------------------------------------------
-VOID CRemotingServices::InitObjectClass()
-{
- STANDARD_VM_CONTRACT;
-
- s_pFieldSetterDesc = MscorlibBinder::GetMethod(METHOD__OBJECT__FIELD_SETTER);
- s_pFieldGetterDesc = MscorlibBinder::GetMethod(METHOD__OBJECT__FIELD_GETTER);
- s_pObjectGetTypeDesc = MscorlibBinder::GetMethod(METHOD__OBJECT__GET_TYPE);
-}
-
-VOID CRemotingServices::InitLeaseClass()
-{
- STANDARD_VM_CONTRACT;
-
- s_pRenewLeaseOnCallDesc = MscorlibBinder::GetMethod(METHOD__LEASE__RENEW_ON_CALL);
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::RequiresManagedActivation private
-//
-// Synopsis: Determine if a config file has been parsed or if there
-// are any attributes on the class that would require us
-// to go into the managed activation codepath.
-//
-//
-// Note: Called by CreateProxyOrObject (JIT_NewCrossContext)
-//
-//+----------------------------------------------------------------------------
-ManagedActivationType __stdcall CRemotingServices::RequiresManagedActivation(TypeHandle ty)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- SO_TOLERANT;
- PRECONDITION(!ty.IsNull());
- }
- CONTRACTL_END;
-
- MethodTable* pMT = ty.GetMethodTable();
-
- PREFIX_ASSUME(pMT != NULL);
- if (!pMT->MayRequireManagedActivation())
- return NoManagedActivation;
-
-#ifdef _DEBUG
-
- ManagedActivationType bManaged = NoManagedActivation;
- if (pMT->IsRemotingConfigChecked())
- {
- // We have done work to figure this out in the past ...
- // use the cached result
- bManaged = pMT->RequiresManagedActivation() ? ManagedActivation : NoManagedActivation;
- }
- else if (pMT->IsContextful() || pMT->GetClass()->HasRemotingProxyAttribute())
- {
- // Contextful and classes that have a remoting proxy attribute
- // (whether they are MarshalByRef or ContextFul) always take the slow
- // path of managed activation
- bManaged = ManagedActivation;
- }
- else
- {
- // If we have parsed a config file that might have configured
- // this Type to be activated remotely
- if (GetAppDomain()->IsRemotingConfigured())
- {
- bManaged = ManagedActivation;
- // We will remember if the activation is actually going
- // remote based on if the managed call to IsContextOK returned us
- // a proxy or not
- }
-
-#ifdef FEATURE_COMINTEROP
- else if (pMT->IsComObjectType())
- {
- bManaged = ComObjectType;
- }
-#endif // FEATURE_COMINTEROP
-
- }
-
-#endif // _DEBUG
-
- if (pMT->RequiresManagedActivation())
- {
- // Contextful and classes that have a remoting proxy attribute
- // (whether they are MarshalByRef or ContextFul) always take the slow
- // path of managed activation
- _ASSERTE(bManaged == ManagedActivation);
- return ManagedActivation;
- }
-
- ManagedActivationType bMng = NoManagedActivation;
- if (!pMT->IsRemotingConfigChecked())
- {
- g_IBCLogger.LogMethodTableAccess(pMT);
-
- // If we have parsed a config file that might have configured
- // this Type to be activated remotely
- if (GetAppDomain()->IsRemotingConfigured())
- {
- bMng = ManagedActivation;
- // We will remember if the activation is actually going
- // remote based on if the managed call to IsContextOK returned us
- // a proxy or not
- }
-
-#ifdef FEATURE_COMINTEROP
- else if (pMT->IsComObjectType())
- {
- bMng = ComObjectType;
- }
-#endif // FEATURE_COMINTEROP
-
- if (bMng == NoManagedActivation)
- {
- pMT->TrySetRemotingConfigChecked();
- }
- }
-
- _ASSERTE(bManaged == bMng);
- return bMng;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::CreateProxyOrObject public
-//
-// Synopsis: Determine if the current context is appropriate
-// for activation. If the current context is OK then it creates
-// an object else it creates a proxy.
-//
-//
-// Note: Called by JIT_NewCrossContext
-//
-//+----------------------------------------------------------------------------
-OBJECTREF CRemotingServices::CreateProxyOrObject(MethodTable* pMT,
- BOOL fIsCom /*default:FALSE*/, BOOL fIsNewObj /*default:FALSE*/)
- /* fIsCom == Did we come here through CoCreateInstance */
- /* fIsNewObj == Did we come here through Jit_NewCrossContext (newObj) */
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pMT));
- PRECONDITION(!pMT->IsTransparentProxy());
-
- // By the time we reach here, we have already checked that the class may require
- // managed activation. This check is made either through the JIT_NewCrossContext helper
- // or Activator.CreateInstance codepath.
- PRECONDITION(pMT->MayRequireManagedActivation());
- }
- CONTRACTL_END;
-
- // Ensure remoting has been started.
- EnsureRemotingStarted();
-
- // Get the address of IsCurrentContextOK in managed code
- MethodDesc* pTargetMD = NULL;
- Object *pServer = NULL;
-
-#ifdef FEATURE_COMINTEROP
- if(fIsCom)
- {
- pTargetMD = CRemotingServices::MDofCreateObjectForCom();
- }
- else
-#endif // FEATURE_COMINTEROP
- {
- pTargetMD = CRemotingServices::MDofIsCurrentContextOK();
- }
-
- // Arrays are not created by JIT_NewCrossContext
- _ASSERTE(!pMT->IsArray());
-
- // Get the type seen by reflection
- REFLECTCLASSBASEREF reflectType = (REFLECTCLASSBASEREF) pMT->GetManagedClassObject();
- LPVOID pvType = NULL;
- *(REFLECTCLASSBASEREF *)&pvType = reflectType;
-
- // This will return either an uninitialized object or a proxy
- pServer = (Object *)CTPMethodTable::CallTarget(pTargetMD, pvType, NULL, (LPVOID)(size_t)(fIsNewObj?1:0));
-
- if (!pMT->IsContextful() && !pMT->IsComObjectType())
- {
- // Cache the result of the activation attempt ...
- // if a strictly MBR class is not configured for remote
- // activation we will not go
- // through this slow path next time!
- // (see RequiresManagedActivation)
- if (IsTransparentProxy(pServer))
- {
- // Set the flag that this class is remote activate
- // which means activation will go to managed code.
- pMT->SetRequiresManagedActivation();
- }
- else
- {
- // Set only the flag that no managed checks are required
- // for this class next time.
- pMT->SetRemotingConfigChecked();
- }
- }
-
- LOG((LF_REMOTING, LL_INFO1000, "CreateProxyOrObject returning 0x%p\n", pServer));
- if (pMT->IsContextful())
- {
- COUNTER_ONLY(GetPerfCounters().m_Context.cObjAlloc++);
- }
- return ObjectToOBJECTREF(pServer);
-}
-
-
-#ifndef HAS_REMOTING_PRECODE
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::GetStubForNonVirtualMethod public
-//
-// Synopsis: Get a stub for a non virtual method.
-//
-//
-//+----------------------------------------------------------------------------
-Stub* CRemotingServices::GetStubForNonVirtualMethod(MethodDesc* pMD, LPVOID pvAddrOfCode, Stub* pInnerStub)
-{
- CONTRACT (Stub*)
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(pMD));
- PRECONDITION(CheckPointer(pvAddrOfCode));
- PRECONDITION(CheckPointer(pInnerStub, NULL_OK));
- POSTCONDITION(CheckPointer(RETVAL));
- }
- CONTRACT_END;
-
- CPUSTUBLINKER sl;
- Stub* pStub = CTPMethodTable::CreateStubForNonVirtualMethod(pMD, &sl, pvAddrOfCode, pInnerStub);
-
- RETURN pStub;
-}
-#endif // HAS_REMOTING_PRECODE
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::GetNonVirtualEntryPointForVirtualMethod public
-//
-// Synopsis: Get a thunk for a non-virtual call to a virtual method.
-// Virtual methods do not normally get thunked in the vtable. This
-// is because virtual calls use the object's vtable, and proxied objects
-// would use the proxy's vtable. Hence local object (which would
-// have the real vtable) can make virtual calls without going through
-// the thunk.
-// However, if the virtual function is called non-virtually, we have
-// a problem (since this would bypass the proxy's vtable). Since this
-// is not a common case, we fix it by using a stub in such cases.
-//
-//
-//+----------------------------------------------------------------------------
-PCODE CRemotingServices::GetNonVirtualEntryPointForVirtualMethod(MethodDesc* pMD)
-{
- CONTRACT (PCODE)
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(pMD));
- PRECONDITION(pMD->IsRemotingInterceptedViaVirtualDispatch());
- POSTCONDITION(RETVAL != NULL);
- }
- CONTRACT_END;
-
-#ifdef HAS_REMOTING_PRECODE
- RETURN pMD->GetLoaderAllocator()->GetFuncPtrStubs()->GetFuncPtrStub(pMD, PRECODE_REMOTING);
-#else
- GCX_PREEMP();
- RETURN *CTPMethodTable::GetOrCreateNonVirtualSlotForVirtualMethod(pMD);
-#endif
-}
-
-#ifndef HAS_REMOTING_PRECODE
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::DestroyThunk public
-//
-// Synopsis: Destroy the thunk for the non virtual method.
-//
-//
-//+----------------------------------------------------------------------------
-void CRemotingServices::DestroyThunk(MethodDesc* pMD)
-{
- WRAPPER_NO_CONTRACT;
-
- // Delegate to a helper routine
- CTPMethodTable::DestroyThunk(pMD);
-}
-#endif // HAS_REMOTING_PRECODE
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::GetDispatchInterfaceHelper public
-//
-// Synopsis: Returns helper for dispatching interface call into the remoting system
-// with exact MethodDesc. Used for remoting of calls on generic interfaces.
-// The returned helper has MethodDesc calling convention
-//+----------------------------------------------------------------------------
-PCODE CRemotingServices::GetDispatchInterfaceHelper(MethodDesc* pMD)
-{
- WRAPPER_NO_CONTRACT;
-
- return GetEEFuncEntryPoint(CRemotingServices__DispatchInterfaceCall);
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::CheckCast public
-//
-// Synopsis: Checks either
-// (1) If the object type supports the given interface OR
-// (2) If the given type is present in the hierarchy of the
-// object type
-//
-//+----------------------------------------------------------------------------
-BOOL CRemotingServices::CheckCast(OBJECTREF orTP, TypeHandle objTy, TypeHandle ty)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(orTP != NULL);
- PRECONDITION(!objTy.IsNull());
- PRECONDITION(!ty.IsNull());
-
- // Object class can never be an interface. We use a separate cached
- // entry for storing interfaces that the proxy supports.
- PRECONDITION(!objTy.IsInterface());
- }
- CONTRACTL_END;
-
- // Early out if someone's trying to cast us to a type desc (such as a byref,
- // array or function pointer).
- if (ty.IsTypeDesc())
- return FALSE;
-
- BOOL fCastOK = FALSE;
-
- // (1) We are trying to cast to an interface
- if (ty.IsInterface())
- {
- // Do a quick check for interface cast by comparing it against the
- // cached entry
- MethodTable *pItfMT = ((TRANSPARENTPROXYREF)orTP)->GetInterfaceMethodTable();
- if (NULL != pItfMT)
- {
- if(pItfMT == ty.GetMethodTable())
- fCastOK = TRUE;
- else
- fCastOK = pItfMT->CanCastToInterface(ty.GetMethodTable());
- }
-
- if(!fCastOK)
- fCastOK = objTy.GetMethodTable()->CanCastToInterface(ty.GetMethodTable());
- }
- // (2) Everything else...
- else
- {
- // Walk up the class hierarchy and find a matching class
- while (ty != objTy)
- {
- if (objTy.IsNull())
- {
- // Oh-oh, the cast did not succeed. Maybe we have to refine
- // the proxy to match the clients view
- break;
- }
-
- // Continue searching
- objTy = objTy.GetParent();
- }
-
- if(objTy == ty)
- fCastOK = TRUE;
- }
-
- return fCastOK;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::CheckCast public
-//
-// Synopsis: Refine the type hierarchy that the proxy represents to match
-// the client view. If the client is trying to cast the proxy
-// to a type not supported by the server object then we
-// return NULL
-//
-//
-//+----------------------------------------------------------------------------
-BOOL CRemotingServices::CheckCast(OBJECTREF orTP, TypeHandle ty)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(orTP != NULL);
- PRECONDITION(!ty.IsNull());
- }
- CONTRACTL_END;
-
- BOOL fCastOK = FALSE;
-
- GCPROTECT_BEGIN(orTP);
-
- // Make sure the type being cast to has been restored.
- ty.CheckRestore();
-
- MethodTable *pMT = orTP->GetMethodTable();
-
- // Make sure that we have a transparent proxy
- _ASSERTE(pMT->IsTransparentProxy());
-
- pMT = orTP->GetTrueMethodTable();
-
- // Do a cast check without taking a lock
- fCastOK = CheckCast(orTP, TypeHandle(pMT), ty);
-
- if (!fCastOK && !ty.IsTypeDesc())
- {
- // We reach here only if any of the types in the current type hierarchy
- // represented by the proxy does not match the given type.
- // Call a helper routine in managed RemotingServices to find out
- // whether the server object supports the given type
- MethodDesc* pTargetMD = MDofCheckCast();
- fCastOK = CTPMethodTable::CheckCast(pTargetMD, (TRANSPARENTPROXYREF)orTP, ty);
- }
-
- if (fCastOK)
- {
- // Do the type equivalence tests
- CRealProxy::UpdateOptFlags(orTP);
- }
-
- GCPROTECT_END();
-
- LOG((LF_REMOTING, LL_INFO100, "CheckCast returning %s for object 0x%x and class 0x%x \n", (fCastOK ? "TRUE" : "FALSE")));
-
- return (fCastOK);
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::FieldAccessor public
-//
-// Synopsis: Sets/Gets the value of the field given an instance or a proxy
-//
-//+----------------------------------------------------------------------------
-void CRemotingServices::FieldAccessor(FieldDesc* pFD, OBJECTREF o, LPVOID pVal, BOOL fIsGetter)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pFD));
- PRECONDITION(o != NULL);
- PRECONDITION(CheckPointer(pVal, NULL_OK));
- PRECONDITION(o->IsTransparentProxy() || o->GetMethodTable()->IsMarshaledByRef());
- }
- CONTRACTL_END;
-
- MethodTable *pMT = o->GetMethodTable();
- TypeHandle fldClass;
- TypeHandle thRealObjectType;
-
- GCPROTECT_BEGIN(o);
- GCPROTECT_BEGININTERIOR(pVal);
-
- // If the field descriptor type is not exact (i.e. it's a representative
- // descriptor for a generic field) then we need to be more careful
- // determining the properties of the field.
- if (pFD->IsSharedByGenericInstantiations())
- {
- // We need to resolve the field type in the context of the actual object
- // it belongs to. If we've been handed a proxy we have to go grab the
- // proxied type for this to work.
- thRealObjectType = o->GetTrueTypeHandle();
-
- // Evaluate the field signature in the type context of the parent object.
- MetaSig sig(pFD, thRealObjectType);
- sig.NextArg();
- fldClass = sig.GetLastTypeHandleThrowing();
- }
- else
- {
- fldClass = pFD->GetFieldTypeHandleThrowing();
- }
-
- GCPROTECT_END();
- GCPROTECT_END();
-
- CorElementType fieldType = fldClass.GetSignatureCorElementType();
- UINT cbSize = GetSizeForCorElementType(fieldType);
- BOOL fIsGCRef = CorTypeInfo::IsObjRef(fieldType);
- BOOL fIsByValue = fieldType == ELEMENT_TYPE_VALUETYPE;
-
- if(pMT->IsMarshaledByRef())
- {
- GCX_FORBID();
-
- _ASSERTE(!o->IsTransparentProxy());
-
- // This is a reference to a real object. Get/Set the field value
- // and return
- LPVOID pFieldAddress = pFD->GetAddress((LPVOID)OBJECTREFToObject(o));
- LPVOID pDest = (fIsGetter ? pVal : pFieldAddress);
- LPVOID pSrc = (fIsGetter ? pFieldAddress : pVal);
- if(fIsGCRef && !fIsGetter)
- {
- SetObjectReference((OBJECTREF*)pDest, ObjectToOBJECTREF(*(Object **)pSrc), o->GetAppDomain());
- }
- else if(fIsByValue)
- {
- CopyValueClass(pDest, pSrc, fldClass.AsMethodTable(), o->GetAppDomain());
- }
- else
- {
- CopyDestToSrc(pDest, pSrc, cbSize);
- }
- }
- else
- {
- // Call the managed code to start the field access call
- CallFieldAccessor(pFD, o, pVal, fIsGetter, fIsByValue, fIsGCRef, thRealObjectType, fldClass, fieldType, cbSize);
- }
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::CopyDestToSrc private
-//
-// Synopsis: Copies the specified number of bytes from the src to dest
-//
-//
-//+----------------------------------------------------------------------------
-VOID CRemotingServices::CopyDestToSrc(LPVOID pDest, LPVOID pSrc, UINT cbSize)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pDest));
- PRECONDITION(CheckPointer(pSrc));
- }
- CONTRACTL_END;
-
- switch (cbSize)
- {
- case 1:
- VolatileStore((INT8*)pDest, *(INT8*)pSrc);
- break;
-
- case 2:
- VolatileStore((INT16*)pDest, *(INT16*)pSrc);
- break;
-
- case 4:
- VolatileStore((INT32*)pDest, *(INT32*)pSrc);
- break;
-
- case 8:
- VolatileStore((INT64*)pDest, *(INT64*)pSrc);
- break;
-
- default:
- UNREACHABLE();
- break;
- }
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::CallFieldAccessor private
-//
-// Synopsis: Sets up the arguments and calls RealProxy::FieldAccessor
-//
-//
-//+----------------------------------------------------------------------------
-VOID CRemotingServices::CallFieldAccessor(FieldDesc* pFD,
- OBJECTREF o,
- VOID* pVal,
- BOOL fIsGetter,
- BOOL fIsByValue,
- BOOL fIsGCRef,
- TypeHandle ty,
- TypeHandle fldTy,
- CorElementType fieldType,
- UINT cbSize)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pFD));
- PRECONDITION(o != NULL);
- PRECONDITION(CheckPointer(pVal));
- }
- CONTRACTL_END;
-
- //****************************WARNING******************************
- // GC Protect all non-primitive variables
- //*****************************************************************
-
- FieldArgs fieldArgs;
- fieldArgs.obj = NULL;
- fieldArgs.val = NULL;
- fieldArgs.typeName = NULL;
- fieldArgs.fieldName = NULL;
-
- GCPROTECT_BEGIN(fieldArgs);
- GCPROTECT_BEGININTERIOR(pVal);
-
- fieldArgs.obj = o;
-
- // protect the field value if it is a gc-ref type
- if(fIsGCRef)
- fieldArgs.val = ObjectToOBJECTREF(*(Object **)pVal);
-
-
- // Set up the arguments
-
- // Argument 1: String typeName
- // Argument 2: String fieldName
- // Get the type name and field name strings
- GetTypeAndFieldName(&fieldArgs, pFD, ty);
-
- // Argument 3: Object val
- OBJECTREF val = NULL;
- if(!fIsGetter)
- {
- // If we are setting a field value then we create a variant data
- // structure to hold the field value
- // Extract the field from the gc protected structure if it is an object
- // else use the value passed to the function
- LPVOID pvFieldVal = (fIsGCRef ? (LPVOID)&(fieldArgs.val) : pVal);
- // <REVISIT_TODO>: This can cause a GC. We need some way to protect the variant
- // data</REVISIT_TODO>
- OBJECTREF *lpVal = &val;
- GCPROTECT_BEGININTERIOR (pvFieldVal);
- CMessage::GetObjectFromStack(lpVal, &pvFieldVal, fieldType, fldTy, TRUE);
- GCPROTECT_END ();
- }
-
- // Get the method descriptor of the call
- MethodDesc *pMD = (fIsGetter ? MDofFieldGetter() : MDofFieldSetter());
-
- // Call the field accessor function
- //////////////////////////////// GETTER ///////////////////////////////////
- if(fIsGetter)
- {
- // Set up the return value
- OBJECTREF oRet = NULL;
-
- GCPROTECT_BEGIN (oRet);
- CRemotingServices__CallFieldGetter(pMD,
- (LPVOID)OBJECTREFToObject(fieldArgs.obj),
- (LPVOID)OBJECTREFToObject(fieldArgs.typeName),
- (LPVOID)OBJECTREFToObject(fieldArgs.fieldName),
- (LPVOID)&(oRet));
-
- // If we are getting a field value then extract the field value
- // based on the type of the field
- if(fIsGCRef)
- {
- // Do a check cast to ensure that the field type and the
- // return value are compatible
- OBJECTREF orRet = oRet;
- OBJECTREF orSaved = orRet;
- if(IsTransparentProxy(OBJECTREFToObject(orRet)))
- {
- GCPROTECT_BEGIN(orRet);
-
- if(!CheckCast(orRet, fldTy))
- COMPlusThrow(kInvalidCastException, W("Arg_ObjObj"));
-
- orSaved = orRet;
-
- GCPROTECT_END();
- }
-
- *(OBJECTREF *)pVal = orSaved;
- }
- else if (fIsByValue)
- {
- // Copy from the source to the destination
- if (oRet != NULL)
- {
- fldTy.GetMethodTable()->UnBoxIntoUnchecked(pVal, oRet);
- }
- }
- else
- {
- if (oRet != NULL)
- CopyDestToSrc(pVal, oRet->UnBox(), cbSize);
- }
- GCPROTECT_END ();
- }
- ///////////////////////// SETTER //////////////////////////////////////////
- else
- {
- CRemotingServices__CallFieldSetter(pMD,
- (LPVOID)OBJECTREFToObject(fieldArgs.obj),
- (LPVOID)OBJECTREFToObject(fieldArgs.typeName),
- (LPVOID)OBJECTREFToObject(fieldArgs.fieldName),
- (LPVOID)OBJECTREFToObject(val));
- }
-
- GCPROTECT_END(); // pVal
- GCPROTECT_END(); // fieldArgs
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::GetTypeAndFieldName private
-//
-// Synopsis: Get the type name and field name of the
-//
-//
-//+----------------------------------------------------------------------------
-VOID CRemotingServices::GetTypeAndFieldName(FieldArgs *pArgs, FieldDesc *pFD, TypeHandle thEnclosingClass)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pArgs));
- PRECONDITION(CheckPointer(pFD));
- }
- CONTRACTL_END;
-
- TypeHandle thDeclaringType = !thEnclosingClass.IsNull() ?
- pFD->GetExactDeclaringType(thEnclosingClass.AsMethodTable()) : pFD->GetEnclosingMethodTable();
- _ASSERTE(!thDeclaringType.IsNull());
-
- // Extract the type name and field name string
- // <REVISIT_TODO>FUTURE: Put this in the reflection data structure cache TarunA 11/26/00</REVISIT_TODO>
- StackSString ss;
- TypeString::AppendType(ss, thDeclaringType, TypeString::FormatNamespace | TypeString::FormatFullInst);
- pArgs->typeName = StringObject::NewString(ss);
-
- pArgs->fieldName = StringObject::NewString(pFD->GetName());
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::MatchField private
-//
-// Synopsis: Find out whether the given field name is the same as the name
-// of the field descriptor field name.
-//
-//
-//+----------------------------------------------------------------------------
-BOOL CRemotingServices::MatchField(FieldDesc* pCurField, LPCUTF8 szFieldName)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCurField));
- PRECONDITION(CheckPointer(szFieldName));
- }
- CONTRACTL_END;
-
- // Get the name of the field
- LPCUTF8 szCurFieldName;
- if (FAILED(pCurField->GetName_NoThrow(&szCurFieldName)))
- {
- return FALSE;
- }
-
- return strcmp(szCurFieldName, szFieldName) == 0;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::Wrap public
-//
-// Synopsis: Wrap a contextful object to create a proxy
-// Delegates to a helper method to do the actual work
-//
-//
-//+----------------------------------------------------------------------------
-OBJECTREF CRemotingServices::Wrap(OBJECTREF obj)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
-
- // Basic sanity check
- VALIDATEOBJECTREF(obj);
-
- // ******************* WARNING ********************************************
- // Do not throw any exceptions or provoke GC without setting up a frame.
- // At present its the callers responsibility to setup a frame that can
- // handle exceptions.
- // ************************************************************************
- OBJECTREF orProxy = obj;
- if(obj != NULL && (obj->GetMethodTable()->IsContextful()))
- {
- if(!IsTransparentProxy(OBJECTREFToObject(obj)))
- {
- // See if we can extract the proxy from the object
- orProxy = GetProxyFromObject(obj);
- if(orProxy == NULL)
- {
- // ask the remoting services to wrap the object
- orProxy = CRemotingServices::WrapHelper(obj);
- }
- }
- }
-
- return orProxy;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::WrapHelper public
-//
-// Synopsis: Wrap an object to return a proxy. This function assumes that
-// a fcall frame is already setup.
-//
-//+----------------------------------------------------------------------------
-OBJECTREF CRemotingServices::WrapHelper(OBJECTREF obj)
-{
- // Basic sanity check
- VALIDATEOBJECTREF(obj);
-
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(obj != NULL);
- PRECONDITION(!IsTransparentProxy(OBJECTREFToObject(obj)));
- PRECONDITION(obj->GetMethodTable()->IsContextful());
- }
- CONTRACTL_END;
-
-
- // Default return value indicates an error
- OBJECTREF newobj = NULL;
- MethodDesc* pTargetMD = NULL;
-
- // Ensure remoting has been started.
- EnsureRemotingStarted();
-
- // Get the address of wrap in managed code
- pTargetMD = CRemotingServices::MDofWrap();
-
- // call the managed method to wrap
- newobj = ObjectToOBJECTREF( (Object *)CTPMethodTable::CallTarget(pTargetMD,
- (LPVOID)OBJECTREFToObject(obj),
- NULL));
-
- return newobj;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::GetProxyFromObject public
-//
-// Synopsis: Extract the proxy from the field in the
-// ContextBoundObject class
-//
-//
-//+----------------------------------------------------------------------------
-OBJECTREF CRemotingServices::GetProxyFromObject(OBJECTREF obj)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- PRECONDITION(obj != NULL);
- }
- CONTRACTL_END;
-
- // Basic sanity check
- VALIDATEOBJECTREF(obj);
-
- // We can derive a proxy for contextful types only.
- _ASSERTE(obj->GetMethodTable()->IsContextful());
-
- OBJECTREF srvID = (OBJECTREF)(Object*)obj->GetPtrOffset(s_dwMBRIDOffset);
- OBJECTREF orProxy = NULL;
-
- if (srvID != NULL)
- orProxy = (OBJECTREF)(Object*)srvID->GetPtrOffset(s_dwTPOrObjOffsetInIdentity);
-
- // This should either be null or a proxy type
- _ASSERTE((orProxy == NULL) || IsTransparentProxy(OBJECTREFToObject(orProxy)));
-
- return orProxy;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::IsProxyToRemoteObject public
-//
-// Synopsis: Check if the proxy is to a remote object
-// (1) TRUE : if object is non local (ie outside this PROCESS) otherwise
-// (2) FALSE
-//
-//+----------------------------------------------------------------------------
-BOOL CRemotingServices::IsProxyToRemoteObject(OBJECTREF obj)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(obj != NULL);
- }
- CONTRACTL_END;
-
- // Basic sanity check
- VALIDATEOBJECTREF(obj);
-
- // If remoting is not started, for now let us just return FALSE
- if(!s_fRemotingStarted)
- return FALSE;
-
- if(!obj->IsTransparentProxy())
- return FALSE;
-
- // so it is a transparent proxy
- AppDomain *pDomain = GetServerDomainForProxy(obj);
- if(pDomain != NULL)
- return TRUE;
-
- return FALSE;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::GetObjectFromProxy public
-//
-// Synopsis: Extract the object given a proxy.
-//
-//
-//+----------------------------------------------------------------------------
-OBJECTREF CRemotingServices::GetObjectFromProxy(OBJECTREF obj)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- PRECONDITION(obj != NULL);
- PRECONDITION(s_fRemotingStarted);
- PRECONDITION(IsTransparentProxy(OBJECTREFToObject(obj)));
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- // Basic sanity check
- VALIDATEOBJECTREF(obj);
-
- OBJECTREF oref = NULL;
- if (CTPMethodTable__GenericCheckForContextMatch(OBJECTREFToObject(obj)))
- {
- OBJECTREF objRef = ObjectToOBJECTREF(GetRealProxy(OBJECTREFToObject(obj)));
- oref = (OBJECTREF)(Object*)objRef->GetPtrOffset(s_dwServerOffsetInRealProxy);
- if (oref != NULL)
- obj = oref;
- }
-
- return obj;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::GetServerIdentityFromProxy private
-//
-// Synopsis: Gets the server identity (if one exists) from a proxy
-//
-//
-//
-//
-//+----------------------------------------------------------------------------
-OBJECTREF CRemotingServices::GetServerIdentityFromProxy(OBJECTREF obj)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(obj != NULL);
- PRECONDITION(IsTransparentProxy(OBJECTREFToObject(obj)));
- }
- CONTRACTL_END;
-
-
- // Extract the real proxy underlying the transparent proxy
- OBJECTREF pObj = ObjectToOBJECTREF(GetRealProxy(OBJECTREFToObject(obj)));
-
- OBJECTREF id = NULL;
-
- // Extract the identity object
- pObj = (OBJECTREF)(Object*)pObj->GetPtrOffset(s_dwIdOffset);
-
- // Extract the _identity from the real proxy only if it is an instance of
- // remoting proxy
- if((pObj != NULL) && IsInstanceOfServerIdentity(pObj->GetMethodTable()))
- id = pObj;
-
- return id;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::GetServerDomainForProxy public
-//
-// Synopsis: Returns the AppDomain corresponding to the server
-// if the proxy and the server are in the same process.
-//
-//
-//+----------------------------------------------------------------------------
-AppDomain *CRemotingServices::GetServerDomainForProxy(OBJECTREF proxy)
-{
- CONTRACT (AppDomain*)
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(proxy != NULL);
- POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
- }
- CONTRACT_END;
-
- // call the managed method
- Context *pContext = (Context *)GetServerContextForProxy(proxy);
- if (pContext)
- RETURN pContext->GetDomain();
- else
- RETURN NULL;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::GetServerDomainIdForProxy public
-//
-// Synopsis: Returns the AppDomain ID corresponding to the server
-// if the proxy and the server are in the same process.
-// Returns 0 if it cannot determine.
-//
-//
-//+----------------------------------------------------------------------------
-int CRemotingServices::GetServerDomainIdForProxy(OBJECTREF proxy)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(proxy != NULL);
- PRECONDITION(IsTransparentProxy(OBJECTREFToObject(proxy)));
- }
- CONTRACTL_END;
-
- // Get the address of GetDomainIdForProxy in managed code
- MethodDesc* pTargetMD = CRemotingServices::MDofGetServerDomainIdForProxy();
-
- // This will just read the appDomain ID from the marshaled data
- // for the proxy. It returns 0 if the proxy is to a server in another
- // process. It may also return 0 if it cannot determine the server
- // domain ID (eg. for Well Known Object proxies).
-
- // call the managed method
- // <REVISIT_TODO>This cast to Int32 actually causes a potential loss
- // of data.</REVISIT_TODO>
- return (int)(INT_PTR)CTPMethodTable::CallTarget(
- pTargetMD,
- (LPVOID)OBJECTREFToObject(proxy),
- NULL);
-}
-
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::GetServerContextForProxy public
-//
-// Synopsis: Returns the AppDomain corresponding to the server
-// if the proxy and the server are in the same process.
-//
-//
-//+----------------------------------------------------------------------------
-Context *CRemotingServices::GetServerContextForProxy(OBJECTREF proxy)
-{
- CONTRACT (Context*)
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(proxy != NULL);
- PRECONDITION(IsTransparentProxy(OBJECTREFToObject(proxy)));
- POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
- }
- CONTRACT_END;
-
- // Get the address of GetAppDomainForProxy in managed code
- MethodDesc* pTargetMD = CRemotingServices::MDofGetServerContextForProxy();
-
- // This will return the correct VM Context object for the server if
- // the proxy is true cross domain proxy to a server in another domain
- // in the same process. The managed method will Assert if called on a proxy
- // which is either half-built or does not have an ObjRef ... which may
- // happen for eg. if the proxy and the server are in the same appdomain.
-
- // we return NULL if the server object for the proxy is in another
- // process or if the appDomain for the server is invalid or if we cannot
- // determine the context (eg. well known object proxies).
-
- // call the managed method
- RETURN (Context *)CTPMethodTable::CallTarget(
- pTargetMD,
- (LPVOID)OBJECTREFToObject(proxy),
- NULL);
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::CreateProxyForDomain public
-//
-// Synopsis: Create a proxy for the app domain object by calling marshal
-// inside the newly created domain and unmarshaling in the old
-// domain
-//
-//
-//+----------------------------------------------------------------------------
-OBJECTREF CRemotingServices::CreateProxyForDomain(AppDomain* pDomain)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pDomain));
- }
- CONTRACTL_END;
-
- // Ensure remoting has been started.
- EnsureRemotingStarted();
-
- MethodDesc* pTargetMD = MDOfCreateProxyForDomain();
-
- // Call the managed method which will marshal and unmarshal the
- // appdomain object to create the proxy
-
- // We pass the ContextID of the default context of the new appDomain
- // object. This helps the boot-strapping! (i.e. entering the new domain
- // to marshal itself out).
-
- Object *proxy = (Object *)CTPMethodTable::CallTarget(
- pTargetMD,
- (LPVOID)(DWORD_PTR)pDomain->GetId().m_dwId,
- (LPVOID)pDomain->GetDefaultContext());
- return ObjectToOBJECTREF(proxy);
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::GetClass public
-//
-// Synopsis: Extract the true class of the object whose proxy is given.
-//
-//
-//
-//+----------------------------------------------------------------------------
-REFLECTCLASSBASEREF CRemotingServices::GetClass(OBJECTREF pThis)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(pThis != NULL);
- }
- CONTRACTL_END;
-
- REFLECTCLASSBASEREF refClass = NULL;
- MethodTable *pMT = NULL;
-
- GCPROTECT_BEGIN(pThis);
-
- // For proxies to objects in the same appdomain, we always know the
- // correct type
- if(GetServerIdentityFromProxy(pThis) != NULL)
- {
- pMT = pThis->GetTrueMethodTable();
- }
- else
- {
- // For everything else either we have refined the proxy to its correct type
- // or we have to consult the objref to get the true type
-
- MethodDesc* pTargetMD = CRemotingServices::MDofGetType();
-
- refClass = (REFLECTCLASSBASEREF)(ObjectToOBJECTREF((Object *)CTPMethodTable::CallTarget(pTargetMD,
- (LPVOID)OBJECTREFToObject(pThis), NULL)));
-
- if(refClass == NULL)
- {
- // There was no objref associated with the proxy or it is a proxy
- // that we do not understand.
- // In this case, we return the class that is stored in the proxy
- pMT = pThis->GetTrueMethodTable();
- }
-
- _ASSERTE(refClass != NULL || pMT != NULL);
-
- // Refine the proxy to the class just retrieved
- if(refClass != NULL)
- {
- CTPMethodTable::RefineProxy((TRANSPARENTPROXYREF)pThis, refClass->GetType());
- }
- }
-
- if (refClass == NULL)
- {
- PREFIX_ASSUME(pMT != NULL);
- refClass = (REFLECTCLASSBASEREF)pMT->GetManagedClassObject();
- }
-
- GCPROTECT_END();
-
- _ASSERTE(refClass != NULL);
- return refClass;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRealProxy::SetStubData public
-//
-// Synopsis: Set the stub data in the transparent proxy
-//
-//+----------------------------------------------------------------------------
-FCIMPL2(VOID, CRealProxy::SetStubData, Object* orRPUNSAFE, Object* orStubDataUNSAFE)
-{
- CONTRACTL
- {
- FCALL_CHECK;
- }
- CONTRACTL_END;
-
- BOOL fThrow = FALSE;
- REALPROXYREF orRP = (REALPROXYREF)ObjectToOBJECTREF(orRPUNSAFE);
- OBJECTREF orStubData = ObjectToOBJECTREF(orStubDataUNSAFE);
-
- if (orRP != NULL && orStubData != NULL)
- {
- TRANSPARENTPROXYREF orTP = orRP->GetTransparentProxy();
- if (orTP != NULL)
- {
- orTP->SetStubData(orStubData);
- }
- else
- {
- fThrow = TRUE;
- }
- }
- else
- {
- fThrow = TRUE;
- }
-
- if(fThrow)
- FCThrowVoid(kArgumentNullException);
-}
-FCIMPLEND
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRealProxy::GetStubData public
-//
-// Synopsis: Get the stub data in the transparent proxy
-//
-//+----------------------------------------------------------------------------
-FCIMPL1(Object*, CRealProxy::GetStubData, Object* orRPUNSAFE)
-{
- CONTRACTL
- {
- FCALL_CHECK;
- }
- CONTRACTL_END;
-
- BOOL fThrow = FALSE;
- REALPROXYREF orRP = (REALPROXYREF)ObjectToOBJECTREF(orRPUNSAFE);
- OBJECTREF orRet = NULL;
-
- if (orRP != NULL)
- {
- TRANSPARENTPROXYREF orTP = orRP->GetTransparentProxy();
- if (orTP != NULL)
- orRet = orTP->GetStubData();
- else
- fThrow = TRUE;
- }
- else
- {
- fThrow = TRUE;
- }
-
- if(fThrow)
- FCThrow(kArgumentNullException);
-
- return OBJECTREFToObject(orRet);
-}
-FCIMPLEND
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRealProxy::GetDefaultStub public
-//
-// Synopsis: Get the default stub implemented by us which matches contexts
-//
-//+----------------------------------------------------------------------------
-FCIMPL0(LPVOID, CRealProxy::GetDefaultStub)
-{
- FCALL_CONTRACT;
-
- return (LPVOID)CRemotingServices__CheckForContextMatch;
-}
-FCIMPLEND
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRealProxy::GetStub public
-//
-// Synopsis: Get the stub pointer in the transparent proxy
-//
-//+----------------------------------------------------------------------------
-FCIMPL1(LPVOID, CRealProxy::GetStub, Object* orRPUNSAFE)
-{
- CONTRACTL
- {
- FCALL_CHECK;
- PRECONDITION(CheckPointer(orRPUNSAFE));
- }
- CONTRACTL_END;
-
- REALPROXYREF orRP = (REALPROXYREF)ObjectToOBJECTREF(orRPUNSAFE);
- TRANSPARENTPROXYREF orTP = orRP->GetTransparentProxy();
-
- return orTP->GetStub();
-}
-FCIMPLEND
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRealProxy::GetProxiedType public
-//
-// Synopsis: Get the type that is represented by the transparent proxy
-//
-//+----------------------------------------------------------------------------
-FCIMPL1(Object*, CRealProxy::GetProxiedType, Object* orRPUNSAFE)
-{
- FCALL_CONTRACT;
-
- REFLECTCLASSBASEREF refClass = NULL;
- REALPROXYREF orRP = (REALPROXYREF)ObjectToOBJECTREF(orRPUNSAFE);
- HELPER_METHOD_FRAME_BEGIN_RET_1(orRP);
-
- TRANSPARENTPROXYREF orTP = orRP->GetTransparentProxy();
-
- refClass = CRemotingServices::GetClass(orTP);
- _ASSERTE(refClass != NULL);
-
- HELPER_METHOD_FRAME_END();
- return OBJECTREFToObject(refClass);
-}
-FCIMPLEND
-
-//+----------------------------------------------------------------------------
-//
-// Method: CTPMethodTable::Initialize public
-//
-// Synopsis: Initialized data structures needed for managing tranparent
-// proxies
-//
-//+----------------------------------------------------------------------------
-VOID CTPMethodTable::Initialize()
-{
- STANDARD_VM_CONTRACT;
-
- s_TPMethodTableCrst.Init(CrstTPMethodTable);
-}
-
-//+----------------------------------------------------------------------------
-
-PCODE CTPMethodTable::GetTPStubEntryPoint()
-{
- LIMITED_METHOD_CONTRACT;
- return GetEEFuncEntryPoint(TransparentProxyStub);
-}
-
-PCODE CTPMethodTable::GetDelegateStubEntryPoint()
-{
- LIMITED_METHOD_CONTRACT;
- return GetEEFuncEntryPoint(TransparentProxyStub_CrossContext);
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CTPMethodTable::EnsureFieldsInitialized private
-//
-// Synopsis: Initialize the static fields of CTPMethodTable class
-// and the thunk manager classes
-//
-//
-//+----------------------------------------------------------------------------
-void CTPMethodTable::EnsureFieldsInitialized()
-{
- CONTRACT_VOID
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- POSTCONDITION(s_fTPTableFieldsInitialized);
- }
- CONTRACT_END;
-
- if (!s_fTPTableFieldsInitialized)
- {
- GCX_PREEMP();
-
- // Load Tranparent proxy class (do this before we enter the critical section)
- MethodTable* pTPMT = MscorlibBinder::GetClass(CLASS__TRANSPARENT_PROXY);
- _ASSERTE(pTPMT->IsTransparentProxy());
-
- CrstHolder ch(&s_TPMethodTableCrst);
-
- if(!s_fTPTableFieldsInitialized)
- {
- // Obtain size of GCInfo stored above the method table
- CGCDesc *pGCDesc = CGCDesc::GetCGCDescFromMT(pTPMT);
- BYTE *pGCTop = (BYTE *) pGCDesc->GetLowestSeries();
- s_dwGCInfoBytes = (DWORD)(((BYTE *) pTPMT) - pGCTop);
- _ASSERTE((s_dwGCInfoBytes & 3) == 0);
-
- // Obtain the number of bytes to be copied for creating the TP
- // method tables containing thunks
- _ASSERTE(((s_dwGCInfoBytes + sizeof(MethodTable)) & (sizeof(PCODE)-1)) == 0);
- s_dwMTDataSlots = ((s_dwGCInfoBytes + sizeof(MethodTable)) / sizeof(PCODE));
- _ASSERTE(sizeof(MethodTable) == MethodTable::GetVtableOffset());
-
- // We rely on the number of interfaces implemented by the
- // Transparent proxy being 0, so that InterfaceInvoke hints
- // fail and trap to InnerFailStub which also fails and
- // in turn traps to FailStubWorker. In FailStubWorker, we
- // determine the class being proxied and return correct slot.
- _ASSERTE(pTPMT->GetNumInterfaces() == 0);
-
- CVirtualThunkMgr::InitVirtualThunkManager();
-
- // Create the global thunk table and set the cycle between
- // the transparent proxy class and the global thunk table
- CreateTPMethodTable(pTPMT);
-
-#ifdef HAS_REMOTING_PRECODE
- // Activate the remoting precode helper
- ActivatePrecodeRemotingThunk();
-#endif // HAS_REMOTING_PRECODE
-
- // NOTE: This must always be the last statement in this block
- // to prevent races
- // Load Tranparent proxy class
- s_fTPTableFieldsInitialized = TRUE;
- }
- }
-
- RETURN;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CTPMethodTable::GetRP public
-//
-// Synopsis: Get the real proxy backing the transparent proxy
-//
-//+----------------------------------------------------------------------------
-REALPROXYREF CTPMethodTable::GetRP(OBJECTREF orTP)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- PRECONDITION(orTP != NULL);
- PRECONDITION(orTP->IsTransparentProxy());
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- return (REALPROXYREF)(((TRANSPARENTPROXYREF)orTP)->GetRealProxy());
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CTPMethodTable::GetMethodTableBeingProxied public
-//
-// Synopsis: Get the real type backing the transparent proxy
-//
-//+----------------------------------------------------------------------------
-MethodTable * CTPMethodTable::GetMethodTableBeingProxied(OBJECTREF orTP)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- SO_TOLERANT;
- PRECONDITION(orTP != NULL);
- PRECONDITION(orTP->IsTransparentProxy());
- }
- CONTRACTL_END;
-
- return ((TRANSPARENTPROXYREF)orTP)->GetMethodTableBeingProxied();
-}
-
-#define PAGE_ROUND_UP(cb) (((cb) + g_SystemInfo.dwAllocationGranularity) & ~(g_SystemInfo.dwAllocationGranularity - 1))
-
-//+----------------------------------------------------------------------------
-//
-// Method: CTPMethodTable::CreateTPMethodTable private
-//
-// Synopsis: (1) Reserves a transparent proxy method table that is large
-// enough to support the largest vtable
-// (2) Commits memory for the GC info of the global thunk table and
-// sets the cycle between the transparent proxy class and the
-// globale thunk table.
-//
-//+----------------------------------------------------------------------------
-
-void CTPMethodTable::CreateTPMethodTable(MethodTable* pTPMT)
-{
- CONTRACT_VOID {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- POSTCONDITION(CheckPointer(s_pThunkTable));
- } CONTRACT_END;
-
- // The largest possible vtable size 64K
- DWORD dwMaxSlots = 64*1024;
-
- // Allocate virtual memory that is big enough to hold a method table
- // of the maximum possible size
- DWORD dwReserveSize = 0;
- DWORD dwMethodTableReserveSize = (DWORD)(s_dwMTDataSlots * sizeof(PCODE));
- s_dwReservedTPIndirectionSlotSize = MethodTable::GetNumVtableIndirections(dwMaxSlots) * sizeof(PTR_PCODE);
- dwMethodTableReserveSize += s_dwReservedTPIndirectionSlotSize;
-
- dwMethodTableReserveSize += (DWORD)(dwMaxSlots * sizeof(PCODE));
- dwReserveSize = PAGE_ROUND_UP(dwMethodTableReserveSize);
-
- void *pAlloc = ::ClrVirtualAlloc(0, dwReserveSize, MEM_RESERVE | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
-
- if (pAlloc)
- {
- BOOL bFailed = TRUE;
-
- // Make sure that we have not created the one and only
- // transparent proxy method table before
- _ASSERTE(NULL == s_pThunkTable);
-
- // Commit the required amount of memory
- DWORD dwCommitSize = 0;
-
- // MethodTable memory
- DWORD dwMethodTableCommitSize = (s_dwMTDataSlots) * sizeof(PCODE);
- if (!ClrSafeInt<DWORD>::addition(0, dwMethodTableCommitSize, dwCommitSize))
- {
- COMPlusThrowHR(COR_E_OVERFLOW);
- }
-
- if (::ClrVirtualAlloc(pAlloc, dwCommitSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE))
- {
- // Copy the fixed portion from the true TP Method Table
- memcpy(pAlloc,MTToAlloc(pTPMT, s_dwGCInfoBytes), (dwMethodTableCommitSize));
-
- // Initialize the transparent proxy method table
- InitThunkTable(0, dwMaxSlots, AllocToMT((BYTE *) pAlloc, s_dwGCInfoBytes));
-
- // At this point the transparent proxy class points to the
- // the true TP Method Table and not the transparent
- // proxy method table. We do not use the true method table
- // any more. Instead we use the transparent proxy method table
- // for allocating transparent proxies. So, we have to make the
- // transparent proxy class point to the one and only transparent
- // proxy method table
- pTPMT->GetClass()->SetMethodTableForTransparentProxy(s_pThunkTable);
-
- // Allocate the slots of the Object class method table because
- // we can reflect on the __Transparent proxy class even though
- // we never intend to use remoting.
- _ASSERTE(NULL != g_pObjectClass);
- _ASSERTE(0 == GetCommitedTPSlots());
- if(ExtendCommitedSlots(g_pObjectClass->GetNumMethods()))
- bFailed = FALSE;
- }
- else
- {
- ClrVirtualFree(pAlloc, 0, MEM_RELEASE);
- }
-
- if(bFailed)
- DestroyThunkTable();
- }
- else {
- if (pAlloc != NULL)
- ::ClrVirtualFree(pAlloc, 0, MEM_RELEASE);
- }
-
- // Note that the thunk table is set to null on any failure path
- // via DestroyThunkTable
- if (!s_pThunkTable)
- COMPlusThrowOM();
-
- RETURN;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CTPMethodTable::ExtendCommitedSlots private
-//
-// Synopsis: Extends the commited slots of transparent proxy method table to
-// the desired number
-//
-//+----------------------------------------------------------------------------
-BOOL CTPMethodTable::ExtendCommitedSlots(_In_range_(1,64*1024) DWORD dwSlots)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- INJECT_FAULT(return FALSE);
- PRECONDITION(s_dwCommitedTPSlots <= dwSlots);
- PRECONDITION(dwSlots <= s_dwReservedTPSlots);
- PRECONDITION((CVirtualThunks::GetVirtualThunks() == NULL) ||
- (s_dwCommitedTPSlots == CVirtualThunks::GetVirtualThunks()->_dwCurrentThunk));
-
- // Either we have initialized everything or we are asked to allocate
- // some slots during initialization
- PRECONDITION(s_fTPTableFieldsInitialized || (0 == s_dwCommitedTPSlots));
- }
- CONTRACTL_END;
-
- // Commit memory for TPMethodTable
- BOOL bAlloc = FALSE;
- void *pAlloc = MTToAlloc(s_pThunkTable, s_dwGCInfoBytes);
- ClrSafeInt<DWORD> dwCommitSize;
- dwCommitSize += s_dwMTDataSlots * sizeof(PCODE);
- dwCommitSize += MethodTable::GetNumVtableIndirections(dwSlots) * sizeof(PTR_PCODE);
-
- DWORD dwLastIndirectionSlot = s_pThunkTable->GetIndexOfVtableIndirection(s_pThunkTable->GetNumVirtuals() - 1);
- DWORD dwSlotsCommitSize = dwSlots * sizeof(PCODE);
- PCODE *pAllocSlots = (PCODE*)(((BYTE*)s_pThunkTable) + s_dwMTDataSlots * sizeof(PCODE) + s_dwReservedTPIndirectionSlotSize);
-
- if (dwCommitSize.IsOverflow())
- {
- return FALSE; // error condition
- }
-
- if (::ClrVirtualAlloc(pAlloc, dwCommitSize.Value(), MEM_COMMIT, PAGE_EXECUTE_READWRITE) &&
- ::ClrVirtualAlloc(pAllocSlots, dwSlotsCommitSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE))
- {
- _ASSERTE(FitsIn<WORD>(dwSlots));
- s_pThunkTable->SetNumVirtuals((WORD)dwSlots);
-
- MethodTable::VtableIndirectionSlotIterator it = s_pThunkTable->IterateVtableIndirectionSlotsFrom(dwLastIndirectionSlot);
- do
- {
- it.SetIndirectionSlot(&pAllocSlots[it.GetStartSlot()]);
- }
- while (it.Next());
-
- bAlloc = AllocateThunks(dwSlots, dwCommitSize.Value());
- }
-
- return bAlloc;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CTPMethodTable::AllocateThunks private
-//
-// Synopsis: Allocates the desired number of thunks for virtual methods
-//
-//+----------------------------------------------------------------------------
-BOOL CTPMethodTable::AllocateThunks(DWORD dwSlots, DWORD dwCommitSize)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
- // Check for existing thunks
- DWORD dwCommitThunks = 0;
- DWORD dwAllocThunks = dwSlots;
- MethodTable *pThunkTable = s_pThunkTable;
-
- CVirtualThunks* pThunks = CVirtualThunks::GetVirtualThunks();
- if (pThunks)
- {
- // Compute the sizes of memory to be commited and allocated
- BOOL fCommit;
- if (dwSlots < pThunks->_dwReservedThunks)
- {
- fCommit = TRUE;
- dwCommitThunks = dwSlots;
- dwAllocThunks = 0;
- }
- else
- {
- fCommit = (pThunks->_dwCurrentThunk != pThunks->_dwReservedThunks);
- dwCommitThunks = pThunks->_dwReservedThunks;
- dwAllocThunks = dwSlots - pThunks->_dwReservedThunks;
- }
-
- // Commit memory if needed
- if (fCommit)
- {
- DWORD dwCommitSizeTmp = (sizeof(CVirtualThunks) - ConstVirtualThunkSize) +
- ((dwCommitThunks - pThunks->_dwStartThunk) * ConstVirtualThunkSize);
-
- if (!::ClrVirtualAlloc(pThunks, dwCommitSizeTmp, MEM_COMMIT, PAGE_EXECUTE_READWRITE))
- return(NULL);
-
- // Generate thunks that push slot number and jump to TP stub
- DWORD dwStartSlot = pThunks->_dwStartThunk;
- DWORD dwCurrentSlot = pThunks->_dwCurrentThunk;
- while (dwCurrentSlot < dwCommitThunks)
- {
- PCODE pCode = CreateThunkForVirtualMethod(dwCurrentSlot, (BYTE *)&pThunks->ThunkCode[dwCurrentSlot-dwStartSlot]);
- pThunkTable->SetSlot(dwCurrentSlot, pCode);
- ++dwCurrentSlot;
- }
-
- ClrFlushInstructionCache(&pThunks->ThunkCode[pThunks->_dwCurrentThunk-dwStartSlot],
- (dwCommitThunks-pThunks->_dwCurrentThunk)*ConstVirtualThunkSize);
-
- s_dwCommitedTPSlots = dwCommitThunks;
- pThunks->_dwCurrentThunk = dwCommitThunks;
- }
- }
-
- // <REVISIT_TODO>
- // Check for the avialability of a TP method table that is no longer being
- // reused </REVISIT_TODO>
-
- // Allocate memory if necessary
- if (dwAllocThunks)
- {
- DWORD dwReserveSize = ((sizeof(CVirtualThunks) - ConstVirtualThunkSize) +
- ((dwAllocThunks << 1) * ConstVirtualThunkSize) +
- g_SystemInfo.dwAllocationGranularity) & ~((size_t) g_SystemInfo.dwAllocationGranularity - 1);
-
- void *pAlloc = ::ClrVirtualAlloc(0, dwReserveSize,
- MEM_RESERVE | MEM_TOP_DOWN,
- PAGE_EXECUTE_READWRITE);
- if (pAlloc)
- {
- // Commit the required amount of memory
- DWORD dwCommitSizeTmp = (sizeof(CVirtualThunks) - ConstVirtualThunkSize) +
- (dwAllocThunks * ConstVirtualThunkSize);
-
- if (::ClrVirtualAlloc(pAlloc, dwCommitSizeTmp, MEM_COMMIT, PAGE_EXECUTE_READWRITE))
- {
- ((CVirtualThunks *) pAlloc)->_pNext = pThunks;
- pThunks = CVirtualThunks::SetVirtualThunks((CVirtualThunks *) pAlloc);
- pThunks->_dwReservedThunks = (dwReserveSize -
- (sizeof(CVirtualThunks) - ConstVirtualThunkSize)) /
- ConstVirtualThunkSize;
- pThunks->_dwStartThunk = dwCommitThunks;
- pThunks->_dwCurrentThunk = dwCommitThunks;
-
- // Generate thunks that push slot number and jump to TP stub
- DWORD dwStartSlot = pThunks->_dwStartThunk;
- DWORD dwCurrentSlot = pThunks->_dwCurrentThunk;
- while (dwCurrentSlot < dwSlots)
- {
- PCODE pCode = CreateThunkForVirtualMethod(dwCurrentSlot, (BYTE *)&pThunks->ThunkCode[dwCurrentSlot-dwStartSlot]);
- pThunkTable->SetSlot(dwCurrentSlot, pCode);
- ++dwCurrentSlot;
- }
-
- ClrFlushInstructionCache(&pThunks->ThunkCode[pThunks->_dwCurrentThunk-dwStartSlot],
- (dwSlots-pThunks->_dwCurrentThunk)*ConstVirtualThunkSize);
-
- s_dwCommitedTPSlots = dwSlots;
- pThunks->_dwCurrentThunk = dwSlots;
- }
- else
- {
- ::ClrVirtualFree(pAlloc, 0, MEM_RELEASE);
- return FALSE;
- }
- }
- else
- {
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CTPMethodTable::CreateTPOfClassForRP private
-//
-// Synopsis: Creates a transparent proxy that behaves as an object of the
-// supplied class
-//
-//+----------------------------------------------------------------------------
-void CTPMethodTable::CreateTPOfClassForRP(TypeHandle ty, REALPROXYREF *pRP, TRANSPARENTPROXYREF *pTP)
-{
- CONTRACT_VOID
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(!ty.IsNull());
- PRECONDITION(pRP != NULL);
- PRECONDITION(*pRP != NULL);
- PRECONDITION(pTP != NULL);
- POSTCONDITION(*pTP != NULL);
- }
- CONTRACT_END;
-
- // Ensure remoting is started.
- EnsureFieldsInitialized();
-
- MethodTable * pMT = ty.GetMethodTable();
-
- // Get the size of the VTable for the class to proxy
- DWORD dwSlots = pMT->GetNumVirtuals();
-
- if (dwSlots == 0)
- dwSlots = 1;
-
- // The global thunk table must have been initialized
- _ASSERTE(s_pThunkTable != NULL);
-
- // Check for the need to extend existing TP method table
- if (dwSlots > GetCommitedTPSlots())
- {
- CrstHolder ch(&s_TPMethodTableCrst);
-
- if (dwSlots > GetCommitedTPSlots())
- {
- if (!ExtendCommitedSlots(dwSlots))
- COMPlusThrowOM();
- }
- }
-
- // Create a TP Object
- IfNullThrow(*pTP = (TRANSPARENTPROXYREF) AllocateObject(GetMethodTable()));
-
- // Create the cycle between TP and RP
- (*pRP)->SetTransparentProxy(*pTP);
-
- // Make the TP behave as an object of supplied class
- (*pTP)->SetRealProxy(*pRP);
-
- // If we are creating a proxy for an interface then the class
- // is the object class else it is the class supplied
- if (pMT->IsInterface())
- {
- _ASSERTE(NULL != g_pObjectClass);
-
- (*pTP)->SetMethodTableBeingProxied(CRemotingServices::GetMarshalByRefClass());
-
- // Set the cached interface method table to the given interface
- // method table
- (*pTP)->SetInterfaceMethodTable(pMT);
- }
- else
- {
- (*pTP)->SetMethodTableBeingProxied(pMT);
- }
-
- RETURN;
-}
-
-Signature InitMessageData(messageData *msgData,
- FramedMethodFrame *pFrame,
- Module **ppModule,
- SigTypeContext *pTypeContext)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(msgData));
- PRECONDITION(CheckPointer(pFrame));
- PRECONDITION(CheckPointer(ppModule));
- PRECONDITION(CheckPointer(pTypeContext));
- }
- CONTRACTL_END;
-
- msgData->pFrame = pFrame;
- msgData->iFlags = 0;
-
- MethodDesc *pMD = pFrame->GetFunction();
- _ASSERTE(!pMD->ContainsGenericVariables());
- _ASSERTE(pMD->IsRuntimeMethodHandle());
-
- TypeHandle thGoverningType;
- BOOL fIsDelegate = pMD->GetMethodTable()->IsDelegate();
-
- // We want to calculate and store a governing type for the method since
- // sometimes the parent method table might be representative. We get the
- // exact type context from the this reference we're calling on (adjusting
- // for the fact it's a TP).
-
- // But cope with the common cases first for speed:
- // * If the method is not on a generic type and this is not the async
- // delegate case (which requires us to unwrap the delegate and have a
- // look) then we know the method desc's parent method table will be exact.
- // * We require method descs to be exact for the interface case as well (since
- // the target object doesn't help us resolve the interface type at all).
- // * COM interop can use this code path, but that doesn't support generics so
- // we can use the quick logic for that too.
- if ((!pMD->HasClassInstantiation() && !fIsDelegate) ||
- pMD->IsInterface() ||
- pMD->IsComPlusCall())
- {
- thGoverningType = TypeHandle(pMD->GetMethodTable());
- }
- else
- {
- MethodDesc *pTargetMD;
- MethodTable *pTargetMT;
- if (fIsDelegate)
- {
- // Async delegates are also handled differently in that the method and the
- // this are delegate wrappers round the real method and target.
- pTargetMD = COMDelegate::GetMethodDesc(pFrame->GetThis());
-
- // Delegates on static methods don't have a useful target instance.
- // But in that case the target method is guaranteed to have exact
- // type information.
- if (pTargetMD->IsStatic())
- pTargetMT = pTargetMD->GetMethodTable();
- else
- {
- OBJECTREF refDelegateTarget = COMDelegate::GetTargetObject(pFrame->GetThis());
- pTargetMT = refDelegateTarget->GetTrueMethodTable();
- }
- }
- else
- {
- pTargetMD = pMD;
- pTargetMT = CTPMethodTable::GetMethodTableBeingProxied(pFrame->GetThis());
- }
-
- // One last check to see if we can optimize the delegate case now we've
- // unwrapped it.
- if (fIsDelegate && !pTargetMD->HasClassInstantiation() && !pTargetMT->IsDelegate())
- {
- thGoverningType = TypeHandle(pTargetMD->GetMethodTable());
- }
- else
- {
- // Not quite done yet, we need to get the type that declares the method,
- // which may be a superclass of the type we're calling on.
- MethodTable *pDeclaringMT = pTargetMD->GetMethodTable();
- thGoverningType = ClassLoader::LoadGenericInstantiationThrowing(pDeclaringMT->GetModule(),
- pDeclaringMT->GetCl(),
- pTargetMD->GetExactClassInstantiation(TypeHandle(pTargetMT)));
- }
- }
-
- msgData->thGoverningType = thGoverningType;
-
- if (fIsDelegate)
- {
- DelegateEEClass* delegateCls = (DelegateEEClass*) pMD->GetMethodTable()->GetClass();
-
- _ASSERTE(pFrame->GetThis()->GetMethodTable()->IsDelegate());
-
- msgData->pDelegateMD = pMD;
- msgData->pMethodDesc = COMDelegate::GetMethodDesc(pFrame->GetThis());
-
- _ASSERTE(msgData->pMethodDesc != NULL);
- _ASSERTE(!msgData->pMethodDesc->ContainsGenericVariables());
- _ASSERTE(msgData->pMethodDesc->IsRuntimeMethodHandle());
-
- if (pMD == delegateCls->m_pBeginInvokeMethod)
- {
- msgData->iFlags |= MSGFLG_BEGININVOKE;
- }
- else
- {
- _ASSERTE(pMD == delegateCls->m_pEndInvokeMethod);
- msgData->iFlags |= MSGFLG_ENDINVOKE;
- }
- }
- else
- {
- msgData->pDelegateMD = NULL;
- msgData->pMethodDesc = pMD;
- _ASSERTE(msgData->pMethodDesc->IsRuntimeMethodHandle());
- }
-
- if (msgData->pMethodDesc->IsOneWay())
- {
- msgData->iFlags |= MSGFLG_ONEWAY;
- }
-
- if (msgData->pMethodDesc->IsCtor())
- {
- msgData->iFlags |= MSGFLG_CTOR;
- }
-
- Signature signature;
- Module *pModule;
-
- if (msgData->pDelegateMD)
- {
- signature = msgData->pDelegateMD->GetSignature();
- pModule = msgData->pDelegateMD->GetModule();
-
- // If the delegate is generic, pDelegateMD may not represent the exact instantiation so we recover it from 'this'.
- SigTypeContext::InitTypeContext(pFrame->GetThis()->GetMethodTable()->GetInstantiation(), Instantiation(), pTypeContext);
- }
- else if (msgData->pMethodDesc->IsVarArg())
- {
- VASigCookie *pVACookie = pFrame->GetVASigCookie();
- signature = pVACookie->signature;
- pModule = pVACookie->pModule;
- SigTypeContext::InitTypeContext(pTypeContext);
-
- }
- else
- {
- signature = msgData->pMethodDesc->GetSignature();
- pModule = msgData->pMethodDesc->GetModule();
- SigTypeContext::InitTypeContext(msgData->pMethodDesc, thGoverningType, pTypeContext);
- }
-
- *ppModule = pModule;
- return signature;
-}
-
-VOID CRealProxy::UpdateOptFlags(OBJECTREF refTP)
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END
-
- DWORD hierarchyDepth = 0;
- REALPROXYREF refRP = CTPMethodTable::GetRP(refTP);
-
- OBJECTHANDLE hServerIdentity = (OBJECTHANDLE)refRP->GetPtrOffset(CRemotingServices::GetOffsetOfSrvIdentityInRP());
- if (hServerIdentity == NULL)
- return;
-
- // Check if the proxy has already been marked as not equivalent.
- // In which case, it can never get marked as anything else
- RealProxyObject *rpTemp = (RealProxyObject *)OBJECTREFToObject(refRP);
-
- DWORD domainID = rpTemp->GetDomainID();
- AppDomainFromIDHolder ad((ADID)domainID, TRUE);
- if (domainID == 0 || ad.IsUnloaded()) //we do not use ptr
- return; // The appdomain the server belongs to, has been unloaded
- ad.Release();
- DWORD optFlag = rpTemp->GetOptFlags();
- if ((optFlag & OPTIMIZATION_FLAG_INITTED) &&
- !(optFlag & OPTIMIZATION_FLAG_PROXY_EQUIVALENT))
- return;
-
- OBJECTREF refSrvIdentity = ObjectFromHandle(hServerIdentity);
- // Is this a disconnected proxy ?
- if (refSrvIdentity == NULL)
- return;
-
- OBJECTREF refSrvObject = ObjectToOBJECTREF((Object *)refSrvIdentity->GetPtrOffset(CRemotingServices::GetOffsetOfTPOrObjInIdentity()));
-
- MethodTable *pCliMT = CTPMethodTable::GetMethodTableBeingProxied(refTP);
-
- BOOL bProxyQualifies = FALSE;
- BOOL bCastToSharedType = FALSE;
-
- // Check if modules are physically the same
-
- // Check the inheritance hierarchy of the server object, to find the type
- // that corresponds to the type the proxy is being cast to
- // @TODO - If being cast to an interface, currently the proxy doesnt get marked equivalent
- // @TODO - Need to check equivalency of the interface being cast to, and then reuse interface slot # on other side
- LPCUTF8 szCliTypeName, szCliNameSpace;
- szCliTypeName = pCliMT->GetFullyQualifiedNameInfo(&szCliNameSpace);
- PREFIX_ASSUME(szCliTypeName != NULL);
-
- MethodTable *pSrvHierarchy = refSrvObject->GetMethodTable();
-
- GCPROTECT_BEGIN(refRP);
- while (pSrvHierarchy)
- {
- LPCUTF8 szSrvTypeName, szSrvNameSpace;
- szSrvTypeName = pSrvHierarchy->GetFullyQualifiedNameInfo(&szSrvNameSpace);
- PREFIX_ASSUME(szSrvNameSpace != NULL);
-
- if (!strcmp(szCliTypeName, szSrvTypeName) && !strcmp(szCliNameSpace, szSrvNameSpace))
- {
- // Check if the types are shared. If they are, no further check neccesary
- if (pSrvHierarchy == pCliMT)
- {
- bProxyQualifies = TRUE;
- bCastToSharedType = TRUE;
- }
- else
- {
- bProxyQualifies = CRealProxy::ProxyTypeIdentityCheck(pCliMT, pSrvHierarchy);
- }
- break;
- }
-
- pSrvHierarchy = pSrvHierarchy->GetParentMethodTable();
- hierarchyDepth++;
- }
- GCPROTECT_END();
-
- optFlag = 0;
- if (bProxyQualifies && hierarchyDepth < OPTIMIZATION_FLAG_DEPTH_MASK)
- {
- optFlag = OPTIMIZATION_FLAG_INITTED | OPTIMIZATION_FLAG_PROXY_EQUIVALENT;
- if (bCastToSharedType)
- optFlag |= OPTIMIZATION_FLAG_PROXY_SHARED_TYPE;
- optFlag |= (hierarchyDepth & OPTIMIZATION_FLAG_DEPTH_MASK);
- }
- else
- optFlag = OPTIMIZATION_FLAG_INITTED;
-
- RealProxyObject *rpUNSAFE = (RealProxyObject *)OBJECTREFToObject(refRP);
- rpUNSAFE->SetOptFlags(optFlag);
-}
-
-BOOL CRealProxy::ProxyTypeIdentityCheck(MethodTable *pCliHierarchy, MethodTable *pSrvHierarchy)
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- THROWS;
- }
- CONTRACTL_END
- // We have found the server side type that corresponds to the most derived type
- // on client side, that the proxy is cast to
- // Now do identity check on the server type hierarchy to see if there is an exact match
-
- BOOL bProxyQualifies = FALSE;
- do
- {
- LPCUTF8 szCliTypeName, szCliNameSpace;
- LPCUTF8 szSrvTypeName, szSrvNameSpace;
- szCliTypeName = pCliHierarchy->GetFullyQualifiedNameInfo(&szCliNameSpace);
- szSrvTypeName = pSrvHierarchy->GetFullyQualifiedNameInfo(&szSrvNameSpace);
- PREFIX_ASSUME(szCliTypeName != NULL);
- PREFIX_ASSUME(szSrvNameSpace != NULL);
-
- // If type names are different, there is no match
- if (strcmp(szCliTypeName, szSrvTypeName) ||
- strcmp(szCliNameSpace, szSrvNameSpace))
- {
- bProxyQualifies = FALSE;
- return bProxyQualifies;
- }
-
- PEAssembly *pClientPE = pCliHierarchy->GetAssembly()->GetManifestFile();
- PEAssembly *pServerPE = pSrvHierarchy->GetAssembly()->GetManifestFile();
- // If the PE files are different, there is no match
- if (!pClientPE->Equals(pServerPE))
- {
- bProxyQualifies = FALSE;
- return bProxyQualifies;
- }
-
- // If the number of interfaces implemented are different, there is no match
- if (pSrvHierarchy->GetNumInterfaces() != pCliHierarchy->GetNumInterfaces())
- {
- bProxyQualifies = FALSE;
- return bProxyQualifies;
- }
-
- MethodTable::InterfaceMapIterator srvItfIt = pSrvHierarchy->IterateInterfaceMap();
- MethodTable::InterfaceMapIterator cliItfIt = pCliHierarchy->IterateInterfaceMap();
- while (srvItfIt.Next())
- {
- BOOL succeeded;
- succeeded = cliItfIt.Next();
- CONSISTENCY_CHECK(succeeded);
- if (!ProxyTypeIdentityCheck(srvItfIt.GetInterface(), cliItfIt.GetInterface()))
- {
- bProxyQualifies = FALSE;
- return bProxyQualifies;
- }
- }
-
- pSrvHierarchy = pSrvHierarchy->GetParentMethodTable();
- pCliHierarchy = pCliHierarchy->GetParentMethodTable();
- }
- while (pSrvHierarchy && pCliHierarchy);
-
- if (pSrvHierarchy || pCliHierarchy)
- {
- bProxyQualifies = FALSE;
- return bProxyQualifies;
- }
-
- bProxyQualifies = TRUE;
- return bProxyQualifies;
-
-}
-
-ProfilerRemotingClientCallbackHolder::ProfilerRemotingClientCallbackHolder()
-{
-#ifdef PROFILING_SUPPORTED
- // If profiling is active, notify it that remoting stuff is kicking in
- BEGIN_PIN_PROFILER(CORProfilerTrackRemoting());
- GCX_PREEMP();
- g_profControlBlock.pProfInterface->RemotingClientInvocationStarted();
- END_PIN_PROFILER();
-#endif // PROFILING_SUPPORTED
-}
-
-ProfilerRemotingClientCallbackHolder::~ProfilerRemotingClientCallbackHolder()
-{
-#ifdef PROFILING_SUPPORTED
- // If profiling is active, tell profiler we've made the call, received the
- // return value, done any processing necessary, and now remoting is done.
- BEGIN_PIN_PROFILER(CORProfilerTrackRemoting());
- GCX_PREEMP();
- g_profControlBlock.pProfInterface->RemotingClientInvocationFinished();
- END_PIN_PROFILER();
-#endif // PROFILING_SUPPORTED
-}
-
-enum
-{
- CALLTYPE_INVALIDCALL = 0x0, // Important:: sync this with RealProxy.cs
- CALLTYPE_METHODCALL = 0x1, // Important:: sync this with RealProxy.cs
- CALLTYPE_CONSTRUCTORCALL = 0x2 // Important:: sync this with RealProxy.cs
-};
-
-extern "C" void STDCALL TransparentProxyStubPatch();
-
-//+----------------------------------------------------------------------------
-//
-// Method: TransparentProxyStubWorker
-//
-// Synopsis: This function gets control in two situations
-// (1) When a call is made on the transparent proxy it delegates to
-// PrivateInvoke method on the real proxy
-// (2) When a call is made on the constructor it again delegates to the
-// PrivateInvoke method on the real proxy.
-//
-//
-//+----------------------------------------------------------------------------
-extern "C" UINT32 STDCALL TransparentProxyStubWorker(TransitionBlock * pTransitionBlock, TADDR pMethodDescOrSlot)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- ENTRY_POINT;
- PRECONDITION(CheckPointer(pTransitionBlock));
- }
- CONTRACTL_END;
-
- UINT fpRetSize = 0;
-
- FrameWithCookie<TPMethodFrame> frame(pTransitionBlock);
- TPMethodFrame * pFrame = &frame;
-
- //we need to zero out the return value buffer because we will report it during GC
-#ifdef ENREGISTERED_RETURNTYPE_MAXSIZE
- ZeroMemory (pFrame->GetReturnValuePtr(), ENREGISTERED_RETURNTYPE_MAXSIZE);
-#else
- *(ARG_SLOT *)pFrame->GetReturnValuePtr() = 0;
-#endif
-
- // For virtual calls the slot number is pushed but for
- // non virtual calls/interface invoke the method descriptor is already
- // pushed
- MethodDesc * pMD;
- if ((pMethodDescOrSlot >> 16) == 0)
- {
- // The frame is not completly setup at this point.
- // Do not throw exceptions or provoke GC
- MethodTable* pMT = CTPMethodTable::GetMethodTableBeingProxied(pFrame->GetThis());
- _ASSERTE(pMT);
-
- // Replace the slot number with the method descriptor on the stack
- pMD = pMT->GetMethodDescForSlot((WORD)pMethodDescOrSlot);
- }
- else
- {
- pMD = dac_cast<PTR_MethodDesc>(pMethodDescOrSlot);
- }
- pFrame->SetFunction(pMD);
-
- pFrame->Push();
-
- // Give debugger opportunity to stop here now that we know the MethodDesc *
- TransparentProxyStubPatch();
-
- INSTALL_UNWIND_AND_CONTINUE_HANDLER;
-
- if (g_pConfig->UseNewCrossDomainRemoting())
- {
- BOOL bOptSuccess = FALSE;
- CrossDomainChannel cdc;
- bOptSuccess = cdc.CheckCrossDomainCall(pFrame);
- if (bOptSuccess)
- {
- fpRetSize = cdc.GetFPReturnSize();
- goto Done;
- }
- }
-
- {
- messageData msgData;
- Module *pModule = NULL;
- SigTypeContext inst;
- Signature signature = InitMessageData(&msgData, pFrame, &pModule, &inst);
-
- _ASSERTE(!signature.IsEmpty() && pModule);
-
- // Allocate metasig on the stack
- MetaSig mSig(signature, pModule, &inst);
- msgData.pSig = &mSig;
-
- MethodDesc *pMD = pFrame->GetFunction();
- if (pMD->GetMethodTable()->IsDelegate())
- {
- // check that there is only one target
- if (COMDelegate::IsTrueMulticastDelegate(pFrame->GetThis()))
- {
- COMPlusThrow(kArgumentException, W("Remoting_Delegate_TooManyTargets"));
- }
- }
-
- {
- ProfilerRemotingClientCallbackHolder profilerHolder;
-
- OBJECTREF pThisPointer = NULL;
-
- if (pMD->GetMethodTable()->IsDelegate())
- {
- // this is an async call
- _ASSERTE(pFrame->GetThis()->GetMethodTable()->IsDelegate());
-
- pThisPointer = COMDelegate::GetTargetObject(pFrame->GetThis());
- }
- else
- {
- pThisPointer = pFrame->GetThis();
- }
-
- OBJECTREF firstParameter;
- MethodDesc* pTargetMD = NULL;
- size_t callType = CALLTYPE_INVALIDCALL;
-
- // We are invoking either the constructor or a method on the object
- if(pMD->IsCtor())
- {
- // Get the address of PrivateInvoke in managed code
- pTargetMD = CRemotingServices::MDofPrivateInvoke();
- _ASSERTE(pThisPointer->IsTransparentProxy());
-
- firstParameter = CTPMethodTable::GetRP(pThisPointer);
-
- // Set a field to indicate that it is a constructor call
- callType = CALLTYPE_CONSTRUCTORCALL;
- }
- else
- {
- // Set a field to indicate that it is a method call
- callType = CALLTYPE_METHODCALL;
-
- if (pThisPointer->IsTransparentProxy())
- {
- // Extract the real proxy underlying the transparent proxy
- firstParameter = CTPMethodTable::GetRP(pThisPointer);
-
- // Get the address of PrivateInvoke in managed code
- pTargetMD = CRemotingServices::MDofPrivateInvoke();
- _ASSERTE(pTargetMD);
- }
- else
- {
- // must be async if this is not a TP
- _ASSERTE(pMD->GetMethodTable()->IsDelegate());
- firstParameter = NULL;
-
- // Get the address of PrivateInvoke in managed code
- pTargetMD = CRemotingServices::MDofInvokeStatic();
- }
-
- // Go ahead and call PrivateInvoke on Real proxy. There is no need to
- // catch exceptions thrown by it
- // See RealProxy.cs
- }
-
- _ASSERTE(pTargetMD);
-
- // Call the appropriate target
- CTPMethodTable::CallTarget(pTargetMD, (LPVOID)OBJECTREFToObject(firstParameter), (LPVOID)&msgData, (LPVOID)callType);
-
- // Check for the need to trip thread
- if (GetThread()->CatchAtSafePointOpportunistic())
- {
- // There is no need to GC protect the return object as
- // TPFrame is GC protecting it
- CommonTripThread();
- }
- } // ProfilerClientCallbackHolder
-
- {
- mSig.Reset();
-
- ArgIterator argit(&mSig);
-
-#ifdef _TARGET_X86_
- // Set the number of bytes to pop for x86
- pFrame->SetCbStackPop(argit.CbStackPop());
-#endif // _TARGET_X86_
-
- fpRetSize = argit.GetFPReturnSize();
- }
- }
-
-Done: ;
-
- pFrame->Pop();
-
- UNINSTALL_UNWIND_AND_CONTINUE_HANDLER;
-
- return fpRetSize;
-}
-
-
-// Helper due to inability to combine SEH with anything interesting.
-BOOL CTPMethodTable::CheckCastHelper(MethodDesc* pTargetMD, LPVOID pFirst, LPVOID pSecond)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pTargetMD));
- PRECONDITION(CheckPointer(pFirst, NULL_OK));
- PRECONDITION(CheckPointer(pSecond, NULL_OK));
- }
- CONTRACTL_END;
-
- // Actual return type is a managed 'bool', so only look at a CLR_BOOL-sized
- // result. The high bits are undefined on AMD64. (Note that a narrowing
- // cast to CLR_BOOL will not work since it is the same as checking the
- // size_t result != 0.)
- LPVOID ret = CallTarget(pTargetMD, pFirst, pSecond);
- return *(CLR_BOOL*)StackElemEndianessFixup(&ret, sizeof(CLR_BOOL));
-}
-
-
-
-//+----------------------------------------------------------------------------
-//
-// Method: CTPMethodTable::CheckCast private
-//
-// Synopsis: Call the managed checkcast method to determine whether the
-// server type can be cast to the given type
-//
-//
-//
-//+----------------------------------------------------------------------------
-BOOL CTPMethodTable::CheckCast(MethodDesc* pTargetMD, TRANSPARENTPROXYREF orTP, TypeHandle ty)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pTargetMD));
- PRECONDITION(orTP != NULL);
- PRECONDITION(!ty.IsNull());
- }
- CONTRACTL_END;
-
- REFLECTCLASSBASEREF reflectType = NULL;
- LPVOID pvType = NULL;
- BOOL fCastOK = FALSE;
-
- typedef struct _GCStruct
- {
- TRANSPARENTPROXYREF orTP;
- REALPROXYREF orRP;
- } GCStruct;
-
- GCStruct gcValues;
- gcValues.orTP = orTP;
- gcValues.orRP = GetRP(orTP);
-
- GCPROTECT_BEGIN (gcValues);
-
- reflectType = (REFLECTCLASSBASEREF) ty.GetMethodTable()->GetManagedClassObject();
- *(REFLECTCLASSBASEREF *)&pvType = reflectType;
-
- fCastOK = CheckCastHelper(pTargetMD,
- (LPVOID)OBJECTREFToObject(gcValues.orRP),
- pvType);
-
- if (fCastOK)
- {
- _ASSERTE(s_fTPTableFieldsInitialized);
-
- // The cast succeeded. Replace the current type in the proxy
- // with the given type.
-
- CrstHolder ch(&s_TPMethodTableCrst);
-
- if (ty.IsInterface())
- {
- // We replace the cached interface method table with the interface
- // method table that we are trying to cast to. This will ensure that
- // casts to this interface, which are likely to happen, will succeed.
- gcValues.orTP->SetInterfaceMethodTable(ty.GetMethodTable());
- }
- else
- {
- MethodTable *pCurrent = gcValues.orTP->GetMethodTableBeingProxied();
-
- BOOL fDerivedClass = FALSE;
- // Check whether this class derives from the current class
- fDerivedClass = CRemotingServices::CheckCast(gcValues.orTP, ty,
- TypeHandle(pCurrent));
- // We replace the current method table only if we cast to a more
- // derived class
- if (fDerivedClass)
- {
- // Set the method table in the proxy to the given method table
- RefineProxy(gcValues.orTP, ty);
- }
- }
- }
-
- GCPROTECT_END();
- return fCastOK;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CTPMethodTable::RefineProxy public
-//
-// Synopsis: Set the method table in the proxy to the given class' method table.
-// Additionally, expand the TP method table to the required number of slots.
-//
-//
-//+----------------------------------------------------------------------------
-void CTPMethodTable::RefineProxy(TRANSPARENTPROXYREF orTP, TypeHandle ty)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(orTP != NULL);
- PRECONDITION(!ty.IsNull());
- }
- CONTRACTL_END;
-
- // Do the expansion only if necessary
- MethodTable *pMT = ty.GetMethodTable();
-
- if (pMT != orTP->GetMethodTableBeingProxied())
- {
- orTP->SetMethodTableBeingProxied(pMT);
-
- // Extend the vtable if necessary
- DWORD dwSlots = pMT->GetNumVirtuals();
-
- if (dwSlots == 0)
- dwSlots = 1;
-
- if((dwSlots > GetCommitedTPSlots()) && !ExtendCommitedSlots(dwSlots))
- {
- // We failed to extend the committed slots. Out of memory.
- COMPlusThrowOM();
- }
-
- }
-}
-
-#ifndef HAS_REMOTING_PRECODE
-//+----------------------------------------------------------------------------
-//
-// Method: CTPMethodTable::GetOrCreateNonVirtualSlotForVirtualMethod private
-//
-// Synopsis: Get a slot for a non-virtual call to a virtual method.
-//
-//+----------------------------------------------------------------------------
-PTR_PCODE CTPMethodTable::GetOrCreateNonVirtualSlotForVirtualMethod(MethodDesc* pMD)
-{
- CONTRACT (PTR_PCODE)
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(pMD));
- PRECONDITION(pMD->IsRemotingInterceptedViaVirtualDispatch());
- POSTCONDITION(CheckPointer(RETVAL));
- }
- CONTRACT_END;
-
- // Ensure the TP MethodTable's fields have been initialized.
- EnsureFieldsInitialized();
-
- PTR_PCODE pSlot;
-
- {
- // Create the thunk in a thread safe manner
- CrstHolder ch(&s_TPMethodTableCrst);
-
- // NOTE: CNonVirtualThunk::SetNonVirtualThunks() depends on the lock being initialized
- CNonVirtualThunk::InitializeListLock();
-
- // Create hash table if we do not have one yet
- if (s_pThunkHashTable == NULL)
- {
- NewHolder <EEThunkHashTable> pTempHash(new EEThunkHashTable());
-
- LockOwner lock = {&s_TPMethodTableCrst, IsOwnerOfCrst};
- IfNullThrow(pTempHash->Init(23,&lock));
-
- s_pThunkHashTable = pTempHash.Extract();
- }
-
- if (!s_pThunkHashTable->GetValue(pMD, (HashDatum *)&pSlot))
- {
- PCODE pThunkCode = CreateNonVirtualThunkForVirtualMethod(pMD);
-
- _ASSERTE(CNonVirtualThunkMgr::IsThunkByASM(pThunkCode));
- _ASSERTE(CNonVirtualThunkMgr::GetMethodDescByASM(pThunkCode));
-
- // Set the generated thunk once and for all..
- CNonVirtualThunk *pThunk = CNonVirtualThunk::SetNonVirtualThunks((BYTE*)pThunkCode);
-
- // Remember the thunk address in a hash table
- // so that we dont generate it again
- pSlot = (PTR_PCODE)pThunk->GetAddrOfCode();
- s_pThunkHashTable->InsertValue(pMD, (HashDatum)pSlot);
- }
- }
-
- RETURN pSlot;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CTPMethodTable::DestroyThunk public
-//
-// Synopsis: Destroy the thunk for the non virtual method.
-//
-//
-//+----------------------------------------------------------------------------
-void CTPMethodTable::DestroyThunk(MethodDesc* pMD)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(pMD));
- }
- CONTRACTL_END;
-
- if(s_pThunkHashTable)
- {
- CrstHolder ch(&s_TPMethodTableCrst);
-
- LPVOID pvCode = NULL;
- s_pThunkHashTable->GetValue(pMD, (HashDatum *)&pvCode);
- CNonVirtualThunk *pThunk = NULL;
- if(NULL != pvCode)
- {
- pThunk = CNonVirtualThunk::AddrToThunk(pvCode);
- delete pThunk;
- s_pThunkHashTable->DeleteValue(pMD);
- }
- }
-}
-#endif // HAS_REMOTING_PRECODE
-
-static LPVOID CallTargetWorker1(MethodDesc* pTargetMD,
- LPVOID pvFirst,
- LPVOID pvSecond)
-{
- STATIC_CONTRACT_THROWS;
- STATIC_CONTRACT_GC_TRIGGERS;
- STATIC_CONTRACT_MODE_COOPERATIVE;
- STATIC_CONTRACT_SO_INTOLERANT;
-
- LPVOID ret = NULL;
- PCODE pTarget = pTargetMD->GetSingleCallableAddrOfCode();
-
-#if defined(DEBUGGING_SUPPORTED)
- if (CORDebuggerTraceCall())
- {
- g_pDebugInterface->TraceCall((const BYTE*)pTarget);
- }
-#endif // DEBUGGING_SUPPORTED
-
-
- BEGIN_CALL_TO_MANAGED();
-
- ret = CTPMethodTable__CallTargetHelper2((const BYTE*)pTarget, pvFirst, pvSecond);
-
- END_CALL_TO_MANAGED();
-
- return ret;
-}
-
-
-//+----------------------------------------------------------------------------
-//
-// Method: CTPMethodTable::CallTarget private
-//
-// Synopsis: Calls the target method on the given object
-//
-//+----------------------------------------------------------------------------
-LPVOID __stdcall CTPMethodTable::CallTarget (MethodDesc* pTargetMD,
- LPVOID pvFirst,
- LPVOID pvSecond)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- SO_INTOLERANT;
- PRECONDITION(CheckPointer(pTargetMD));
- PRECONDITION(CheckPointer(pvFirst, NULL_OK));
- PRECONDITION(CheckPointer(pvSecond, NULL_OK));
- }
- CONTRACTL_END;
-
-#ifdef _DEBUG
-
- Thread* curThread = GetThread();
-
- Object* ObjRefTable[OBJREF_TABSIZE];
-
- if (curThread)
- memcpy(ObjRefTable, curThread->dangerousObjRefs, sizeof(curThread->dangerousObjRefs));
-
-#endif // _DEBUG
-
- LPVOID ret = CallTargetWorker1(pTargetMD, pvFirst, pvSecond);
-
-#ifdef _DEBUG
- // Restore dangerousObjRefs when we return back to EE after call
- if (curThread)
- memcpy(curThread->dangerousObjRefs, ObjRefTable, sizeof(curThread->dangerousObjRefs));
-
- ENABLESTRESSHEAP ();
-#endif // _DEBUG
-
- return ret;
-}
-
-
-static LPVOID CallTargetWorker2(MethodDesc* pTargetMD,
- LPVOID pvFirst,
- LPVOID pvSecond,
- LPVOID pvThird)
-{
- STATIC_CONTRACT_THROWS;
- STATIC_CONTRACT_GC_TRIGGERS;
- STATIC_CONTRACT_MODE_COOPERATIVE;
- STATIC_CONTRACT_SO_INTOLERANT;
-
- LPVOID ret = NULL;
- PCODE pTarget = pTargetMD->GetSingleCallableAddrOfCode();
-
-#if defined(DEBUGGING_SUPPORTED)
- if (CORDebuggerTraceCall())
- {
- g_pDebugInterface->TraceCall((const BYTE*)pTarget);
- }
-#endif // DEBUGGING_SUPPORTED
-
- BEGIN_CALL_TO_MANAGED();
-
- ret = CTPMethodTable__CallTargetHelper3((const BYTE*)pTarget, pvFirst, pvSecond, pvThird);
-
- END_CALL_TO_MANAGED();
- return ret;
-
-}
-
-LPVOID __stdcall CTPMethodTable::CallTarget (MethodDesc* pTargetMD,
- LPVOID pvFirst,
- LPVOID pvSecond,
- LPVOID pvThird)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- SO_INTOLERANT;
- PRECONDITION(CheckPointer(pTargetMD));
- PRECONDITION(CheckPointer(pvFirst, NULL_OK));
- PRECONDITION(CheckPointer(pvSecond, NULL_OK));
- PRECONDITION(CheckPointer(pvThird, NULL_OK));
- }
- CONTRACTL_END;
-
-#ifdef _DEBUG
- Thread* curThread = GetThread();
-
- Object* ObjRefTable[OBJREF_TABSIZE];
- if (curThread)
- memcpy(ObjRefTable, curThread->dangerousObjRefs, sizeof(curThread->dangerousObjRefs));
-
-#endif // _DEBUG
-
- LPVOID ret = CallTargetWorker2(pTargetMD, pvFirst, pvSecond, pvThird);
-
-#ifdef _DEBUG
- // Restore dangerousObjRefs when we return back to EE after call
- if (curThread)
- memcpy(curThread->dangerousObjRefs, ObjRefTable, sizeof(curThread->dangerousObjRefs));
-
- ENABLESTRESSHEAP ();
-#endif // _DEBUG
-
- return ret;
-}
-
-
-#ifndef HAS_REMOTING_PRECODE
-//+----------------------------------------------------------------------------
-//
-// Method: CNonVirtualThunk::SetNextThunk public
-//
-// Synopsis: Creates a thunk for the given address and adds it to the global
-// list
-//
-//+----------------------------------------------------------------------------
-CNonVirtualThunk* CNonVirtualThunk::SetNonVirtualThunks(const BYTE* pbCode)
-{
- CONTRACT (CNonVirtualThunk*)
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pbCode));
- POSTCONDITION(CheckPointer(RETVAL));
- }
- CONTRACT_END;
-
- CNonVirtualThunk *pThunk = new CNonVirtualThunk(pbCode);
-
- // Put the generated thunk in a global list
- // Note: this is called when a NV thunk is being created ..
- // The TPMethodTable critsec is held at this point
- pThunk->SetNextThunk();
-
- // Set up the stub manager if necessary
- CNonVirtualThunkMgr::InitNonVirtualThunkManager();
-
- RETURN pThunk;
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CNonVirtualThunk::~CNonVirtualThunk public
-//
-// Synopsis: Deletes the thunk from the global list of thunks
-//
-//
-//+----------------------------------------------------------------------------
-CNonVirtualThunk::~CNonVirtualThunk()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(s_pNonVirtualThunks));
- }
- CONTRACTL_END;
-
- CNonVirtualThunk* pCurr = s_pNonVirtualThunks;
- CNonVirtualThunk* pPrev = NULL;
- BOOL found = FALSE;
-
- // Note: This is called with the TPMethodTable critsec held
- while(!found && (NULL != pCurr))
- {
- if(pCurr == this)
- {
- found = TRUE;
- SimpleRWLock::SimpleWriteLockHolder swlh(s_pNonVirtualThunksListLock);
-
- // Unlink from the chain
- if(NULL != pPrev)
- {
- pPrev->_pNext = pCurr->_pNext;
- }
- else
- {
- // First entry needs to be deleted
- s_pNonVirtualThunks = pCurr->_pNext;
- }
- }
- pPrev = pCurr;
- pCurr = pCurr->_pNext;
- }
-
- _ASSERTE(found);
-}
-#endif // HAS_REMOTING_PRECODE
-
-//+----------------------------------------------------------------------------
-//
-// Method: CVirtualThunkMgr::InitVirtualThunkManager public
-//
-// Synopsis: Adds the stub manager to aid debugger in stepping into calls
-//
-//
-//+----------------------------------------------------------------------------
-void CVirtualThunkMgr::InitVirtualThunkManager()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- INJECT_FAULT(COMPlusThrowOM());
- }
- CONTRACTL_END;
-
- // This is function is already threadsafe since this method is called from within a
- // critical section
- if(NULL == s_pVirtualThunkMgr)
- {
- // Add the stub manager for vtable calls
- s_pVirtualThunkMgr = new CVirtualThunkMgr();
-
- StubManager::AddStubManager(s_pVirtualThunkMgr);
- }
-
-}
-
-#endif // !DACCESS_COMPILE
-
-//+----------------------------------------------------------------------------
-//
-// Method: CVirtualThunkMgr::CheckIsStub_Internal public
-//
-// Synopsis: Returns TRUE if the given address is the starting address of
-// the transparent proxy stub
-//
-//+----------------------------------------------------------------------------
-BOOL CVirtualThunkMgr::CheckIsStub_Internal(PCODE stubStartAddress)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- SUPPORTS_DAC;
- }
- CONTRACTL_END;
-
- BOOL bIsStub = FALSE;
-
-#ifndef DACCESS_COMPILE
- if (!IsThunkByASM(stubStartAddress))
- return FALSE;
- if(NULL != FindThunk((const BYTE *) stubStartAddress))
- bIsStub = TRUE;
-#endif // !DACCESS_COMPILE
-
- return bIsStub;
-}
-
-#ifndef DACCESS_COMPILE
-
-//+----------------------------------------------------------------------------
-//
-// Method: CVirtualThunkMgr::Entry2MethodDesc public
-//
-// Synopsis: Convert a starting address to a MethodDesc
-//
-//+----------------------------------------------------------------------------
-MethodDesc *CVirtualThunkMgr::Entry2MethodDesc(PCODE StubStartAddress, MethodTable *pMT)
-{
- CONTRACT (MethodDesc*)
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pMT, NULL_OK));
- POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
- }
- CONTRACT_END;
-
- if (s_pVirtualThunkMgr == NULL)
- RETURN NULL;
-
- if (!pMT)
- RETURN NULL;
-
- if (!s_pVirtualThunkMgr->CheckIsStub_Internal(StubStartAddress))
- RETURN NULL;
-
- RETURN GetMethodDescByASM(StubStartAddress, pMT);
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CVirtualThunkMgr::FindThunk private
-//
-// Synopsis: Finds a thunk that matches the given starting address
-//
-//+----------------------------------------------------------------------------
-LPBYTE CVirtualThunkMgr::FindThunk(const BYTE *stubStartAddress)
-{
- CONTRACT (LPBYTE)
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(stubStartAddress, NULL_OK));
- POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
- SO_TOLERANT;
- }
- CONTRACT_END;
-
- CVirtualThunks* pThunks = CVirtualThunks::GetVirtualThunks();
- LPBYTE pThunkAddr = NULL;
-
- while(NULL != pThunks)
- {
- DWORD dwStartSlot = pThunks->_dwStartThunk;
- DWORD dwCurrSlot = pThunks->_dwStartThunk;
- DWORD dwMaxSlot = pThunks->_dwCurrentThunk;
- while (dwCurrSlot < dwMaxSlot)
- {
- LPBYTE pStartAddr = pThunks->ThunkCode[dwCurrSlot-dwStartSlot].pCode;
- if((stubStartAddress >= pStartAddr) &&
- (stubStartAddress < (pStartAddr + ConstVirtualThunkSize)))
- {
- pThunkAddr = pStartAddr;
- break;
- }
- ++dwCurrSlot;
- }
-
- pThunks = pThunks->GetNextThunk();
- }
-
- RETURN pThunkAddr;
-}
-
-#endif // !DACCESS_COMPILE
-
-#ifndef HAS_REMOTING_PRECODE
-
-#ifndef DACCESS_COMPILE
-
-//+----------------------------------------------------------------------------
-//
-// Method: CNonVirtualThunkMgr::InitNonVirtualThunkManager public
-//
-// Synopsis: Adds the stub manager to aid debugger in stepping into calls
-//
-//
-//+----------------------------------------------------------------------------
-void CNonVirtualThunkMgr::InitNonVirtualThunkManager()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- INJECT_FAULT(COMPlusThrowOM());
- }
- CONTRACTL_END;
-
- // This function is already thread safe since this method is called from within a
- // critical section
- if(NULL == s_pNonVirtualThunkMgr)
- {
- // Add the stub manager for non vtable calls
- s_pNonVirtualThunkMgr = new CNonVirtualThunkMgr();
-
- StubManager::AddStubManager(s_pNonVirtualThunkMgr);
- }
-}
-
-#endif // !DACCESS_COMPILE
-
-//+----------------------------------------------------------------------------
-//
-// Method: CNonVirtualThunkMgr::CheckIsStub_Internal public
-//
-// Synopsis: Returns TRUE if the given address is the starting address of
-// one of our thunks
-//
-//+----------------------------------------------------------------------------
-BOOL CNonVirtualThunkMgr::CheckIsStub_Internal(PCODE stubStartAddress)
-{
- WRAPPER_NO_CONTRACT;
-
- BOOL bIsStub = FALSE;
-
-#ifndef DACCESS_COMPILE
- if (!IsThunkByASM(stubStartAddress))
- return FALSE;
- if(NULL != FindThunk((const BYTE *) stubStartAddress))
- bIsStub = TRUE;
-#endif // !DACCESS_COMPILE
-
- return bIsStub;
-}
-
-#ifndef DACCESS_COMPILE
-
-//+----------------------------------------------------------------------------
-//
-// Method: CNonVirtualThunkMgr::Entry2MethodDesc public
-//
-// Synopsis: Convert a starting address to a MethodDesc
-//
-//+----------------------------------------------------------------------------
-MethodDesc *CNonVirtualThunkMgr::Entry2MethodDesc(PCODE StubStartAddress, MethodTable *pMT)
-{
- CONTRACT (MethodDesc*)
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pMT, NULL_OK));
- POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
- }
- CONTRACT_END;
-
- if (s_pNonVirtualThunkMgr == NULL)
- RETURN NULL;
-
- if (!s_pNonVirtualThunkMgr->CheckIsStub_Internal(StubStartAddress))
- RETURN NULL;
-
- RETURN GetMethodDescByASM(StubStartAddress);
-}
-
-//+----------------------------------------------------------------------------
-//
-// Method: CNonVirtualThunkMgr::FindThunk private
-//
-// Synopsis: Finds a thunk that matches the given starting address
-//
-//+----------------------------------------------------------------------------
-CNonVirtualThunk* CNonVirtualThunkMgr::FindThunk(const BYTE *stubStartAddress)
-{
- CONTRACT (CNonVirtualThunk*)
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(stubStartAddress, NULL_OK));
- POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
- SO_TOLERANT;
- }
- CONTRACT_END;
-
- SimpleRWLock::SimpleReadLockHolder srlh(CNonVirtualThunk::GetThunksListLock());
- CNonVirtualThunk* pThunk = CNonVirtualThunk::GetNonVirtualThunks();
-
- while(NULL != pThunk)
- {
- if(stubStartAddress == pThunk->GetThunkCode())
- break;
-
- pThunk = pThunk->GetNextThunk();
- }
-
- RETURN pThunk;
-}
-
-#endif // !DACCESS_COMPILE
-
-#endif // HAS_REMOTING_PRECODE
-
-
-#ifndef DACCESS_COMPILE
-
-//+----------------------------------------------------------------------------
-//+- HRESULT MethodDescDispatchHelper(MethodDesc* pMD, ARG_SLOT[] args, ARG_SLOT *pret)
-//+----------------------------------------------------------------------------
-HRESULT MethodDescDispatchHelper(MethodDescCallSite* pMethodCallSite, ARG_SLOT args[], ARG_SLOT *pret)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pMethodCallSite));
- PRECONDITION(CheckPointer(args));
- PRECONDITION(CheckPointer(pret));
- }
- CONTRACTL_END;
-
- HRESULT hr = S_OK;
- EX_TRY
- {
- *pret = pMethodCallSite->Call_RetArgSlot(args);
- }
- EX_CATCH_HRESULT(hr);
-
- return hr;
-}
-
-
-#ifdef FEATURE_COMINTEROP
-
-//+----------------------------------------------------------------------------
-//
-// Method: VOID CRemotingServices::CallSetDCOMProxy(OBJECTREF realProxy, IUnknown* pUnk)
-//
-//+----------------------------------------------------------------------------
-
-VOID CRemotingServices::CallSetDCOMProxy(OBJECTREF realProxy, IUnknown* pUnk)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(realProxy != NULL);
- PRECONDITION(CheckPointer(pUnk, NULL_OK));
- }
- CONTRACTL_END;
-
- GCPROTECT_BEGIN(realProxy);
-
- MethodDescCallSite setDCOMProxy(METHOD__REAL_PROXY__SETDCOMPROXY, &realProxy);
-
- ARG_SLOT args[] =
- {
- ObjToArgSlot(realProxy),
- (ARG_SLOT)pUnk
- };
-
- ARG_SLOT ret;
- MethodDescDispatchHelper(&setDCOMProxy, args, &ret);
-
- GCPROTECT_END();
-}
-
-
-BOOL CRemotingServices::CallSupportsInterface(OBJECTREF realProxy, REFIID iid, ARG_SLOT* pret)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(realProxy != NULL);
- PRECONDITION(CheckPointer(pret));
- }
- CONTRACTL_END;
-
- BOOL fResult = TRUE;
-
- GCPROTECT_BEGIN(realProxy);
-
- MethodDescCallSite supportsInterface(METHOD__REAL_PROXY__SUPPORTSINTERFACE, &realProxy);
-
- ARG_SLOT args[] =
- {
- ObjToArgSlot(realProxy),
- (ARG_SLOT)&iid
- };
-
- HRESULT hr = MethodDescDispatchHelper(&supportsInterface, args, pret);
-
- // It is allowed for the managed code to return a NULL interface pointer without returning
- // a failure HRESULT. This is done for performance to avoid having to throw an exception.
- // If this occurs, we need to return E_NOINTERFACE.
- if ((*(IUnknown**)pret) == NULL)
- hr = E_NOINTERFACE;
-
- if (FAILED(hr))
- fResult = FALSE;
-
- GCPROTECT_END();
- return fResult;
-}
-#endif // FEATURE_COMINTEROP
-
-//+----------------------------------------------------------------------------
-//
-// Method: CRemotingServices::GetStubForInterfaceMethod
-//
-// Synopsis: Given the exact interface method we wish to invoke on, return
-// the entry point of a stub that will correctly transition into
-// the remoting system passing it this method.
-// The stubs is just another kind of precode. They are cached
-// in per appdomain hash.
-//
-//
-//+----------------------------------------------------------------------------
-PCODE CRemotingServices::GetStubForInterfaceMethod(MethodDesc *pItfMD)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(pItfMD));
- PRECONDITION(pItfMD->IsInterface() && !pItfMD->IsStatic());
- }
- CONTRACTL_END;
-
- return pItfMD->GetLoaderAllocator()->GetFuncPtrStubs()->GetFuncPtrStub(pItfMD, PRECODE_STUB);
-}
-
-#endif // !DACCESS_COMPILE
-#endif // FEATURE_REMOTING
diff --git a/src/vm/rwlock.cpp b/src/vm/rwlock.cpp
deleted file mode 100644
index 9d8233d140..0000000000
--- a/src/vm/rwlock.cpp
+++ /dev/null
@@ -1,2952 +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.
-//
-
-//
-//+-------------------------------------------------------------------
-//
-// File: RWLock.cpp
-//
-// Contents: Reader writer lock implementation that supports the
-// following features
-// 1. Cheap enough to be used in large numbers
-// such as per object synchronization.
-// 2. Supports timeout. This is a valuable feature
-// to detect deadlocks
-// 3. Supports caching of events. This allows
-// the events to be moved from least contentious
-// regions to the most contentious regions.
-// In other words, the number of events needed by
-// Reader-Writer lockls is bounded by the number
-// of threads in the process.
-// 4. Supports nested locks by readers and writers
-// 5. Supports spin counts for avoiding context switches
-// on multi processor machines.
-// 6. Supports functionality for upgrading to a writer
-// lock with a return argument that indicates
-// intermediate writes. Downgrading from a writer
-// lock restores the state of the lock.
-// 7. Supports functionality to Release Lock for calling
-// app code. RestoreLock restores the lock state and
-// indicates intermediate writes.
-// 8. Recovers from most common failures such as creation of
-// events. In other words, the lock mainitains consistent
-// internal state and remains usable
-//
-//
-// Classes: CRWLock
-//
-//--------------------------------------------------------------------
-
-
-#include "common.h"
-#include "rwlock.h"
-#include "corhost.h"
-
-#ifdef FEATURE_RWLOCK
-
-// Reader increment
-#define READER 0x00000001
-// Max number of readers
-#define READERS_MASK 0x000003FF
-// Reader being signaled
-#define READER_SIGNALED 0x00000400
-// Writer being signaled
-#define WRITER_SIGNALED 0x00000800
-#define WRITER 0x00001000
-// Waiting reader increment
-#define WAITING_READER 0x00002000
-// Note size of waiting readers must be less
-// than or equal to size of readers
-#define WAITING_READERS_MASK 0x007FE000
-#define WAITING_READERS_SHIFT 13
-// Waiting writer increment
-#define WAITING_WRITER 0x00800000
-// Max number of waiting writers
-#define WAITING_WRITERS_MASK 0xFF800000
-// Events are being cached
-#define CACHING_EVENTS (READER_SIGNALED | WRITER_SIGNALED)
-
-// Cookie flags
-#define UPGRADE_COOKIE 0x02000
-#define RELEASE_COOKIE 0x04000
-#define COOKIE_NONE 0x10000
-#define COOKIE_WRITER 0x20000
-#define COOKIE_READER 0x40000
-#define INVALID_COOKIE (~(UPGRADE_COOKIE | RELEASE_COOKIE | \
- COOKIE_NONE | COOKIE_WRITER | COOKIE_READER))
-#define RWLOCK_MAX_ACQUIRE_COUNT 0xFFFF
-
-// globals
-Volatile<LONGLONG> CRWLock::s_mostRecentLockID = 0;
-CrstStatic CRWLock::s_RWLockCrst;
-
-// Default values
-#ifdef _DEBUG
-DWORD gdwDefaultTimeout = 120000;
-#else //!_DEBUG
-DWORD gdwDefaultTimeout = INFINITE;
-#endif //_DEBUG
-const DWORD gdwReasonableTimeout = 120000;
-DWORD gdwDefaultSpinCount = 0;
-BOOL fBreakOnErrors = FALSE; // Temporarily break on errors
-
-// <REVISIT_TODO> REVISIT_TODO: Bad practise</REVISIT_TODO>
-#define HEAP_SERIALIZE 0
-#define RWLOCK_RECOVERY_FAILURE (0xC0000227L)
-
-// Catch GC holes
-#if _DEBUG
-#define VALIDATE_LOCK(pRWLock) ((Object *) (pRWLock))->Validate();
-#else // !_DEBUG
-#define VALIDATE_LOCK(pRWLock)
-#endif // _DEBUG
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::ProcessInit public
-//
-// Synopsis: Reads default values from registry and intializes
-// process wide data structures
-//
-//+-------------------------------------------------------------------
-void CRWLock::ProcessInit()
-{
- CONTRACTL
- {
- THROWS; // From Crst.Init()
- GC_NOTRIGGER;
- PRECONDITION((g_SystemInfo.dwNumberOfProcessors != 0));
- }
- CONTRACTL_END;
-
- gdwDefaultSpinCount = (g_SystemInfo.dwNumberOfProcessors != 1) ? 500 : 0;
-
- PPEB peb = (PPEB) ClrTeb::GetProcessEnvironmentBlock();
- DWORD dwTimeout = (DWORD)(peb->CriticalSectionTimeout.QuadPart/-10000000);
- if (dwTimeout)
- {
- gdwDefaultTimeout = dwTimeout;
- }
-
- // Initialize the critical section used by the lock
- // Can throw out of memory here.
- s_RWLockCrst.Init(CrstRWLock, CRST_UNSAFE_ANYMODE);
-}
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::CRWLock public
-//
-// Synopsis: Constructor
-//
-//+-------------------------------------------------------------------
-CRWLock::CRWLock()
-: _hWriterEvent(NULL),
- _hReaderEvent(NULL),
- _dwState(0),
- _dwWriterID(0),
- _dwWriterSeqNum(1),
- _wWriterLevel(0)
-#ifdef RWLOCK_STATISTICS
- ,
- _dwReaderEntryCount(0),
- _dwReaderContentionCount(0),
- _dwWriterEntryCount(0),
- _dwWriterContentionCount(0),
- _dwEventsReleasedCount(0)
-#endif
-{
-
- CONTRACT_VOID
- {
- NOTHROW;
- GC_NOTRIGGER;
- POSTCONDITION((_dwLLockID > 0));
- }
- CONTRACT_END;
-
- LONGLONG qwLockID = s_mostRecentLockID;
- while (true)
- {
- LONGLONG qwNextLockID = qwLockID + 1;
- if (static_cast<LONG>(qwNextLockID) == 0)
- {
- // A value of zero for the lower half of the ID is reserved to identify that a thread does not own any RW locks,
- // regardless of the upper half of the ID
- ++qwNextLockID;
- }
-
- LONGLONG qwLockIDBeforeExchange = RWInterlockedCompareExchange64(&s_mostRecentLockID, qwNextLockID, qwLockID);
- if (qwLockIDBeforeExchange == qwLockID)
- {
- qwLockID = qwNextLockID;
- break;
- }
-
- qwLockID = qwLockIDBeforeExchange;
- }
-
- _dwLLockID = static_cast<LONG>(qwLockID);
- _dwULockID = static_cast<LONG>(qwLockID >> 32);
-
- RETURN;
-}
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::Cleanup public
-//
-// Synopsis: Cleansup state
-//
-//+-------------------------------------------------------------------
-void CRWLock::Cleanup()
-{
-
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- PRECONDITION((_dwState == 0)); // sanity checks
- PRECONDITION((_dwWriterID == 0));
- PRECONDITION((_wWriterLevel == 0));
- }
- CONTRACTL_END;
-
- if(_hWriterEvent) {
- delete _hWriterEvent;
- _hWriterEvent = NULL;
- }
- if(_hReaderEvent) {
- delete _hReaderEvent;
- _hReaderEvent = NULL;
- }
-
- return;
-}
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::ChainEntry private
-//
-// Synopsis: Chains the given lock entry into the chain
-//
-//+-------------------------------------------------------------------
-inline void CRWLock::ChainEntry(Thread *pThread, LockEntry *pLockEntry)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- // This is to synchronize with finalizer thread and deadlock detection.
- CrstHolder rwl(&s_RWLockCrst);
- LockEntry *pHeadEntry = pThread->m_pHead;
- pLockEntry->pNext = pHeadEntry;
- pLockEntry->pPrev = pHeadEntry->pPrev;
- pLockEntry->pPrev->pNext = pLockEntry;
- pHeadEntry->pPrev = pLockEntry;
-
- return;
-}
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::GetLockEntry private
-//
-// Synopsis: Gets lock entry from TLS
-//
-//+-------------------------------------------------------------------
-inline LockEntry *CRWLock::GetLockEntry(Thread* pThread)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- if (pThread == NULL) {
- pThread = GetThread();
- }
- LockEntry *pHeadEntry = pThread->m_pHead;
- LockEntry *pLockEntry = pHeadEntry;
- do
- {
- if((pLockEntry->dwLLockID == _dwLLockID) && (pLockEntry->dwULockID == _dwULockID))
- return(pLockEntry);
- pLockEntry = pLockEntry->pNext;
- } while(pLockEntry != pHeadEntry);
-
- return(NULL);
-}
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::FastGetOrCreateLockEntry private
-//
-// Synopsis: The fast path for getting a lock entry from TLS
-//
-//+-------------------------------------------------------------------
-inline LockEntry *CRWLock::FastGetOrCreateLockEntry()
-{
-
- CONTRACTL
- {
- THROWS; // SlowGetOrCreateLockEntry can throw out of memory exception
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- Thread *pThread = GetThread();
- _ASSERTE(pThread);
- LockEntry *pLockEntry = pThread->m_pHead;
- if(pLockEntry->dwLLockID == 0)
- {
- _ASSERTE(pLockEntry->wReaderLevel == 0);
- pLockEntry->dwLLockID = _dwLLockID;
- pLockEntry->dwULockID = _dwULockID;
- return(pLockEntry);
- }
- else if((pLockEntry->dwLLockID == _dwLLockID) && (pLockEntry->dwULockID == _dwULockID))
- {
- // Note, StaticAcquireReaderLock can have reentry via pumping while it's blocking
- // so no assertions about pLockEntry->wReaderLevel's state
- return(pLockEntry);
- }
-
- return(SlowGetOrCreateLockEntry(pThread));
-}
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::SlowGetorCreateLockEntry private
-//
-// Synopsis: The slow path for getting a lock entry from TLS
-//
-//+-------------------------------------------------------------------
-LockEntry *CRWLock::SlowGetOrCreateLockEntry(Thread *pThread)
-{
-
- CONTRACTL
- {
- THROWS; // memory allocation can throw out of memory exception
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- LockEntry *pFreeEntry = NULL;
- LockEntry *pHeadEntry = pThread->m_pHead;
-
- // Search for an empty entry or an entry belonging to this lock
- LockEntry *pLockEntry = pHeadEntry->pNext;
- while(pLockEntry != pHeadEntry)
- {
- if(pLockEntry->dwLLockID &&
- ((pLockEntry->dwLLockID != _dwLLockID) || (pLockEntry->dwULockID != _dwULockID)))
- {
- // Move to the next entry
- pLockEntry = pLockEntry->pNext;
- }
- else
- {
- // Prepare to move it to the head
- pFreeEntry = pLockEntry;
- pLockEntry->pPrev->pNext = pLockEntry->pNext;
- pLockEntry->pNext->pPrev = pLockEntry->pPrev;
-
- break;
- }
- }
-
- if(pFreeEntry == NULL)
- {
- pFreeEntry = new LockEntry;
- pFreeEntry->wReaderLevel = 0;
- }
-
- if(pFreeEntry)
- {
- _ASSERTE((pFreeEntry->dwLLockID != 0) || (pFreeEntry->wReaderLevel == 0));
- _ASSERTE((pFreeEntry->wReaderLevel == 0) ||
- ((pFreeEntry->dwLLockID == _dwLLockID) && (pFreeEntry->dwULockID == _dwULockID)));
-
- // Chain back the entry
- ChainEntry(pThread, pFreeEntry);
-
- // Move this entry to the head
- pThread->m_pHead = pFreeEntry;
-
- // Mark the entry as belonging to this lock
- pFreeEntry->dwLLockID = _dwLLockID;
- pFreeEntry->dwULockID = _dwULockID;
- }
-
- return pFreeEntry;
-}
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::FastRecycleLockEntry private
-//
-// Synopsis: Fast path for recycling the lock entry that is used
-// when the thread is the next few instructions is going
-// to call FastGetOrCreateLockEntry again
-//
-//+-------------------------------------------------------------------
-inline void CRWLock::FastRecycleLockEntry(LockEntry *pLockEntry)
-{
-
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
-
- // Sanity checks
- PRECONDITION(pLockEntry->wReaderLevel == 0);
- PRECONDITION((pLockEntry->dwLLockID == _dwLLockID) && (pLockEntry->dwULockID == _dwULockID));
- PRECONDITION(pLockEntry == GetThread()->m_pHead);
- }
- CONTRACTL_END;
-
-
- pLockEntry->dwLLockID = 0;
-}
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::RecycleLockEntry private
-//
-// Synopsis: Fast path for recycling the lock entry
-//
-//+-------------------------------------------------------------------
-inline void CRWLock::RecycleLockEntry(LockEntry *pLockEntry)
-{
-
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
-
- // Sanity check
- PRECONDITION(pLockEntry->wReaderLevel == 0);
- }
- CONTRACTL_END;
-
- // Move the entry to tail
- Thread *pThread = GetThread();
- LockEntry *pHeadEntry = pThread->m_pHead;
- if(pLockEntry == pHeadEntry)
- {
- pThread->m_pHead = pHeadEntry->pNext;
- }
- else if(pLockEntry->pNext->dwLLockID)
- {
- // Prepare to move the entry to tail
- pLockEntry->pPrev->pNext = pLockEntry->pNext;
- pLockEntry->pNext->pPrev = pLockEntry->pPrev;
-
- // Chain back the entry
- ChainEntry(pThread, pLockEntry);
- }
-
- // The entry does not belong to this lock anymore
- pLockEntry->dwLLockID = 0;
- return;
-}
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::StaticIsWriterLockHeld public
-//
-// Synopsis: Return TRUE if writer lock is held
-//
-//+-------------------------------------------------------------------
-FCIMPL1(FC_BOOL_RET, CRWLock::StaticIsWriterLockHeld, CRWLock *pRWLock)
-{
- FCALL_CONTRACT;
-
- if (pRWLock == NULL)
- {
- FCThrow(kNullReferenceException);
- }
-
- if(pRWLock->_dwWriterID == GetThread()->GetThreadId())
- FC_RETURN_BOOL(TRUE);
-
- FC_RETURN_BOOL(FALSE);
-}
-FCIMPLEND
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::StaticIsReaderLockHeld public
-//
-// Synopsis: Return TRUE if reader lock is held
-//
-//+-------------------------------------------------------------------
-FCIMPL1(FC_BOOL_RET, CRWLock::StaticIsReaderLockHeld, CRWLock *pRWLock)
-{
- FCALL_CONTRACT;
-
- if (pRWLock == NULL)
- {
- FCThrow(kNullReferenceException);
- }
-
- LockEntry *pLockEntry = pRWLock->GetLockEntry();
- if(pLockEntry)
- {
- FC_RETURN_BOOL(pLockEntry->wReaderLevel > 0);
- }
-
- FC_RETURN_BOOL(FALSE);
-}
-FCIMPLEND
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::AssertWriterLockHeld public
-//
-// Synopsis: Asserts that writer lock is held
-//
-//+-------------------------------------------------------------------
-#ifdef _DEBUG
-BOOL CRWLock::AssertWriterLockHeld()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- if(_dwWriterID == GetThread()->GetThreadId())
- return(TRUE);
-
- _ASSERTE(!"Writer lock not held by the current thread");
- return(FALSE);
-}
-#endif
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::AssertWriterLockNotHeld public
-//
-// Synopsis: Asserts that writer lock is not held
-//
-//+-------------------------------------------------------------------
-#ifdef _DEBUG
-BOOL CRWLock::AssertWriterLockNotHeld()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- if(_dwWriterID != GetThread()->GetThreadId())
- return(TRUE);
-
- _ASSERTE(!"Writer lock held by the current thread");
- return(FALSE);
-}
-#endif
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::AssertReaderLockHeld public
-//
-// Synopsis: Asserts that reader lock is held
-//
-//+-------------------------------------------------------------------
-#ifdef _DEBUG
-BOOL CRWLock::AssertReaderLockHeld()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- LockEntry *pLockEntry = GetLockEntry();
- if(pLockEntry)
- {
- _ASSERTE(pLockEntry->wReaderLevel);
- return(TRUE);
- }
-
- _ASSERTE(!"Reader lock not held by the current thread");
- return(FALSE);
-}
-#endif
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::AssertReaderLockNotHeld public
-//
-// Synopsis: Asserts that writer lock is not held
-//
-//+-------------------------------------------------------------------
-#ifdef _DEBUG
-BOOL CRWLock::AssertReaderLockNotHeld()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- LockEntry *pLockEntry = GetLockEntry();
- if(pLockEntry == NULL)
- return(TRUE);
-
- _ASSERTE(pLockEntry->wReaderLevel);
- _ASSERTE(!"Reader lock held by the current thread");
-
- return(FALSE);
-}
-#endif
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::AssertReaderOrWriterLockHeld public
-//
-// Synopsis: Asserts that writer lock is not held
-//
-//+-------------------------------------------------------------------
-#ifdef _DEBUG
-BOOL CRWLock::AssertReaderOrWriterLockHeld()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- if(_dwWriterID == GetThread()->GetThreadId())
- {
- return(TRUE);
- }
- else
- {
- LockEntry *pLockEntry = GetLockEntry();
- if(pLockEntry)
- {
- _ASSERTE(pLockEntry->wReaderLevel);
- return(TRUE);
- }
- }
-
- _ASSERTE(!"Neither Reader nor Writer lock held");
- return(FALSE);
-}
-#endif
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::RWSetEvent private
-//
-// Synopsis: Helper function for setting an event
-//
-//+-------------------------------------------------------------------
-inline void CRWLock::RWSetEvent(CLREvent* event)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- }
- CONTRACTL_END;
-
- if(!event->Set())
- {
- _ASSERTE(!"SetEvent failed");
- if(fBreakOnErrors) // fBreakOnErrors == FALSE so will be optimized out.
- DebugBreak();
- COMPlusThrowWin32(E_UNEXPECTED);
- }
-}
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::RWResetEvent private
-//
-// Synopsis: Helper function for resetting an event
-//
-//+-------------------------------------------------------------------
-inline void CRWLock::RWResetEvent(CLREvent* event)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- }
- CONTRACTL_END;
-
- if(!event->Reset())
- {
- _ASSERTE(!"ResetEvent failed");
- if(fBreakOnErrors) // fBreakOnErrors == FALSE so will be optimized out.
- DebugBreak();
- COMPlusThrowWin32(E_UNEXPECTED);
- }
-}
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::RWWaitForSingleObject public
-//
-// Synopsis: Helper function for waiting on an event
-//
-//+-------------------------------------------------------------------
-inline DWORD CRWLock::RWWaitForSingleObject(CLREvent* event, DWORD dwTimeout)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- }
- CONTRACTL_END;
-
- DWORD status = WAIT_FAILED;
- EX_TRY
- {
- status = event->Wait(dwTimeout,TRUE);
- }
- EX_CATCH
- {
- status = GET_EXCEPTION()->GetHR();
- if (status == S_OK)
- {
- status = WAIT_FAILED;
- }
- }
- EX_END_CATCH(SwallowAllExceptions); // The caller will rethrow the exception
-
- return status;
-}
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::RWSleep public
-//
-// Synopsis: Helper function for calling Sleep
-//
-//+-------------------------------------------------------------------
-inline void CRWLock::RWSleep(DWORD dwTime)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- ClrSleepEx(dwTime, TRUE);
-}
-
-
-#undef volatile
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::RWInterlockedCompareExchange public
-//
-// Synopsis: Helper function for calling intelockedCompareExchange
-//
-//+-------------------------------------------------------------------
-inline LONG CRWLock::RWInterlockedCompareExchange(LONG volatile *pvDestination,
- LONG dwExchange,
- LONG dwComparand)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- return FastInterlockCompareExchange(pvDestination,
- dwExchange,
- dwComparand);
-}
-
-inline LONGLONG CRWLock::RWInterlockedCompareExchange64(LONGLONG volatile *pvDestination,
- LONGLONG qwExchange,
- LONGLONG qwComparand)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- return FastInterlockCompareExchangeLong(pvDestination, qwExchange, qwComparand);
-}
-
-inline void* CRWLock::RWInterlockedCompareExchangePointer(PVOID volatile *pvDestination,
- void* pExchange,
- void* pComparand)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- return FastInterlockCompareExchangePointer(pvDestination,
- pExchange,
- pComparand);
-}
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::RWInterlockedExchangeAdd public
-//
-// Synopsis: Helper function for adding state
-//
-//+-------------------------------------------------------------------
-inline LONG CRWLock::RWInterlockedExchangeAdd(LONG volatile *pvDestination,
- LONG dwAddToState)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- return FastInterlockExchangeAdd(pvDestination, dwAddToState);
-}
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::RWInterlockedIncrement public
-//
-// Synopsis: Helper function for incrementing a pointer
-//
-//+-------------------------------------------------------------------
-inline LONG CRWLock::RWInterlockedIncrement(LONG volatile *pdwState)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- return FastInterlockIncrement(pdwState);
-}
-
-#define volatile DoNotUserVolatileKeyword
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::ReleaseEvents public
-//
-// Synopsis: Helper function for caching events
-//
-//+-------------------------------------------------------------------
-void CRWLock::ReleaseEvents()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- PRECONDITION(((_dwState & CACHING_EVENTS) == CACHING_EVENTS)); // Ensure that reader and writers have been stalled
-
- }
- CONTRACTL_END;
-
- // Save writer event
- CLREvent *hWriterEvent = _hWriterEvent;
- _hWriterEvent = NULL;
-
- // Save reader event
- CLREvent *hReaderEvent = _hReaderEvent;
- _hReaderEvent = NULL;
-
- // Allow readers and writers to continue
- RWInterlockedExchangeAdd(&_dwState, -(CACHING_EVENTS));
-
- // Cache events
- // <REVISIT_TODO>:
- // I am closing events for now. What is needed
- // is an event cache to which the events are
- // released using InterlockedCompareExchange64</REVISIT_TODO>
- if(hWriterEvent)
- {
- LOG((LF_SYNC, LL_INFO10, "Releasing writer event\n"));
- delete hWriterEvent;
- }
- if(hReaderEvent)
- {
- LOG((LF_SYNC, LL_INFO10, "Releasing reader event\n"));
- delete hReaderEvent;
- }
-#ifdef RWLOCK_STATISTICS
- RWInterlockedIncrement(&_dwEventsReleasedCount);
-#endif
-
- return;
-}
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::GetWriterEvent public
-//
-// Synopsis: Helper function for obtaining a auto reset event used
-// for serializing writers. It utilizes event cache
-//
-//+-------------------------------------------------------------------
-CLREvent* CRWLock::GetWriterEvent(HRESULT *pHR)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- }
- CONTRACTL_END;
-
- *pHR = S_OK;
- //GC could happen in ~CLREvent or EH. "this" is a GC object so it could be moved
- //during GC. So we need to cache the field before GC could happen
- CLREvent * result = _hWriterEvent;
-
- if(_hWriterEvent == NULL)
- {
- EX_TRY
- {
- CLREvent *pEvent = new CLREvent();
- NewHolder<CLREvent> hWriterEvent (pEvent);
- hWriterEvent->CreateRWLockWriterEvent(FALSE,this);
- if(hWriterEvent)
- {
- if(RWInterlockedCompareExchangePointer((PVOID*) &_hWriterEvent,
- hWriterEvent.GetValue(),
- NULL) == NULL)
- {
- hWriterEvent.SuppressRelease();
- }
- //GC could happen in ~CLREvent or EH. "this" is a GC object so it could be moved
- //during GC. So we need to cache the field before GC could happen.
- result = _hWriterEvent;
- }
- }
- EX_CATCH
- {
- *pHR = GET_EXCEPTION()->GetHR();
- }
- EX_END_CATCH(SwallowAllExceptions);
- }
-
- return(result);
-}
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::GetReaderEvent public
-//
-// Synopsis: Helper function for obtaining a manula reset event used
-// by readers to wait when a writer holds the lock.
-// It utilizes event cache
-//
-//+-------------------------------------------------------------------
-CLREvent* CRWLock::GetReaderEvent(HRESULT *pHR)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- }
- CONTRACTL_END;
-
- *pHR = S_OK;
- //GC could happen in ~CLREvent or EH. "this" is a GC object so it could be moved
- //during GC. So we need to cache the field before GC could happen
- CLREvent * result = _hReaderEvent;
-
- if(_hReaderEvent == NULL)
- {
- EX_TRY
- {
- CLREvent *pEvent = new CLREvent();
- NewHolder<CLREvent> hReaderEvent (pEvent);
- hReaderEvent->CreateRWLockReaderEvent(FALSE, this);
- if(hReaderEvent)
- {
- if(RWInterlockedCompareExchangePointer((PVOID*) &_hReaderEvent,
- hReaderEvent.GetValue(),
- NULL) == NULL)
- {
- hReaderEvent.SuppressRelease();
- }
- //GC could happen in ~CLREvent or EH. "this" is a GC object so it could be moved
- //during GC. So we need to cache the field before GC could happen
- result = _hReaderEvent;
- }
- }
- EX_CATCH
- {
- *pHR = GET_EXCEPTION()->GetHR();
- }
- EX_END_CATCH(SwallowAllExceptions);
- }
-
- return(result);
-}
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::StaticRecoverLock public
-//
-// Synopsis: Helper function to restore the lock to
-// the original state
-//
-
-//
-//+-------------------------------------------------------------------
-void CRWLock::StaticRecoverLock(
- CRWLock **ppRWLock,
- LockCookie *pLockCookie,
- DWORD dwFlags)
-{
- CONTRACTL
- {
- THROWS; // StaticAcquireWriterLock can throw exception
- GC_TRIGGERS;
- CAN_TAKE_LOCK;
- }
- CONTRACTL_END;
-
- DWORD dwTimeout = (gdwDefaultTimeout > gdwReasonableTimeout)
- ? gdwDefaultTimeout
- : gdwReasonableTimeout;
-
- Thread *pThread = GetThread();
- _ASSERTE (pThread);
-
- EX_TRY
- {
- // Check if the thread was a writer
- if(dwFlags & COOKIE_WRITER)
- {
- // Acquire writer lock
- StaticAcquireWriterLock(ppRWLock, dwTimeout);
- _ASSERTE (pThread->m_dwLockCount >= (*ppRWLock)->_wWriterLevel);
- ASSERT_UNLESS_NO_DEBUG_STATE(__pClrDebugState->GetLockCount(kDbgStateLockType_User) >= (*ppRWLock)->_wWriterLevel);
- pThread->m_dwLockCount -= (*ppRWLock)->_wWriterLevel;
- USER_LOCK_RELEASED_MULTIPLE((*ppRWLock)->_wWriterLevel, GetPtrForLockContract(ppRWLock));
- (*ppRWLock)->_wWriterLevel = pLockCookie->wWriterLevel;
- pThread->m_dwLockCount += (*ppRWLock)->_wWriterLevel;
- USER_LOCK_TAKEN_MULTIPLE((*ppRWLock)->_wWriterLevel, GetPtrForLockContract(ppRWLock));
- }
- // Check if the thread was a reader
- else if(dwFlags & COOKIE_READER)
- {
- StaticAcquireReaderLock(ppRWLock, dwTimeout);
- LockEntry *pLockEntry = (*ppRWLock)->GetLockEntry();
- _ASSERTE(pLockEntry);
- _ASSERTE (pThread->m_dwLockCount >= pLockEntry->wReaderLevel);
- ASSERT_UNLESS_NO_DEBUG_STATE(__pClrDebugState->GetLockCount(kDbgStateLockType_User) >= pLockEntry->wReaderLevel);
- pThread->m_dwLockCount -= pLockEntry->wReaderLevel;
- USER_LOCK_RELEASED_MULTIPLE(pLockEntry->wReaderLevel, GetPtrForLockContract(ppRWLock));
- pLockEntry->wReaderLevel = pLockCookie->wReaderLevel;
- pThread->m_dwLockCount += pLockEntry->wReaderLevel;
- USER_LOCK_TAKEN_MULTIPLE(pLockEntry->wReaderLevel, GetPtrForLockContract(ppRWLock));
- }
- }
- EX_CATCH
- {
- // Removed an assert here. This error is expected in case of
- // ThreadAbort.
- COMPlusThrowWin32(RWLOCK_RECOVERY_FAILURE);
- }
- EX_END_CATCH_UNREACHABLE
-}
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::StaticAcquireReaderLockPublic public
-//
-// Synopsis: Public access to StaticAcquireReaderLock
-//
-//+-------------------------------------------------------------------
-FCIMPL2(void, CRWLock::StaticAcquireReaderLockPublic, CRWLock *pRWLockUNSAFE, DWORD dwDesiredTimeout)
-{
- FCALL_CONTRACT;
-
- if (pRWLockUNSAFE == NULL)
- {
- FCThrowVoid(kNullReferenceException);
- }
-
- OBJECTREF pRWLock = ObjectToOBJECTREF((Object*)pRWLockUNSAFE);
- HELPER_METHOD_FRAME_BEGIN_1(pRWLock);
-
- StaticAcquireReaderLock((CRWLock**)&pRWLock, dwDesiredTimeout);
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::StaticAcquireReaderLock private
-//
-// Synopsis: Makes the thread a reader. Supports nested reader locks.
-//
-//+-------------------------------------------------------------------
-
-void CRWLock::StaticAcquireReaderLock(
- CRWLock **ppRWLock,
- DWORD dwDesiredTimeout)
-{
-
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS; // CLREvent::Wait is GC_TRIGGERS
- CAN_TAKE_LOCK;
- PRECONDITION(CheckPointer(ppRWLock));
- PRECONDITION(CheckPointer(*ppRWLock));
- }
- CONTRACTL_END;
-
- TESTHOOKCALL(AppDomainCanBeUnloaded(GetThread()->GetDomain()->GetId().m_dwId,FALSE));
-
- if (GetThread()->IsAbortRequested()) {
- GetThread()->HandleThreadAbort();
- }
-
- LockEntry *pLockEntry = (*ppRWLock)->FastGetOrCreateLockEntry();
- if (pLockEntry == NULL)
- {
- COMPlusThrowWin32(STATUS_NO_MEMORY);
- }
-
- DWORD dwStatus = WAIT_OBJECT_0;
- // Check for the fast path
- if(RWInterlockedCompareExchange(&(*ppRWLock)->_dwState, READER, 0) == 0)
- {
- _ASSERTE(pLockEntry->wReaderLevel == 0);
- }
- // Check for nested reader
- else if(pLockEntry->wReaderLevel != 0)
- {
- _ASSERTE((*ppRWLock)->_dwState & READERS_MASK);
-
- if (pLockEntry->wReaderLevel == RWLOCK_MAX_ACQUIRE_COUNT) {
- COMPlusThrow(kOverflowException, W("Overflow_UInt16"));
- }
- ++pLockEntry->wReaderLevel;
- INCTHREADLOCKCOUNT();
- USER_LOCK_TAKEN(GetPtrForLockContract(ppRWLock));
- return;
- }
- // Check if the thread already has writer lock
- else if((*ppRWLock)->_dwWriterID == GetThread()->GetThreadId())
- {
- StaticAcquireWriterLock(ppRWLock, dwDesiredTimeout);
- (*ppRWLock)->FastRecycleLockEntry(pLockEntry);
- return;
- }
- else
- {
- DWORD dwSpinCount;
- DWORD dwCurrentState, dwKnownState;
-
- // Initialize
- dwSpinCount = 0;
- dwCurrentState = (*ppRWLock)->_dwState;
- do
- {
- dwKnownState = dwCurrentState;
-
- // Reader need not wait if there are only readers and no writer
- if((dwKnownState < READERS_MASK) ||
- (((dwKnownState & READER_SIGNALED) && ((dwKnownState & WRITER) == 0)) &&
- (((dwKnownState & READERS_MASK) +
- ((dwKnownState & WAITING_READERS_MASK) >> WAITING_READERS_SHIFT)) <=
- (READERS_MASK - 2))))
- {
- // Add to readers
- dwCurrentState = RWInterlockedCompareExchange(&(*ppRWLock)->_dwState,
- (dwKnownState + READER),
- dwKnownState);
- if(dwCurrentState == dwKnownState)
- {
- // One more reader
- break;
- }
- }
- // Check for too many Readers or waiting readers or signaling in progress
- else if(((dwKnownState & READERS_MASK) == READERS_MASK) ||
- ((dwKnownState & WAITING_READERS_MASK) == WAITING_READERS_MASK) ||
- ((dwKnownState & CACHING_EVENTS) == READER_SIGNALED))
- {
- // Sleep
- GetThread()->UserSleep(1000);
-
- // Update to latest state
- dwSpinCount = 0;
- dwCurrentState = (*ppRWLock)->_dwState;
- }
- // Check if events are being cached
- else if((dwKnownState & CACHING_EVENTS) == CACHING_EVENTS)
- {
- if(++dwSpinCount > gdwDefaultSpinCount)
- {
- RWSleep(1);
- dwSpinCount = 0;
- }
- dwCurrentState = (*ppRWLock)->_dwState;
- }
- // Check spin count
- else if(++dwSpinCount <= gdwDefaultSpinCount)
- {
- dwCurrentState = (*ppRWLock)->_dwState;
- }
- else
- {
- // Add to waiting readers
- dwCurrentState = RWInterlockedCompareExchange(&(*ppRWLock)->_dwState,
- (dwKnownState + WAITING_READER),
- dwKnownState);
- if(dwCurrentState == dwKnownState)
- {
- CLREvent* hReaderEvent;
- DWORD dwModifyState;
-
- // One more waiting reader
-#ifdef RWLOCK_STATISTICS
- RWInterlockedIncrement(&(*ppRWLock)->_dwReaderContentionCount);
-#endif
- HRESULT hr;
- hReaderEvent = (*ppRWLock)->GetReaderEvent(&hr);
- if(hReaderEvent)
- {
- dwStatus = RWWaitForSingleObject(hReaderEvent, dwDesiredTimeout);
- VALIDATE_LOCK(*ppRWLock);
-
- // StaticAcquireReaderLock can have reentry via pumping while waiting for
- // hReaderEvent, which may change pLockEntry's state from underneath us.
- if ((pLockEntry->dwLLockID != (*ppRWLock)->_dwLLockID) ||
- (pLockEntry->dwULockID != (*ppRWLock)->_dwULockID))
- {
- pLockEntry = (*ppRWLock)->FastGetOrCreateLockEntry();
- if (pLockEntry == NULL)
- {
- COMPlusThrowWin32(STATUS_NO_MEMORY);
- }
- }
- }
- else
- {
- LOG((LF_SYNC, LL_WARNING,
- "AcquireReaderLock failed to create reader "
- "event for RWLock 0x%x\n", *ppRWLock));
- dwStatus = E_FAIL;
- }
-
- if(dwStatus == WAIT_OBJECT_0)
- {
- _ASSERTE((*ppRWLock)->_dwState & READER_SIGNALED);
- _ASSERTE(((*ppRWLock)->_dwState & READERS_MASK) < READERS_MASK);
- dwModifyState = READER - WAITING_READER;
- }
- else
- {
- dwModifyState = (DWORD) -WAITING_READER;
- if(dwStatus == WAIT_TIMEOUT)
- {
- LOG((LF_SYNC, LL_WARNING,
- "Timed out trying to acquire reader lock "
- "for RWLock 0x%x\n", *ppRWLock));
- hr = HRESULT_FROM_WIN32(ERROR_TIMEOUT);
- }
- else if(dwStatus == WAIT_IO_COMPLETION)
- {
- LOG((LF_SYNC, LL_WARNING,
- "Thread interrupted while trying to acquire reader lock "
- "for RWLock 0x%x\n", *ppRWLock));
- hr = COR_E_THREADINTERRUPTED;
- }
- else if (dwStatus == WAIT_FAILED)
- {
- if (SUCCEEDED(hr))
- {
- dwStatus = GetLastError();
- if (dwStatus == WAIT_OBJECT_0)
- {
- dwStatus = WAIT_FAILED;
- }
- hr = HRESULT_FROM_WIN32(dwStatus);
- LOG((LF_SYNC, LL_WARNING,
- "WaitForSingleObject on Event 0x%x failed for "
- "RWLock 0x%x with status code 0x%x\n",
- hReaderEvent, *ppRWLock, dwStatus));
- }
- }
- }
-
- // One less waiting reader and he may have become a reader
- dwKnownState = RWInterlockedExchangeAdd(&(*ppRWLock)->_dwState, dwModifyState);
-
- // Check for last signaled waiting reader
- if(dwStatus == WAIT_OBJECT_0)
- {
- _ASSERTE(dwKnownState & READER_SIGNALED);
- _ASSERTE((dwKnownState & READERS_MASK) < READERS_MASK);
- if((dwKnownState & WAITING_READERS_MASK) == WAITING_READER)
- {
- // Reset the event and lower reader signaled flag
- RWResetEvent(hReaderEvent);
- RWInterlockedExchangeAdd(&(*ppRWLock)->_dwState, -READER_SIGNALED);
- }
- }
- else
- {
- if(((dwKnownState & WAITING_READERS_MASK) == WAITING_READER) &&
- (dwKnownState & READER_SIGNALED))
- {
- HRESULT hr1;
- if(hReaderEvent == NULL)
- hReaderEvent = (*ppRWLock)->GetReaderEvent(&hr1);
- _ASSERTE(hReaderEvent);
-
- // Ensure the event is signalled before resetting it.
- DWORD dwTemp;
- dwTemp = hReaderEvent->Wait(INFINITE, FALSE);
- _ASSERTE(dwTemp == WAIT_OBJECT_0);
- _ASSERTE(((*ppRWLock)->_dwState & READERS_MASK) < READERS_MASK);
-
- // Reset the event and lower reader signaled flag
- RWResetEvent(hReaderEvent);
- RWInterlockedExchangeAdd(&(*ppRWLock)->_dwState, (READER - READER_SIGNALED));
-
- // Honor the orginal status
- ++pLockEntry->wReaderLevel;
- INCTHREADLOCKCOUNT();
- USER_LOCK_TAKEN(GetPtrForLockContract(ppRWLock));
- StaticReleaseReaderLock(ppRWLock);
- }
- else
- {
- (*ppRWLock)->FastRecycleLockEntry(pLockEntry);
- }
-
- _ASSERTE((pLockEntry == NULL) ||
- ((pLockEntry->dwLLockID == 0) &&
- (pLockEntry->wReaderLevel == 0)));
- if(fBreakOnErrors) // fBreakOnErrors == FALSE so will be optimized out.
- {
- _ASSERTE(!"Failed to acquire reader lock");
- DebugBreak();
- }
-
- // Prepare the frame for throwing an exception
- if ((DWORD)HOST_E_DEADLOCK == dwStatus)
- {
- // So that the error message is in the exception.
- RaiseDeadLockException();
- } else if ((DWORD)COR_E_THREADINTERRUPTED == dwStatus) {
- COMPlusThrow(kThreadInterruptedException);
- }
- else
- {
- COMPlusThrowWin32 (hr);
- }
- }
-
- // Sanity check
- _ASSERTE(dwStatus == WAIT_OBJECT_0);
- break;
- }
- }
- YieldProcessor(); // Indicate to the processor that we are spining
- } while(TRUE);
- }
-
- // Success
- _ASSERTE(dwStatus == WAIT_OBJECT_0);
- _ASSERTE(((*ppRWLock)->_dwState & WRITER) == 0);
- _ASSERTE((*ppRWLock)->_dwState & READERS_MASK);
- ++pLockEntry->wReaderLevel;
- INCTHREADLOCKCOUNT();
- USER_LOCK_TAKEN(GetPtrForLockContract(ppRWLock));
-#ifdef RWLOCK_STATISTICS
- RWInterlockedIncrement(&(*ppRWLock)->_dwReaderEntryCount);
-#endif
- return;
-}
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::StaticAcquireWriterLockPublic public
-//
-// Synopsis: Public access to StaticAcquireWriterLock
-//
-//+-------------------------------------------------------------------
-FCIMPL2(void, CRWLock::StaticAcquireWriterLockPublic, CRWLock *pRWLockUNSAFE, DWORD dwDesiredTimeout)
-{
- FCALL_CONTRACT;
-
- if (pRWLockUNSAFE == NULL)
- {
- FCThrowVoid(kNullReferenceException);
- }
-
- OBJECTREF pRWLock = ObjectToOBJECTREF((Object*)pRWLockUNSAFE);
- HELPER_METHOD_FRAME_BEGIN_1(pRWLock);
-
- StaticAcquireWriterLock((CRWLock**)&pRWLock, dwDesiredTimeout);
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::StaticAcquireWriterLock private
-//
-// Synopsis: Makes the thread a writer. Supports nested writer
-// locks
-//
-//+-------------------------------------------------------------------
-
-void CRWLock::StaticAcquireWriterLock(
- CRWLock **ppRWLock,
- DWORD dwDesiredTimeout)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS; // CLREvent::Wait can trigger GC
- CAN_TAKE_LOCK;
- PRECONDITION((CheckPointer(ppRWLock)));
- PRECONDITION((CheckPointer(*ppRWLock)));
- }
- CONTRACTL_END;
-
- TESTHOOKCALL(AppDomainCanBeUnloaded(GetThread()->GetDomain()->GetId().m_dwId,FALSE));
- if (GetThread()->IsAbortRequested()) {
- GetThread()->HandleThreadAbort();
- }
-
- // Declare locals needed for setting up frame
- DWORD dwThreadID = GetThread()->GetThreadId();
- DWORD dwStatus;
-
- // Check for the fast path
- if(RWInterlockedCompareExchange(&(*ppRWLock)->_dwState, WRITER, 0) == 0)
- {
- _ASSERTE(((*ppRWLock)->_dwState & READERS_MASK) == 0);
- }
- // Check if the thread already has writer lock
- else if((*ppRWLock)->_dwWriterID == dwThreadID)
- {
- if ((*ppRWLock)->_wWriterLevel == RWLOCK_MAX_ACQUIRE_COUNT) {
- COMPlusThrow(kOverflowException, W("Overflow_UInt16"));
- }
- ++(*ppRWLock)->_wWriterLevel;
- INCTHREADLOCKCOUNT();
- USER_LOCK_TAKEN(GetPtrForLockContract(ppRWLock));
- return;
- }
- else
- {
- DWORD dwCurrentState, dwKnownState;
- DWORD dwSpinCount;
-
- // Initialize
- dwSpinCount = 0;
- dwCurrentState = (*ppRWLock)->_dwState;
- do
- {
- dwKnownState = dwCurrentState;
-
- // Writer need not wait if there are no readers and writer
- if((dwKnownState == 0) || (dwKnownState == CACHING_EVENTS))
- {
- // Can be a writer
- dwCurrentState = RWInterlockedCompareExchange(&(*ppRWLock)->_dwState,
- (dwKnownState + WRITER),
- dwKnownState);
- if(dwCurrentState == dwKnownState)
- {
- // Only writer
- break;
- }
- }
- // Check for too many waiting writers
- else if(((dwKnownState & WAITING_WRITERS_MASK) == WAITING_WRITERS_MASK))
- {
- // Sleep
- GetThread()->UserSleep(1000);
-
- // Update to latest state
- dwSpinCount = 0;
- dwCurrentState = (*ppRWLock)->_dwState;
- }
- // Check if events are being cached
- else if((dwKnownState & CACHING_EVENTS) == CACHING_EVENTS)
- {
- if(++dwSpinCount > gdwDefaultSpinCount)
- {
- RWSleep(1);
- dwSpinCount = 0;
- }
- dwCurrentState = (*ppRWLock)->_dwState;
- }
- // Check spin count
- else if(++dwSpinCount <= gdwDefaultSpinCount)
- {
- dwCurrentState = (*ppRWLock)->_dwState;
- }
- else
- {
- // Add to waiting writers
- dwCurrentState = RWInterlockedCompareExchange(&(*ppRWLock)->_dwState,
- (dwKnownState + WAITING_WRITER),
- dwKnownState);
- if(dwCurrentState == dwKnownState)
- {
- CLREvent* hWriterEvent;
- DWORD dwModifyState;
-
- // One more waiting writer
-#ifdef RWLOCK_STATISTICS
- RWInterlockedIncrement(&(*ppRWLock)->_dwWriterContentionCount);
-#endif
- HRESULT hr;
- hWriterEvent = (*ppRWLock)->GetWriterEvent(&hr);
- if(hWriterEvent)
- {
- dwStatus = RWWaitForSingleObject(hWriterEvent, dwDesiredTimeout);
- VALIDATE_LOCK(*ppRWLock);
- }
- else
- {
- LOG((LF_SYNC, LL_WARNING,
- "AcquireWriterLock failed to create writer "
- "event for RWLock 0x%x\n", *ppRWLock));
- dwStatus = WAIT_FAILED;
- }
-
- if(dwStatus == WAIT_OBJECT_0)
- {
- _ASSERTE((*ppRWLock)->_dwState & WRITER_SIGNALED);
- dwModifyState = WRITER - WAITING_WRITER - WRITER_SIGNALED;
- }
- else
- {
- dwModifyState = (DWORD) -WAITING_WRITER;
- if(dwStatus == WAIT_TIMEOUT)
- {
- LOG((LF_SYNC, LL_WARNING,
- "Timed out trying to acquire writer "
- "lock for RWLock 0x%x\n", *ppRWLock));
- hr = HRESULT_FROM_WIN32 (ERROR_TIMEOUT);
- }
- else if(dwStatus == WAIT_IO_COMPLETION)
- {
- LOG((LF_SYNC, LL_WARNING,
- "Thread interrupted while trying to acquire writer lock "
- "for RWLock 0x%x\n", *ppRWLock));
- hr = COR_E_THREADINTERRUPTED;
- }
- else if (dwStatus == WAIT_FAILED)
- {
- if (SUCCEEDED(hr))
- {
- dwStatus = GetLastError();
- if (dwStatus == WAIT_OBJECT_0)
- {
- dwStatus = WAIT_FAILED;
- }
- hr = HRESULT_FROM_WIN32(dwStatus);
- LOG((LF_SYNC, LL_WARNING,
- "WaitForSingleObject on Event 0x%x failed for "
- "RWLock 0x%x with status code 0x%x",
- hWriterEvent, *ppRWLock, dwStatus));
- }
- }
- }
-
- // One less waiting writer and he may have become a writer
- dwKnownState = RWInterlockedExchangeAdd(&(*ppRWLock)->_dwState, dwModifyState);
-
- // Check for last timing out signaled waiting writer
- if(dwStatus == WAIT_OBJECT_0)
- {
- // Common case
- }
- else
- {
- if((dwKnownState & WRITER_SIGNALED) &&
- ((dwKnownState & WAITING_WRITERS_MASK) == WAITING_WRITER))
- {
- HRESULT hr1;
- if(hWriterEvent == NULL)
- hWriterEvent = (*ppRWLock)->GetWriterEvent(&hr1);
- _ASSERTE(hWriterEvent);
- do
- {
- dwKnownState = (*ppRWLock)->_dwState;
- if((dwKnownState & WRITER_SIGNALED) &&
- ((dwKnownState & WAITING_WRITERS_MASK) == 0))
- {
- DWORD dwTemp = hWriterEvent->Wait(10, FALSE);
- if(dwTemp == WAIT_OBJECT_0)
- {
- dwKnownState = RWInterlockedExchangeAdd(&(*ppRWLock)->_dwState, (WRITER - WRITER_SIGNALED));
- _ASSERTE(dwKnownState & WRITER_SIGNALED);
- _ASSERTE((dwKnownState & WRITER) == 0);
-
- // Honor the orginal status
- (*ppRWLock)->_dwWriterID = dwThreadID;
- Thread *pThread = GetThread();
- _ASSERTE (pThread);
- _ASSERTE ((*ppRWLock)->_wWriterLevel == 0);
- pThread->m_dwLockCount ++;
- USER_LOCK_TAKEN(GetPtrForLockContract(ppRWLock));
- (*ppRWLock)->_wWriterLevel = 1;
- StaticReleaseWriterLock(ppRWLock);
- break;
- }
- // else continue;
- }
- else
- break;
- }while(TRUE);
- }
-
- if(fBreakOnErrors) // fBreakOnErrors == FALSE so will be optimized out.
- {
- _ASSERTE(!"Failed to acquire writer lock");
- DebugBreak();
- }
-
- // Prepare the frame for throwing an exception
- if ((DWORD)HOST_E_DEADLOCK == dwStatus)
- {
- // So that the error message is in the exception.
- RaiseDeadLockException();
- } else if ((DWORD)COR_E_THREADINTERRUPTED == dwStatus) {
- COMPlusThrow(kThreadInterruptedException);
- }
- else
- {
- COMPlusThrowWin32(hr);
- }
- }
-
- // Sanity check
- _ASSERTE(dwStatus == WAIT_OBJECT_0);
- break;
- }
- }
- YieldProcessor(); // indicate to the processor that we are spinning
- } while(TRUE);
- }
-
- // Success
- _ASSERTE((*ppRWLock)->_dwState & WRITER);
- _ASSERTE(((*ppRWLock)->_dwState & READERS_MASK) == 0);
- _ASSERTE((*ppRWLock)->_dwWriterID == 0);
-
- // Save threadid of the writer
- (*ppRWLock)->_dwWriterID = dwThreadID;
- (*ppRWLock)->_wWriterLevel = 1;
- INCTHREADLOCKCOUNT();
- USER_LOCK_TAKEN(GetPtrForLockContract(ppRWLock));
- ++(*ppRWLock)->_dwWriterSeqNum;
-#ifdef RWLOCK_STATISTICS
- ++(*ppRWLock)->_dwWriterEntryCount;
-#endif
- return;
-}
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::StaticReleaseWriterLockPublic public
-//
-// Synopsis: Public access to StaticReleaseWriterLock
-//
-//+-------------------------------------------------------------------
-FCIMPL1(void, CRWLock::StaticReleaseWriterLockPublic, CRWLock *pRWLockUNSAFE)
-{
- FCALL_CONTRACT;
-
- if (pRWLockUNSAFE == NULL)
- {
- FCThrowVoid(kNullReferenceException);
- }
-
- OBJECTREF pRWLock = ObjectToOBJECTREF((Object*)pRWLockUNSAFE);
-
- HELPER_METHOD_FRAME_BEGIN_ATTRIB_1(Frame::FRAME_ATTR_NO_THREAD_ABORT, pRWLock);
-
- // We don't want to block thread abort when we need to construct exception in
- // unwind-continue handler.
- // note that we cannot use this holder in FCALLs outside our HMF since it breaks the epilog walker on x86!
- ThreadPreventAbortHolder preventAbortIn;
-
- StaticReleaseWriterLock((CRWLock**)&pRWLock);
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::StaticReleaseWriterLock private
-//
-// Synopsis: Removes the thread as a writer if not a nested
-// call to release the lock
-//
-//+-------------------------------------------------------------------
-void CRWLock::StaticReleaseWriterLock(
- CRWLock **ppRWLock)
-{
-
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- PRECONDITION((CheckPointer(ppRWLock)));
- PRECONDITION((CheckPointer(*ppRWLock)));
- }
- CONTRACTL_END;
-
- DWORD dwThreadID = GetThread()->GetThreadId();
-
- // Check validity of caller
- if((*ppRWLock)->_dwWriterID == dwThreadID)
- {
- DECTHREADLOCKCOUNT();
- USER_LOCK_RELEASED(GetPtrForLockContract(ppRWLock));
- // Check for nested release
- if(--(*ppRWLock)->_wWriterLevel == 0)
- {
- DWORD dwCurrentState, dwKnownState, dwModifyState;
- BOOL fCacheEvents;
- CLREvent* hReaderEvent = NULL, *hWriterEvent = NULL;
-
- // Not a writer any more
- (*ppRWLock)->_dwWriterID = 0;
- dwCurrentState = (*ppRWLock)->_dwState;
- do
- {
- dwKnownState = dwCurrentState;
- dwModifyState = (DWORD) -WRITER;
- fCacheEvents = FALSE;
- if(dwKnownState & WAITING_READERS_MASK)
- {
- HRESULT hr;
- hReaderEvent = (*ppRWLock)->GetReaderEvent(&hr);
- if(hReaderEvent == NULL)
- {
- LOG((LF_SYNC, LL_WARNING,
- "ReleaseWriterLock failed to create "
- "reader event for RWLock 0x%x\n", *ppRWLock));
- RWSleep(100);
- dwCurrentState = (*ppRWLock)->_dwState;
- dwKnownState = 0;
- _ASSERTE(dwCurrentState != dwKnownState);
- continue;
- }
- dwModifyState += READER_SIGNALED;
- }
- else if(dwKnownState & WAITING_WRITERS_MASK)
- {
- HRESULT hr;
- hWriterEvent = (*ppRWLock)->GetWriterEvent(&hr);
- if(hWriterEvent == NULL)
- {
- LOG((LF_SYNC, LL_WARNING,
- "ReleaseWriterLock failed to create "
- "writer event for RWLock 0x%x\n", *ppRWLock));
- RWSleep(100);
- dwCurrentState = (*ppRWLock)->_dwState;
- dwKnownState = 0;
- _ASSERTE(dwCurrentState != dwKnownState);
- continue;
- }
- dwModifyState += WRITER_SIGNALED;
- }
- else if(((*ppRWLock)->_hReaderEvent || (*ppRWLock)->_hWriterEvent) &&
- (dwKnownState == WRITER))
- {
- fCacheEvents = TRUE;
- dwModifyState += CACHING_EVENTS;
- }
-
- // Sanity checks
- _ASSERTE((dwKnownState & READERS_MASK) == 0);
-
- dwCurrentState = RWInterlockedCompareExchange(&(*ppRWLock)->_dwState,
- (dwKnownState + dwModifyState),
- dwKnownState);
- } while(dwCurrentState != dwKnownState);
-
- // Check for waiting readers
- if(dwKnownState & WAITING_READERS_MASK)
- {
- _ASSERTE((*ppRWLock)->_dwState & READER_SIGNALED);
- _ASSERTE(hReaderEvent);
- RWSetEvent(hReaderEvent);
- }
- // Check for waiting writers
- else if(dwKnownState & WAITING_WRITERS_MASK)
- {
- _ASSERTE((*ppRWLock)->_dwState & WRITER_SIGNALED);
- _ASSERTE(hWriterEvent);
- RWSetEvent(hWriterEvent);
- }
- // Check for the need to release events
- else if(fCacheEvents)
- {
- (*ppRWLock)->ReleaseEvents();
- }
-
- Thread *pThread = GetThread();
- TESTHOOKCALL(AppDomainCanBeUnloaded(pThread->GetDomain()->GetId().m_dwId,FALSE));
- if (pThread->IsAbortRequested()) {
- pThread->HandleThreadAbort();
- }
-
- }
- }
- else
- {
- if(fBreakOnErrors) // fBreakOnErrors == FALSE so will be optimized out.
- {
- _ASSERTE(!"Attempt to release writer lock on a wrong thread");
- DebugBreak();
- }
- COMPlusThrowWin32(ERROR_NOT_OWNER);
- }
-
- return;
-}
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::StaticReleaseReaderLockPublic public
-//
-// Synopsis: Public access to StaticReleaseReaderLock
-//
-//+-------------------------------------------------------------------
-FCIMPL1(void, CRWLock::StaticReleaseReaderLockPublic, CRWLock *pRWLockUNSAFE)
-{
- FCALL_CONTRACT;
-
- if (pRWLockUNSAFE == NULL)
- {
- FCThrowVoid(kNullReferenceException);
- }
-
- OBJECTREF pRWLock = ObjectToOBJECTREF((Object*)pRWLockUNSAFE);
-
- HELPER_METHOD_FRAME_BEGIN_ATTRIB_1(Frame::FRAME_ATTR_NO_THREAD_ABORT, pRWLock);
-
- // note that we cannot use this holder in FCALLs outside our HMF since it breaks the epilog walker on x86!
- ThreadPreventAbortHolder preventAbortIn;
-
- StaticReleaseReaderLock((CRWLock**)&pRWLock);
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::StaticReleaseReaderLock private
-//
-// Synopsis: Removes the thread as a reader
-//
-//+-------------------------------------------------------------------
-
-void CRWLock::StaticReleaseReaderLock(
- CRWLock **ppRWLock)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- PRECONDITION((CheckPointer(ppRWLock)));
- PRECONDITION((CheckPointer(*ppRWLock)));
- }
- CONTRACTL_END;
-
- // Check if the thread has writer lock
- if((*ppRWLock)->_dwWriterID == GetThread()->GetThreadId())
- {
- StaticReleaseWriterLock(ppRWLock);
- }
- else
- {
- LockEntry *pLockEntry = (*ppRWLock)->GetLockEntry();
- if(pLockEntry)
- {
- --pLockEntry->wReaderLevel;
- DECTHREADLOCKCOUNT();
- USER_LOCK_RELEASED(GetPtrForLockContract(ppRWLock));
- if(pLockEntry->wReaderLevel == 0)
- {
- DWORD dwCurrentState, dwKnownState, dwModifyState;
- BOOL fLastReader, fCacheEvents = FALSE;
- CLREvent* hReaderEvent = NULL, *hWriterEvent = NULL;
-
- // Sanity checks
- _ASSERTE(((*ppRWLock)->_dwState & WRITER) == 0);
- _ASSERTE((*ppRWLock)->_dwState & READERS_MASK);
-
- // Not a reader any more
- dwCurrentState = (*ppRWLock)->_dwState;
- do
- {
- dwKnownState = dwCurrentState;
- dwModifyState = (DWORD) -READER;
- if((dwKnownState & (READERS_MASK | READER_SIGNALED)) == READER)
- {
- fLastReader = TRUE;
- fCacheEvents = FALSE;
- if(dwKnownState & WAITING_WRITERS_MASK)
- {
- HRESULT hr;
- hWriterEvent = (*ppRWLock)->GetWriterEvent(&hr);
- if(hWriterEvent == NULL)
- {
- LOG((LF_SYNC, LL_WARNING,
- "ReleaseReaderLock failed to create "
- "writer event for RWLock 0x%x\n", *ppRWLock));
- RWSleep(100);
- dwCurrentState = (*ppRWLock)->_dwState;
- dwKnownState = 0;
- _ASSERTE(dwCurrentState != dwKnownState);
- continue;
- }
- dwModifyState += WRITER_SIGNALED;
- }
- else if(dwKnownState & WAITING_READERS_MASK)
- {
- HRESULT hr;
- hReaderEvent = (*ppRWLock)->GetReaderEvent(&hr);
- if(hReaderEvent == NULL)
- {
- LOG((LF_SYNC, LL_WARNING,
- "ReleaseReaderLock failed to create "
- "reader event\n", *ppRWLock));
- RWSleep(100);
- dwCurrentState = (*ppRWLock)->_dwState;
- dwKnownState = 0;
- _ASSERTE(dwCurrentState != dwKnownState);
- continue;
- }
- dwModifyState += READER_SIGNALED;
- }
- else if(((*ppRWLock)->_hReaderEvent || (*ppRWLock)->_hWriterEvent) &&
- (dwKnownState == READER))
- {
- fCacheEvents = TRUE;
- dwModifyState += CACHING_EVENTS;
- }
- }
- else
- {
- fLastReader = FALSE;
- }
-
- // Sanity checks
- _ASSERTE((dwKnownState & WRITER) == 0);
- _ASSERTE(dwKnownState & READERS_MASK);
-
- dwCurrentState = RWInterlockedCompareExchange(&(*ppRWLock)->_dwState,
- (dwKnownState + dwModifyState),
- dwKnownState);
- } while(dwCurrentState != dwKnownState);
-
- // Check for last reader
- if(fLastReader)
- {
- // Check for waiting writers
- if(dwKnownState & WAITING_WRITERS_MASK)
- {
- _ASSERTE((*ppRWLock)->_dwState & WRITER_SIGNALED);
- _ASSERTE(hWriterEvent);
- RWSetEvent(hWriterEvent);
- }
- // Check for waiting readers
- else if(dwKnownState & WAITING_READERS_MASK)
- {
- _ASSERTE((*ppRWLock)->_dwState & READER_SIGNALED);
- _ASSERTE(hReaderEvent);
- RWSetEvent(hReaderEvent);
- }
- // Check for the need to release events
- else if(fCacheEvents)
- {
- (*ppRWLock)->ReleaseEvents();
- }
- }
-
- // Recycle lock entry
- RecycleLockEntry(pLockEntry);
-
- Thread *pThread = GetThread();
- TESTHOOKCALL(AppDomainCanBeUnloaded(pThread->GetDomain()->GetId().m_dwId,FALSE));
-
- if (pThread->IsAbortRequested()) {
- pThread->HandleThreadAbort();
- }
- }
- }
- else
- {
- if(fBreakOnErrors) // fBreakOnErrors == FALSE so will be optimized out.
- {
- _ASSERTE(!"Attempt to release reader lock on a wrong thread");
- DebugBreak();
- }
- COMPlusThrowWin32(ERROR_NOT_OWNER);
- }
- }
-
- return;
-}
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::StaticDoUpgradeToWriterLockPublic private
-//
-// Synopsis: Public Access to StaticUpgradeToWriterLockPublic
-//
-//
-//+-------------------------------------------------------------------
-FCIMPL3(void, CRWLock::StaticDoUpgradeToWriterLockPublic, CRWLock *pRWLockUNSAFE, LockCookie * pLockCookie, DWORD dwDesiredTimeout)
-{
- FCALL_CONTRACT;
-
- if (pRWLockUNSAFE == NULL)
- {
- FCThrowVoid(kNullReferenceException);
- }
-
- OBJECTREF pRWLock = ObjectToOBJECTREF((Object*)pRWLockUNSAFE);
- HELPER_METHOD_FRAME_BEGIN_1(pRWLock);
- GCPROTECT_BEGININTERIOR (pLockCookie)
-
- StaticUpgradeToWriterLock((CRWLock**)&pRWLock, pLockCookie, dwDesiredTimeout);
-
- GCPROTECT_END ();
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::StaticUpgradeToWriterLock Private
-//
-// Synopsis: Upgrades to a writer lock. It returns a BOOL that
-// indicates intervening writes.
-//
-
-//
-//+-------------------------------------------------------------------
-
-void CRWLock::StaticUpgradeToWriterLock(
- CRWLock **ppRWLock,
- LockCookie *pLockCookie,
- DWORD dwDesiredTimeout)
-
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- CAN_TAKE_LOCK;
- }
- CONTRACTL_END;
-
- DWORD dwThreadID = GetThread()->GetThreadId();
-
- // Check if the thread is already a writer
- if((*ppRWLock)->_dwWriterID == dwThreadID)
- {
- // Update cookie state
- pLockCookie->dwFlags = UPGRADE_COOKIE | COOKIE_WRITER;
- pLockCookie->wWriterLevel = (*ppRWLock)->_wWriterLevel;
-
- // Acquire the writer lock again
- StaticAcquireWriterLock(ppRWLock, dwDesiredTimeout);
- }
- else
- {
- BOOL fAcquireWriterLock;
- LockEntry *pLockEntry = (*ppRWLock)->GetLockEntry();
- if(pLockEntry == NULL)
- {
- fAcquireWriterLock = TRUE;
- pLockCookie->dwFlags = UPGRADE_COOKIE | COOKIE_NONE;
- }
- else
- {
- // Sanity check
- _ASSERTE((*ppRWLock)->_dwState & READERS_MASK);
- _ASSERTE(pLockEntry->wReaderLevel);
-
- // Save lock state in the cookie
- pLockCookie->dwFlags = UPGRADE_COOKIE | COOKIE_READER;
- pLockCookie->wReaderLevel = pLockEntry->wReaderLevel;
- pLockCookie->dwWriterSeqNum = (*ppRWLock)->_dwWriterSeqNum;
-
- // If there is only one reader, try to convert reader to a writer
- DWORD dwKnownState = RWInterlockedCompareExchange(&(*ppRWLock)->_dwState,
- WRITER,
- READER);
- if(dwKnownState == READER)
- {
- // Thread is no longer a reader
- Thread* pThread = GetThread();
- _ASSERTE (pThread);
- _ASSERTE (pThread->m_dwLockCount >= pLockEntry->wReaderLevel);
- ASSERT_UNLESS_NO_DEBUG_STATE(__pClrDebugState->GetLockCount(kDbgStateLockType_User) >= pLockEntry->wReaderLevel);
- pThread->m_dwLockCount -= pLockEntry->wReaderLevel;
- USER_LOCK_RELEASED_MULTIPLE(pLockEntry->wReaderLevel, GetPtrForLockContract(ppRWLock));
- pLockEntry->wReaderLevel = 0;
- RecycleLockEntry(pLockEntry);
-
- // Thread is a writer
- (*ppRWLock)->_dwWriterID = dwThreadID;
- (*ppRWLock)->_wWriterLevel = 1;
- INCTHREADLOCKCOUNT();
- USER_LOCK_TAKEN(GetPtrForLockContract(ppRWLock));
- ++(*ppRWLock)->_dwWriterSeqNum;
- fAcquireWriterLock = FALSE;
-
- // No intevening writes
-#if RWLOCK_STATISTICS
- ++(*ppRWLock)->_dwWriterEntryCount;
-#endif
- }
- else
- {
- // Release the reader lock
- Thread *pThread = GetThread();
- _ASSERTE (pThread);
- _ASSERTE (pThread->m_dwLockCount >= (DWORD)(pLockEntry->wReaderLevel - 1));
- ASSERT_UNLESS_NO_DEBUG_STATE(__pClrDebugState->GetLockCount(kDbgStateLockType_User) >=
- (DWORD)(pLockEntry->wReaderLevel - 1));
- pThread->m_dwLockCount -= (pLockEntry->wReaderLevel - 1);
- USER_LOCK_RELEASED_MULTIPLE(pLockEntry->wReaderLevel - 1, GetPtrForLockContract(ppRWLock));
- pLockEntry->wReaderLevel = 1;
- StaticReleaseReaderLock(ppRWLock);
- fAcquireWriterLock = TRUE;
- }
- }
-
- // Check for the need to acquire the writer lock
- if(fAcquireWriterLock)
- {
-
- // Declare and Setup the frame as we are aware of the contention
- // on the lock and the thread will most probably block
- // to acquire writer lock
-
- EX_TRY
- {
- StaticAcquireWriterLock(ppRWLock, dwDesiredTimeout);
- }
- EX_CATCH
- {
- // Invalidate cookie
- DWORD dwFlags = pLockCookie->dwFlags;
- pLockCookie->dwFlags = INVALID_COOKIE;
-
- StaticRecoverLock(ppRWLock, pLockCookie, dwFlags & COOKIE_READER);
-
- EX_RETHROW;
- }
- EX_END_CATCH_UNREACHABLE
- }
- }
-
-
- // Update the validation fields of the cookie
- pLockCookie->dwThreadID = dwThreadID;
-
- return;
-}
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::StaticDowngradeFromWriterLock public
-//
-// Synopsis: Downgrades from a writer lock.
-//
-//+-------------------------------------------------------------------
-
-inline CRWLock* GetLock(OBJECTREF orLock)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- return (CRWLock*)OBJECTREFToObject(orLock);
-}
-
-FCIMPL2(void, CRWLock::StaticDowngradeFromWriterLock, CRWLock *pRWLockUNSAFE, LockCookie* pLockCookie)
-{
- FCALL_CONTRACT;
- STATIC_CONTRACT_CAN_TAKE_LOCK;
-
- DWORD dwThreadID = GetThread()->GetThreadId();
-
- if (pRWLockUNSAFE == NULL)
- {
- FCThrowVoid(kNullReferenceException);
- }
-
- if( NULL == pLockCookie) {
- FCThrowVoid(kNullReferenceException);
- }
-
- OBJECTREF pRWLock = ObjectToOBJECTREF((Object*)pRWLockUNSAFE);
- HELPER_METHOD_FRAME_BEGIN_1(pRWLock);
-
- if (GetLock(pRWLock)->_dwWriterID != dwThreadID)
- {
- COMPlusThrowWin32(ERROR_NOT_OWNER);
- }
-
- // Validate cookie
- DWORD dwStatus;
- if(((pLockCookie->dwFlags & INVALID_COOKIE) == 0) &&
- (pLockCookie->dwThreadID == dwThreadID))
- {
- DWORD dwFlags = pLockCookie->dwFlags;
- pLockCookie->dwFlags = INVALID_COOKIE;
-
- // Check if the thread was a reader
- if(dwFlags & COOKIE_READER)
- {
- // Sanity checks
- _ASSERTE(GetLock(pRWLock)->_wWriterLevel == 1);
-
- LockEntry *pLockEntry = GetLock(pRWLock)->FastGetOrCreateLockEntry();
- if(pLockEntry)
- {
- DWORD dwCurrentState, dwKnownState, dwModifyState;
- CLREvent* hReaderEvent = NULL;
-
- // Downgrade to a reader
- GetLock(pRWLock)->_dwWriterID = 0;
- GetLock(pRWLock)->_wWriterLevel = 0;
- DECTHREADLOCKCOUNT ();
- USER_LOCK_RELEASED(GetPtrForLockContract((CRWLock**)&pRWLock));
- dwCurrentState = GetLock(pRWLock)->_dwState;
- do
- {
- dwKnownState = dwCurrentState;
- dwModifyState = READER - WRITER;
- if(dwKnownState & WAITING_READERS_MASK)
- {
- HRESULT hr;
- hReaderEvent = GetLock(pRWLock)->GetReaderEvent(&hr);
- if(hReaderEvent == NULL)
- {
- LOG((LF_SYNC, LL_WARNING,
- "DowngradeFromWriterLock failed to create "
- "reader event for RWLock 0x%x\n", GetLock(pRWLock)));
- RWSleep(100);
- dwCurrentState = GetLock(pRWLock)->_dwState;
- dwKnownState = 0;
- _ASSERTE(dwCurrentState != dwKnownState);
- continue;
- }
- dwModifyState += READER_SIGNALED;
- }
-
- // Sanity checks
- _ASSERTE((dwKnownState & READERS_MASK) == 0);
-
- dwCurrentState = RWInterlockedCompareExchange(&GetLock(pRWLock)->_dwState,
- (dwKnownState + dwModifyState),
- dwKnownState);
- } while(dwCurrentState != dwKnownState);
-
- // Check for waiting readers
- if(dwKnownState & WAITING_READERS_MASK)
- {
- _ASSERTE(GetLock(pRWLock)->_dwState & READER_SIGNALED);
- _ASSERTE(hReaderEvent);
- RWSetEvent(hReaderEvent);
- }
-
- // Restore reader nesting level
- Thread *pThread = GetThread();
- _ASSERTE (pThread);
- _ASSERTE (pThread->m_dwLockCount >= pLockEntry->wReaderLevel);
- ASSERT_UNLESS_NO_DEBUG_STATE(__pClrDebugState->GetLockCount(kDbgStateLockType_User) >=
- pLockEntry->wReaderLevel);
- pThread->m_dwLockCount -= pLockEntry->wReaderLevel;
- USER_LOCK_RELEASED_MULTIPLE(pLockEntry->wReaderLevel, GetPtrForLockContract((CRWLock**)&pRWLock));
- pLockEntry->wReaderLevel = pLockCookie->wReaderLevel;
- pThread->m_dwLockCount += pLockEntry->wReaderLevel;
- USER_LOCK_TAKEN_MULTIPLE(pLockEntry->wReaderLevel, GetPtrForLockContract((CRWLock**)&pRWLock));
- #ifdef RWLOCK_STATISTICS
- RWInterlockedIncrement(&GetLock(pRWLock)->_dwReaderEntryCount);
- #endif
- }
- else
- {
- // Removed assert, as thread abort can occur normally
- dwStatus = RWLOCK_RECOVERY_FAILURE;
- goto ThrowException;
- }
- }
- else if(dwFlags & (COOKIE_WRITER | COOKIE_NONE))
- {
- // Release the writer lock
- StaticReleaseWriterLock((CRWLock**)&pRWLock);
- _ASSERTE((GetLock(pRWLock)->_dwWriterID != GetThread()->GetThreadId()) ||
- (dwFlags & COOKIE_WRITER));
- }
- }
- else
- {
- dwStatus = E_INVALIDARG;
-ThrowException:
- COMPlusThrowWin32(dwStatus);
- }
-
- HELPER_METHOD_FRAME_END();
-
- // Update the validation fields of the cookie
- pLockCookie->dwThreadID = dwThreadID;
-
-}
-FCIMPLEND
-
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::StaticDoReleaseLock private
-//
-// Synopsis: Releases the lock held by the current thread
-//
-//+-------------------------------------------------------------------
-
-FCIMPL2(void, CRWLock::StaticDoReleaseLock, CRWLock *pRWLockUNSAFE, LockCookie * pLockCookie)
-{
- FCALL_CONTRACT;
-
- if (pRWLockUNSAFE == NULL)
- {
- FCThrowVoid(kNullReferenceException);
- }
-
- DWORD dwThreadID = GetThread()->GetThreadId();
-
- OBJECTREF pRWLock = ObjectToOBJECTREF((Object*)pRWLockUNSAFE);
-
- HELPER_METHOD_FRAME_BEGIN_ATTRIB_1(Frame::FRAME_ATTR_NO_THREAD_ABORT, pRWLock);
-
- // note that we cannot use this holder in FCALLs outside our HMF since it breaks the epilog walker on x86!
- ThreadPreventAbortHolder preventAbortIn;
-
- GCPROTECT_BEGININTERIOR (pLockCookie)
-
- // Check if the thread is a writer
- if(GetLock(pRWLock)->_dwWriterID == dwThreadID)
- {
- // Save lock state in the cookie
- pLockCookie->dwFlags = RELEASE_COOKIE | COOKIE_WRITER;
- pLockCookie->dwWriterSeqNum = GetLock(pRWLock)->_dwWriterSeqNum;
- pLockCookie->wWriterLevel = GetLock(pRWLock)->_wWriterLevel;
-
- // Release the writer lock
- Thread *pThread = GetThread();
- _ASSERTE (pThread);
- _ASSERTE (pThread->m_dwLockCount >= (DWORD)(GetLock(pRWLock)->_wWriterLevel - 1));
- ASSERT_UNLESS_NO_DEBUG_STATE(__pClrDebugState->GetLockCount(kDbgStateLockType_User) >=
- (DWORD)(GetLock(pRWLock)->_wWriterLevel - 1));
- pThread->m_dwLockCount -= (GetLock(pRWLock)->_wWriterLevel - 1);
- USER_LOCK_RELEASED_MULTIPLE(GetLock(pRWLock)->_wWriterLevel - 1, GetPtrForLockContract((CRWLock**)&pRWLock));
- GetLock(pRWLock)->_wWriterLevel = 1;
- StaticReleaseWriterLock((CRWLock**)&pRWLock);
- }
- else
- {
- LockEntry *pLockEntry = GetLock(pRWLock)->GetLockEntry();
- if(pLockEntry)
- {
- // Sanity check
- _ASSERTE(GetLock(pRWLock)->_dwState & READERS_MASK);
- _ASSERTE(pLockEntry->wReaderLevel);
-
- // Save lock state in the cookie
- pLockCookie->dwFlags = RELEASE_COOKIE | COOKIE_READER;
- pLockCookie->wReaderLevel = pLockEntry->wReaderLevel;
- pLockCookie->dwWriterSeqNum = GetLock(pRWLock)->_dwWriterSeqNum;
-
- // Release the reader lock
- Thread *pThread = GetThread();
- _ASSERTE (pThread);
- _ASSERTE (pThread->m_dwLockCount >= (DWORD)(pLockEntry->wReaderLevel - 1));
- ASSERT_UNLESS_NO_DEBUG_STATE(__pClrDebugState->GetLockCount(kDbgStateLockType_User) >=
- (DWORD)(pLockEntry->wReaderLevel - 1));
- pThread->m_dwLockCount -= (pLockEntry->wReaderLevel - 1);
- USER_LOCK_RELEASED_MULTIPLE(pLockEntry->wReaderLevel - 1, GetPtrForLockContract((CRWLock**)&pRWLock));
- pLockEntry->wReaderLevel = 1;
- StaticReleaseReaderLock((CRWLock**)&pRWLock);
- }
- else
- {
- pLockCookie->dwFlags = RELEASE_COOKIE | COOKIE_NONE;
- }
- }
-
- GCPROTECT_END ();
-
- HELPER_METHOD_FRAME_END();
-
- // Update the validation fields of the cookie
- pLockCookie->dwThreadID = dwThreadID;
-}
-FCIMPLEND
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::StaticRestoreLockPublic public
-//
-// Synopsis: Public Access to StaticRestoreLock
-//
-//
-//+-------------------------------------------------------------------
-
-FCIMPL2(void, CRWLock::StaticRestoreLockPublic, CRWLock *pRWLockUNSAFE, LockCookie* pLockCookie)
-{
- FCALL_CONTRACT;
-
- if (pRWLockUNSAFE == NULL) {
- FCThrowVoid(kNullReferenceException);
- }
-
- if( NULL == pLockCookie) {
- FCThrowVoid(kNullReferenceException);
- }
-
- OBJECTREF pRWLock = ObjectToOBJECTREF((Object*)pRWLockUNSAFE);
- HELPER_METHOD_FRAME_BEGIN_1(pRWLock);
-
- StaticRestoreLock((CRWLock**)&pRWLock, pLockCookie);
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-//+-------------------------------------------------------------------
-//
-// Method: CRWLock::StaticRestoreLock Private
-//
-// Synopsis: Restore the lock held by the current thread
-//
-
-//
-//+-------------------------------------------------------------------
-
-void CRWLock::StaticRestoreLock(
- CRWLock **ppRWLock,
- LockCookie *pLockCookie)
-{
- CONTRACTL
- {
- THROWS;
- CAN_TAKE_LOCK;
- GC_TRIGGERS; // CRWLock::StaticAquireWriterLock can trigger GC
- }
- CONTRACTL_END;
-
- // Validate cookie
- DWORD dwThreadID = GetThread()->GetThreadId();
- DWORD dwFlags = pLockCookie->dwFlags;
- if(pLockCookie->dwThreadID == dwThreadID)
- {
- if (((*ppRWLock)->_dwWriterID == dwThreadID) || ((*ppRWLock)->GetLockEntry() != NULL))
- {
- COMPlusThrow(kSynchronizationLockException, W("Arg_RWLockRestoreException"));
- }
-
- // Check for the no contention case
- pLockCookie->dwFlags = INVALID_COOKIE;
- if(dwFlags & COOKIE_WRITER)
- {
- if(RWInterlockedCompareExchange(&(*ppRWLock)->_dwState, WRITER, 0) == 0)
- {
- // Restore writer nesting level
- (*ppRWLock)->_dwWriterID = dwThreadID;
- Thread *pThread = GetThread();
- _ASSERTE (pThread);
- _ASSERTE (pThread->m_dwLockCount >= (*ppRWLock)->_wWriterLevel);
- ASSERT_UNLESS_NO_DEBUG_STATE(__pClrDebugState->GetLockCount(kDbgStateLockType_User) >=
- (*ppRWLock)->_wWriterLevel);
- pThread->m_dwLockCount -= (*ppRWLock)->_wWriterLevel;
- USER_LOCK_RELEASED_MULTIPLE((*ppRWLock)->_wWriterLevel, GetPtrForLockContract(ppRWLock));
- (*ppRWLock)->_wWriterLevel = pLockCookie->wWriterLevel;
- pThread->m_dwLockCount += (*ppRWLock)->_wWriterLevel;
- USER_LOCK_TAKEN_MULTIPLE((*ppRWLock)->_wWriterLevel, GetPtrForLockContract(ppRWLock));
- ++(*ppRWLock)->_dwWriterSeqNum;
-#ifdef RWLOCK_STATISTICS
- ++(*ppRWLock)->_dwWriterEntryCount;
-#endif
- goto LNormalReturn;
- }
- }
- else if(dwFlags & COOKIE_READER)
- {
- LockEntry *pLockEntry = (*ppRWLock)->FastGetOrCreateLockEntry();
- if(pLockEntry)
- {
- // This thread should not already be a reader
- // else bad things can happen
- _ASSERTE(pLockEntry->wReaderLevel == 0);
- DWORD dwKnownState = (*ppRWLock)->_dwState;
- if(dwKnownState < READERS_MASK)
- {
- DWORD dwCurrentState = RWInterlockedCompareExchange(&(*ppRWLock)->_dwState,
- (dwKnownState + READER),
- dwKnownState);
- if(dwCurrentState == dwKnownState)
- {
- // Restore reader nesting level
- Thread *pThread = GetThread();
- _ASSERTE (pThread);
- pLockEntry->wReaderLevel = pLockCookie->wReaderLevel;
- pThread->m_dwLockCount += pLockEntry->wReaderLevel;
- USER_LOCK_TAKEN_MULTIPLE(pLockEntry->wReaderLevel, GetPtrForLockContract(ppRWLock));
-#ifdef RWLOCK_STATISTICS
- RWInterlockedIncrement(&(*ppRWLock)->_dwReaderEntryCount);
-#endif
- goto LNormalReturn;
- }
- }
-
- // Recycle the lock entry for the slow case
- (*ppRWLock)->FastRecycleLockEntry(pLockEntry);
- }
- else
- {
- // Ignore the error and try again below. May be thread will luck
- // out the second time
- }
- }
- else if(dwFlags & COOKIE_NONE)
- {
- goto LNormalReturn;
- }
-
- // Declare and Setup the frame as we are aware of the contention
- // on the lock and the thread will most probably block
- // to acquire lock below
-ThrowException:
- if((dwFlags & INVALID_COOKIE) == 0)
- {
- StaticRecoverLock(ppRWLock, pLockCookie, dwFlags);
- }
- else
- {
- COMPlusThrowWin32(E_INVALIDARG);
- }
-
- goto LNormalReturn;
- }
- else
- {
- dwFlags = INVALID_COOKIE;
- goto ThrowException;
- }
-
-LNormalReturn:
- return;
-}
-
-
-//+-------------------------------------------------------------------
-//
-// Class: CRWLock::StaticPrivateInitialize
-//
-// Synopsis: Initialize lock
-//
-//+-------------------------------------------------------------------
-FCIMPL1(void, CRWLock::StaticPrivateInitialize, CRWLock *pRWLock)
-{
- FCALL_CONTRACT;
-
- HELPER_METHOD_FRAME_BEGIN_1(pRWLock);
-
- // Run the constructor on the GC allocated space
- // CRWLock's constructor can throw exception
-#ifndef _PREFAST_
- // Prefast falsely complains of memory leak.
- CRWLock *pTemp;
- pTemp = new (pRWLock) CRWLock();
- _ASSERTE(pTemp == pRWLock);
-#endif
-
- // Catch GC holes
- VALIDATE_LOCK(pRWLock);
-
- HELPER_METHOD_FRAME_END();
- return;
-}
-FCIMPLEND
-
-
-//+-------------------------------------------------------------------
-//
-// Class: CRWLock::StaticPrivateDestruct
-//
-// Synopsis: Destruct lock
-//+-------------------------------------------------------------------
-FCIMPL1(void, CRWLock::StaticPrivateDestruct, CRWLock *pRWLock)
-{
- FCALL_CONTRACT;
-
- HELPER_METHOD_FRAME_BEGIN_ATTRIB_1(Frame::FRAME_ATTR_NO_THREAD_ABORT, pRWLock);
-
- // Fixing one handle recycling security hole by
- // ensuring we don't delete the events more than once.
- // After deletion (for now, assuming ONE FINALIZER THREAD)
- // make the object essentially unusable by setting handle to
- // INVALID_HANDLE_VALUE (unusable) versus NULL (uninitialized)
-
- if ((pRWLock->_hWriterEvent != INVALID_HANDLE_VALUE) && (pRWLock->_hReaderEvent != INVALID_HANDLE_VALUE))
- {
- // Note, this still allows concurrent event consumers (such as StaticAcquireReaderLock)
- // to Set and/or Wait on non-events. There still exists a security hole here.
- if(pRWLock->_hWriterEvent)
- {
- CLREvent *h = (CLREvent *) FastInterlockExchangePointer((PVOID *)&(pRWLock->_hWriterEvent), INVALID_HANDLE_VALUE);
- delete h;
- }
- if(pRWLock->_hReaderEvent)
- {
- CLREvent *h = (CLREvent *) FastInterlockExchangePointer((PVOID *)&(pRWLock->_hReaderEvent), INVALID_HANDLE_VALUE);
- delete h;
- }
-
- // There is no LockEntry for this lock.
- if (pRWLock->_dwState != 0)
- {
- // Recycle LockEntry on threads
- ThreadStoreLockHolder tsl;
-
- // Take ThreadStore lock and walk over every thread in the process
- Thread *thread = NULL;
- while ((thread = ThreadStore::s_pThreadStore->GetAllThreadList(thread,
- Thread::TS_Unstarted|Thread::TS_Dead|Thread::TS_Detached, 0))
- != NULL)
- {
- LockEntry *pLockEntry;
- {
- CrstHolder rwl(&s_RWLockCrst);
- pLockEntry = pRWLock->GetLockEntry(thread);
- }
- if (pLockEntry)
- {
- // The entry does not belong to this lock anymore
- pLockEntry->dwLLockID = 0;
- pLockEntry->wReaderLevel = 0;
- }
- }
- }
- }
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-
-//+-------------------------------------------------------------------
-//
-// Class: CRWLock::StaticGetWriterSeqNum
-//
-// Synopsis: Returns the current sequence number
-//
-//+-------------------------------------------------------------------
-FCIMPL1(INT32, CRWLock::StaticGetWriterSeqNum, CRWLock *pRWLock)
-{
- FCALL_CONTRACT;
-
- if (pRWLock == NULL)
- {
- FCThrow(kNullReferenceException);
- }
-
- return(pRWLock->_dwWriterSeqNum);
-}
-FCIMPLEND
-
-
-//+-------------------------------------------------------------------
-//
-// Class: CRWLock::StaticAnyWritersSince
-//
-// Synopsis: Returns TRUE if there were writers since the given
-// sequence number
-//
-//+-------------------------------------------------------------------
-FCIMPL2(FC_BOOL_RET, CRWLock::StaticAnyWritersSince, CRWLock *pRWLock, DWORD dwSeqNum)
-{
- FCALL_CONTRACT;
-
- if (pRWLock == NULL)
- {
- FCThrow(kNullReferenceException);
- }
-
-
- if(pRWLock->_dwWriterID == GetThread()->GetThreadId())
- ++dwSeqNum;
-
- FC_RETURN_BOOL(pRWLock->_dwWriterSeqNum > dwSeqNum);
-}
-FCIMPLEND
-
-struct RWLockIterator
-{
- IHostTask **m_Owner;
- DWORD m_Capacity;
- DWORD m_index;
-};
-
-OBJECTHANDLE CRWLock::GetObjectHandle()
-{
- CONTRACTL
- {
- THROWS;
- MODE_COOPERATIVE;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- if (_hObjectHandle == NULL)
- {
- OBJECTREF obj = ObjectToOBJECTREF((Object*)this);
- OBJECTHANDLE handle = GetAppDomain()->CreateLongWeakHandle(obj);
- if (RWInterlockedCompareExchangePointer((PVOID*)&_hObjectHandle, handle, NULL) != NULL)
- {
- DestroyLongWeakHandle(handle);
- }
- }
- return _hObjectHandle;
-}
-
-// CRWLock::CreateOwnerIterator can return E_OUTOFMEMORY
-//
-HRESULT CRWLock::CreateOwnerIterator(SIZE_T *pIterator)
-{
- CONTRACTL
- {
- NOTHROW;
- MODE_PREEMPTIVE;
- GC_NOTRIGGER;
- SO_INTOLERANT;
- }
- CONTRACTL_END;
-
- *pIterator = 0;
- if (_dwState == 0) {
- return S_OK;
- }
- NewHolder<RWLockIterator> IteratorHolder(new (nothrow) RWLockIterator);
- RWLockIterator *pRWLockIterator = IteratorHolder;
- if (pRWLockIterator == NULL) {
- return E_OUTOFMEMORY;
- }
- // Writer can be handled fast
- if (_dwState & WRITER) {
- DWORD writerID = _dwWriterID;
- if (writerID != 0)
- {
- pRWLockIterator->m_Capacity = 1;
- pRWLockIterator->m_index = 0;
- pRWLockIterator->m_Owner = new (nothrow) IHostTask*[1];
- if (pRWLockIterator->m_Owner == NULL) {
- return E_OUTOFMEMORY;
- }
- Thread *pThread = g_pThinLockThreadIdDispenser->IdToThreadWithValidation(writerID);
- if (pThread == NULL)
- {
- return S_OK;
- }
- IteratorHolder.SuppressRelease();
- pRWLockIterator->m_Owner[0] = pThread->GetHostTaskWithAddRef();
- *pIterator = (SIZE_T)pRWLockIterator;
- return S_OK;
- }
- }
- if (_dwState == 0) {
- return S_OK;
- }
- pRWLockIterator->m_Capacity = 4;
- pRWLockIterator->m_index = 0;
- pRWLockIterator->m_Owner = new (nothrow) IHostTask*[pRWLockIterator->m_Capacity];
- if (pRWLockIterator->m_Owner == NULL) {
- return E_OUTOFMEMORY;
- }
-
- HRESULT hr = S_OK;
-
- NewArrayHolder<IHostTask*> OwnerHolder(pRWLockIterator->m_Owner);
-
- // Take ThreadStore lock and walk over every thread in the process
- Thread *thread = NULL;
- while ((thread = ThreadStore::s_pThreadStore->GetAllThreadList(thread,
- Thread::TS_Unstarted|Thread::TS_Dead|Thread::TS_Detached, 0))
- != NULL)
- {
- LockEntry *pLockEntry;
- {
- CrstHolder rwl(&s_RWLockCrst);
- pLockEntry = GetLockEntry(thread);
- }
- if (pLockEntry && pLockEntry->wReaderLevel >= 1) {
- if (pRWLockIterator->m_index == pRWLockIterator->m_Capacity) {
- IHostTask** newArray = new (nothrow) IHostTask*[2*pRWLockIterator->m_Capacity];
- if (newArray == NULL) {
- hr = E_OUTOFMEMORY;
- break;
- }
- memcpy (newArray,pRWLockIterator->m_Owner,pRWLockIterator->m_Capacity*sizeof(IHostTask*));
- pRWLockIterator->m_Owner = newArray;
- pRWLockIterator->m_Capacity *= 2;
- OwnerHolder = pRWLockIterator->m_Owner;
- }
- IHostTask *pHostTask = thread->GetHostTaskWithAddRef();
- if (pHostTask)
- {
- pRWLockIterator->m_Owner[pRWLockIterator->m_index++] = pHostTask;
- }
- }
- }
- if (FAILED(hr))
- {
- for (DWORD i = 0; i < pRWLockIterator->m_index; i ++)
- {
- if (pRWLockIterator->m_Owner[i])
- {
- pRWLockIterator->m_Owner[i]->Release();
- }
- }
- }
- if (SUCCEEDED(hr)) {
- IteratorHolder.SuppressRelease();
- OwnerHolder.SuppressRelease();
- pRWLockIterator->m_Capacity = pRWLockIterator->m_index;
- pRWLockIterator->m_index = 0;
- *pIterator = (SIZE_T)pRWLockIterator;
- }
-
- return hr;
-}
-
-void CRWLock::GetNextOwner(SIZE_T Iterator, IHostTask **ppOwnerHostTask)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- *ppOwnerHostTask = NULL;
- if (Iterator) {
- RWLockIterator* tmp = (RWLockIterator*)Iterator;
- if (tmp->m_index < tmp->m_Capacity) {
- *ppOwnerHostTask = tmp->m_Owner[tmp->m_index];
- tmp->m_index ++;
- }
- }
-}
-
-void CRWLock::DeleteOwnerIterator(SIZE_T Iterator)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
-
- if (Iterator) {
- RWLockIterator* pIterator = (RWLockIterator*)Iterator;
- while (pIterator->m_index < pIterator->m_Capacity) {
- IHostTask *pHostTask = pIterator->m_Owner[pIterator->m_index];
- if (pHostTask)
- {
- pHostTask->Release();
- }
- pIterator->m_index ++;
- }
- delete[] pIterator->m_Owner;
- delete pIterator;
- }
-}
-#endif // FEATURE_RWLOCK
diff --git a/src/vm/rwlock.h b/src/vm/rwlock.h
index dc8e67e6fb..908e007169 100644
--- a/src/vm/rwlock.h
+++ b/src/vm/rwlock.h
@@ -67,220 +67,6 @@ typedef struct {
DWORD dwThreadID;
} LockCookie;
-//+-------------------------------------------------------------------
-//
-// Class: CRWLock
-//
-// Synopsis: Class the implements the reader writer locks.
-//
-//+-------------------------------------------------------------------
-class CRWLock : public Object
-{
- friend class MscorlibBinder;
-
-public:
- // Constuctor
- CRWLock();
-
- // Cleanup
- void Cleanup();
-
- OBJECTHANDLE GetObjectHandle();
- HRESULT CreateOwnerIterator(SIZE_T *pIterator);
- static void GetNextOwner(SIZE_T Iterator, IHostTask **ppOwnerHostTask);
- static void DeleteOwnerIterator(SIZE_T Iterator);
-
- // Statics that do the core work
- static FCDECL1 (void, StaticPrivateInitialize, CRWLock *pRWLock);
- static FCDECL1 (void, StaticPrivateDestruct, CRWLock *pRWLock);
- static FCDECL2 (void, StaticAcquireReaderLockPublic, CRWLock *pRWLock, DWORD dwDesiredTimeout);
- static FCDECL2 (void, StaticAcquireWriterLockPublic, CRWLock *pRWLock, DWORD dwDesiredTimeout);
- static FCDECL1 (void, StaticReleaseReaderLockPublic, CRWLock *pRWLock);
- static FCDECL1 (void, StaticReleaseWriterLockPublic, CRWLock *pRWLock);
- static FCDECL3 (void, StaticDoUpgradeToWriterLockPublic, CRWLock *pRWLock, LockCookie * pLockCookie, DWORD dwDesiredTimeout);
- static FCDECL2 (void, StaticDowngradeFromWriterLock, CRWLock *pRWLock, LockCookie* pLockCookie);
- static FCDECL2 (void, StaticDoReleaseLock, CRWLock *pRWLock, LockCookie * pLockCookie);
- static FCDECL2 (void, StaticRestoreLockPublic, CRWLock *pRWLock, LockCookie* pLockCookie);
- static FCDECL1 (FC_BOOL_RET, StaticIsReaderLockHeld, CRWLock *pRWLock);
- static FCDECL1 (FC_BOOL_RET, StaticIsWriterLockHeld, CRWLock *pRWLock);
- static FCDECL1 (INT32, StaticGetWriterSeqNum, CRWLock *pRWLock);
- static FCDECL2 (FC_BOOL_RET, StaticAnyWritersSince, CRWLock *pRWLock, DWORD dwSeqNum);
-private:
- static void StaticAcquireReaderLock(CRWLock **ppRWLock, DWORD dwDesiredTimeout);
- static void StaticAcquireWriterLock(CRWLock **ppRWLock, DWORD dwDesiredTimeout);
- static void StaticReleaseReaderLock(CRWLock **ppRWLock);
- static void StaticReleaseWriterLock(CRWLock **ppRWLock);
- static void StaticRecoverLock(CRWLock **ppRWLock, LockCookie *pLockCookie, DWORD dwFlags);
- static void StaticRestoreLock(CRWLock **ppRWLock, LockCookie *pLockCookie);
- static void StaticUpgradeToWriterLock(CRWLock **ppRWLock, LockCookie *pLockCookie, DWORD dwDesiredTimeout);
-public:
- // Assert functions
-#ifdef _DEBUG
- BOOL AssertWriterLockHeld();
- BOOL AssertWriterLockNotHeld();
- BOOL AssertReaderLockHeld();
- BOOL AssertReaderLockNotHeld();
- BOOL AssertReaderOrWriterLockHeld();
- void AssertHeld()
- {
- WRAPPER_NO_CONTRACT;
- AssertWriterLockHeld();
- }
- void AssertNotHeld()
- {
- WRAPPER_NO_CONTRACT;
- AssertWriterLockNotHeld();
- AssertReaderLockNotHeld();
- }
-#else
- void AssertWriterLockHeld() { LIMITED_METHOD_CONTRACT; }
- void AssertWriterLockNotHeld() { LIMITED_METHOD_CONTRACT; }
- void AssertReaderLockHeld() { LIMITED_METHOD_CONTRACT; }
- void AssertReaderLockNotHeld() { LIMITED_METHOD_CONTRACT; }
- void AssertReaderOrWriterLockHeld() { LIMITED_METHOD_CONTRACT; }
- void AssertHeld() { LIMITED_METHOD_CONTRACT; }
- void AssertNotHeld() { LIMITED_METHOD_CONTRACT; }
-#endif
-
- // Helper functions
-#ifdef RWLOCK_STATISTICS
- DWORD GetReaderEntryCount()
- {
- LIMITED_METHOD_CONTRACT;
- return(_dwReaderEntryCount);
- }
- DWORD GetReaderContentionCount() { LIMITED_METHOD_CONTRACT; return(_dwReaderContentionCount); }
- DWORD GetWriterEntryCount() { LIMITED_METHOD_CONTRACT; return(_dwWriterEntryCount); }
- DWORD GetWriterContentionCount() { LIMITED_METHOD_CONTRACT; return(_dwWriterContentionCount); }
-#endif
- // Static functions
- static void *operator new(size_t size)
- {
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- return ::operator new(size);
- }
- static void ProcessInit();
-
- static void SetTimeout(DWORD dwTimeout)
- {
- LIMITED_METHOD_CONTRACT;
-
- gdwDefaultTimeout = dwTimeout;
- }
- static DWORD GetTimeout()
- {
- LIMITED_METHOD_CONTRACT;
- return(gdwDefaultTimeout);
- }
- static void SetSpinCount(DWORD dwSpinCount)
- {
- LIMITED_METHOD_CONTRACT;
-
- gdwDefaultSpinCount = g_SystemInfo.dwNumberOfProcessors > 1
- ? dwSpinCount
- : 0;
- }
- static DWORD GetSpinCount() { LIMITED_METHOD_CONTRACT; return(gdwDefaultSpinCount); }
-
-private:
- // Private helpers
- static void ChainEntry(Thread *pThread, LockEntry *pLockEntry);
- LockEntry *GetLockEntry(Thread *pThread = NULL);
- LockEntry *FastGetOrCreateLockEntry();
- LockEntry *SlowGetOrCreateLockEntry(Thread *pThread);
- void FastRecycleLockEntry(LockEntry *pLockEntry);
- static void RecycleLockEntry(LockEntry *pLockEntry);
-
- CLREvent* GetReaderEvent(HRESULT *pHR);
- CLREvent* GetWriterEvent(HRESULT *pHR);
- void ReleaseEvents();
-
- static LONG RWInterlockedCompareExchange(LONG RAW_KEYWORD(volatile) *pvDestination,
- LONG dwExchange,
- LONG dwComperand);
- static LONGLONG RWInterlockedCompareExchange64(LONGLONG RAW_KEYWORD(volatile) *pvDestination,
- LONGLONG qwExchange,
- LONGLONG qwComparand);
- static void* RWInterlockedCompareExchangePointer(PVOID RAW_KEYWORD(volatile) *pvDestination,
- PVOID pExchange,
- PVOID pComparand);
- static LONG RWInterlockedExchangeAdd(LONG RAW_KEYWORD(volatile) *pvDestination, LONG dwAddState);
- static LONG RWInterlockedIncrement(LONG RAW_KEYWORD(volatile) *pdwState);
-
- static DWORD RWWaitForSingleObject(CLREvent* event, DWORD dwTimeout);
- static void RWSetEvent(CLREvent* event);
- static void RWResetEvent(CLREvent* event);
- static void RWSleep(DWORD dwTime);
-
-#if defined(ENABLE_CONTRACTS_IMPL)
- // The LOCK_TAKEN/RELEASED macros need a "pointer" to the lock object to do
- // comparisons between takes & releases (and to provide debugging info to the
- // developer). We can't use "this" (*ppRWLock), because CRWLock is an Object and thus
- // can move. So we use _dwLLockID instead. It's not exactly unique, but it's
- // good enough--worst that can happen is if a thread takes RWLock A and erroneously
- // releases RWLock B (instead of A), we'll fail to catch that if their _dwLLockID's
- // are the same. On 64 bits, we can use both _dwULockID & _dwLLockID and be unique
- static void * GetPtrForLockContract(CRWLock ** ppRWLock)
- {
-#if defined(_WIN64)
- return (void *)
- (
- (
- ((__int64) ((*ppRWLock)->_dwULockID)) << 32
- )
- |
- (
- (__int64) ((*ppRWLock)->_dwLLockID)
- )
- );
-#else //defined(_WIN64)
- return LongToPtr((*ppRWLock)->_dwLLockID);
-#endif //defined(_WIN64)
- }
-#endif //defined(ENABLE_CONTRACTS_IMPL)
-
- // private new
- static void *operator new(size_t size, void *pv) { LIMITED_METHOD_CONTRACT; return(pv); }
-
- // Private data
- CLREvent *_hWriterEvent;
- CLREvent *_hReaderEvent;
- OBJECTHANDLE _hObjectHandle;
- Volatile<LONG> _dwState;
- LONG _dwULockID;
- LONG _dwLLockID;
- DWORD _dwWriterID;
- DWORD _dwWriterSeqNum;
- WORD _wWriterLevel;
-#ifdef RWLOCK_STATISTICS
- // WARNING: You must explicitly #define RWLOCK_STATISTICS when you build
- // in both the VM and BCL directories, as the managed class must also
- // contain these fields!
- Volatile<LONG> _dwReaderEntryCount;
- Volatile<LONG> _dwReaderContentionCount;
- Volatile<LONG> _dwWriterEntryCount;
- Volatile<LONG> _dwWriterContentionCount;
- Volatile<LONG> _dwEventsReleasedCount;
-#endif
-
- // Static data
- static Volatile<LONGLONG> s_mostRecentLockID;
- static CrstStatic s_RWLockCrst;
-};
-
-#ifdef USE_CHECKED_OBJECTREFS
-typedef REF<CRWLock> RWLOCKREF;
-
-#else
-typedef CRWLock* RWLOCKREF;
-#endif
-
#endif // _RWLOCK_H_
#endif // FEATURE_RWLOCK
diff --git a/src/vm/securitymeta.cpp b/src/vm/securitymeta.cpp
index 7027c47c83..7cc8b65426 100644
--- a/src/vm/securitymeta.cpp
+++ b/src/vm/securitymeta.cpp
@@ -29,7 +29,6 @@
#include "threads.h"
#include "eventtrace.h"
#ifdef FEATURE_REMOTING
-#include "appdomainhelper.h"
#include "objectclone.h"
#endif //FEATURE_REMOTING
#include "typestring.h"
diff --git a/src/vm/securitystackwalk.h b/src/vm/securitystackwalk.h
index 3aaf9b5084..f59c958145 100644
--- a/src/vm/securitystackwalk.h
+++ b/src/vm/securitystackwalk.h
@@ -19,7 +19,6 @@
#include "security.h"
#include "holder.h"
#ifdef FEATURE_REMOTING
-#include "appdomainhelper.h"
#endif
class ApplicationSecurityDescriptor;
diff --git a/src/vm/stackbuildersink.cpp b/src/vm/stackbuildersink.cpp
deleted file mode 100644
index 2e363f2802..0000000000
--- a/src/vm/stackbuildersink.cpp
+++ /dev/null
@@ -1,702 +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.
-//
-// File: StackBuilderSink.cpp
-//
-
-//
-// Purpose: Native implementation for System.Runtime.Remoting.Messaging.StackBuilderSink
-//
-
-
-#include "common.h"
-
-#ifdef FEATURE_REMOTING
-
-#include "excep.h"
-#include "message.h"
-#include "stackbuildersink.h"
-#include "dbginterface.h"
-#include "remoting.h"
-#include "profilepriv.h"
-#include "class.h"
-
-struct ArgInfo
-{
- PBYTE dataLocation;
- INT32 dataSize;
- TypeHandle dataTypeHandle;
- BYTE dataType;
- BYTE byref;
-};
-
-
-//+----------------------------------------------------------------------------
-//
-// Method: CStackBuilderSink::PrivateProcessMessage, public
-//
-// Synopsis: Builds the stack and calls an object
-//
-//
-//+----------------------------------------------------------------------------
-FCIMPL5(Object*, CStackBuilderSink::PrivateProcessMessage,
- Object* pSBSinkUNSAFE,
- MethodDesc* pMD,
- PTRArray* pArgsUNSAFE,
- Object* pServerUNSAFE,
- PTRARRAYREF* ppVarOutParams)
-{
- CONTRACTL
- {
- FCALL_CHECK;
- PRECONDITION(CheckPointer(pMD));
- PRECONDITION(!pMD->IsGenericMethodDefinition());
- PRECONDITION(pMD->IsRuntimeMethodHandle());
- }
- CONTRACTL_END;
-
- struct _gc
- {
- PTRARRAYREF pArgs;
- OBJECTREF pServer;
- OBJECTREF pSBSink;
- OBJECTREF ret;
- } gc;
- gc.pArgs = (PTRARRAYREF) pArgsUNSAFE;
- gc.pServer = (OBJECTREF) pServerUNSAFE;
- gc.pSBSink = (OBJECTREF) pSBSinkUNSAFE;
- gc.ret = NULL;
-
- HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
-
- // pMD->IsStatic() is SO_INTOLERANT.
- // Either pServer is non-null or the method is static (but not both)
- _ASSERTE( (pServerUNSAFE!=NULL) == !(pMD->IsStatic()) );
-
- LOG((LF_REMOTING, LL_INFO10, "CStackBuilderSink::PrivateProcessMessage\n"));
-
- MethodDesc *pResolvedMD = pMD;
- // Check if this is an interface invoke, if yes, then we have to find the
- // real method descriptor on the class of the server object.
- if(pMD->GetMethodTable()->IsInterface())
- {
- _ASSERTE(gc.pServer != NULL);
-
- // NOTE: This method can trigger GC
- // The last parameter (true) causes the method to take into account that
- // the object passed in is a TP and try to resolve the interface MD into
- // a server MD anyway (normally the call short circuits thunking objects
- // and just returns the interface MD unchanged).
- MethodTable *pRealMT = gc.pServer->GetTrueMethodTable();
-
-#ifdef FEATURE_COMINTEROP
- if (pRealMT->IsComObjectType())
- pResolvedMD = pRealMT->GetMethodDescForComInterfaceMethod(pMD, true);
- else
-#endif // FEATURE_COMINTEROP
- {
- if (pRealMT->ImplementsInterface(pMD->GetMethodTable()))
- {
- pResolvedMD = pRealMT->GetMethodDescForInterfaceMethod(TypeHandle(pMD->GetMethodTable()), pMD);
-
- // If the method is generic then we have more work to do --
- // we'll get back the generic method descriptor and we'll have
- // to load the version with the right instantiation (get the
- // instantiation from the interface method).
- if (pResolvedMD->HasMethodInstantiation())
- {
- _ASSERTE(pResolvedMD->IsGenericMethodDefinition());
- _ASSERTE(pMD->GetNumGenericMethodArgs() == pResolvedMD->GetNumGenericMethodArgs());
-
- pResolvedMD = MethodDesc::FindOrCreateAssociatedMethodDesc(pResolvedMD,
- pRealMT,
- FALSE,
- pMD->GetMethodInstantiation(),
- FALSE);
-
- _ASSERTE(!pResolvedMD->ContainsGenericVariables());
- }
- }
- else
- pResolvedMD = NULL;
- }
-
- if(!pResolvedMD)
- {
- MAKE_WIDEPTR_FROMUTF8(wName, pMD->GetName());
- COMPlusThrow(kMissingMethodException, IDS_EE_MISSING_METHOD, wName);
- }
- }
-
- // <TODO>This looks a little dodgy for generics: pResolvedMD has been interface-resolved but not
- // virtual-resolved. So we seem to be taking the signature of a
- // half-resolved-virtual-call. But the MetaSig
- // is only used for GC purposes, and thus is probably OK: although the
- // metadata for the signature of a call may be different
- // as we move to base classes, the instantiated version
- // of the signature will still be the same
- // at both the callsite and the target). </TODO>
- MetaSig mSig(pResolvedMD);
-
- // get the target depending on whether the method is virtual or non-virtual
- // like a constructor, private or final method
- PCODE pTarget = pResolvedMD->GetCallTarget(&(gc.pServer));
-
- VASigCookie *pCookie = NULL;
- _ASSERTE(NULL != pTarget);
-
- // this function does the work
- ::CallDescrWithObjectArray(
- gc.pServer,
- pResolvedMD,
- //pRM,
- pTarget,
- &mSig,
- pCookie,
- gc.pArgs,
- &gc.ret,
- ppVarOutParams);
-
- LOG((LF_REMOTING, LL_INFO10, "CStackBuilderSink::PrivateProcessMessage OUT\n"));
-
- HELPER_METHOD_FRAME_END();
-
- return OBJECTREFToObject(gc.ret);
-}
-FCIMPLEND
-
-class ProfilerServerCallbackHolder
-{
-public:
- ProfilerServerCallbackHolder(Thread* pThread) : m_pThread(pThread)
- {
-#ifdef PROFILING_SUPPORTED
- // If we're profiling, notify the profiler that we're about to invoke the remoting target
- {
- BEGIN_PIN_PROFILER(CORProfilerTrackRemoting());
- GCX_PREEMP();
- g_profControlBlock.pProfInterface->RemotingServerInvocationStarted();
- END_PIN_PROFILER();
- }
-#endif // PROFILING_SUPPORTED
- }
-
- ~ProfilerServerCallbackHolder()
- {
-#ifdef PROFILING_SUPPORTED
- // If profiling is active, tell profiler we've made the call, received the
- // return value, done any processing necessary, and now remoting is done.
- {
- BEGIN_PIN_PROFILER(CORProfilerTrackRemoting());
- GCX_PREEMP();
- g_profControlBlock.pProfInterface->RemotingServerInvocationReturned();
- END_PIN_PROFILER();
- }
-#endif // PROFILING_SUPPORTED
- }
-
-private:
- Thread* m_pThread;
-};
-
-//+----------------------------------------------------------------------------
-//
-// Function: CallDescrWithObjectArray, private
-//
-// Synopsis: Builds the stack from a object array and call the object
-//
-//
-// Note this function triggers GC and assumes that pServer, pArguments, pVarRet, and ppVarOutParams are
-// all already protected!!
-//+----------------------------------------------------------------------------
-void CallDescrWithObjectArray(OBJECTREF& pServer,
- //ReflectMethod *pRM,
- MethodDesc *pMeth,
- PCODE pTarget,
- MetaSig* sig,
- VASigCookie *pCookie,
- PTRARRAYREF& pArgArray,
- OBJECTREF *pVarRet,
- PTRARRAYREF *ppVarOutParams)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- }
- CONTRACTL_END;
-
- LOG((LF_REMOTING, LL_INFO10, "CallDescrWithObjectArray IN\n"));
-
-#ifdef _PREFAST_
-#pragma warning(push)
-#pragma warning(disable:6263) // "Suppress PREFast warning about _alloca in a loop"
- // _alloca is called within a loop in a number of places within this method
- // (as an ultra fast means of acquiring temporary storage). This can be a
- // problem in some scenarios (swiftly drive us to stack overflow). But in
- // this case the allocations are tightly bounded (by the number of arguments
- // in the target method) and the allocations themselves are small (no worse
- // really than calling the method an extra time).
-#endif
-
- ByRefInfo *pByRefs = NULL;
- FrameWithCookie<ProtectValueClassFrame> *pProtectValueClassFrame = NULL;
- FrameWithCookie<ProtectByRefsFrame> *pProtectionFrame = NULL;
- UINT nStackBytes = 0;
- LPBYTE pAlloc = 0;
- LPBYTE pTransitionBlock = 0;
- UINT32 numByRef = 0;
- //DWORD attr = pRM->dwFlags;
-#ifdef _DEBUG
- //MethodDesc *pMD = pRM->pMethod;
-#endif
- ValueClassInfo *pValueClasses = NULL;
-
- // check the calling convention
-
- BYTE callingconvention = sig->GetCallingConvention();
- if (!isCallConv(callingconvention, IMAGE_CEE_CS_CALLCONV_DEFAULT))
- {
- _ASSERTE(!"This calling convention is not supported.");
- COMPlusThrow(kInvalidProgramException);
- }
-
- // Make sure we are properly loaded
- CONSISTENCY_CHECK(GetAppDomain()->CheckCanExecuteManagedCode(pMeth));
-
- // Note this is redundant with the above but we do it anyway for safety
- pMeth->EnsureActive();
-
-#ifdef DEBUGGING_SUPPORTED
- // debugger goo What does this do? can someone put a comment here?
- if (CORDebuggerTraceCall())
- {
- g_pDebugInterface->TraceCall((const BYTE *)pTarget);
- }
-#endif // DEBUGGING_SUPPORTED
-
- Thread * pThread = GetThread();
-
- {
- ProfilerServerCallbackHolder profilerHolder(pThread);
-
- ArgIterator argit(sig);
-
- // Create a fake FramedMethodFrame on the stack.
- nStackBytes = argit.SizeOfFrameArgumentArray();
-
- UINT32 cbAlloc = 0;
- if (!ClrSafeInt<UINT32>::addition(TransitionBlock::GetNegSpaceSize(), sizeof(TransitionBlock), cbAlloc))
- COMPlusThrow(kArgumentException);
- if (!ClrSafeInt<UINT32>::addition(cbAlloc, nStackBytes, cbAlloc))
- COMPlusThrow(kArgumentException);
-
- pAlloc = (LPBYTE)_alloca(cbAlloc);
- pTransitionBlock = pAlloc + TransitionBlock::GetNegSpaceSize();
-
- // cycle through the parameters and see if there are byrefs
- BOOL fHasByRefs = FALSE;
-
- //if (attr & RM_ATTR_BYREF_FLAG_SET)
- // fHasByRefs = attr & RM_ATTR_HAS_BYREF_ARG;
- //else
- {
- sig->Reset();
- CorElementType typ;
- while ((typ = sig->NextArg()) != ELEMENT_TYPE_END)
- {
- if (typ == ELEMENT_TYPE_BYREF)
- {
- fHasByRefs = TRUE;
- //attr |= RM_ATTR_HAS_BYREF_ARG;
- break;
- }
- }
- //attr |= RM_ATTR_BYREF_FLAG_SET;
- //pRM->dwFlags = attr;
- sig->Reset();
- }
-
- UINT32 nFixedArgs = sig->NumFixedArgs();
- // To avoid any security problems with integer overflow/underflow we're
- // going to validate the number of args here (we're about to _alloca an
- // array of ArgInfo structures and maybe a managed object array as well
- // based on this count).
- _ASSERTE(sizeof(Object*) <= sizeof(ArgInfo));
- UINT32 nMaxArgs = UINT32_MAX / sizeof(ArgInfo);
- if (nFixedArgs > nMaxArgs)
- COMPlusThrow(kArgumentException);
-
- // if there are byrefs allocate and array for the out parameters
- if (fHasByRefs)
- {
- *ppVarOutParams = PTRARRAYREF(AllocateObjectArray(sig->NumFixedArgs(), g_pObjectClass));
-
- // Null out the array
- memset(&(*ppVarOutParams)->m_Array, 0, sizeof(OBJECTREF) * sig->NumFixedArgs());
- }
-
- OBJECTREF *ppThis = NULL;
-
- if (sig->HasThis())
- {
- ppThis = (OBJECTREF*)(pTransitionBlock + argit.GetThisOffset());
-
- // *ppThis is not GC protected. It will be set to the right value
- // after all object allocations are made.
- *ppThis = NULL;
- }
-
- // if we have the Value Class return, we need to allocate that class and place a pointer to it on the stack.
-
- *pVarRet = NULL;
- TypeHandle retType = sig->GetRetTypeHandleThrowing();
- // Note that we want the unnormalized (signature) type because GetStackObject
- // boxes as the element type, which if we normalized it would loose information.
- CorElementType retElemType = sig->GetReturnType();
-
- // The MethodTable pointer of the return type, if that's a struct
- MethodTable* pStructRetTypeMT = NULL;
-
- // Allocate a boxed struct instance to hold the return value in any case.
- if (retElemType == ELEMENT_TYPE_VALUETYPE)
- {
- pStructRetTypeMT = retType.GetMethodTable();
- *pVarRet = pStructRetTypeMT->Allocate();
- }
- else {
- _ASSERTE(!argit.HasRetBuffArg());
- }
-
-#ifdef CALLDESCR_REGTYPEMAP
- UINT64 dwRegTypeMap = 0;
- BYTE* pMap = (BYTE*)&dwRegTypeMap;
-#endif // CALLDESCR_REGTYPEMAP
-
-#ifdef CALLDESCR_FPARGREGS
- FloatArgumentRegisters *pFloatArgumentRegisters = NULL;
-#endif // CALLDESCR_FPARGREGS
-
- // gather data about the parameters by iterating over the sig:
- UINT32 arg = 0;
- int ofs = 0;
-
- // REVIEW: need to use actual arg count if VarArgs are supported
- ArgInfo* pArgInfoStart = (ArgInfo*) _alloca(nFixedArgs*sizeof(ArgInfo));
-
-#ifdef _DEBUG
- // We expect to write useful data over every part of this so need
- // not do this in retail!
- memset((void *)pArgInfoStart, 0, sizeof(ArgInfo)*nFixedArgs);
-#endif
-
- for (; TransitionBlock::InvalidOffset != (ofs = argit.GetNextOffset()); arg++)
- {
- CONSISTENCY_CHECK(arg < nFixedArgs);
- ArgInfo* pArgInfo = pArgInfoStart + arg;
-
-#ifdef CALLDESCR_REGTYPEMAP
- FillInRegTypeMap(ofs, argit.GetArgType(), pMap);
-#endif
-
-#ifdef CALLDESCR_FPARGREGS
- // Under CALLDESCR_FPARGREGS we can have arguments in floating point registers. If we have at
- // least one such argument we point the call worker at the floating point area of the frame (we leave
- // it null otherwise since the worker can perform a useful optimization if it knows no floating point
- // registers need to be set up).
- if (TransitionBlock::HasFloatRegister(ofs, argit.GetArgLocDescForStructInRegs()) &&
- (pFloatArgumentRegisters == NULL))
- {
- pFloatArgumentRegisters = (FloatArgumentRegisters*)(pTransitionBlock +
- TransitionBlock::GetOffsetOfFloatArgumentRegisters());
- }
-#endif
-
- if (argit.GetArgType() == ELEMENT_TYPE_BYREF)
- {
- TypeHandle ty = TypeHandle();
- CorElementType brType = sig->GetByRefType(&ty);
- if (CorIsPrimitiveType(brType))
- {
- pArgInfo->dataSize = gElementTypeInfo[brType].m_cbSize;
- }
- else if (ty.IsValueType())
- {
- pArgInfo->dataSize = ty.GetMethodTable()->GetNumInstanceFieldBytes();
- numByRef ++;
- }
- else
- {
- pArgInfo->dataSize = sizeof(Object *);
- numByRef ++;
- }
-
- ByRefInfo *brInfo = (ByRefInfo *) _alloca(offsetof(ByRefInfo,data) + pArgInfo->dataSize);
- brInfo->argIndex = arg;
- brInfo->typ = brType;
- brInfo->typeHandle = ty;
- brInfo->pNext = pByRefs;
- pByRefs = brInfo;
- pArgInfo->dataLocation = (BYTE*)brInfo->data;
- *((void**)(pTransitionBlock + ofs)) = (void*)pArgInfo->dataLocation;
- pArgInfo->dataTypeHandle = ty;
- pArgInfo->dataType = static_cast<BYTE>(brType);
- pArgInfo->byref = TRUE;
- }
- else
- {
- pArgInfo->dataLocation = pTransitionBlock + ofs;
- pArgInfo->dataSize = argit.GetArgSize();
- pArgInfo->dataTypeHandle = sig->GetLastTypeHandleThrowing(); // this may cause GC!
- pArgInfo->dataType = (BYTE)argit.GetArgType();
- pArgInfo->byref = FALSE;
- }
- }
-
-
- if (ppThis)
- {
- // If this isn't a value class, verify the objectref
-#ifdef _DEBUG
- //if (pMD->GetMethodTable()->IsValueType() == FALSE)
- //{
- // VALIDATEOBJECTREF(pServer);
- //}
-#endif //_DEBUG
- *ppThis = pServer;
- }
-
- PVOID pRetBufStackData = NULL;
-
- if (argit.HasRetBuffArg())
- {
- // If the return buffer *must* be a stack-allocated object, allocate it.
- PVOID pRetBufData = NULL;
- if (pStructRetTypeMT->IsStructRequiringStackAllocRetBuf())
- {
- SIZE_T sz = pStructRetTypeMT->GetNumInstanceFieldBytes();
- pRetBufData = pRetBufStackData = _alloca(sz);
- memset(pRetBufData, 0, sz);
- pValueClasses = new (_alloca(sizeof(ValueClassInfo))) ValueClassInfo(pRetBufStackData, pStructRetTypeMT, pValueClasses);
- }
- else
- {
- pRetBufData = (*pVarRet)->GetData();
- }
- *((LPVOID*) (pTransitionBlock + argit.GetRetBuffArgOffset())) = pRetBufData;
- }
-
- // There should be no GC when we fill up the stack with parameters, as we don't protect them
- // Assignment of "*ppThis" above triggers the point where we become unprotected.
- {
- GCX_FORBID();
-
- PBYTE dataLocation;
- INT32 dataSize;
- TypeHandle dataTypeHandle;
- BYTE dataType;
-
- OBJECTREF* pArguments = pArgArray->m_Array;
- UINT32 i;
- for (i=0; i<nFixedArgs; i++)
- {
- ArgInfo* pArgInfo = pArgInfoStart + i;
-
- dataSize = pArgInfo->dataSize;
- dataLocation = pArgInfo->dataLocation;
- dataTypeHandle = pArgInfo->dataTypeHandle;
- dataType = pArgInfo->dataType;
-
- // Nullable<T> needs special treatment, even if it is 1, 2, 4, or 8 bytes
- if (dataType == ELEMENT_TYPE_VALUETYPE)
- goto DEFAULT_CASE;
-
- switch (dataSize)
- {
- case 1:
- // This "if" statement is necessary to make the assignement big-endian aware
- if (pArgInfo->byref)
- *((INT8*)dataLocation) = *((INT8*)pArguments[i]->GetData());
- else
- *(StackElemType*)dataLocation = (StackElemType)*((INT8*)pArguments[i]->GetData());
- break;
- case 2:
- // This "if" statement is necessary to make the assignement big-endian aware
- if (pArgInfo->byref)
- *((INT16*)dataLocation) = *((INT16*)pArguments[i]->GetData());
- else
- *(StackElemType*)dataLocation = (StackElemType)*((INT16*)pArguments[i]->GetData());
- break;
- case 4:
-#ifndef _WIN64
- if ((dataType == ELEMENT_TYPE_STRING) ||
- (dataType == ELEMENT_TYPE_OBJECT) ||
- (dataType == ELEMENT_TYPE_CLASS) ||
- (dataType == ELEMENT_TYPE_SZARRAY) ||
- (dataType == ELEMENT_TYPE_ARRAY))
- {
- *(OBJECTREF *)dataLocation = pArguments[i];
- }
- else
- {
- *(StackElemType*)dataLocation = (StackElemType)*((INT32*)pArguments[i]->GetData());
- }
-#else // !_WIN64
- // This "if" statement is necessary to make the assignement big-endian aware
- if (pArgInfo->byref)
- *(INT32*)dataLocation = *((INT32*)pArguments[i]->GetData());
- else
- *(StackElemType*)dataLocation = (StackElemType)*((INT32*)pArguments[i]->GetData());
-#endif // !_WIN64
- break;
-
- case 8:
-#ifdef _WIN64
- if ((dataType == ELEMENT_TYPE_STRING) ||
- (dataType == ELEMENT_TYPE_OBJECT) ||
- (dataType == ELEMENT_TYPE_CLASS) ||
- (dataType == ELEMENT_TYPE_SZARRAY) ||
- (dataType == ELEMENT_TYPE_ARRAY))
- {
- *(OBJECTREF *)dataLocation = pArguments[i];
- }
- else
- {
- *((INT64*)dataLocation) = *((INT64*)pArguments[i]->GetData());
- }
-#else // _WIN64
- *((INT64*)dataLocation) = *((INT64*)pArguments[i]->GetData());
-#endif // _WIN64
- break;
-
- default:
- {
- DEFAULT_CASE:
- MethodTable * pMT = dataTypeHandle.GetMethodTable();
-
-#ifdef ENREGISTERED_PARAMTYPE_MAXSIZE
- // We do not need to allocate a buffer if the argument is already passed by reference.
- if (!pArgInfo->byref && ArgIterator::IsArgPassedByRef(dataTypeHandle))
- {
- PVOID pvArg = _alloca(dataSize);
- pMT->UnBoxIntoUnchecked(pvArg, pArguments[i]);
- *(PVOID*)dataLocation = pvArg;
-
- pValueClasses = new (_alloca(sizeof(ValueClassInfo))) ValueClassInfo(pvArg, pMT, pValueClasses);
- }
- else
-#endif
- {
- pMT->UnBoxIntoUnchecked(dataLocation, pArguments[i]);
- }
- }
- }
- }
-
-#ifdef _DEBUG
- // Should not be using this any more
- memset((void *)pArgInfoStart, 0, sizeof(ArgInfo)*nFixedArgs);
-#endif
-
- // if there were byrefs, push a protection frame
- if (pByRefs && numByRef > 0)
- {
- char *pBuffer = (char*)_alloca (sizeof (FrameWithCookie<ProtectByRefsFrame>));
- pProtectionFrame = new (pBuffer) FrameWithCookie<ProtectByRefsFrame>(pThread, pByRefs);
- }
-
- // If there were any value classes that must be protected by the
- // caller, push a ProtectValueClassFrame.
- if (pValueClasses)
- {
- char *pBuffer = (char*)_alloca (sizeof (FrameWithCookie<ProtectValueClassFrame>));
- pProtectValueClassFrame = new (pBuffer) FrameWithCookie<ProtectValueClassFrame>(pThread, pValueClasses);
- }
-
- } // GCX_FORBID
-
- UINT fpReturnSize = argit.GetFPReturnSize();
-
- CallDescrData callDescrData;
-
- callDescrData.pSrc = pTransitionBlock + sizeof(TransitionBlock);
- callDescrData.numStackSlots = nStackBytes / STACK_ELEM_SIZE;
-#ifdef CALLDESCR_ARGREGS
- callDescrData.pArgumentRegisters = (ArgumentRegisters*)(pTransitionBlock + TransitionBlock::GetOffsetOfArgumentRegisters());
-#endif
-#ifdef CALLDESCR_FPARGREGS
- callDescrData.pFloatArgumentRegisters = pFloatArgumentRegisters;
-#endif
-#ifdef CALLDESCR_REGTYPEMAP
- callDescrData.dwRegTypeMap = dwRegTypeMap;
-#endif
- callDescrData.fpReturnSize = fpReturnSize;
- callDescrData.pTarget = pTarget;
-
- CallDescrWorkerWithHandler(&callDescrData);
-
- // It is still illegal to do a GC here. The return type might have/contain GC pointers.
- if (retElemType == ELEMENT_TYPE_VALUETYPE)
- {
- _ASSERTE(*pVarRet != NULL); // we have already allocated a return object
- PVOID pVarRetData = (*pVarRet)->GetData();
-
- // If the return result was passed back in registers, then copy it into the return object
- if (!argit.HasRetBuffArg())
- {
- CopyValueClass(pVarRetData, &callDescrData.returnValue, (*pVarRet)->GetMethodTable(), (*pVarRet)->GetAppDomain());
- }
- else if (pRetBufStackData != NULL)
- {
- // Copy the stack-allocated ret buff to the heap-allocated one.
- CopyValueClass(pVarRetData, pRetBufStackData, (*pVarRet)->GetMethodTable(), (*pVarRet)->GetAppDomain());
- }
-
- // If the return is a Nullable<T>, box it using Nullable<T> conventions.
- // TODO: this double allocates on constructions which is wasteful
- if (!retType.IsNull())
- *pVarRet = Nullable::NormalizeBox(*pVarRet);
- }
- else
- CMessage::GetObjectFromStack(pVarRet, &callDescrData.returnValue, retElemType, retType);
-
- // You can now do GCs if you want to
-
- if (pProtectValueClassFrame)
- pProtectValueClassFrame->Pop(pThread);
-
- // extract the out args from the byrefs
- if (pByRefs)
- {
- do
- {
- // Always extract the data ptr every time we enter this loop because
- // calls to GetObjectFromStack below can cause a GC.
- // Even this is not enough, because that we are passing a pointer to GC heap
- // to GetObjectFromStack . If GC happens, nobody is protecting the passed in pointer.
-
- OBJECTREF pTmp = NULL;
- void* dataLocation = pByRefs->data;
- CMessage::GetObjectFromStack(&pTmp, &dataLocation, pByRefs->typ, pByRefs->typeHandle, TRUE);
- (*ppVarOutParams)->SetAt(pByRefs->argIndex, pTmp);
- pByRefs = pByRefs->pNext;
- }
- while (pByRefs);
-
- if (pProtectionFrame)
- pProtectionFrame->Pop(pThread);
- }
-
- } // ProfilerServerCallbackHolder
-
-#ifdef _PREFAST_
-#pragma warning(pop)
-#endif
-
- LOG((LF_REMOTING, LL_INFO10, "CallDescrWithObjectArray OUT\n"));
-}
-
-#endif // FEATURE_REMOTING
diff --git a/src/vm/threads.cpp b/src/vm/threads.cpp
index 791a09fc42..81bf023568 100644
--- a/src/vm/threads.cpp
+++ b/src/vm/threads.cpp
@@ -31,7 +31,6 @@
#include "appdomainstack.inl"
#include "eventtrace.h"
#ifdef FEATURE_REMOTING
-#include "appdomainhelper.h"
#endif
#include "comutilnative.h"
#include "finalizerthread.h"
diff --git a/src/vm/validator.cpp b/src/vm/validator.cpp
deleted file mode 100644
index 54f6ecdb2b..0000000000
--- a/src/vm/validator.cpp
+++ /dev/null
@@ -1,946 +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.
-
-
-/*
- *
- * Purpose: Provide IValidate implementation.
- * IValidate is used to validate PE stub, Metadata and IL.
- *
- */
-
-#include "common.h"
-
-#include "corerror.h"
-#include "vererror.h"
-#include "ivalidator.h"
-#include "securityattributes.h"
-#include "corhost.h"
-#include "verifier.hpp"
-#include "pedecoder.h"
-#include "comcallablewrapper.h"
-#include "../dlls/mscorrc/resource.h"
-#include "posterror.h"
-#include "comcallablewrapper.h"
-#include "eeconfig.h"
-#include "corhost.h"
-#include "security.h"
-#include "appdomain.inl"
-
-typedef void (*VerifyErrorHandler)(void* pThis, HRESULT hrError, struct VerErrorStruct* pError);
-
-// Declare global variables
-#define DECLARE_DATA
-#include "veropcodes.hpp"
-#undef DECLARE_DATA
-
-class CValidator
-{
-public:
- CValidator(IVEHandler *veh) : m_veh(veh)
- {
- LIMITED_METHOD_CONTRACT;
- }
- HRESULT VerifyAllMethodsForClass(Module *pModule, mdTypeDef cl, ValidateWorkerArgs* pArgs);
- HRESULT VerifyAllGlobalFunctions(Module *pModule, ValidateWorkerArgs* pArgs);
- HRESULT VerifyAssembly(Assembly *pAssembly, ValidateWorkerArgs* pArgs);
- HRESULT VerifyModule(Module* pModule, ValidateWorkerArgs* pArgs);
- HRESULT ReportError(HRESULT hr, ValidateWorkerArgs* pArgs, mdToken tok=0);
- HRESULT VerifyMethod(COR_ILMETHOD_DECODER* pILHeader, IVEHandler* pVEHandler, WORD wFlags, ValidateWorkerArgs* pArgs);
- HRESULT VerifyExportedType(
- Module * pModule,
- mdToken tkExportedType,
- ValidateWorkerArgs * pArgs);
- void HandleError(HRESULT hrError, struct VerErrorStruct* pError);
-
-private:
- IVEHandler *m_veh;
- ValidateWorkerArgs* m_pArgs;
-}; // class CValidator
-
-HRESULT CValidator::ReportError(HRESULT hr, ValidateWorkerArgs* pArgs, mdToken tok /* = 0 */)
-{
- CONTRACTL {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- } CONTRACTL_END;
-
- if (m_veh == NULL)
- return hr;
-
- HRESULT hr2 = E_FAIL;
- BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), return COR_E_STACKOVERFLOW);
- VEContext vec;
-
- memset(&vec, 0, sizeof(VEContext));
-
- if (tok != 0)
- {
- vec.flags = VER_ERR_TOKEN;
- vec.Token = tok;
- }
-
- hr2 = Verifier::ReportError(m_veh, hr, &vec, pArgs);
- END_SO_INTOLERANT_CODE;
- return hr2;
-} // CValidator::ReportError
-
-// Separate method since EX_TRY uses _alloca and is in a loop below.
-COR_ILMETHOD* GetILHeader(MethodDesc *pMD)
-{
- STANDARD_VM_CONTRACT;
-
- COR_ILMETHOD *pILHeader = NULL;
-
- EX_TRY
- {
- pILHeader = pMD->GetILHeader();
- }
- EX_CATCH
- {
- }
- EX_END_CATCH(SwallowAllExceptions);
-
- return pILHeader;
-}
-
-HRESULT CValidator::VerifyAllMethodsForClass(Module *pModule, mdTypeDef cl, ValidateWorkerArgs* pArgs)
-{
- STANDARD_VM_CONTRACT;
-
- HRESULT hr = S_OK;
- MethodTable *pMT = NULL;
-
- // In the case of COR_GLOBAL_PARENT_TOKEN (i.e. global functions), it is guaranteed
- // that the module has a method table or our caller will have skipped this step.
- TypeHandle th;
- {
- // <REVISIT>
- // Although there's no assert to disable here, we need to improve OOM reliability here. We are ignoring the HRESULT from the loader here.
- // That could cause an OOM failure to be disguised as something else. OOM's
- // need to be handled or propagated up to the caller.
- // </REVISIT>
- CONTRACT_VIOLATION(0);
-
- EX_TRY {
- th = ClassLoader::LoadTypeDefOrRefThrowing(pModule, cl,
- ClassLoader::ReturnNullIfNotFound,
- ClassLoader::PermitUninstDefOrRef);
- }
- EX_CATCH_HRESULT(hr);
-
- if (FAILED(hr)) {
- if ((hr==COR_E_TYPELOAD) || (hr==VER_E_TYPELOAD)) {
- hr = ReportError(hr, pArgs,cl);
- } else {
- hr = ReportError(hr, pArgs);
- }
- goto Exit;
- }
- }
-
- pMT = th.GetMethodTable();
- if (pMT == NULL)
- {
- hr = ReportError(VER_E_TYPELOAD, pArgs, cl);
- goto Exit;
- }
-
- g_fVerifierOff = false;
-
- {
- // Verify all methods in class - excluding inherited methods
- MethodTable::MethodIterator it(pMT);
- for (; it.IsValid(); it.Next())
- {
- pArgs->pMethodDesc = it.GetMethodDesc();
-
- bool fVerifyTransparentMethod = true;
- if (pArgs->fTransparentMethodsOnly)
- {
- MethodSecurityDescriptor msd(pArgs->pMethodDesc);
- fVerifyTransparentMethod = !msd.IsCritical();
- }
-
- if (pArgs->pMethodDesc &&
- pArgs->pMethodDesc->GetMethodTable() == pMT &&
- pArgs->pMethodDesc->IsIL() &&
- !pArgs->pMethodDesc->IsAbstract() &&
- !pArgs->pMethodDesc->IsUnboxingStub() &&
- fVerifyTransparentMethod)
- {
- COR_ILMETHOD* pILHeader = GetILHeader(pArgs->pMethodDesc);
-
- if (pILHeader != NULL)
- {
- COR_ILMETHOD_DECODER::DecoderStatus status;
- COR_ILMETHOD_DECODER ILHeader(pILHeader,
- pArgs->pMethodDesc->GetMDImport(), &status);
-
- if (status == COR_ILMETHOD_DECODER::SUCCESS)
- {
- hr = VerifyMethod(&ILHeader, m_veh, VER_FORCE_VERIFY, pArgs);
- if (hr == VER_E_INTERNAL) // this probably means peverify.dll was missing
- {
- goto Exit;
- }
- }
- else if (status == COR_ILMETHOD_DECODER::VERIFICATION_ERROR)
- {
- hr = COR_E_VERIFICATION;
- }
- else if (status == COR_ILMETHOD_DECODER::FORMAT_ERROR)
- {
- hr = COR_E_BADIMAGEFORMAT;
- }
- else
- {
- _ASSERTE(!"Unhandled status from COR_ILMETHOD_DECODER");
- }
- }
- else
- {
- hr = COR_E_BADIMAGEFORMAT;
- }
-
- if (FAILED(hr))
- hr = ReportError(hr, pArgs);
-
- if (FAILED(hr))
- goto Exit;
- }
- // We should ideally have an API to yield to the host,
- // but this is not critical for Whidbey.
- if (CLRTaskHosted())
- ClrSleepEx(0, FALSE);
- }
- }
-
-Exit:
- pArgs->pMethodDesc = NULL;
- return hr;
-} // CValidator::VerifyAllMethodsForClass
-
-//---------------------------------------------------------------------------------------
-//
-void
-MethodDescAndCorILMethodDecoderToCorInfoMethodInfo(
- MethodDesc * ftn,
- COR_ILMETHOD_DECODER * ILHeader,
- CORINFO_METHOD_INFO * pMethodInfo)
-{
- STANDARD_VM_CONTRACT;
-
- pMethodInfo->ftn = CORINFO_METHOD_HANDLE(ftn);
- pMethodInfo->scope = CORINFO_MODULE_HANDLE(ftn->GetModule());
- pMethodInfo->ILCode = const_cast<BYTE*>(ILHeader->Code);
- pMethodInfo->ILCodeSize = ILHeader->GetCodeSize();
- pMethodInfo->maxStack = ILHeader->GetMaxStack();
- pMethodInfo->EHcount = ILHeader->EHCount();
- pMethodInfo->options =
- (CorInfoOptions)
- (((ILHeader->GetFlags() & CorILMethod_InitLocals) ? CORINFO_OPT_INIT_LOCALS : 0) |
- (ftn->AcquiresInstMethodTableFromThis() ? CORINFO_GENERICS_CTXT_FROM_THIS : 0) |
- (ftn->RequiresInstMethodTableArg() ? CORINFO_GENERICS_CTXT_FROM_METHODTABLE : 0) |
- (ftn->RequiresInstMethodDescArg() ? CORINFO_GENERICS_CTXT_FROM_METHODDESC : 0));
-
- PCCOR_SIGNATURE pSigToConvert;
- DWORD cbSigToConvert;
- ftn->GetSig(&pSigToConvert, &cbSigToConvert);
- CONSISTENCY_CHECK(NULL != pSigToConvert);
- // fetch the method signature
- CEEInfo::ConvToJitSig(
- pSigToConvert,
- cbSigToConvert,
- pMethodInfo->scope,
- mdTokenNil,
- &pMethodInfo->args,
- ftn,
- false);
-
- //@GENERICS:
- // Shared generic methods and shared methods on generic structs take an extra argument representing their instantiation
- if (ftn->RequiresInstArg())
- pMethodInfo->args.callConv = (CorInfoCallConv) (pMethodInfo->args.callConv | CORINFO_CALLCONV_PARAMTYPE);
-
- // method attributes and signature are consistant
- _ASSERTE(!!ftn->IsStatic() == ((pMethodInfo->args.callConv & CORINFO_CALLCONV_HASTHIS) == 0));
-
- // And its local variables
- CEEInfo::ConvToJitSig(
- ILHeader->LocalVarSig,
- ILHeader->cbLocalVarSig,
- pMethodInfo->scope,
- mdTokenNil,
- &pMethodInfo->locals,
- ftn,
- true);
-} // MethodDescAndCorILMethodDecoderToCorInfoMethodInfo
-
-//---------------------------------------------------------------------------------------
-//
-void PEVerifyErrorHandler(void* pThis, HRESULT hrError, struct VerErrorStruct* pError)
-{
- WRAPPER_NO_CONTRACT;
- STATIC_CONTRACT_SO_TOLERANT;
- ((CValidator*)pThis)->HandleError(hrError, pError);
-}
-
-void CValidator::HandleError(HRESULT hrError, struct VerErrorStruct* pError)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- BEGIN_SO_INTOLERANT_CODE(GetThread());
- _ASSERTE(sizeof(VEContext) == sizeof(struct VerErrorStruct));
- Verifier::ReportError(m_veh, hrError, (VEContext*)pError, m_pArgs);
- END_SO_INTOLERANT_CODE;
-}
-typedef void (__stdcall* VerifyFunc)(ICorJitInfo* pJitInfo, CORINFO_METHOD_INFO* pMethodInfo, VerifyErrorHandler pErrorHandler, void* pThis);
-static void VerifyMethodHelper(VerifyFunc pVerFunc, CEEJitInfo* pJI, CORINFO_METHOD_INFO* pMethodInfo, void* pThis)
-{
- // Helper method to allow us to use SO_TOLERANT_CODE macro
- STATIC_CONTRACT_SO_INTOLERANT;
- WRAPPER_NO_CONTRACT;
-
- BEGIN_SO_TOLERANT_CODE(GetThread());
- // Verify the method
- pVerFunc(pJI, pMethodInfo, PEVerifyErrorHandler, pThis);
- END_SO_TOLERANT_CODE;
-
-}
-
-static Volatile<VerifyFunc> g_pVerFunc = NULL;
-
-HRESULT CValidator::VerifyMethod(COR_ILMETHOD_DECODER* pILHeader, IVEHandler* pVEHandler, WORD wFlags, ValidateWorkerArgs* pArgs)
-{
- STANDARD_VM_CONTRACT;
-
- HRESULT hr = S_OK;
- EX_TRY
- {
- // Find the DLL entrypoint
- m_pArgs = pArgs;
- if (g_pVerFunc.Load() == NULL)
- {
- HINSTANCE hJit64 = NULL;
- if (SUCCEEDED(g_pCLRRuntime->LoadLibrary(W("peverify.dll"), &hJit64)))
- {
- typedef void (__stdcall* psxsPeVerifyStartup) (CoreClrCallbacks);
- psxsPeVerifyStartup sxsPeVerifyStartup = (psxsPeVerifyStartup) GetProcAddress(hJit64, "sxsPeVerifyStartup");
-
- if(sxsPeVerifyStartup)
- {
- CoreClrCallbacks cccallbacks = GetClrCallbacks();
- (*sxsPeVerifyStartup) (cccallbacks);
- g_pVerFunc = (VerifyFunc)GetProcAddress(hJit64, "VerifyMethod");
- }
- }
- }
-
- if(!g_pVerFunc)
- {
- _ASSERTE(!"Failed to load peverify.dll or find VerifyMethod proc address");
- hr = VER_E_INTERNAL;
- }
- else
- {
- Thread *pThread = GetThread();
- if (pThread->IsAbortRequested())
- {
- pThread->HandleThreadAbort();
- }
- // Prepare the args
- MethodDesc* ftn = pArgs->pMethodDesc;
- CEEJitInfo ji(pArgs->pMethodDesc, pILHeader, NULL, true /* verify only */);
- CORINFO_METHOD_INFO methodInfo;
- MethodDescAndCorILMethodDecoderToCorInfoMethodInfo(ftn, pILHeader, &methodInfo);
-
- // Verify the method
- VerifyMethodHelper(g_pVerFunc, &ji, &methodInfo, this);
- }
- }
- EX_CATCH
- {
- // Catch and report any errors that peverify.dll lets fall through (ideally that should never happen)
- hr = GET_EXCEPTION()->GetHR();
- hr = ReportError(hr, pArgs);
- }
- EX_END_CATCH(RethrowTerminalExceptions)
-
- return hr;
-} // CValidator::VerifyMethod
-
-// Helper function to verify the global functions
-HRESULT CValidator::VerifyAllGlobalFunctions(Module *pModule, ValidateWorkerArgs* pArgs)
-{
- STANDARD_VM_CONTRACT;
-
- HRESULT hr = S_OK;
- // Is there anything worth verifying?
- if (pModule->GetGlobalMethodTable())
- hr = VerifyAllMethodsForClass(pModule, COR_GLOBAL_PARENT_TOKEN, pArgs);
- return hr;
-} // CValidator::VerifyAllGlobalFunctions
-
-HRESULT CValidator::VerifyModule(Module* pModule, ValidateWorkerArgs* pArgs)
-{
- STANDARD_VM_CONTRACT;
-
- // Get a count of all the classdefs and enumerate them.
- HRESULT hr = S_OK;
- IMDInternalImport * pMDI = NULL;
-
- if (pModule == NULL)
- {
- IfFailGo(VER_E_BAD_MD);
- }
-
- pMDI = pModule->GetMDImport();
- if (pMDI == NULL)
- {
- IfFailGo(VER_E_BAD_MD);
- }
-
- // First verify all global functions - if there are any
- IfFailGoto(
- VerifyAllGlobalFunctions(pModule, pArgs),
- ErrExit_SkipReportError);
-
- {
- HENUMTypeDefInternalHolder hTypeDefEnum(pMDI);
-
- IfFailGo(hTypeDefEnum.EnumTypeDefInitNoThrow());
-
- // Verify all TypeDefs
- mdTypeDef tkTypeDef;
- while (pMDI->EnumTypeDefNext(&hTypeDefEnum, &tkTypeDef))
- {
- IfFailGoto(
- VerifyAllMethodsForClass(pModule, tkTypeDef, pArgs),
- ErrExit_SkipReportError);
- }
- }
-
- {
- HENUMInternalHolder hExportedTypeEnum(pMDI);
-
- IfFailGo(hExportedTypeEnum.EnumInitNoThrow(
- mdtExportedType,
- mdTokenNil));
-
- // Verify all ExportedTypes
- mdToken tkExportedType;
- while (pMDI->EnumNext(&hExportedTypeEnum, &tkExportedType))
- {
- IfFailGoto(
- VerifyExportedType(pModule, tkExportedType, pArgs),
- ErrExit_SkipReportError);
- }
- }
-
-ErrExit:
- if (FAILED(hr))
- {
- hr = ReportError(hr, pArgs);
- }
-
-ErrExit_SkipReportError:
- return hr;
-} // CValidator::VerifyModule
-
-HRESULT CValidator::VerifyAssembly(Assembly *pAssembly, ValidateWorkerArgs* pArgs)
-{
- STANDARD_VM_CONTRACT;
-
- HRESULT hr;
-
- _ASSERTE(pAssembly->GetManifestImport());
-
- // Verify the module containing the manifest. There is no
- // FileRefence so will no show up in the list.
- hr = VerifyModule(pAssembly->GetManifestModule(), pArgs);
- if (FAILED(hr))
- goto Exit;
-
- {
- IMDInternalImport* pManifestImport = pAssembly->GetManifestImport();
-
- HENUMInternalHolder hEnum(pManifestImport);
-
- mdToken mdFile;
- hr = hEnum.EnumInitNoThrow(mdtFile, mdTokenNil);
- if (FAILED(hr))
- {
- hr = ReportError(hr, pArgs);
- goto Exit;
- }
-
- while(pManifestImport->EnumNext(&hEnum, &mdFile))
- {
- DomainFile* pModule = pAssembly->GetManifestModule()->LoadModule(GetAppDomain(), mdFile, FALSE);
-
- if (pModule != NULL)
- {
- hr = VerifyModule(pModule->GetModule(), pArgs);
- if (FAILED(hr))
- goto Exit;
- }
- }
- }
-
-Exit:
- return hr;
-} // CValidator::VerifyAssembly
-
-HRESULT
-CValidator::VerifyExportedType(
- Module * pModule,
- mdToken tkExportedType,
- ValidateWorkerArgs * pArgs)
-{
- STANDARD_VM_CONTRACT;
-
- HRESULT hr;
- TypeHandle th;
- NameHandle nameHandle(pModule, tkExportedType);
-
- LPCSTR szNamespace;
- LPCSTR szName;
- IfFailGo(pModule->GetMDImport()->GetExportedTypeProps(
- tkExportedType,
- &szNamespace,
- &szName,
- NULL, // tkImplementation
- NULL, // tkTypeDefId
- NULL)); // dwExportedTypeFlags
-
- nameHandle.SetName(szNamespace, szName);
-
- EX_TRY
- {
- th = pModule->GetClassLoader()->LoadTypeHandleThrowing(
- &nameHandle,
- CLASS_LOADED,
- pModule);
- hr = S_OK;
- }
- EX_CATCH
- {
- hr = GET_EXCEPTION()->GetHR();
- }
- EX_END_CATCH(SwallowAllExceptions);
-
- IfFailGo(hr);
- if (th.GetMethodTable() == NULL)
- {
- IfFailGo(VER_E_TYPELOAD);
- }
-
-ErrExit:
- if (FAILED(hr))
- {
- hr = ReportError(hr, pArgs, tkExportedType);
- }
-
- return hr;
-} // CValidator::VerifyExportedType
-
-static void ValidateWorker(LPVOID /* ValidateWorker_Args */ ptr)
-{
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- } CONTRACTL_END;
-
- ValidateWorkerArgs *args = (ValidateWorkerArgs *) ptr;
- AppDomain *pDomain = GetThread()->GetDomain();
-
- StackSString ssFile(args->wszFileName);
- StackSString ssFileDir;
- StackSString ssDirectory;
-
- // Fill ssDirectory with just drive of the file (e.g. 'C:')
- SplitPath(ssFile, &ssDirectory, &ssFileDir, NULL, NULL);
- // Now apped directory from the file name (incl. leading and trailing '/' or '\')
- ssDirectory.Append(ssFileDir);
-
- {
- // Set up the domain to resolve all dependency assemblies for introspection
- struct _gc {
- OBJECTREF orAppDomain;
- STRINGREF refDirectory;
- } gc;
- ZeroMemory(&gc, sizeof(gc));
-
- GCPROTECT_BEGIN(gc);
-
- gc.orAppDomain = pDomain->GetExposedObject();
- if (!ssDirectory.IsEmpty())
- {
- gc.refDirectory = StringObject::NewString(ssDirectory);
- }
-
- MethodDescCallSite meth(METHOD__APP_DOMAIN__ENABLE_RESOLVE_ASSEMBLIES_FOR_INTROSPECTION, &gc.orAppDomain);
- ARG_SLOT args[2] =
- {
- ObjToArgSlot(gc.orAppDomain),
- ObjToArgSlot(gc.refDirectory)
- };
- meth.Call(args);
-
- GCPROTECT_END();
- }
-
- GCX_PREEMP();
-
- Assembly *pAssembly;
- if (args->wszFileName)
- {
- // Load the primary assembly for introspection
- AssemblySpec spec;
- spec.SetCodeBase(args->wszFileName);
- spec.SetIntrospectionOnly(TRUE);
- pAssembly = spec.LoadAssembly(FILE_LOADED);
- }
- else
- {
- // TODO: This is a workaround to get SQLCLR running.
- // Our loader requires that a parent assembly is specified in order to load an
- // assembly from byte array. But here we do not know the parent.
- PEAssemblyHolder pFile(PEAssembly::OpenMemory(SystemDomain::System()->SystemFile(),
- args->pe, args->size, TRUE));
- pAssembly = pDomain->LoadAssembly(NULL, pFile, FILE_LOADED);
- }
-
- // Verify the assembly
- args->hr = args->val->VerifyAssembly(pAssembly, args);
-}
-
-
-static HRESULT ValidateHelper(
- IVEHandler *veh,
- IUnknown *pAppDomain,
- DWORD ulAppDomainId,
- BOOL UseId,
- unsigned long ulFlags,
- unsigned long ulMaxError,
- unsigned long token,
- __in_z LPWSTR fileName,
- BYTE *pe,
- unsigned long ulSize)
-{
- CONTRACTL {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- SO_TOLERANT;
- } CONTRACTL_END;
-
- Thread *pThread = GetThread();
-
- if (pe == NULL)
- return E_POINTER;
-
- HRESULT hr = S_OK;
- BEGIN_SO_INTOLERANT_CODE_NOTHROW(pThread, return COR_E_STACKOVERFLOW);
- ADID pDomain;
- ValidateWorkerArgs args;
- CValidator val(veh);
- AppDomainFromIDHolder ad;
-
- BOOL Chk = FALSE;
- BOOL UnloadDomain = FALSE;
-
- GCX_COOP();
-
- EX_TRY {
- PEDecoder pev(pe, (COUNT_T)ulSize);
-
- args.wszFileName = fileName;
- args.fVerbose = (ulFlags & VALIDATOR_EXTRA_VERBOSE) ? true : false;
- args.fShowSourceLines = (ulFlags & VALIDATOR_SHOW_SOURCE_LINES) ? true : false;
- args.fTransparentMethodsOnly = (ulFlags & VALIDATOR_TRANSPARENT_ONLY) ? true : false;
- args.val = &val;
- args.pe = pe;
- args.size = ulSize;
-
- if((ulFlags & VALIDATOR_NOCHECK_PEFORMAT) == 0)
- {
- // Verify the PE header / native stubs first
- // <REVISIT> This validation is not performed on non-manifest modules. </REVISIT>
- Chk = ((ulFlags & VALIDATOR_CHECK_ILONLY) != 0) ? (BOOL) pev.CheckILOnlyFormat() :
- (BOOL) pev.CheckILFormat();
- if (!Chk)
- {
- hr = val.ReportError(VER_E_BAD_PE, &args);
-
- if (FAILED(hr))
- goto End;
- }
- }
- if((ulFlags & VALIDATOR_CHECK_PEFORMAT_ONLY) != 0)
- goto End;
-
- if (fileName)
- {
- AppDomain* pAD = AppDomain::CreateDomainContext(fileName);
- UnloadDomain = TRUE;
- pAD->SetPassiveDomain();
- pDomain=pAD->GetId();
- }
- else if (UseId)
- {
- pDomain = (ADID)ulAppDomainId;
- }
- else
- {
- SystemDomain::LockHolder lh;
- ComCallWrapper* pWrap = GetCCWFromIUnknown(pAppDomain, FALSE);
- if (pWrap == NULL)
- {
- hr = COR_E_APPDOMAINUNLOADED;
- goto End;
- }
- pDomain = pWrap->GetDomainID();
- }
-
- if (FAILED(hr))
- {
- hr = val.ReportError(hr, &args);
- goto End;
- }
-
- ad.Assign(pDomain, TRUE);
- if (ad.IsUnloaded())
- COMPlusThrow(kAppDomainUnloadedException);
- if (ad->IsIllegalVerificationDomain())
- COMPlusThrow(kFileLoadException, IDS_LOADINTROSPECTION_DISALLOWED);
- ad->SetVerificationDomain();
- ad.Release();
-
- args.val = &val;
-
- // We need a file path here. This is to do a fusion bind, and also
- // to make sure we can find any modules in the assembly. We assume
- // that the path points to the same place the bytes came from, which is true
- // with PEVerify, but perhaps not with other clients.
-
- if (pDomain != pThread->GetDomain()->GetId())
- {
- pThread->DoADCallBack(
- pDomain, ValidateWorker, &args);
- }
- else
- {
- ValidateWorker(&args);
- }
-
- if (FAILED(args.hr))
- hr = val.ReportError(args.hr, &args);
-
- // Only Unload the domain if we created it.
- if (UnloadDomain)
- AppDomain::UnloadById(pDomain,TRUE);
-End:;
-
- }
- EX_CATCH
- {
- hr = GET_EXCEPTION()->GetHR();
- hr = val.ReportError(hr, &args);
- }
- EX_END_CATCH(RethrowSOExceptions)
-
- END_SO_INTOLERANT_CODE;
- return hr;
-}
-
-void GetFormattingErrorMsg(__out_ecount(ulMaxLength) __out_z LPWSTR msg, unsigned int ulMaxLength)
-{
- CONTRACTL {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(ulMaxLength >= 30);
- } CONTRACTL_END;
-
- EX_TRY
- {
- SString s;
- s.LoadResource(CCompRC::Debugging, IDS_VER_E_FORMATTING);
- wcsncpy_s(msg, ulMaxLength, s.GetUnicode(), _TRUNCATE);
- }
- EX_CATCH
- {
- wcscpy_s(msg, ulMaxLength, W("Error loading resource string"));
- }
- EX_END_CATCH(SwallowAllExceptions)
-}
-
-static HRESULT FormatEventInfoHelper(
- HRESULT hVECode,
- VEContext Context,
- __out_ecount(ulMaxLength) __out_z LPWSTR msg,
- unsigned int ulMaxLength,
- SAFEARRAY *psa)
-{
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(ulMaxLength >= 30);
- SO_TOLERANT;
- } CONTRACTL_END;
-
- BEGIN_SO_INTOLERANT_CODE(GetThread());
-
- VerError err;
- memcpy(&err, &Context, sizeof(VerError));
-
- ValidateWorkerArgs argsDefault;
- ValidateWorkerArgs* pArgs = &argsDefault;
-
- // We passed a pointer to the ValidateWorkerArgs object through
- // the SAFEARRAY casted as a UINT because there was no room left in the
- // interface to pass information through it.
- {
- UINT dim;
- LONG l;
-#ifdef _WIN64
- VARTYPE vt;
-#endif // _WIN64
- VARIANT var;
-
- if(!psa) {
- goto lDone;
- }
-
- dim = SafeArrayGetDim(psa);
- if (dim != 1) {
- _ASSERTE(!"There should be one element in the SafeArray");
- goto lDone;
- }
-
- if (FAILED(SafeArrayGetLBound(psa, 1, &l))) {
- _ASSERTE(false);
- goto lDone;
- }
- if (l != 0) {
- _ASSERTE(!"expected the lower bound to be zero");
- goto lDone;
- }
-
- if (FAILED(SafeArrayGetUBound(psa, 1, &l))) {
- _ASSERTE(false);
- goto lDone;
- }
- if (l != 0) {
- _ASSERTE(!"expected the upper bound to be zero");
- goto lDone;
- }
-#ifdef _WIN64
- // This check fails on Win2K when it should pass
- SafeArrayGetVartype(psa, &vt);
- if(vt != VT_VARIANT) {
- _ASSERTE(!"expected the ElementType to be a VT_VARIANT");
- goto lDone;
- }
-#endif // _WIN64
- l = 0;
- SafeArrayGetElement(psa, &l, &var);
-
-#ifdef _WIN64
- if (V_VT(&var) != VT_UI8) { // We expect the VarType to be a VT_UI8 (VT_UI8 is not supported on Windows 2000)
- _ASSERTE(false);
- goto lDone;
- }
-
- pArgs = (ValidateWorkerArgs*)(size_t)V_UI8(&var);
-#else
- // We don't check that the type is V_UINT here because that check fails on Win2K when it should pass
- pArgs = (ValidateWorkerArgs*)(size_t)V_UINT(&var);
-#endif
-
- }
-lDone: ;
-
- EX_TRY
- {
- Verifier::GetErrorMsg(hVECode, err, msg, ulMaxLength, pArgs);
- }
- EX_CATCH
- {
- GetFormattingErrorMsg(msg, ulMaxLength);
- }
- EX_END_CATCH(SwallowAllExceptions)
-
- END_SO_INTOLERANT_CODE;
- return S_OK;
-}
-
-HRESULT CorValidator::Validate(
- IVEHandler *veh,
- IUnknown *pAppDomain,
- unsigned long ulFlags,
- unsigned long ulMaxError,
- unsigned long token,
- __in_z LPWSTR fileName,
- BYTE *pe,
- unsigned long ulSize)
-{
- WRAPPER_NO_CONTRACT;
- STATIC_CONTRACT_SO_TOLERANT;
- return ValidateHelper(veh, pAppDomain, 0, FALSE, ulFlags, ulMaxError,
- token, fileName, pe, ulSize);
-}
-
-HRESULT CLRValidator::Validate(
- IVEHandler *veh,
- unsigned long ulAppDomainId,
- unsigned long ulFlags,
- unsigned long ulMaxError,
- unsigned long token,
- __in_z LPWSTR fileName,
- BYTE *pe,
- unsigned long ulSize)
-{
- WRAPPER_NO_CONTRACT;
- STATIC_CONTRACT_SO_TOLERANT;
- return ValidateHelper(veh, NULL, ulAppDomainId, TRUE, ulFlags, ulMaxError,
- token, fileName, pe, ulSize);
-}
-
-HRESULT CorValidator::FormatEventInfo(
- HRESULT hVECode,
- VEContext Context,
- __out_ecount(ulMaxLength) LPWSTR msg,
- unsigned long ulMaxLength,
- SAFEARRAY *psa)
-{
- WRAPPER_NO_CONTRACT;
- return FormatEventInfoHelper(hVECode, Context, msg, ulMaxLength, psa);
-}
-
-HRESULT CLRValidator::FormatEventInfo(
- HRESULT hVECode,
- VEContext Context,
- __out_ecount(ulMaxLength) LPWSTR msg,
- unsigned long ulMaxLength,
- SAFEARRAY *psa)
-{
- WRAPPER_NO_CONTRACT;
- STATIC_CONTRACT_SO_TOLERANT;
- return FormatEventInfoHelper(hVECode, Context, msg, ulMaxLength, psa);
-}
-
-
diff --git a/src/zap/zapimage.cpp b/src/zap/zapimage.cpp
index 24f081a6f9..499a35b855 100644
--- a/src/zap/zapimage.cpp
+++ b/src/zap/zapimage.cpp
@@ -1742,6 +1742,7 @@ void ZapImage::Compile()
OutputEntrypointsTableForReadyToRun();
OutputDebugInfoForReadyToRun();
OutputTypesTableForReadyToRun(m_pMDImport);
+ OutputInliningTableForReadyToRun();
}
else
#endif
diff --git a/src/zap/zapimage.h b/src/zap/zapimage.h
index 02985f5d12..65347ffcf1 100644
--- a/src/zap/zapimage.h
+++ b/src/zap/zapimage.h
@@ -557,6 +557,7 @@ private:
void OutputEntrypointsTableForReadyToRun();
void OutputDebugInfoForReadyToRun();
void OutputTypesTableForReadyToRun(IMDInternalImport * pMDImport);
+ void OutputInliningTableForReadyToRun();
void CopyDebugDirEntry();
void CopyWin32VersionResource();
diff --git a/src/zap/zapinfo.cpp b/src/zap/zapinfo.cpp
index 4b2f39a264..2095524609 100644
--- a/src/zap/zapinfo.cpp
+++ b/src/zap/zapinfo.cpp
@@ -3622,8 +3622,13 @@ void ZapInfo::reportInliningDecision (CORINFO_METHOD_HANDLE inlinerHnd,
CorInfoInline inlineResult,
const char * reason)
{
-
-
+ if (!dontInline(inlineResult) && inlineeHnd != NULL)
+ {
+ // We deliberately report m_currentMethodHandle (not inlinerHnd) as inliner, because
+ // if m_currentMethodHandle != inlinerHnd, it simply means that inlinerHnd is intermediate link
+ // in inlining into m_currentMethodHandle, and we have no interest to track those intermediate links now.
+ m_pImage->m_pPreloader->ReportInlining(m_currentMethodHandle, inlineeHnd);
+ }
return m_pEEJitInfo->reportInliningDecision(inlinerHnd, inlineeHnd, inlineResult, reason);
}
diff --git a/src/zap/zapreadytorun.cpp b/src/zap/zapreadytorun.cpp
index 30ad296f95..8ed3f55159 100644
--- a/src/zap/zapreadytorun.cpp
+++ b/src/zap/zapreadytorun.cpp
@@ -380,6 +380,15 @@ void ZapImage::OutputDebugInfoForReadyToRun()
GetReadyToRunHeader()->RegisterSection(READYTORUN_SECTION_DEBUG_INFO, pBlob);
}
+void ZapImage::OutputInliningTableForReadyToRun()
+{
+ SBuffer serializedInlineTrackingBuffer;
+ m_pPreloader->GetSerializedInlineTrackingMap(&serializedInlineTrackingBuffer);
+ ZapNode * pBlob = ZapBlob::NewAlignedBlob(this, (PVOID)(const BYTE*) serializedInlineTrackingBuffer, serializedInlineTrackingBuffer.GetSize(), 4);
+ m_pDebugSection->Place(pBlob);
+ GetReadyToRunHeader()->RegisterSection(READYTORUN_SECTION_INLINING_INFO, pBlob);
+}
+
void ZapImage::OutputTypesTableForReadyToRun(IMDInternalImport * pMDImport)
{
NativeWriter writer;