Improving robustness of the run-xunit-perf.cmd script.
--- /dev/null
+# 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.
.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
* [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)
--- /dev/null
+<?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="{"dependencies": {" />
+ <_OptimizationDataJsonLine Include=""$(OptimizationDataPackageName)" : "$(OptimizationDataVersion)" " />
+ <_OptimizationDataJsonLine Include="},"frameworks": {"netcoreapp1.0": {},"net46": {}}}"/>
+ </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
"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"
}
}
},
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
<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>
//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}")
//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\"")
--- /dev/null
+//
+// 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
#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();
}
*/
-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)
{
#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
#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();
}
*/
-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)
{
#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
#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();
}
*/
-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)
{
#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
#include "coreclrcallbacks.h"
#include "iexecutionengine.h"
-IExecutionEngine* STDMETHODCALLTYPE IEE_t()
+IExecutionEngine* IEE_t()
{
MyIEE* iee = InitIExecutionEngine();
return iee;
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);
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;
#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
// 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;
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) {
*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;
}
}
// 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)
return false;
}
- log << W("Starting ICLRRuntimeHost2") << Logger::endl;
+ log << W("Starting ICLRRuntimeHost4") << Logger::endl;
hr = host->Start();
if (FAILED(hr)) {
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;
//-------------------------------------------------------------
// Release the reference to the host
- log << W("Releasing ICLRRuntimeHost2") << Logger::endl;
+ log << W("Releasing ICLRRuntimeHost4") << Logger::endl;
host->Release();
// 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;
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) {
*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;
}
}
// Start the CoreCLR
- ICLRRuntimeHost2 *host = hostEnvironment.GetCLRRuntimeHost();
+ ICLRRuntimeHost4 *host = hostEnvironment.GetCLRRuntimeHost();
if (!host) {
return false;
}
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;
return false;
}
- log << W("Starting ICLRRuntimeHost2") << Logger::endl;
+ log << W("Starting ICLRRuntimeHost4") << Logger::endl;
hr = host->Start();
if (FAILED(hr)) {
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;
//-------------------------------------------------------------
// Release the reference to the host
- log << W("Releasing ICLRRuntimeHost2") << Logger::endl;
+ log << W("Releasing ICLRRuntimeHost4") << Logger::endl;
host->Release();
// 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__)
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,
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
"APP_NI_PATHS",
"NATIVE_DLL_SEARCH_DIRECTORIES",
"System.GC.Server",
+ "System.Globalization.Invariant",
};
const char *propertyValues[] = {
// TRUSTED_PLATFORM_ASSEMBLIES
nativeDllSearchDirs.c_str(),
// System.GC.Server
useServerGc,
+ // System.Globalization.Invariant
+ globalizationInvariant,
};
void* hostHandle;
else
{
fprintf(stderr, "ptrace(ATTACH, %d) FAILED %s\n", tid, strerror(errno));
+ closedir(taskDir);
+ return false;
}
}
}
}
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))
return false;
}
// Gather all the useful memory regions from the DAC
- if (!EnumerateMemoryRegionsWithDAC(pszExePath, minidumpType))
+ if (!EnumerateMemoryRegionsWithDAC(programPath, minidumpType))
{
return false;
}
}
bool
-CrashInfo::EnumerateMemoryRegionsWithDAC(const char *pszExePath, MINIDUMP_TYPE minidumpType)
+CrashInfo::EnumerateMemoryRegionsWithDAC(const char* programPath, MINIDUMP_TYPE minidumpType)
{
PFN_CLRDataCreateInstance pfnCLRDataCreateInstance = nullptr;
ICLRDataEnumMemoryRegions *clrDataEnumRegions = nullptr;
// 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)
{
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);
}
}
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);
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);
#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
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;
}
{
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;
//
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;
}
fprintf(stderr, "Could not open output %s: %s\n", dumpFileName, strerror(errno));
return false;
}
- printf("Writing core file %s\n", dumpFileName);
return true;
}
}
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())
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())
}
}
- 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)
{
}
}
+ printf("Written %ld bytes (%ld pages) to core file\n", total, total >> PAGE_SHIFT);
+
return true;
}
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)) ||
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)) {
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) ||
PAL_GetResourceString
PAL_get_stdout
PAL_get_stderr
+PAL_GetCurrentThread
PAL_GetSymbolModuleBase
PAL_GetTransportPipeName
PAL_InitializeDLL
#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)
}
}
-#if !defined(FEATURE_PAL)
void set_thread_group_affinity_for_heap(int heap_number, GCThreadAffinity* affinity)
{
affinity->Group = GCThreadAffinity::None;
}
}
}
-#endif // !FEATURE_PAL
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
else
set_thread_affinity_mask_for_heap(heap_number, &affinity);
}
-#endif // !FEATURE_PAL
return GCToOSInterface::CreateThread(gc_thread_stub, this, &affinity);
}
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
{
// Let the string itself become garbage.
// will be realloced next time around
- StoreObjectInHandle(m_StressObjs[m_CurStressObj], 0);
+ HndAssignHandle(m_StressObjs[m_CurStressObj], 0);
}
}
}
{
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));
+}
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_
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.
// 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);
// 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);
// 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;
#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;
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
*/
// 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);")
};
[
+ 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"),
static BOOL CanEnableGCNumaAware();
static void InitNumaNodeInfo();
-#if !defined(FEATURE_REDHAWK)&& !defined(FEATURE_PAL)
+#if !defined(FEATURE_REDHAWK)
private: // apis types
//GetNumaHighestNodeNumber()
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
//----------------------------------------------------------------------------------------
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;
// ======================================================================================
-void* __stdcall GetCLRFunction(LPCSTR FunctionName);
+void* GetCLRFunction(LPCSTR FunctionName);
#endif // __UtilCode_h__
// 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);
}
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
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
{
}
#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;
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)
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;
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;
#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;
}
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.
//
// 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);
}
#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
StructPromotionInfo->canPromote = false;
unsigned structSize = info.compCompHnd->getClassSize(typeHnd);
- if (structSize >= MaxOffset)
+ if (structSize > MaxOffset)
{
return; // struct is too large
}
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_)
#ifdef _TARGET_ARM_
else if (isHfaArg)
{
- size = GetHfaCount(argx);
+ size = GetHfaCount(argx);
+ hasMultiregStructArgs = true;
}
#endif // _TARGET_ARM_
else // struct type
}
}
-#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)
// '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)
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
// 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);
}
}
}
-#endif // defined (_TARGET_X86_) && !defined(LEGACY_BACKEND)
+#endif // defined (_TARGET_64BIT_) && !defined(LEGACY_BACKEND)
#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
if (isStructArg && !isRegArg)
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
// 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
}
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
{
// 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;
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;
}
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++)
{
}
}
+#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())
//
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
/* 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 */
internal long MTime;
internal long CTime;
internal long BirthTime;
+ internal long Dev;
+ internal long Ino;
}
internal static class FileTypes
namespace System
{
+ [Serializable]
public sealed class CharEnumerator : IEnumerator, IEnumerator<char>, IDisposable, ICloneable
{
private String _str;
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
}
}
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())
{
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====================================
**
==============================================================================*/
// Clears the contents of List.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Clear()
{
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
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)
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern /* struct _EXCEPTION_POINTERS* */ IntPtr GetExceptionPointers();
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
public static extern int GetExceptionCode();
type,
stateMachine,
pHandle,
+ values
}
//
#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
#define STDMETHODCALLTYPE __stdcall
#define STDMETHODVCALLTYPE __cdecl
-#define STDAPICALLTYPE __stdcall
+#define STDAPICALLTYPE __cdecl
#define STDAPIVCALLTYPE __cdecl
#define STDMETHODIMP HRESULT STDMETHODCALLTYPE
misc/sysinfo.cpp
misc/time.cpp
misc/utils.cpp
+ numa/numa.cpp
objmgr/palobjbase.cpp
objmgr/shmobject.cpp
objmgr/shmobjectmanager.cpp
)
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)
#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
#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
#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
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")
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)
}" 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)
#ifdef FEATURE_PAL_SXS
DCI_SXS,
#endif // FEATURE_PAL_SXS
-
+ DCI_NUMA,
DCI_LAST
} DBG_CHANNEL_ID;
--- /dev/null
+// 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_ */
#include "pal/debug.h"
#include "pal/locale.h"
#include "pal/init.h"
+#include "pal/numa.h"
#include "pal/stackstring.hpp"
#if HAVE_MACH_EXCEPTIONS
goto CLEANUP15;
}
+ if (FALSE == NUMASupportInitialize())
+ {
+ ERROR("Unable to initialize NUMA support\n");
+ goto CLEANUP15;
+ }
+
TRACE("First-time PAL initialization complete.\n");
init_count++;
}
goto done;
+ NUMASupportCleanup();
/* No cleanup required for CRTInitStdStreams */
CLEANUP15:
FILECleanupStdHandles();
return pRetVal;
}
-
/*++
Function:
VirtualFree
#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:
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;
--- /dev/null
+// 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;
+}
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
}
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;
{
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;
}
// 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);
}
//******************************************************************************
// 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;
/*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;
//******************************************************************************
// 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;
}
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;
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)
{
}
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;
{
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;
}
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;
{
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;
}
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);
#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)
{
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);
}
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
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.
// 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
#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
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;
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
{
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
// 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;
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
{
// 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
{
// 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;
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, '.');
#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;
FCFuncElement("DestroyStructure", MarshalNative::DestroyStructure)
FCFuncElement("UnsafeAddrOfPinnedArrayElement", MarshalNative::FCUnsafeAddrOfPinnedArrayElement)
FCFuncElement("GetExceptionCode", ExceptionNative::GetExceptionCode)
+ FCFuncElement("GetExceptionPointers", ExceptionNative::GetExceptionPointers)
QCFuncElement("GetHINSTANCE", COMModule::GetHINSTANCE)
FCFuncElement("OffsetOfHelper", MarshalNative::OffsetOfHelper)
{
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
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)
_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
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)
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
{
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
#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
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
}
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);
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
push eax // indirection cell address.
push esi // pTransitionBlock
+ CHECK_STACK_ALIGNMENT
call C_FUNC(DynamicHelperWorker)
test eax,eax
jnz LOCAL_LABEL(TailCallDelayLoad_Helper\suffix)
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();
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;
*(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();
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;
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);
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;
#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;
WorkingDir=Regressions\coreclr\GitHub_7685\Test7685
Expected=0
MaxAllowedDurationSeconds=600
-Categories=EXPECTED_FAIL;10107;NEW
+Categories=EXPECTED_PASS;NEW
HostStyle=0
[Generated921.cmd_9903]
<!-- 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>
{
"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": {
{
"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": {}
{
"dependencies": {
- "Microsoft.TargetingPack.Private.CoreCLR": "2.0.0-preview1-25215-03"
+ "Microsoft.TargetingPack.Private.CoreCLR": "2.0.0-preview1-25221-01"
},
"frameworks": {
"netcoreapp1.1": {
{
"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": {
{
"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",
{
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
{
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;
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:
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;
}
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);
}
}
}
return (99);
}
+#if !PROJECTK_BUILD
[DllImport("kernel32.dll")]
private extern static void DebugBreak();
[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
}
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
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.
test.TestStarted();
StartTestWorker(test);
-#else
+#else
try
{
if (curTestSet.AppDomainLoaderMode == AppDomainLoaderMode.Lazy)
{
HandleOom(e, "StartTest");
}
-#endif
+#endif
}
/// <summary>
{
SignalTestFinished(daTest);
}
-#endif
+#endif
break;
}
}
{
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;
{
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;
}
}
}
+
if (test.TestObject == null)
{
Console.WriteLine("Couldn't find path for {0}", test.Assembly);
test.EntryPointMethod = methodInfo;
}
-#endif
+#endif
}
#if !PROJECTK_BUILD
{
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));
Console.WriteLine("//b //nologo record.js -i %STRESSID% -a LOG_FAILED_TEST -k \"{0}\"", test.RefOrID);
}
p.Dispose();
+#endif
}
catch
{
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)
</ProjectReference>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
\ No newline at end of file
+</Project>
[DllImport(NativeBinaryName)]
public static extern bool ReverseP_MarshalStrB_Out(Del_MarshalStrB_Out d);
}
-}
\ No newline at end of file
+}
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);
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);
--- /dev/null
+// 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());
+ }
+}
--- /dev/null
+<?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>
"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",
"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",
"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",
"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",
// 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
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;}
// 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);
// 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);
// 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();
// 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);
// 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);
// 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);
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
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
{
"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",
--- /dev/null
+// 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
+}
--- /dev/null
+<?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>
--- /dev/null
+<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>
--- /dev/null
+Microsoft.CodeAnalysis
+Microsoft.CodeAnalysis.CSharp
+System.Private.CoreLib
--- /dev/null
+<linker>
+ <assembly fullname="csc">
+ <type fullname="*" required="true" />
+ </assembly>
+</linker>
--- /dev/null
+<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>
--- /dev/null
+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);
+ }
+ }
+}
--- /dev/null
+<?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>
--- /dev/null
+@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
--- /dev/null
+@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
--- /dev/null
+@echo off
+"%VS140COMNTOOLS%\..\..\VC\bin\amd64\dumpbin.exe" /headers %1 | findstr /C:"Certificates Directory
"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",
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