Merge pull request #11055 from jorive/dev/xUnit-Performance-API
authorDrew Scoggins <anscoggi@microsoft.com>
Fri, 21 Apr 2017 17:16:01 +0000 (02:16 +0900)
committerGitHub <noreply@github.com>
Fri, 21 Apr 2017 17:16:01 +0000 (02:16 +0900)
Improving robustness of the run-xunit-perf.cmd script.

141 files changed:
Documentation/design-docs/core-minidump-generation.md [new file with mode: 0644]
Linked [new file with mode: 0644]
README.md
Tools-Override/codeOptimization.targets [new file with mode: 0644]
config.json
cross/x86/tryrun.cmake
dependencies.props
perf.groovy
src/ToolBox/superpmi/superpmi-shared/coreclrcommoncallbacks.h [new file with mode: 0644]
src/ToolBox/superpmi/superpmi-shim-collector/coreclrcallbacks.cpp
src/ToolBox/superpmi/superpmi-shim-collector/coreclrcallbacks.h
src/ToolBox/superpmi/superpmi-shim-counter/coreclrcallbacks.cpp
src/ToolBox/superpmi/superpmi-shim-counter/coreclrcallbacks.h
src/ToolBox/superpmi/superpmi-shim-simple/coreclrcallbacks.cpp
src/ToolBox/superpmi/superpmi-shim-simple/coreclrcallbacks.h
src/ToolBox/superpmi/superpmi/coreclrcallbacks.cpp
src/ToolBox/superpmi/superpmi/coreclrcallbacks.h
src/coreclr/hosts/coreconsole/coreconsole.cpp
src/coreclr/hosts/corerun/corerun.cpp
src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp
src/debug/createdump/crashinfo.cpp
src/debug/createdump/crashinfo.h
src/debug/createdump/createdump.cpp
src/debug/createdump/dumpwriter.cpp
src/dlls/mscordac/mscordac_unixexports.src
src/dlls/mscoree/mscoree.cpp
src/gc/gc.cpp
src/gc/gchandletable.cpp
src/gc/gchandletableimpl.h
src/gc/gcinterface.h
src/gc/handletable.inl
src/gc/objecthandle.h
src/inc/MSCOREE.IDL
src/inc/utilcode.h
src/jit/codegenarm.cpp
src/jit/codegenarmarch.cpp
src/jit/codegenxarch.cpp
src/jit/compiler.h
src/jit/gentree.cpp
src/jit/importer.cpp
src/jit/instr.cpp
src/jit/jit.h
src/jit/lclvars.cpp
src/jit/morph.cpp
src/mscorlib/shared/Interop/Unix/System.Native/Interop.Stat.cs
src/mscorlib/shared/System/CharEnumerator.cs
src/mscorlib/shared/System/Security/SecurityException.cs
src/mscorlib/shared/System/Text/StringBuilder.cs
src/mscorlib/src/System/Collections/Generic/List.cs
src/mscorlib/src/System/Delegate.cs
src/mscorlib/src/System/Runtime/InteropServices/Marshal.cs
src/mscorlib/src/System/ThrowHelper.cs
src/pal/inc/pal.h
src/pal/inc/rt/palrt.h
src/pal/src/CMakeLists.txt
src/pal/src/config.h.in
src/pal/src/configure.cmake
src/pal/src/include/pal/dbgmsg.h
src/pal/src/include/pal/numa.h [new file with mode: 0644]
src/pal/src/init/pal.cpp
src/pal/src/map/virtual.cpp
src/pal/src/misc/sysinfo.cpp
src/pal/src/numa/numa.cpp [new file with mode: 0644]
src/pal/src/thread/process.cpp
src/strongname/api/strongnamecoreclr.cpp
src/utilcode/util.cpp
src/vm/appdomain.cpp
src/vm/argdestination.h
src/vm/callingconvention.h
src/vm/ceemain.cpp
src/vm/compile.cpp
src/vm/corhost.cpp
src/vm/ecalllist.h
src/vm/gcenv.os.cpp
src/vm/gchandleutilities.h
src/vm/gcheaputilities.cpp
src/vm/hosting.cpp
src/vm/i386/asmhelpers.S
src/vm/i386/cgenx86.cpp
src/vm/i386/gmsx86.cpp
src/vm/object.cpp
src/vm/threads.h
src/vm/util.cpp
tests/arm64/Tests.lst
tests/issues.targets
tests/src/Common/build_against_pkg_dependencies/project.json
tests/src/Common/netcoreapp/project.json
tests/src/Common/targeting_pack_ref/project.json
tests/src/Common/test_dependencies/project.json
tests/src/Common/test_runtime/project.json
tests/src/CoreMangLib/cti/system/delegate/delegategethashcode1.cs
tests/src/GC/Stress/Framework/ReliabilityConfiguration.cs
tests/src/GC/Stress/Framework/ReliabilityFramework.cs
tests/src/Interop/StringMarshalling/LPSTR/CMakeLists.txt [changed mode: 0755->0644]
tests/src/Interop/StringMarshalling/LPSTR/LPSTRTest.cs [changed mode: 0755->0644]
tests/src/Interop/StringMarshalling/LPSTR/LPSTRTest.csproj [changed mode: 0755->0644]
tests/src/Interop/StringMarshalling/LPSTR/LPSTRTestNative.cpp [changed mode: 0755->0644]
tests/src/Interop/StringMarshalling/LPSTR/PinvokeDef.cs [changed mode: 0755->0644]
tests/src/Interop/StringMarshalling/LPTSTR/CMakeLists.txt [changed mode: 0755->0644]
tests/src/Interop/StringMarshalling/LPTSTR/LPTSTRTest.cs [changed mode: 0755->0644]
tests/src/Interop/StringMarshalling/LPTSTR/LPTSTRTestNative.cpp [changed mode: 0755->0644]
tests/src/Interop/StringMarshalling/LPTSTR/LPTSTRTestPInvokeDef.cs [changed mode: 0755->0644]
tests/src/JIT/CheckProjects/CheckProjects.cs
tests/src/JIT/Regression/JitBlue/GitHub_10940/GitHub_10940.cs [new file with mode: 0644]
tests/src/JIT/Regression/JitBlue/GitHub_10940/GitHub_10940.csproj [new file with mode: 0644]
tests/src/JIT/config/benchmark+roslyn/project.json
tests/src/JIT/config/benchmark+serialize/project.json
tests/src/JIT/config/benchmark/project.json
tests/src/JIT/jit64/hfa/main/dll/hfa_native.h
tests/src/Regressions/coreclr/GitHub_7685/test7685.cs
tests/src/TestWrappersConfig/project.json
tests/src/baseservices/multidimmarray/rank1array.il [new file with mode: 0644]
tests/src/baseservices/multidimmarray/rank1array.ilproj [new file with mode: 0644]
tests/src/performance/linkbench/assets/MusicStore/MusicStoreReflection.xml [new file with mode: 0644]
tests/src/performance/linkbench/assets/Roslyn/RoslynRoots.txt [new file with mode: 0644]
tests/src/performance/linkbench/assets/Roslyn/RoslynRoots.xml [new file with mode: 0644]
tests/src/performance/linkbench/assets/Roslyn/illinkcsproj [new file with mode: 0644]
tests/src/performance/linkbench/linkbench.cs [new file with mode: 0644]
tests/src/performance/linkbench/linkbench.csproj [new file with mode: 0644]
tests/src/performance/linkbench/scripts/build.cmd [new file with mode: 0644]
tests/src/performance/linkbench/scripts/clone.cmd [new file with mode: 0644]
tests/src/performance/linkbench/scripts/empty.cmd [new file with mode: 0644]
tests/src/performance/linkbench/scripts/getcert.cmd [new file with mode: 0644]
tests/src/performance/project.json
tests/src/readytorun/tests/fieldgetter.il [moved from tests/src/readytorun/fieldgetter.il with 100% similarity]
tests/src/readytorun/tests/fieldgetter.ilproj [moved from tests/src/readytorun/fieldgetter.ilproj with 100% similarity]
tests/src/readytorun/tests/generics.cs [moved from tests/src/readytorun/generics.cs with 100% similarity]
tests/src/readytorun/tests/generics.csproj [moved from tests/src/readytorun/generics.csproj with 100% similarity]
tests/src/readytorun/tests/genericsload/callgenericctor.cs [moved from tests/src/readytorun/genericsload/callgenericctor.cs with 100% similarity]
tests/src/readytorun/tests/genericsload/callgenericctor.csproj [moved from tests/src/readytorun/genericsload/callgenericctor.csproj with 100% similarity]
tests/src/readytorun/tests/genericsload/genericslib.il [moved from tests/src/readytorun/genericsload/genericslib.il with 100% similarity]
tests/src/readytorun/tests/genericsload/genericslib.ilproj [moved from tests/src/readytorun/genericsload/genericslib.ilproj with 100% similarity]
tests/src/readytorun/tests/genericsload/usegenericfield.cs [moved from tests/src/readytorun/genericsload/usegenericfield.cs with 100% similarity]
tests/src/readytorun/tests/genericsload/usegenericfield.csproj [moved from tests/src/readytorun/genericsload/usegenericfield.csproj with 100% similarity]
tests/src/readytorun/tests/main.cs [moved from tests/src/readytorun/main.cs with 100% similarity]
tests/src/readytorun/tests/mainv1.csproj [moved from tests/src/readytorun/mainv1.csproj with 100% similarity]
tests/src/readytorun/tests/mainv2.csproj [moved from tests/src/readytorun/mainv2.csproj with 100% similarity]
tests/src/readytorun/tests/test.cs [moved from tests/src/readytorun/test.cs with 100% similarity]
tests/src/readytorun/tests/testv1/test.csproj [moved from tests/src/readytorun/testv1/test.csproj with 100% similarity]
tests/src/readytorun/tests/testv2/test.csproj [moved from tests/src/readytorun/testv2/test.csproj with 100% similarity]
tests/testsFailingOutsideWindows.txt

diff --git a/Documentation/design-docs/core-minidump-generation.md b/Documentation/design-docs/core-minidump-generation.md
new file mode 100644 (file)
index 0000000..f099610
--- /dev/null
@@ -0,0 +1,80 @@
+# Introduction #
+
+Core dump generation on Linux and other non-Windows platforms has several challenges. Dumps can be very large and the default name/location of a dump is not consistent across all our supported platforms.  The size of a full core dumps can be controlled somewhat with the "coredump_filter" file/flags but even with the smallest settings may be still too large and may not contain all the managed state needed for debugging. By default, some platforms use _core_ as the name and place the core dump in the current directory from where the program is launched; others add the _pid_ to the name. Configuring the core name and location requires superuser permission. Requiring superuser to make this consistent is not a satisfactory option.
+
+Our goal is to generate core dumps that are on par with WER (Windows Error Reporting) crash dumps on any supported Linux platform. To the very least we want to enable the following: 
+- automatic generation of minimal size minidumps that can be automatically uploaded to a server for triage. The quality and quantity of the information contained in the dump should be on par with the information contained in a traditional Windows mini-dump.
+- simple configurabilty by the user (not _su_!). 
+
+Our solution at this time is to intercept any unhandled exception in the PAL layer of the runtime and have coreclr itself trigger and generate a "mini" core dump. 
+
+# Design #
+
+We looked at the existing technologies like Breakpad and its derivatives (e.g.: an internal MS version called _msbreakpad_ from the SQL team....). Breakpad generates Windows minidumps but they are not compatible with existing tools like Windbg, etc. Msbreakpad even more so. There is a minidump to Linux core conversion utility but it seems like a wasted extra step. _Breakpad_ does allow the minidump to be generated in-process inside the signal handlers. It restricts the APIs to what was allowed in a "async" signal handler (like SIGSEGV) and has a small subset of the C++ runtime that was also similarly constrained. We also need to add the set of memory regions for the "managed" state which requires loading and using the _DAC_'s (*) enumerate memory interfaces. Loading modules is not allowed in an async signal handler but forking/execve is allowed so launching an utility that loads the _DAC_, enumerates the list of memory regions and writes the dump is the only reasonable option. It would also allow uploading the dump to a server too.
+
+\* The _DAC_ is a special build of parts of the coreclr runtime that allows inspection of the runtime's managed state (stacks, variables, GC state heaps) out of context. One of the many interfaces it provides is [ICLRDataEnumMemoryRegions](https://github.com/dotnet/coreclr/blob/master/src/debug/daccess/dacimpl.h) which enumerates all the managed state a minidump would require to enable a fuitful debugging experience.
+
+_Breakpad_ could have still been used out of context in the generation utility but there seemed no value to their Windows-like minidump format when it would have to be converted to the native Linux core format away because in most scenarios using the platform tools like _lldb_ is necessary. It also adds a coreclr build dependency on Google's _Breakpad_ or SQL's _msbreakpad_ source repo. The only advantage is that the breakpad minidumps may be a little smaller because minidumps memory regions are byte granule and Linux core memory regions need to be page granule.
+
+# Implementation Details #
+
+### Linux ###
+
+Core dump generation is triggered anytime coreclr is going to abort (via [PROCAbort()](https://github.com/dotnet/coreclr/blob/master/src/pal/src/include/pal/process.h)) the process because of an unhandled managed exception or an async signal like SIGSEGV, SIGILL, SIGFPE, etc. The _createdump_ utility is located in the same directory as libcoreclr.so and is launched with fork/execve. The child _createdump_ process is given permission to ptrace and access to the various special /proc files of the crashing process which waits until _createdump_ finishes.
+
+The _createdump_ utility starts by using ptrace to enumerate and suspend all the threads in the target process. The process and thread info (status, registers, etc.) is gathered. The auxv entries and _DSO_ info is enumerated. _DSO_ is the in memory data structures that described the shared modules loaded by the target. This memory is needed in the dump by gdb and lldb to enumerate the shared modules loaded and access their symbols. The module memory mappings are gathered from /proc/$pid/maps. None of the program or shared modules memory regions are explicitly added to dump's memory regions. The _DAC_ is loaded and the enumerate memory region interfaces are used to build the memory regions list just like on Windows. The threads stacks and one page of code around the IP are added. The byte sized regions are rounded up to pages and then combined into contagious regions.
+
+After all the process crash information has been gathered, the ELF core dump with written. The main ELF header created and written. The PT\_LOAD note section is written one entry for each memory region in the dump. The process info, auxv data and NT_FILE entries are written to core. The NT\_FILE entries are built from module memory mappings from /proc/$pid/maps. The threads state and registers are then written. Lastly all the memory regions gather above by the _DAC_, etc. are read from the target process and written to the core dump. All the threads in the target process are resumed and _createdump_ terminates.
+
+**Severe memory corruption**
+
+As long as control can making it to the signal/abort handler and the fork/execve of the utility succeeds then the _DAC_ memory enumeration interfaces can handle corruption to a point; the resulting dump just may not have enough managed state to be useful. We could investigate detecting this case and writing a full core dump.
+
+**Stack overflow exception**
+
+Like the severe memory corruption case, if the signal handler (`SIGSEGV`) gets control it can detect most stack overflow cases and does trigger a core dump. There are still many cases where this doesn't happen and the OS just terminates the process.
+
+### FreeBSD/OpenBSD/NetBSD ###
+
+There will be some differences gathering the crash information but these platforms still use ELF format core dumps so that part of the utility should be much different. The mechanism used for Linux to give _createdump_ permission to use ptrace and access the /proc doesn't exists on these platforms.
+
+### OS X ###
+
+Gathering the crash information on OS X will be quite a bit different than Linux and the core dump will be written in the Mach-O format instead of ELF. The OS X support currently has not been implemented.
+
+# Configuration/Policy #
+
+Any configuration or policy is set with environment variables which are passed as options to the _createdump_ utility.
+
+Environment variables supported:
+
+- `COMPlus_DbgEnableMiniDump`: if set to "1", enables this core dump generation. The default is NOT to generate a dump.
+- `COMPlus_DbgMiniDumpType`: if set to "1" generates _MiniDumpNormal_, "2" _MiniDumpWithPrivateReadWriteMemory_, "3" _MiniDumpFilterTriage_. Default is _MiniDumpNormal_.
+- `COMPlus_DbgMiniDumpName`: if set, use as the template to create the dump path and file name. The pid can be placed in the name with %d. The default is _/tmp/coredump.%d_.
+- `COMPlus_CreateDumpDiagnostics`: if set to "1", enables the _createdump_ utilities diagnostic messages (TRACE macro).
+
+(Please refer to MSDN for the meaning of the [minidump enum values](https://msdn.microsoft.com/en-us/library/windows/desktop/ms680519(v=vs.85).aspx) reported above)
+
+**Utility command line options**:
+
+    createdump [options] pid
+    -f, --name - dump path and file name. The pid can be placed in the name with %d. The default is "/tmp/coredump.%d"
+    -n, --normal - create minidump (default).
+    -h, --withheap - create minidump with heap.
+    -m, --micro - create triage minidump.
+    -d, --diag - enable diagnostic messages.
+
+# Testing #
+
+The test plan is to modify the SOS tests in the (still) private debuggertests repo to trigger and use the core minidumps generated. Debugging managed core dumps on Linux is not supported by _mdbg_ at this time until we have a ELF core dump reader so only the SOS tests (which use _lldb_ on Linux) will be modified.
+
+# Open Issues #
+
+- Do we need a full memory dump option? It would not use the _DAC_ to get the memory regions but all the readable memory from the shared module list. Do we include the shared modules' code? 
+- May need more than just the pid for decorating dump names for docker containers because I think the _pid_ is always 1.
+- Do we need all the memory mappings from `/proc/$pid/maps` in the PT\_LOAD sections even though the memory is not actually in the dump? They have a file offset/size of 0. Full dumps generated by the system or _gdb_ do have these un-backed regions.
+- Don't know how to get the proper size/range of the non-main thread stacks. Currently uses 4 pages around the stack pointer. The main thread has a memory region in `/proc/$pid/maps`.
+- There is no way to get the signal number, etc. that causes the abort from the _createdump_ utility using _ptrace_ or a /proc file. It would have to be passed from CoreCLR on the command line.
+- Do we need the "dynamic" sections of each shared module in the core dump? It is part of the "link_map" entry enumerated when gathering the _DSO_ information.
+- There may be more versioning and/or build id information needed to be added to the dump.
+- It is unclear exactly what cases stack overflow does not get control in the signal handler and when the OS just aborts the process.
diff --git a/Linked b/Linked
new file mode 100644 (file)
index 0000000..675a79b
Binary files /dev/null and b/Linked differ
index 21dd9f7..378ce52 100644 (file)
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ that quickly points you to [.NET Core Tutorials](https://docs.microsoft.com/en-u
 .NET Core is best thought of as 'agile .NET'.   Generally speaking it is the same as 
 the [Desktop .NET Framework](https://en.wikipedia.org/wiki/.NET_Framework)
 distributed as part of the Windows operating system, but it is a cross platform 
-(Windows, Linux, OSX) and cross architecture (x86, x64, arm) subset that can be deployed
+(Windows, Linux, macOS) and cross architecture (x86, x64, arm) subset that can be deployed
 as part of the application (if desired), and thus can be updated quickly to fix bugs or add features.  
 
 ## If You Just Want to Use .NET Core
@@ -116,7 +116,7 @@ You have to be on the particular platform to build that platform.
 
  * [Windows Build Instructions](Documentation/building/windows-instructions.md)
  * [Linux Build Instructions](Documentation/building/linux-instructions.md)
- * [OSX Build Instructions](Documentation/building/osx-instructions.md)
+ * [macOS Build Instructions](Documentation/building/osx-instructions.md)
  * [FreeBSD Build Instructions](Documentation/building/freebsd-instructions.md) 
  * [NetBSD Build Instructions](Documentation/building/netbsd-instructions.md)
 
diff --git a/Tools-Override/codeOptimization.targets b/Tools-Override/codeOptimization.targets
new file mode 100644 (file)
index 0000000..4db340f
--- /dev/null
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <UsingTask TaskName="ZipFileExtractToDirectory" AssemblyFile="$(BuildToolsTaskDir)Microsoft.DotNet.Build.Tasks.dll"/>
+
+  <PropertyGroup>
+    <OptimizationDataVersion Condition="'$(OptimizationDataVersion)'==''">2.0.0-rc-61101-16</OptimizationDataVersion>
+    <OptimizationDataPackageName Condition="'$(OptimizationDataPackageName)'==''">RoslynDependencies.OptimizationData</OptimizationDataPackageName>
+    <OptimizationDataDir Condition="'$(OptimizationDataDir)'==''">$(ToolsDir)OptimizationData/</OptimizationDataDir>
+    <RestoreDefaultOptimizationDataPackage Condition="'$(RestoreDefaultOptimizationDataPackage)'==''">true</RestoreDefaultOptimizationDataPackage>
+    <UsePartialNGENOptimization Condition="'$(UsePartialNGENOptimization)'==''">true</UsePartialNGENOptimization>
+  </PropertyGroup>
+
+  <!-- If IBC data hasn't been merged with the IL yet, preprocess it first -->
+  <Target Name="PreProcessIBCData"
+          BeforeTargets="OptimizeWithTrainingData"
+          DependsOnTargets="ResolveOptionalTools"
+          Condition="'$(OS)'=='Windows_NT' and '$(EnableProfileGuidedOptimization)'=='true' and Exists('$(OptimizationDataDir)$(AssemblyName).dll')">
+
+    <!-- Find IBCMerge as a resolved optional tool. -->
+    <PropertyGroup>
+      <IBCMergeToolPath Condition="'%(Filename)%(Extension)'=='ibcmerge.exe'">@(ResolvedOptionalToolReferences)</IBCMergeToolPath>
+    </PropertyGroup>
+
+    <!-- Enumerate the various files that need merging -->
+    <PropertyGroup>
+      <InputAssemblyFile>$(OptimizationDataDir)$(AssemblyName).dll</InputAssemblyFile>
+      <TargetOptimizationDataFile>$(OptimizationDataDir)$(AssemblyName).pgo</TargetOptimizationDataFile>
+    </PropertyGroup>
+    <ItemGroup>
+      <RawOptimizationDataFiles Include="$(OptimizationDataDir)$(AssemblyName)*.ibc" />
+    </ItemGroup>
+
+    <!-- Merge the optimization data into the source DLL -->
+    <Exec Command="$(IBCMergeToolPath) -q -f -delete -mo $(InputAssemblyFile) @(RawOptimizationDataFiles, ' ')" />
+
+    <!-- Verify that the optimization data has been merged -->
+    <Exec Command="$(IBCMergeToolPath) -mi $(InputAssemblyFile)" />
+
+    <!-- Save the module as *.pgo to match the convention expected in target OptimizeWithTrainingData -->
+    <Copy SourceFiles="$(InputAssemblyFile)" DestinationFiles="$(TargetOptimizationDataFile)" />
+  </Target>
+
+  <!-- We should only run this target on Windows and only if EnableProfileGuidedOptimization is set and we have training data -->
+  <Target Name="OptimizeWithTrainingData"
+          AfterTargets="AfterBuild"
+          BeforeTargets="CopyFilesToOutputDirectory"
+          DependsOnTargets="ResolveOptionalTools"
+          Condition="'$(OS)'=='Windows_NT' and '$(EnableProfileGuidedOptimization)'=='true' and Exists('$(OptimizationDataDir)$(AssemblyName).pgo')">
+
+    <!-- Find IBCMerge as a resolved optional tool. -->
+    <PropertyGroup>
+      <IBCMergeToolPath Condition="'%(Filename)%(Extension)'=='ibcmerge.exe'">@(ResolvedOptionalToolReferences)</IBCMergeToolPath>
+    </PropertyGroup>
+
+    <PropertyGroup>
+      <OptimizedAssemblyDir>$(IntermediateOutputPath)/OptimizedAssembly</OptimizedAssemblyDir>
+      <OptimizedAssemblyFile>$(OptimizedAssemblyDir)/$(AssemblyName).dll</OptimizedAssemblyFile>
+    </PropertyGroup>
+
+    <!-- Customize IBCMerge's arguments depending on input props -->
+    <PropertyGroup>
+      <IBCMergeArguments>-q -f -mo $(OptimizedAssemblyFile) -incremental $(OptimizationDataDir)$(AssemblyName).pgo</IBCMergeArguments>
+      <IBCMergeArguments Condition="$(UsePartialNGENOptimization)">$(IBCMergeArguments) -partialNGEN -minify</IBCMergeArguments>
+    </PropertyGroup>
+
+    <!-- Copy the compiled assembly into a folder for further processing -->
+    <MakeDir Directories="$(OptimizedAssemblyDir)" />
+    <Copy SourceFiles="@(IntermediateAssembly)" DestinationFolder="$(OptimizedAssemblyDir)" />
+
+    <!-- Apply optimization data to the compiled assembly -->
+    <Exec Command="$(IBCMergeToolPath) $(IBCMergeArguments)" />
+
+    <!-- Verify that the optimization data has been applied -->
+    <Exec Command="$(IBCMergeToolPath) -mi $(OptimizedAssemblyFile)" />
+
+    <!-- We need to make sure that the assembly that gets packaged is the one with the optimization data -->
+    <ItemGroup>
+      <IntermediateAssembly Remove="@(IntermediateAssembly)"/>
+      <IntermediateAssembly Include="$(OptimizedAssemblyDir)/$(AssemblyName).dll"/>
+    </ItemGroup>
+  </Target>
+
+  <!-- We need the OptimizationData package in order to be able to optimize the assembly -->
+  <Target Name="RestoreOptimizationDataPackage"
+          BeforeTargets="Sync"
+          Condition="'$(EnableProfileGuidedOptimization)'=='true' and '$(RestoreDefaultOptimizationDataPackage)'=='true' and !Exists('$(OptimizationDataDir)project.json')">
+
+    <!-- Dynamically create a project.json file used to restore the optimization data-->
+    <Message Text="Generating project.json for optimization data"  Importance="low" />
+    <ItemGroup>
+      <_OptimizationDataJsonLine Include="{&quot;dependencies&quot;: {" />
+      <_OptimizationDataJsonLine Include="&quot;$(OptimizationDataPackageName)&quot; : &quot;$(OptimizationDataVersion)&quot; " />
+      <_OptimizationDataJsonLine Include="},&quot;frameworks&quot;: {&quot;netcoreapp1.0&quot;: {},&quot;net46&quot;: {}}}"/>
+    </ItemGroup>
+    
+    <PropertyGroup>
+      <OptimizationDataProjectJson>$(OptimizationDataDir)project.json</OptimizationDataProjectJson>
+      <OptimizationDataNuGetFeed Condition="'$(OptimizationDataNuGetFeed)'==''">https:%2F%2Fdotnet.myget.org/F/roslyn/api/v3/index.json</OptimizationDataNuGetFeed>
+    </PropertyGroup>
+
+    <MakeDir Directories="$(OptimizationDataDir)" ContinueOnError="true" />
+    <WriteLinesToFile File="$(OptimizationDataProjectJson)" Lines="@(_OptimizationDataJsonLine)" Overwrite="true" />
+
+    <!-- Restore the OptimizationData package -->
+    <Exec Command="$(DnuRestoreCommand) $(OptimizationDataProjectJson) --source $(OptimizationDataNuGetFeed)"
+          StandardOutputImportance="Low"/>
+
+    <!-- Copy the restored files into a more accessible location -->
+    <ItemGroup>
+      <_OptimizationDataFiles Include="$(PackagesDir)/$(OptimizationDataPackageName)/$(OptimizationDataVersion)/content/OptimizationData/*.pgo" />
+    </ItemGroup>
+
+    <Copy SourceFiles="@(_OptimizationDataFiles)"
+          DestinationFiles="@(_OptimizationDataFiles->'$(OptimizationDataDir)%(Filename)%(Extension)')"
+          SkipUnchangedFiles="true"
+          ContinueOnError="true"/>
+  </Target>
+</Project>
\ No newline at end of file
index 158c1b9..c975171 100644 (file)
       "values": [ true, false ],
       "defaultValue": false
     },
+    "RestoreDefaultOptimizationDataPackage": {
+      "description": "Instructs BuildTools to restore the default OptimizationData package.",
+      "valueType": "property",
+      "values": [ true, false ],
+      "defaultValue": true
+    },
+    "UsePartialNGENOptimization": {
+      "description": "Adds the `-partialNGEN -minify` arguments when invoking IBCMerge.",
+      "valueType": "property",
+      "values": [ true, false ],
+      "defaultValue": true
+    },
     "OptimizationDataDir": {
       "description": "Sets the path where the build should look for IBC profile data.",
       "valueType": "property",
           "MsBuildLog": "default",
           "MsBuildWrn": "default",
           "MsBuildErr": "default",
-          "MsBuildEventLogging": "default"
+          "MsBuildEventLogging": "default",
+          "RestoreDefaultOptimizationDataPackage": "false",
+          "UsePartialNGENOptimization": "false"
         }
       }
     },
index cfc5208..1bf3da9 100644 (file)
@@ -55,7 +55,7 @@ SET( HAVE_COMPATIBLE_ASIN_EXITCODE
      CACHE STRING "Result from TRY_RUN" FORCE)
 
 SET( HAVE_COMPATIBLE_POW_EXITCODE
-     1
+     0
      CACHE STRING "Result from TRY_RUN" FORCE)
 
 SET( HAVE_VALID_NEGATIVE_INF_POW_EXITCODE
index 9739380..c06c465 100644 (file)
@@ -1,18 +1,18 @@
 <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <!-- Source of truth for dependency tooling: the commit hash of the dotnet/versions master branch as of the last auto-upgrade. -->
   <PropertyGroup>
-    <CoreFxCurrentRef>af313dccb7aff26364a85300da16d39a783c86cd</CoreFxCurrentRef>
-    <CoreClrCurrentRef>af313dccb7aff26364a85300da16d39a783c86cd</CoreClrCurrentRef>
+    <CoreFxCurrentRef>947e90b41c30a1f0a906f8d996443233c2ceedf4</CoreFxCurrentRef>
+    <CoreClrCurrentRef>947e90b41c30a1f0a906f8d996443233c2ceedf4</CoreClrCurrentRef>
   </PropertyGroup>
 
   <!-- Auto-upgraded properties for each build info dependency. -->
   <PropertyGroup>
-    <CoreFxExpectedPrerelease>preview1-25214-03</CoreFxExpectedPrerelease>
+    <CoreFxExpectedPrerelease>preview1-25221-01</CoreFxExpectedPrerelease>
   </PropertyGroup>
 
   <!-- Full package version strings that are used in other parts of the build. -->
   <PropertyGroup>
-    <CoreClrPackageVersion>2.0.0-preview1-25215-03</CoreClrPackageVersion>
+    <CoreClrPackageVersion>2.0.0-preview1-25221-01</CoreClrPackageVersion>
     <XunitPackageVersion>2.2.0-beta2-build3300</XunitPackageVersion>
   </PropertyGroup>
 
index cb454b3..5a88ff1 100644 (file)
@@ -69,7 +69,9 @@ def static getOSGroup(def os) {
                     //Do this here to remove the origin but at the front of the branch name as this is a problem for BenchView
                     //we have to do it all as one statement because cmd is called each time and we lose the set environment variable
                     batchFile("if [%GIT_BRANCH:~0,7%] == [origin/] (set GIT_BRANCH_WITHOUT_ORIGIN=%GIT_BRANCH:origin/=%) else (set GIT_BRANCH_WITHOUT_ORIGIN=%GIT_BRANCH%)\n" +
-                    "py \"%WORKSPACE%\\Microsoft.BenchView.JSONFormat\\tools\\submission-metadata.py\" --name \"${benchViewName}\" --user \"dotnet-bot@microsoft.com\"\n" +
+                    "set BENCHVIEWNAME=${benchViewName}\n" +
+                    "set BENCHVIEWNAME=%BENCHVIEWNAME:\"=%\n" +
+                    "py \"%WORKSPACE%\\Microsoft.BenchView.JSONFormat\\tools\\submission-metadata.py\" --name \"%BENCHVIEWNAME%\" --user \"dotnet-bot@microsoft.com\"\n" +
                     "py \"%WORKSPACE%\\Microsoft.BenchView.JSONFormat\\tools\\build.py\" git --branch %GIT_BRANCH_WITHOUT_ORIGIN% --type ${runType}")
                     batchFile("py \"%WORKSPACE%\\Microsoft.BenchView.JSONFormat\\tools\\machinedata.py\"")
                     batchFile("set __TestIntermediateDir=int&&build.cmd ${configuration} ${architecture}")
@@ -162,6 +164,8 @@ def static getOSGroup(def os) {
                     //Do this here to remove the origin but at the front of the branch name as this is a problem for BenchView
                     //we have to do it all as one statement because cmd is called each time and we lose the set environment variable
                     batchFile("if [%GIT_BRANCH:~0,7%] == [origin/] (set GIT_BRANCH_WITHOUT_ORIGIN=%GIT_BRANCH:origin/=%) else (set GIT_BRANCH_WITHOUT_ORIGIN=%GIT_BRANCH%)\n" +
+                    "set BENCHVIEWNAME=${benchViewName}\n" +
+                    "set BENCHVIEWNAME=%BENCHVIEWNAME:\"=%\n" +
                     "py \"%WORKSPACE%\\Microsoft.BenchView.JSONFormat\\tools\\submission-metadata.py\" --name \"${benchViewName}\" --user \"dotnet-bot@microsoft.com\"\n" +
                     "py \"%WORKSPACE%\\Microsoft.BenchView.JSONFormat\\tools\\build.py\" git --branch %GIT_BRANCH_WITHOUT_ORIGIN% --type ${runType}")
                     batchFile("py \"%WORKSPACE%\\Microsoft.BenchView.JSONFormat\\tools\\machinedata.py\"")
diff --git a/src/ToolBox/superpmi/superpmi-shared/coreclrcommoncallbacks.h b/src/ToolBox/superpmi/superpmi-shared/coreclrcommoncallbacks.h
new file mode 100644 (file)
index 0000000..ca542fb
--- /dev/null
@@ -0,0 +1,20 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#ifndef _CoreClrCommonCallbacks
+#define _CoreClrCommonCallbacks
+
+#include "runtimedetails.h"
+
+IExecutionEngine* IEE_t();
+HRESULT GetCORSystemDirectory(LPWSTR pbuffer, DWORD cchBuffer, DWORD* pdwlength);
+LPVOID EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes);
+BOOL EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem);
+void* GetCLRFunction(LPCSTR functionName);
+
+typedef LPVOID (*pfnEEHeapAllocInProcessHeap)(DWORD dwFlags, SIZE_T dwBytes);
+typedef BOOL (*pfnEEHeapFreeInProcessHeap)(DWORD dwFlags, LPVOID lpMem);
+
+#endif
index e9a42d8..14a55b5 100644 (file)
@@ -7,14 +7,11 @@
 #include "coreclrcallbacks.h"
 #include "iexecutionengine.h"
 
-typedef LPVOID(__stdcall* pfnEEHeapAllocInProcessHeap)(DWORD dwFlags, SIZE_T dwBytes);
-typedef BOOL(__stdcall* pfnEEHeapFreeInProcessHeap)(DWORD dwFlags, LPVOID lpMem);
-
 CoreClrCallbacks*           original_CoreClrCallbacks         = nullptr;
 pfnEEHeapAllocInProcessHeap original_EEHeapAllocInProcessHeap = nullptr;
 pfnEEHeapFreeInProcessHeap  original_EEHeapFreeInProcessHeap  = nullptr;
 
-IExecutionEngine* STDMETHODCALLTYPE IEE_t()
+IExecutionEngine* IEE_t()
 {
     interceptor_IEE* iee = new interceptor_IEE();
     iee->original_IEE    = original_CoreClrCallbacks->m_pfnIEE();
@@ -29,21 +26,21 @@ HRESULT STDMETHODCALLTYPE GetCORSystemDirectory(LPWSTR pbuffer, DWORD cchBuffer,
 }
 */
 
-LPVOID STDMETHODCALLTYPE EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes)
+LPVOID EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes)
 {
     if (original_EEHeapAllocInProcessHeap == nullptr)
         __debugbreak();
     return original_EEHeapAllocInProcessHeap(dwFlags, dwBytes);
 }
 
-BOOL STDMETHODCALLTYPE EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem)
+BOOL EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem)
 {
     if (original_EEHeapFreeInProcessHeap == nullptr)
         __debugbreak();
     return original_EEHeapFreeInProcessHeap(dwFlags, lpMem);
 }
 
-void* STDMETHODCALLTYPE GetCLRFunction(LPCSTR functionName)
+void* GetCLRFunction(LPCSTR functionName)
 {
     if (strcmp(functionName, "EEHeapAllocInProcessHeap") == 0)
     {
index 1d4b801..a525742 100644 (file)
@@ -6,14 +6,8 @@
 #ifndef _CoreClrCallbacks
 #define _CoreClrCallbacks
 
-#include "runtimedetails.h"
-
-IExecutionEngine* STDMETHODCALLTYPE IEE_t();
-HRESULT STDMETHODCALLTYPE GetCORSystemDirectory(LPWSTR pbuffer, DWORD cchBuffer, DWORD* pdwlength);
-LPVOID STDMETHODCALLTYPE EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes);
-BOOL STDMETHODCALLTYPE EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem);
-void* STDMETHODCALLTYPE GetCLRFunction(LPCSTR functionName);
+#include "coreclrcommoncallbacks.h"
 
 extern CoreClrCallbacks* original_CoreClrCallbacks;
 
-#endif
\ No newline at end of file
+#endif
index e9a42d8..14a55b5 100644 (file)
@@ -7,14 +7,11 @@
 #include "coreclrcallbacks.h"
 #include "iexecutionengine.h"
 
-typedef LPVOID(__stdcall* pfnEEHeapAllocInProcessHeap)(DWORD dwFlags, SIZE_T dwBytes);
-typedef BOOL(__stdcall* pfnEEHeapFreeInProcessHeap)(DWORD dwFlags, LPVOID lpMem);
-
 CoreClrCallbacks*           original_CoreClrCallbacks         = nullptr;
 pfnEEHeapAllocInProcessHeap original_EEHeapAllocInProcessHeap = nullptr;
 pfnEEHeapFreeInProcessHeap  original_EEHeapFreeInProcessHeap  = nullptr;
 
-IExecutionEngine* STDMETHODCALLTYPE IEE_t()
+IExecutionEngine* IEE_t()
 {
     interceptor_IEE* iee = new interceptor_IEE();
     iee->original_IEE    = original_CoreClrCallbacks->m_pfnIEE();
@@ -29,21 +26,21 @@ HRESULT STDMETHODCALLTYPE GetCORSystemDirectory(LPWSTR pbuffer, DWORD cchBuffer,
 }
 */
 
-LPVOID STDMETHODCALLTYPE EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes)
+LPVOID EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes)
 {
     if (original_EEHeapAllocInProcessHeap == nullptr)
         __debugbreak();
     return original_EEHeapAllocInProcessHeap(dwFlags, dwBytes);
 }
 
-BOOL STDMETHODCALLTYPE EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem)
+BOOL EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem)
 {
     if (original_EEHeapFreeInProcessHeap == nullptr)
         __debugbreak();
     return original_EEHeapFreeInProcessHeap(dwFlags, lpMem);
 }
 
-void* STDMETHODCALLTYPE GetCLRFunction(LPCSTR functionName)
+void* GetCLRFunction(LPCSTR functionName)
 {
     if (strcmp(functionName, "EEHeapAllocInProcessHeap") == 0)
     {
index 1d4b801..a525742 100644 (file)
@@ -6,14 +6,8 @@
 #ifndef _CoreClrCallbacks
 #define _CoreClrCallbacks
 
-#include "runtimedetails.h"
-
-IExecutionEngine* STDMETHODCALLTYPE IEE_t();
-HRESULT STDMETHODCALLTYPE GetCORSystemDirectory(LPWSTR pbuffer, DWORD cchBuffer, DWORD* pdwlength);
-LPVOID STDMETHODCALLTYPE EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes);
-BOOL STDMETHODCALLTYPE EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem);
-void* STDMETHODCALLTYPE GetCLRFunction(LPCSTR functionName);
+#include "coreclrcommoncallbacks.h"
 
 extern CoreClrCallbacks* original_CoreClrCallbacks;
 
-#endif
\ No newline at end of file
+#endif
index 60018b8..85ceaa2 100644 (file)
@@ -7,14 +7,11 @@
 #include "coreclrcallbacks.h"
 #include "iexecutionengine.h"
 
-typedef LPVOID(__stdcall* pfnEEHeapAllocInProcessHeap)(DWORD dwFlags, SIZE_T dwBytes);
-typedef BOOL(__stdcall* pfnEEHeapFreeInProcessHeap)(DWORD dwFlags, LPVOID lpMem);
-
 CoreClrCallbacks*           original_CoreClrCallbacks         = nullptr;
 pfnEEHeapAllocInProcessHeap original_EEHeapAllocInProcessHeap = nullptr;
 pfnEEHeapFreeInProcessHeap  original_EEHeapFreeInProcessHeap  = nullptr;
 
-IExecutionEngine* STDMETHODCALLTYPE IEE_t()
+IExecutionEngine* IEE_t()
 {
     interceptor_IEE* iee = new interceptor_IEE();
     iee->original_IEE    = original_CoreClrCallbacks->m_pfnIEE();
@@ -29,17 +26,17 @@ HRESULT STDMETHODCALLTYPE GetCORSystemDirectory(LPWSTR pbuffer, DWORD cchBuffer,
 }
 */
 
-LPVOID STDMETHODCALLTYPE EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes)
+LPVOID EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes)
 {
     return original_EEHeapAllocInProcessHeap(dwFlags, dwBytes);
 }
 
-BOOL STDMETHODCALLTYPE EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem)
+BOOL EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem)
 {
     return original_EEHeapFreeInProcessHeap(dwFlags, lpMem);
 }
 
-void* STDMETHODCALLTYPE GetCLRFunction(LPCSTR functionName)
+void* GetCLRFunction(LPCSTR functionName)
 {
     if (strcmp(functionName, "EEHeapAllocInProcessHeap") == 0)
     {
index 3207bbe..6c4a054 100644 (file)
@@ -6,15 +6,9 @@
 #ifndef _CoreClrCallbacks
 #define _CoreClrCallbacks
 
-#include "runtimedetails.h"
-
-IExecutionEngine* STDMETHODCALLTYPE IEE_t();
-HRESULT STDMETHODCALLTYPE GetCORSystemDirectory(LPWSTR pbuffer, DWORD cchBuffer, DWORD* pdwlength);
-LPVOID STDMETHODCALLTYPE EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes);
-BOOL STDMETHODCALLTYPE EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem);
-void* STDMETHODCALLTYPE GetCLRFunction(LPCSTR functionName);
+#include "coreclrcommoncallbacks.h"
 
 // Added to allow us to persist a copy of the original callbacks
 extern CoreClrCallbacks* original_CoreClrCallbacks;
 
-#endif
\ No newline at end of file
+#endif
index d96e2be..98fbe69 100644 (file)
@@ -8,7 +8,7 @@
 #include "coreclrcallbacks.h"
 #include "iexecutionengine.h"
 
-IExecutionEngine* STDMETHODCALLTYPE IEE_t()
+IExecutionEngine* IEE_t()
 {
     MyIEE* iee = InitIExecutionEngine();
     return iee;
@@ -24,7 +24,7 @@ HRESULT STDMETHODCALLTYPE GetCORSystemDirectory(LPWSTR pbuffer, DWORD cchBuffer,
 
 HANDLE ourHeap = nullptr;
 
-LPVOID STDMETHODCALLTYPE EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes)
+LPVOID EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes)
 {
     if (ourHeap == nullptr)
         ourHeap = HeapCreate(0, 4096, 0);
@@ -39,13 +39,13 @@ LPVOID STDMETHODCALLTYPE EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes)
     return result;
 }
 
-BOOL STDMETHODCALLTYPE EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem)
+BOOL EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem)
 {
     //  return true;
     return HeapFree(ourHeap, dwFlags, lpMem);
 }
 
-void* STDMETHODCALLTYPE GetCLRFunction(LPCSTR functionName)
+void* GetCLRFunction(LPCSTR functionName)
 {
     if (strcmp(functionName, "EEHeapAllocInProcessHeap") == 0)
         return (void*)EEHeapAllocInProcessHeap;
index e43267c..3305779 100644 (file)
@@ -6,13 +6,8 @@
 #ifndef _CoreClrCallbacks
 #define _CoreClrCallbacks
 
-#include "runtimedetails.h"
+#include "coreclrcommoncallbacks.h"
 
-IExecutionEngine* STDMETHODCALLTYPE IEE_t();
-HRESULT STDMETHODCALLTYPE GetCORSystemDirectory(LPWSTR pbuffer, DWORD cchBuffer, DWORD* pdwlength);
-LPVOID STDMETHODCALLTYPE EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes);
-BOOL STDMETHODCALLTYPE EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem);
-void* STDMETHODCALLTYPE GetCLRFunction(LPCSTR functionName);
 CoreClrCallbacks* InitCoreClrCallbacks();
 
-#endif
\ No newline at end of file
+#endif
index ea4e2e7..e3813d4 100644 (file)
@@ -71,7 +71,7 @@ class HostEnvironment
     // The list of paths to the assemblies that will be trusted by CoreCLR
     StringBuffer m_tpaList;
 
-    ICLRRuntimeHost2* m_CLRRuntimeHost;
+    ICLRRuntimeHost4* m_CLRRuntimeHost;
 
     HMODULE m_coreCLRModule;
 
@@ -326,8 +326,8 @@ public:
         return m_hostExeName;
     }
 
-    // Returns the ICLRRuntimeHost2 instance, loading it from CoreCLR.dll if necessary, or nullptr on failure.
-    ICLRRuntimeHost2* GetCLRRuntimeHost() {
+    // Returns the ICLRRuntimeHost4 instance, loading it from CoreCLR.dll if necessary, or nullptr on failure.
+    ICLRRuntimeHost4* GetCLRRuntimeHost() {
         if (!m_CLRRuntimeHost) {
 
             if (!m_coreCLRModule) {
@@ -347,9 +347,9 @@ public:
 
             *m_log << W("Calling GetCLRRuntimeHost(...)") << Logger::endl;
 
-            HRESULT hr = pfnGetCLRRuntimeHost(IID_ICLRRuntimeHost2, (IUnknown**)&m_CLRRuntimeHost);
+            HRESULT hr = pfnGetCLRRuntimeHost(IID_ICLRRuntimeHost4, (IUnknown**)&m_CLRRuntimeHost);
             if (FAILED(hr)) {
-                *m_log << W("Failed to get ICLRRuntimeHost2 interface. ERRORCODE: ") << hr << Logger::endl;
+                *m_log << W("Failed to get ICLRRuntimeHost4 interface. ERRORCODE: ") << hr << Logger::endl;
                 return nullptr;
             }
         }
@@ -405,14 +405,14 @@ bool TryRun(const int argc, const wchar_t* argv[], Logger &log, const bool verbo
 
     // Start the CoreCLR
 
-    ICLRRuntimeHost2 *host = hostEnvironment.GetCLRRuntimeHost();
+    ICLRRuntimeHost4 *host = hostEnvironment.GetCLRRuntimeHost();
     if (!host) {
         return false;
     }
 
     HRESULT hr;
 
-    log << W("Setting ICLRRuntimeHost2 startup flags") << Logger::endl;
+    log << W("Setting ICLRRuntimeHost4 startup flags") << Logger::endl;
 
     // Default startup flags
     hr = host->SetStartupFlags((STARTUP_FLAGS)
@@ -424,7 +424,7 @@ bool TryRun(const int argc, const wchar_t* argv[], Logger &log, const bool verbo
         return false;
     }
 
-    log << W("Starting ICLRRuntimeHost2") << Logger::endl;
+    log << W("Starting ICLRRuntimeHost4") << Logger::endl;
 
     hr = host->Start();
     if (FAILED(hr)) {
@@ -541,15 +541,17 @@ bool TryRun(const int argc, const wchar_t* argv[], Logger &log, const bool verbo
 
     log << W("Unloading the AppDomain") << Logger::endl;
 
-    hr = host->UnloadAppDomain(
+    hr = host->UnloadAppDomain2(
         domainId, 
-        true);                          // Wait until done
+        true,
+        (int *)&exitCode);                          // Wait until done
 
     if (FAILED(hr)) {
         log << W("Failed to unload the AppDomain. ERRORCODE: ") << hr << Logger::endl;
         return false;
     }
 
+    log << W("App domain unloaded exit value = ") << exitCode << Logger::endl;
 
     //-------------------------------------------------------------
 
@@ -568,7 +570,7 @@ bool TryRun(const int argc, const wchar_t* argv[], Logger &log, const bool verbo
 
     // Release the reference to the host
 
-    log << W("Releasing ICLRRuntimeHost2") << Logger::endl;
+    log << W("Releasing ICLRRuntimeHost4") << Logger::endl;
 
     host->Release();
 
index dfbb79c..c65c626 100644 (file)
@@ -47,7 +47,7 @@ class HostEnvironment
     // The list of paths to the assemblies that will be trusted by CoreCLR
     SString m_tpaList;
 
-    ICLRRuntimeHost2* m_CLRRuntimeHost;
+    ICLRRuntimeHost4* m_CLRRuntimeHost;
 
     HMODULE m_coreCLRModule;
 
@@ -298,8 +298,8 @@ public:
         return m_hostExeName;
     }
 
-    // Returns the ICLRRuntimeHost2 instance, loading it from CoreCLR.dll if necessary, or nullptr on failure.
-    ICLRRuntimeHost2* GetCLRRuntimeHost() {
+    // Returns the ICLRRuntimeHost4 instance, loading it from CoreCLR.dll if necessary, or nullptr on failure.
+    ICLRRuntimeHost4* GetCLRRuntimeHost() {
         if (!m_CLRRuntimeHost) {
 
             if (!m_coreCLRModule) {
@@ -319,9 +319,9 @@ public:
 
             *m_log << W("Calling GetCLRRuntimeHost(...)") << Logger::endl;
 
-            HRESULT hr = pfnGetCLRRuntimeHost(IID_ICLRRuntimeHost2, (IUnknown**)&m_CLRRuntimeHost);
+            HRESULT hr = pfnGetCLRRuntimeHost(IID_ICLRRuntimeHost4, (IUnknown**)&m_CLRRuntimeHost);
             if (FAILED(hr)) {
-                *m_log << W("Failed to get ICLRRuntimeHost2 interface. ERRORCODE: ") << Logger::hresult << hr << Logger::endl;
+                *m_log << W("Failed to get ICLRRuntimeHost4 interface. ERRORCODE: ") << Logger::hresult << hr << Logger::endl;
                 return nullptr;
             }
         }
@@ -442,7 +442,7 @@ bool TryRun(const int argc, const wchar_t* argv[], Logger &log, const bool verbo
 
     // Start the CoreCLR
 
-    ICLRRuntimeHost2 *host = hostEnvironment.GetCLRRuntimeHost();
+    ICLRRuntimeHost4 *host = hostEnvironment.GetCLRRuntimeHost();
     if (!host) {
         return false;
     }
@@ -451,7 +451,7 @@ bool TryRun(const int argc, const wchar_t* argv[], Logger &log, const bool verbo
     
     
     STARTUP_FLAGS flags = CreateStartupFlags();
-    log << W("Setting ICLRRuntimeHost2 startup flags") << Logger::endl;
+    log << W("Setting ICLRRuntimeHost4 startup flags") << Logger::endl;
     log << W("Server GC enabled: ") << HAS_FLAG(flags, STARTUP_FLAGS::STARTUP_SERVER_GC) << Logger::endl;
     log << W("Concurrent GC enabled: ") << HAS_FLAG(flags, STARTUP_FLAGS::STARTUP_CONCURRENT_GC) << Logger::endl;
 
@@ -462,7 +462,7 @@ bool TryRun(const int argc, const wchar_t* argv[], Logger &log, const bool verbo
         return false;
     }
 
-    log << W("Starting ICLRRuntimeHost2") << Logger::endl;
+    log << W("Starting ICLRRuntimeHost4") << Logger::endl;
 
     hr = host->Start();
     if (FAILED(hr)) {
@@ -581,15 +581,17 @@ bool TryRun(const int argc, const wchar_t* argv[], Logger &log, const bool verbo
 
     log << W("Unloading the AppDomain") << Logger::endl;
 
-    hr = host->UnloadAppDomain(
+    hr = host->UnloadAppDomain2(
         domainId, 
-        true);                          // Wait until done
+        true,
+        (int *)&exitCode);                          // Wait until done
 
     if (FAILED(hr)) {
         log << W("Failed to unload the AppDomain. ERRORCODE: ") << Logger::hresult << hr << Logger::endl;
         return false;
     }
 
+    log << W("App domain unloaded exit value = ") << exitCode << Logger::endl;
 
     //-------------------------------------------------------------
 
@@ -608,7 +610,7 @@ bool TryRun(const int argc, const wchar_t* argv[], Logger &log, const bool verbo
 
     // Release the reference to the host
 
-    log << W("Releasing ICLRRuntimeHost2") << Logger::endl;
+    log << W("Releasing ICLRRuntimeHost4") << Logger::endl;
 
     host->Release();
 
index 52ffda8..df4c93f 100644 (file)
 // disabled. Server GC is off by default.
 static const char* serverGcVar = "CORECLR_SERVER_GC";
 
+// Name of environment variable to control "System.Globalization.Invariant"
+// Set to 1 for Globalization Invariant mode to be true. Default is false.
+static const char* globalizationInvariantVar = "CORECLR_GLOBAL_INVARIANT";
+
 #if defined(__linux__)
 #define symlinkEntrypointExecutable "/proc/self/exe"
 #elif !defined(__APPLE__)
@@ -260,6 +264,17 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList)
     closedir(dir);
 }
 
+const char* GetEnvValueBoolean(const char* envVariable)
+{
+    const char* envValue = std::getenv(envVariable);
+    if (envValue == nullptr)
+    {
+        envValue = "0";
+    }
+    // CoreCLR expects strings "true" and "false" instead of "1" and "0".
+    return (std::strcmp(envValue, "1") == 0 || strcasecmp(envValue, "true") == 0) ? "true" : "false";
+}
+
 int ExecuteManagedAssembly(
             const char* currentExeAbsolutePath,
             const char* clrFilesAbsolutePath,
@@ -338,14 +353,10 @@ int ExecuteManagedAssembly(
         else
         {
             // Check whether we are enabling server GC (off by default)
-            const char* useServerGc = std::getenv(serverGcVar);
-            if (useServerGc == nullptr)
-            {
-                useServerGc = "0";
-            }
+            const char* useServerGc = GetEnvValueBoolean(serverGcVar);
 
-            // CoreCLR expects strings "true" and "false" instead of "1" and "0".
-            useServerGc = std::strcmp(useServerGc, "1") == 0 ? "true" : "false";
+            // Check Globalization Invariant mode (false by default)
+            const char* globalizationInvariant = GetEnvValueBoolean(globalizationInvariantVar);
 
             // Allowed property names:
             // APPBASE
@@ -369,6 +380,7 @@ int ExecuteManagedAssembly(
                 "APP_NI_PATHS",
                 "NATIVE_DLL_SEARCH_DIRECTORIES",
                 "System.GC.Server",
+                "System.Globalization.Invariant",
             };
             const char *propertyValues[] = {
                 // TRUSTED_PLATFORM_ASSEMBLIES
@@ -381,6 +393,8 @@ int ExecuteManagedAssembly(
                 nativeDllSearchDirs.c_str(),
                 // System.GC.Server
                 useServerGc,
+                // System.Globalization.Invariant
+                globalizationInvariant,
             };
 
             void* hostHandle;
index 8f72542..f92630b 100644 (file)
@@ -120,6 +120,8 @@ CrashInfo::EnumerateAndSuspendThreads()
             else 
             {
                 fprintf(stderr, "ptrace(ATTACH, %d) FAILED %s\n", tid, strerror(errno));
+                closedir(taskDir);
+                return false;
             }
         }
     }
@@ -129,7 +131,7 @@ CrashInfo::EnumerateAndSuspendThreads()
 }
 
 bool
-CrashInfo::GatherCrashInfo(const char* pszExePath, MINIDUMP_TYPE minidumpType)
+CrashInfo::GatherCrashInfo(const char* programPath, MINIDUMP_TYPE minidumpType)
 {
     // Get the process info
     if (!GetStatus(m_pid, &m_ppid, &m_tgid, &m_name))
@@ -160,7 +162,7 @@ CrashInfo::GatherCrashInfo(const char* pszExePath, MINIDUMP_TYPE minidumpType)
         return false;
     }
     // Gather all the useful memory regions from the DAC
-    if (!EnumerateMemoryRegionsWithDAC(pszExePath, minidumpType))
+    if (!EnumerateMemoryRegionsWithDAC(programPath, minidumpType))
     {
         return false;
     }
@@ -326,7 +328,7 @@ CrashInfo::EnumerateModuleMappings()
 }
 
 bool
-CrashInfo::EnumerateMemoryRegionsWithDAC(const char *pszExePath, MINIDUMP_TYPE minidumpType)
+CrashInfo::EnumerateMemoryRegionsWithDAC(const char* programPath, MINIDUMP_TYPE minidumpType)
 {
     PFN_CLRDataCreateInstance pfnCLRDataCreateInstance = nullptr;
     ICLRDataEnumMemoryRegions *clrDataEnumRegions = nullptr;
@@ -336,7 +338,7 @@ CrashInfo::EnumerateMemoryRegionsWithDAC(const char *pszExePath, MINIDUMP_TYPE m
 
     // We assume that the DAC is in the same location as this createdump exe
     ArrayHolder<char> dacPath = new char[MAX_LONGPATH];
-    strcpy_s(dacPath, MAX_LONGPATH, pszExePath);
+    strcpy_s(dacPath, MAX_LONGPATH, programPath);
     char *last = strrchr(dacPath, '/');
     if (last != nullptr)
     {
@@ -572,13 +574,10 @@ CrashInfo::CombineMemoryRegions()
     if (g_diagnostics)
     {
         TRACE("Memory Regions:\n");
-        uint64_t total = 0;
         for (const MemoryRegion& region : m_memoryRegions)
         {
             region.Print();
-            total += region.Size();
         }
-        TRACE("Total %ld bytes (%ld pages) to write\n", total, total >> PAGE_SHIFT);
     }
 }
 
index a03ebe3..bdd19cf 100644 (file)
@@ -34,7 +34,7 @@ public:
     CrashInfo(pid_t pid, DataTarget& dataTarget);
     virtual ~CrashInfo();
     bool EnumerateAndSuspendThreads();
-    bool GatherCrashInfo(const char* pszExePath, MINIDUMP_TYPE minidumpType);
+    bool GatherCrashInfo(const char* programPath, MINIDUMP_TYPE minidumpType);
     void ResumeThreads();
     static bool GetStatus(pid_t pid, pid_t* ppid, pid_t* tgid, char** name);
 
@@ -63,7 +63,7 @@ public:
 private:
     bool GetAuxvEntries();
     bool EnumerateModuleMappings();
-    bool EnumerateMemoryRegionsWithDAC(const char* pszExePath, MINIDUMP_TYPE minidumpType);
+    bool EnumerateMemoryRegionsWithDAC(const char* programPath, MINIDUMP_TYPE minidumpType);
     bool GetDSOInfo();
     bool ReadMemory(void* address, void* buffer, size_t size);
     void InsertMemoryRegion(uint64_t address, size_t size);
index 4f43d11..87cf4f9 100644 (file)
@@ -4,18 +4,26 @@
 
 #include "createdump.h"
 
+const char* g_help = "createdump [options] pid\n" 
+"-f, --name - dump path and file name. The pid can be placed in the name with %d. The default is '/tmp/coredump.%d'\n"
+"-n, --normal - create minidump (default).\n"
+"-h, --withheap - create minidump with heap.\n" 
+"-m, --micro - create triage minidump.\n" 
+"-d, --diag - enable diagnostic messages.\n";
+
 bool g_diagnostics = true;
 
 //
 // Create a minidump using the DAC's enum memory regions interface
 //
 static bool 
-CreateDump(const char* pszExePath, const char* dumpPathTemplate, pid_t pid, MINIDUMP_TYPE minidumpType)
+CreateDump(const char* programPath, const char* dumpPathTemplate, pid_t pid, MINIDUMP_TYPE minidumpType)
 {
     DataTarget* dataTarget = new DataTarget(pid);
     CrashInfo* crashInfo = new CrashInfo(pid, *dataTarget);
     DumpWriter* dumpWriter = new DumpWriter(*dataTarget, *crashInfo);
     ArrayHolder<char> dumpPath = new char[MAX_LONGPATH];
+    const char* dumpType = "minidump";
     bool result = false;
 
     // Suspend all the threads in the target process and build the list of threads
@@ -29,7 +37,7 @@ CreateDump(const char* pszExePath, const char* dumpPathTemplate, pid_t pid, MINI
         goto exit;
     }
     // Gather all the info about the process, threads (registers, etc.) and memory regions
-    if (!crashInfo->GatherCrashInfo(pszExePath, minidumpType))
+    if (!crashInfo->GatherCrashInfo(programPath, minidumpType))
     {
         goto exit;
     }
@@ -38,6 +46,20 @@ CreateDump(const char* pszExePath, const char* dumpPathTemplate, pid_t pid, MINI
     {
         goto exit;
     }
+    switch (minidumpType)
+    {
+        case MiniDumpWithPrivateReadWriteMemory:
+            dumpType = "minidump with heap";
+            break;
+
+        case MiniDumpFilterTriage:
+            dumpType = "triage minidump";
+            break;
+
+        default:
+            break;
+    }
+    printf("Writing %s to file %s\n", dumpType, (char*)dumpPath);
     if (!dumpWriter->WriteDump())
     {
         goto exit;
@@ -56,32 +78,60 @@ exit:
 //
 int __cdecl main(const int argc, const char* argv[])
 {
+    MINIDUMP_TYPE minidumpType = MiniDumpNormal;
     const char* dumpPathTemplate = "/tmp/coredump.%d";
-
-    char* diagnostics = getenv("COMPlus_CreateDumpDiagnostics");
-    g_diagnostics = diagnostics != nullptr && strcmp(diagnostics, "1") == 0;
+    const char* programPath = nullptr;
+    pid_t pid = 0;
 
     int exitCode = PAL_InitializeDLL();
     if (exitCode != 0)
     {
-        fprintf(stderr, "PAL_Initialize FAILED %d\n", exitCode);
+        fprintf(stderr, "PAL initialization FAILED %d\n", exitCode);
         return exitCode;
     }
-    pid_t pid;
-    if (argc < 2)
+    programPath = *argv;
+    argv++;
+
+    for (int i = 1; i < argc; i++)
     {
-        fprintf(stderr, "Not enough arguments\n");
+        if (*argv != nullptr)
+        {
+            if ((strcmp(*argv, "-f") == 0) || (strcmp(*argv, "--name") == 0))
+            {
+                dumpPathTemplate = *++argv;
+            }
+            else if ((strcmp(*argv, "-n") == 0) || (strcmp(*argv, "--normal") == 0))
+            {
+                minidumpType = MiniDumpNormal;
+            }
+            else if ((strcmp(*argv, "-h") == 0) || (strcmp(*argv, "--withheap") == 0))
+            {
+                minidumpType = MiniDumpWithPrivateReadWriteMemory;
+            }
+            else if ((strcmp(*argv, "-m") == 0) || (strcmp(*argv, "--micro") == 0))
+            {
+                minidumpType = MiniDumpFilterTriage;
+            }
+            else if ((strcmp(*argv, "-d") == 0) || (strcmp(*argv, "--diag") == 0))
+            {
+                g_diagnostics = true;
+            }
+            else {
+                pid = atoll(*argv);
+            }
+            argv++;
+        }
+    }
+    // if no pid or invalid command line option
+    if (pid == 0)
+    {
+        fprintf(stderr, "%s", g_help);
         exitCode = -1;
-        goto exit;
     }
-    pid = _atoi64(argv[1]);
-
-    if (!CreateDump(argv[0], dumpPathTemplate, pid, MiniDumpNormal)) 
+    else if (!CreateDump(programPath, dumpPathTemplate, pid, minidumpType)) 
     {
         exitCode = -1;
-        goto exit;
     }
-exit:
     PAL_TerminateEx(exitCode);
     return exitCode;
 }
index ef3adac..cec19e8 100644 (file)
@@ -70,7 +70,6 @@ DumpWriter::OpenDump(char* dumpFileName)
         fprintf(stderr, "Could not open output %s: %s\n", dumpFileName, strerror(errno));
         return false;
     }
-    printf("Writing core file %s\n", dumpFileName);
     return true;
 }
 
@@ -175,7 +174,7 @@ DumpWriter::WriteDump()
     }
     offset += finalNoteAlignment;
 
-    printf("Writing memory region headers to core file\n");
+    TRACE("Writing memory region headers to core file\n");
 
     // Write memory region note headers
     for (const MemoryRegion& memoryRegion : m_crashInfo.MemoryRegions())
@@ -208,7 +207,7 @@ DumpWriter::WriteDump()
         return false;
     }
 
-    printf("Writing %ld thread entries to core file\n", m_crashInfo.Threads().size());
+    TRACE("Writing %ld thread entries to core file\n", m_crashInfo.Threads().size());
 
     // Write all the thread's state and registers
     for (const ThreadInfo* thread : m_crashInfo.Threads()) 
@@ -228,13 +227,15 @@ DumpWriter::WriteDump()
         }
     }
 
-    printf("Writing %ld memory regions to core file\n", m_crashInfo.MemoryRegions().size());
+    TRACE("Writing %ld memory regions to core file\n", m_crashInfo.MemoryRegions().size());
 
     // Read from target process and write memory regions to core
+    uint64_t total = 0;
     for (const MemoryRegion& memoryRegion : m_crashInfo.MemoryRegions())
     {
         uint32_t size = memoryRegion.Size();
         uint64_t address = memoryRegion.StartAddress();
+        total += size;
 
         while (size > 0)
         {
@@ -255,6 +256,8 @@ DumpWriter::WriteDump()
         }
     }
 
+    printf("Written %ld bytes (%ld pages) to core file\n", total, total >> PAGE_SHIFT);
+
     return true;
 }
 
@@ -275,7 +278,7 @@ DumpWriter::WriteProcessInfo()
     nhdr.n_descsz = sizeof(prpsinfo_t);
     nhdr.n_type = NT_PRPSINFO;
 
-    printf("Writing process information to core file\n");
+    TRACE("Writing process information to core file\n");
 
     // Write process info data to core file
     if (!WriteData(&nhdr, sizeof(nhdr)) ||
@@ -295,7 +298,7 @@ DumpWriter::WriteAuxv()
     nhdr.n_descsz = m_crashInfo.GetAuxvSize();
     nhdr.n_type = NT_AUXV;
 
-    printf("Writing %ld auxv entries to core file\n", m_crashInfo.AuxvEntries().size());
+    TRACE("Writing %ld auxv entries to core file\n", m_crashInfo.AuxvEntries().size());
 
     if (!WriteData(&nhdr, sizeof(nhdr)) ||
         !WriteData("CORE\0AUX", 8)) { 
@@ -373,7 +376,7 @@ DumpWriter::WriteNTFileInfo()
     size_t count = m_crashInfo.ModuleMappings().size();
     size_t pageSize = PAGE_SIZE;
 
-    printf("Writing %ld NT_FILE entries to core file\n", m_crashInfo.ModuleMappings().size());
+    TRACE("Writing %ld NT_FILE entries to core file\n", m_crashInfo.ModuleMappings().size());
 
     if (!WriteData(&nhdr, sizeof(nhdr)) ||
         !WriteData("CORE\0FIL", 8) ||
index c2c96fa..b0c3b04 100644 (file)
@@ -21,6 +21,7 @@ PAL_GetPALDirectoryW
 PAL_GetResourceString
 PAL_get_stdout
 PAL_get_stderr
+PAL_GetCurrentThread
 PAL_GetSymbolModuleBase
 PAL_GetTransportPipeName
 PAL_InitializeDLL
index f33f095..f3e22da 100644 (file)
@@ -48,7 +48,7 @@ HINSTANCE g_hThisInst;  // This library.
 
 #include <process.h> // for __security_init_cookie()
 
-extern "C" IExecutionEngine* __stdcall IEE();
+extern "C" IExecutionEngine* IEE();
 
 #ifdef NO_CRT_INIT
 #define _CRT_INIT(hInstance, dwReason, lpReserved) (TRUE)
index 6d53c89..745b24f 100644 (file)
@@ -5151,7 +5151,6 @@ void gc_heap::destroy_thread_support ()
     }
 }
 
-#if !defined(FEATURE_PAL)
 void set_thread_group_affinity_for_heap(int heap_number, GCThreadAffinity* affinity)
 {
     affinity->Group = GCThreadAffinity::None;
@@ -5231,7 +5230,6 @@ void set_thread_affinity_mask_for_heap(int heap_number, GCThreadAffinity* affini
         }
     }
 }
-#endif // !FEATURE_PAL
 
 bool gc_heap::create_gc_thread ()
 {
@@ -5241,7 +5239,6 @@ bool gc_heap::create_gc_thread ()
     affinity.Group = GCThreadAffinity::None;
     affinity.Processor = GCThreadAffinity::None;
 
-#if !defined(FEATURE_PAL)
     if (!gc_thread_no_affinitize_p)
     {
         // We are about to set affinity for GC threads. It is a good place to set up NUMA and
@@ -5252,7 +5249,6 @@ bool gc_heap::create_gc_thread ()
         else
             set_thread_affinity_mask_for_heap(heap_number, &affinity);
     }
-#endif // !FEATURE_PAL
 
     return GCToOSInterface::CreateThread(gc_thread_stub, this, &affinity);
 }
@@ -34222,7 +34218,7 @@ bool GCHeap::StressHeap(gc_alloc_context * context)
                     if (g_pConfig->AppDomainLeaks() && str->SetAppDomainNoThrow())
                     {
 #endif
-                        StoreObjectInHandle(m_StressObjs[i], ObjectToOBJECTREF(str));
+                        HndAssignHandle(m_StressObjs[i], ObjectToOBJECTREF(str));
 #if CHECK_APP_DOMAIN_LEAKS
                     }
 #endif
@@ -34255,7 +34251,7 @@ bool GCHeap::StressHeap(gc_alloc_context * context)
             {
                 // Let the string itself become garbage.
                 // will be realloced next time around
-                StoreObjectInHandle(m_StressObjs[m_CurStressObj], 0);
+                HndAssignHandle(m_StressObjs[m_CurStressObj], 0);
             }
         }
     }
index 68a1c97..75646e8 100644 (file)
@@ -132,3 +132,18 @@ void* GCHandleManager::GetExtraInfoFromHandle(OBJECTHANDLE handle)
 {
     return (void*)::HndGetHandleExtraInfo(handle);
 }
+
+void GCHandleManager::StoreObjectInHandle(OBJECTHANDLE handle, Object* object)
+{
+    ::HndAssignHandle(handle, ObjectToOBJECTREF(object));
+}
+
+bool GCHandleManager::StoreObjectInHandleIfNull(OBJECTHANDLE handle, Object* object)
+{
+    return !!::HndFirstAssignHandle(handle, ObjectToOBJECTREF(object));
+}
+
+Object* GCHandleManager::InterlockedCompareExchangeObjectInHandle(OBJECTHANDLE handle, Object* object, Object* comparandObject)
+{
+    return (Object*)::HndInterlockedCompareExchangeHandle(handle, ObjectToOBJECTREF(object), ObjectToOBJECTREF(comparandObject));
+}
index 9247615..01c1c13 100644 (file)
@@ -54,6 +54,12 @@ public:
     virtual void DestroyHandleOfUnknownType(OBJECTHANDLE handle);
 
     virtual void* GetExtraInfoFromHandle(OBJECTHANDLE handle);
+
+    virtual void StoreObjectInHandle(OBJECTHANDLE handle, Object* object);
+
+    virtual bool StoreObjectInHandleIfNull(OBJECTHANDLE handle, Object* object);
+
+    virtual Object* InterlockedCompareExchangeObjectInHandle(OBJECTHANDLE handle, Object* object, Object* comparandObject);
 };
 
 #endif  // GCHANDLETABLE_H_
index 85c331b..552a8ca 100644 (file)
@@ -444,6 +444,12 @@ public:
     virtual void DestroyHandleOfUnknownType(OBJECTHANDLE handle) = 0;
 
     virtual void* GetExtraInfoFromHandle(OBJECTHANDLE handle) = 0;
+
+    virtual void StoreObjectInHandle(OBJECTHANDLE handle, Object* object) = 0;
+
+    virtual bool StoreObjectInHandleIfNull(OBJECTHANDLE handle, Object* object) = 0;
+
+    virtual Object* InterlockedCompareExchangeObjectInHandle(OBJECTHANDLE handle, Object* object, Object* comparandObject) = 0;
 };
 
 // IGCHeap is the interface that the VM will use when interacting with the GC.
index ae815c1..752a7b0 100644 (file)
@@ -22,13 +22,6 @@ inline void HndAssignHandle(OBJECTHANDLE handle, OBJECTREF objref)
     // sanity
     _ASSERTE(handle);
 
-#ifdef _DEBUG_IMPL
-    // handle should not be in unloaded domain
-    ValidateAppDomainForHandle(handle);
-
-    // Make sure the objref is valid before it is assigned to a handle
-    ValidateAssignObjrefForHandle(objref, HndGetHandleTableADIndex(HndGetHandleTable(handle)));
-#endif
     // unwrap the objectref we were given
     _UNCHECKED_OBJECTREF value = OBJECTREF_TO_UNCHECKED_OBJECTREF(objref);
 
@@ -49,13 +42,6 @@ inline void* HndInterlockedCompareExchangeHandle(OBJECTHANDLE handle, OBJECTREF
     // sanity
     _ASSERTE(handle);
 
-#ifdef _DEBUG_IMPL
-    // handle should not be in unloaded domain
-    ValidateAppDomainForHandle(handle);
-
-    // Make sure the objref is valid before it is assigned to a handle
-    ValidateAssignObjrefForHandle(objref, HndGetHandleTableADIndex(HndGetHandleTable(handle)));
-#endif
     // unwrap the objectref we were given
     _UNCHECKED_OBJECTREF value = OBJECTREF_TO_UNCHECKED_OBJECTREF(objref);
     _UNCHECKED_OBJECTREF oldValue = OBJECTREF_TO_UNCHECKED_OBJECTREF(oldObjref);
@@ -88,13 +74,6 @@ inline BOOL HndFirstAssignHandle(OBJECTHANDLE handle, OBJECTREF objref)
     // sanity
     _ASSERTE(handle);
 
-#ifdef _DEBUG_IMPL
-    // handle should not be in unloaded domain
-    ValidateAppDomainForHandle(handle);
-
-    // Make sure the objref is valid before it is assigned to a handle
-    ValidateAssignObjrefForHandle(objref, HndGetHandleTableADIndex(HndGetHandleTable(handle)));
-#endif
     // unwrap the objectref we were given
     _UNCHECKED_OBJECTREF value = OBJECTREF_TO_UNCHECKED_OBJECTREF(objref);
     _UNCHECKED_OBJECTREF null = NULL;
index 945e8d6..b3e4b58 100644 (file)
 #include <weakreference.h>
 #endif // FEATURE_COMINTEROP
 
-/*
- * Convenience macros for accessing handles.  StoreFirstObjectInHandle is like
- * StoreObjectInHandle, except it only succeeds if transitioning from NULL to
- * non-NULL.  In other words, if this handle is being initialized for the first
- * time.
- */
-#define StoreObjectInHandle(handle, object)        HndAssignHandle(handle, object)
-#define InterlockedCompareExchangeObjectInHandle(handle, object, oldObj)        HndInterlockedCompareExchangeHandle(handle, object, oldObj)
-#define StoreFirstObjectInHandle(handle, object)   HndFirstAssignHandle(handle, object)
-
 typedef DPTR(struct HandleTableMap) PTR_HandleTableMap;
 typedef DPTR(struct HandleTableBucket) PTR_HandleTableBucket;
 typedef DPTR(PTR_HandleTableBucket) PTR_PTR_HandleTableBucket;
@@ -90,17 +80,6 @@ void GCHandleValidatePinnedObject(OBJECTREF obj);
 
 int GetCurrentThreadHomeHeapNumber();
 
-inline void ResetOBJECTHANDLE(OBJECTHANDLE handle)
-{
-    WRAPPER_NO_CONTRACT;
-
-    StoreObjectInHandle(handle, NULL);
-}
-
-#ifndef FEATURE_REDHAWK
-typedef Holder<OBJECTHANDLE,DoNothing<OBJECTHANDLE>,ResetOBJECTHANDLE> ObjectInHandleHolder;
-#endif
-
 /*
  * Table maintenance routines
  */
index 97e2f2a..53d4ce3 100644 (file)
@@ -86,6 +86,9 @@ cpp_quote("EXTERN_GUID(IID_ICLRRuntimeHost, 0x90F1A06C, 0x7712, 0x4762, 0x86, 0x
 // IID ICLRRuntimeHost2: uuid(712AB73F-2C22-4807-AD7E-F501D7B72C2D)
 cpp_quote("EXTERN_GUID(IID_ICLRRuntimeHost2, 0x712AB73F, 0x2C22, 0x4807, 0xAD, 0x7E, 0xF5, 0x01, 0xD7, 0xb7, 0x2C, 0x2D);")
 
+// IID ICLRRuntimeHost4: uuid(64F6D366-D7C2-4F1F-B4B2-E8160CAC43AF)
+cpp_quote("EXTERN_GUID(IID_ICLRRuntimeHost4, 0x64F6D366, 0xD7C2, 0x4F1F, 0xB4, 0xB2, 0xE8, 0x16, 0x0C, 0xAC, 0x43, 0xAF);")
+
 // IID IID_ICLRExecutionManager: uuid(1000A3E7-B420-4620-AE30-FB19B587AD1D)
 cpp_quote("EXTERN_GUID(IID_ICLRExecutionManager, 0x1000A3E7, 0xB420, 0x4620, 0xAE, 0x30, 0xFB, 0x19, 0xB5, 0x87, 0xAD, 0x1D);")
 
@@ -848,6 +851,21 @@ interface ICLRRuntimeHost2 : ICLRRuntimeHost
 };
 
 [
+    object,
+    uuid(64F6D366-D7C2-4F1F-B4B2-E8160CAC43AF),
+    version(4.0),
+    helpstring("Common Language Runtime Hosting Interface"),
+    pointer_default(unique),
+    local
+]
+interface ICLRRuntimeHost4 : ICLRRuntimeHost2
+{
+    HRESULT UnloadAppDomain2([in] DWORD dwAppDomainId,
+                                          [in] BOOL fWaitUntilDone,
+                                          [out] int *pLatchedExitCode);
+};
+
+[
     uuid(1000A3E7-B420-4620-AE30-FB19B587AD1D),
     version(1.0),
     helpstring("Pause and Resume Interface"),
index 5394f1b..78dbf69 100644 (file)
@@ -1380,7 +1380,7 @@ public:
     static BOOL CanEnableGCNumaAware();
     static void InitNumaNodeInfo();
 
-#if !defined(FEATURE_REDHAWK)&& !defined(FEATURE_PAL)
+#if !defined(FEATURE_REDHAWK)
 private:       // apis types
 
     //GetNumaHighestNodeNumber()
@@ -1448,7 +1448,7 @@ public:
     static DWORD CalculateCurrentProcessorNumber();
     //static void PopulateCPUUsageArray(void * infoBuffer, ULONG infoSize);
 
-#if !defined(FEATURE_REDHAWK) && !defined(FEATURE_PAL)
+#if !defined(FEATURE_REDHAWK)
 private:
     //GetLogicalProcessorInforomationEx()
     typedef BOOL
@@ -5109,9 +5109,9 @@ BOOL IsIPInModule(HMODULE_TGT hModule, PCODE ip);
 //----------------------------------------------------------------------------------------
 struct CoreClrCallbacks
 {
-    typedef IExecutionEngine* (__stdcall * pfnIEE_t)();
-    typedef HRESULT (__stdcall * pfnGetCORSystemDirectory_t)(SString& pbuffer);
-    typedef void* (__stdcall * pfnGetCLRFunction_t)(LPCSTR functionName);
+    typedef IExecutionEngine* (* pfnIEE_t)();
+    typedef HRESULT (* pfnGetCORSystemDirectory_t)(SString& pbuffer);
+    typedef void* (* pfnGetCLRFunction_t)(LPCSTR functionName);
 
     HINSTANCE                   m_hmodCoreCLR;
     pfnIEE_t                    m_pfnIEE;
@@ -5516,6 +5516,6 @@ extern SpinConstants g_SpinConstants;
 
 // ======================================================================================
 
-void* __stdcall GetCLRFunction(LPCSTR FunctionName);
+void* GetCLRFunction(LPCSTR FunctionName);
 
 #endif // __UtilCode_h__
index 4507a5c..bac24d5 100644 (file)
@@ -1267,7 +1267,7 @@ void CodeGen::genLclHeap(GenTreePtr tree)
         // If not done, loop
         // Note that regCnt is the number of bytes to stack allocate.
         assert(genIsValidIntReg(regCnt));
-        getEmitter()->emitIns_R_R_I(INS_sub, EA_PTRSIZE, regCnt, regCnt, STACK_ALIGN);
+        getEmitter()->emitIns_R_I(INS_sub, EA_PTRSIZE, regCnt, STACK_ALIGN, INS_FLAGS_SET);
         emitJumpKind jmpNotEqual = genJumpKindForOper(GT_NE, CK_SIGNED);
         inst_JMP(jmpNotEqual, loop);
     }
@@ -1311,7 +1311,7 @@ void CodeGen::genLclHeap(GenTreePtr tree)
         BasicBlock* done = genCreateTempLabel();
 
         //       subs  regCnt, SP, regCnt      // regCnt now holds ultimate SP
-        getEmitter()->emitIns_R_R_R(INS_sub, EA_PTRSIZE, regCnt, REG_SPBASE, regCnt);
+        getEmitter()->emitIns_R_R_R(INS_sub, EA_PTRSIZE, regCnt, REG_SPBASE, regCnt, INS_FLAGS_SET);
 
         inst_JMP(EJ_vc, loop); // branch if the V flag is not set
 
index 3144343..6012396 100644 (file)
@@ -771,16 +771,10 @@ void CodeGen::genCodeForArrOffset(GenTreeArrOffs* arrOffset)
         var_types elemType = arrOffset->gtArrElemType;
         unsigned  offset   = genOffsetOfMDArrayDimensionSize(elemType, rank, dim);
 
-// Load tmpReg with the dimension size and evaluate
-// tgtReg = offsetReg*dim_size + indexReg.
-#if defined(_TARGET_ARM_)
-        emit->emitIns_R_R_I(ins_Load(TYP_INT), EA_4BYTE, tmpReg, arrReg, offset); // a 4 BYTE sign extending load
-        emit->emitIns_R_R_R(INS_MUL, EA_4BYTE, tgtReg, tmpReg, offsetReg);
-        emit->emitIns_R_R_R(INS_add, EA_4BYTE, tgtReg, tgtReg, indexReg);
-#elif defined(_TARGET_ARM64_)
-        emit->emitIns_R_R_I(ins_Load(TYP_INT), EA_8BYTE, tmpReg, arrReg, offset); // a 4 BYTE sign extending load
-        emit->emitIns_R_R_R_R(INS_madd, EA_4BYTE, tgtReg, tmpReg, offsetReg, indexReg);
-#endif // _TARGET_*
+        // Load tmpReg with the dimension size and evaluate
+        // tgtReg = offsetReg*tmpReg + indexReg.
+        emit->emitIns_R_R_I(ins_Load(TYP_INT), EA_PTRSIZE, tmpReg, arrReg, offset);
+        emit->emitIns_R_R_R_R(INS_MULADD, EA_PTRSIZE, tgtReg, tmpReg, offsetReg, indexReg);
     }
     else
     {
index ad1f027..386a9f0 100644 (file)
@@ -4979,9 +4979,10 @@ void CodeGen::genCallInstruction(GenTreeCall* call)
     }
 
 #if defined(_TARGET_X86_)
-    bool fCallerPop = (call->gtFlags & GTF_CALL_POP_ARGS) != 0;
+    bool fCallerPop = call->CallerPop();
 
 #ifdef UNIX_X86_ABI
+    if (!call->IsUnmanaged())
     {
         CorInfoCallConv callConv = CORINFO_CALLCONV_DEFAULT;
 
index 9da7f09..1ba059a 100644 (file)
@@ -1218,13 +1218,13 @@ struct fgArgTabEntry
     regNumber otherRegNum; // The (second) register to use when passing this argument.
 
     SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR structDesc;
-#elif defined(_TARGET_X86_)
+#elif !defined(_TARGET_64BIT_)
     __declspec(property(get = getIsStruct)) bool isStruct;
     bool getIsStruct()
     {
         return varTypeIsStruct(node);
     }
-#endif // _TARGET_X86_
+#endif // !_TARGET_64BIT_
 
 #ifdef _TARGET_ARM_
     void SetIsHfaRegArg(bool hfaRegArg)
@@ -9472,6 +9472,7 @@ const instruction INS_XOR             = INS_eor;
 const instruction INS_NEG             = INS_rsb;
 const instruction INS_TEST            = INS_tst;
 const instruction INS_MUL             = INS_mul;
+const instruction INS_MULADD          = INS_mla;
 const instruction INS_SIGNED_DIVIDE   = INS_sdiv;
 const instruction INS_UNSIGNED_DIVIDE = INS_udiv;
 const instruction INS_BREAKPOINT      = INS_bkpt;
@@ -9497,6 +9498,7 @@ const instruction INS_XOR             = INS_eor;
 const instruction INS_NEG             = INS_neg;
 const instruction INS_TEST            = INS_tst;
 const instruction INS_MUL             = INS_mul;
+const instruction INS_MULADD          = INS_madd;
 const instruction INS_SIGNED_DIVIDE   = INS_sdiv;
 const instruction INS_UNSIGNED_DIVIDE = INS_udiv;
 const instruction INS_BREAKPOINT      = INS_bkpt;
index c75b814..18199bf 100644 (file)
@@ -450,7 +450,7 @@ bool GenTree::IsNodeProperlySized() const
 
 #define BASH_HASH_SIZE 211
 
-inline hashme(genTreeOps op1, genTreeOps op2)
+inline unsigned hashme(genTreeOps op1, genTreeOps op2)
 {
     return ((op1 * 104729) ^ (op2 * 56569)) % BASH_HASH_SIZE;
 }
index e678b15..2e3ca81 100644 (file)
@@ -15051,7 +15051,7 @@ void Compiler::impMarkLclDstNotPromotable(unsigned tmpNum, GenTreePtr src, CORIN
 GenTreePtr Compiler::impAssignMultiRegTypeToVar(GenTreePtr op, CORINFO_CLASS_HANDLE hClass)
 {
     unsigned tmpNum = lvaGrabTemp(true DEBUGARG("Return value temp for multireg return."));
-    impAssignTempGen(tmpNum, op, hClass, (unsigned)CHECK_SPILL_NONE);
+    impAssignTempGen(tmpNum, op, hClass, (unsigned)CHECK_SPILL_ALL);
     GenTreePtr ret = gtNewLclvNode(tmpNum, op->gtType);
 
     // TODO-1stClassStructs: Handle constant propagation and CSE-ing of multireg returns.
index e2435ca..5bbfdde 100644 (file)
@@ -244,8 +244,15 @@ void CodeGen::inst_JMP(emitJumpKind jmp, BasicBlock* tgtBlock)
     //
     // Thus only on x86 do we need to assert that the stack level at the target block matches the current stack level.
     //
-    assert(tgtBlock->bbTgtStkDepth * sizeof(int) == genStackLevel || compiler->rpFrameType != FT_ESP_FRAME);
+    CLANG_FORMAT_COMMENT_ANCHOR;
+
+#ifdef UNIX_X86_ABI
+    // bbTgtStkDepth is a (pure) argument count (stack alignment padding should be excluded).
+    assert((tgtBlock->bbTgtStkDepth * sizeof(int) == (genStackLevel - curNestedAlignment)) || isFramePointerUsed());
+#else
+    assert((tgtBlock->bbTgtStkDepth * sizeof(int) == genStackLevel) || isFramePointerUsed());
 #endif
+#endif // !FEATURE_FIXED_OUT_ARGS
 
     getEmitter()->emitIns_J(emitter::emitJumpKindToIns(jmp), tgtBlock);
 }
index ee3f8c9..5120449 100644 (file)
 #define FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY(x)
 #endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
 
-#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) || (defined(_TARGET_X86_) && !defined(LEGACY_BACKEND))
+#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) || (!defined(_TARGET_64BIT_) && !defined(LEGACY_BACKEND))
 #define FEATURE_PUT_STRUCT_ARG_STK 1
 #define PUT_STRUCT_ARG_STK_ONLY_ARG(x) , x
 #define PUT_STRUCT_ARG_STK_ONLY(x) x
-#else // !(defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)|| (defined(_TARGET_X86_) && !defined(LEGACY_BACKEND)))
+#else // !(defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)|| (!defined(_TARGET_64BIT_) && !defined(LEGACY_BACKEND)))
 #define PUT_STRUCT_ARG_STK_ONLY_ARG(x)
 #define PUT_STRUCT_ARG_STK_ONLY(x)
-#endif // !(defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)|| (defined(_TARGET_X86_) && !defined(LEGACY_BACKEND)))
+#endif // !(defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)|| (!defined(_TARGET_64BIT_) && !defined(LEGACY_BACKEND)))
 
 #if defined(UNIX_AMD64_ABI)
 #define UNIX_AMD64_ABI_ONLY_ARG(x) , x
index 5bcb1c8..e64b5a1 100644 (file)
@@ -1459,7 +1459,7 @@ void Compiler::lvaCanPromoteStructType(CORINFO_CLASS_HANDLE    typeHnd,
         StructPromotionInfo->canPromote = false;
 
         unsigned structSize = info.compCompHnd->getClassSize(typeHnd);
-        if (structSize >= MaxOffset)
+        if (structSize > MaxOffset)
         {
             return; // struct is too large
         }
index aad413d..8409c89 100644 (file)
@@ -3385,10 +3385,19 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
                     size = (unsigned)(roundUp(info.compCompHnd->getClassSize(argx->gtArgPlace.gtArgPlaceClsHnd),
                                               TARGET_POINTER_SIZE)) /
                            TARGET_POINTER_SIZE;
+                    if (isHfaArg)
+                    {
+                        hasMultiregStructArgs = true;
+                    }
+                    else if (size > 1 && size <= 4)
+                    {
+                        hasMultiregStructArgs = true;
+                    }
                 }
                 else
                 {
                     // The typical case
+                    // long/double type argument(s) will be changed to GT_FIELD_LIST in lower phase
                     size = genTypeStSz(argx->gtType);
                 }
 #elif defined(_TARGET_X86_)
@@ -3400,7 +3409,8 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
 #ifdef _TARGET_ARM_
             else if (isHfaArg)
             {
-                size = GetHfaCount(argx);
+                size                  = GetHfaCount(argx);
+                hasMultiregStructArgs = true;
             }
 #endif           // _TARGET_ARM_
             else // struct type
@@ -3760,14 +3770,25 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
                     }
                 }
 
-#ifndef _TARGET_X86_
-                // TODO-Arm: Does this apply for _TARGET_ARM_, where structs passed by value can be split between
-                // registers and stack?
+#ifdef _TARGET_64BIT_
                 if (size > 1)
                 {
                     hasMultiregStructArgs = true;
                 }
-#endif // !_TARGET_X86_
+#elif defined(_TARGET_ARM_)
+                // TODO-Arm: Need to handle the case
+                // where structs passed by value can be split between registers and stack.
+                if (size > 1 && size <= 4)
+                {
+                    hasMultiregStructArgs = true;
+                }
+#ifndef LEGACY_BACKEND
+                else if (size > 4 && passUsingIntRegs)
+                {
+                    NYI("Struct can be split between registers and stack");
+                }
+#endif // !LEGACY_BACKEND
+#endif // _TARGET_ARM_
             }
 
             // The 'size' value has now must have been set. (the original value of zero is an invalid value)
@@ -4146,7 +4167,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
             // 'Lower' the MKREFANY tree and insert it.
             noway_assert(!reMorphing);
 
-#ifdef _TARGET_X86_
+#ifndef _TARGET_64BIT_
 
             // Build the mkrefany as a GT_FIELD_LIST
             GenTreeFieldList* fieldList = new (this, GT_FIELD_LIST)
@@ -4157,7 +4178,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
             fp->node            = fieldList;
             args->gtOp.gtOp1    = fieldList;
 
-#else  // !_TARGET_X86_
+#else  // _TARGET_64BIT_
 
             // Get a new temp
             // Here we don't need unsafe value cls check since the addr of temp is used only in mkrefany
@@ -4183,11 +4204,11 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
             // EvalArgsToTemps will cause tmp to actually get loaded as the argument
             call->fgArgInfo->EvalToTmp(argIndex, tmp, asg);
             lvaSetVarAddrExposed(tmp);
-#endif // !_TARGET_X86_
+#endif // _TARGET_64BIT_
         }
 #endif // !LEGACY_BACKEND
 
-#if defined(_TARGET_X86_) && !defined(LEGACY_BACKEND)
+#if !defined(_TARGET_64BIT_) && !defined(LEGACY_BACKEND)
         if (isStructArg)
         {
             GenTree* lclNode = fgIsIndirOfAddrOfLocal(argx);
@@ -4222,7 +4243,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
                 }
             }
         }
-#endif // defined (_TARGET_X86_) && !defined(LEGACY_BACKEND)
+#endif // defined (_TARGET_64BIT_) && !defined(LEGACY_BACKEND)
 
 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
         if (isStructArg && !isRegArg)
@@ -4602,14 +4623,10 @@ void Compiler::fgMorphMultiregStructArgs(GenTreeCall* call)
     unsigned     flagsSummary   = 0;
     fgArgInfoPtr allArgInfo     = call->fgArgInfo;
 
-    // Currently only ARM64 is using this method to morph the MultiReg struct args
-    //  in the future AMD64_UNIX and for HFAs ARM32, will also use this method
-    //
+    // Currently ARM64/ARM is using this method to morph the MultiReg struct args
+    //  in the future AMD64_UNIX will also use this method
     CLANG_FORMAT_COMMENT_ANCHOR;
 
-#ifdef _TARGET_ARM_
-    NYI_ARM("fgMorphMultiregStructArgs");
-#endif
 #ifdef _TARGET_X86_
     assert(!"Logic error: no MultiregStructArgs for X86");
 #endif
@@ -4705,13 +4722,13 @@ void Compiler::fgMorphMultiregStructArgs(GenTreeCall* call)
 //    this also forces the struct to be stack allocated into the local frame.
 //    For the GT_OBJ case will clone the address expression and generate two (or more)
 //    indirections.
-//    Currently the implementation only handles ARM64 and will NYI for other architectures.
+//    Currently the implementation handles ARM64/ARM and will NYI for other architectures.
 //
 GenTreePtr Compiler::fgMorphMultiregStructArg(GenTreePtr arg, fgArgTabEntryPtr fgEntryPtr)
 {
     assert(arg->TypeGet() == TYP_STRUCT);
 
-#ifndef _TARGET_ARM64_
+#ifndef _TARGET_ARMARCH_
     NYI("fgMorphMultiregStructArg requires implementation for this target");
 #endif
 
@@ -4767,21 +4784,37 @@ GenTreePtr Compiler::fgMorphMultiregStructArg(GenTreePtr arg, fgArgTabEntryPtr f
     }
     else
     {
+#ifdef _TARGET_ARM64_
         assert(structSize <= 2 * TARGET_POINTER_SIZE);
+#elif defined(_TARGET_ARM_)
+        assert(structSize <= 4 * TARGET_POINTER_SIZE);
+#endif
+
+#ifdef _TARGET_ARM64_
         BYTE gcPtrs[2] = {TYPE_GC_NONE, TYPE_GC_NONE};
         info.compCompHnd->getClassGClayout(objClass, &gcPtrs[0]);
         elemCount = 2;
         type[0]   = getJitGCType(gcPtrs[0]);
         type[1]   = getJitGCType(gcPtrs[1]);
+#elif defined(_TARGET_ARM_)
+        BYTE gcPtrs[4] = {TYPE_GC_NONE, TYPE_GC_NONE, TYPE_GC_NONE, TYPE_GC_NONE};
+        elemCount      = (unsigned)roundUp(structSize, TARGET_POINTER_SIZE) / TARGET_POINTER_SIZE;
+        for (unsigned inx = 0; inx < elemCount; inx++)
+        {
+            gcPtrs[inx] = TYPE_GC_NONE;
+            info.compCompHnd->getClassGClayout(objClass, &gcPtrs[inx]);
+            type[inx] = getJitGCType(gcPtrs[inx]);
+        }
+#endif // _TARGET_ARM_
 
         if ((argValue->OperGet() == GT_LCL_FLD) || (argValue->OperGet() == GT_LCL_VAR))
         {
-            // We can safely widen this to 16 bytes since we are loading from
+            elemSize = TARGET_POINTER_SIZE;
+            // We can safely widen this to aligned bytes since we are loading from
             // a GT_LCL_VAR or a GT_LCL_FLD which is properly padded and
             // lives in the stack frame or will be a promoted field.
             //
-            elemSize   = TARGET_POINTER_SIZE;
-            structSize = 2 * TARGET_POINTER_SIZE;
+            structSize = elemCount * TARGET_POINTER_SIZE;
         }
         else // we must have a GT_OBJ
         {
@@ -4789,21 +4822,25 @@ GenTreePtr Compiler::fgMorphMultiregStructArg(GenTreePtr arg, fgArgTabEntryPtr f
 
             // We need to load the struct from an arbitrary address
             // and we can't read past the end of the structSize
-            // We adjust the second load type here
+            // We adjust the last load type here
             //
-            if (structSize < 2 * TARGET_POINTER_SIZE)
+            unsigned remainingBytes = structSize % TARGET_POINTER_SIZE;
+            unsigned lastElem       = elemCount - 1;
+            if (remainingBytes != 0)
             {
-                switch (structSize - TARGET_POINTER_SIZE)
+                switch (remainingBytes)
                 {
                     case 1:
-                        type[1] = TYP_BYTE;
+                        type[lastElem] = TYP_BYTE;
                         break;
                     case 2:
-                        type[1] = TYP_SHORT;
+                        type[lastElem] = TYP_SHORT;
                         break;
+#ifdef _TARGET_ARM64_
                     case 4:
-                        type[1] = TYP_INT;
+                        type[lastElem] = TYP_INT;
                         break;
+#endif // _TARGET_ARM64_
                     default:
                         noway_assert(!"NYI: odd sized struct in fgMorphMultiregStructArg");
                         break;
@@ -4825,10 +4862,10 @@ GenTreePtr Compiler::fgMorphMultiregStructArg(GenTreePtr arg, fgArgTabEntryPtr f
         assert(varNum < lvaCount);
         LclVarDsc* varDsc = &lvaTable[varNum];
 
-        // At this point any TYP_STRUCT LclVar must be a 16-byte struct
+        // At this point any TYP_STRUCT LclVar must be an aligned struct
         // or an HFA struct, both which are passed by value.
         //
-        assert((varDsc->lvSize() == 2 * TARGET_POINTER_SIZE) || varDsc->lvIsHfa());
+        assert((varDsc->lvSize() == elemCount * TARGET_POINTER_SIZE) || varDsc->lvIsHfa());
 
         varDsc->lvIsMultiRegArg = true;
 
@@ -4856,8 +4893,12 @@ GenTreePtr Compiler::fgMorphMultiregStructArg(GenTreePtr arg, fgArgTabEntryPtr f
         }
         else
         {
+#ifdef _TARGET_ARM64_
             // We must have a 16-byte struct (non-HFA)
             noway_assert(elemCount == 2);
+#elif defined(_TARGET_ARM_)
+            noway_assert(elemCount <= 4);
+#endif
 
             for (unsigned inx = 0; inx < elemCount; inx++)
             {
@@ -4879,6 +4920,7 @@ GenTreePtr Compiler::fgMorphMultiregStructArg(GenTreePtr arg, fgArgTabEntryPtr f
             }
         }
 
+#ifdef _TARGET_ARM64_
         // Is this LclVar a promoted struct with exactly 2 fields?
         // TODO-ARM64-CQ: Support struct promoted HFA types here
         if (varDsc->lvPromoted && (varDsc->lvFieldCnt == 2) && !varDsc->lvIsHfa())
@@ -4930,6 +4972,78 @@ GenTreePtr Compiler::fgMorphMultiregStructArg(GenTreePtr arg, fgArgTabEntryPtr f
             //
             lvaSetVarDoNotEnregister(varNum DEBUG_ARG(DNER_LocalField));
         }
+#elif defined(_TARGET_ARM_)
+        // Is this LclVar a promoted struct with exactly same size?
+        if (varDsc->lvPromoted && (varDsc->lvFieldCnt == elemCount) && !varDsc->lvIsHfa())
+        {
+            // See if we have promoted fields?
+            unsigned varNums[4];
+            bool     hasBadVarNum = false;
+            for (unsigned inx = 0; inx < elemCount; inx++)
+            {
+                varNums[inx] = lvaGetFieldLocal(varDsc, TARGET_POINTER_SIZE * inx);
+                if (varNums[inx] == BAD_VAR_NUM)
+                {
+                    hasBadVarNum = true;
+                    break;
+                }
+            }
+
+            // Did we find the promoted fields at the necessary offsets?
+            if (!hasBadVarNum)
+            {
+                LclVarDsc* varDscs[4];
+                var_types  varType[4];
+                bool       varIsFloat = false;
+
+                for (unsigned inx = 0; inx < elemCount; inx++)
+                {
+                    varDscs[inx] = &lvaTable[inx];
+                    varType[inx] = varDscs[inx]->lvType;
+                    if (varTypeIsFloating(varType[inx]))
+                    {
+                        // TODO-LSRA - It currently doesn't support the passing of floating point LCL_VARS in the
+                        // integer
+                        // registers. So for now we will use GT_LCLFLD's to pass this struct (it won't be enregistered)
+                        //
+                        JITDUMP("Multireg struct V%02u will be passed using GT_LCLFLD because it has float fields.\n",
+                                varNum);
+                        //
+                        // we call lvaSetVarDoNotEnregister and do the proper transformation below.
+                        //
+                        varIsFloat = true;
+                        break;
+                    }
+                }
+
+                if (!varIsFloat)
+                {
+                    unsigned          offset    = 0;
+                    GenTreeFieldList* listEntry = nullptr;
+                    // We can use the struct promoted field as arguments
+                    for (unsigned inx = 0; inx < elemCount; inx++)
+                    {
+                        GenTreePtr lclVar = gtNewLclvNode(varNums[inx], varType[inx], varNums[inx]);
+                        // Create a new tree for 'arg'
+                        //    replace the existing LDOBJ(ADDR(LCLVAR))
+                        listEntry = new (this, GT_FIELD_LIST) GenTreeFieldList(lclVar, offset, varType[inx], listEntry);
+                        if (newArg == nullptr)
+                        {
+                            newArg = listEntry;
+                        }
+                        offset += TARGET_POINTER_SIZE;
+                    }
+                }
+            }
+        }
+        else
+        {
+            //
+            // We will create a list of GT_LCL_FLDs nodes to pass this struct
+            //
+            lvaSetVarDoNotEnregister(varNum DEBUG_ARG(DNER_LocalField));
+        }
+#endif // _TARGET_ARM_
     }
 
     // If we didn't set newarg to a new List Node tree
@@ -13701,20 +13815,20 @@ GenTree* Compiler::fgMorphSmpOpOptional(GenTreeOp* tree)
 
             /* Make sure we have the operator range right */
 
-            noway_assert(GT_SUB == GT_ADD + 1);
-            noway_assert(GT_MUL == GT_ADD + 2);
-            noway_assert(GT_DIV == GT_ADD + 3);
-            noway_assert(GT_MOD == GT_ADD + 4);
-            noway_assert(GT_UDIV == GT_ADD + 5);
-            noway_assert(GT_UMOD == GT_ADD + 6);
+            static_assert(GT_SUB == GT_ADD + 1, "bad oper value");
+            static_assert(GT_MUL == GT_ADD + 2, "bad oper value");
+            static_assert(GT_DIV == GT_ADD + 3, "bad oper value");
+            static_assert(GT_MOD == GT_ADD + 4, "bad oper value");
+            static_assert(GT_UDIV == GT_ADD + 5, "bad oper value");
+            static_assert(GT_UMOD == GT_ADD + 6, "bad oper value");
 
-            noway_assert(GT_OR == GT_ADD + 7);
-            noway_assert(GT_XOR == GT_ADD + 8);
-            noway_assert(GT_AND == GT_ADD + 9);
+            static_assert(GT_OR == GT_ADD + 7, "bad oper value");
+            static_assert(GT_XOR == GT_ADD + 8, "bad oper value");
+            static_assert(GT_AND == GT_ADD + 9, "bad oper value");
 
-            noway_assert(GT_LSH == GT_ADD + 10);
-            noway_assert(GT_RSH == GT_ADD + 11);
-            noway_assert(GT_RSZ == GT_ADD + 12);
+            static_assert(GT_LSH == GT_ADD + 10, "bad oper value");
+            static_assert(GT_RSH == GT_ADD + 11, "bad oper value");
+            static_assert(GT_RSZ == GT_ADD + 12, "bad oper value");
 
             /* Check for a suitable operator on the RHS */
 
index a8bc2ec..cda00ac 100644 (file)
@@ -27,6 +27,8 @@ internal static partial class Interop
             internal long MTime;
             internal long CTime;
             internal long BirthTime;
+            internal long Dev;
+            internal long Ino;
         }
 
         internal static class FileTypes
index ea9915a..4dbd5cd 100644 (file)
@@ -17,6 +17,7 @@ using System.Collections.Generic;
 
 namespace System
 {
+    [Serializable]
     public sealed class CharEnumerator : IEnumerator, IEnumerator<char>, IDisposable, ICloneable
     {
         private String _str;
index 9010652..86e3cd4 100644 (file)
@@ -62,16 +62,5 @@ namespace System.Security
         public object PermitOnlySetInstance { get; set; }
         public string RefusedSet { get; set; }
         public string Url { get; set; }
-        public SecurityZone Zone { get; set; }
-    }
-
-    public enum SecurityZone
-    {
-        MyComputer   = 0,
-        Intranet     = 1,
-        Trusted      = 2,
-        Internet     = 3,
-        Untrusted    = 4,
-        NoZone       = -1
     }
 }
index df1a889..3a06114 100644 (file)
@@ -1081,67 +1081,56 @@ namespace System.Text
             return this;
         }
 
-        // Append joined values with a separator between each value.
-        public unsafe StringBuilder AppendJoin<T>(char separator, params T[] values)
-        {
-            // Defer argument validation to the internal function
-            return AppendJoinCore(&separator, 1, values);
-        }
+        
+        #region AppendJoin
 
-        public unsafe StringBuilder AppendJoin<T>(string separator, params T[] values)
+        public unsafe StringBuilder AppendJoin(string separator, params object[] values)
         {
             separator = separator ?? string.Empty;
             fixed (char* pSeparator = separator)
             {
-                // Defer argument validation to the internal function
                 return AppendJoinCore(pSeparator, separator.Length, values);
             }
         }
 
-        public unsafe StringBuilder AppendJoin<T>(char separator, IEnumerable<T> values)
+        public unsafe StringBuilder AppendJoin<T>(string separator, IEnumerable<T> values)
         {
-            // Defer argument validation to the internal function
-            return AppendJoinCore(&separator, 1, values);
+            separator = separator ?? string.Empty;
+            fixed (char* pSeparator = separator)
+            {
+                return AppendJoinCore(pSeparator, separator.Length, values);
+            }
         }
 
-        public unsafe StringBuilder AppendJoin<T>(string separator, IEnumerable<T> values)
+        public unsafe StringBuilder AppendJoin(string separator, params string[] values)
         {
             separator = separator ?? string.Empty;
             fixed (char* pSeparator = separator)
             {
-                // Defer argument validation to the internal function
                 return AppendJoinCore(pSeparator, separator.Length, values);
             }
         }
 
-        private unsafe StringBuilder AppendJoinCore<T>(char* separator, int separatorLength, params T[] values)
+        public unsafe StringBuilder AppendJoin(char separator, params object[] values)
         {
-            if (values == null)
-                throw new ArgumentNullException(nameof(values));
-            Contract.Ensures(Contract.Result<StringBuilder>() != null);
-
-            if (values.Length == 0)
-                return this;
+            return AppendJoinCore(&separator, 1, values);
+        }
 
-            var value = values[0];
-            if (value != null)
-                Append(value.ToString());
+        public unsafe StringBuilder AppendJoin<T>(char separator, IEnumerable<T> values)
+        {
+            return AppendJoinCore(&separator, 1, values);
+        }
 
-            for (var i = 1; i < values.Length; i++)
-            {
-                Append(separator, separatorLength);
-                value = values[i];
-                if (value != null)
-                    Append(value.ToString());
-            }
-            return this;
+        public unsafe StringBuilder AppendJoin(char separator, params string[] values)
+        {
+            return AppendJoinCore(&separator, 1, values);
         }
 
+        
         private unsafe StringBuilder AppendJoinCore<T>(char* separator, int separatorLength, IEnumerable<T> values)
         {
             if (values == null)
-                throw new ArgumentNullException(nameof(values));
-            Contract.Ensures(Contract.Result<StringBuilder>() != null);
+                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values);
 
             using (var en = values.GetEnumerator())
             {
@@ -1163,6 +1152,29 @@ namespace System.Text
             return this;
         }
 
+        private unsafe StringBuilder AppendJoinCore<T>(char* separator, int separatorLength, T[] values)
+        {
+            if (values == null)
+                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values);
+
+            if (values.Length == 0)
+                return this;
+
+            if (values[0] != null)
+                Append(values[0].ToString());
+
+            for (var i = 1; i < values.Length; i++)
+            {
+                Append(separator, separatorLength);
+                if (values[i] != null)
+                    Append(values[i].ToString());
+            }
+            return this;
+        }
+
+        #endregion
+
+
         /*====================================Insert====================================
         **
         ==============================================================================*/
index 67d1668..4e48088 100644 (file)
@@ -350,6 +350,7 @@ namespace System.Collections.Generic
 
 
         // Clears the contents of List.
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void Clear()
         {
             if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
index de0ff65..75ec57a 100644 (file)
@@ -179,7 +179,10 @@ namespace System
             else
                 return unchecked((int)((long)this._methodPtrAux));
             */
-            return GetType().GetHashCode();
+            if (_methodPtrAux.IsNull())
+                return ( _target != null ? RuntimeHelpers.GetHashCode(_target) * 33 : 0) + GetType().GetHashCode();
+            else
+                return GetType().GetHashCode();
         }
 
         public static Delegate Combine(Delegate a, Delegate b)
index 248e0d5..6fb6311 100644 (file)
@@ -824,6 +824,9 @@ namespace System.Runtime.InteropServices
         }
 
         [MethodImplAttribute(MethodImplOptions.InternalCall)]
+        public static extern /* struct _EXCEPTION_POINTERS* */ IntPtr GetExceptionPointers();
+        
+        [MethodImplAttribute(MethodImplOptions.InternalCall)]
         public static extern int GetExceptionCode();
 
 
index 4dcf8d4..ff76738 100644 (file)
@@ -416,6 +416,7 @@ namespace System
         type,
         stateMachine,
         pHandle,
+        values
     }
 
     //
index 5d2739e..9e97edc 100644 (file)
@@ -4826,6 +4826,161 @@ RegisterEventSourceW (
 #endif // !UNICODE
 
 //
+// NUMA related APIs
+//
+
+typedef enum _PROCESSOR_CACHE_TYPE { 
+  CacheUnified,
+  CacheInstruction,
+  CacheData,
+  CacheTrace
+} PROCESSOR_CACHE_TYPE;
+
+typedef struct _PROCESSOR_NUMBER {
+  WORD Group;
+  BYTE Number;
+  BYTE Reserved;
+} PROCESSOR_NUMBER, *PPROCESSOR_NUMBER;
+
+typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP { 
+  RelationProcessorCore,
+  RelationNumaNode,
+  RelationCache,
+  RelationProcessorPackage,
+  RelationGroup,
+  RelationAll               = 0xffff
+} LOGICAL_PROCESSOR_RELATIONSHIP;
+
+typedef ULONG_PTR KAFFINITY;
+
+#define ANYSIZE_ARRAY 1
+
+typedef struct _GROUP_AFFINITY {
+  KAFFINITY Mask;
+  WORD      Group;
+  WORD      Reserved[3];
+} GROUP_AFFINITY, *PGROUP_AFFINITY;
+
+typedef struct _PROCESSOR_GROUP_INFO {
+  BYTE      MaximumProcessorCount;
+  BYTE      ActiveProcessorCount;
+  BYTE      Reserved[38];
+  KAFFINITY ActiveProcessorMask;
+} PROCESSOR_GROUP_INFO, *PPROCESSOR_GROUP_INFO;
+
+typedef struct _PROCESSOR_RELATIONSHIP {
+  BYTE           Flags;
+  BYTE           EfficiencyClass;
+  BYTE           Reserved[21];
+  WORD           GroupCount;
+  GROUP_AFFINITY GroupMask[ANYSIZE_ARRAY];
+} PROCESSOR_RELATIONSHIP, *PPROCESSOR_RELATIONSHIP;
+
+typedef struct _GROUP_RELATIONSHIP {
+  WORD                 MaximumGroupCount;
+  WORD                 ActiveGroupCount;
+  BYTE                 Reserved[20];
+  PROCESSOR_GROUP_INFO GroupInfo[ANYSIZE_ARRAY];
+} GROUP_RELATIONSHIP, *PGROUP_RELATIONSHIP;
+
+typedef struct _NUMA_NODE_RELATIONSHIP {
+  DWORD          NodeNumber;
+  BYTE           Reserved[20];
+  GROUP_AFFINITY GroupMask;
+} NUMA_NODE_RELATIONSHIP, *PNUMA_NODE_RELATIONSHIP;
+
+typedef struct _CACHE_RELATIONSHIP {
+  BYTE                 Level;
+  BYTE                 Associativity;
+  WORD                 LineSize;
+  DWORD                CacheSize;
+  PROCESSOR_CACHE_TYPE Type;
+  BYTE                 Reserved[20];
+  GROUP_AFFINITY       GroupMask;
+} CACHE_RELATIONSHIP, *PCACHE_RELATIONSHIP;
+
+typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX {
+  LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
+  DWORD                          Size;
+  union {
+    PROCESSOR_RELATIONSHIP Processor;
+    NUMA_NODE_RELATIONSHIP NumaNode;
+    CACHE_RELATIONSHIP     Cache;
+    GROUP_RELATIONSHIP     Group;
+  };
+} SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX;
+
+
+PALIMPORT
+BOOL
+PALAPI
+GetNumaHighestNodeNumber(
+  OUT PULONG HighestNodeNumber
+);
+
+PALIMPORT
+BOOL
+PALAPI
+GetNumaProcessorNodeEx(
+  IN  PPROCESSOR_NUMBER Processor,
+  OUT PUSHORT NodeNumber
+);
+
+PALIMPORT
+LPVOID
+PALAPI
+VirtualAllocExNuma(
+  IN HANDLE hProcess,
+  IN OPTIONAL LPVOID lpAddress,
+  IN SIZE_T dwSize,
+  IN DWORD flAllocationType,
+  IN DWORD flProtect,
+  IN DWORD nndPreferred
+);
+
+PALIMPORT
+BOOL
+PALAPI
+GetLogicalProcessorInformationEx(
+  IN LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType,
+  OUT OPTIONAL PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer,
+  IN OUT PDWORD ReturnedLength
+);
+
+PALIMPORT
+BOOL
+PALAPI
+SetThreadGroupAffinity(
+  IN HANDLE hThread,
+  IN const GROUP_AFFINITY *GroupAffinity,
+  OUT OPTIONAL PGROUP_AFFINITY PreviousGroupAffinity
+);
+
+PALIMPORT
+BOOL
+PALAPI
+GetThreadGroupAffinity(
+  IN HANDLE hThread,
+  OUT PGROUP_AFFINITY GroupAffinity
+);
+
+PALIMPORT
+VOID
+PALAPI
+GetCurrentProcessorNumberEx(
+  OUT PPROCESSOR_NUMBER ProcNumber
+);
+
+PALIMPORT
+BOOL
+PALAPI
+GetProcessAffinityMask(
+  IN HANDLE hProcess,
+  OUT PDWORD_PTR lpProcessAffinityMask,
+  OUT PDWORD_PTR lpSystemAffinityMask
+);
+
+//
 // The types of events that can be logged.
 //
 #define EVENTLOG_SUCCESS                0x0000
index 51f90b9..d1c2209 100644 (file)
@@ -252,7 +252,7 @@ inline void *__cdecl operator new(size_t, void *_P)
 #define STDMETHODCALLTYPE    __stdcall
 #define STDMETHODVCALLTYPE   __cdecl
 
-#define STDAPICALLTYPE       __stdcall
+#define STDAPICALLTYPE       __cdecl
 #define STDAPIVCALLTYPE      __cdecl
 
 #define STDMETHODIMP         HRESULT STDMETHODCALLTYPE
index 5314cdf..145c2c9 100644 (file)
@@ -181,6 +181,7 @@ set(SOURCES
   misc/sysinfo.cpp
   misc/time.cpp
   misc/utils.cpp
+  numa/numa.cpp
   objmgr/palobjbase.cpp
   objmgr/shmobject.cpp
   objmgr/shmobjectmanager.cpp
@@ -372,6 +373,12 @@ if(CMAKE_SYSTEM_NAME STREQUAL NetBSD)
   )
 endif(CMAKE_SYSTEM_NAME STREQUAL NetBSD)
 
+if(HAVE_NUMA_H)
+  target_link_libraries(coreclrpal
+    numa
+  )
+endif(HAVE_NUMA_H)
+
 add_subdirectory(examples)
 
 if(FEATURE_EVENT_TRACE)
index c2939f3..e3024ac 100644 (file)
@@ -21,6 +21,8 @@
 #cmakedefine01 HAVE_SYS_SYSCTL_H
 #cmakedefine01 HAVE_GNU_LIBNAMES_H
 #cmakedefine01 HAVE_PRCTL_H
+#cmakedefine01 HAVE_NUMA_H
+#cmakedefine01 HAVE_PTHREAD_NP_H
 
 #cmakedefine01 HAVE_KQUEUE
 #cmakedefine01 HAVE_GETPWUID_R
@@ -33,6 +35,8 @@
 #cmakedefine01 HAVE_PTHREAD_GETATTR_NP
 #cmakedefine01 HAVE_PTHREAD_GETCPUCLOCKID
 #cmakedefine01 HAVE_PTHREAD_SIGQUEUE
+#cmakedefine01 HAVE_PTHREAD_GETAFFINITY_NP
+#cmakedefine01 HAVE_CPUSET_T
 #cmakedefine01 HAVE_SIGRETURN
 #cmakedefine01 HAVE__THREAD_SYS_SIGRETURN
 #cmakedefine01 HAVE_COPYSIGN
@@ -57,6 +61,7 @@
 #cmakedefine01 HAS_SYSV_SEMAPHORES
 #cmakedefine01 HAS_PTHREAD_MUTEXES
 #cmakedefine01 HAVE_TTRACE
+#cmakedefine01 HAVE_SCHED_GETAFFINITY
 #cmakedefine HAVE_UNW_GET_SAVE_LOC
 #cmakedefine HAVE_UNW_GET_ACCESSORS
 #cmakedefine01 HAVE_XSWDEV
index 03c7343..f9a23e8 100644 (file)
@@ -35,6 +35,8 @@ check_include_files(libunwind.h HAVE_LIBUNWIND_H)
 check_include_files(runetype.h HAVE_RUNETYPE_H)
 check_include_files(semaphore.h HAVE_SEMAPHORE_H)
 check_include_files(sys/prctl.h HAVE_PRCTL_H)
+check_include_files(numa.h HAVE_NUMA_H)
+check_include_files(pthread_np.h HAVE_PTHREAD_NP_H)
 
 if(NOT CMAKE_SYSTEM_NAME STREQUAL FreeBSD AND NOT CMAKE_SYSTEM_NAME STREQUAL NetBSD)
   set(CMAKE_REQUIRED_FLAGS "-ldl")
@@ -69,6 +71,7 @@ check_library_exists(${PTHREAD_LIBRARY} pthread_attr_get_np "" HAVE_PTHREAD_ATTR
 check_library_exists(${PTHREAD_LIBRARY} pthread_getattr_np "" HAVE_PTHREAD_GETATTR_NP)
 check_library_exists(${PTHREAD_LIBRARY} pthread_getcpuclockid "" HAVE_PTHREAD_GETCPUCLOCKID)
 check_library_exists(${PTHREAD_LIBRARY} pthread_sigqueue "" HAVE_PTHREAD_SIGQUEUE)
+check_library_exists(${PTHREAD_LIBRARY} pthread_getaffinity_np "" HAVE_PTHREAD_GETAFFINITY_NP)
 
 check_function_exists(sigreturn HAVE_SIGRETURN)
 check_function_exists(_thread_sys_sigreturn HAVE__THREAD_SYS_SIGRETURN)
@@ -119,6 +122,14 @@ int main(int argc, char **argv) {
 }" HAVE_UNW_GET_ACCESSORS)
 set(CMAKE_REQUIRED_LIBRARIES)
 
+check_cxx_source_compiles("
+#include <pthread_np.h>
+int main(int argc, char **argv) {
+  cpuset_t cpuSet;
+
+  return 0;
+}" HAVE_CPUSET_T)
+
 check_struct_has_member ("struct stat" st_atimespec "sys/types.h;sys/stat.h" HAVE_STAT_TIMESPEC)
 check_struct_has_member ("struct stat" st_atimensec "sys/types.h;sys/stat.h" HAVE_STAT_NSEC)
 check_struct_has_member ("struct tm" tm_gmtoff time.h HAVE_TM_GMTOFF)
index 7a49fc0..052c6fa 100644 (file)
@@ -194,7 +194,7 @@ typedef enum
 #ifdef FEATURE_PAL_SXS
     DCI_SXS,
 #endif // FEATURE_PAL_SXS
-
+    DCI_NUMA,
     DCI_LAST
 } DBG_CHANNEL_ID;
 
diff --git a/src/pal/src/include/pal/numa.h b/src/pal/src/include/pal/numa.h
new file mode 100644 (file)
index 0000000..4fb2308
--- /dev/null
@@ -0,0 +1,39 @@
+// 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.
+
+/*++
+
+
+
+Module Name:
+
+    include/pal/numa.h
+
+Abstract:
+    
+    Header file for the NUMA functions.
+    
+
+
+--*/
+
+#ifndef _PAL_NUMA_H_
+#define _PAL_NUMA_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+BOOL
+NUMASupportInitialize();
+
+VOID
+NUMASupportCleanup();
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* _PAL_CRITSECT_H_ */
index 8b0e0f5..2fdafe4 100644 (file)
@@ -42,6 +42,7 @@ SET_DEFAULT_DEBUG_CHANNEL(PAL); // some headers have code with asserts, so do th
 #include "pal/debug.h"
 #include "pal/locale.h"
 #include "pal/init.h"
+#include "pal/numa.h"
 #include "pal/stackstring.hpp"
 
 #if HAVE_MACH_EXCEPTIONS
@@ -523,6 +524,12 @@ Initialize(
             goto CLEANUP15;
         }
 
+        if (FALSE == NUMASupportInitialize())
+        {
+            ERROR("Unable to initialize NUMA support\n");
+            goto CLEANUP15;
+        }
+
         TRACE("First-time PAL initialization complete.\n");
         init_count++;        
 
@@ -548,6 +555,7 @@ Initialize(
     }
     goto done;
 
+    NUMASupportCleanup();
     /* No cleanup required for CRTInitStdStreams */ 
 CLEANUP15:
     FILECleanupStdHandles();
index d52ba1e..7e00843 100644 (file)
@@ -1350,7 +1350,6 @@ done:
     return pRetVal;
 }
 
-
 /*++
 Function:
   VirtualFree
index fff0518..70fe3e6 100644 (file)
@@ -94,6 +94,39 @@ SET_DEFAULT_DEBUG_CHANNEL(MISC);
 #endif
 #endif // __APPLE__
 
+/*++
+Function:
+    GetNumberOfProcessors
+
+Return number of processors available for the current process
+--*/
+int GetNumberOfProcessors()
+{
+    int nrcpus = 0;
+
+#if HAVE_SYSCONF
+    nrcpus = sysconf(_SC_NPROCESSORS_ONLN);
+    if (nrcpus < 1)
+    {
+        ASSERT("sysconf failed for _SC_NPROCESSORS_ONLN (%d)\n", errno);
+    }
+#elif HAVE_SYSCTL
+    int rc;
+    size_t sz;
+    int mib[2];
+
+    sz = sizeof(nrcpus);
+    mib[0] = CTL_HW;
+    mib[1] = HW_NCPU;
+    rc = sysctl(mib, 2, &nrcpus, &sz, NULL, 0);
+    if (rc != 0)
+    {
+        ASSERT("sysctl failed for HW_NCPU (%d)\n", errno);
+    }
+#endif // HAVE_SYSCONF
+
+    return nrcpus;
+}
 
 /*++
 Function:
@@ -137,27 +170,7 @@ GetSystemInfo(
     lpSystemInfo->dwPageSize = pagesize;
     lpSystemInfo->dwActiveProcessorMask_PAL_Undefined = 0;
 
-#if HAVE_SYSCONF
-    nrcpus = sysconf(_SC_NPROCESSORS_ONLN);
-    if (nrcpus < 1)
-    {
-        ASSERT("sysconf failed for _SC_NPROCESSORS_ONLN (%d)\n", errno);
-    }
-#elif HAVE_SYSCTL
-    int rc;
-    size_t sz;
-    int mib[2];
-
-    sz = sizeof(nrcpus);
-    mib[0] = CTL_HW;
-    mib[1] = HW_NCPU;
-    rc = sysctl(mib, 2, &nrcpus, &sz, NULL, 0);
-    if (rc != 0)
-    {
-        ASSERT("sysctl failed for HW_NCPU (%d)\n", errno);
-    }
-#endif // HAVE_SYSCONF
-
+    nrcpus = GetNumberOfProcessors();
     TRACE("dwNumberOfProcessors=%d\n", nrcpus);
     lpSystemInfo->dwNumberOfProcessors = nrcpus;
 
diff --git a/src/pal/src/numa/numa.cpp b/src/pal/src/numa/numa.cpp
new file mode 100644 (file)
index 0000000..549c10a
--- /dev/null
@@ -0,0 +1,692 @@
+// 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.
+
+/*++
+
+
+
+Module Name:
+
+    numa.cpp
+
+Abstract:
+
+    Implementation of NUMA related APIs
+
+--*/
+
+#include "pal/dbgmsg.h"
+SET_DEFAULT_DEBUG_CHANNEL(NUMA);
+
+#include "pal/palinternal.h"
+#include "pal/dbgmsg.h"
+#include "pal/numa.h"
+#include "pal/corunix.hpp"
+#include "pal/thread.hpp"
+
+#if HAVE_NUMA_H
+#include <numa.h>
+#include <numaif.h>
+#endif
+
+#if HAVE_PTHREAD_NP_H
+#include <pthread_np.h>
+#endif
+
+#include <pthread.h>
+
+using namespace CorUnix;
+
+#if HAVE_CPUSET_T
+typedef cpuset_t cpu_set_t;
+#endif
+
+int GetNumberOfProcessors();
+
+// CPU affinity descriptor
+struct CpuAffinity
+{
+    // NUMA node
+    BYTE Node;
+    // CPU number relative to the group the CPU is in
+    BYTE Number;
+    // CPU group
+    WORD Group;
+};
+
+// Array mapping global CPU index to its affinity
+CpuAffinity *g_cpuToAffinity = NULL;
+
+// Array mapping CPU group and index in the group to the global CPU index
+short *g_groupAndIndexToCpu = NULL;
+// Array mapping CPU group to the corresponding affinity mask of the CPUs in the group
+KAFFINITY *g_groupToCpuMask = NULL;
+// Array mapping CPU group to the number of processors in the group
+BYTE *g_groupToCpuCount = NULL;
+
+// Total number of processors in the system
+int g_cpuCount = 0;
+// Total number of CPU groups
+int g_groupCount = 0;
+// The highest NUMA node available
+int g_highestNumaNode = 0;
+
+static const int MaxCpusPerGroup = 8 * sizeof(KAFFINITY);
+static const WORD NO_GROUP = 0xffff;
+
+/*++
+Function:
+  AllocateLookupArrays
+
+Allocate CPU and group lookup arrays
+--*/
+VOID
+AllocateLookupArrays()
+{
+    g_groupAndIndexToCpu = (short*)malloc(g_groupCount * MaxCpusPerGroup * sizeof(short));
+    g_cpuToAffinity = (CpuAffinity*)malloc(g_cpuCount * sizeof(CpuAffinity));
+    g_groupToCpuMask = (KAFFINITY*)malloc(g_groupCount * sizeof(KAFFINITY));
+    g_groupToCpuCount = (BYTE*)malloc(g_groupCount * sizeof(BYTE));
+
+    memset(g_groupAndIndexToCpu, 0xff, g_groupCount * MaxCpusPerGroup * sizeof(short));
+    memset(g_cpuToAffinity, 0xff, g_cpuCount * sizeof(CpuAffinity));
+    memset(g_groupToCpuMask, 0, g_groupCount * sizeof(KAFFINITY));
+    memset(g_groupToCpuCount, 0, g_groupCount * sizeof(BYTE));
+}
+
+/*++
+Function:
+  FreeLookupArrays
+
+Free CPU and group lookup arrays
+--*/
+VOID
+FreeLookupArrays()
+{
+    free(g_groupAndIndexToCpu);
+    free(g_cpuToAffinity);
+    free(g_groupToCpuMask);
+    free(g_groupToCpuCount);
+
+    g_groupAndIndexToCpu = NULL;
+    g_cpuToAffinity = NULL;
+    g_groupToCpuMask = NULL;
+    g_groupToCpuCount = NULL;
+}
+
+/*++
+Function:
+  GetFullAffinityMask
+
+Get affinity mask for the specified number of processors with all
+the processors enabled.
+--*/
+KAFFINITY GetFullAffinityMask(int cpuCount)
+{
+    return ((KAFFINITY)1 << (cpuCount)) - 1;
+}
+
+/*++
+Function:
+  NUMASupportInitialize
+
+Initialize data structures for getting and setting thread affinities to processors and
+querying NUMA related processor information.
+On systems with no NUMA support, it behaves as if there was a single NUMA node with
+a single group of processors.
+--*/
+BOOL
+NUMASupportInitialize()
+{
+#if HAVE_NUMA_H
+    if (numa_available() != -1)
+    {
+        struct bitmask *mask = numa_allocate_cpumask();
+        int numaNodesCount = numa_max_node() + 1;
+
+        g_cpuCount = numa_num_possible_cpus();
+        g_groupCount = 0;
+
+        for (int i = 0; i < numaNodesCount; i++)
+        {
+            int st = numa_node_to_cpus(i, mask);
+            // The only failure that can happen is that the mask is not large enough
+            // but that cannot happen since the mask was allocated by numa_allocate_cpumask
+            _ASSERTE(st == 0);
+            unsigned int nodeCpuCount = numa_bitmask_weight(mask);
+            unsigned int nodeGroupCount = (nodeCpuCount + MaxCpusPerGroup - 1) / MaxCpusPerGroup;
+            g_groupCount += nodeGroupCount;
+        }
+
+        AllocateLookupArrays();
+
+        WORD currentGroup = 0;
+        int currentGroupCpus = 0;
+
+        for (int i = 0; i < numaNodesCount; i++)
+        {
+            int st = numa_node_to_cpus(i, mask);
+            // The only failure that can happen is that the mask is not large enough
+            // but that cannot happen since the mask was allocated by numa_allocate_cpumask
+            _ASSERTE(st == 0);
+            unsigned int nodeCpuCount = numa_bitmask_weight(mask);
+            unsigned int nodeGroupCount = (nodeCpuCount + MaxCpusPerGroup - 1) / MaxCpusPerGroup;
+            for (int j = 0; j < g_cpuCount; j++)
+            {
+                if (numa_bitmask_isbitset(mask, j))
+                {
+                    if (currentGroupCpus == MaxCpusPerGroup)
+                    {
+                        g_groupToCpuCount[currentGroup] = MaxCpusPerGroup;
+                        g_groupToCpuMask[currentGroup] = GetFullAffinityMask(MaxCpusPerGroup);
+                        currentGroupCpus = 0;
+                        currentGroup++;
+                    }
+                    g_cpuToAffinity[j].Node = i;
+                    g_cpuToAffinity[j].Group = currentGroup;
+                    g_cpuToAffinity[j].Number = currentGroupCpus;
+                    g_groupAndIndexToCpu[currentGroup * MaxCpusPerGroup + currentGroupCpus] = j;
+                    currentGroupCpus++;
+                }
+            }
+
+            if (currentGroupCpus != 0)
+            {
+                g_groupToCpuCount[currentGroup] = currentGroupCpus;
+                g_groupToCpuMask[currentGroup] = GetFullAffinityMask(currentGroupCpus);
+                currentGroupCpus = 0;
+                currentGroup++;
+            }
+        }
+
+        numa_free_cpumask(mask);
+
+        g_highestNumaNode = numa_max_node();
+    }
+    else
+#endif // HAVE_NUMA_H
+    {
+        // No NUMA
+        g_cpuCount = GetNumberOfProcessors();
+        g_groupCount = 1;
+        g_highestNumaNode = 0;
+
+        AllocateLookupArrays();
+    }
+
+    return TRUE;
+}
+
+/*++
+Function:
+  NUMASupportCleanup
+
+Cleanup of the NUMA support data structures
+--*/
+VOID
+NUMASupportCleanup()
+{
+    FreeLookupArrays();
+}
+
+/*++
+Function:
+  GetNumaHighestNodeNumber
+
+See MSDN doc.
+--*/
+BOOL
+PALAPI
+GetNumaHighestNodeNumber(
+  OUT PULONG HighestNodeNumber
+)
+{
+    PERF_ENTRY(GetNumaHighestNodeNumber);
+    ENTRY("GetNumaHighestNodeNumber(HighestNodeNumber=%p)\n", HighestNodeNumber);
+    *HighestNodeNumber = (ULONG)g_highestNumaNode;
+
+    BOOL success = TRUE;
+
+    LOGEXIT("GetNumaHighestNodeNumber returns BOOL %d\n", success);
+    PERF_EXIT(GetNumaHighestNodeNumber);
+
+    return success;
+}
+
+/*++
+Function:
+  GetNumaProcessorNodeEx
+
+See MSDN doc.
+--*/
+BOOL
+PALAPI
+GetNumaProcessorNodeEx(
+  IN  PPROCESSOR_NUMBER Processor,
+  OUT PUSHORT NodeNumber
+)
+{
+    PERF_ENTRY(GetNumaProcessorNodeEx);
+    ENTRY("GetNumaProcessorNodeEx(Processor=%p, NodeNumber=%p)\n", Processor, NodeNumber);
+
+    BOOL success = FALSE;
+
+    if ((Processor->Group < g_groupCount) && 
+        (Processor->Number < MaxCpusPerGroup) && 
+        (Processor->Reserved == 0))
+    {  
+        short cpu = g_groupAndIndexToCpu[Processor->Group * MaxCpusPerGroup + Processor->Number];
+        if (cpu != -1)
+        {
+            *NodeNumber = g_cpuToAffinity[cpu].Node;
+            success = TRUE;
+        }
+    }
+
+    if (!success)
+    {
+        *NodeNumber = 0xffff;
+        SetLastError(ERROR_INVALID_PARAMETER);  
+    }
+
+    LOGEXIT("GetNumaProcessorNodeEx returns BOOL %d\n", success);
+    PERF_EXIT(GetNumaProcessorNodeEx);
+
+    return success;
+}
+
+/*++
+Function:
+  GetLogicalProcessorInformationEx
+
+See MSDN doc.
+--*/
+BOOL
+PALAPI
+GetLogicalProcessorInformationEx(
+  IN LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType,
+  OUT OPTIONAL PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer,
+  IN OUT PDWORD ReturnedLength
+)
+{
+    PERF_ENTRY(GetLogicalProcessorInformationEx);
+    ENTRY("GetLogicalProcessorInformationEx(RelationshipType=%d, Buffer=%p, ReturnedLength=%p)\n", RelationshipType, Buffer, ReturnedLength);
+
+    BOOL success = FALSE;
+
+    if (RelationshipType == RelationGroup)
+    {
+        size_t requiredSize = __builtin_offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Group);
+        requiredSize += __builtin_offsetof(GROUP_RELATIONSHIP, GroupInfo);
+        requiredSize += g_groupCount * sizeof(PROCESSOR_GROUP_INFO);
+
+        if (*ReturnedLength >= requiredSize)
+        {
+            Buffer->Relationship = RelationGroup;
+            Buffer->Size = requiredSize;
+            Buffer->Group.MaximumGroupCount = g_groupCount;
+            Buffer->Group.ActiveGroupCount = g_groupCount;
+            for (int i = 0; i < g_groupCount; i++)
+            {
+                Buffer->Group.GroupInfo[i].MaximumProcessorCount = MaxCpusPerGroup;
+                Buffer->Group.GroupInfo[i].ActiveProcessorCount = g_groupToCpuCount[i];
+                Buffer->Group.GroupInfo[i].ActiveProcessorMask = g_groupToCpuMask[i];
+            }
+
+            success = TRUE;
+        }
+        else
+        {
+            SetLastError(ERROR_INSUFFICIENT_BUFFER);
+        }
+
+        *ReturnedLength = requiredSize;
+    }
+    else
+    {
+        // We only support the group relationship
+        SetLastError(ERROR_INVALID_PARAMETER);  
+    }
+
+    LOGEXIT("GetLogicalProcessorInformationEx returns BOOL %d\n", success);
+    PERF_EXIT(GetLogicalProcessorInformationEx);
+
+    return success;
+}
+
+/*++
+Function:
+  GetThreadGroupAffinityInternal
+
+Get the group affinity for the specified pthread
+--*/
+BOOL
+GetThreadGroupAffinityInternal(
+  IN pthread_t thread,
+  OUT PGROUP_AFFINITY GroupAffinity
+)
+{
+    BOOL success = FALSE;
+
+#if HAVE_PTHREAD_GETAFFINITY_NP
+    cpu_set_t cpuSet;
+
+    int st = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuSet);
+
+    if (st == 0)
+    {
+        WORD group = NO_GROUP;
+        KAFFINITY mask = 0;
+
+        for (int i = 0; i < g_cpuCount; i++)
+        {
+            if (CPU_ISSET(i, &cpuSet))
+            {
+                WORD g = g_cpuToAffinity[i].Group;
+                // Unless the thread affinity was already set by SetThreadGroupAffinity, it is possible that
+                // the current thread has affinity with processors from multiple groups. So we report just the
+                // first group we find.
+                if (group == NO_GROUP || g == group)
+                {
+                    group = g;
+                    mask |= ((KAFFINITY)1) << g_cpuToAffinity[i].Number;
+                }
+            }
+        }
+
+        GroupAffinity->Group = group;
+        GroupAffinity->Mask = mask;
+        success = TRUE;
+    }
+    else
+    {
+        SetLastError(ERROR_GEN_FAILURE);
+    }
+#else // HAVE_PTHREAD_GETAFFINITY_NP
+    // There is no API to manage thread affinity, so let's return a group affinity
+    // with all the CPUs on the system.
+    GroupAffinity->Group = 0;
+    GroupAffinity->Mask = GetFullAffinityMask(g_cpuCount);
+    success = TRUE;
+#endif // HAVE_PTHREAD_GETAFFINITY_NP
+
+    return success;
+}
+
+/*++
+Function:
+  GetThreadGroupAffinity
+
+See MSDN doc.
+--*/
+BOOL
+PALAPI
+GetThreadGroupAffinity(
+  IN HANDLE hThread,
+  OUT PGROUP_AFFINITY GroupAffinity
+)
+{
+    PERF_ENTRY(GetThreadGroupAffinity);
+    ENTRY("GetThreadGroupAffinity(hThread=%p, GroupAffinity=%p)\n", hThread, GroupAffinity);
+
+    CPalThread *palThread = InternalGetCurrentThread();
+
+    BOOL success = GetThreadGroupAffinityInternal(palThread->GetPThreadSelf(), GroupAffinity);
+
+    LOGEXIT("GetThreadGroupAffinity returns BOOL %d\n", success);
+    PERF_EXIT(GetThreadGroupAffinity);
+
+    return success;
+}
+
+
+/*++
+Function:
+  SetThreadGroupAffinity
+
+See MSDN doc.
+--*/
+BOOL
+PALAPI
+SetThreadGroupAffinity(
+  IN HANDLE hThread,
+  IN const GROUP_AFFINITY *GroupAffinity,
+  OUT OPTIONAL PGROUP_AFFINITY PreviousGroupAffinity
+)
+{
+    PERF_ENTRY(SetThreadGroupAffinity);
+    ENTRY("SetThreadGroupAffinity(hThread=%p, GroupAffinity=%p, PreviousGroupAffinity=%p)\n", hThread, GroupAffinity, PreviousGroupAffinity);
+
+    CPalThread *palThread = InternalGetCurrentThread();
+
+    pthread_t thread = palThread->GetPThreadSelf();
+
+    if (PreviousGroupAffinity != NULL)
+    {
+        GetThreadGroupAffinityInternal(thread, PreviousGroupAffinity);
+    }
+
+#if HAVE_PTHREAD_GETAFFINITY_NP
+    int groupStartIndex = GroupAffinity->Group * MaxCpusPerGroup;
+    KAFFINITY mask = 1;
+    cpu_set_t cpuSet;
+    CPU_ZERO(&cpuSet);
+
+    for (int i = 0; i < MaxCpusPerGroup; i++, mask <<= 1)
+    {
+        if (GroupAffinity->Mask & mask)
+        {
+            int cpu = g_groupAndIndexToCpu[groupStartIndex + i];
+            if (cpu != -1)
+            {
+                CPU_SET(cpu, &cpuSet);
+            }
+        }
+    }
+
+    int st = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuSet);
+
+    if (st == -1)
+    {
+        switch (errno)
+        {
+            case EINVAL:
+                // There is no processor in the mask that is allowed to execute the process
+                SetLastError(ERROR_INVALID_PARAMETER);
+                break;
+            case EPERM:
+                SetLastError(ERROR_ACCESS_DENIED);
+                break;
+            default:
+                SetLastError(ERROR_GEN_FAILURE);
+                break;
+        }
+    }
+
+    BOOL success = (st == 0);
+#else // HAVE_PTHREAD_GETAFFINITY_NP
+    // There is no API to manage thread affinity, so let's ignore the request
+    BOOL success = TRUE;
+#endif // HAVE_PTHREAD_GETAFFINITY_NP
+
+    LOGEXIT("SetThreadGroupAffinity returns BOOL %d\n", success);
+    PERF_EXIT(SetThreadGroupAffinity);
+
+    return success;
+}
+
+/*++
+Function:
+  GetCurrentProcessorNumberEx
+
+See MSDN doc.
+--*/
+VOID
+PALAPI
+GetCurrentProcessorNumberEx(
+  OUT PPROCESSOR_NUMBER ProcNumber
+)
+{
+    PERF_ENTRY(GetCurrentProcessorNumberEx);
+    ENTRY("GetCurrentProcessorNumberEx(ProcNumber=%p\n", ProcNumber);
+
+    DWORD cpu = GetCurrentProcessorNumber();
+    _ASSERTE(cpu < g_cpuCount);
+    ProcNumber->Group = g_cpuToAffinity[cpu].Group;
+    ProcNumber->Number = g_cpuToAffinity[cpu].Number;
+
+    LOGEXIT("GetCurrentProcessorNumberEx\n");
+    PERF_EXIT(GetCurrentProcessorNumberEx);
+}
+
+/*++
+Function:
+  GetProcessAffinityMask
+
+See MSDN doc.
+--*/
+BOOL
+PALAPI
+GetProcessAffinityMask(
+  IN HANDLE hProcess,
+  OUT PDWORD_PTR lpProcessAffinityMask,
+  OUT PDWORD_PTR lpSystemAffinityMask
+)
+{
+    PERF_ENTRY(GetProcessAffinityMask);
+    ENTRY("GetProcessAffinityMask(hProcess=%p, lpProcessAffinityMask=%p, lpSystemAffinityMask=%p\n", hProcess, lpProcessAffinityMask, lpSystemAffinityMask);
+
+    BOOL success = FALSE;
+
+    if (hProcess == GetCurrentProcess())
+    {
+        DWORD_PTR systemMask = GetFullAffinityMask(g_cpuCount);
+
+#if HAVE_SCHED_GETAFFINITY
+        int pid = getpid();
+        cpu_set_t cpuSet;
+        int st = sched_getaffinity(pid, sizeof(cpu_set_t), &cpuSet);
+        if (st == 0)
+        {
+            WORD group = NO_GROUP;
+            DWORD_PTR processMask = 0;
+
+            for (int i = 0; i < g_cpuCount; i++)
+            {
+                if (CPU_ISSET(i, &cpuSet))
+                {
+                    WORD g = g_cpuToAffinity[i].Group;
+                    if (group == NO_GROUP || g == group)
+                    {
+                        group = g;
+                        processMask |= ((DWORD_PTR)1) << g_cpuToAffinity[i].Number;
+                    }
+                    else
+                    {
+                        // The process has affinity in more than one group, in such case
+                        // the function needs to return zero in both masks.
+                        processMask = 0;
+                        systemMask = 0;
+                        group = NO_GROUP;
+                        break;
+                    }
+                }
+            }
+
+            success = TRUE;
+
+            *lpProcessAffinityMask = processMask;
+            *lpSystemAffinityMask = systemMask;
+        }
+        else
+        {
+            // We should not get any of the errors that the sched_getaffinity can return since none
+            // of them applies for the current thread, so this is an unexpected kind of failure.
+            SetLastError(ERROR_GEN_FAILURE);
+        }
+#else // HAVE_SCHED_GETAFFINITY
+        // There is no API to manage thread affinity, so let's return both affinity masks
+        // with all the CPUs on the system set.
+        *lpSystemAffinityMask = systemMask;
+        *lpProcessAffinityMask = systemMask;
+
+        success = TRUE;
+#endif // HAVE_SCHED_GETAFFINITY
+    }
+    else
+    {
+        // PAL supports getting affinity mask for the current process only
+        SetLastError(ERROR_INVALID_PARAMETER);
+    }
+
+    LOGEXIT("GetProcessAffinityMask returns BOOL %d\n", success);
+    PERF_EXIT(GetProcessAffinityMask);
+
+    return success;
+}
+
+/*++
+Function:
+  VirtualAllocExNuma
+
+See MSDN doc.
+--*/
+LPVOID
+PALAPI
+VirtualAllocExNuma(
+  IN HANDLE hProcess,
+  IN OPTIONAL LPVOID lpAddress,
+  IN SIZE_T dwSize,
+  IN DWORD flAllocationType,
+  IN DWORD flProtect,
+  IN DWORD nndPreferred
+)
+{
+    PERF_ENTRY(VirtualAllocExNuma);
+    ENTRY("VirtualAllocExNuma(hProcess=%p, lpAddress=%p, dwSize=%u, flAllocationType=%#x, flProtect=%#x, nndPreferred=%d\n", 
+        hProcess, lpAddress, dwSize, flAllocationType, flProtect, nndPreferred);
+
+    LPVOID result = NULL;
+
+    if (hProcess == GetCurrentProcess())
+    {
+        if (nndPreferred <= g_highestNumaNode)
+        {
+            result = VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect);
+#if HAVE_NUMA_H
+            if (result != NULL)
+            {
+                int nodeMaskLength = (g_highestNumaNode + 1 + sizeof(unsigned long) - 1) / sizeof(unsigned long);
+                unsigned long *nodeMask = new unsigned long[nodeMaskLength];
+
+                memset(nodeMask, 0, nodeMaskLength);
+
+                int index = nndPreferred / sizeof(unsigned long);
+                int mask = ((unsigned long)1) << (nndPreferred & (sizeof(unsigned long) - 1));
+                nodeMask[index] = mask;
+
+                int st = mbind(result, dwSize, MPOL_PREFERRED, nodeMask, g_highestNumaNode, 0);
+                free(nodeMask);
+                _ASSERTE(st == 0);
+                // If the mbind fails, we still return the allocated memory since the nndPreferred is just a hint
+            }
+#endif // HAVE_NUMA_H
+        }
+        else
+        {
+            // The specified node number is larger than the maximum available one
+            SetLastError(ERROR_INVALID_PARAMETER);
+        }
+    }    
+    else
+    {
+        // PAL supports allocating from the current process virtual space only
+        SetLastError(ERROR_INVALID_PARAMETER);
+    }
+
+    LOGEXIT("VirtualAllocExNuma returns %p\n", result);
+    PERF_EXIT(VirtualAllocExNuma);
+
+    return result;
+}
index e7380ee..e7a2d2f 100644 (file)
@@ -149,7 +149,7 @@ DWORD gSID = (DWORD) -1;
 Volatile<PSHUTDOWN_CALLBACK> g_shutdownCallback = nullptr;
 
 // Crash dump generating program arguments. Initialized in PROCAbortInitialize().
-char *g_argvCreateDump[3] = { nullptr, nullptr, nullptr };
+char* g_argvCreateDump[8] = { nullptr };
 
 //
 // Key used for associating CPalThread's with the underlying pthread
@@ -2895,8 +2895,11 @@ PROCAbortInitialize()
         }
         const char* DumpGeneratorName = "createdump";
         int programLen = strlen(g_szCoreCLRPath) + strlen(DumpGeneratorName);
-        char* program = new char[programLen];
-
+        char* program = (char*)InternalMalloc(programLen);
+        if (program == nullptr)
+        {
+            return FALSE;
+        }
         if (strcpy_s(program, programLen, g_szCoreCLRPath) != SAFECRT_SUCCESS)
         {
             return FALSE;
@@ -2914,19 +2917,50 @@ PROCAbortInitialize()
         {
             return FALSE;
         }
-        char pidarg[128];
-        if (sprintf_s(pidarg, sizeof(pidarg), "%d", gPID) == -1)
+        char* pidarg = (char*)InternalMalloc(128);
+        if (pidarg == nullptr)
         {
             return FALSE;
         }
-        g_argvCreateDump[0] = program;
-        g_argvCreateDump[1] = _strdup(pidarg);
-        g_argvCreateDump[2] = nullptr;
-
-        if (g_argvCreateDump[0] == nullptr || g_argvCreateDump[1] == nullptr)
+        if (sprintf_s(pidarg, 128, "%d", gPID) == -1)
         {
             return FALSE;
         }
+        const char** argv = (const char**)g_argvCreateDump;
+        *argv++ = program;
+
+        char* envvar = getenv("COMPlus_DbgMiniDumpName");
+        if (envvar != nullptr)
+        {
+            *argv++ = "--name";
+            *argv++ = envvar;
+        }
+
+        envvar = getenv("COMPlus_DbgMiniDumpType");
+        if (envvar != nullptr)
+        {
+            if (strcmp(envvar, "1") == 0)
+            {
+                *argv++ = "--normal";
+            }
+            else if (strcmp(envvar, "2") == 0)
+            {
+                *argv++ = "--withheap";
+            }
+            else if (strcmp(envvar, "3") == 0)
+            {
+                *argv++ = "--micro";
+            }
+        }
+
+        envvar = getenv("COMPlus_CreateDumpDiagnostics");
+        if (envvar != nullptr && strcmp(envvar, "1") == 0)
+        {
+            *argv++ = "--diag";
+        }
+
+        *argv++ = pidarg;
+        *argv = nullptr;
     }
     return TRUE;
 }
index b02cde3..2b9b4b8 100644 (file)
@@ -39,15 +39,15 @@ FunctionPointer ApiShim(LPCSTR szApiName)
 // Shim APIs, passing off into the desktop VM
 //
 
-IExecutionEngine * __stdcall SnIEE()
+IExecutionEngine* SnIEE()
 {
-    typedef IExecutionEngine * ( __stdcall *IEEFn_t)();
+    typedef IExecutionEngine* (* IEEFn_t)();
     return ApiShim<IEEFn_t>("IEE")();
 }
 
-STDAPI SnGetCorSystemDirectory(SString&  pbuffer)
+HRESULT SnGetCorSystemDirectory(SString&  pbuffer)
 {
-    typedef HRESULT (__stdcall *GetCorSystemDirectoryFn_t)(SString&);
+    typedef HRESULT (*GetCorSystemDirectoryFn_t)(SString&);
     return ApiShim<GetCorSystemDirectoryFn_t>("GetCORSystemDirectory")(pbuffer);
 }
 
index c215a49..a8786de 100644 (file)
@@ -728,7 +728,7 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr,
 //******************************************************************************
 // NumaNodeInfo 
 //******************************************************************************
-#if !defined(FEATURE_REDHAWK) && !defined(FEATURE_PAL)
+#if !defined(FEATURE_REDHAWK)
 /*static*/ NumaNodeInfo::PGNHNN NumaNodeInfo::m_pGetNumaHighestNodeNumber = NULL;
 /*static*/ NumaNodeInfo::PVAExN NumaNodeInfo::m_pVirtualAllocExNuma = NULL;
 
@@ -748,15 +748,19 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr,
 /*static*/ BOOL NumaNodeInfo::m_enableGCNumaAware = FALSE;
 /*static*/ BOOL NumaNodeInfo::InitNumaNodeInfoAPI()
 {
-#if !defined(FEATURE_REDHAWK) && !defined(FEATURE_PAL)
+#if !defined(FEATURE_REDHAWK)
     //check for numa support if multiple heaps are used
     ULONG highest = 0;
        
     if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_GCNumaAware) == 0)
         return FALSE;
 
+#ifndef FEATURE_PAL
     // check if required APIs are supported
     HMODULE hMod = GetModuleHandleW(WINDOWS_KERNEL32_DLLNAME_W);
+#else
+    HMODULE hMod = GetCLRModule();
+#endif    
     if (hMod == NULL)
         return FALSE;
 
@@ -795,7 +799,7 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr,
 //******************************************************************************
 // NumaNodeInfo 
 //******************************************************************************
-#if !defined(FEATURE_REDHAWK) && !defined(FEATURE_PAL)
+#if !defined(FEATURE_REDHAWK)
 /*static*/ CPUGroupInfo::PGLPIEx CPUGroupInfo::m_pGetLogicalProcessorInformationEx = NULL;
 /*static*/ CPUGroupInfo::PSTGA   CPUGroupInfo::m_pSetThreadGroupAffinity = NULL;
 /*static*/ CPUGroupInfo::PGTGA   CPUGroupInfo::m_pGetThreadGroupAffinity = NULL;
@@ -848,8 +852,12 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr,
     }
     CONTRACTL_END;
 
-#if !defined(FEATURE_REDHAWK) && defined(_TARGET_AMD64_) && !defined(FEATURE_PAL)
+#if !defined(FEATURE_REDHAWK) && defined(_TARGET_AMD64_)
+#ifndef FEATURE_PAL    
     HMODULE hMod = GetModuleHandleW(WINDOWS_KERNEL32_DLLNAME_W);
+#else
+    HMODULE hMod = GetCLRModule();
+#endif
     if (hMod == NULL)
         return FALSE;
 
@@ -869,17 +877,19 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr,
     if (m_pGetCurrentProcessorNumberEx == NULL)
         return FALSE;
 
+#ifndef FEATURE_PAL    
     m_pGetSystemTimes = (PGST)GetProcAddress(hMod, "GetSystemTimes");
     if (m_pGetSystemTimes == NULL)
         return FALSE;
-
+#endif
+    
     return TRUE;
 #else
     return FALSE;
 #endif
 }
 
-#if !defined(FEATURE_REDHAWK) && defined(_TARGET_AMD64_) && !defined(FEATURE_PAL)
+#if !defined(FEATURE_REDHAWK) && defined(_TARGET_AMD64_)
 // Calculate greatest common divisor
 DWORD GCD(DWORD u, DWORD v)
 {
@@ -910,7 +920,7 @@ DWORD LCM(DWORD u, DWORD v)
     }
     CONTRACTL_END;
 
-#if !defined(FEATURE_REDHAWK) && defined(_TARGET_AMD64_) && !defined(FEATURE_PAL)
+#if !defined(FEATURE_REDHAWK) && defined(_TARGET_AMD64_)
     BYTE *bBuffer = NULL;
     SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *pSLPIEx = NULL;
     SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *pRecord = NULL;
@@ -985,7 +995,7 @@ DWORD LCM(DWORD u, DWORD v)
 {
     LIMITED_METHOD_CONTRACT;
 
-#if !defined(FEATURE_REDHAWK) && defined(_TARGET_AMD64_) && !defined(FEATURE_PAL)
+#if !defined(FEATURE_REDHAWK) && defined(_TARGET_AMD64_)
     WORD begin   = 0;
     WORD nr_proc = 0;
 
@@ -1012,7 +1022,7 @@ DWORD LCM(DWORD u, DWORD v)
     }
     CONTRACTL_END;
 
-#if !defined(FEATURE_REDHAWK) && defined(_TARGET_AMD64_) && !defined(FEATURE_PAL)
+#if !defined(FEATURE_REDHAWK) && defined(_TARGET_AMD64_)
     BOOL enableGCCPUGroups     = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_GCCpuGroup) != 0;
     BOOL threadUseAllCpuGroups = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_Thread_UseAllCpuGroups) != 0;
 
@@ -1095,7 +1105,7 @@ retry:
 {
     LIMITED_METHOD_CONTRACT;
 
-#if !defined(FEATURE_REDHAWK) && defined(_TARGET_AMD64_) && !defined(FEATURE_PAL)
+#if !defined(FEATURE_REDHAWK) && defined(_TARGET_AMD64_)
     WORD bTemp = 0;
     WORD bDiff = processor_number - bTemp;
 
@@ -1126,7 +1136,7 @@ retry:
     }
     CONTRACTL_END;
 
-#if !defined(FEATURE_REDHAWK) && defined(_TARGET_AMD64_) && !defined(FEATURE_PAL)
+#if !defined(FEATURE_REDHAWK) && defined(_TARGET_AMD64_)
     // m_enableGCCPUGroups and m_threadUseAllCpuGroups must be TRUE
     _ASSERTE(m_enableGCCPUGroups && m_threadUseAllCpuGroups);
 
@@ -1147,7 +1157,7 @@ retry:
 #endif
 }
 
-#if !defined(FEATURE_REDHAWK) && !defined(FEATURE_PAL)
+#if !defined(FEATURE_REDHAWK)
 //Lock ThreadStore before calling this function, so that updates of weights/counts are consistent
 /*static*/ void CPUGroupInfo::ChooseCPUGroupAffinity(GROUP_AFFINITY *gf)
 {
index 942d11b..4fd35b0 100644 (file)
@@ -4679,7 +4679,8 @@ OBJECTREF AppDomain::GetExposedObject()
         obj = (APPDOMAINREF) AllocateObject(pMT);
         obj->SetDomain(this);
 
-        if(StoreFirstObjectInHandle(m_ExposedObject, (OBJECTREF) obj) == FALSE) {
+        if (!StoreFirstObjectInHandle(m_ExposedObject, (OBJECTREF) obj))
+        {
             obj = (APPDOMAINREF) GetRawExposedObject();
             _ASSERTE(obj);
         }
index 8a3fb4f..8ab0a56 100644 (file)
@@ -30,6 +30,9 @@ public:
         LIMITED_METHOD_CONTRACT;
 #if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
         _ASSERTE((argLocDescForStructInRegs != NULL) || (offset != TransitionBlock::StructInRegsOffset));
+#elif defined(_TARGET_ARM64_)
+        // This assert is not interesting on arm64. argLocDescForStructInRegs could be
+        // initialized if the args are being enregistered.
 #else        
         _ASSERTE(argLocDescForStructInRegs == NULL);
 #endif        
@@ -42,6 +45,46 @@ public:
         return dac_cast<PTR_VOID>(dac_cast<TADDR>(m_base) + m_offset);
     }
 
+#if defined(_TARGET_ARM64_)
+#ifndef DACCESS_COMPILE
+
+    // Returns true if the ArgDestination represents an HFA struct
+    bool IsHFA()
+    {
+        return m_argLocDescForStructInRegs != NULL;
+    }
+
+    // Copy struct argument into registers described by the current ArgDestination.
+    // Arguments:
+    //  src = source data of the structure 
+    //  fieldBytes - size of the structure
+    void CopyHFAStructToRegister(void *src, int fieldBytes)
+    {
+        // We are either copying either a float or double HFA and need to
+        // enregister each field.
+
+        int floatRegCount = m_argLocDescForStructInRegs->m_cFloatReg;
+        bool typeFloat = m_argLocDescForStructInRegs->m_isSinglePrecision;
+        void* dest = this->GetDestinationAddress();
+
+        if (typeFloat)
+        {
+            for (int i = 0; i < floatRegCount; ++i) 
+            {
+                // Copy 4 bytes on 8 bytes alignment
+                *((UINT64*)dest + i) = *((UINT32*)src + i);
+            }
+        }
+        else
+        {
+            // We can just do a memcpy.
+            memcpyNoGCRefs(dest, src, fieldBytes);
+        }
+    }
+
+#endif // !DACCESS_COMPILE
+#endif // defined(_TARGET_ARM64_)
+
 #if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
 
     // Returns true if the ArgDestination represents a struct passed in registers.
index cde2ba4..b707b4b 100644 (file)
@@ -34,21 +34,26 @@ BOOL IsRetBuffPassedAsFirstArg();
 // and possibly on to the stack as well.
 struct ArgLocDesc
 {
-    int     m_idxFloatReg;  // First floating point register used (or -1)
-    int     m_cFloatReg;    // Count of floating point registers used (or 0)
+    int     m_idxFloatReg;        // First floating point register used (or -1)
+    int     m_cFloatReg;          // Count of floating point registers used (or 0)
 
-    int     m_idxGenReg;    // First general register used (or -1)
-    int     m_cGenReg;      // Count of general registers used (or 0)
+    int     m_idxGenReg;          // First general register used (or -1)
+    int     m_cGenReg;            // Count of general registers used (or 0)
 
-    int     m_idxStack;     // First stack slot used (or -1)
-    int     m_cStack;       // Count of stack slots used (or 0)
+    int     m_idxStack;           // First stack slot used (or -1)
+    int     m_cStack;             // Count of stack slots used (or 0)
 
 #if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
 
-    EEClass* m_eeClass;     // For structs passed in register, it points to the EEClass of the struct
+    EEClass* m_eeClass;           // For structs passed in register, it points to the EEClass of the struct
 
 #endif // UNIX_AMD64_ABI && FEATURE_UNIX_AMD64_STRUCT_PASSING
 
+#if defined(_TARGET_ARM64_)
+    bool    m_isSinglePrecision;  // For determining if HFA is single or double
+                                  // precision
+#endif // defined(_TARGET_ARM64_)
+
 #if defined(_TARGET_ARM_)
     BOOL    m_fRequires64BitAlignment; // True if the argument should always be aligned (in registers or on the stack
 #endif
@@ -70,6 +75,9 @@ struct ArgLocDesc
 #if defined(_TARGET_ARM_)
         m_fRequires64BitAlignment = FALSE;
 #endif
+#if defined(_TARGET_ARM64_)
+        m_isSinglePrecision = FALSE;
+#endif // defined(_TARGET_ARM64_)
 #if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
         m_eeClass = NULL;
 #endif
@@ -490,7 +498,7 @@ public:
 
     ArgLocDesc* GetArgLocDescForStructInRegs()
     {
-#if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
+#if (defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)) || defined (_TARGET_ARM64_)
         return m_hasArgLocDescForStructInRegs ? &m_argLocDescForStructInRegs : NULL;
 #else
         return NULL;
@@ -556,7 +564,10 @@ public:
             if (!m_argTypeHandle.IsNull() && m_argTypeHandle.IsHFA())
             {
                 CorElementType type = m_argTypeHandle.GetHFAType();
-                pLoc->m_cFloatReg = (type == ELEMENT_TYPE_R4)? GetArgSize()/sizeof(float): GetArgSize()/sizeof(double);
+                bool isFloatType = (type == ELEMENT_TYPE_R4);
+
+                pLoc->m_cFloatReg = isFloatType ? GetArgSize()/sizeof(float): GetArgSize()/sizeof(double);
+                pLoc->m_isSinglePrecision = isFloatType;
             }
             else
             {
@@ -639,7 +650,7 @@ protected:
     CorElementType      m_argType;
     int                 m_argSize;
     TypeHandle          m_argTypeHandle;
-#if defined(_TARGET_AMD64_) && defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
+#if (defined(_TARGET_AMD64_) && defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)) || defined(_TARGET_ARM64_)
     ArgLocDesc          m_argLocDescForStructInRegs;
     bool                m_hasArgLocDescForStructInRegs;
 #endif // _TARGET_AMD64_ && UNIX_AMD64_ABI && FEATURE_UNIX_AMD64_STRUCT_PASSING
@@ -1103,7 +1114,9 @@ int ArgIteratorTemplate<ARGITERATOR_BASE>::GetNextOffset()
         // Handle HFAs: packed structures of 1-4 floats or doubles that are passed in FP argument
         // registers if possible.
         if (thValueType.IsHFA())
+        {
             fFloatingPoint = true;
+        }
 #endif
 
         break;
@@ -1255,7 +1268,17 @@ int ArgIteratorTemplate<ARGITERATOR_BASE>::GetNextOffset()
         if (thValueType.IsHFA())
         {
             CorElementType type = thValueType.GetHFAType();
+            bool isFloatType = (type == ELEMENT_TYPE_R4);
+
             cFPRegs = (type == ELEMENT_TYPE_R4)? (argSize/sizeof(float)): (argSize/sizeof(double));
+
+            m_argLocDescForStructInRegs.Init();
+            m_argLocDescForStructInRegs.m_cFloatReg = cFPRegs;
+            m_argLocDescForStructInRegs.m_idxFloatReg = m_idxFPReg;
+
+            m_argLocDescForStructInRegs.m_isSinglePrecision = isFloatType;
+                
+            m_hasArgLocDescForStructInRegs = true;
         }
         else 
         {
index 22f1152..9cce46d 100644 (file)
@@ -2386,7 +2386,7 @@ BOOL CanRunManagedCode(LoaderLockCheck::kind checkKind, HINSTANCE hInst /*= 0*/)
 //  no longer maintains a ref count since the EE doesn't support being
 //  unloaded and re-loaded. It simply ensures the EE has been started.
 // ---------------------------------------------------------------------------
-HRESULT STDMETHODCALLTYPE CoInitializeEE(DWORD fFlags)
+HRESULT STDAPICALLTYPE CoInitializeEE(DWORD fFlags)
 {
     CONTRACTL
     {
@@ -2417,7 +2417,7 @@ HRESULT STDMETHODCALLTYPE CoInitializeEE(DWORD fFlags)
 // Description:
 //  Must be called by client on shut down in order to free up the system.
 // ---------------------------------------------------------------------------
-void STDMETHODCALLTYPE CoUninitializeEE(BOOL fIsDllUnloading)
+void STDAPICALLTYPE CoUninitializeEE(BOOL fIsDllUnloading)
 {
     LIMITED_METHOD_CONTRACT;
     //BEGIN_ENTRYPOINT_VOIDRET;
index 09925cd..9161585 100644 (file)
@@ -3140,8 +3140,8 @@ HRESULT NGenModulePdbWriter::WritePDBData()
        SString dllPath = pLoadedLayout->GetPath();
        if (!dllPath.EndsWithCaseInsensitive(L".ni.dll") && !dllPath.EndsWithCaseInsensitive(L".ni.exe"))
        {
-               SString::Iterator fileNameStart = dllPath.Begin();
-               dllPath.FindBack(fileNameStart, '\\');
+               SString::Iterator fileNameStart = dllPath.End();
+               dllPath.FindBack(fileNameStart, DIRECTORY_SEPARATOR_STR_W);
 
                SString::Iterator ext = dllPath.End();
                dllPath.FindBack(ext, '.');
index d935ddd..fd27a7a 100644 (file)
@@ -75,7 +75,7 @@ SVAL_IMPL_INIT(ECustomDumpFlavor, CCLRErrorReportingManager, g_ECustomDumpFlavor
 #ifndef DACCESS_COMPILE
 
 extern void STDMETHODCALLTYPE EEShutDown(BOOL fIsDllUnloading);
-extern HRESULT STDMETHODCALLTYPE CoInitializeEE(DWORD fFlags);
+extern HRESULT STDAPICALLTYPE CoInitializeEE(DWORD fFlags);
 extern void PrintToStdOutA(const char *pszString);
 extern void PrintToStdOutW(const WCHAR *pwzString);
 extern BOOL g_fEEHostedStartup;
index 6ed29b8..5c3e5f8 100644 (file)
@@ -946,6 +946,7 @@ FCFuncStart(gInteropMarshalFuncs)
     FCFuncElement("DestroyStructure", MarshalNative::DestroyStructure)
     FCFuncElement("UnsafeAddrOfPinnedArrayElement", MarshalNative::FCUnsafeAddrOfPinnedArrayElement)
     FCFuncElement("GetExceptionCode", ExceptionNative::GetExceptionCode)
+    FCFuncElement("GetExceptionPointers", ExceptionNative::GetExceptionPointers)
     QCFuncElement("GetHINSTANCE", COMModule::GetHINSTANCE)
 
     FCFuncElement("OffsetOfHelper", MarshalNative::OffsetOfHelper)
index d519c3c..5e820a6 100644 (file)
@@ -329,11 +329,7 @@ bool GCToOSInterface::GetCurrentProcessAffinityMask(uintptr_t* processMask, uint
 {
     LIMITED_METHOD_CONTRACT;
 
-#ifndef FEATURE_PAL
     return !!::GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)processMask, (PDWORD_PTR)systemMask);
-#else
-    return false;
-#endif
 }
 
 // Get number of processors assigned to the current process
index 79bfc1b..72c38a6 100644 (file)
@@ -30,7 +30,8 @@ private:
     GCHandleUtilities() = delete;
 };
 
-void ValidateHandleAndAppDomain(OBJECTHANDLE handle);
+void ValidateObjectAndAppDomain(OBJECTREF objRef, ADIndex appDomainIndex);
+void ValidateHandleAssignment(OBJECTHANDLE handle, OBJECTREF objRef);
 
 // Given a handle, returns an OBJECTREF for the object it refers to.
 inline OBJECTREF ObjectFromHandle(OBJECTHANDLE handle)
@@ -38,7 +39,10 @@ inline OBJECTREF ObjectFromHandle(OBJECTHANDLE handle)
     _ASSERTE(handle);
 
 #ifdef _DEBUG_IMPL
-    ValidateHandleAndAppDomain(handle);
+    DWORD context = (DWORD)GCHandleUtilities::GetGCHandleManager()->GetHandleContext(handle);
+    OBJECTREF objRef = ObjectToOBJECTREF(*(Object**)handle);
+
+    ValidateObjectAndAppDomain(objRef, ADIndex(context));
 #endif // _DEBUG_IMPL
 
     // Wrap the raw OBJECTREF and return it
@@ -169,6 +173,34 @@ inline OBJECTHANDLE CreateVariableHandle(IGCHandleStore* store, OBJECTREF object
     return store->CreateHandleWithExtraInfo(OBJECTREFToObject(object), HNDTYPE_VARIABLE, (void*)((uintptr_t)type));
 }
 
+// Handle object manipulation convenience functions
+
+inline void StoreObjectInHandle(OBJECTHANDLE handle, OBJECTREF object)
+{
+    ValidateHandleAssignment(handle, object);
+
+    GCHandleUtilities::GetGCHandleManager()->StoreObjectInHandle(handle, OBJECTREFToObject(object));
+}
+
+inline bool StoreFirstObjectInHandle(OBJECTHANDLE handle, OBJECTREF object)
+{
+    ValidateHandleAssignment(handle, object);
+
+    return GCHandleUtilities::GetGCHandleManager()->StoreObjectInHandleIfNull(handle, OBJECTREFToObject(object));
+}
+
+inline void* InterlockedCompareExchangeObjectInHandle(OBJECTHANDLE handle, OBJECTREF object, OBJECTREF comparandObject)
+{
+    ValidateHandleAssignment(handle, object);
+
+    return GCHandleUtilities::GetGCHandleManager()->InterlockedCompareExchangeObjectInHandle(handle, OBJECTREFToObject(object), OBJECTREFToObject(comparandObject));
+}
+
+inline void ResetOBJECTHANDLE(OBJECTHANDLE handle)
+{
+    GCHandleUtilities::GetGCHandleManager()->StoreObjectInHandle(handle, NULL);
+}
+
 // Handle destruction convenience functions
 
 inline void DestroyHandle(OBJECTHANDLE handle)
@@ -309,6 +341,7 @@ typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyRefcountedHandle>
 typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyLongWeakHandle>            LongWeakHandleHolder;
 typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyGlobalStrongHandle>        GlobalStrongHandleHolder;
 typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyGlobalShortWeakHandle>     GlobalShortWeakHandleHolder;
+typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, ResetOBJECTHANDLE>                ObjectInHandleHolder;
 
 class RCOBJECTHANDLEHolder : public RefCountedOHWrapper
 {
index 4bce7f5..cd7afed 100644 (file)
@@ -40,17 +40,12 @@ bool g_sw_ww_enabled_for_gc_heap = false;
 gc_alloc_context g_global_alloc_context = {};
 
 // Debug-only validation for handle.
-void ValidateHandleAndAppDomain(OBJECTHANDLE handle)
+
+void ValidateObjectAndAppDomain(OBJECTREF objRef, ADIndex appDomainIndex)
 {
 #ifdef _DEBUG_IMPL
-    OBJECTREF objRef = ObjectToOBJECTREF(*(Object**)handle);
     VALIDATEOBJECTREF(objRef);
 
-    IGCHandleManager *pHandleManager = GCHandleUtilities::GetGCHandleManager();
-
-    DWORD context = (DWORD)pHandleManager->GetHandleContext(handle);
-
-    ADIndex appDomainIndex = ADIndex(context);
     AppDomain *domain = SystemDomain::GetAppDomainAtIndex(appDomainIndex);
 
     // Access to a handle in an unloaded domain is not allowed
@@ -72,3 +67,25 @@ void ValidateHandleAndAppDomain(OBJECTHANDLE handle)
 #endif // CHECK_APP_DOMAIN_LEAKS
 #endif // _DEBUG_IMPL
 }
+
+void ValidateHandleAssignment(OBJECTHANDLE handle, OBJECTREF objRef)
+{
+#ifdef _DEBUG_IMPL
+    _ASSERTE(handle);
+
+#ifdef DEBUG_DestroyedHandleValue
+    // Verify that we are not trying to access a freed handle.
+    _ASSERTE("Attempt to access destroyed handle." && *(_UNCHECKED_OBJECTREF*)handle != DEBUG_DestroyedHandleValue);
+#endif
+
+    ADIndex appDomainIndex = HndGetHandleADIndex(handle);
+
+    AppDomain *unloadingDomain = SystemDomain::AppDomainBeingUnloaded();
+    if (unloadingDomain && unloadingDomain->GetIndex() == appDomainIndex && unloadingDomain->NoAccessToHandleTable())
+    {
+        _ASSERTE (!"Access to a handle in unloaded domain is not allowed");
+    }
+
+    ValidateObjectAndAppDomain(objRef, appDomainIndex);
+#endif // _DEBUG_IMPL
+}
\ No newline at end of file
index 620b9d6..d47bc28 100644 (file)
@@ -444,6 +444,11 @@ LPVOID EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes)
     WRAPPER_NO_CONTRACT;
     STATIC_CONTRACT_SO_TOLERANT;
 
+#ifdef _DEBUG
+    // Check whether (indispensable) implicit casting in ClrAllocInProcessHeapBootstrap is safe.
+    static FastAllocInProcessHeapFunc pFunc = EEHeapAllocInProcessHeap;
+#endif
+
     static HANDLE ProcessHeap = NULL;
 
     // We need to guarentee a very small stack consumption in allocating.  And we can't allow
@@ -506,6 +511,11 @@ BOOL EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem)
     }
     CONTRACTL_END;
 
+#ifdef _DEBUG
+    // Check whether (indispensable) implicit casting in ClrFreeInProcessHeapBootstrap is safe.
+    static FastFreeInProcessHeapFunc pFunc = EEHeapFreeInProcessHeap;
+#endif
+
     // Take a look at comment in EEHeapFree and EEHeapAllocInProcessHeap, obviously someone
     // needs to take a little time to think more about this code.
     //CONTRACT_VIOLATION(SOToleranceViolation);
index 647442c..9bb4566 100644 (file)
@@ -815,6 +815,14 @@ PATCH_LABEL ExternalMethodFixupPatchLabel
 NESTED_END ExternalMethodFixupStub, _TEXT
 
 #ifdef FEATURE_READYTORUN
+NESTED_ENTRY DynamicHelperArgsStub, _TEXT, NoHandler
+    .cfi_def_cfa_offset 16
+    CHECK_STACK_ALIGNMENT
+    call  eax
+    add   esp, 12
+    ret
+NESTED_END DynamicHelperArgsStub, _TEXT
+
 // ==========================================================================
 NESTED_ENTRY DelayLoad_MethodCall, _TEXT, NoHandler
     STUB_PROLOG_2_HIDDEN_ARGS
@@ -971,6 +979,7 @@ NESTED_ENTRY DelayLoad_Helper\suffix, _TEXT, NoHandler
     push        eax             // indirection cell address.
     push        esi             // pTransitionBlock
 
+    CHECK_STACK_ALIGNMENT
     call        C_FUNC(DynamicHelperWorker)
     test        eax,eax
     jnz         LOCAL_LABEL(TailCallDelayLoad_Helper\suffix)
index 4c83265..05cd476 100644 (file)
@@ -1878,23 +1878,47 @@ PCODE DynamicHelpers::CreateReturnIndirConst(LoaderAllocator * pAllocator, TADDR
     END_DYNAMIC_HELPER_EMIT();
 }
 
+EXTERN_C VOID DynamicHelperArgsStub();
+
 PCODE DynamicHelpers::CreateHelperWithTwoArgs(LoaderAllocator * pAllocator, TADDR arg, PCODE target)
 {
+#ifdef UNIX_X86_ABI
+    BEGIN_DYNAMIC_HELPER_EMIT(18);
+#else
     BEGIN_DYNAMIC_HELPER_EMIT(12);
+#endif
 
+#ifdef UNIX_X86_ABI
+       // sub esp, 8
+       *p++ = 0x83;
+       *p++ = 0xec;
+       *p++ = 0x8;
+#else
     // pop eax
     *p++ = 0x58;
+#endif
 
     // push arg
     *p++ = 0x68;
     *(INT32 *)p = arg;
     p += 4;
 
+#ifdef UNIX_X86_ABI
+    // mov eax, target
+    *p++ = 0xB8;
+    *(INT32 *)p = target;
+    p += 4;
+#else
     // push eax
     *p++ = 0x50;
+#endif
 
     *p++ = X86_INSTR_JMP_REL32; // jmp rel32
+#ifdef UNIX_X86_ABI
+    *(INT32 *)p = rel32UsingJumpStub((INT32 *)p, (PCODE)DynamicHelperArgsStub);
+#else
     *(INT32 *)p = rel32UsingJumpStub((INT32 *)p, target);
+#endif
     p += 4;
 
     END_DYNAMIC_HELPER_EMIT();
@@ -1902,10 +1926,21 @@ PCODE DynamicHelpers::CreateHelperWithTwoArgs(LoaderAllocator * pAllocator, TADD
 
 PCODE DynamicHelpers::CreateHelperWithTwoArgs(LoaderAllocator * pAllocator, TADDR arg, TADDR arg2, PCODE target)
 {
+#ifdef UNIX_X86_ABI
+    BEGIN_DYNAMIC_HELPER_EMIT(23);
+#else
     BEGIN_DYNAMIC_HELPER_EMIT(17);
+#endif
 
+#ifdef UNIX_X86_ABI
+       // sub esp, 4
+       *p++ = 0x83;
+       *p++ = 0xec;
+       *p++ = 0x4;
+#else
     // pop eax
     *p++ = 0x58;
+#endif
 
     // push arg
     *p++ = 0x68;
@@ -1917,11 +1952,22 @@ PCODE DynamicHelpers::CreateHelperWithTwoArgs(LoaderAllocator * pAllocator, TADD
     *(INT32 *)p = arg2;
     p += 4;
 
+#ifdef UNIX_X86_ABI
+    // mov eax, target
+    *p++ = 0xB8;
+    *(INT32 *)p = target;
+    p += 4;
+#else
     // push eax
     *p++ = 0x50;
+#endif
 
     *p++ = X86_INSTR_JMP_REL32; // jmp rel32
+#ifdef UNIX_X86_ABI
+    *(INT32 *)p = rel32UsingJumpStub((INT32 *)p, (PCODE)DynamicHelperArgsStub);
+#else
     *(INT32 *)p = rel32UsingJumpStub((INT32 *)p, target);
+#endif
     p += 4;
 
     END_DYNAMIC_HELPER_EMIT();
index 840a50d..2852b92 100644 (file)
@@ -1295,10 +1295,10 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState,
     ctx.Esi = lazyState->_esi = baseState->_esi;
     ctx.Ebx = lazyState->_ebx = baseState->_ebx;
 
-    nonVolRegPtrs.Edi = &(lazyState->_edi);
-    nonVolRegPtrs.Esi = &(lazyState->_esi);
-    nonVolRegPtrs.Ebx = &(lazyState->_ebx);
-    nonVolRegPtrs.Ebp = &(lazyState->_ebp);
+    nonVolRegPtrs.Edi = &(baseState->_edi);
+    nonVolRegPtrs.Esi = &(baseState->_esi);
+    nonVolRegPtrs.Ebx = &(baseState->_ebx);
+    nonVolRegPtrs.Ebp = &(baseState->_ebp);
 
     PCODE pvControlPc;
 
index 1725ef7..3e3f6d1 100644 (file)
@@ -1592,6 +1592,14 @@ void STDCALL CopyValueClassArgUnchecked(ArgDestination *argDest, void* src, Meth
         return;
     }
 
+#elif defined(_TARGET_ARM64_)
+
+    if (argDest->IsHFA())
+    {
+        argDest->CopyHFAStructToRegister(src, pMT->GetAlignedNumInstanceFieldBytes());
+        return;
+    }
+
 #endif // UNIX_AMD64_ABI && FEATURE_UNIX_AMD64_STRUCT_PASSING
     // destOffset is only valid for Nullable<T> passed in registers
     _ASSERTE(destOffset == 0);
index 6b8825c..34fca24 100644 (file)
@@ -6735,30 +6735,29 @@ public:
                             Thread::TriggersGC(GetThread());                \
                         } while(0)
 
+#else // ENABLE_CONTRACTS_IMPL
+
+#define BEGINFORBIDGC()
+#define ENDFORBIDGC()
+#define TRIGGERSGC_NOSTOMP() ANNOTATION_GC_TRIGGERS
+#define TRIGGERSGC() ANNOTATION_GC_TRIGGERS
+
+#endif // ENABLE_CONTRACTS_IMPL
 
 inline BOOL GC_ON_TRANSITIONS(BOOL val) {
     WRAPPER_NO_CONTRACT;
+#ifdef _DEBUG
     Thread* thread = GetThread();
     if (thread == 0)
         return(FALSE);
     BOOL ret = thread->m_GCOnTransitionsOK;
     thread->m_GCOnTransitionsOK = val;
     return(ret);
+#else // _DEBUG
+    return FALSE;
+#endif // !_DEBUG
 }
 
-#else   // _DEBUG_IMPL
-
-#define BEGINFORBIDGC()
-#define ENDFORBIDGC()
-#define TRIGGERSGC_NOSTOMP() ANNOTATION_GC_TRIGGERS
-#define TRIGGERSGC() ANNOTATION_GC_TRIGGERS
-
-inline BOOL GC_ON_TRANSITIONS(BOOL val) {
-        return FALSE;
-}
-
-#endif  // _DEBUG_IMPL
-
 #ifdef _DEBUG
 inline void ENABLESTRESSHEAP() {
     WRAPPER_NO_CONTRACT;
index 70ed0e2..da7d18c 100644 (file)
@@ -2525,12 +2525,12 @@ HMODULE CLRGetCurrentModuleHandle()
 
 #endif // !FEATURE_PAL
 
-extern LPVOID EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes);
-extern BOOL EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem);
-extern void ShutdownRuntimeWithoutExiting(int exitCode);
-extern BOOL IsRuntimeStarted(DWORD *pdwStartupFlags);
+LPVOID EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes);
+BOOL EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem);
+void ShutdownRuntimeWithoutExiting(int exitCode);
+BOOL IsRuntimeStarted(DWORD *pdwStartupFlags);
 
-void * __stdcall GetCLRFunction(LPCSTR FunctionName)
+void *GetCLRFunction(LPCSTR FunctionName)
 {
 
     void* func = NULL;
index ee641ef..53801cb 100644 (file)
@@ -76801,7 +76801,7 @@ RelativePath=Regressions\coreclr\GitHub_7685\Test7685\Test7685.cmd
 WorkingDir=Regressions\coreclr\GitHub_7685\Test7685
 Expected=0
 MaxAllowedDurationSeconds=600
-Categories=EXPECTED_FAIL;10107;NEW
+Categories=EXPECTED_PASS;NEW
 HostStyle=0
 
 [Generated921.cmd_9903]
index 9f8b2b3..b7b6287 100644 (file)
 
     <!-- The following are tests that fail on non-Windows, which we must not run when building against packages -->
 
-    <ItemGroup Condition="'$(XunitTestBinBase)' != '' and '$(BuildTestsAgainstPackages)' == 'true' and '$(RuntimeID)' != ''">
+    <ItemGroup Condition="'$(XunitTestBinBase)' != '' and '$(BuildTestsAgainstPackages)' == 'true' and '$(TargetsWindows)' != 'true'">
         <ExcludeList Include="$(XunitTestBinBase)\CoreMangLib\cti\system\byte\ByteToString3\ByteToString3.cmd">
             <Issue>needs triage</Issue>
         </ExcludeList>
index 1ab2dfc..327340f 100644 (file)
@@ -1,10 +1,10 @@
 {
   "dependencies": {
-    "Microsoft.NETCore.ILAsm": "2.0.0-preview1-25215-03",
-    "Microsoft.NETCore.ILDAsm": "2.0.0-preview1-25215-03",
-    "Microsoft.NETCore.Jit": "2.0.0-preview1-25215-03",
-    "Microsoft.NETCore.Runtime.CoreCLR": "2.0.0-preview1-25215-03",
-    "Microsoft.NETCore.TestHost": "2.0.0-preview1-25215-03"
+    "Microsoft.NETCore.ILAsm": "2.0.0-preview1-25221-01",
+    "Microsoft.NETCore.ILDAsm": "2.0.0-preview1-25221-01",
+    "Microsoft.NETCore.Jit": "2.0.0-preview1-25221-01",
+    "Microsoft.NETCore.Runtime.CoreCLR": "2.0.0-preview1-25221-01",
+    "Microsoft.NETCore.TestHost": "2.0.0-preview1-25221-01"
   },
   "frameworks": {
     "netcoreapp2.0": {
index 25ae479..ca40b18 100644 (file)
@@ -1,7 +1,7 @@
 {
   "dependencies": {
     "Microsoft.NETCore.App": "2.0.0-beta-001494-00",
-    "System.Runtime.CompilerServices.Unsafe": "4.4.0-preview1-25214-03"
+    "System.Runtime.CompilerServices.Unsafe": "4.4.0-preview1-25221-01"
   },
   "frameworks": {
     "netcoreapp2.0": {}
index 8e22e91..0754b74 100644 (file)
@@ -1,6 +1,6 @@
 {
   "dependencies": {
-    "Microsoft.TargetingPack.Private.CoreCLR": "2.0.0-preview1-25215-03"
+    "Microsoft.TargetingPack.Private.CoreCLR": "2.0.0-preview1-25221-01"
   },
   "frameworks": {
     "netcoreapp1.1": {
index 85ac392..4477c68 100644 (file)
@@ -1,9 +1,10 @@
 {
   "dependencies": {
-    "Microsoft.NETCore.Platforms": "2.0.0-preview1-25214-03",
-    "Microsoft.Private.CoreFx.NETCoreApp": "4.4.0-preview1-25214-03",
-    "System.Memory": "4.4.0-preview1-25214-03",
-    "System.Runtime.CompilerServices.Unsafe": "4.4.0-preview1-25214-03"
+    "Microsoft.NETCore.Platforms": "2.0.0-preview1-25221-01",
+    "Microsoft.Private.CoreFx.NETCoreApp": "4.4.0-preview1-25221-01",
+    "System.Memory": "4.4.0-preview1-25221-01",
+    "System.Runtime.CompilerServices.Unsafe": "4.4.0-preview1-25221-01",
+    "System.Security.Permissions": "4.4.0-preview1-25221-01"
   },
   "frameworks": {
     "netcoreapp2.0": {
index c33b3b8..575d75d 100644 (file)
@@ -1,6 +1,6 @@
 {
   "dependencies": {
-    "Microsoft.NETCore.Platforms": "2.0.0-preview1-25214-03",
+    "Microsoft.NETCore.Platforms": "2.0.0-preview1-25221-01",
     "Microsoft.DotNet.CoreCLR.TestDependencies": "1.0.0-prerelease",
     "jit-dasm": "0.0.1.4",
     "cijobs": "0.0.1.2",
index f2c5c51..05ba362 100644 (file)
@@ -218,7 +218,7 @@ namespace DelegateTest
         {
             bool retVal = true;
 
-            TestLibrary.TestFramework.BeginScenario("PosTest7:  Use the different instance's same instance method to create two delegate which delegate object is the same,their hashcode is equal");
+            TestLibrary.TestFramework.BeginScenario("PosTest7:  Use the different instance's same instance method to create two delegate which delegate object is the same, their hashcode is different");
 
             try
             {
@@ -226,7 +226,7 @@ namespace DelegateTest
                 booldelegate workDelegate = new booldelegate(new TestClass(1).StartWork_Bool);
                 booldelegate workDelegate1 = new booldelegate(new TestClass1(2).StartWork_Bool );
 
-                if (workDelegate.GetHashCode()!=workDelegate1.GetHashCode())
+                if (workDelegate.GetHashCode()==workDelegate1.GetHashCode())
                 {
                     TestLibrary.TestFramework.LogError("013", "HashCode is not excepted ");
                     retVal = false;
index f5fe8db..6be9e66 100644 (file)
@@ -413,11 +413,22 @@ public class ReliabilityConfig : IEnumerable, IEnumerator
                                         case RFConfigOptions.RFConfigOptions_Test_MinMaxTestsUseCPUCount:
                                             if (GetTrueFalseOptionValue(currentXML.Value, RFConfigOptions.RFConfigOptions_Test_MinMaxTestsUseCPUCount))
                                             {
-                                                int CPUCount = Convert.ToInt32(Environment.GetEnvironmentVariable("NUMBER_OF_PROCESSORS"));
-                                                if (CPUCount <= 0)
-                                                    throw new Exception("Invalid Value when reading NUMBER_OF_PROCESSORS: {0}" + CPUCount);
-                                                _curTestSet.MinTestsRunning = CPUCount;
-                                                _curTestSet.MaxTestsRunning = (int)(CPUCount * 1.5);
+                                                string numProcessors = Environment.GetEnvironmentVariable("NUMBER_OF_PROCESSORS");
+                                                int cpuCount;
+                                                if (numProcessors == null)
+                                                {
+                                                    Console.WriteLine("NUMBER_OF_PROCESSORS environment variable not supplied, falling back to Environment");
+                                                    cpuCount = Environment.ProcessorCount;
+                                                }
+                                                else
+                                                {
+                                                    cpuCount = Convert.ToInt32(Environment.GetEnvironmentVariable("NUMBER_OF_PROCESSORS"));
+                                                }
+
+                                               if (cpuCount <= 0)
+                                                    throw new Exception("Invalid Value when reading processor count: " + cpuCount);
+                                                _curTestSet.MinTestsRunning = cpuCount;
+                                                _curTestSet.MaxTestsRunning = (int)(cpuCount * 1.5);
                                             }
                                             break;
                                         case RFConfigOptions.RFConfigOptions_Test_SuppressConsoleOutputFromTests:
index 6aaeddf..cb7bcab 100644 (file)
@@ -35,23 +35,54 @@ using System.Runtime.Loader;
 
 internal class CustomAssemblyResolver : AssemblyLoadContext
 {
-    protected override Assembly Load(AssemblyName assemblyName)
+    private string _frameworkPath;
+    private string _testsPath;
+
+    public CustomAssemblyResolver()
     {
-        Console.WriteLine("\nCustomAssemblyLoader: Got request to load {0}\n", assemblyName.ToString());
+        Console.WriteLine("CustomAssemblyResolver initializing");
+        _frameworkPath = Environment.GetEnvironmentVariable("BVT_ROOT");
+        if (_frameworkPath == null)
+        {
+            Console.WriteLine("CustomAssemblyResolver: BVT_ROOT not set");
+            _frameworkPath = Environment.GetEnvironmentVariable("CORE_ROOT");
+        }
 
-        string strBVTRoot = Environment.GetEnvironmentVariable("BVT_ROOT");
-        if (String.IsNullOrEmpty(strBVTRoot))
-            strBVTRoot = Path.Combine(Directory.GetCurrentDirectory(), "Tests");
+        if (_frameworkPath == null)
+        {
+            Console.WriteLine("CustomAssemblyResolver: CORE_ROOT not set");
+            _frameworkPath = Directory.GetCurrentDirectory();
+        }
+
+        Console.WriteLine("CustomAssemblyResolver: looking for framework libraries at path: {0}", _frameworkPath);
+        string stressFrameworkDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+        Console.WriteLine("CustomAssemblyResolver: currently executing assembly is at path: {0}", stressFrameworkDir);
+        _testsPath = Path.Combine(stressFrameworkDir, "Tests");
+        Console.WriteLine("CustomAssemblyResolver: looking for tests in dir: {0}", _testsPath);
+    }
+
+    protected override Assembly Load(AssemblyName assemblyName)
+    {
+        Console.WriteLine("CustomAssemblyLoader: Got request to load {0}", assemblyName.ToString());
 
-        string strPath = Path.Combine(strBVTRoot, assemblyName.Name + ".exe");
+        string strPath;
+        if (assemblyName.Name.StartsWith("System."))
+        {
+            Console.WriteLine("CustomAssemblyLoader: this looks like a framework assembly");
+            strPath = Path.Combine(_frameworkPath, assemblyName.Name + ".dll");
+        }
+        else
+        {
+            Console.WriteLine("CustomAssemblyLoader: this looks like a test");
+            strPath = Path.Combine(_testsPath, assemblyName.Name + ".exe");
+        }
 
-        Console.WriteLine("Incoming AssemblyName: {0}\n", assemblyName.ToString());
-        Console.WriteLine("Trying to Load: {0}\n", strPath);
-        Console.WriteLine("Computed AssemblyName: {0}\n", GetAssemblyName(strPath).ToString());
+        Console.WriteLine("Incoming AssemblyName: {0}", assemblyName.ToString());
+        Console.WriteLine("Trying to Load: {0}", strPath);
+        Console.WriteLine("Computed AssemblyName: {0}", GetAssemblyName(strPath).ToString());
         Assembly asmLoaded = LoadFromAssemblyPath(strPath);
 
-        //Console.WriteLine("Loaded {0} from {1}", asmLoaded.FullName, asmLoaded.Location);
-        Console.WriteLine("Loaded {0}", asmLoaded.FullName);
+        Console.WriteLine("Loaded {0} from {1}", asmLoaded.FullName, asmLoaded.Location);
 
         return asmLoaded;
     }
@@ -217,7 +248,7 @@ public class ReliabilityFramework
                 if (eTemp == null)
                 {
                     rf._logger.WriteToInstrumentationLog(null, LoggingLevels.Tests, String.Format("Exception while running tests: {0}", e));
-                    Console.WriteLine("There was an exception while attempting to run the tests: See Instrumentation Log for details");
+                    Console.WriteLine("There was an exception while attempting to run the tests: See Instrumentation Log for details. (Exception: {0})", e);
                 }
             }
         }
@@ -529,6 +560,7 @@ public class ReliabilityFramework
         return (99);
     }
 
+#if !PROJECTK_BUILD
     [DllImport("kernel32.dll")]
     private extern static void DebugBreak();
 
@@ -537,6 +569,7 @@ public class ReliabilityFramework
 
     [DllImport("kernel32.dll")]
     private extern static void OutputDebugString(string debugStr);
+#endif
 
     /// <summary>
     /// Checks to see if we should block all execution due to a fatal error
@@ -558,12 +591,20 @@ public class ReliabilityFramework
     }
     internal static void MyDebugBreak(string extraData)
     {
+#if !PROJECTK_BUILD
         if (IsDebuggerPresent())
         {
             OutputDebugString(String.Format("\r\n\r\n\r\nRELIABILITYFRAMEWORK DEBUGBREAK: Breaking in because test throw an exception ({0})\r\n\r\n\r\n", extraData));
             DebugBreak();
         }
         else
+#else
+        if (Debugger.IsAttached)
+        {
+            Console.WriteLine(string.Format("DebugBreak: breaking in because test threw an exception: {0}", extraData));
+            Debugger.Break();
+        }
+#endif
         {
             // We need to stop the process now, 
             // but all the threads are still running
@@ -669,7 +710,7 @@ public class ReliabilityFramework
             ourPageFaultsCounter = new PerformanceCounter("Process", "Page Faults/sec", myProcessName);
         }
     }
-#endif 
+#endif
     /// <summary>
     /// Calculates the total number of tests to be run based upon the maximum
     /// number of loops & number of tests in the current test set.
@@ -1017,7 +1058,7 @@ public class ReliabilityFramework
         test.TestStarted();
 
         StartTestWorker(test);
-#else     
+#else
         try
         {
             if (curTestSet.AppDomainLoaderMode == AppDomainLoaderMode.Lazy)
@@ -1062,7 +1103,7 @@ public class ReliabilityFramework
         {
             HandleOom(e, "StartTest");
         }
-#endif      
+#endif
     }
 
     /// <summary>
@@ -1439,7 +1480,7 @@ public class ReliabilityFramework
                     {
                         SignalTestFinished(daTest);
                     }
-#endif 
+#endif
                     break;
             }
         }
@@ -1531,15 +1572,31 @@ public class ReliabilityFramework
         {
             RunCommands(test.PreCommands, "pre", test);
 
+            List<string> newPaths = new List<string>(paths);
+            string bvtRoot = Environment.GetEnvironmentVariable("BVT_ROOT");
+            if (bvtRoot != null)
+            {
+                newPaths.Add(bvtRoot);
+            }
+
+            string coreRoot = Environment.GetEnvironmentVariable("CORE_ROOT");
+            if (coreRoot != null)
+            {
+                newPaths.Add(coreRoot);
+            }
+
+            string thisRoot = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Tests");
+            newPaths.Add(thisRoot);
+
             switch (test.TestStartMode)
             {
                 case TestStartModeEnum.ProcessLoader:
-                    TestPreLoader_Process(test, paths);
+                    TestPreLoader_Process(test, newPaths.ToArray());
                     break;
                 case TestStartModeEnum.AppDomainLoader:
 #if PROJECTK_BUILD
                     Console.WriteLine("Appdomain mode is NOT supported for ProjectK");
-#else                    
+#else
                     TestPreLoader_AppDomain(test, paths);
 #endif
                     break;
@@ -1688,21 +1745,30 @@ public class ReliabilityFramework
     {
         Console.WriteLine("Preloading for process mode");
 
+        Console.WriteLine("basepath: {0}, asm: {1}", test.BasePath, test.Assembly);
+        foreach (var path in paths)
+        {
+            Console.WriteLine(" path: {0}", path);
+        }
         string realpath = ReliabilityConfig.ConvertPotentiallyRelativeFilenameToFullPath(test.BasePath, test.Assembly);
         Debug.Assert(test.TestObject == null);
+        Console.WriteLine("Real path: {0}", realpath);
         if (File.Exists(realpath))
         {
             test.TestObject = realpath;
         }
         else if (File.Exists((string)test.Assembly))
         {
+            Console.WriteLine("asm path: {0}", test.Assembly);
             test.TestObject = test.Assembly;
         }
         else
         {
             foreach (string path in paths)
             {
+                Console.WriteLine("Candidate path: {0}", path);
                 string fullPath = ReliabilityConfig.ConvertPotentiallyRelativeFilenameToFullPath(path, (string)test.Assembly);
+                Console.WriteLine("Candidate full path: {0}", fullPath);
                 if (File.Exists(fullPath))
                 {
                     test.TestObject = fullPath;
@@ -1710,6 +1776,7 @@ public class ReliabilityFramework
                 }
             }
         }
+
         if (test.TestObject == null)
         {
             Console.WriteLine("Couldn't find path for {0}", test.Assembly);
@@ -1740,7 +1807,7 @@ public class ReliabilityFramework
 
             test.EntryPointMethod = methodInfo;
         }
-#endif 
+#endif
     }
 
 #if !PROJECTK_BUILD
@@ -1902,6 +1969,7 @@ Thanks for contributing to CLR Stress!
         {
             try
             {
+#if !PROJECTK_BUILD
                 // Record the failure to the database
                 string arguments = String.Format("//b //nologo %SCRIPTSDIR%\\record.js -i %STRESSID% -a LOG_FAILED_TEST -k \"FAILED  {0}\"", test.RefOrID);
                 ProcessStartInfo psi = new ProcessStartInfo("cscript.exe", Environment.ExpandEnvironmentVariables(arguments));
@@ -1916,6 +1984,7 @@ Thanks for contributing to CLR Stress!
                     Console.WriteLine("//b //nologo record.js -i %STRESSID% -a LOG_FAILED_TEST -k \"{0}\"", test.RefOrID);
                 }
                 p.Dispose();
+#endif
             }
             catch
             {
old mode 100755 (executable)
new mode 100644 (file)
index aa3fd76..3d30d82
@@ -7,4 +7,4 @@ add_library (LPSTRTestNative SHARED ${SOURCES})
 target_link_libraries(LPSTRTestNative ${LINK_LIBRARIES_ADDITIONAL}) 
 
 # add the install targets
-install (TARGETS LPSTRTestNative DESTINATION bin)
\ No newline at end of file
+install (TARGETS LPSTRTestNative DESTINATION bin)
old mode 100755 (executable)
new mode 100644 (file)
index f704791..12cff70
Binary files a/tests/src/Interop/StringMarshalling/LPSTR/LPSTRTest.cs and b/tests/src/Interop/StringMarshalling/LPSTR/LPSTRTest.cs differ
old mode 100755 (executable)
new mode 100644 (file)
index 88a0330..d78ecb1
@@ -39,4 +39,4 @@
     </ProjectReference>
   </ItemGroup>
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
\ No newline at end of file
+</Project>
old mode 100755 (executable)
new mode 100644 (file)
index ce8455f..31d0eba
@@ -70,4 +70,4 @@ namespace NativeDefs
         [DllImport(NativeBinaryName)]
         public static extern bool ReverseP_MarshalStrB_Out(Del_MarshalStrB_Out d);
     }
-}
\ No newline at end of file
+}
index dc44d2e..be42ab9 100644 (file)
@@ -52,9 +52,9 @@ internal class ScanProjectFiles
 
             if (binIndex < 0)
             {
-                Console.WriteLine("CORE_ROOT must be set to full path to repo test dir; was '{0}'.",
-                    coreRoot);
-                return -1;
+                Console.WriteLine("No bin directory found in CORE_ROOT path `{0}`," + 
+                    " so no checking will be performed.", coreRoot);
+                return 100;
             }
 
             string repoRoot = coreRoot.Substring(0, binIndex);
@@ -78,8 +78,8 @@ internal class ScanProjectFiles
 
         if (!Directory.Exists(projectRoot))
         {
-            Console.WriteLine("Project directory does not exist");
-            return -1;
+            Console.WriteLine("Project directory does not exist, so no checking will be performed.");
+            return 100;
         }
 
         DirectoryInfo projectRootDir = new DirectoryInfo(projectRoot);
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_10940/GitHub_10940.cs b/tests/src/JIT/Regression/JitBlue/GitHub_10940/GitHub_10940.cs
new file mode 100644 (file)
index 0000000..2a72bd8
--- /dev/null
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.CompilerServices;
+
+// This test checks whether or not the JIT properly spills side effects in the importer when dumping multi-reg values
+// to temps. If the JIT does not do so correctly, the calls to GetString() and GetDecimal() will be reordered and the
+// test will fail with exit code 0; if it does do so correctly, the calls will not be reordered and the test will
+// pass.
+
+class Test
+{
+    abstract class ValueSourceBase
+    {
+        public abstract string GetString();
+        public abstract decimal GetDecimal();
+        public abstract int GetReturnValue();
+    }
+
+    class ValueSource : ValueSourceBase
+    {
+        int rv;
+
+        public override string GetString()
+        {
+            rv = 0;
+            return "";
+        }
+
+        public override decimal GetDecimal()
+        {
+            rv = 100;
+            return 0;
+        }
+
+        public override int GetReturnValue()
+        {
+            return rv;
+        }
+    }
+
+    Test(string s, decimal d)
+    {
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    static int M(ValueSourceBase vs)
+    {
+        new Test(vs.GetString(), vs.GetDecimal());
+        return vs.GetReturnValue();
+    }
+
+    static int Main()
+    {
+        return M(new ValueSource());
+    }
+}
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_10940/GitHub_10940.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_10940/GitHub_10940.csproj
new file mode 100644 (file)
index 0000000..ef69a3b
--- /dev/null
@@ -0,0 +1,42 @@
+<?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>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <AssemblyName>$(MSBuildProjectName)</AssemblyName>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+
+    <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <PropertyGroup>
+    <DebugType></DebugType>
+    <Optimize>True</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="GitHub_10940.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup> 
+</Project>
index 39b4fa9..18907a1 100644 (file)
@@ -6,15 +6,15 @@
     "xunit.performance.execution": "1.0.0-beta-build0003",
     "xunit.performance.metrics": "1.0.0-beta-build0003",
     "Microsoft.Diagnostics.Tracing.TraceEvent": "1.0.3-alpha-experimental",
-    "Microsoft.NETCore.Platforms": "2.0.0-preview1-25214-03",
+    "Microsoft.NETCore.Platforms": "2.0.0-preview1-25221-01",
     "System.Console": "4.4.0-beta-24913-02",
     "System.Dynamic.Runtime": "4.4.0-beta-24913-02",
     "System.Linq": "4.4.0-beta-24913-02",
     "System.IO.FileSystem": "4.4.0-beta-24913-02",
-    "System.Numerics.Vectors": "4.4.0-preview1-25214-03",
+    "System.Numerics.Vectors": "4.4.0-preview1-25221-01",
     "System.Reflection": "4.4.0-beta-24913-02",
     "System.Reflection.Extensions": "4.4.0-beta-24913-02",
-    "System.Reflection.TypeExtensions": "4.4.0-preview1-25214-03",
+    "System.Reflection.TypeExtensions": "4.4.0-preview1-25221-01",
     "System.Runtime": "4.4.0-beta-24913-02",
     "System.Runtime.Extensions": "4.4.0-beta-24913-02",
     "System.Runtime.Numerics": "4.4.0-beta-24913-02",
index 1299b92..b71701f 100644 (file)
@@ -5,7 +5,7 @@
     "xunit.performance.execution": "1.0.0-beta-build0003",
     "xunit.performance.metrics": "1.0.0-beta-build0003",
     "Microsoft.Diagnostics.Tracing.TraceEvent": "1.0.3-alpha-experimental",
-    "Microsoft.NETCore.Platforms": "2.0.0-preview1-25214-03",
+    "Microsoft.NETCore.Platforms": "2.0.0-preview1-25221-01",
     "Newtonsoft.Json": "7.0.1",
     "System.Console": "4.4.0-beta-24913-02",
     "System.IO": "4.4.0-beta-24913-02",
@@ -15,7 +15,7 @@
     "System.Dynamic.Runtime": "4.4.0-beta-24913-02",
     "System.Reflection": "4.4.0-beta-24913-02",
     "System.Reflection.Extensions": "4.4.0-beta-24913-02",
-    "System.Reflection.TypeExtensions": "4.4.0-preview1-25214-03",
+    "System.Reflection.TypeExtensions": "4.4.0-preview1-25221-01",
     "System.Runtime": "4.4.0-beta-24913-02",
     "System.Runtime.Serialization.Json": "4.4.0-beta-24913-02",
     "System.Runtime.Serialization.Primitives": "4.4.0-beta-24913-02",
index cf3bc64..3e88bee 100644 (file)
@@ -5,20 +5,20 @@
     "xunit.performance.execution": "1.0.0-beta-build0003",
     "xunit.performance.metrics": "1.0.0-beta-build0003",
     "Microsoft.Diagnostics.Tracing.TraceEvent": "1.0.3-alpha-experimental",
-    "Microsoft.NETCore.Platforms": "2.0.0-preview1-25214-03",
+    "Microsoft.NETCore.Platforms": "2.0.0-preview1-25221-01",
     "System.Collections.NonGeneric": "4.4.0-beta-24913-02",
     "System.Console": "4.4.0-beta-24913-02",
     "System.IO.FileSystem": "4.4.0-beta-24913-02",
     "System.Linq": "4.4.0-beta-24913-02",
     "System.Linq.Parallel": "4.4.0-beta-24913-02",
     "System.Linq.Expressions": "4.4.0-beta-24913-02",
-    "System.Memory": "4.4.0-preview1-25214-03",
-    "System.Numerics.Vectors": "4.4.0-preview1-25214-03",
+    "System.Memory": "4.4.0-preview1-25221-01",
+    "System.Numerics.Vectors": "4.4.0-preview1-25221-01",
     "System.Reflection": "4.4.0-beta-24913-02",
     "System.Reflection.Extensions": "4.4.0-beta-24913-02",
-    "System.Reflection.TypeExtensions": "4.4.0-preview1-25214-03",
+    "System.Reflection.TypeExtensions": "4.4.0-preview1-25221-01",
     "System.Runtime": "4.4.0-beta-24913-02",
-    "System.Runtime.CompilerServices.Unsafe": "4.4.0-preview1-25214-03",
+    "System.Runtime.CompilerServices.Unsafe": "4.4.0-preview1-25221-01",
     "System.Runtime.Extensions": "4.4.0-beta-24913-02",
     "System.Runtime.Numerics": "4.4.0-beta-24913-02",
     "System.Text.RegularExpressions": "4.4.0-beta-24913-02",
index 814ae4a..7cfdb28 100644 (file)
@@ -1,11 +1,20 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+#if !defined(_MSC_VER)
+#if __i386__
+#define __stdcall __attribute__((stdcall))
+#else // __i386__
+#define __stdcall
+#endif  // !__i386__
+#endif // !defined(_MSC_VER)
 
 #if defined(_MSC_VER)
 #define HFADLL_API extern "C" __declspec(dllexport)
+#define HFADLL_CALLCONV
 #else
 #define HFADLL_API extern "C" __attribute__((visibility("default")))
+#define HFADLL_CALLCONV __stdcall
 #endif 
 
 
@@ -102,13 +111,13 @@ const FLOATTYPE EXPECTED_SUM_HFA11 = static_cast<FLOATTYPE>(66);
 const FLOATTYPE EXPECTED_SUM_HFA19 = static_cast<FLOATTYPE>(190);
 #endif
 
-HFADLL_API FLOATTYPE  get_EXPECTED_SUM_HFA01() {return EXPECTED_SUM_HFA01;}
-HFADLL_API FLOATTYPE  get_EXPECTED_SUM_HFA02() {return EXPECTED_SUM_HFA02;}
-HFADLL_API FLOATTYPE  get_EXPECTED_SUM_HFA03() {return EXPECTED_SUM_HFA03;}
-HFADLL_API FLOATTYPE  get_EXPECTED_SUM_HFA05() {return EXPECTED_SUM_HFA05;}
-HFADLL_API FLOATTYPE  get_EXPECTED_SUM_HFA08() {return EXPECTED_SUM_HFA08;}
-HFADLL_API FLOATTYPE  get_EXPECTED_SUM_HFA11() {return EXPECTED_SUM_HFA11;}
-HFADLL_API FLOATTYPE  get_EXPECTED_SUM_HFA19() {return EXPECTED_SUM_HFA19;}
+HFADLL_API FLOATTYPE HFADLL_CALLCONV get_EXPECTED_SUM_HFA01() {return EXPECTED_SUM_HFA01;}
+HFADLL_API FLOATTYPE HFADLL_CALLCONV get_EXPECTED_SUM_HFA02() {return EXPECTED_SUM_HFA02;}
+HFADLL_API FLOATTYPE HFADLL_CALLCONV get_EXPECTED_SUM_HFA03() {return EXPECTED_SUM_HFA03;}
+HFADLL_API FLOATTYPE HFADLL_CALLCONV get_EXPECTED_SUM_HFA05() {return EXPECTED_SUM_HFA05;}
+HFADLL_API FLOATTYPE HFADLL_CALLCONV get_EXPECTED_SUM_HFA08() {return EXPECTED_SUM_HFA08;}
+HFADLL_API FLOATTYPE HFADLL_CALLCONV get_EXPECTED_SUM_HFA11() {return EXPECTED_SUM_HFA11;}
+HFADLL_API FLOATTYPE HFADLL_CALLCONV get_EXPECTED_SUM_HFA19() {return EXPECTED_SUM_HFA19;}
 
 
 
@@ -116,13 +125,13 @@ HFADLL_API FLOATTYPE  get_EXPECTED_SUM_HFA19() {return EXPECTED_SUM_HFA19;}
 // init Methods
 // ---------------------------------------------------
 
-HFADLL_API void  init_HFA01(HFA01& hfa);
-HFADLL_API void  init_HFA02(HFA02& hfa);
-HFADLL_API void  init_HFA03(HFA03& hfa);
-HFADLL_API void  init_HFA05(HFA05& hfa);
-HFADLL_API void  init_HFA08(HFA08& hfa);
-HFADLL_API void  init_HFA11(HFA11& hfa);
-HFADLL_API void  init_HFA19(HFA19& hfa);
+HFADLL_API void HFADLL_CALLCONV init_HFA01(HFA01& hfa);
+HFADLL_API void HFADLL_CALLCONV init_HFA02(HFA02& hfa);
+HFADLL_API void HFADLL_CALLCONV init_HFA03(HFA03& hfa);
+HFADLL_API void HFADLL_CALLCONV init_HFA05(HFA05& hfa);
+HFADLL_API void HFADLL_CALLCONV init_HFA08(HFA08& hfa);
+HFADLL_API void HFADLL_CALLCONV init_HFA11(HFA11& hfa);
+HFADLL_API void HFADLL_CALLCONV init_HFA19(HFA19& hfa);
 
 
 
@@ -130,13 +139,13 @@ HFADLL_API void  init_HFA19(HFA19& hfa);
 // identity methods
 // --------------------------------------------------------------
 
-HFADLL_API HFA01  identity_HFA01(HFA01 hfa);
-HFADLL_API HFA02  identity_HFA02(HFA02 hfa);
-HFADLL_API HFA03  identity_HFA03(HFA03 hfa);
-HFADLL_API HFA05  identity_HFA05(HFA05 hfa);
-HFADLL_API HFA08  identity_HFA08(HFA08 hfa);
-HFADLL_API HFA11  identity_HFA11(HFA11 hfa);
-HFADLL_API HFA19  identity_HFA19(HFA19 hfa);
+HFADLL_API HFA01 HFADLL_CALLCONV identity_HFA01(HFA01 hfa);
+HFADLL_API HFA02 HFADLL_CALLCONV identity_HFA02(HFA02 hfa);
+HFADLL_API HFA03 HFADLL_CALLCONV identity_HFA03(HFA03 hfa);
+HFADLL_API HFA05 HFADLL_CALLCONV identity_HFA05(HFA05 hfa);
+HFADLL_API HFA08 HFADLL_CALLCONV identity_HFA08(HFA08 hfa);
+HFADLL_API HFA11 HFADLL_CALLCONV identity_HFA11(HFA11 hfa);
+HFADLL_API HFA19 HFADLL_CALLCONV identity_HFA19(HFA19 hfa);
 
 
 
@@ -144,13 +153,13 @@ HFADLL_API HFA19  identity_HFA19(HFA19 hfa);
 // get methods
 // --------------------------------------------------------------
 
-HFADLL_API HFA01  get_HFA01();
-HFADLL_API HFA02  get_HFA02();
-HFADLL_API HFA03  get_HFA03();
-HFADLL_API HFA05  get_HFA05();
-HFADLL_API HFA08  get_HFA08();
-HFADLL_API HFA11  get_HFA11();
-HFADLL_API HFA19  get_HFA19();
+HFADLL_API HFA01 HFADLL_CALLCONV get_HFA01();
+HFADLL_API HFA02 HFADLL_CALLCONV get_HFA02();
+HFADLL_API HFA03 HFADLL_CALLCONV get_HFA03();
+HFADLL_API HFA05 HFADLL_CALLCONV get_HFA05();
+HFADLL_API HFA08 HFADLL_CALLCONV get_HFA08();
+HFADLL_API HFA11 HFADLL_CALLCONV get_HFA11();
+HFADLL_API HFA19 HFADLL_CALLCONV get_HFA19();
 
 
 
@@ -158,53 +167,53 @@ HFADLL_API HFA19  get_HFA19();
 // sum Methods
 // ---------------------------------------------------
 
-HFADLL_API FLOATTYPE  sum_HFA01(HFA01 hfa);
-HFADLL_API FLOATTYPE  sum_HFA02(HFA02 hfa);
-HFADLL_API FLOATTYPE  sum_HFA03(HFA03 hfa);
-HFADLL_API FLOATTYPE  sum_HFA05(HFA05 hfa);
-HFADLL_API FLOATTYPE  sum_HFA08(HFA08 hfa);
-HFADLL_API FLOATTYPE  sum_HFA11(HFA11 hfa);
-HFADLL_API FLOATTYPE  sum_HFA19(HFA19 hfa);
-
-HFADLL_API FLOATTYPE  sum3_HFA01(float v1, __int64 v2, HFA01 hfa);
-HFADLL_API FLOATTYPE  sum3_HFA02(float v1, __int64 v2, HFA02 hfa);
-HFADLL_API FLOATTYPE  sum3_HFA03(float v1, __int64 v2, HFA03 hfa);
-HFADLL_API FLOATTYPE  sum3_HFA05(float v1, __int64 v2, HFA05 hfa);
-HFADLL_API FLOATTYPE  sum3_HFA08(float v1, __int64 v2, HFA08 hfa);
-HFADLL_API FLOATTYPE  sum3_HFA11(float v1, __int64 v2, HFA11 hfa);
-HFADLL_API FLOATTYPE  sum3_HFA19(float v1, __int64 v2, HFA19 hfa);
-
-HFADLL_API FLOATTYPE  sum5_HFA01(__int64 v1, double v2, short v3, signed char v4, HFA01 hfa);
-HFADLL_API FLOATTYPE  sum5_HFA02(__int64 v1, double v2, short v3, signed char v4, HFA02 hfa);
-HFADLL_API FLOATTYPE  sum5_HFA03(__int64 v1, double v2, short v3, signed char v4, HFA03 hfa);
-HFADLL_API FLOATTYPE  sum5_HFA05(__int64 v1, double v2, short v3, signed char v4, HFA05 hfa);
-HFADLL_API FLOATTYPE  sum5_HFA08(__int64 v1, double v2, short v3, signed char v4, HFA08 hfa);
-HFADLL_API FLOATTYPE  sum5_HFA11(__int64 v1, double v2, short v3, signed char v4, HFA11 hfa);
-HFADLL_API FLOATTYPE  sum5_HFA19(__int64 v1, double v2, short v3, signed char v4, HFA19 hfa);
-
-HFADLL_API FLOATTYPE  sum8_HFA01(float v1, double v2, __int64 v3, signed char v4, double v5, HFA01 hfa);
-HFADLL_API FLOATTYPE  sum8_HFA02(float v1, double v2, __int64 v3, signed char v4, double v5, HFA02 hfa);
-HFADLL_API FLOATTYPE  sum8_HFA03(float v1, double v2, __int64 v3, signed char v4, double v5, HFA03 hfa);
-HFADLL_API FLOATTYPE  sum8_HFA05(float v1, double v2, __int64 v3, signed char v4, double v5, HFA05 hfa);
-HFADLL_API FLOATTYPE  sum8_HFA08(float v1, double v2, __int64 v3, signed char v4, double v5, HFA08 hfa);
-HFADLL_API FLOATTYPE  sum8_HFA11(float v1, double v2, __int64 v3, signed char v4, double v5, HFA11 hfa);
-HFADLL_API FLOATTYPE  sum8_HFA19(float v1, double v2, __int64 v3, signed char v4, double v5, HFA19 hfa);
-
-HFADLL_API FLOATTYPE  sum11_HFA01(double v1, float v2, float v3, int v4, float v5, __int64 v6, double v7, float v8, HFA01 hfa);
-HFADLL_API FLOATTYPE  sum11_HFA02(double v1, float v2, float v3, int v4, float v5, __int64 v6, double v7, float v8, HFA02 hfa);
-HFADLL_API FLOATTYPE  sum11_HFA03(double v1, float v2, float v3, int v4, float v5, __int64 v6, double v7, float v8, HFA03 hfa);
-HFADLL_API FLOATTYPE  sum11_HFA05(double v1, float v2, float v3, int v4, float v5, __int64 v6, double v7, float v8, HFA05 hfa);
-HFADLL_API FLOATTYPE  sum11_HFA08(double v1, float v2, float v3, int v4, float v5, __int64 v6, double v7, float v8, HFA08 hfa);
-HFADLL_API FLOATTYPE  sum11_HFA11(double v1, float v2, float v3, int v4, float v5, __int64 v6, double v7, float v8, HFA11 hfa);
-HFADLL_API FLOATTYPE  sum11_HFA19(double v1, float v2, float v3, int v4, float v5, __int64 v6, double v7, float v8, HFA19 hfa);
-
-HFADLL_API FLOATTYPE  sum19_HFA01(float v1, double v2, float v3, double v4, float v5, double v6, float v7, double v8, float v9, double v10, float v11, double v12, float v13, HFA01 hfa);
-HFADLL_API FLOATTYPE  sum19_HFA02(float v1, double v2, float v3, double v4, float v5, double v6, float v7, double v8, float v9, double v10, float v11, double v12, float v13, HFA02 hfa);
-HFADLL_API FLOATTYPE  sum19_HFA03(float v1, double v2, float v3, double v4, float v5, double v6, float v7, double v8, float v9, double v10, float v11, double v12, float v13, HFA03 hfa);
-HFADLL_API FLOATTYPE  sum19_HFA05(float v1, double v2, float v3, double v4, float v5, double v6, float v7, double v8, float v9, double v10, float v11, double v12, float v13, HFA05 hfa);
-HFADLL_API FLOATTYPE  sum19_HFA08(float v1, double v2, float v3, double v4, float v5, double v6, float v7, double v8, float v9, double v10, float v11, double v12, float v13, HFA08 hfa);
-HFADLL_API FLOATTYPE  sum19_HFA11(float v1, double v2, float v3, double v4, float v5, double v6, float v7, double v8, float v9, double v10, float v11, double v12, float v13, HFA11 hfa);
-HFADLL_API FLOATTYPE  sum19_HFA19(float v1, double v2, float v3, double v4, float v5, double v6, float v7, double v8, float v9, double v10, float v11, double v12, float v13, HFA19 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum_HFA01(HFA01 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum_HFA02(HFA02 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum_HFA03(HFA03 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum_HFA05(HFA05 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum_HFA08(HFA08 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum_HFA11(HFA11 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum_HFA19(HFA19 hfa);
+
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum3_HFA01(float v1, __int64 v2, HFA01 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum3_HFA02(float v1, __int64 v2, HFA02 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum3_HFA03(float v1, __int64 v2, HFA03 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum3_HFA05(float v1, __int64 v2, HFA05 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum3_HFA08(float v1, __int64 v2, HFA08 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum3_HFA11(float v1, __int64 v2, HFA11 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum3_HFA19(float v1, __int64 v2, HFA19 hfa);
+
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum5_HFA01(__int64 v1, double v2, short v3, signed char v4, HFA01 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum5_HFA02(__int64 v1, double v2, short v3, signed char v4, HFA02 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum5_HFA03(__int64 v1, double v2, short v3, signed char v4, HFA03 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum5_HFA05(__int64 v1, double v2, short v3, signed char v4, HFA05 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum5_HFA08(__int64 v1, double v2, short v3, signed char v4, HFA08 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum5_HFA11(__int64 v1, double v2, short v3, signed char v4, HFA11 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum5_HFA19(__int64 v1, double v2, short v3, signed char v4, HFA19 hfa);
+
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum8_HFA01(float v1, double v2, __int64 v3, signed char v4, double v5, HFA01 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum8_HFA02(float v1, double v2, __int64 v3, signed char v4, double v5, HFA02 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum8_HFA03(float v1, double v2, __int64 v3, signed char v4, double v5, HFA03 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum8_HFA05(float v1, double v2, __int64 v3, signed char v4, double v5, HFA05 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum8_HFA08(float v1, double v2, __int64 v3, signed char v4, double v5, HFA08 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum8_HFA11(float v1, double v2, __int64 v3, signed char v4, double v5, HFA11 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum8_HFA19(float v1, double v2, __int64 v3, signed char v4, double v5, HFA19 hfa);
+
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum11_HFA01(double v1, float v2, float v3, int v4, float v5, __int64 v6, double v7, float v8, HFA01 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum11_HFA02(double v1, float v2, float v3, int v4, float v5, __int64 v6, double v7, float v8, HFA02 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum11_HFA03(double v1, float v2, float v3, int v4, float v5, __int64 v6, double v7, float v8, HFA03 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum11_HFA05(double v1, float v2, float v3, int v4, float v5, __int64 v6, double v7, float v8, HFA05 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum11_HFA08(double v1, float v2, float v3, int v4, float v5, __int64 v6, double v7, float v8, HFA08 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum11_HFA11(double v1, float v2, float v3, int v4, float v5, __int64 v6, double v7, float v8, HFA11 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum11_HFA19(double v1, float v2, float v3, int v4, float v5, __int64 v6, double v7, float v8, HFA19 hfa);
+
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum19_HFA01(float v1, double v2, float v3, double v4, float v5, double v6, float v7, double v8, float v9, double v10, float v11, double v12, float v13, HFA01 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum19_HFA02(float v1, double v2, float v3, double v4, float v5, double v6, float v7, double v8, float v9, double v10, float v11, double v12, float v13, HFA02 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum19_HFA03(float v1, double v2, float v3, double v4, float v5, double v6, float v7, double v8, float v9, double v10, float v11, double v12, float v13, HFA03 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum19_HFA05(float v1, double v2, float v3, double v4, float v5, double v6, float v7, double v8, float v9, double v10, float v11, double v12, float v13, HFA05 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum19_HFA08(float v1, double v2, float v3, double v4, float v5, double v6, float v7, double v8, float v9, double v10, float v11, double v12, float v13, HFA08 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum19_HFA11(float v1, double v2, float v3, double v4, float v5, double v6, float v7, double v8, float v9, double v10, float v11, double v12, float v13, HFA11 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV sum19_HFA19(float v1, double v2, float v3, double v4, float v5, double v6, float v7, double v8, float v9, double v10, float v11, double v12, float v13, HFA19 hfa);
 
 
 
@@ -212,53 +221,53 @@ HFADLL_API FLOATTYPE  sum19_HFA19(float v1, double v2, float v3, double v4, floa
 // sverage Methods
 // ---------------------------------------------------
 
-HFADLL_API FLOATTYPE  average_HFA01(HFA01 hfa);
-HFADLL_API FLOATTYPE  average_HFA02(HFA02 hfa);
-HFADLL_API FLOATTYPE  average_HFA03(HFA03 hfa);
-HFADLL_API FLOATTYPE  average_HFA05(HFA05 hfa);
-HFADLL_API FLOATTYPE  average_HFA08(HFA08 hfa);
-HFADLL_API FLOATTYPE  average_HFA11(HFA11 hfa);
-HFADLL_API FLOATTYPE  average_HFA19(HFA19 hfa);
-
-HFADLL_API FLOATTYPE  average3_HFA01(HFA01 hfa1, HFA01 hfa2, HFA01 hfa3);
-HFADLL_API FLOATTYPE  average3_HFA02(HFA02 hfa1, HFA02 hfa2, HFA02 hfa3);
-HFADLL_API FLOATTYPE  average3_HFA03(HFA03 hfa1, HFA03 hfa2, HFA03 hfa3);
-HFADLL_API FLOATTYPE  average3_HFA05(HFA05 hfa1, HFA05 hfa2, HFA05 hfa3);
-HFADLL_API FLOATTYPE  average3_HFA08(HFA08 hfa1, HFA08 hfa2, HFA08 hfa3);
-HFADLL_API FLOATTYPE  average3_HFA11(HFA11 hfa1, HFA11 hfa2, HFA11 hfa3);
-HFADLL_API FLOATTYPE  average3_HFA19(HFA19 hfa1, HFA19 hfa2, HFA19 hfa3);
-
-HFADLL_API FLOATTYPE  average5_HFA01(HFA01 hfa1, HFA01 hfa2, HFA01 hfa3, HFA01 hfa4, HFA01 hfa5);
-HFADLL_API FLOATTYPE  average5_HFA02(HFA02 hfa1, HFA02 hfa2, HFA02 hfa3, HFA02 hfa4, HFA02 hfa5);
-HFADLL_API FLOATTYPE  average5_HFA03(HFA03 hfa1, HFA03 hfa2, HFA03 hfa3, HFA03 hfa4, HFA03 hfa5);
-HFADLL_API FLOATTYPE  average5_HFA05(HFA05 hfa1, HFA05 hfa2, HFA05 hfa3, HFA05 hfa4, HFA05 hfa5);
-HFADLL_API FLOATTYPE  average5_HFA08(HFA08 hfa1, HFA08 hfa2, HFA08 hfa3, HFA08 hfa4, HFA08 hfa5);
-HFADLL_API FLOATTYPE  average5_HFA11(HFA11 hfa1, HFA11 hfa2, HFA11 hfa3, HFA11 hfa4, HFA11 hfa5);
-HFADLL_API FLOATTYPE  average5_HFA19(HFA19 hfa1, HFA19 hfa2, HFA19 hfa3, HFA19 hfa4, HFA19 hfa5);
-
-HFADLL_API FLOATTYPE  average8_HFA01(HFA01 hfa1, HFA01 hfa2, HFA01 hfa3, HFA01 hfa4, HFA01 hfa5, HFA01 hfa6, HFA01 hfa7, HFA01 hfa8);
-HFADLL_API FLOATTYPE  average8_HFA02(HFA02 hfa1, HFA02 hfa2, HFA02 hfa3, HFA02 hfa4, HFA02 hfa5, HFA02 hfa6, HFA02 hfa7, HFA02 hfa8);
-HFADLL_API FLOATTYPE  average8_HFA03(HFA03 hfa1, HFA03 hfa2, HFA03 hfa3, HFA03 hfa4, HFA03 hfa5, HFA03 hfa6, HFA03 hfa7, HFA03 hfa8);
-HFADLL_API FLOATTYPE  average8_HFA05(HFA05 hfa1, HFA05 hfa2, HFA05 hfa3, HFA05 hfa4, HFA05 hfa5, HFA05 hfa6, HFA05 hfa7, HFA05 hfa8);
-HFADLL_API FLOATTYPE  average8_HFA08(HFA08 hfa1, HFA08 hfa2, HFA08 hfa3, HFA08 hfa4, HFA08 hfa5, HFA08 hfa6, HFA08 hfa7, HFA08 hfa8);
-HFADLL_API FLOATTYPE  average8_HFA11(HFA11 hfa1, HFA11 hfa2, HFA11 hfa3, HFA11 hfa4, HFA11 hfa5, HFA11 hfa6, HFA11 hfa7, HFA11 hfa8);
-HFADLL_API FLOATTYPE  average8_HFA19(HFA19 hfa1, HFA19 hfa2, HFA19 hfa3, HFA19 hfa4, HFA19 hfa5, HFA19 hfa6, HFA19 hfa7, HFA19 hfa8);
-
-HFADLL_API FLOATTYPE  average11_HFA01(HFA01 hfa1, HFA01 hfa2, HFA01 hfa3, HFA01 hfa4, HFA01 hfa5, HFA01 hfa6, HFA01 hfa7, HFA01 hfa8, HFA01 hfa9, HFA01 hfa10, HFA01 hfa11);
-HFADLL_API FLOATTYPE  average11_HFA02(HFA02 hfa1, HFA02 hfa2, HFA02 hfa3, HFA02 hfa4, HFA02 hfa5, HFA02 hfa6, HFA02 hfa7, HFA02 hfa8, HFA02 hfa9, HFA02 hfa10, HFA02 hfa11);
-HFADLL_API FLOATTYPE  average11_HFA03(HFA03 hfa1, HFA03 hfa2, HFA03 hfa3, HFA03 hfa4, HFA03 hfa5, HFA03 hfa6, HFA03 hfa7, HFA03 hfa8, HFA03 hfa9, HFA03 hfa10, HFA03 hfa11);
-HFADLL_API FLOATTYPE  average11_HFA05(HFA05 hfa1, HFA05 hfa2, HFA05 hfa3, HFA05 hfa4, HFA05 hfa5, HFA05 hfa6, HFA05 hfa7, HFA05 hfa8, HFA05 hfa9, HFA05 hfa10, HFA05 hfa11);
-HFADLL_API FLOATTYPE  average11_HFA08(HFA08 hfa1, HFA08 hfa2, HFA08 hfa3, HFA08 hfa4, HFA08 hfa5, HFA08 hfa6, HFA08 hfa7, HFA08 hfa8, HFA08 hfa9, HFA08 hfa10, HFA08 hfa11);
-HFADLL_API FLOATTYPE  average11_HFA11(HFA11 hfa1, HFA11 hfa2, HFA11 hfa3, HFA11 hfa4, HFA11 hfa5, HFA11 hfa6, HFA11 hfa7, HFA11 hfa8, HFA11 hfa9, HFA11 hfa10, HFA11 hfa11);
-HFADLL_API FLOATTYPE  average11_HFA19(HFA19 hfa1, HFA19 hfa2, HFA19 hfa3, HFA19 hfa4, HFA19 hfa5, HFA19 hfa6, HFA19 hfa7, HFA19 hfa8, HFA19 hfa9, HFA19 hfa10, HFA19 hfa11);
-
-HFADLL_API FLOATTYPE  average19_HFA01(HFA01 hfa1, HFA01 hfa2, HFA01 hfa3, HFA01 hfa4, HFA01 hfa5, HFA01 hfa6, HFA01 hfa7, HFA01 hfa8, HFA01 hfa9, HFA01 hfa10, HFA01 hfa11, HFA01 hfa12, HFA01 hfa13, HFA01 hfa14, HFA01 hfa15, HFA01 hfa16, HFA01 hfa17, HFA01 hfa18, HFA01 hfa19);
-HFADLL_API FLOATTYPE  average19_HFA02(HFA02 hfa1, HFA02 hfa2, HFA02 hfa3, HFA02 hfa4, HFA02 hfa5, HFA02 hfa6, HFA02 hfa7, HFA02 hfa8, HFA02 hfa9, HFA02 hfa10, HFA02 hfa11, HFA02 hfa12, HFA02 hfa13, HFA02 hfa14, HFA02 hfa15, HFA02 hfa16, HFA02 hfa17, HFA02 hfa18, HFA02 hfa19);
-HFADLL_API FLOATTYPE  average19_HFA03(HFA03 hfa1, HFA03 hfa2, HFA03 hfa3, HFA03 hfa4, HFA03 hfa5, HFA03 hfa6, HFA03 hfa7, HFA03 hfa8, HFA03 hfa9, HFA03 hfa10, HFA03 hfa11, HFA03 hfa12, HFA03 hfa13, HFA03 hfa14, HFA03 hfa15, HFA03 hfa16, HFA03 hfa17, HFA03 hfa18, HFA03 hfa19);
-HFADLL_API FLOATTYPE  average19_HFA05(HFA05 hfa1, HFA05 hfa2, HFA05 hfa3, HFA05 hfa4, HFA05 hfa5, HFA05 hfa6, HFA05 hfa7, HFA05 hfa8, HFA05 hfa9, HFA05 hfa10, HFA05 hfa11, HFA05 hfa12, HFA05 hfa13, HFA05 hfa14, HFA05 hfa15, HFA05 hfa16, HFA05 hfa17, HFA05 hfa18, HFA05 hfa19);
-HFADLL_API FLOATTYPE  average19_HFA08(HFA08 hfa1, HFA08 hfa2, HFA08 hfa3, HFA08 hfa4, HFA08 hfa5, HFA08 hfa6, HFA08 hfa7, HFA08 hfa8, HFA08 hfa9, HFA08 hfa10, HFA08 hfa11, HFA08 hfa12, HFA08 hfa13, HFA08 hfa14, HFA08 hfa15, HFA08 hfa16, HFA08 hfa17, HFA08 hfa18, HFA08 hfa19);
-HFADLL_API FLOATTYPE  average19_HFA11(HFA11 hfa1, HFA11 hfa2, HFA11 hfa3, HFA11 hfa4, HFA11 hfa5, HFA11 hfa6, HFA11 hfa7, HFA11 hfa8, HFA11 hfa9, HFA11 hfa10, HFA11 hfa11, HFA11 hfa12, HFA11 hfa13, HFA11 hfa14, HFA11 hfa15, HFA11 hfa16, HFA11 hfa17, HFA11 hfa18, HFA11 hfa19);
-HFADLL_API FLOATTYPE  average19_HFA19(HFA19 hfa1, HFA19 hfa2, HFA19 hfa3, HFA19 hfa4, HFA19 hfa5, HFA19 hfa6, HFA19 hfa7, HFA19 hfa8, HFA19 hfa9, HFA19 hfa10, HFA19 hfa11, HFA19 hfa12, HFA19 hfa13, HFA19 hfa14, HFA19 hfa15, HFA19 hfa16, HFA19 hfa17, HFA19 hfa18, HFA19 hfa19);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average_HFA01(HFA01 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average_HFA02(HFA02 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average_HFA03(HFA03 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average_HFA05(HFA05 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average_HFA08(HFA08 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average_HFA11(HFA11 hfa);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average_HFA19(HFA19 hfa);
+
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average3_HFA01(HFA01 hfa1, HFA01 hfa2, HFA01 hfa3);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average3_HFA02(HFA02 hfa1, HFA02 hfa2, HFA02 hfa3);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average3_HFA03(HFA03 hfa1, HFA03 hfa2, HFA03 hfa3);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average3_HFA05(HFA05 hfa1, HFA05 hfa2, HFA05 hfa3);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average3_HFA08(HFA08 hfa1, HFA08 hfa2, HFA08 hfa3);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average3_HFA11(HFA11 hfa1, HFA11 hfa2, HFA11 hfa3);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average3_HFA19(HFA19 hfa1, HFA19 hfa2, HFA19 hfa3);
+
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average5_HFA01(HFA01 hfa1, HFA01 hfa2, HFA01 hfa3, HFA01 hfa4, HFA01 hfa5);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average5_HFA02(HFA02 hfa1, HFA02 hfa2, HFA02 hfa3, HFA02 hfa4, HFA02 hfa5);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average5_HFA03(HFA03 hfa1, HFA03 hfa2, HFA03 hfa3, HFA03 hfa4, HFA03 hfa5);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average5_HFA05(HFA05 hfa1, HFA05 hfa2, HFA05 hfa3, HFA05 hfa4, HFA05 hfa5);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average5_HFA08(HFA08 hfa1, HFA08 hfa2, HFA08 hfa3, HFA08 hfa4, HFA08 hfa5);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average5_HFA11(HFA11 hfa1, HFA11 hfa2, HFA11 hfa3, HFA11 hfa4, HFA11 hfa5);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average5_HFA19(HFA19 hfa1, HFA19 hfa2, HFA19 hfa3, HFA19 hfa4, HFA19 hfa5);
+
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average8_HFA01(HFA01 hfa1, HFA01 hfa2, HFA01 hfa3, HFA01 hfa4, HFA01 hfa5, HFA01 hfa6, HFA01 hfa7, HFA01 hfa8);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average8_HFA02(HFA02 hfa1, HFA02 hfa2, HFA02 hfa3, HFA02 hfa4, HFA02 hfa5, HFA02 hfa6, HFA02 hfa7, HFA02 hfa8);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average8_HFA03(HFA03 hfa1, HFA03 hfa2, HFA03 hfa3, HFA03 hfa4, HFA03 hfa5, HFA03 hfa6, HFA03 hfa7, HFA03 hfa8);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average8_HFA05(HFA05 hfa1, HFA05 hfa2, HFA05 hfa3, HFA05 hfa4, HFA05 hfa5, HFA05 hfa6, HFA05 hfa7, HFA05 hfa8);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average8_HFA08(HFA08 hfa1, HFA08 hfa2, HFA08 hfa3, HFA08 hfa4, HFA08 hfa5, HFA08 hfa6, HFA08 hfa7, HFA08 hfa8);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average8_HFA11(HFA11 hfa1, HFA11 hfa2, HFA11 hfa3, HFA11 hfa4, HFA11 hfa5, HFA11 hfa6, HFA11 hfa7, HFA11 hfa8);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average8_HFA19(HFA19 hfa1, HFA19 hfa2, HFA19 hfa3, HFA19 hfa4, HFA19 hfa5, HFA19 hfa6, HFA19 hfa7, HFA19 hfa8);
+
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average11_HFA01(HFA01 hfa1, HFA01 hfa2, HFA01 hfa3, HFA01 hfa4, HFA01 hfa5, HFA01 hfa6, HFA01 hfa7, HFA01 hfa8, HFA01 hfa9, HFA01 hfa10, HFA01 hfa11);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average11_HFA02(HFA02 hfa1, HFA02 hfa2, HFA02 hfa3, HFA02 hfa4, HFA02 hfa5, HFA02 hfa6, HFA02 hfa7, HFA02 hfa8, HFA02 hfa9, HFA02 hfa10, HFA02 hfa11);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average11_HFA03(HFA03 hfa1, HFA03 hfa2, HFA03 hfa3, HFA03 hfa4, HFA03 hfa5, HFA03 hfa6, HFA03 hfa7, HFA03 hfa8, HFA03 hfa9, HFA03 hfa10, HFA03 hfa11);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average11_HFA05(HFA05 hfa1, HFA05 hfa2, HFA05 hfa3, HFA05 hfa4, HFA05 hfa5, HFA05 hfa6, HFA05 hfa7, HFA05 hfa8, HFA05 hfa9, HFA05 hfa10, HFA05 hfa11);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average11_HFA08(HFA08 hfa1, HFA08 hfa2, HFA08 hfa3, HFA08 hfa4, HFA08 hfa5, HFA08 hfa6, HFA08 hfa7, HFA08 hfa8, HFA08 hfa9, HFA08 hfa10, HFA08 hfa11);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average11_HFA11(HFA11 hfa1, HFA11 hfa2, HFA11 hfa3, HFA11 hfa4, HFA11 hfa5, HFA11 hfa6, HFA11 hfa7, HFA11 hfa8, HFA11 hfa9, HFA11 hfa10, HFA11 hfa11);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average11_HFA19(HFA19 hfa1, HFA19 hfa2, HFA19 hfa3, HFA19 hfa4, HFA19 hfa5, HFA19 hfa6, HFA19 hfa7, HFA19 hfa8, HFA19 hfa9, HFA19 hfa10, HFA19 hfa11);
+
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average19_HFA01(HFA01 hfa1, HFA01 hfa2, HFA01 hfa3, HFA01 hfa4, HFA01 hfa5, HFA01 hfa6, HFA01 hfa7, HFA01 hfa8, HFA01 hfa9, HFA01 hfa10, HFA01 hfa11, HFA01 hfa12, HFA01 hfa13, HFA01 hfa14, HFA01 hfa15, HFA01 hfa16, HFA01 hfa17, HFA01 hfa18, HFA01 hfa19);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average19_HFA02(HFA02 hfa1, HFA02 hfa2, HFA02 hfa3, HFA02 hfa4, HFA02 hfa5, HFA02 hfa6, HFA02 hfa7, HFA02 hfa8, HFA02 hfa9, HFA02 hfa10, HFA02 hfa11, HFA02 hfa12, HFA02 hfa13, HFA02 hfa14, HFA02 hfa15, HFA02 hfa16, HFA02 hfa17, HFA02 hfa18, HFA02 hfa19);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average19_HFA03(HFA03 hfa1, HFA03 hfa2, HFA03 hfa3, HFA03 hfa4, HFA03 hfa5, HFA03 hfa6, HFA03 hfa7, HFA03 hfa8, HFA03 hfa9, HFA03 hfa10, HFA03 hfa11, HFA03 hfa12, HFA03 hfa13, HFA03 hfa14, HFA03 hfa15, HFA03 hfa16, HFA03 hfa17, HFA03 hfa18, HFA03 hfa19);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average19_HFA05(HFA05 hfa1, HFA05 hfa2, HFA05 hfa3, HFA05 hfa4, HFA05 hfa5, HFA05 hfa6, HFA05 hfa7, HFA05 hfa8, HFA05 hfa9, HFA05 hfa10, HFA05 hfa11, HFA05 hfa12, HFA05 hfa13, HFA05 hfa14, HFA05 hfa15, HFA05 hfa16, HFA05 hfa17, HFA05 hfa18, HFA05 hfa19);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average19_HFA08(HFA08 hfa1, HFA08 hfa2, HFA08 hfa3, HFA08 hfa4, HFA08 hfa5, HFA08 hfa6, HFA08 hfa7, HFA08 hfa8, HFA08 hfa9, HFA08 hfa10, HFA08 hfa11, HFA08 hfa12, HFA08 hfa13, HFA08 hfa14, HFA08 hfa15, HFA08 hfa16, HFA08 hfa17, HFA08 hfa18, HFA08 hfa19);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average19_HFA11(HFA11 hfa1, HFA11 hfa2, HFA11 hfa3, HFA11 hfa4, HFA11 hfa5, HFA11 hfa6, HFA11 hfa7, HFA11 hfa8, HFA11 hfa9, HFA11 hfa10, HFA11 hfa11, HFA11 hfa12, HFA11 hfa13, HFA11 hfa14, HFA11 hfa15, HFA11 hfa16, HFA11 hfa17, HFA11 hfa18, HFA11 hfa19);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV average19_HFA19(HFA19 hfa1, HFA19 hfa2, HFA19 hfa3, HFA19 hfa4, HFA19 hfa5, HFA19 hfa6, HFA19 hfa7, HFA19 hfa8, HFA19 hfa9, HFA19 hfa10, HFA19 hfa11, HFA19 hfa12, HFA19 hfa13, HFA19 hfa14, HFA19 hfa15, HFA19 hfa16, HFA19 hfa17, HFA19 hfa18, HFA19 hfa19);
 
 
 
@@ -267,29 +276,29 @@ HFADLL_API FLOATTYPE  average19_HFA19(HFA19 hfa1, HFA19 hfa2, HFA19 hfa3, HFA19
 // add Methods
 // ---------------------------------------------------
 
-HFADLL_API FLOATTYPE  add01_HFA01(HFA01 hfa1, float v1, HFA01 hfa2, int v2, HFA01 hfa3, short v3, double v4, HFA01 hfa4, HFA01 hfa5, float v5, __int64 v6, float v7, HFA01 hfa6, float v8, HFA01 hfa7);
-HFADLL_API FLOATTYPE  add01_HFA02(HFA02 hfa1, float v1, HFA02 hfa2, int v2, HFA02 hfa3, short v3, double v4, HFA02 hfa4, HFA02 hfa5, float v5, __int64 v6, float v7, HFA02 hfa6, float v8, HFA02 hfa7);
-HFADLL_API FLOATTYPE  add01_HFA03(HFA03 hfa1, float v1, HFA03 hfa2, int v2, HFA03 hfa3, short v3, double v4, HFA03 hfa4, HFA03 hfa5, float v5, __int64 v6, float v7, HFA03 hfa6, float v8, HFA03 hfa7);
-HFADLL_API FLOATTYPE  add01_HFA05(HFA05 hfa1, float v1, HFA05 hfa2, int v2, HFA05 hfa3, short v3, double v4, HFA05 hfa4, HFA05 hfa5, float v5, __int64 v6, float v7, HFA05 hfa6, float v8, HFA05 hfa7);
-HFADLL_API FLOATTYPE  add01_HFA08(HFA08 hfa1, float v1, HFA08 hfa2, int v2, HFA08 hfa3, short v3, double v4, HFA08 hfa4, HFA08 hfa5, float v5, __int64 v6, float v7, HFA08 hfa6, float v8, HFA08 hfa7);
-HFADLL_API FLOATTYPE  add01_HFA11(HFA11 hfa1, float v1, HFA11 hfa2, int v2, HFA11 hfa3, short v3, double v4, HFA11 hfa4, HFA11 hfa5, float v5, __int64 v6, float v7, HFA11 hfa6, float v8, HFA11 hfa7);
-HFADLL_API FLOATTYPE  add01_HFA19(HFA19 hfa1, float v1, HFA19 hfa2, int v2, HFA19 hfa3, short v3, double v4, HFA19 hfa4, HFA19 hfa5, float v5, __int64 v6, float v7, HFA19 hfa6, float v8, HFA19 hfa7);
-HFADLL_API FLOATTYPE  add01_HFA00(HFA03 hfa1, float v1, HFA02 hfa2, int v2, HFA19 hfa3, short v3, double v4, HFA05 hfa4, HFA08 hfa5, float v5, __int64 v6, float v7, HFA11 hfa6, float v8, HFA01 hfa7);
-
-HFADLL_API FLOATTYPE  add02_HFA01(HFA01 hfa1, HFA01 hfa2, __int64 v1, short v2, float v3, int v4, double v5, float v6, HFA01 hfa3, double v7, float v8, HFA01 hfa4, short v9, HFA01 hfa5, float v10, HFA01 hfa6, HFA01 hfa7);
-HFADLL_API FLOATTYPE  add02_HFA02(HFA02 hfa1, HFA02 hfa2, __int64 v1, short v2, float v3, int v4, double v5, float v6, HFA02 hfa3, double v7, float v8, HFA02 hfa4, short v9, HFA02 hfa5, float v10, HFA02 hfa6, HFA02 hfa7);
-HFADLL_API FLOATTYPE  add02_HFA03(HFA03 hfa1, HFA03 hfa2, __int64 v1, short v2, float v3, int v4, double v5, float v6, HFA03 hfa3, double v7, float v8, HFA03 hfa4, short v9, HFA03 hfa5, float v10, HFA03 hfa6, HFA03 hfa7);
-HFADLL_API FLOATTYPE  add02_HFA05(HFA05 hfa1, HFA05 hfa2, __int64 v1, short v2, float v3, int v4, double v5, float v6, HFA05 hfa3, double v7, float v8, HFA05 hfa4, short v9, HFA05 hfa5, float v10, HFA05 hfa6, HFA05 hfa7);
-HFADLL_API FLOATTYPE  add02_HFA08(HFA08 hfa1, HFA08 hfa2, __int64 v1, short v2, float v3, int v4, double v5, float v6, HFA08 hfa3, double v7, float v8, HFA08 hfa4, short v9, HFA08 hfa5, float v10, HFA08 hfa6, HFA08 hfa7);
-HFADLL_API FLOATTYPE  add02_HFA11(HFA11 hfa1, HFA11 hfa2, __int64 v1, short v2, float v3, int v4, double v5, float v6, HFA11 hfa3, double v7, float v8, HFA11 hfa4, short v9, HFA11 hfa5, float v10, HFA11 hfa6, HFA11 hfa7);
-HFADLL_API FLOATTYPE  add02_HFA19(HFA19 hfa1, HFA19 hfa2, __int64 v1, short v2, float v3, int v4, double v5, float v6, HFA19 hfa3, double v7, float v8, HFA19 hfa4, short v9, HFA19 hfa5, float v10, HFA19 hfa6, HFA19 hfa7);
-HFADLL_API FLOATTYPE  add02_HFA00(HFA01 hfa1, HFA05 hfa2, __int64 v1, short v2, float v3, int v4, double v5, float v6, HFA03 hfa3, double v7, float v8, HFA11 hfa4, short v9, HFA19 hfa5, float v10, HFA08 hfa6, HFA02 hfa7);
-
-HFADLL_API FLOATTYPE  add03_HFA01(float v1, signed char v2, HFA01 hfa1, double v3, signed char v4, HFA01 hfa2, __int64 v5, short v6, int v7, HFA01 hfa3, HFA01 hfa4, float v8, HFA01 hfa5, float v9, HFA01 hfa6, float v10, HFA01 hfa7);
-HFADLL_API FLOATTYPE  add03_HFA02(float v1, signed char v2, HFA02 hfa1, double v3, signed char v4, HFA02 hfa2, __int64 v5, short v6, int v7, HFA02 hfa3, HFA02 hfa4, float v8, HFA02 hfa5, float v9, HFA02 hfa6, float v10, HFA02 hfa7);
-HFADLL_API FLOATTYPE  add03_HFA03(float v1, signed char v2, HFA03 hfa1, double v3, signed char v4, HFA03 hfa2, __int64 v5, short v6, int v7, HFA03 hfa3, HFA03 hfa4, float v8, HFA03 hfa5, float v9, HFA03 hfa6, float v10, HFA03 hfa7);
-HFADLL_API FLOATTYPE  add03_HFA05(float v1, signed char v2, HFA05 hfa1, double v3, signed char v4, HFA05 hfa2, __int64 v5, short v6, int v7, HFA05 hfa3, HFA05 hfa4, float v8, HFA05 hfa5, float v9, HFA05 hfa6, float v10, HFA05 hfa7);
-HFADLL_API FLOATTYPE  add03_HFA08(float v1, signed char v2, HFA08 hfa1, double v3, signed char v4, HFA08 hfa2, __int64 v5, short v6, int v7, HFA08 hfa3, HFA08 hfa4, float v8, HFA08 hfa5, float v9, HFA08 hfa6, float v10, HFA08 hfa7);
-HFADLL_API FLOATTYPE  add03_HFA11(float v1, signed char v2, HFA11 hfa1, double v3, signed char v4, HFA11 hfa2, __int64 v5, short v6, int v7, HFA11 hfa3, HFA11 hfa4, float v8, HFA11 hfa5, float v9, HFA11 hfa6, float v10, HFA11 hfa7);
-HFADLL_API FLOATTYPE  add03_HFA19(float v1, signed char v2, HFA19 hfa1, double v3, signed char v4, HFA19 hfa2, __int64 v5, short v6, int v7, HFA19 hfa3, HFA19 hfa4, float v8, HFA19 hfa5, float v9, HFA19 hfa6, float v10, HFA19 hfa7);
-HFADLL_API FLOATTYPE  add03_HFA00(float v1, signed char v2, HFA08 hfa1, double v3, signed char v4, HFA19 hfa2, __int64 v5, short v6, int v7, HFA03 hfa3, HFA01 hfa4, float v8, HFA11 hfa5, float v9, HFA02 hfa6, float v10, HFA05 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add01_HFA01(HFA01 hfa1, float v1, HFA01 hfa2, int v2, HFA01 hfa3, short v3, double v4, HFA01 hfa4, HFA01 hfa5, float v5, __int64 v6, float v7, HFA01 hfa6, float v8, HFA01 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add01_HFA02(HFA02 hfa1, float v1, HFA02 hfa2, int v2, HFA02 hfa3, short v3, double v4, HFA02 hfa4, HFA02 hfa5, float v5, __int64 v6, float v7, HFA02 hfa6, float v8, HFA02 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add01_HFA03(HFA03 hfa1, float v1, HFA03 hfa2, int v2, HFA03 hfa3, short v3, double v4, HFA03 hfa4, HFA03 hfa5, float v5, __int64 v6, float v7, HFA03 hfa6, float v8, HFA03 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add01_HFA05(HFA05 hfa1, float v1, HFA05 hfa2, int v2, HFA05 hfa3, short v3, double v4, HFA05 hfa4, HFA05 hfa5, float v5, __int64 v6, float v7, HFA05 hfa6, float v8, HFA05 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add01_HFA08(HFA08 hfa1, float v1, HFA08 hfa2, int v2, HFA08 hfa3, short v3, double v4, HFA08 hfa4, HFA08 hfa5, float v5, __int64 v6, float v7, HFA08 hfa6, float v8, HFA08 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add01_HFA11(HFA11 hfa1, float v1, HFA11 hfa2, int v2, HFA11 hfa3, short v3, double v4, HFA11 hfa4, HFA11 hfa5, float v5, __int64 v6, float v7, HFA11 hfa6, float v8, HFA11 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add01_HFA19(HFA19 hfa1, float v1, HFA19 hfa2, int v2, HFA19 hfa3, short v3, double v4, HFA19 hfa4, HFA19 hfa5, float v5, __int64 v6, float v7, HFA19 hfa6, float v8, HFA19 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add01_HFA00(HFA03 hfa1, float v1, HFA02 hfa2, int v2, HFA19 hfa3, short v3, double v4, HFA05 hfa4, HFA08 hfa5, float v5, __int64 v6, float v7, HFA11 hfa6, float v8, HFA01 hfa7);
+
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add02_HFA01(HFA01 hfa1, HFA01 hfa2, __int64 v1, short v2, float v3, int v4, double v5, float v6, HFA01 hfa3, double v7, float v8, HFA01 hfa4, short v9, HFA01 hfa5, float v10, HFA01 hfa6, HFA01 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add02_HFA02(HFA02 hfa1, HFA02 hfa2, __int64 v1, short v2, float v3, int v4, double v5, float v6, HFA02 hfa3, double v7, float v8, HFA02 hfa4, short v9, HFA02 hfa5, float v10, HFA02 hfa6, HFA02 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add02_HFA03(HFA03 hfa1, HFA03 hfa2, __int64 v1, short v2, float v3, int v4, double v5, float v6, HFA03 hfa3, double v7, float v8, HFA03 hfa4, short v9, HFA03 hfa5, float v10, HFA03 hfa6, HFA03 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add02_HFA05(HFA05 hfa1, HFA05 hfa2, __int64 v1, short v2, float v3, int v4, double v5, float v6, HFA05 hfa3, double v7, float v8, HFA05 hfa4, short v9, HFA05 hfa5, float v10, HFA05 hfa6, HFA05 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add02_HFA08(HFA08 hfa1, HFA08 hfa2, __int64 v1, short v2, float v3, int v4, double v5, float v6, HFA08 hfa3, double v7, float v8, HFA08 hfa4, short v9, HFA08 hfa5, float v10, HFA08 hfa6, HFA08 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add02_HFA11(HFA11 hfa1, HFA11 hfa2, __int64 v1, short v2, float v3, int v4, double v5, float v6, HFA11 hfa3, double v7, float v8, HFA11 hfa4, short v9, HFA11 hfa5, float v10, HFA11 hfa6, HFA11 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add02_HFA19(HFA19 hfa1, HFA19 hfa2, __int64 v1, short v2, float v3, int v4, double v5, float v6, HFA19 hfa3, double v7, float v8, HFA19 hfa4, short v9, HFA19 hfa5, float v10, HFA19 hfa6, HFA19 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add02_HFA00(HFA01 hfa1, HFA05 hfa2, __int64 v1, short v2, float v3, int v4, double v5, float v6, HFA03 hfa3, double v7, float v8, HFA11 hfa4, short v9, HFA19 hfa5, float v10, HFA08 hfa6, HFA02 hfa7);
+
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add03_HFA01(float v1, signed char v2, HFA01 hfa1, double v3, signed char v4, HFA01 hfa2, __int64 v5, short v6, int v7, HFA01 hfa3, HFA01 hfa4, float v8, HFA01 hfa5, float v9, HFA01 hfa6, float v10, HFA01 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add03_HFA02(float v1, signed char v2, HFA02 hfa1, double v3, signed char v4, HFA02 hfa2, __int64 v5, short v6, int v7, HFA02 hfa3, HFA02 hfa4, float v8, HFA02 hfa5, float v9, HFA02 hfa6, float v10, HFA02 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add03_HFA03(float v1, signed char v2, HFA03 hfa1, double v3, signed char v4, HFA03 hfa2, __int64 v5, short v6, int v7, HFA03 hfa3, HFA03 hfa4, float v8, HFA03 hfa5, float v9, HFA03 hfa6, float v10, HFA03 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add03_HFA05(float v1, signed char v2, HFA05 hfa1, double v3, signed char v4, HFA05 hfa2, __int64 v5, short v6, int v7, HFA05 hfa3, HFA05 hfa4, float v8, HFA05 hfa5, float v9, HFA05 hfa6, float v10, HFA05 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add03_HFA08(float v1, signed char v2, HFA08 hfa1, double v3, signed char v4, HFA08 hfa2, __int64 v5, short v6, int v7, HFA08 hfa3, HFA08 hfa4, float v8, HFA08 hfa5, float v9, HFA08 hfa6, float v10, HFA08 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add03_HFA11(float v1, signed char v2, HFA11 hfa1, double v3, signed char v4, HFA11 hfa2, __int64 v5, short v6, int v7, HFA11 hfa3, HFA11 hfa4, float v8, HFA11 hfa5, float v9, HFA11 hfa6, float v10, HFA11 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add03_HFA19(float v1, signed char v2, HFA19 hfa1, double v3, signed char v4, HFA19 hfa2, __int64 v5, short v6, int v7, HFA19 hfa3, HFA19 hfa4, float v8, HFA19 hfa5, float v9, HFA19 hfa6, float v10, HFA19 hfa7);
+HFADLL_API FLOATTYPE HFADLL_CALLCONV add03_HFA00(float v1, signed char v2, HFA08 hfa1, double v3, signed char v4, HFA19 hfa2, __int64 v5, short v6, int v7, HFA03 hfa3, HFA01 hfa4, float v8, HFA11 hfa5, float v9, HFA02 hfa6, float v10, HFA05 hfa7);
index a1d35bc..77b25dc 100644 (file)
@@ -6,28 +6,100 @@ using System.Reflection;
 
 public class Test7685
 {
-    static RectangleF argumentInDStuff;
-    
+    static RectangleF passedFloatStruct;
+    static RectangleD passedDoubleStruct;
+    static RectangleI passedIntStruct;
+    static RectangleLLarge passedLongLargeStruct;
+    static RectangleLSmall passedLongSmallStruct;
+    static RectangleNestedF passedNestedSmallFStruct;
+     
     public static int Main()
     {
         int iRetVal = 100;
         
-        var r = new RectangleF(1.2f, 3.4f, 5.6f, 7.8f);
-        typeof(Test7685).GetTypeInfo().GetDeclaredMethod("DoStuff").Invoke(null, new object[] { r });
+        var rF = new RectangleF(1.2f, 3.4f, 5.6f, 7.8f);
+        var rD = new RectangleD(1.7E+3d, 4.5d, 500.1d, 60.0d);
+        var rI = new RectangleI(100, -2, 3, 64);
+        var rLSmall = new RectangleLSmall(11231L);
+        var rLLarge = new RectangleLLarge(1L, 20041L, 22L, 88L);
+        var rNestedFSmall = new RectangleNestedF(1.2f, 3.4f, 5.6f, 7.8f);
+
+        typeof(Test7685).GetTypeInfo().GetDeclaredMethod("DoStuffF").Invoke(null, new object[] { rF });
+        typeof(Test7685).GetTypeInfo().GetDeclaredMethod("DoStuffD").Invoke(null, new object[] { rD });
+        typeof(Test7685).GetTypeInfo().GetDeclaredMethod("DoStuffI").Invoke(null, new object[] { rI });
+        typeof(Test7685).GetTypeInfo().GetDeclaredMethod("DoStuffLSmall").Invoke(null, new object[] { rLSmall });
+        typeof(Test7685).GetTypeInfo().GetDeclaredMethod("DoStuffLLarge").Invoke(null, new object[] { rLLarge });
+        typeof(Test7685).GetTypeInfo().GetDeclaredMethod("DoStuffNestedF").Invoke(null, new object[] { rNestedFSmall });
 
-        if (!RectangleF.Equals(ref argumentInDStuff, ref r))
+        if (!RectangleF.Equals(ref passedFloatStruct, ref rF))
         {
-            TestLibrary.Logging.WriteLine($"Error: passing struct with floats via reflection. Callee received {argumentInDStuff} instead of {r}");
+            TestLibrary.Logging.WriteLine($"Error: passing struct with floats via reflection. Callee received {passedFloatStruct} instead of {rF}");
             iRetVal = 0;
         }
+
+        if (!RectangleD.Equals(ref passedDoubleStruct, ref rD))
+        {
+            TestLibrary.Logging.WriteLine($"Error: passing struct with doubles via reflection. Callee received {passedDoubleStruct} instead of {rD}");
+            iRetVal = 1;
+        }
+
+        if (!RectangleI.Equals(ref passedIntStruct, ref rI))
+        {
+            TestLibrary.Logging.WriteLine($"Error: passing struct with ints via reflection. Callee received {passedIntStruct} instead of {rI}");
+            iRetVal = 2;
+        }
+
+        if (!RectangleLSmall.Equals(ref passedLongSmallStruct, ref rLSmall))
+        {
+            TestLibrary.Logging.WriteLine($"Error: passing struct with a long via reflection. Callee received {passedLongSmallStruct} instead of {rLSmall}");
+            iRetVal = 3;
+        }
+
+        if (!RectangleLLarge.Equals(ref passedLongLargeStruct, ref rLLarge))
+        {
+            TestLibrary.Logging.WriteLine($"Error: passing struct with longs via reflection. Callee received {passedLongLargeStruct} instead of {rLLarge}");
+            iRetVal = 4;
+        }
+
+        if (!RectangleNestedF.Equals(ref passedNestedSmallFStruct, ref rNestedFSmall))
+        {
+            TestLibrary.Logging.WriteLine($"Error: passing struct with longs via reflection. Callee received {passedNestedSmallFStruct} instead of {rNestedFSmall}");
+            iRetVal = 5;
+        }
         
         return iRetVal;
     }
 
-    public static void DoStuff(RectangleF r)
+    public static void DoStuffF(RectangleF r)
+    {
+        passedFloatStruct = r;
+    }
+
+    public static void DoStuffD(RectangleD r)
+    {
+        passedDoubleStruct = r;
+    }
+
+    public static void DoStuffI(RectangleI r)
+    {
+        passedIntStruct = r;
+    }
+
+    public static void DoStuffLSmall(RectangleLSmall r)
     {
-        argumentInDStuff = r;
+        passedLongSmallStruct = r;
     }
+
+    public static void DoStuffLLarge(RectangleLLarge r)
+    {
+        passedLongLargeStruct = r;
+    }
+
+    public static void DoStuffNestedF(RectangleNestedF r)
+    {
+        passedNestedSmallFStruct = r;
+    }
+
 }
 
 public struct RectangleF
@@ -46,3 +118,106 @@ public struct RectangleF
 
     public override string ToString() => $"[{_x}, {_y}, {_width}, {_height}]";
 }
+
+public struct RectangleFSmall
+{
+    public float _x, _y;
+
+    public RectangleFSmall(float x, float y)
+    {
+        _x = x; _y = y;
+    }
+    
+    public static bool Equals(ref RectangleFSmall r1, ref RectangleFSmall r2)
+    {
+        return (r2._x == r1._x) && (r2._y == r1._y);
+    }
+
+    public override string ToString() => $"[{_x}, {_y}]";
+}
+
+public struct RectangleD
+{
+    private double _x, _y, _width, _height;
+
+    public RectangleD(double x, double y, double width, double height)
+    {
+        _x = x; _y = y; _width = width; _height = height;
+    }
+    
+    public static bool Equals(ref RectangleD r1, ref RectangleD r2)
+    {
+        return (r2._x == r1._x) && (r2._y == r1._y) && (r2._width == r1._width) && (r2._height == r1._height);
+    }
+
+    public override string ToString() => $"[{_x}, {_y}, {_width}, {_height}]";
+}
+
+public struct RectangleI
+{
+    private int _x, _y, _width, _height;
+
+    public RectangleI(int x, int y, int width, int height)
+    {
+        _x = x; _y = y; _width = width; _height = height;
+    }
+    
+    public static bool Equals(ref RectangleI r1, ref RectangleI r2)
+    {
+        return (r2._x == r1._x) && (r2._y == r1._y) && (r2._width == r1._width) && (r2._height == r1._height);
+    }
+
+    public override string ToString() => $"[{_x}, {_y}, {_width}, {_height}]";
+}
+
+public struct RectangleLSmall
+{
+    private long _x;
+
+    public RectangleLSmall(long x)
+    {
+        _x = x;
+    }
+    
+    public static bool Equals(ref RectangleLSmall r1, ref RectangleLSmall r2)
+    {
+        return (r2._x == r1._x);
+    }
+
+    public override string ToString() => $"[{_x}]";
+}
+
+public struct RectangleLLarge
+{
+    private long _x, _y, _width, _height;
+
+    public RectangleLLarge(long x, long y, long width, long height)
+    {
+        _x = x; _y = y; _width = width; _height = height;
+    }
+    
+    public static bool Equals(ref RectangleLLarge r1, ref RectangleLLarge r2)
+    {
+        return (r2._x == r1._x) && (r2._y == r1._y) && (r2._width == r1._width) && (r2._height == r1._height);
+    }
+
+    public override string ToString() => $"[{_x}, {_y}, {_width}, {_height}]";
+}
+
+public struct RectangleNestedF
+{
+    private RectangleFSmall first, second;
+
+    public RectangleNestedF(float x, float y, float width, float height)
+    {
+        first = new RectangleFSmall(x, y);
+        second = new RectangleFSmall(width, height);
+    }
+    
+    public static bool Equals(ref RectangleNestedF r1, ref RectangleNestedF r2)
+    {
+        return (r1.first._x == r2.first._x) && (r1.first._y == r2.first._y) && (r1.second._x == r2.second._x) && (r1.second._y == r2.second._y);
+    }
+
+    public override string ToString() => $"[{first._x}, {first._y}, {second._x}, {second._y}]";
+}
\ No newline at end of file
index 51d9cda..56585e1 100644 (file)
@@ -1,6 +1,6 @@
 {
   "dependencies": {
-    "Microsoft.NETCore.Platforms": "2.0.0-preview1-25214-03",
+    "Microsoft.NETCore.Platforms": "2.0.0-preview1-25221-01",
     "xunit": "2.2.0-beta2-build3300",
     "xunit.assert": "2.2.0-beta2-build3300",
     "xunit.core": "2.2.0-beta2-build3300",
diff --git a/tests/src/baseservices/multidimmarray/rank1array.il b/tests/src/baseservices/multidimmarray/rank1array.il
new file mode 100644 (file)
index 0000000..3f36483
--- /dev/null
@@ -0,0 +1,160 @@
+// 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.
+
+// Tests that SzArray is castable to multidimensional array of rank 1 with zero lower bounds
+// and that the MdArray methods can operate on such `this`.
+// We cast an SzArray to MdArray, call methods on it, and validate the SzArray was updated
+// at the expected memory locations.
+
+.assembly extern mscorlib { }
+
+.assembly rank1array
+{
+}
+
+.module rank1array.exe
+.subsystem 0x0003
+.corflags 0x00000001
+
+.method public hidebysig static int32 Main () cil managed
+{
+    .locals init(
+        [0] int32[] szArray,
+        [1] int32[0...] mdArray
+    )
+
+    .maxstack 8
+    .entrypoint
+
+    ldc.i4.2
+    newarr int32
+    stloc.0
+
+    // SzArray is castable to MdArray rank 1 with zero lower bounds
+    ldloc.0
+    castclass int32[0...]
+    stloc.1
+
+    ldloc.1
+    ldc.i4.0
+    ldc.i4 0x4d2
+    call instance void int32[0...]::Set(int32, int32)
+
+    // The call to Set had better updated the memory location we expect
+    ldloc.0
+    ldc.i4.0
+    ldelem.i4
+    ldc.i4 0x4d2
+    ceq
+    brtrue SetOK
+    ldc.i4.1
+    ret
+
+SetOK:
+    ldloc.1
+    ldc.i4.0
+    call instance int32 int32[0...]::Get(int32)
+    ldc.i4 0x4d2
+    ceq
+    brtrue GetOK
+    ldc.i4.2
+    ret
+
+GetOK:
+    ldloc.1
+    ldc.i4.1
+    call instance int32& int32[0...]::Address(int32)
+    ldc.i4 42
+    stind.i4
+
+    // The call to Address had better given us the memory location we expect
+    ldloc.0
+    ldc.i4.1
+    ldelem.i4
+    ldc.i4 42
+    ceq
+    brtrue AddressOK
+    ldc.i4.3
+    ret
+
+AddressOK:
+
+    // We can also cast through type-size-equivalence
+    ldc.i4.0
+    newarr int32
+    isinst uint32[0...]
+    brtrue SizeEquivalenceOK
+    ldc.i4.4
+    ret
+
+SizeEquivalenceOK:
+
+    // We follow all the size equivalence rules though
+    ldc.i4.0
+    newarr float32
+    isinst uint32[0...]
+    brfalse SizeEquivalenceNegativeOK
+    ldc.i4.5
+    ret
+
+SizeEquivalenceNegativeOK:
+
+    // String -> object casts
+    ldc.i4.0
+    newarr string
+    isinst object[0...]
+    brtrue StringObjectCastOK
+    ldc.i4.6
+    ret
+
+StringObjectCastOK:
+
+    // Object -> string negative cast
+    ldc.i4.0
+    newarr object
+    isinst string[0...]
+    brfalse ObjectStringNegativeOK
+    ldc.i4.7
+    ret
+
+ObjectStringNegativeOK:
+
+    // MdArray of rank 1 is also castable to SzArray
+    ldc.i4.0
+    newobj instance void int32[0...]::.ctor(int32)
+    isinst int32[]
+    brtrue MdSzArrayOK
+    ldc.i4.8
+    ret
+
+MdSzArrayOK:
+
+    // "newobj instance void int32[0...]::.ctor(int32)" actually gives you int[]
+    ldc.i4.1
+    newobj instance void int32[0...]::.ctor(int32)
+    call instance class [mscorlib]System.Type class [mscorlib]System.Object::GetType()
+    ldtoken int32[]
+    call class [mscorlib]System.Type class [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+    ceq
+    brtrue Int32ArrayRank1IsInt32SzArray
+    ldc.i4 9
+    ret
+
+Int32ArrayRank1IsInt32SzArray:
+
+    // int32[] and int32[0..] are still different types though
+    ldtoken int32[]
+    call class [mscorlib]System.Type class [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+    ldtoken int32[0...]
+    call class [mscorlib]System.Type class [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+    ceq
+    brfalse DifferentTypes
+    ldc.i4 10
+    ret
+
+DifferentTypes:
+
+    ldc.i4 100
+    ret
+}
diff --git a/tests/src/baseservices/multidimmarray/rank1array.ilproj b/tests/src/baseservices/multidimmarray/rank1array.ilproj
new file mode 100644 (file)
index 0000000..6679689
--- /dev/null
@@ -0,0 +1,31 @@
+<?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>
+    <AssemblyName>rank1array</AssemblyName>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{405DB174-DAB1-4095-BC2D-B64E38E94B8B}</ProjectGuid>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <OutputType>Exe</OutputType>
+    <CLRTestKind>BuildAndRun</CLRTestKind>
+    <CLRTestPriority>0</CLRTestPriority>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Compile Include="rank1array.il" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/tests/src/performance/linkbench/assets/MusicStore/MusicStoreReflection.xml b/tests/src/performance/linkbench/assets/MusicStore/MusicStoreReflection.xml
new file mode 100644 (file)
index 0000000..3673c65
--- /dev/null
@@ -0,0 +1,27 @@
+<linker>
+    <!--- Called by Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions:.cctor -->
+    <assembly fullname="System.Linq.Queryable">
+        <type fullname="System.Linq.Queryable" required="true" />
+    </assembly>
+
+    <assembly fullname="System.Linq.Expressions">
+        <!--- Called by System.Linq.Expressions.Expression:CreateLambda -->
+        <type fullname="System.Linq.Expressions.Expression`1" required="true" />
+        <!--- Called by [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite<>.CreateCustomNoMatchDelegate and [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite<>.CreateCustomUpdateDelegate-->
+        <type fullname="System.Runtime.CompilerServices.CallSiteOps" required="true" />
+        <!--- Called by [System.Linq.Expressions]System.Runtime.CompilerServices.CallSiteBinder.Stitch -->
+        <type fullname="System.Runtime.CompilerServices.CallSite" required="true" />
+        <!--- Called by [System.Linq.Expressions]System.Runtime.CompilerServices.CallSiteBinder.Stitch -->
+        <type fullname="System.Runtime.CompilerServices.CallSite`1" required="true" />
+        <!--- Called by [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite`1.MakeUpdateDelegate -->
+        <type fullname="System.Dynamic.UpdateDelegates" required="true" />
+        <!--- Called by [System.Linq.Expressions]System.Dynamic.DynamicObject.MetaDynamic.BindBinaryOperation -->
+        <type fullname="System.Dynamic.DynamicObject" required="true" />
+    </assembly>
+
+    <assembly fullname="System.ComponentModel.TypeConverter">
+        <type fullname="System.ComponentModel.StringConverter" required="true" />
+        <type fullname="System.ComponentModel.BooleanConverter" required="true" />
+        <type fullname="System.ComponentModel.CollectionConverter" required="true" />
+    </assembly>
+</linker>
diff --git a/tests/src/performance/linkbench/assets/Roslyn/RoslynRoots.txt b/tests/src/performance/linkbench/assets/Roslyn/RoslynRoots.txt
new file mode 100644 (file)
index 0000000..10f149e
--- /dev/null
@@ -0,0 +1,3 @@
+Microsoft.CodeAnalysis
+Microsoft.CodeAnalysis.CSharp
+System.Private.CoreLib
diff --git a/tests/src/performance/linkbench/assets/Roslyn/RoslynRoots.xml b/tests/src/performance/linkbench/assets/Roslyn/RoslynRoots.xml
new file mode 100644 (file)
index 0000000..afc1ce6
--- /dev/null
@@ -0,0 +1,5 @@
+<linker>
+    <assembly fullname="csc">
+        <type fullname="*" required="true" />
+    </assembly>
+</linker>
diff --git a/tests/src/performance/linkbench/assets/Roslyn/illinkcsproj b/tests/src/performance/linkbench/assets/Roslyn/illinkcsproj
new file mode 100644 (file)
index 0000000..1247c5e
--- /dev/null
@@ -0,0 +1,9 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>netcoreapp2.0</TargetFramework>
+    <RuntimeIdentifiers>win7-x86;win7-x64</RuntimeIdentifiers>
+  </PropertyGroup>
+  <ItemGroup>
+    <PackageReference Include="ILLink.Tasks" Version="0.1.0-preview" />
+  </ItemGroup>
+</Project>
diff --git a/tests/src/performance/linkbench/linkbench.cs b/tests/src/performance/linkbench/linkbench.cs
new file mode 100644 (file)
index 0000000..3d29957
--- /dev/null
@@ -0,0 +1,372 @@
+using System;
+using System.Diagnostics;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Runtime.Loader;
+using System.Text;
+using System.Globalization;
+using System.Linq;
+using System.Xml.Linq;
+using Microsoft.Xunit.Performance;
+using Microsoft.Xunit.Performance.Api;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace LinkBench
+{
+    public class Benchmark
+    {
+        public string Name;
+
+        public string UnlinkedDir;
+        public string LinkedDir;
+        public double UnlinkedMsilSize;
+        public double LinkedMsilSize;
+        public double UnlinkedDirSize;
+        public double LinkedDirSize;
+        public double MsilSizeReduction;
+        public double DirSizeReduction;
+
+        private DirectoryInfo unlinkedDirInfo;
+        private DirectoryInfo linkedDirInfo;
+        private double certDiff;
+        const double MB = 1024 * 1024;
+
+        public Benchmark(string _Name, string _UnlinkedDir, string _LinkedDir)
+        {
+            Name = _Name;
+            UnlinkedDir = _UnlinkedDir;
+            LinkedDir = _LinkedDir;
+            unlinkedDirInfo = new DirectoryInfo(UnlinkedDir);
+            linkedDirInfo = new DirectoryInfo(LinkedDir);
+        }
+
+        public void Compute()
+        {
+            ComputeCertDiff();
+            UnlinkedMsilSize = GetMSILSize(UnlinkedDir);
+            LinkedMsilSize = GetMSILSize(LinkedDir);
+            UnlinkedDirSize = GetDirSize(unlinkedDirInfo);
+            LinkedDirSize = GetDirSize(linkedDirInfo);
+
+            MsilSizeReduction = (UnlinkedMsilSize - LinkedMsilSize) / UnlinkedMsilSize * 100;
+            DirSizeReduction = (UnlinkedDirSize - LinkedDirSize) / UnlinkedDirSize * 100;
+        }
+
+        // Compute total size of a directory, in MegaBytes
+        // Includes all files and subdirectories recursively
+        private double GetDirSize(DirectoryInfo dir)
+        {
+            double size = 0;
+            FileInfo[] files = dir.GetFiles();
+            foreach (FileInfo fileInfo in files)
+            {
+                size += fileInfo.Length;
+            }
+            DirectoryInfo[] subDirs = dir.GetDirectories();
+            foreach (DirectoryInfo dirInfo in subDirs)
+            {
+                size += GetDirSize(dirInfo);
+            }
+
+            return size / MB;
+        }
+
+        // Compute the size of MSIL files in a directory, in MegaBytes
+        // Top level only, excludes crossgen files.
+        private double GetMSILSize(string dir)
+        {
+            string[] files = Directory.GetFiles(dir);
+            long msilSize = 0;
+
+            foreach (string file in files)
+            {
+                if (file.EndsWith(".ni.dll") || file.EndsWith(".ni.exe"))
+                {
+                    continue;
+                }
+                try
+                {
+                    AssemblyLoadContext.GetAssemblyName(file);
+                }
+                catch (BadImageFormatException)
+                {
+                    continue;
+                }
+
+                msilSize += new FileInfo(file).Length;
+            }
+
+            return msilSize / MB;
+        }
+
+        // Gets the size of the Certificate header in a MSIL or ReadyToRun binary.
+        private long GetCertSize(string file)
+        {
+            Process p = new Process();
+            p.StartInfo.UseShellExecute = false;
+            p.StartInfo.RedirectStandardOutput = true;
+            p.StartInfo.FileName = LinkBench.ScriptDir + "GetCert.cmd";
+            p.StartInfo.Arguments = file;
+            p.Start();
+            string output = p.StandardOutput.ReadToEnd();
+            p.WaitForExit();
+            long size = Int32.Parse(output.Substring(18, 8),
+                NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite | NumberStyles.HexNumber);
+            return size;
+        }
+
+        // Get the total size difference for all certificates in all managed binaries 
+        // in the unlinked and linked directories.
+        private double ComputeCertDiff()
+        {
+            string[] files = Directory.GetFiles(LinkedDir);
+            long totalDiff = 0;
+
+            foreach (string file in files)
+            {
+                try
+                {
+                    AssemblyLoadContext.GetAssemblyName(file);
+                }
+                catch (BadImageFormatException)
+                {
+                    continue;
+                }
+
+                FileInfo fileInfo = new FileInfo(file);
+                long linkedCert = GetCertSize(file);
+                long unlinkedCert = GetCertSize(UnlinkedDir + "\\" + fileInfo.Name);
+                totalDiff += (unlinkedCert - linkedCert);
+            }
+
+            return totalDiff / MB;
+        }
+    }
+
+    public class LinkBench
+    {
+        private static ScenarioConfiguration scenarioConfiguration = new ScenarioConfiguration(new TimeSpan(2000000));
+        private static MetricModel SizeMetric = new MetricModel { Name = "Size", DisplayName = "File Size", Unit = "MB" };
+        private static MetricModel PercMetric = new MetricModel { Name = "Perc", DisplayName = "% Reduction", Unit = "%" };
+        public static string Workspace;
+        public static string ScriptDir;
+        public static string AssetsDir;
+        private static Benchmark CurrentBenchmark;
+
+        public static int Main(String [] args)
+        {
+            // Workspace is the ROOT of the coreclr tree.
+            // If CORECLR_REPO is not set, the script assumes that the location of sandbox
+            // is <path>\coreclr\sandbox.
+            bool doClone = true;
+            bool doBuild = true;
+
+            for(int i=0; i < args.Length; i++)
+            {
+                if (String.Compare(args[i], "noclone", true) == 0)
+                {
+                    doClone = false;
+                }
+                else if (String.Compare(args[i], "nobuild", true) == 0)
+                {
+                    doClone = false;
+                    doBuild = false;
+                }
+                else
+                {
+                    Console.WriteLine("Unknown argument");
+                    return -4;
+                }
+            }
+
+            Workspace = Environment.GetEnvironmentVariable("CORECLR_REPO");
+            if (Workspace == null)
+            {
+                Workspace = Directory.GetParent(Directory.GetCurrentDirectory()).FullName;
+            }
+            if (Workspace == null)
+            {
+                Console.WriteLine("CORECLR_REPO not found");
+                return -1;
+            }
+
+            string LinkBenchDir = Workspace + "\\tests\\src\\performance\\linkbench\\";
+            ScriptDir = LinkBenchDir + "scripts\\";
+            AssetsDir = LinkBenchDir + "assets\\";
+
+            Benchmark[] Benchmarks =
+            {
+                new Benchmark("HelloWorld", 
+                              "LinkBench\\HelloWorld\\bin\\release\\netcoreapp2.0\\win10-x64\\publish", 
+                              "LinkBench\\HelloWorld\\bin\\release\\netcoreapp2.0\\win10-x64\\linked"),
+                new Benchmark("WebAPI",
+                              "LinkBench\\WebAPI\\bin\\release\\netcoreapp2.0\\win10-x64\\publish",
+                              "LinkBench\\WebAPI\\bin\\release\\netcoreapp2.0\\win10-x64\\linked"),
+                new Benchmark("MusicStore", 
+                              "LinkBench\\JitBench\\src\\MusicStore\\bin\\release\\netcoreapp2.0\\win10-x64\\publish",
+                              "LinkBench\\JitBench\\src\\MusicStore\\bin\\release\\netcoreapp2.0\\win10-x64\\linked"),
+                new Benchmark("MusicStore_R2R", 
+                              "LinkBench\\JitBench\\src\\MusicStore\\bin\\release\\netcoreapp2.0\\win10-x64\\publish_r2r",
+                              "LinkBench\\JitBench\\src\\MusicStore\\bin\\release\\netcoreapp2.0\\win10-x64\\linked_r2r"),
+                new Benchmark("Corefx", 
+                              "LinkBench\\corefx\\bin\\ILLinkTrimAssembly\\netcoreapp-Windows_NT-Release-x64\\pretrimmed",
+                              "LinkBench\\corefx\\bin\\ILLinkTrimAssembly\\netcoreapp-Windows_NT-Release-x64\\trimmed"),
+                new Benchmark("Roslyn", 
+                              "LinkBench\\roslyn\\Binaries\\Release\\Exes\\CscCore",
+                              "LinkBench\\roslyn\\Binaries\\Release\\Exes\\Linked"),
+            };
+
+            // Update the build files to facilitate the link step
+            if(doClone)
+            {
+                if(!Setup())
+                {
+                    return -2;
+                }
+            }
+
+            if (doBuild)
+            {
+                // Run the setup Script, which clones, builds and links the benchmarks.
+                using (var setup = new Process())
+                {
+                    setup.StartInfo.FileName = ScriptDir + "build.cmd";
+                    setup.StartInfo.Arguments = AssetsDir;
+                    setup.Start();
+                    setup.WaitForExit();
+                    if (setup.ExitCode != 0)
+                    {
+                        Console.WriteLine("Setup failed");
+                        return -3;
+                    }
+                }
+            }
+
+            // Since this is a size measurement scenario, there are no iterations 
+            // to perform. So, create a process that does nothing, to satisfy XUnit.
+            // All size measurements are performed PostRun()
+            var emptyCmd = new ProcessStartInfo()
+            {
+                FileName = ScriptDir + "empty.cmd"
+            };
+
+            for (int i = 0; i < Benchmarks.Length; i++)
+            {
+                CurrentBenchmark = Benchmarks[i];
+                string[] scriptArgs = { "--perf:runid", CurrentBenchmark.Name };
+
+                using (var h = new XunitPerformanceHarness(scriptArgs))
+                {
+                    h.RunScenario(emptyCmd, null, null, PostRun, scenarioConfiguration);
+                }
+            }
+
+            return 0;
+        }
+
+        private static ScenarioBenchmark PostRun()
+        {
+            // The XUnit output doesn't print the benchmark name, so print it now.
+            Console.WriteLine("{0}", CurrentBenchmark.Name);
+
+            var scenario = new ScenarioBenchmark(CurrentBenchmark.Name)
+            {
+                Namespace = "LinkBench"
+            };
+
+            CurrentBenchmark.Compute();
+
+            addMeasurement(ref scenario, "MSIL Unlinked", SizeMetric, CurrentBenchmark.UnlinkedMsilSize);
+            addMeasurement(ref scenario, "MSIL Linked", SizeMetric, CurrentBenchmark.LinkedMsilSize);
+            addMeasurement(ref scenario, "MSIL %Reduction", PercMetric, CurrentBenchmark.MsilSizeReduction);
+            addMeasurement(ref scenario, "Total Uninked", SizeMetric, CurrentBenchmark.UnlinkedDirSize);
+            addMeasurement(ref scenario, "Total Linked", SizeMetric, CurrentBenchmark.LinkedDirSize);
+            addMeasurement(ref scenario, "Total %Reduction", PercMetric, CurrentBenchmark.DirSizeReduction);
+
+            return scenario;
+        }
+
+        private static bool Setup()
+        {
+            // Clone the benchmarks
+            using (var setup = new Process())
+            {
+                setup.StartInfo.FileName = ScriptDir + "clone.cmd";
+                Console.WriteLine("Run {0}", setup.StartInfo.FileName);
+                setup.Start();
+                setup.WaitForExit();
+                if (setup.ExitCode != 0)
+                {
+                    Console.WriteLine("clone failed");
+                    return false;
+                }
+            }
+
+            //Update the project files
+            AddLinkerReference("LinkBench\\HelloWorld\\HelloWorld.csproj");
+            AddLinkerReference("LinkBench\\WebAPI\\WebAPI.csproj");
+            AddLinkerReference("LinkBench\\JitBench\\src\\MusicStore\\MusicStore.csproj");
+            RemoveCrossgenTarget("LinkBench\\JitBench\\src\\MusicStore\\MusicStore.csproj");
+
+            return true;
+        }
+
+        private static void AddLinkerReference(string csproj)
+        {
+            var xdoc = XDocument.Load(csproj);
+            var ns = xdoc.Root.GetDefaultNamespace();
+            bool added = false;
+            foreach (var el in xdoc.Root.Elements(ns + "ItemGroup"))
+            {
+                if (el.Elements(ns + "PackageReference").Any())
+                {
+                    el.Add(new XElement(ns + "PackageReference",
+                        new XAttribute("Include", "ILLink.Tasks"),
+                        new XAttribute("Version", "0.1.0-preview")));
+                    added = true;
+                    break;
+                }
+            }
+            if (!added)
+            {
+                xdoc.Root.Add(new XElement(ns + "ItemGroup",
+                    new XElement(ns + "PackageReference",
+                        new XAttribute("Include", "ILLink.Tasks"),
+                        new XAttribute("Version", "0.1.0-preview"))));
+                added = true;
+            }
+            using (var fs = new FileStream(csproj, FileMode.Create))
+            {
+                xdoc.Save(fs);
+            }
+        }
+
+        private static void RemoveCrossgenTarget(string csproj)
+        {
+            var xdoc = XDocument.Load(csproj);
+            var ns = xdoc.Root.GetDefaultNamespace();
+            var target = xdoc.Root.Element(ns + "Target");
+            target.Remove();
+            using (var fs = new FileStream(csproj, FileMode.Create))
+            {
+                xdoc.Save(fs);
+            }
+        }
+
+        private static void addMeasurement(ref ScenarioBenchmark scenario, string name, MetricModel metric, double value)
+        {
+            var iteration = new IterationModel
+            {
+                Iteration = new Dictionary<string, double>()
+            };
+            iteration.Iteration.Add(metric.Name, value);
+
+            var size = new ScenarioTestModel(name);
+            size.Performance.Metrics.Add(metric);
+            size.Performance.IterationModels.Add(iteration);
+            scenario.Tests.Add(size);
+        }
+    }
+}
diff --git a/tests/src/performance/linkbench/linkbench.csproj b/tests/src/performance/linkbench/linkbench.csproj
new file mode 100644 (file)
index 0000000..2a3048a
--- /dev/null
@@ -0,0 +1,41 @@
+<?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>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <AssemblyName>LinkBench</AssemblyName>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{507E3CC2-5D95-414D-9F01-2A106FC177DC}</ProjectGuid>
+    <OutputType>exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+    <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
+    <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+  </PropertyGroup>
+  <PropertyGroup>
+    <ProjectJson>..\project.json</ProjectJson>
+    <ProjectLockJson>..\project.lock.json</ProjectLockJson>
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="linkbench.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), performance.targets))\performance.targets" />
+</Project>
diff --git a/tests/src/performance/linkbench/scripts/build.cmd b/tests/src/performance/linkbench/scripts/build.cmd
new file mode 100644 (file)
index 0000000..88b7eb1
--- /dev/null
@@ -0,0 +1,116 @@
+@echo off
+
+REM Usage: Build.cmd <LinkBench assets directory>
+setlocal
+call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\VsDevCmd.bat"
+
+set ROOT=%cd%\LinkBench
+set AssetDir=%1
+set ExitCode=0
+mkdir LinkBench 2> nul
+pushd %ROOT%
+
+echo Build ** HelloWorld **
+cd %ROOT%\HelloWorld
+dotnet restore -r win10-x64
+dotnet publish -c release -r win10-x64
+dotnet msbuild /t:Link /p:LinkerMode=sdk /p:RuntimeIdentifier=win10-x64 /v:n /p:Configuration=release
+if errorlevel 1 set ExitCode=1 
+echo -- Done -- 
+
+echo Build ** WebAPI **
+cd %ROOT%\WebAPI
+dotnet restore -r win10-x64
+dotnet publish -c release -r win10-x64
+dotnet msbuild /t:Link /p:LinkerMode=sdk /p:RuntimeIdentifier=win10-x64 /v:n /p:Configuration=release
+if errorlevel 1 set ExitCode=1 
+echo -- Done -- 
+
+echo Build ** MusicStore **
+cd %ROOT%\JitBench\src\MusicStore
+copy %AssetDir%\MusicStore\MusicStoreReflection.xml .
+dotnet restore -r win10-x64 
+dotnet publish -c release -r win10-x64
+dotnet msbuild /t:Link /p:LinkerMode=sdk /p:RuntimeIdentifier=win10-x64 /v:n /p:LinkerRootFiles=MusicStoreReflection.xml /p:Configuration=release
+if errorlevel 1 set ExitCode=1 
+echo -- Done -- 
+
+echo Build ** MusicStore Ready2Run **
+cd %ROOT%\JitBench\src\MusicStore
+powershell -noprofile -executionPolicy RemoteSigned -file Get-Crossgen.ps1
+pushd  bin\release\netcoreapp2.0\win10-x64\
+call :SetupR2R publish
+if errorlevel 1 set ExitCode=1 
+call :SetupR2R linked
+if errorlevel 1 set ExitCode=1 
+echo -- Done -- 
+
+echo Build ** CoreFX **
+cd %ROOT%\corefx
+set BinPlaceILLinkTrimAssembly=true
+call build.cmd -release
+if errorlevel 1 set ExitCode=1 
+echo -- Done -- 
+
+echo Build ** Roslyn **
+cd %ROOT%\roslyn
+copy %AssetDir%\Roslyn\RoslynRoots.txt .
+copy %AssetDir%\Roslyn\RoslynRoots.xml .
+set RoslynRoot=%cd%
+REM Build Roslyn
+call restore.cmd
+msbuild /m Roslyn.sln  /p:Configuration=Release
+REM Fetch ILLink
+mkdir illink
+cd illink
+copy %AssetDir%\Roslyn\illinkcsproj illink.csproj
+dotnet restore illink.csproj -r win10-x64 --packages bin
+cd ..
+REM Create Linker Directory
+cd Binaries\Release\Exes
+mkdir Linked
+cd CscCore
+REM Copy Unmanaged Assets
+FOR /F "delims=" %%I IN ('DIR /b *') DO (
+    corflags %%I >nul 2> nul
+    if errorlevel 1 copy %%I ..\Linked >nul
+)
+copy *.ni.dll ..\Linked
+REM Run Linker
+dotnet %RoslynRoot%\illink\bin\illink.tasks\0.1.0-preview\tools\illink.dll -t -c link -a @%RoslynRoot%\RoslynRoots.txt -x %RoslynRoot%\RoslynRoots.xml -l none -out ..\Linked
+if errorlevel 1 set ExitCode=1 
+echo -- Done -- 
+popd
+
+:Done
+exit /b %ExitCode%
+
+:SetupR2R
+REM Create R2R directory and copy all contents from MSIL to R2R directory
+mkdir %1_r2r
+xcopy /E /Y /Q %1 %1_r2r
+REM Generate Ready2Run images for all MSIL files by running crossgen
+cd %1_r2r
+copy ..\..\..\..\..\crossgen.exe 
+FOR /F %%I IN ('dir /b *.dll ^| find /V /I ".ni.dll"  ^| find /V /I "System.Private.CoreLib" ^| find /V /I "mscorlib.dll"') DO (
+    REM Don't crossgen Corlib, since the native image already exists.
+    REM For all other MSIL files (corflags returns 0), run crossgen
+    corflags %%I >nul 2>nul
+    if not errorlevel 1 (
+        crossgen /Platform_Assemblies_Paths . %%I >nul 2>nul
+        if errorlevel 1 (
+            exit /b 1
+        )
+    )
+)
+del crossgen.exe
+
+REM Remove the original MSIL files, rename the Ready2Run files .ni.dll --> .dll
+FOR /F "delims=" %%I IN ('dir /b *.dll') DO (
+    if exist %%~nI.ni.dll (
+        del %%I 
+        ren %%~nI.ni.dll %%I
+    )
+)
+cd ..
+exit /b 0
diff --git a/tests/src/performance/linkbench/scripts/clone.cmd b/tests/src/performance/linkbench/scripts/clone.cmd
new file mode 100644 (file)
index 0000000..ae28d41
--- /dev/null
@@ -0,0 +1,30 @@
+@echo off
+
+rmdir /s /q LinkBench
+
+set ROOT=%cd%\LinkBench
+mkdir LinkBench 2> nul
+pushd %ROOT%
+
+mkdir HelloWorld
+cd HelloWorld
+dotnet new console
+if errorlevel 1 exit /b 1
+cd ..
+
+mkdir WebAPI
+cd WebAPI
+dotnet new webapi
+if errorlevel 1 exit /b 1
+cd ..
+
+git clone https://github.com/aspnet/JitBench -b dev
+if errorlevel 1 exit /b 1
+
+git clone http://github.com/dotnet/corefx
+if errorlevel 1 exit /b 1
+
+git clone https://github.com/dotnet/roslyn.git
+if errorlevel 1 exit /b 1
+
+popd
\ No newline at end of file
diff --git a/tests/src/performance/linkbench/scripts/empty.cmd b/tests/src/performance/linkbench/scripts/empty.cmd
new file mode 100644 (file)
index 0000000..83cb140
--- /dev/null
@@ -0,0 +1 @@
+@echo off
diff --git a/tests/src/performance/linkbench/scripts/getcert.cmd b/tests/src/performance/linkbench/scripts/getcert.cmd
new file mode 100644 (file)
index 0000000..e02f72d
--- /dev/null
@@ -0,0 +1,2 @@
+@echo off
+"%VS140COMNTOOLS%\..\..\VC\bin\amd64\dumpbin.exe" /headers %1 | findstr /C:"Certificates Directory
index abec533..86a42f2 100644 (file)
@@ -5,16 +5,16 @@
     "xunit.performance.execution": "1.0.0-beta-build0003",
     "xunit.performance.metrics": "1.0.0-beta-build0003",
     "Microsoft.Diagnostics.Tracing.TraceEvent": "1.0.3-alpha-experimental",
-    "Microsoft.NETCore.Platforms": "2.0.0-preview1-25214-03",
+    "Microsoft.NETCore.Platforms": "2.0.0-preview1-25221-01",
     "System.Collections.NonGeneric": "4.4.0-beta-24913-02",
     "System.Console": "4.4.0-beta-24913-02",
     "System.IO.FileSystem": "4.4.0-beta-24913-02",
     "System.Linq": "4.4.0-beta-24913-02",
     "System.Linq.Expressions": "4.4.0-beta-24913-02",
-    "System.Numerics.Vectors": "4.4.0-preview1-25214-03",
+    "System.Numerics.Vectors": "4.4.0-preview1-25221-01",
     "System.Reflection": "4.4.0-beta-24913-02",
     "System.Reflection.Extensions": "4.4.0-beta-24913-02",
-    "System.Reflection.TypeExtensions": "4.4.0-preview1-25214-03",
+    "System.Reflection.TypeExtensions": "4.4.0-preview1-25221-01",
     "System.Runtime": "4.4.0-beta-24913-02",
     "System.Runtime.Extensions": "4.4.0-beta-24913-02",
     "System.Runtime.Loader": "4.0.0",
index 809433c..5829a8f 100644 (file)
@@ -70,7 +70,6 @@ GC/Features/BackgroundGC/foregroundgc/foregroundgc.sh
 GC/Features/LOHFragmentation/lohfragmentation/lohfragmentation.sh
 GC/Features/SustainedLowLatency/scenario/scenario.sh
 GC/Regressions/dev10bugs/536168/536168/536168.sh
-GC/Stress/Framework/ReliabilityFramework/ReliabilityFramework.sh
 GC/Scenarios/DoublinkList/doublinkgen/doublinkgen.sh
 Loader/classloader/TypeGeneratorTests/TypeGeneratorTest612/Generated612/Generated612.sh
 Loader/classloader/TypeGeneratorTests/TypeGeneratorTest613/Generated613/Generated613.sh