diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 0e3ca2191814ee..34e18599e5beaf 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -112,4 +112,4 @@
/docs/area-owners.* @jeffhandley
/docs/issue*.md @jeffhandley
/.github/policies/ @jeffhandley @mkArtakMSFT
-/.github/workflows/ @dotnet/runtime-infrastructure
+/.github/workflows/ @jeffhandley @dotnet/runtime-infrastructure
diff --git a/.github/workflows/README.md b/.github/workflows/README.md
index 308cb2d1a85b6b..f5e7799b30e2a2 100644
--- a/.github/workflows/README.md
+++ b/.github/workflows/README.md
@@ -2,5 +2,21 @@
General guidance:
-- Please make sure to include the @dotnet/runtime-infrastructure group as a reviewer of your PRs.
-- Do not use the `pull_request` event. Use `pull_request_target` instead, as documented in [Workflows in forked repositories](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#workflows-in-forked-repositories) and [pull_request_target](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request_target).
+Please make sure to include the @dotnet/runtime-infrastructure group as a reviewer of your PRs.
+
+For workflows that are triggered by pull requests, refer to GitHub's documentation for the `pull_request` and `pull_request_target` events. The `pull_request_target` event is the more common use case in this repository as it runs the workflow in the context of the target branch instead of in the context of the pull request's fork or branch. However, workflows that need to consume the contents of the pull request need to use the `pull_request` event. There are security considerations with each of the events though.
+
+Most workflows are intended to run only in the `dotnet/runtime` repository and not in forks. To force workflow jobs to be skipped in forks, each job should apply an `if` statement that checks the repository name or owner. Either approach works, but checking only the repository owner allows the workflow to run in copies or forks withing the dotnet org.
+
+```yaml
+jobs:
+ job-1:
+ # Do not run this job in forks
+ if: github.repository == 'dotnet/runtime'
+
+ job-2:
+ # Do not run this job in forks outside the dotnet org
+ if: github.repository_owner == 'dotnet'
+```
+
+Refer to GitHub's [Workflows in forked repositories](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#workflows-in-forked-repositories) and [pull_request_target](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request_target) documentation for more information.
diff --git a/.github/workflows/check-no-merge-label.yml b/.github/workflows/check-no-merge-label.yml
index 37cc7adf20596b..55154410c2c09d 100644
--- a/.github/workflows/check-no-merge-label.yml
+++ b/.github/workflows/check-no-merge-label.yml
@@ -12,6 +12,7 @@ on:
jobs:
check-labels:
+ if: github.repository == 'dotnet/runtime'
runs-on: ubuntu-latest
steps:
- name: Check 'NO-MERGE' label
diff --git a/.github/workflows/check-service-labels.yml b/.github/workflows/check-service-labels.yml
index 9726087abbf4dc..6cc9bfddd5c6b2 100644
--- a/.github/workflows/check-service-labels.yml
+++ b/.github/workflows/check-service-labels.yml
@@ -11,6 +11,7 @@ on:
jobs:
check-labels:
+ if: github.repository == 'dotnet/runtime'
runs-on: ubuntu-latest
steps:
- name: Check 'Servicing-approved' label
diff --git a/docs/coding-guidelines/clr-code-guide.md b/docs/coding-guidelines/clr-code-guide.md
index 281156344ec3f0..11b79fea262300 100644
--- a/docs/coding-guidelines/clr-code-guide.md
+++ b/docs/coding-guidelines/clr-code-guide.md
@@ -107,7 +107,7 @@ Rules can either be imposed by invariants or team policy.
"Team Policy" rules are rules we've established as "good practices" – for example, the rule that every function must declare a contract. While a missing contract here or there isn't a shipstopper, violating these rules is still heavily frowned upon and you should expect a bug filed against you unless you can supply a very compelling reason why your code needs an exemption.
-Team policy rules are not necessarily less important than invariants. For example, the rule to use [safemath.h][safemath.h] rather that coding your own integer overflow check is a policy rule. But because it deals with security, we'd probably treat it as higher priority than a very obscure (non-security) related bug.
+Team policy rules are not necessarily less important than invariants. For example, the rule to use [safemath.h][safemath.h] rather than coding your own integer overflow check is a policy rule. But because it deals with security, we'd probably treat it as higher priority than a very obscure (non-security) related bug.
[safemath.h]: https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/safemath.h
@@ -185,7 +185,7 @@ Here's how to fix our buggy code fragment.
GCPROTECT_END();
}
-Notice the addition of the line GCPROTECT_BEGIN(a). GCPROTECT_BEGIN is a macro whose argument is any OBJECTREF-typed storage location (it has to be an expression that can you can legally apply the address-of (&) operator to.) GCPROTECT_BEGIN tells the GC two things:
+Notice the addition of the line GCPROTECT_BEGIN(a). GCPROTECT_BEGIN is a macro whose argument is any OBJECTREF-typed storage location (it has to be an expression that you can legally apply the address-of (&) operator to.) GCPROTECT_BEGIN tells the GC two things:
- The GC is not to discard any object referred to by the reference stored in local "a".
- If the GC moves the object referred to by "a", it must update "a" to point to the new location.
@@ -250,7 +250,7 @@ The following code fragment shows how handles are used. In practice, of course,
{
MethodTable *pMT = g_pObjectClass->GetMethodTable();
- //Another way is to use handles. Handles would be
+ // Another way is to use handles. Handles would be
// wasteful for a case this simple but are useful
// if you need to protect something for the long
// term.
@@ -270,7 +270,7 @@ The following code fragment shows how handles are used. In practice, of course,
There are actually several flavors of handles. This section lists the most common ones. ([objecthandle.h][objecthandle.h] contains the complete list.)
- **HNDTYPE_STRONG**: This is the default and acts like a normal reference. Created by calling CreateHandle(OBJECTREF).
-- **HNDTYPE_WEAK_LONG**: Tracks an object as long as one strong reference to its exists but does not itself prevent the object from being GC'd. Created by calling CreateWeakHandle(OBJECTREF).
+- **HNDTYPE_WEAK_LONG**: Tracks an object as long as one strong reference to it exists but does not itself prevent the object from being GC'd. Created by calling CreateWeakHandle(OBJECTREF).
- **HNDTYPE_PINNED**: Pinned handles are strong handles which have the added property that they prevent an object from moving during a garbage collection cycle. This is useful when passing a pointer to object innards out of the runtime while GC may be enabled.
NOTE: PINNING AN OBJECT IS EXPENSIVE AS IT PREVENTS THE GC FROM ACHIEVING OPTIMAL PACKING OF OBJECTS DURING EPHEMERAL COLLECTIONS. THIS TYPE OF HANDLE SHOULD BE USED SPARINGLY!
@@ -298,7 +298,7 @@ Now, while the compiler can generate any valid code for this, it's very likely i
push [A] ;push argument to DoSomething
call DoSomething
-This is supposed to be work correctly in every case, according to the semantics of GCPROTECT. However, suppose just after the "push" instruction, another thread gets the time-slice, starts a GC and moves the object A. The local variable A will be correctly updated – but the copy of A which we just pushed as an argument to DoSomething() will not. Hence, DoSomething() will receive a pointer to the old location and crash. Clearly, preemptive GC alone will not suffice for the CLR.
+This is supposed to work correctly in every case, according to the semantics of GCPROTECT. However, suppose just after the "push" instruction, another thread gets the time-slice, starts a GC and moves the object A. The local variable A will be correctly updated – but the copy of A which we just pushed as an argument to DoSomething() will not. Hence, DoSomething() will receive a pointer to the old location and crash. Clearly, preemptive GC alone will not suffice for the CLR.
How about the alternative: cooperative GC? With cooperative GC, the above problem doesn't occur and GCPROTECT works as intended. Unfortunately, the CLR has to interop with legacy unmanaged code as well. Suppose a managed app calls out to the Win32 MessageBox api which waits for the user to click a button before returning. Until the user does this, all managed threads in the same process are blocked from GC. Not good.
@@ -447,7 +447,7 @@ Why do we use GC_NOTRIGGERS rather than GC_FORBID? Because forcing every functio
**Note:** There is no GC_FORBID keyword defined for contracts but you can simulate it by combining GC_NOTRIGGER and MODE_COOPERATIVE.
-**Important:** The notrigger thread state is implemented as a counter rather than boolean. This is unfortunate as this should not be necessary and exposes us to nasty ref-counting style bugs. What is important that contracts intentionally do not support unscoped trigger/notrigger transitions. That is, a GC_NOTRIGGER inside a contract will **increment** the thread's notrigger count on entry to the function but on exit, **it will not decrement the count , instead it will restore the count from a saved value.** Thus, any _net_ changes in the trigger state caused within the body of the function will be wiped out. This is good unless your function was designed to make a net change to the trigger state. If you have such a need, you'll just have to work around it somehow because we actively discourage such things in the first place. Ideally, we'd love to replace that counter with a Boolean at sometime.
+**Important:** The notrigger thread state is implemented as a counter rather than boolean. This is unfortunate as this should not be necessary and exposes us to nasty ref-counting style bugs. What is important is that contracts intentionally do not support unscoped trigger/notrigger transitions. That is, a GC_NOTRIGGER inside a contract will **increment** the thread's notrigger count on entry to the function but on exit, **it will not decrement the count , instead it will restore the count from a saved value.** Thus, any _net_ changes in the trigger state caused within the body of the function will be wiped out. This is good unless your function was designed to make a net change to the trigger state. If you have such a need, you'll just have to work around it somehow because we actively discourage such things in the first place. Ideally, we'd love to replace that counter with a Boolean at sometime.
#### 2.1.10.1 GC_NOTRIGGER/TRIGGERSGC on a scope
@@ -467,13 +467,13 @@ One difference between the standalone TRIGGERSGC and the contract GC_TRIGGERS: t
### 2.2.1 What are holders and why are they important?
-The CLR team has coined the name **holder** to refer to the infrastructure that encapsulates the common grunt work of writing robust **backout code**. **Backout code** is code that deallocate resources or restore CLR data structure consistency when we abort an operation due to an error or an asynchronous event. Oftentimes, the same backout code will execute in non-error paths for resources allocated for use of a single scope, but error-time backout is still needed even for longer lived resources.
+The CLR team has coined the name **holder** to refer to the infrastructure that encapsulates the common grunt work of writing robust **backout code**. **Backout code** is code that deallocates resources or restores CLR data structure consistency when we abort an operation due to an error or an asynchronous event. Oftentimes, the same backout code will execute in non-error paths for resources allocated for use of a single scope, but error-time backout is still needed even for longer lived resources.
Way back in V1, error paths were _ad-hoc._ Typically, they flowed through "fail:" labels where the backout code was accumulated.
Due to the no-compromise robustness requirements that the CLR Hosting model (with SQL Server as the initial customer) imposed on us in the .NET Framework v2 release, we have since become much more formal about backout. One reason is that we like to write backout that will execute if you leave the scope because of an exception. We also want to centralize policy regarding exceptions occurring inside backout. Finally, we want an infrastructure that will discourage developer errors from introducing backout bugs in the first place.
-Thus, we have centralized cleanup around C++ destructor technology. Instead of declaring a HANDLE, you declare a HandleHolder. The holder wraps a HANDLE and its destructor closes the handle no matter how control leaves the scope. We have already implemented standard holders for common resources (arrays, memory allocated with C++ new, Win32 handles and locks.) The Holder mechanism is extensible so you can add new types of holders as you need them.
+Thus, we have centralized cleanup around C++ destructor technology. Instead of declaring a HANDLE, you declare a HandleHolder. The holder wraps a HANDLE and its destructor closes the handle no matter how control leaves the scope. We have already implemented standard holders for common resources (arrays, memory allocated with C++ new, Win32 handles, and locks.) The Holder mechanism is extensible so you can add new types of holders as you need them.
### 2.2.2 An example of holder usage
@@ -707,8 +707,8 @@ If you wish to set the OOM state for a scope rather than a function, use the FAU
#### 2.3.2.3 Remember...
- Do not use INJECT_FAULT to indicate the possibility of non-OOM errors such as entries not existing in a hash table or a COM object not supporting an interface. INJECT_FAULT indicates OOM errors and no other type.
-- Be very suspicious if your INJECT_FAULT() argument is anything other than throwing an OOM exception or returning E_OUTOFMEMORY. OOM errors must distinguishable from other types of errors so if you're merely returning NULL without indicating the type of error, you'd better be a simple memory allocator or some other function that will never fail for any reason other than an OOM.
-- THROWS and INJECT_FAULT correlate strongly but are independent. A NOTHROW/INJECT_FAULT combo might indicate a function that returns HRESULTs including E_OUTOFMEMORY. A THROWS/FORBID_FAULT however indicate a function that can throw an exception but not an OutOfMemoryException. While theoretically possible, such a contract is probably a bug.
+- Be very suspicious if your INJECT_FAULT() argument is anything other than throwing an OOM exception or returning E_OUTOFMEMORY. OOM errors must be distinguishable from other types of errors so if you're merely returning NULL without indicating the type of error, you'd better be a simple memory allocator or some other function that will never fail for any reason other than an OOM.
+- THROWS and INJECT_FAULT correlate strongly but are independent. A NOTHROW/INJECT_FAULT combo might indicate a function that returns HRESULTs including E_OUTOFMEMORY. A THROWS/FORBID_FAULT however indicates a function that can throw an exception but not an OutOfMemoryException. While theoretically possible, such a contract is probably a bug.
## 2.4 Are you using SString and/or the safe string manipulation functions?
@@ -716,7 +716,7 @@ The native C implementation of strings as raw char* buffers is a well-known bree
### 2.4.1 SString
-SString is the abstraction to use for unmanaged strings in CLR code. It is important that as much code is possible uses the SString abstraction rather than raw character arrays, because of the danger of buffer overrun related to direct manipulation of arrays. Code which does not use SString must be manually reviewed for the possibility of buffer overrun or corruption during every security review.
+SString is the abstraction to use for unmanaged strings in CLR code. It is important that as much code as possible uses the SString abstraction rather than raw character arrays, because of the danger of buffer overrun related to direct manipulation of arrays. Code which does not use SString must be manually reviewed for the possibility of buffer overrun or corruption during every security review.
This section will provide an overview for SString. For specific details on methods and use, see the file [src\inc\sstring.h][sstring.h]. SString has been in use in our codebase for quite a few years now so examples of its use should be easy to find.
@@ -724,7 +724,7 @@ This section will provide an overview for SString. For specific details on metho
An SString object represents a Unicode string. It has its own buffer which it internally manages. The string buffer is typically not referenced directly by user code; instead the string is manipulated indirectly by methods defined on SString. Ultimately there are several ways to get at the raw string buffer if such functionality is needed to interface to existing APIs. But these should be used only when absolutely necessary.
-When SStrings are used as local variables, they are typically used via the StackSString type, which uses a bit of stack space as a preallocated buffer for optimization purposes. When SStrings are use in structures, the SString type may be used directly (if it is likely that the string will be empty), or through the InlineSString template, which allows an arbitrary amount of preallocated space to be declared inline in the structure with the SString. Since InlineSStrings and StackSStrings are subtypes of SString, they have the same API, and can be passed wherever an SString is required.
+When SStrings are used as local variables, they are typically used via the StackSString type, which uses a bit of stack space as a preallocated buffer for optimization purposes. When SStrings are used in structures, the SString type may be used directly (if it is likely that the string will be empty), or through the InlineSString template, which allows an arbitrary amount of preallocated space to be declared inline in the structure with the SString. Since InlineSStrings and StackSStrings are subtypes of SString, they have the same API, and can be passed wherever an SString is required.
As parameters, SStrings should always be declared as reference parameters. Similarly, SStrings as return value should also use a "by reference" style.
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index d4109bba4deda3..493889cf360c37 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -60,14 +60,14 @@
dfa03011d6474bd0e6c9d0363e4f3b18b99f2ad8
-
+
https://github.com/dotnet/emsdk
- 191ba073d94b647f70bce142d16ec96bfd436387
+ dd097e361bffff02e11fceab854f6156027acee9
-
+
https://github.com/dotnet/emsdk
- 191ba073d94b647f70bce142d16ec96bfd436387
+ dd097e361bffff02e11fceab854f6156027acee9
@@ -376,17 +376,17 @@
https://github.com/dotnet/runtime-assets
fc476e8f2d685eb7cadf6342393a0af2708f4dbf
-
+
https://github.com/dotnet/roslyn
- b5e48cce69950f6f8cf8b6c6919cddf4c03a2f48
+ a6c751e3b34ba2cb87ff3761d1ba89dcb4f3069f
-
+
https://github.com/dotnet/roslyn
- b5e48cce69950f6f8cf8b6c6919cddf4c03a2f48
+ a6c751e3b34ba2cb87ff3761d1ba89dcb4f3069f
-
+
https://github.com/dotnet/roslyn
- b5e48cce69950f6f8cf8b6c6919cddf4c03a2f48
+ a6c751e3b34ba2cb87ff3761d1ba89dcb4f3069f
https://github.com/dotnet/roslyn-analyzers
@@ -397,9 +397,9 @@
8fe7aeb135c64e095f43292c427453858d937184
-
+
https://github.com/dotnet/roslyn
- b5e48cce69950f6f8cf8b6c6919cddf4c03a2f48
+ a6c751e3b34ba2cb87ff3761d1ba89dcb4f3069f
@@ -432,37 +432,37 @@
https://github.com/NuGet/NuGet.Client
8fef55f5a55a3b4f2c96cd1a9b5ddc51d4b927f8
-
+
https://github.com/dotnet/node
- 7609fd62519260f6b2c10131b03ed878e671a2e4
+ f157b219c30f5296cb3ffaa6937ef19d702c5aab
-
+
https://github.com/dotnet/node
- 7609fd62519260f6b2c10131b03ed878e671a2e4
+ f157b219c30f5296cb3ffaa6937ef19d702c5aab
-
+
https://github.com/dotnet/node
- 7609fd62519260f6b2c10131b03ed878e671a2e4
+ f157b219c30f5296cb3ffaa6937ef19d702c5aab
-
+
https://github.com/dotnet/node
- 7609fd62519260f6b2c10131b03ed878e671a2e4
+ f157b219c30f5296cb3ffaa6937ef19d702c5aab
-
+
https://github.com/dotnet/node
- 7609fd62519260f6b2c10131b03ed878e671a2e4
+ f157b219c30f5296cb3ffaa6937ef19d702c5aab
-
+
https://github.com/dotnet/node
- 7609fd62519260f6b2c10131b03ed878e671a2e4
+ f157b219c30f5296cb3ffaa6937ef19d702c5aab
-
+
https://github.com/dotnet/node
- 7609fd62519260f6b2c10131b03ed878e671a2e4
+ f157b219c30f5296cb3ffaa6937ef19d702c5aab
-
+
https://github.com/dotnet/node
- 7609fd62519260f6b2c10131b03ed878e671a2e4
+ f157b219c30f5296cb3ffaa6937ef19d702c5aab
https://github.com/dotnet/runtime-assets
diff --git a/eng/Versions.props b/eng/Versions.props
index a2d4fc5c5c2006..c404ab8efcccad 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -44,9 +44,9 @@
Any tools that contribute to the design-time experience should use the MicrosoftCodeAnalysisVersion_LatestVS property above to ensure
they do not break the local dev experience.
-->
- 4.14.0-2.25081.4
- 4.14.0-2.25081.4
- 4.14.0-2.25081.4
+ 4.14.0-2.25104.11
+ 4.14.0-2.25104.11
+ 4.14.0-2.25104.11
- 10.0.0-preview.2.25103.1
+ 10.0.0-preview.2.25104.1
$(MicrosoftNETWorkloadEmscriptenCurrentManifest100100TransportVersion)
1.1.87-gba258badda
@@ -270,7 +270,7 @@
1.0.406601
$(MicrosoftDotNetApiCompatTaskVersion)
- 10.0.0-alpha.1.25077.1
+ 10.0.0-alpha.1.25103.1
$(MicrosoftNETRuntimeEmscriptenVersion)
$(runtimewinx64MicrosoftNETCoreRuntimeWasmNodeTransportPackageVersion)
diff --git a/eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml b/eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml
index db0ab302b43545..26b86483cd8e28 100644
--- a/eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml
+++ b/eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml
@@ -19,8 +19,7 @@ parameters:
variables: {}
pool: ''
dependsOn: []
- compileOnHelix: false
- interpreter: false
+ extraHelixArguments: ''
buildAllTestsAsStandalone: false
#arcade-specific parameters
condition: always()
@@ -84,56 +83,41 @@ steps:
env:
__MonoToolPrefix: aarch64-linux-gnu-
- # Checks the value of the compileOnHelix parameter
- # and if set invokes libraries pipeline for AOT on Helix
- - ${{ if eq(parameters.compileOnHelix, 'true') }}:
- - template: /eng/pipelines/libraries/helix.yml
- parameters:
- osGroup: ${{ parameters.osGroup }}
- runtimeFlavor: ${{ parameters.runtimeFlavor }}
- archType: ${{ parameters.archType }}
- targetRid: ${{ parameters.targetRid }}
- buildConfig: ${{ parameters.buildConfig }}
- interpreter: ${{ parameters.interpreter }}
- testRunNamePrefixSuffix: ${{ parameters.testRunNamePrefixSuffix }}
- extraHelixArguments: ${{ parameters.extraHelixArguments }}
- helixQueues: ${{ parameters.helixQueues }}
- creator: ${{ parameters.creator }}
- - ${{ else }}:
- - template: /eng/pipelines/common/templates/runtimes/send-to-helix-step.yml
- parameters:
- displayName: Send tests to Helix
- buildConfig: $(buildConfigUpper)
- archType: ${{ parameters.archType }}
- osGroup: ${{ parameters.osGroup }}
- osSubgroup: ${{ parameters.osSubgroup}}
- coreClrRepoRoot: $(Build.SourcesDirectory)/src/coreclr
- shouldContinueOnError: ${{ parameters.shouldContinueOnError }}
- runtimeFlavor: ${{ parameters.runtimeFlavor }}
- runtimeVariant: ${{ parameters.runtimeVariant }}
+ - template: /eng/pipelines/common/templates/runtimes/send-to-helix-step.yml
+ parameters:
+ displayName: Send tests to Helix
+ buildConfig: $(buildConfigUpper)
+ archType: ${{ parameters.archType }}
+ osGroup: ${{ parameters.osGroup }}
+ osSubgroup: ${{ parameters.osSubgroup}}
+ coreClrRepoRoot: $(Build.SourcesDirectory)/src/coreclr
+ shouldContinueOnError: ${{ parameters.shouldContinueOnError }}
+ runtimeFlavor: ${{ parameters.runtimeFlavor }}
+ runtimeVariant: ${{ parameters.runtimeVariant }}
- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
- # Access token variable for internal project from the
- # DotNet-HelixApi-Access variable group
- helixAccessToken: $(HelixApiAccessToken)
- ${{ else }}:
- creator: $(Build.DefinitionName)
+ ${{ if eq(variables['System.TeamProject'], 'internal') }}:
+ # Access token variable for internal project from the
+ # DotNet-HelixApi-Access variable group
+ helixAccessToken: $(HelixApiAccessToken)
+ ${{ else }}:
+ creator: $(Build.DefinitionName)
- helixBuild: $(Build.BuildNumber)
- helixSource: $(_HelixSource)
- ${{ if ne(parameters.readyToRun, true) }}:
- helixType: 'test/functional/cli/'
+ helixBuild: $(Build.BuildNumber)
+ helixSource: $(_HelixSource)
+ ${{ if ne(parameters.readyToRun, true) }}:
+ helixType: 'test/functional/cli/'
- helixQueues: ${{ parameters.helixQueues }}
- # This tests whether an array is empty
- ${{ if eq(join('', parameters.helixQueues), '') }}:
- condition: false
- publishTestResults: true
- timeoutPerTestInMinutes: $(timeoutPerTestInMinutes)
- timeoutPerTestCollectionInMinutes: $(timeoutPerTestCollectionInMinutes)
- runCrossGen2: ${{ eq(parameters.readyToRun, true) }}
- compositeBuildMode: ${{ parameters.compositeBuildMode }}
- runInUnloadableContext: ${{ parameters.runInUnloadableContext }}
- nativeAotTest: ${{ parameters.nativeAotTest }}
- helixProjectArguments: '$(Build.SourcesDirectory)/src/tests/Common/helixpublishwitharcade.proj'
- scenarios: ${{ parameters.scenarios }}
+ helixQueues: ${{ parameters.helixQueues }}
+ # This tests whether an array is empty
+ ${{ if eq(join('', parameters.helixQueues), '') }}:
+ condition: false
+ publishTestResults: true
+ timeoutPerTestInMinutes: $(timeoutPerTestInMinutes)
+ timeoutPerTestCollectionInMinutes: $(timeoutPerTestCollectionInMinutes)
+ runCrossGen2: ${{ eq(parameters.readyToRun, true) }}
+ compositeBuildMode: ${{ parameters.compositeBuildMode }}
+ runInUnloadableContext: ${{ parameters.runInUnloadableContext }}
+ nativeAotTest: ${{ parameters.nativeAotTest }}
+ helixProjectArguments: '$(Build.SourcesDirectory)/src/tests/Common/helixpublishwitharcade.proj'
+ extraHelixArguments: ${{ parameters.extraHelixArguments }}
+ scenarios: ${{ parameters.scenarios }}
diff --git a/eng/pipelines/common/templates/runtimes/send-to-helix-step.yml b/eng/pipelines/common/templates/runtimes/send-to-helix-step.yml
index a45c3817d13b53..989ccdc9319a92 100644
--- a/eng/pipelines/common/templates/runtimes/send-to-helix-step.yml
+++ b/eng/pipelines/common/templates/runtimes/send-to-helix-step.yml
@@ -19,6 +19,7 @@ parameters:
runCrossGen2: ''
compositeBuildMode: false
helixProjectArguments: ''
+ extraHelixArguments: ''
runInUnloadableContext: ''
tieringTest: ''
hotColdSplitting: ''
@@ -38,7 +39,7 @@ steps:
- template: send-to-helix-inner-step.yml
parameters:
osGroup: ${{ parameters.osGroup }}
- sendParams: ${{ parameters.helixProjectArguments }} ${{ parameters.msbuildParallelism }} /bl:$(Build.SourcesDirectory)/artifacts/log/SendToHelix.binlog /p:TargetArchitecture=${{ parameters.archType }} /p:TargetOS=${{ parameters.osGroup }} /p:TargetOSSubgroup=${{ parameters.osSubgroup }} /p:Configuration=${{ parameters.buildConfig }}
+ sendParams: ${{ parameters.helixProjectArguments }} ${{ parameters.msbuildParallelism }} /bl:$(Build.SourcesDirectory)/artifacts/log/SendToHelix.binlog /p:TargetArchitecture=${{ parameters.archType }} /p:TargetOS=${{ parameters.osGroup }} /p:TargetOSSubgroup=${{ parameters.osSubgroup }} /p:Configuration=${{ parameters.buildConfig }} ${{ parameters.extraHelixArguments }}
condition: and(succeeded(), ${{ parameters.condition }})
shouldContinueOnError: ${{ parameters.shouldContinueOnError }}
displayName: ${{ parameters.displayName }}
diff --git a/eng/pipelines/extra-platforms/runtime-extra-platforms-ioslike.yml b/eng/pipelines/extra-platforms/runtime-extra-platforms-ioslike.yml
index c123ea162e4d08..47a38df343f80d 100644
--- a/eng/pipelines/extra-platforms/runtime-extra-platforms-ioslike.yml
+++ b/eng/pipelines/extra-platforms/runtime-extra-platforms-ioslike.yml
@@ -91,9 +91,8 @@ jobs:
- template: /eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml
parameters:
creator: dotnet-bot
+ testBuildArgs: /p:DevTeamProvisioning=- /p:RunAOTCompilation=true /p:MonoForceInterpreter=true /p:BuildTestsOnHelix=true
compileOnHelix: true
- interpreter: true
- testBuildArgs: /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true /p:MonoForceInterpreter=true /p:BuildTestsOnHelix=true
testRunNamePrefixSuffix: Mono_$(_BuildConfig)
extraHelixArguments: /p:NeedsToBuildAppsOnHelix=true
diff --git a/eng/pipelines/extra-platforms/runtime-extra-platforms-ioslikesimulator.yml b/eng/pipelines/extra-platforms/runtime-extra-platforms-ioslikesimulator.yml
index 714acd5b9c159f..2cfb553d5dbd6e 100644
--- a/eng/pipelines/extra-platforms/runtime-extra-platforms-ioslikesimulator.yml
+++ b/eng/pipelines/extra-platforms/runtime-extra-platforms-ioslikesimulator.yml
@@ -89,9 +89,8 @@ jobs:
- template: /eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml
parameters:
creator: dotnet-bot
+ testBuildArgs: /p:DevTeamProvisioning=- /p:RunAOTCompilation=true /p:MonoForceInterpreter=true /p:BuildTestsOnHelix=true
compileOnHelix: true
- interpreter: true
- testBuildArgs: /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true /p:MonoForceInterpreter=true /p:BuildTestsOnHelix=true
testRunNamePrefixSuffix: Mono_$(_BuildConfig)
extraHelixArguments: /p:NeedsToBuildAppsOnHelix=true
diff --git a/eng/testing/tests.ioslike.targets b/eng/testing/tests.ioslike.targets
index e2e36415a31834..6e7d667bdfe020 100644
--- a/eng/testing/tests.ioslike.targets
+++ b/eng/testing/tests.ioslike.targets
@@ -28,6 +28,7 @@
<_AppleBuildCommand Condition="'$(IncludesTestRunner)' == 'true'">apple test
<_AppleBuildCommand Condition="'$(IncludesTestRunner)' != 'true'">apple run
+
<_AppleExpectedExitCode Condition="'$(ExpectedExitCode)' != ''">--expected-exit-code $(ExpectedExitCode)
<_AfterBuildCommands>
mv $XHARNESS_OUT/AOTBuild.binlog "$HELIX_WORKITEM_UPLOAD_ROOT"
@@ -178,7 +179,7 @@
true
true
true
- AppleTestRunner.dll
+ AppleTestRunner.dll
$(PublishDir)
$(BundleDir)
diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp
index 8cc80f91b48b09..b8482f4592ae9a 100644
--- a/src/coreclr/jit/compiler.cpp
+++ b/src/coreclr/jit/compiler.cpp
@@ -8292,7 +8292,7 @@ const StructSegments& Compiler::GetSignificantSegments(ClassLayout* layout)
StructSegments* newSegments = new (this, CMK_Promotion) StructSegments(getAllocator(CMK_Promotion));
- if (layout->IsBlockLayout())
+ if (layout->IsCustomLayout())
{
newSegments->Add(StructSegments::Segment(0, layout->GetSize()));
}
diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h
index 6a7298cf3d2373..2bcbe0ee2bd31d 100644
--- a/src/coreclr/jit/compiler.h
+++ b/src/coreclr/jit/compiler.h
@@ -1938,12 +1938,16 @@ class FlowGraphDfsTree
// Whether the DFS that produced the tree found any backedges.
bool m_hasCycle;
+ // Whether the DFS that produced the tree used edge likelihoods to influence successor visitation order.
+ bool m_profileAware;
+
public:
- FlowGraphDfsTree(Compiler* comp, BasicBlock** postOrder, unsigned postOrderCount, bool hasCycle)
+ FlowGraphDfsTree(Compiler* comp, BasicBlock** postOrder, unsigned postOrderCount, bool hasCycle, bool profileAware)
: m_comp(comp)
, m_postOrder(postOrder)
, m_postOrderCount(postOrderCount)
, m_hasCycle(hasCycle)
+ , m_profileAware(profileAware)
{
}
@@ -1978,6 +1982,11 @@ class FlowGraphDfsTree
return m_hasCycle;
}
+ bool IsProfileAware() const
+ {
+ return m_profileAware;
+ }
+
#ifdef DEBUG
void Dump() const;
#endif // DEBUG
@@ -9246,7 +9255,7 @@ class Compiler
bool isOpaqueSIMDType(ClassLayout* layout) const
{
- if (layout->IsBlockLayout())
+ if (layout->IsCustomLayout())
{
return true;
}
@@ -11104,14 +11113,16 @@ class Compiler
ClassLayout* typGetLayoutByNum(unsigned layoutNum);
// Get the layout number of the specified layout.
unsigned typGetLayoutNum(ClassLayout* layout);
+ // Get the layout for the specified class handle.
+ ClassLayout* typGetObjLayout(CORINFO_CLASS_HANDLE classHandle);
+ // Get the number of a layout for the specified class handle.
+ unsigned typGetObjLayoutNum(CORINFO_CLASS_HANDLE classHandle);
+ ClassLayout* typGetCustomLayout(const ClassLayoutBuilder& builder);
+ unsigned typGetCustomLayoutNum(const ClassLayoutBuilder& builder);
// Get the layout having the specified size but no class handle.
ClassLayout* typGetBlkLayout(unsigned blockSize);
// Get the number of a layout having the specified size but no class handle.
unsigned typGetBlkLayoutNum(unsigned blockSize);
- // Get the layout for the specified class handle.
- ClassLayout* typGetObjLayout(CORINFO_CLASS_HANDLE classHandle);
- // Get the number of a layout for the specified class handle.
- unsigned typGetObjLayoutNum(CORINFO_CLASS_HANDLE classHandle);
var_types TypeHandleToVarType(CORINFO_CLASS_HANDLE handle, ClassLayout** pLayout = nullptr);
var_types TypeHandleToVarType(CorInfoType jitType, CORINFO_CLASS_HANDLE handle, ClassLayout** pLayout = nullptr);
diff --git a/src/coreclr/jit/fgdiagnostic.cpp b/src/coreclr/jit/fgdiagnostic.cpp
index 1794c6b57954c7..824c974067184a 100644
--- a/src/coreclr/jit/fgdiagnostic.cpp
+++ b/src/coreclr/jit/fgdiagnostic.cpp
@@ -4742,15 +4742,30 @@ void Compiler::fgDebugCheckFlowGraphAnnotations()
return;
}
- unsigned count = fgRunDfs(
- [](BasicBlock* block, unsigned preorderNum) {
+ auto visitPreorder = [](BasicBlock* block, unsigned preorderNum) {
assert(block->bbPreorderNum == preorderNum);
- },
- [=](BasicBlock* block, unsigned postorderNum) {
+ };
+
+ auto visitPostorder = [=](BasicBlock* block, unsigned postorderNum) {
assert(block->bbPostorderNum == postorderNum);
assert(m_dfsTree->GetPostOrder(postorderNum) == block);
- },
- [](BasicBlock* block, BasicBlock* succ) {});
+ };
+
+ auto visitEdge = [](BasicBlock* block, BasicBlock* succ) {};
+
+ unsigned count;
+ if (m_dfsTree->IsProfileAware())
+ {
+ count = fgRunDfs(visitPreorder,
+ visitPostorder,
+ visitEdge);
+ }
+ else
+ {
+ count = fgRunDfs(visitPreorder,
+ visitPostorder,
+ visitEdge);
+ }
assert(m_dfsTree->GetPostOrderCount() == count);
diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp
index 8c8376694281f6..064c94d6af4107 100644
--- a/src/coreclr/jit/fgopt.cpp
+++ b/src/coreclr/jit/fgopt.cpp
@@ -4663,10 +4663,6 @@ void Compiler::fgDoReversePostOrderLayout()
}
#endif // DEBUG
- // Compute DFS of all blocks in the method, using profile data to determine the order successors are visited in.
- //
- m_dfsTree = fgComputeDfs* useProfile */ true>();
-
// If LSRA didn't create any new blocks, we can reuse its loop-aware RPO traversal,
// which is cached in Compiler::fgBBs.
// If the cache isn't available, we need to recompute the loop-aware RPO.
@@ -4675,15 +4671,21 @@ void Compiler::fgDoReversePostOrderLayout()
if (rpoSequence == nullptr)
{
- rpoSequence = new (this, CMK_BasicBlock) BasicBlock*[m_dfsTree->GetPostOrderCount()];
+ assert(m_dfsTree == nullptr);
+ m_dfsTree = fgComputeDfs* useProfile */ true>();
FlowGraphNaturalLoops* const loops = FlowGraphNaturalLoops::Find(m_dfsTree);
- unsigned index = 0;
- auto addToSequence = [rpoSequence, &index](BasicBlock* block) {
+ rpoSequence = new (this, CMK_BasicBlock) BasicBlock*[m_dfsTree->GetPostOrderCount()];
+ unsigned index = 0;
+ auto addToSequence = [rpoSequence, &index](BasicBlock* block) {
rpoSequence[index++] = block;
};
fgVisitBlocksInLoopAwareRPO(m_dfsTree, loops, addToSequence);
}
+ else
+ {
+ assert(m_dfsTree != nullptr);
+ }
// Fast path: We don't have any EH regions, so just reorder the blocks
//
diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp
index eaed687a57eee2..369b7b7a30241c 100644
--- a/src/coreclr/jit/flowgraph.cpp
+++ b/src/coreclr/jit/flowgraph.cpp
@@ -4353,7 +4353,7 @@ FlowGraphDfsTree* Compiler::fgComputeDfs()
fgRunDfs(visitPreorder,
visitPostorder,
visitEdge);
- return new (this, CMK_DepthFirstSearch) FlowGraphDfsTree(this, postOrder, numBlocks, hasCycle);
+ return new (this, CMK_DepthFirstSearch) FlowGraphDfsTree(this, postOrder, numBlocks, hasCycle, useProfile);
}
// Add explicit instantiations.
diff --git a/src/coreclr/jit/layout.cpp b/src/coreclr/jit/layout.cpp
index 655750718bc734..5c9105b04072d6 100644
--- a/src/coreclr/jit/layout.cpp
+++ b/src/coreclr/jit/layout.cpp
@@ -5,6 +5,65 @@
#include "layout.h"
#include "compiler.h"
+// Key used in ClassLayoutTable's hash table for custom layouts.
+struct CustomLayoutKey
+{
+ unsigned Size;
+ const BYTE* GCPtrTypes;
+
+ CustomLayoutKey(ClassLayout* layout)
+ : Size(layout->GetSize())
+ , GCPtrTypes(layout->m_gcPtrCount > 0 ? layout->GetGCPtrs() : nullptr)
+ {
+ assert(layout->IsCustomLayout());
+ }
+
+ CustomLayoutKey(const ClassLayoutBuilder& builder)
+ : Size(builder.m_size)
+ , GCPtrTypes(builder.m_gcPtrCount > 0 ? builder.m_gcPtrs : nullptr)
+ {
+ }
+
+ static bool Equals(const CustomLayoutKey& l, const CustomLayoutKey& r)
+ {
+ if (l.Size != r.Size)
+ {
+ return false;
+ }
+
+ if ((l.GCPtrTypes == nullptr) != (r.GCPtrTypes == nullptr))
+ {
+ return false;
+ }
+
+ if ((l.GCPtrTypes != nullptr) && (memcmp(l.GCPtrTypes, r.GCPtrTypes, l.Size / TARGET_POINTER_SIZE) != 0))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ static unsigned GetHashCode(const CustomLayoutKey& key)
+ {
+ unsigned hash = key.Size;
+ if (key.GCPtrTypes != nullptr)
+ {
+ hash ^= 0xc4cfbb2a + (hash << 19) + (hash >> 13);
+ for (unsigned i = 0; i < key.Size / TARGET_POINTER_SIZE; i++)
+ {
+ hash ^= key.GCPtrTypes[i] + 0x9e3779b9 + (hash << 19) + (hash >> 13);
+ }
+ }
+ else
+ {
+ hash ^= 0x324ba6da + (hash << 19) + (hash >> 13);
+ }
+
+ return hash;
+ }
+};
+
// Keeps track of layout objects associated to class handles or block sizes. A layout is usually
// referenced by a pointer (ClassLayout*) but can also be referenced by a number (unsigned,
// FirstLayoutNum-based), when space constraints or other needs make numbers more appealing.
@@ -18,7 +77,7 @@ class ClassLayoutTable
static constexpr unsigned ZeroSizedBlockLayoutNum = TYP_UNKNOWN + 1;
static constexpr unsigned FirstLayoutNum = TYP_UNKNOWN + 2;
- typedef JitHashTable, unsigned> BlkLayoutIndexMap;
+ typedef JitHashTable CustomLayoutIndexMap;
typedef JitHashTable, unsigned> ObjLayoutIndexMap;
union
@@ -29,15 +88,15 @@ class ClassLayoutTable
// Otherwise a dynamic array is allocated and hashtables are used to map from handle/size to layout array index.
struct
{
- ClassLayout** m_layoutLargeArray;
- BlkLayoutIndexMap* m_blkLayoutMap;
- ObjLayoutIndexMap* m_objLayoutMap;
+ ClassLayout** m_layoutLargeArray;
+ CustomLayoutIndexMap* m_customLayoutMap;
+ ObjLayoutIndexMap* m_objLayoutMap;
};
};
// The number of layout objects stored in this table.
- unsigned m_layoutCount;
+ unsigned m_layoutCount = 0;
// The capacity of m_layoutLargeArray (when more than 3 layouts are stored).
- unsigned m_layoutLargeCapacity;
+ unsigned m_layoutLargeCapacity = 0;
// We furthermore fast-path the 0-sized block layout which is used for
// block locals that may grow (e.g. the outgoing arg area in every non-x86
// compilation).
@@ -45,9 +104,7 @@ class ClassLayoutTable
public:
ClassLayoutTable()
- : m_layoutCount(0)
- , m_layoutLargeCapacity(0)
- , m_zeroSizedBlockLayout(0)
+ : m_zeroSizedBlockLayout(0)
{
}
@@ -76,25 +133,25 @@ class ClassLayoutTable
}
// Get the layout having the specified size but no class handle.
- ClassLayout* GetBlkLayout(Compiler* compiler, unsigned blockSize)
+ ClassLayout* GetCustomLayout(Compiler* compiler, const ClassLayoutBuilder& builder)
{
- if (blockSize == 0)
+ if (builder.m_size == 0)
{
return &m_zeroSizedBlockLayout;
}
- return GetLayoutByIndex(GetBlkLayoutIndex(compiler, blockSize));
+ return GetLayoutByIndex(GetCustomLayoutIndex(compiler, builder));
}
// Get a number that uniquely identifies a layout having the specified size but no class handle.
- unsigned GetBlkLayoutNum(Compiler* compiler, unsigned blockSize)
+ unsigned GetCustomLayoutNum(Compiler* compiler, const ClassLayoutBuilder& builder)
{
- if (blockSize == 0)
+ if (builder.m_size == 0)
{
return ZeroSizedBlockLayoutNum;
}
- return GetBlkLayoutIndex(compiler, blockSize) + FirstLayoutNum;
+ return GetCustomLayoutIndex(compiler, builder) + FirstLayoutNum;
}
// Get the layout for the specified class handle.
@@ -147,8 +204,8 @@ class ClassLayoutTable
else
{
unsigned index = 0;
- if ((layout->IsBlockLayout() && m_blkLayoutMap->Lookup(layout->GetSize(), &index)) ||
- m_objLayoutMap->Lookup(layout->GetClassHandle(), &index))
+ if (layout->IsCustomLayout() ? m_customLayoutMap->Lookup(CustomLayoutKey(layout), &index)
+ : m_objLayoutMap->Lookup(layout->GetClassHandle(), &index))
{
return index;
}
@@ -157,16 +214,19 @@ class ClassLayoutTable
unreached();
}
- unsigned GetBlkLayoutIndex(Compiler* compiler, unsigned blockSize)
+ unsigned GetCustomLayoutIndex(Compiler* compiler, const ClassLayoutBuilder& builder)
{
- // The 0-sized block layout has its own fast path.
- assert(blockSize != 0);
+ // The 0-sized layout has its own fast path.
+ assert(builder.m_size != 0);
+
+ CustomLayoutKey key(builder);
if (HasSmallCapacity())
{
for (unsigned i = 0; i < m_layoutCount; i++)
{
- if (m_layoutArray[i]->IsBlockLayout() && (m_layoutArray[i]->GetSize() == blockSize))
+ if (m_layoutArray[i]->IsCustomLayout() &&
+ CustomLayoutKey::Equals(key, CustomLayoutKey(m_layoutArray[i])))
{
return i;
}
@@ -175,21 +235,16 @@ class ClassLayoutTable
else
{
unsigned index;
- if (m_blkLayoutMap->Lookup(blockSize, &index))
+ if (m_customLayoutMap->Lookup(key, &index))
{
return index;
}
}
- return AddBlkLayout(compiler, CreateBlkLayout(compiler, blockSize));
+ return AddCustomLayout(compiler, ClassLayout::Create(compiler, builder));
}
- ClassLayout* CreateBlkLayout(Compiler* compiler, unsigned blockSize)
- {
- return new (compiler, CMK_ClassLayout) ClassLayout(blockSize);
- }
-
- unsigned AddBlkLayout(Compiler* compiler, ClassLayout* layout)
+ unsigned AddCustomLayout(Compiler* compiler, ClassLayout* layout)
{
if (m_layoutCount < ArrLen(m_layoutArray))
{
@@ -198,7 +253,7 @@ class ClassLayoutTable
}
unsigned index = AddLayoutLarge(compiler, layout);
- m_blkLayoutMap->Set(layout->GetSize(), index);
+ m_customLayoutMap->Set(CustomLayoutKey(layout), index);
return index;
}
@@ -225,12 +280,7 @@ class ClassLayoutTable
}
}
- return AddObjLayout(compiler, CreateObjLayout(compiler, classHandle));
- }
-
- ClassLayout* CreateObjLayout(Compiler* compiler, CORINFO_CLASS_HANDLE classHandle)
- {
- return ClassLayout::Create(compiler, classHandle);
+ return AddObjLayout(compiler, ClassLayout::Create(compiler, classHandle));
}
unsigned AddObjLayout(Compiler* compiler, ClassLayout* layout)
@@ -256,17 +306,17 @@ class ClassLayoutTable
if (m_layoutCount <= ArrLen(m_layoutArray))
{
- BlkLayoutIndexMap* blkLayoutMap = new (alloc) BlkLayoutIndexMap(alloc);
- ObjLayoutIndexMap* objLayoutMap = new (alloc) ObjLayoutIndexMap(alloc);
+ CustomLayoutIndexMap* customLayoutMap = new (alloc) CustomLayoutIndexMap(alloc);
+ ObjLayoutIndexMap* objLayoutMap = new (alloc) ObjLayoutIndexMap(alloc);
for (unsigned i = 0; i < m_layoutCount; i++)
{
ClassLayout* l = m_layoutArray[i];
newArray[i] = l;
- if (l->IsBlockLayout())
+ if (l->IsCustomLayout())
{
- blkLayoutMap->Set(l->GetSize(), i);
+ customLayoutMap->Set(CustomLayoutKey(l), i);
}
else
{
@@ -274,8 +324,8 @@ class ClassLayoutTable
}
}
- m_blkLayoutMap = blkLayoutMap;
- m_objLayoutMap = objLayoutMap;
+ m_customLayoutMap = customLayoutMap;
+ m_objLayoutMap = objLayoutMap;
}
else
{
@@ -334,26 +384,46 @@ unsigned Compiler::typGetLayoutNum(ClassLayout* layout)
return typGetClassLayoutTable()->GetLayoutNum(layout);
}
-unsigned Compiler::typGetBlkLayoutNum(unsigned blockSize)
+unsigned Compiler::typGetObjLayoutNum(CORINFO_CLASS_HANDLE classHandle)
{
- return typGetClassLayoutTable()->GetBlkLayoutNum(this, blockSize);
+ return typGetClassLayoutTable()->GetObjLayoutNum(this, classHandle);
}
-ClassLayout* Compiler::typGetBlkLayout(unsigned blockSize)
+ClassLayout* Compiler::typGetObjLayout(CORINFO_CLASS_HANDLE classHandle)
{
- return typGetClassLayoutTable()->GetBlkLayout(this, blockSize);
+ return typGetClassLayoutTable()->GetObjLayout(this, classHandle);
}
-unsigned Compiler::typGetObjLayoutNum(CORINFO_CLASS_HANDLE classHandle)
+unsigned Compiler::typGetCustomLayoutNum(const ClassLayoutBuilder& builder)
{
- return typGetClassLayoutTable()->GetObjLayoutNum(this, classHandle);
+ return typGetClassLayoutTable()->GetCustomLayoutNum(this, builder);
}
-ClassLayout* Compiler::typGetObjLayout(CORINFO_CLASS_HANDLE classHandle)
+ClassLayout* Compiler::typGetCustomLayout(const ClassLayoutBuilder& builder)
{
- return typGetClassLayoutTable()->GetObjLayout(this, classHandle);
+ return typGetClassLayoutTable()->GetCustomLayout(this, builder);
}
+unsigned Compiler::typGetBlkLayoutNum(unsigned blockSize)
+{
+ return typGetCustomLayoutNum(ClassLayoutBuilder(this, blockSize));
+}
+
+ClassLayout* Compiler::typGetBlkLayout(unsigned blockSize)
+{
+ return typGetCustomLayout(ClassLayoutBuilder(this, blockSize));
+}
+
+//------------------------------------------------------------------------
+// Create: Create a ClassLayout from an EE side class handle.
+//
+// Parameters:
+// compiler - The Compiler object
+// classHandle - The class handle
+//
+// Return value:
+// New layout representing an EE side class.
+//
ClassLayout* ClassLayout::Create(Compiler* compiler, CORINFO_CLASS_HANDLE classHandle)
{
bool isValueClass = compiler->eeIsValueClass(classHandle);
@@ -375,49 +445,82 @@ ClassLayout* ClassLayout::Create(Compiler* compiler, CORINFO_CLASS_HANDLE classH
ClassLayout* layout = new (compiler, CMK_ClassLayout)
ClassLayout(classHandle, isValueClass, size, type DEBUGARG(className) DEBUGARG(shortClassName));
- layout->InitializeGCPtrs(compiler);
- return layout;
-}
-
-void ClassLayout::InitializeGCPtrs(Compiler* compiler)
-{
- assert(!m_gcPtrsInitialized);
- assert(!IsBlockLayout());
-
- if (m_size < TARGET_POINTER_SIZE)
+ if (layout->m_size < TARGET_POINTER_SIZE)
{
- assert(GetSlotCount() == 1);
- assert(m_gcPtrCount == 0);
+ assert(layout->GetSlotCount() == 1);
+ assert(layout->m_gcPtrCount == 0);
- m_gcPtrsArray[0] = TYPE_GC_NONE;
+ layout->m_gcPtrsArray[0] = TYPE_GC_NONE;
}
else
{
BYTE* gcPtrs;
-
- if (GetSlotCount() > sizeof(m_gcPtrsArray))
+ if (layout->GetSlotCount() <= sizeof(m_gcPtrsArray))
{
- gcPtrs = m_gcPtrs = new (compiler, CMK_ClassLayout) BYTE[GetSlotCount()];
+ gcPtrs = layout->m_gcPtrsArray;
}
else
{
- gcPtrs = m_gcPtrsArray;
+ layout->m_gcPtrs = gcPtrs = new (compiler, CMK_ClassLayout) BYTE[layout->GetSlotCount()];
}
- unsigned gcPtrCount = compiler->info.compCompHnd->getClassGClayout(m_classHandle, gcPtrs);
+ unsigned gcPtrCount = compiler->info.compCompHnd->getClassGClayout(classHandle, gcPtrs);
- assert((gcPtrCount == 0) || ((compiler->info.compCompHnd->getClassAttribs(m_classHandle) &
+ assert((gcPtrCount == 0) || ((compiler->info.compCompHnd->getClassAttribs(classHandle) &
(CORINFO_FLG_CONTAINS_GC_PTR | CORINFO_FLG_BYREF_LIKE)) != 0));
// Since class size is unsigned there's no way we could have more than 2^30 slots
// so it should be safe to fit this into a 30 bits bit field.
assert(gcPtrCount < (1 << 30));
- m_gcPtrCount = gcPtrCount;
+ layout->m_gcPtrCount = gcPtrCount;
}
- INDEBUG(m_gcPtrsInitialized = true;)
+ return layout;
+}
+
+//------------------------------------------------------------------------
+// Create: Create a ClassLayout from a ClassLayoutBuilder.
+//
+// Parameters:
+// compiler - The Compiler object
+// builder - Builder representing the layout
+//
+// Return value:
+// New layout representing a custom (JIT internal) class layout.
+//
+ClassLayout* ClassLayout::Create(Compiler* compiler, const ClassLayoutBuilder& builder)
+{
+ ClassLayout* newLayout = new (compiler, CMK_ClassLayout) ClassLayout(builder.m_size);
+ newLayout->m_gcPtrCount = builder.m_gcPtrCount;
+
+#ifdef DEBUG
+ newLayout->m_name = builder.m_name;
+ newLayout->m_shortName = builder.m_shortName;
+#endif
+
+ if (newLayout->GetSlotCount() <= sizeof(newLayout->m_gcPtrsArray))
+ {
+ if (builder.m_gcPtrCount > 0)
+ {
+ memcpy(newLayout->m_gcPtrsArray, builder.m_gcPtrs, newLayout->GetSlotCount());
+ }
+ else
+ {
+ memset(newLayout->m_gcPtrsArray, TYPE_GC_NONE, newLayout->GetSlotCount());
+ }
+ }
+ else if (builder.m_gcPtrCount > 0)
+ {
+ newLayout->m_gcPtrs = builder.m_gcPtrs;
+ }
+ else
+ {
+ newLayout->m_gcPtrs = new (compiler, CMK_ClassLayout) BYTE[newLayout->GetSlotCount()]{};
+ }
+
+ return newLayout;
}
//------------------------------------------------------------------------
@@ -497,9 +600,23 @@ bool ClassLayout::AreCompatible(const ClassLayout* layout1, const ClassLayout* l
CORINFO_CLASS_HANDLE clsHnd1 = layout1->GetClassHandle();
CORINFO_CLASS_HANDLE clsHnd2 = layout2->GetClassHandle();
- if ((clsHnd1 != NO_CLASS_HANDLE) && (clsHnd1 == clsHnd2))
+ if ((clsHnd1 != NO_CLASS_HANDLE) == (clsHnd2 != NO_CLASS_HANDLE))
{
- return true;
+ // Either both are class-based layout or both are custom layouts.
+ // Custom layouts only match each other if they are the same pointer.
+ if (clsHnd1 == NO_CLASS_HANDLE)
+ {
+ return layout1 == layout2;
+ }
+
+ // For class-based layouts they are definitely compatible for the same
+ // handle
+ if (clsHnd1 == clsHnd2)
+ {
+ return true;
+ }
+
+ // But they may still be compatible for different handles.
}
if (layout1->GetSize() != layout2->GetSize())
@@ -543,3 +660,132 @@ bool ClassLayout::AreCompatible(const ClassLayout* layout1, const ClassLayout* l
}
return true;
}
+
+//------------------------------------------------------------------------
+// ClassLayoutbuilder: Construct a new builder for a class layout of the
+// specified size.
+//
+// Arguments:
+// compiler - Compiler instance
+// size - Size of the layout
+//
+ClassLayoutBuilder::ClassLayoutBuilder(Compiler* compiler, unsigned size)
+ : m_compiler(compiler)
+ , m_size(size)
+{
+}
+
+//------------------------------------------------------------------------
+// GetOrCreateGCPtrs: Get or create the array indicating GC pointer types.
+//
+// Returns:
+// The array of CorInfoGCType.
+//
+BYTE* ClassLayoutBuilder::GetOrCreateGCPtrs()
+{
+ assert(m_size % TARGET_POINTER_SIZE == 0);
+
+ if (m_gcPtrs == nullptr)
+ {
+ m_gcPtrs = new (m_compiler, CMK_ClassLayout) BYTE[m_size / TARGET_POINTER_SIZE]{};
+ }
+
+ return m_gcPtrs;
+}
+
+//------------------------------------------------------------------------
+// SetGCPtr: Set a slot to have specified GC pointer type.
+//
+// Arguments:
+// slot - The GC pointer slot. The slot number corresponds to offset slot * TARGET_POINTER_SIZE.
+// type - Type of GC pointer that this slot contains.
+//
+// Remarks:
+// GC pointer information can only be set in layouts of size divisible by
+// TARGET_POINTER_SIZE.
+//
+void ClassLayoutBuilder::SetGCPtr(unsigned slot, CorInfoGCType type)
+{
+ BYTE* ptrs = GetOrCreateGCPtrs();
+
+ assert(slot * TARGET_POINTER_SIZE < m_size);
+
+ if (ptrs[slot] != TYPE_GC_NONE)
+ {
+ m_gcPtrCount--;
+ }
+
+ ptrs[slot] = static_cast(type);
+
+ if (type != TYPE_GC_NONE)
+ {
+ m_gcPtrCount++;
+ }
+}
+
+//------------------------------------------------------------------------
+// SetGCPtrType: Set a slot to have specified type.
+//
+// Arguments:
+// slot - The GC pointer slot. The slot number corresponds to offset slot * TARGET_POINTER_SIZE.
+// type - Type that this slot contains. Must be TYP_REF, TYP_BYREF or TYP_I_IMPL.
+//
+// Remarks:
+// GC pointer information can only be set in layouts of size divisible by
+// TARGET_POINTER_SIZE.
+//
+void ClassLayoutBuilder::SetGCPtrType(unsigned slot, var_types type)
+{
+ switch (type)
+ {
+ case TYP_REF:
+ SetGCPtr(slot, TYPE_GC_REF);
+ break;
+ case TYP_BYREF:
+ SetGCPtr(slot, TYPE_GC_BYREF);
+ break;
+ case TYP_I_IMPL:
+ SetGCPtr(slot, TYPE_GC_NONE);
+ break;
+ default:
+ assert(!"Invalid type passed to ClassLayoutBuilder::SetGCPtrType");
+ break;
+ }
+}
+
+//------------------------------------------------------------------------
+// CopyInfoFrom: Copy GC pointers from another layout.
+//
+// Arguments:
+// offset - Offset in this builder to start copy information into.
+// layout - Layout to get information from.
+//
+void ClassLayoutBuilder::CopyInfoFrom(unsigned offset, ClassLayout* layout)
+{
+ assert(offset + layout->GetSize() <= m_size);
+
+ if (layout->GetGCPtrCount() > 0)
+ {
+ assert(offset % TARGET_POINTER_SIZE == 0);
+ unsigned startSlot = offset / TARGET_POINTER_SIZE;
+ for (unsigned slot = 0; slot < layout->GetSlotCount(); slot++)
+ {
+ SetGCPtr(startSlot + slot, layout->GetGCPtr(slot));
+ }
+ }
+}
+
+#ifdef DEBUG
+//------------------------------------------------------------------------
+// SetName: Set the long and short name of the layout.
+//
+// Arguments:
+// name - The long name
+// shortName - The short name
+//
+void ClassLayoutBuilder::SetName(const char* name, const char* shortName)
+{
+ m_name = name;
+ m_shortName = shortName;
+}
+#endif
diff --git a/src/coreclr/jit/layout.h b/src/coreclr/jit/layout.h
index c2c901d1f33c9a..97122ced8d5476 100644
--- a/src/coreclr/jit/layout.h
+++ b/src/coreclr/jit/layout.h
@@ -6,13 +6,46 @@
#include "jit.h"
+// Builder for class layouts
+//
+class ClassLayoutBuilder
+{
+ friend class ClassLayout;
+ friend class ClassLayoutTable;
+ friend struct CustomLayoutKey;
+
+ Compiler* m_compiler;
+ BYTE* m_gcPtrs = nullptr;
+ unsigned m_size;
+ unsigned m_gcPtrCount = 0;
+#ifdef DEBUG
+ const char* m_name = "UNNAMED";
+ const char* m_shortName = "UNNAMED";
+#endif
+
+ BYTE* GetOrCreateGCPtrs();
+ void SetGCPtr(unsigned slot, CorInfoGCType type);
+public:
+ // Create a class layout builder.
+ //
+ ClassLayoutBuilder(Compiler* compiler, unsigned size);
+
+ void SetGCPtrType(unsigned slot, var_types type);
+ void CopyInfoFrom(unsigned offset, ClassLayout* layout);
+
+#ifdef DEBUG
+ void SetName(const char* name, const char* shortName);
+#endif
+};
+
// Encapsulates layout information about a class (typically a value class but this can also be
// be used for reference classes when they are stack allocated). The class handle is optional,
-// allowing the creation of "block" layout objects having a specific size but lacking any other
-// layout information. The JIT uses such layout objects in cases where a class handle is not
-// available (cpblk/initblk operations) or not necessary (classes that do not contain GC pointers).
+// allowing the creation of custom layout objects having a specific size where the offsets of
+// GC fields can be specified during creation.
class ClassLayout
{
+private:
+
// Class handle or NO_CLASS_HANDLE for "block" layouts.
const CORINFO_CLASS_HANDLE m_classHandle;
@@ -22,7 +55,6 @@ class ClassLayout
const unsigned m_size;
const unsigned m_isValueClass : 1;
- INDEBUG(unsigned m_gcPtrsInitialized : 1;)
// The number of GC pointers in this layout. Since the maximum size is 2^32-1 the count
// can fit in at most 30 bits.
unsigned m_gcPtrCount : 30;
@@ -39,33 +71,33 @@ class ClassLayout
// The normalized type to use in IR for block nodes with this layout.
const var_types m_type;
- // Class name as reported by ICorJitInfo::getClassName
- INDEBUG(const char* m_className;)
+ // Name of the layout
+ INDEBUG(const char* m_name;)
- // Shortened class name as constructed by Compiler::eeGetShortClassName()
- INDEBUG(const char* m_shortClassName;)
+ // Short name of the layout
+ INDEBUG(const char* m_shortName;)
// ClassLayout instances should only be obtained via ClassLayoutTable.
friend class ClassLayoutTable;
+ friend class ClassLayoutBuilder;
+ friend struct CustomLayoutKey;
ClassLayout(unsigned size)
: m_classHandle(NO_CLASS_HANDLE)
, m_size(size)
, m_isValueClass(false)
-#ifdef DEBUG
- , m_gcPtrsInitialized(true)
-#endif
, m_gcPtrCount(0)
, m_gcPtrs(nullptr)
, m_type(TYP_STRUCT)
#ifdef DEBUG
- , m_className("block")
- , m_shortClassName("block")
+ , m_name(size == 0 ? "Empty" : "Custom")
+ , m_shortName(size == 0 ? "Empty" : "Custom")
#endif
{
}
static ClassLayout* Create(Compiler* compiler, CORINFO_CLASS_HANDLE classHandle);
+ static ClassLayout* Create(Compiler* compiler, const ClassLayoutBuilder& builder);
ClassLayout(CORINFO_CLASS_HANDLE classHandle,
bool isValueClass,
@@ -74,43 +106,43 @@ class ClassLayout
: m_classHandle(classHandle)
, m_size(size)
, m_isValueClass(isValueClass)
-#ifdef DEBUG
- , m_gcPtrsInitialized(false)
-#endif
, m_gcPtrCount(0)
, m_gcPtrs(nullptr)
, m_type(type)
#ifdef DEBUG
- , m_className(className)
- , m_shortClassName(shortClassName)
+ , m_name(className)
+ , m_shortName(shortClassName)
#endif
{
assert(size != 0);
}
-
- void InitializeGCPtrs(Compiler* compiler);
-
public:
+
CORINFO_CLASS_HANDLE GetClassHandle() const
{
return m_classHandle;
}
- bool IsBlockLayout() const
+ bool IsCustomLayout() const
{
return m_classHandle == NO_CLASS_HANDLE;
}
+ bool IsBlockLayout() const
+ {
+ return IsCustomLayout() && !HasGCPtr();
+ }
+
#ifdef DEBUG
const char* GetClassName() const
{
- return m_className;
+ return m_name;
}
const char* GetShortClassName() const
{
- return m_shortClassName;
+ return m_shortName;
}
#endif // DEBUG
@@ -134,7 +166,7 @@ class ClassLayout
// GetRegisterType: Determine register type for the layout.
//
// Return Value:
- // TYP_UNDEF if the layout is enregistrable, register type otherwise.
+ // TYP_UNDEF if the layout is not enregistrable, register type otherwise.
//
var_types GetRegisterType() const
{
@@ -173,15 +205,11 @@ class ClassLayout
unsigned GetGCPtrCount() const
{
- assert(m_gcPtrsInitialized);
-
return m_gcPtrCount;
}
bool HasGCPtr() const
{
- assert(m_gcPtrsInitialized);
-
return m_gcPtrCount != 0;
}
@@ -224,15 +252,11 @@ class ClassLayout
private:
const BYTE* GetGCPtrs() const
{
- assert(m_gcPtrsInitialized);
- assert(!IsBlockLayout());
-
return (GetSlotCount() > sizeof(m_gcPtrsArray)) ? m_gcPtrs : m_gcPtrsArray;
}
CorInfoGCType GetGCPtr(unsigned slot) const
{
- assert(m_gcPtrsInitialized);
assert(slot < GetSlotCount());
if (m_gcPtrCount == 0)
diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp
index dc5144b0431659..f9d84a12bc9a28 100644
--- a/src/coreclr/jit/lclvars.cpp
+++ b/src/coreclr/jit/lclvars.cpp
@@ -2497,9 +2497,9 @@ bool Compiler::StructPromotionHelper::CanPromoteStructVar(unsigned lclNum)
return false;
}
- if (varDsc->GetLayout()->IsBlockLayout())
+ if (varDsc->GetLayout()->IsCustomLayout())
{
- JITDUMP(" struct promotion of V%02u is disabled because it has block layout\n", lclNum);
+ JITDUMP(" struct promotion of V%02u is disabled because it has custom layout\n", lclNum);
return false;
}
@@ -2764,8 +2764,7 @@ void Compiler::StructPromotionHelper::PromoteStructVar(unsigned lclNum)
#ifdef DEBUG
if (compiler->verbose)
{
- printf("\nPromoting struct local V%02u (%s):", lclNum,
- compiler->eeGetClassName(varDsc->GetLayout()->GetClassHandle()));
+ printf("\nPromoting struct local V%02u (%s):", lclNum, varDsc->GetLayout()->GetClassName());
}
#endif
@@ -3368,10 +3367,10 @@ void Compiler::lvaSetStruct(unsigned varNum, ClassLayout* layout, bool unsafeVal
assert(ClassLayout::AreCompatible(varDsc->GetLayout(), layout));
// Inlining could replace a canon struct type with an exact one.
varDsc->SetLayout(layout);
- assert(layout->IsBlockLayout() || (layout->GetSize() != 0));
+ assert(layout->IsCustomLayout() || (layout->GetSize() != 0));
}
- if (!layout->IsBlockLayout())
+ if (!layout->IsCustomLayout())
{
#ifndef TARGET_64BIT
bool fDoubleAlignHint = false;
@@ -7643,7 +7642,7 @@ void Compiler::lvaDumpEntry(unsigned lclNum, FrameLayoutState curState, size_t r
else if (varTypeIsStruct(varDsc->TypeGet()))
{
ClassLayout* layout = varDsc->GetLayout();
- if (layout != nullptr && !layout->IsBlockLayout())
+ if (layout != nullptr)
{
printf(" <%s>", layout->GetClassName());
}
@@ -8097,8 +8096,8 @@ Compiler::fgWalkResult Compiler::lvaStressLclFldCB(GenTree** pTree, fgWalkData*
return WALK_CONTINUE;
}
- // Can't have GC ptrs in block layouts.
- if (!varTypeIsArithmetic(lclType))
+ // Structs are not currently supported
+ if (varTypeIsStruct(lclType))
{
varDsc->lvNoLclFldStress = true;
return WALK_CONTINUE;
@@ -8112,6 +8111,13 @@ Compiler::fgWalkResult Compiler::lvaStressLclFldCB(GenTree** pTree, fgWalkData*
return WALK_CONTINUE;
}
+ // Pinned locals would not remain pinned if we did this transformation.
+ if (varDsc->lvPinned)
+ {
+ varDsc->lvNoLclFldStress = true;
+ return WALK_CONTINUE;
+ }
+
// Weed out "small" types like TYP_BYTE as we don't mark the GT_LCL_VAR
// node with the accurate small type. If we bash lvaTable[].lvType,
// then there will be no indication that it was ever a small type.
@@ -8134,7 +8140,7 @@ Compiler::fgWalkResult Compiler::lvaStressLclFldCB(GenTree** pTree, fgWalkData*
else
{
// Do the morphing
- noway_assert((varType == lclType) || ((varType == TYP_STRUCT) && varDsc->GetLayout()->IsBlockLayout()));
+ noway_assert((varType == lclType) || ((varType == TYP_STRUCT) && varDsc->GetLayout()->IsCustomLayout()));
// Calculate padding
unsigned padding = pComp->lvaStressLclFldPadding(lclNum);
@@ -8145,17 +8151,34 @@ Compiler::fgWalkResult Compiler::lvaStressLclFldCB(GenTree** pTree, fgWalkData*
padding = roundUp(padding, genTypeSize(TYP_DOUBLE));
#endif // defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
+ // Also for GC types we need to round up
+ if (varTypeIsGC(varType) || ((varType == TYP_STRUCT) && varDsc->GetLayout()->HasGCPtr()))
+ {
+ padding = roundUp(padding, TARGET_POINTER_SIZE);
+ }
+
if (varType != TYP_STRUCT)
{
- // Change the variable to a block struct
- ClassLayout* layout =
- pComp->typGetBlkLayout(roundUp(padding + pComp->lvaLclSize(lclNum), TARGET_POINTER_SIZE));
- varDsc->lvType = TYP_STRUCT;
+ // Change the variable to a custom layout struct
+ unsigned size = roundUp(padding + pComp->lvaLclSize(lclNum), TARGET_POINTER_SIZE);
+ ClassLayoutBuilder builder(pComp, size);
+#ifdef DEBUG
+ builder.SetName(pComp->printfAlloc("%s_%u_Stress", varTypeName(varType), size),
+ pComp->printfAlloc("%s_%u", varTypeName(varType), size));
+#endif
+
+ if (varTypeIsGC(varType))
+ {
+ builder.SetGCPtrType(padding / TARGET_POINTER_SIZE, varType);
+ }
+
+ ClassLayout* layout = pComp->typGetCustomLayout(builder);
+ varDsc->lvType = TYP_STRUCT;
varDsc->SetLayout(layout);
pComp->lvaSetVarAddrExposed(lclNum DEBUGARG(AddressExposedReason::STRESS_LCL_FLD));
- JITDUMP("Converting V%02u to %u sized block with LCL_FLD at offset (padding %u)\n", lclNum,
- layout->GetSize(), padding);
+ JITDUMP("Converting V%02u of type %s to %u sized block with LCL_FLD at offset (padding %u)\n", lclNum,
+ varTypeName(varType), layout->GetSize(), padding);
}
tree->gtFlags |= GTF_GLOB_REF;
diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp
index c764a7259fba38..0f7397012f2d14 100644
--- a/src/coreclr/jit/lsra.cpp
+++ b/src/coreclr/jit/lsra.cpp
@@ -947,13 +947,16 @@ void LinearScan::setBlockSequence()
bbVisitedSet = BitVecOps::MakeEmpty(traits);
assert((blockSequence == nullptr) && (bbSeqCount == 0));
- FlowGraphDfsTree* const dfsTree = compiler->fgComputeDfs* useProfile */ true>();
+
+ compiler->m_dfsTree = compiler->fgComputeDfs* useProfile */ true>();
+ FlowGraphDfsTree* const dfsTree = compiler->m_dfsTree;
blockSequence = new (compiler, CMK_LSRA) BasicBlock*[compiler->fgBBcount];
if (compiler->opts.OptimizationEnabled() && dfsTree->HasCycle())
{
- // Ensure loop bodies are compact in the visitation order
- FlowGraphNaturalLoops* const loops = FlowGraphNaturalLoops::Find(dfsTree);
+ // Ensure loop bodies are compact in the visitation order.
+ compiler->m_loops = FlowGraphNaturalLoops::Find(dfsTree);
+ FlowGraphNaturalLoops* const loops = compiler->m_loops;
unsigned index = 0;
auto addToSequence = [this, &index](BasicBlock* block) {
@@ -1319,6 +1322,7 @@ PhaseStatus LinearScan::doLinearScan()
{
assert(compiler->fgBBcount > bbSeqCount);
compiler->fgBBs = nullptr;
+ compiler->fgInvalidateDfsTree();
}
return PhaseStatus::MODIFIED_EVERYTHING;
diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp
index 4c0fc233196482..fb362d51b381b9 100644
--- a/src/coreclr/jit/morph.cpp
+++ b/src/coreclr/jit/morph.cpp
@@ -3296,7 +3296,7 @@ void Compiler::fgMakeOutgoingStructArgCopy(GenTreeCall* call, CallArg* arg)
found = ForEachHbvBitSet(*fgAvailableOutgoingArgTemps, [&](indexType lclNum) {
LclVarDsc* varDsc = lvaGetDesc((unsigned)lclNum);
ClassLayout* layout = varDsc->GetLayout();
- if (!layout->IsBlockLayout() && (layout->GetClassHandle() == copyBlkClass))
+ if (!layout->IsCustomLayout() && (layout->GetClassHandle() == copyBlkClass))
{
tmp = (unsigned)lclNum;
JITDUMP("reusing outgoing struct arg V%02u\n", tmp);
diff --git a/src/coreclr/jit/objectalloc.cpp b/src/coreclr/jit/objectalloc.cpp
index 8c84d47cf75536..ec3b37eb15901e 100644
--- a/src/coreclr/jit/objectalloc.cpp
+++ b/src/coreclr/jit/objectalloc.cpp
@@ -1840,7 +1840,7 @@ GenTree* ObjectAllocator::IsGuard(BasicBlock* block, GuardInfo* info)
info->m_local = addr->AsLclVar()->GetLclNum();
bool isNonNull = false;
bool isExact = false;
- info->m_type = (CORINFO_CLASS_HANDLE)op2->AsIntCon()->gtIconVal;
+ info->m_type = (CORINFO_CLASS_HANDLE)op2->AsIntCon()->gtCompileTimeHandle;
JITDUMP("... " FMT_BB " is guard for V%02u\n", block->bbNum, info->m_local);
return tree;
@@ -2347,10 +2347,10 @@ bool ObjectAllocator::CheckCanClone(CloneInfo* info)
// object in the blocks we intend to clone (and beyond). Verify those have the
// expected def-use behavior.
//
- // The goal of all this is to try and ensure that if we rewrite all the T,V,U appeances
+ // The goal of all this is to try and ensure that if we rewrite all the T,V,U appearances
// to new locals in the cloned code we get proper behavior.
//
- // There is one distingushed local V (info.m_local) that holds the result of the
+ // There is one distinguished local V (info.m_local) that holds the result of the
// initial GDV and is the local tested in subsequent GDVs. It must have a single def.
//
// The other locals are either temps T that refer to the allocated object between
@@ -2373,7 +2373,7 @@ bool ObjectAllocator::CheckCanClone(CloneInfo* info)
// Tv's use should be at the def of V.
//
// For the U's: all Ui appearances should be dominated by the def of V; all Ui defs
- // should have another Ui or V as their source. (We should also verfy each Ui is
+ // should have another Ui or V as their source. (We should also verify each Ui is
// single-def and the def dominates all the Ui uses, but this may not work out...?)
//
// Also we do not expect any Ti or Ui use to be a GDV guard. U's typically arise from
@@ -2422,45 +2422,50 @@ bool ObjectAllocator::CheckCanClone(CloneInfo* info)
BitVecTraits traits(comp->compBasicBlockID, comp);
BitVec visitedBlocks(BitVecOps::MakeEmpty(&traits));
toVisit.Push(allocBlock);
+ BitVecOps::AddElemD(&traits, visitedBlocks, allocBlock->bbID);
- // todo -- some kind of runaway size limit
+ // We don't expect to have to search very far
//
+ unsigned searchCount = 0;
+ unsigned const searchLimit = 25;
+
while (toVisit.Height() > 0)
{
- BasicBlock* const visitBlock = toVisit.Pop();
- if (!BitVecOps::TryAddElemD(&traits, visitedBlocks, visitBlock->bbID))
+ BasicBlock* const block = toVisit.Pop();
+
+ if (searchCount > searchLimit)
{
- continue;
+ JITDUMP("Too many blocks between alloc and def block\n");
+ return false;
}
- if (visitBlock != allocBlock)
+ if (block != allocBlock)
{
- visited->push_back(visitBlock);
+ visited->push_back(block);
}
// We expect this stretch of blocks to all be in the same EH region.
//
- if (!BasicBlock::sameEHRegion(allocBlock, visitBlock))
+ if (!BasicBlock::sameEHRegion(allocBlock, block))
{
- JITDUMP("Unexpected: new EH region at " FMT_BB "\n", visitBlock->bbNum);
+ JITDUMP("Unexpected: new EH region at " FMT_BB "\n", block->bbNum);
return false;
}
- if (visitBlock == defBlock)
+ if (block == defBlock)
{
continue;
}
- JITDUMP("walking through " FMT_BB "\n", visitBlock->bbNum);
+ JITDUMP("walking through " FMT_BB "\n", block->bbNum);
- for (BasicBlock* const succ : visitBlock->Succs())
- {
- if (BitVecOps::IsMember(&traits, visitedBlocks, succ->bbID))
+ block->VisitRegularSuccs(comp, [&](BasicBlock* succ) {
+ if (BitVecOps::TryAddElemD(&traits, visitedBlocks, succ->bbID))
{
- continue;
+ toVisit.Push(succ);
}
- toVisit.Push(succ);
- }
+ return BasicBlockVisit::Continue;
+ });
}
JITDUMP("def block " FMT_BB " post-dominates allocation site " FMT_BB "\n", defBlock->bbNum, allocBlock->bbNum);
@@ -2617,14 +2622,18 @@ bool ObjectAllocator::CheckCanClone(CloneInfo* info)
for (EnumeratorVarAppearance* const a : *(ev->m_appearances))
{
- if (!comp->m_domTree->Dominates(defBlock, a->m_block))
+ BasicBlock* const aBlock = a->m_block;
+ if (!comp->m_domTree->Dominates(defBlock, aBlock))
{
JITDUMP("%sV%02u %s in " FMT_BB " not dominated by def " FMT_BB "\n", ev->m_isUseTemp ? "Use temp" : "",
lclNum, a->m_isDef ? "def" : "use", a->m_block->bbNum, defBlock->bbNum);
return false;
}
- toVisit.Push(a->m_block);
+ if (BitVecOps::TryAddElemD(&traits, visitedBlocks, aBlock->bbID))
+ {
+ toVisit.Push(aBlock);
+ }
}
}
@@ -2637,23 +2646,19 @@ bool ObjectAllocator::CheckCanClone(CloneInfo* info)
//
while (toVisit.Height() > 0)
{
- BasicBlock* const visitBlock = toVisit.Pop();
- if (!BitVecOps::TryAddElemD(&traits, visitedBlocks, visitBlock->bbID))
- {
- continue;
- }
- visited->push_back(visitBlock);
+ BasicBlock* const block = toVisit.Pop();
+ visited->push_back(block);
// If we see try region entries here, we will handle them below.
//
- if (comp->bbIsTryBeg(visitBlock))
+ if (comp->bbIsTryBeg(block))
{
- toVisitTryEntry->push_back(visitBlock);
+ toVisitTryEntry->push_back(block);
}
- JITDUMP("walking back through " FMT_BB "\n", visitBlock->bbNum);
+ JITDUMP("walking back through " FMT_BB "\n", block->bbNum);
- for (FlowEdge* predEdge = comp->BlockPredsWithEH(visitBlock); predEdge != nullptr;
+ for (FlowEdge* predEdge = comp->BlockPredsWithEH(block); predEdge != nullptr;
predEdge = predEdge->getNextPredEdge())
{
BasicBlock* const predBlock = predEdge->getSourceBlock();
@@ -2662,11 +2667,10 @@ bool ObjectAllocator::CheckCanClone(CloneInfo* info)
// (consider eh paths?)
//
assert(comp->m_domTree->Dominates(defBlock, predBlock));
- if (BitVecOps::IsMember(&traits, visitedBlocks, predBlock->bbID))
+ if (BitVecOps::TryAddElemD(&traits, visitedBlocks, predBlock->bbID))
{
- continue;
+ toVisit.Push(predBlock);
}
- toVisit.Push(predBlock);
}
}
@@ -2754,8 +2758,6 @@ bool ObjectAllocator::CheckCanClone(CloneInfo* info)
// Save off blocks that we need to clone
//
- // TODO: use postorder nums to keeping the vector and bitvec?
- //
info->m_blocksToClone = visited;
info->m_blocks = visitedBlocks;
info->m_canClone = true;
diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.SingleEntry.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.SingleEntry.targets
index c2627502f9ddd6..059d1754c68263 100644
--- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.SingleEntry.targets
+++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.SingleEntry.targets
@@ -24,6 +24,8 @@
<_hostPackageName Condition="'$(_targetsNonPortableSdkRid)' == 'true'">runtime.$(RuntimeIdentifier).Microsoft.DotNet.ILCompiler
<_targetPackageName>runtime.$(_originalTargetOS)-$(_targetArchitecture).Microsoft.DotNet.ILCompiler
<_targetPackageName Condition="'$(_targetsNonPortableSdkRid)' == 'true'">runtime.$(RuntimeIdentifier).Microsoft.DotNet.ILCompiler
+ <_targetRuntimePackName>Microsoft.NETCore.App.Runtime.NativeAOT.$(_originalTargetOS)-$(_targetArchitecture)
+ <_targetRuntimePackName Condition="'$(_targetsNonPortableSdkRid)' == 'true'">Microsoft.NETCore.App.Runtime.NativeAOT.$(RuntimeIdentifier)
<_targetOS>$(_originalTargetOS)
@@ -64,8 +66,10 @@
@(ResolvedILCompilerPack->'%(PackageDirectory)')
- @(ResolvedTargetILCompilerPack->'%(PackageDirectory)')
@(ResolvedILCompilerPack->'%(PackageDirectory)')
+ @(ResolvedTargetILCompilerPack->'%(PackageDirectory)')
+ true
+ $(PublishAotUsingRuntimePack)
diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets
index 0e633f34e3b24f..656e525ca32eb7 100644
--- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets
+++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets
@@ -68,8 +68,8 @@
Text="Add a PackageReference for '$(_hostPackageName)' to allow cross-compilation for $(_targetArchitecture)" />
-
-
+
+
+
+
+ <_NETCoreAppRuntimePackPath Condition="'$(PublishAotUsingRuntimePack)' == 'true'">%(_NETCoreAppFrameworkReference.RuntimePackPath)/runtimes/$(RuntimeIdentifier)/
+ <_NETCoreAppRuntimePackPath Condition="'$(PublishAotUsingRuntimePack)' != 'true'">$(RuntimePackagePath)/runtimes/$(RuntimeIdentifier)/
+ $(_NETCoreAppRuntimePackPath)\native\
+ $(IlcFrameworkNativePath)
+
+
+
+ $(RuntimePackagePath)\framework\
+ $(RuntimePackagePath)\framework\
+ $(RuntimePackagePath)\sdk\
+
+
$(IlcHostPackagePath)\tools\
- $(RuntimePackagePath)\framework\
- <_NETCoreAppRuntimePackPath>%(_NETCoreAppFrameworkReference.RuntimePackPath)/runtimes/$(RuntimeIdentifier)/
- $(_NETCoreAppRuntimePackPath)\native\
- $(RuntimePackagePath)\framework\
- $(IlcFrameworkNativePath)
- $(RuntimePackagePath)\sdk\
$(RuntimePackagePath)\mibc\
-
+
-
+
diff --git a/src/coreclr/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs
index bab6cd0e8121df..5f05fdeb9f4703 100644
--- a/src/coreclr/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs
@@ -277,22 +277,22 @@ private static bool IsInterfaceImplementedOnType(MetadataType type, MetadataType
private static MethodDesc FindImplFromDeclFromMethodImpls(MetadataType type, MethodDesc decl)
{
+ if (decl.OwningType.IsInterface)
+ return FindInterfaceImplFromDeclFromMethodImpls(type, decl);
+
MethodImplRecord[] foundMethodImpls = type.FindMethodsImplWithMatchingDeclName(decl.Name);
if (foundMethodImpls == null)
return null;
- bool interfaceDecl = decl.OwningType.IsInterface;
-
foreach (MethodImplRecord record in foundMethodImpls)
{
MethodDesc recordDecl = record.Decl;
- if (interfaceDecl != recordDecl.OwningType.IsInterface)
+ if (recordDecl.OwningType.IsInterface)
continue;
- if (!interfaceDecl)
- recordDecl = FindSlotDefiningMethodForVirtualMethod(recordDecl);
+ recordDecl = FindSlotDefiningMethodForVirtualMethod(recordDecl);
if (recordDecl == decl)
{
@@ -303,6 +303,56 @@ private static MethodDesc FindImplFromDeclFromMethodImpls(MetadataType type, Met
return null;
}
+ private static MethodDesc FindInterfaceImplFromDeclFromMethodImpls(MetadataType type, MethodDesc decl)
+ {
+ Debug.Assert(decl.OwningType.IsInterface);
+
+ MethodImplRecord[] foundMethodImpls = type.FindMethodsImplWithMatchingDeclName(decl.Name);
+
+ if (foundMethodImpls == null)
+ return null;
+
+ // We might find more than one result due to generic parameter folding
+ var results = new ArrayBuilder(1);
+ for (int i = 0; i < foundMethodImpls.Length; i++)
+ {
+ MethodDesc recordDecl = foundMethodImpls[i].Decl;
+ if (recordDecl == decl)
+ {
+ results.Add(i);
+ }
+ }
+
+ if (results.Count == 0)
+ return null;
+
+ int resultIndex = results[0];
+
+ // If we found multiple MethodImpls, need to do a tie break using type declaration order
+ if (results.Count > 1)
+ {
+ MetadataType typeDefinition = (MetadataType)type.GetTypeDefinition();
+ DefType[] interfacesOnDefinition = typeDefinition.RuntimeInterfaces;
+ MethodImplRecord[] foundMethodImplsOnDefinition = typeDefinition.FindMethodsImplWithMatchingDeclName(decl.Name);
+ Debug.Assert(foundMethodImplsOnDefinition.Length == foundMethodImpls.Length);
+
+ int bestInterfaceIndex = int.MaxValue;
+
+ for (int i = 0; i < results.Count; i++)
+ {
+ int index = Array.IndexOf(interfacesOnDefinition, foundMethodImplsOnDefinition[results[i]].Decl.OwningType);
+ Debug.Assert(index >= 0);
+ if (index < bestInterfaceIndex)
+ {
+ bestInterfaceIndex = index;
+ resultIndex = i;
+ }
+ }
+ }
+
+ return FindSlotDefiningMethodForVirtualMethod(foundMethodImpls[resultIndex].Body);
+ }
+
private static bool IsInterfaceExplicitlyImplementedOnType(MetadataType type, MetadataType interfaceType)
{
foreach (TypeDesc iface in type.ExplicitlyImplementedInterfaces)
diff --git a/src/coreclr/vm/amd64/AsmHelpers.asm b/src/coreclr/vm/amd64/AsmHelpers.asm
index 95714fd0757321..380893996db617 100644
--- a/src/coreclr/vm/amd64/AsmHelpers.asm
+++ b/src/coreclr/vm/amd64/AsmHelpers.asm
@@ -447,6 +447,25 @@ NESTED_ENTRY OnCallCountThresholdReachedStub, _TEXT
TAILJMP_RAX
NESTED_END OnCallCountThresholdReachedStub, _TEXT
+extern JIT_PatchpointWorkerWorkerWithPolicy:proc
+
+NESTED_ENTRY JIT_Patchpoint, _TEXT
+ PROLOG_WITH_TRANSITION_BLOCK
+
+ lea rcx, [rsp + __PWTB_TransitionBlock] ; TransitionBlock *
+ call JIT_PatchpointWorkerWorkerWithPolicy
+
+ EPILOG_WITH_TRANSITION_BLOCK_RETURN
+ TAILJMP_RAX
+NESTED_END JIT_Patchpoint, _TEXT
+
+; first arg register holds iloffset, which needs to be moved to the second register, and the first register filled with NULL
+LEAF_ENTRY JIT_PartialCompilationPatchpoint, _TEXT
+ mov rdx, rcx
+ xor rcx, rcx
+ jmp JIT_Patchpoint
+LEAF_END JIT_PartialCompilationPatchpoint, _TEXT
+
endif ; FEATURE_TIERED_COMPILATION
LEAF_ENTRY JIT_PollGC, _TEXT
diff --git a/src/coreclr/vm/amd64/unixasmhelpers.S b/src/coreclr/vm/amd64/unixasmhelpers.S
index 7e404a2a09cf6c..10ab11933caee4 100644
--- a/src/coreclr/vm/amd64/unixasmhelpers.S
+++ b/src/coreclr/vm/amd64/unixasmhelpers.S
@@ -195,4 +195,20 @@ NESTED_ENTRY OnCallCountThresholdReachedStub, _TEXT, NoHandler
TAILJMP_RAX
NESTED_END OnCallCountThresholdReachedStub, _TEXT
+NESTED_ENTRY JIT_Patchpoint, _TEXT, NoHandler
+ PROLOG_WITH_TRANSITION_BLOCK
+
+ lea rdi, [rsp + __PWTB_TransitionBlock] // TransitionBlock *
+ call C_FUNC(JIT_PatchpointWorkerWorkerWithPolicy)
+
+ EPILOG_WITH_TRANSITION_BLOCK_RETURN
+NESTED_END JIT_Patchpoint, _TEXT
+
+// first arg register holds iloffset, which needs to be moved to the second register, and the first register filled with NULL
+LEAF_ENTRY JIT_PartialCompilationPatchpoint, _TEXT
+ mov rsi, rdi
+ xor rdi, rdi
+ jmp C_FUNC(JIT_Patchpoint)
+LEAF_END JIT_PartialCompilationPatchpoint, _TEXT
+
#endif // FEATURE_TIERED_COMPILATION
diff --git a/src/coreclr/vm/arm64/asmhelpers.S b/src/coreclr/vm/arm64/asmhelpers.S
index a6801090ad9b25..fdfa833d250f7b 100644
--- a/src/coreclr/vm/arm64/asmhelpers.S
+++ b/src/coreclr/vm/arm64/asmhelpers.S
@@ -747,6 +747,22 @@ NESTED_ENTRY OnCallCountThresholdReachedStub, _TEXT, NoHandler
EPILOG_BRANCH_REG x9
NESTED_END OnCallCountThresholdReachedStub, _TEXT
+NESTED_ENTRY JIT_Patchpoint, _TEXT, NoHandler
+ PROLOG_WITH_TRANSITION_BLOCK
+
+ add x0, sp, #__PWTB_TransitionBlock // TransitionBlock *
+ bl C_FUNC(JIT_PatchpointWorkerWorkerWithPolicy)
+
+ EPILOG_WITH_TRANSITION_BLOCK_RETURN
+NESTED_END JIT_Patchpoint, _TEXT
+
+// first arg register holds iloffset, which needs to be moved to the second register, and the first register filled with NULL
+LEAF_ENTRY JIT_PartialCompilationPatchpoint, _TEXT
+ mov x1, x0
+ mov x0, #0
+ b C_FUNC(JIT_Patchpoint)
+LEAF_END JIT_PartialCompilationPatchpoint, _TEXT
+
#endif // FEATURE_TIERED_COMPILATION
LEAF_ENTRY JIT_ValidateIndirectCall, _TEXT
diff --git a/src/coreclr/vm/arm64/asmhelpers.asm b/src/coreclr/vm/arm64/asmhelpers.asm
index e240919a7395f0..cd7c06500ee315 100644
--- a/src/coreclr/vm/arm64/asmhelpers.asm
+++ b/src/coreclr/vm/arm64/asmhelpers.asm
@@ -1139,6 +1139,24 @@ __HelperNakedFuncName SETS "$helper":CC:"Naked"
EPILOG_BRANCH_REG x9
NESTED_END
+ IMPORT JIT_PatchpointWorkerWorkerWithPolicy
+
+ NESTED_ENTRY JIT_Patchpoint
+ PROLOG_WITH_TRANSITION_BLOCK
+
+ add x0, sp, #__PWTB_TransitionBlock ; TransitionBlock *
+ bl JIT_PatchpointWorkerWorkerWithPolicy
+
+ EPILOG_WITH_TRANSITION_BLOCK_RETURN
+ NESTED_END
+
+ // first arg register holds iloffset, which needs to be moved to the second register, and the first register filled with NULL
+ LEAF_ENTRY JIT_PartialCompilationPatchpoint
+ mov x1, x0
+ mov x0, #0
+ b JIT_Patchpoint
+ LEAF_END
+
#endif ; FEATURE_TIERED_COMPILATION
LEAF_ENTRY JIT_ValidateIndirectCall
diff --git a/src/coreclr/vm/callingconvention.h b/src/coreclr/vm/callingconvention.h
index d15c724a20b5e3..41539478e78723 100644
--- a/src/coreclr/vm/callingconvention.h
+++ b/src/coreclr/vm/callingconvention.h
@@ -2209,4 +2209,28 @@ inline BOOL IsRetBuffPassedAsFirstArg()
#endif
}
+inline TADDR GetFirstArgumentRegisterValuePtr(TransitionBlock * pTransitionBlock)
+{
+ TADDR pArgument = (TADDR)pTransitionBlock + TransitionBlock::GetOffsetOfArgumentRegisters();
+#ifdef TARGET_X86
+ // x86 is special as always
+ pArgument += offsetof(ArgumentRegisters, ECX);
+#endif
+
+ return pArgument;
+}
+
+inline TADDR GetSecondArgumentRegisterValuePtr(TransitionBlock * pTransitionBlock)
+{
+ TADDR pArgument = (TADDR)pTransitionBlock + TransitionBlock::GetOffsetOfArgumentRegisters();
+#ifdef TARGET_X86
+ // x86 is special as always
+ pArgument += offsetof(ArgumentRegisters, EDX);
+#else
+ pArgument += sizeof(TADDR);
+#endif
+
+ return pArgument;
+}
+
#endif // __CALLING_CONVENTION_INCLUDED
diff --git a/src/coreclr/vm/codeman.h b/src/coreclr/vm/codeman.h
index 87b8bfd27f03a6..61bd8b07cdb32c 100644
--- a/src/coreclr/vm/codeman.h
+++ b/src/coreclr/vm/codeman.h
@@ -2477,7 +2477,7 @@ class EECodeInfo
TADDR GetSavedMethodCode();
- TADDR GetStartAddress();
+ TADDR GetStartAddress() const;
BOOL IsValid()
{
@@ -2505,15 +2505,15 @@ class EECodeInfo
}
// This returns a pointer to the start of an instruction; conceptually, a PINSTR.
- TADDR GetCodeAddress()
+ TADDR GetCodeAddress() const
{
LIMITED_METHOD_DAC_CONTRACT;
return PCODEToPINSTR(m_codeAddress);
}
- NativeCodeVersion GetNativeCodeVersion();
+ NativeCodeVersion GetNativeCodeVersion() const;
- MethodDesc * GetMethodDesc()
+ MethodDesc * GetMethodDesc() const
{
LIMITED_METHOD_DAC_CONTRACT;
return m_pMD;
diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp
index 630ebfe42286fd..26a5398e104738 100644
--- a/src/coreclr/vm/jithelpers.cpp
+++ b/src/coreclr/vm/jithelpers.cpp
@@ -2302,7 +2302,7 @@ HCIMPLEND
//
// Returns the address of the jitted code.
// Returns NULL if osr method can't be created.
-static PCODE JitPatchpointWorker(MethodDesc* pMD, EECodeInfo& codeInfo, int ilOffset)
+static PCODE JitPatchpointWorker(MethodDesc* pMD, const EECodeInfo& codeInfo, int ilOffset)
{
STANDARD_VM_CONTRACT;
PCODE osrVariant = (PCODE)NULL;
@@ -2347,55 +2347,20 @@ static PCODE JitPatchpointWorker(MethodDesc* pMD, EECodeInfo& codeInfo, int ilOf
return osrVariant;
}
-// Helper method wrapper to set up a frame so we can invoke methods that might GC
-HCIMPL3(PCODE, JIT_Patchpoint_Framed, MethodDesc* pMD, EECodeInfo& codeInfo, int ilOffset)
+static PCODE PatchpointOptimizationPolicy(TransitionBlock* pTransitionBlock, int* counter, int ilOffset, PerPatchpointInfo * ppInfo, const EECodeInfo& codeInfo, bool *pIsNewMethod)
{
- PCODE result = (PCODE)NULL;
-
- HELPER_METHOD_FRAME_BEGIN_RET_0();
-
- GCX_PREEMP();
- result = JitPatchpointWorker(pMD, codeInfo, ilOffset);
-
- HELPER_METHOD_FRAME_END();
-
- return result;
-}
-HCIMPLEND
-
-// Jit helper invoked at a patchpoint.
-//
-// Checks to see if this is a known patchpoint, if not,
-// an entry is added to the patchpoint table.
-//
-// When the patchpoint has been hit often enough to trigger
-// a transition, create an OSR method.
-//
-// Currently, counter is a pointer into the Tier0 method stack
-// frame so we have exclusive access.
-
-void JIT_Patchpoint(int* counter, int ilOffset)
-{
- // BEGIN_PRESERVE_LAST_ERROR;
- DWORD dwLastError = ::GetLastError();
-
- // This method may not return normally
- STATIC_CONTRACT_GC_NOTRIGGER;
+ STATIC_CONTRACT_NOTHROW;
+ STATIC_CONTRACT_GC_TRIGGERS;
STATIC_CONTRACT_MODE_COOPERATIVE;
- // Patchpoint identity is the helper return address
- PCODE ip = (PCODE)_ReturnAddress();
+ // See if we have an OSR method for this patchpoint.
+ PCODE osrMethodCode = ppInfo->m_osrMethodCode;
+ *pIsNewMethod = false;
+ TADDR ip = codeInfo.GetCodeAddress();
- // Fetch or setup patchpoint info for this patchpoint.
- EECodeInfo codeInfo(ip);
MethodDesc* pMD = codeInfo.GetMethodDesc();
- LoaderAllocator* allocator = pMD->GetLoaderAllocator();
- OnStackReplacementManager* manager = allocator->GetOnStackReplacementManager();
- PerPatchpointInfo * ppInfo = manager->GetPerPatchpointInfo(ip);
- PCODE osrMethodCode = (PCODE)NULL;
- bool isNewMethod = false;
- // In the current prototype, counter is shared by all patchpoints
+ // In the current implementation, counter is shared by all patchpoints
// in a method, so no matter what happens below, we don't want to
// impair those other patchpoints.
//
@@ -2406,7 +2371,7 @@ void JIT_Patchpoint(int* counter, int ilOffset)
//
// So we always reset the counter to the bump value.
//
- // In the prototype, counter is a location in a stack frame,
+ // In the implementation, counter is a location in a stack frame,
// so we can update it without worrying about other threads.
const int counterBump = g_pConfig->OSR_CounterBump();
*counter = counterBump;
@@ -2415,18 +2380,14 @@ void JIT_Patchpoint(int* counter, int ilOffset)
const int ppId = ppInfo->m_patchpointId;
#endif
- // Is this a patchpoint that was previously marked as invalid? If so, just return to the Tier0 method.
if ((ppInfo->m_flags & PerPatchpointInfo::patchpoint_invalid) == PerPatchpointInfo::patchpoint_invalid)
{
- LOG((LF_TIEREDCOMPILATION, LL_INFO1000, "Jit_Patchpoint: invalid patchpoint [%d] (0x%p) in Method=0x%pM (%s::%s) at offset %d\n",
+ LOG((LF_TIEREDCOMPILATION, LL_INFO1000, "PatchpointOptimizationPolicy: invalid patchpoint [%d] (0x%p) in Method=0x%pM (%s::%s) at offset %d\n",
ppId, ip, pMD, pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName, ilOffset));
goto DONE;
}
- // See if we have an OSR method for this patchpoint.
- osrMethodCode = ppInfo->m_osrMethodCode;
-
if (osrMethodCode == (PCODE)NULL)
{
// No OSR method yet, let's see if we should create one.
@@ -2446,7 +2407,7 @@ void JIT_Patchpoint(int* counter, int ilOffset)
if ((ppId < lowId) || (ppId > highId))
{
- LOG((LF_TIEREDCOMPILATION, LL_INFO10, "Jit_Patchpoint: ignoring patchpoint [%d] (0x%p) in Method=0x%pM (%s::%s) at offset %d\n",
+ LOG((LF_TIEREDCOMPILATION, LL_INFO10, "PatchpointOptimizationPolicy: ignoring patchpoint [%d] (0x%p) in Method=0x%pM (%s::%s) at offset %d\n",
ppId, ip, pMD, pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName, ilOffset));
goto DONE;
}
@@ -2483,7 +2444,7 @@ void JIT_Patchpoint(int* counter, int ilOffset)
const int hitCount = InterlockedIncrement(&ppInfo->m_patchpointCount);
const int hitLogLevel = (hitCount == 1) ? LL_INFO10 : LL_INFO1000;
- LOG((LF_TIEREDCOMPILATION, hitLogLevel, "Jit_Patchpoint: patchpoint [%d] (0x%p) hit %d in Method=0x%pM (%s::%s) [il offset %d] (limit %d)\n",
+ LOG((LF_TIEREDCOMPILATION, hitLogLevel, "PatchpointOptimizationPolicy: patchpoint [%d] (0x%p) hit %d in Method=0x%pM (%s::%s) [il offset %d] (limit %d)\n",
ppId, ip, hitCount, pMD, pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName, ilOffset, hitLimit));
// Defer, if we haven't yet reached the limit
@@ -2496,7 +2457,7 @@ void JIT_Patchpoint(int* counter, int ilOffset)
LONG oldFlags = ppInfo->m_flags;
if ((oldFlags & PerPatchpointInfo::patchpoint_triggered) == PerPatchpointInfo::patchpoint_triggered)
{
- LOG((LF_TIEREDCOMPILATION, LL_INFO1000, "Jit_Patchpoint: AWAITING OSR method for patchpoint [%d] (0x%p)\n", ppId, ip));
+ LOG((LF_TIEREDCOMPILATION, LL_INFO1000, "PatchpointOptimizationPolicy: AWAITING OSR method for patchpoint [%d] (0x%p)\n", ppId, ip));
goto DONE;
}
@@ -2505,49 +2466,252 @@ void JIT_Patchpoint(int* counter, int ilOffset)
if (!triggerTransition)
{
- LOG((LF_TIEREDCOMPILATION, LL_INFO1000, "Jit_Patchpoint: (lost race) AWAITING OSR method for patchpoint [%d] (0x%p)\n", ppId, ip));
+ LOG((LF_TIEREDCOMPILATION, LL_INFO1000, "PatchpointOptimizationPolicy: (lost race) AWAITING OSR method for patchpoint [%d] (0x%p)\n", ppId, ip));
goto DONE;
}
- // Time to create the OSR method.
- //
- // We currently do this synchronously. We could instead queue
- // up a request on some worker thread, like we do for
- // rejitting, and return control to the Tier0 method. It may
- // eventually return here, if the patchpoint is hit often
- // enough.
- //
- // There is a chance the async version will create methods
- // that are never used (just like there is a chance that Tier1
- // methods are ever called).
- //
- // In this prototype we want to expose bugs in the jitted code
- // for OSR methods, so we stick with synchronous creation.
- LOG((LF_TIEREDCOMPILATION, LL_INFO10, "Jit_Patchpoint: patchpoint [%d] (0x%p) TRIGGER at count %d\n", ppId, ip, hitCount));
+ MAKE_CURRENT_THREAD_AVAILABLE();
+
+ #ifdef _DEBUG
+ Thread::ObjectRefFlush(CURRENT_THREAD);
+ #endif
+
+ FrameWithCookie frame(pTransitionBlock, 0);
+ DynamicHelperFrame * pFrame = &frame;
+
+ pFrame->Push(CURRENT_THREAD);
+
+ INSTALL_MANAGED_EXCEPTION_DISPATCHER;
+ INSTALL_UNWIND_AND_CONTINUE_HANDLER;
- // Invoke the helper to build the OSR method
- osrMethodCode = HCCALL3(JIT_Patchpoint_Framed, pMD, codeInfo, ilOffset);
+ GCX_PREEMP();
- // If that failed, mark the patchpoint as invalid.
+ osrMethodCode = ppInfo->m_osrMethodCode;
if (osrMethodCode == (PCODE)NULL)
{
- // Unexpected, but not fatal
- STRESS_LOG3(LF_TIEREDCOMPILATION, LL_WARNING, "Jit_Patchpoint: patchpoint (0x%p) OSR method creation failed,"
- " marking patchpoint invalid for Method=0x%pM il offset %d\n", ip, pMD, ilOffset);
+ // Time to create the OSR method.
+ //
+ // We currently do this synchronously. We could instead queue
+ // up a request on some worker thread, like we do for
+ // rejitting, and return control to the Tier0 method. It may
+ // eventually return here, if the patchpoint is hit often
+ // enough.
+ //
+ // There is a chance the async version will create methods
+ // that are never used (just like there is a chance that Tier1
+ // methods are ever called).
+ //
+ // We want to expose bugs in the jitted code
+ // for OSR methods, so we stick with synchronous creation.
+ LOG((LF_TIEREDCOMPILATION, LL_INFO10, "PatchpointOptimizationPolicy: patchpoint [%d] (0x%p) TRIGGER at count %d\n", ppId, ip, hitCount));
- InterlockedOr(&ppInfo->m_flags, (LONG)PerPatchpointInfo::patchpoint_invalid);
- goto DONE;
+ // Invoke the helper to build the OSR method
+ osrMethodCode = JitPatchpointWorker(pMD, codeInfo, ilOffset);
+
+ // If that failed, mark the patchpoint as invalid.
+ if (osrMethodCode == (PCODE)NULL)
+ {
+ // Unexpected, but not fatal
+ STRESS_LOG3(LF_TIEREDCOMPILATION, LL_WARNING, "PatchpointOptimizationPolicy: patchpoint (0x%p) OSR method creation failed,"
+ " marking patchpoint invalid for Method=0x%pM il offset %d\n", ip, pMD, ilOffset);
+
+ InterlockedOr(&ppInfo->m_flags, (LONG)PerPatchpointInfo::patchpoint_invalid);
+ }
+ else
+ {
+ *pIsNewMethod = true;
+ ppInfo->m_osrMethodCode = osrMethodCode;
+ }
}
- // We've successfully created the osr method; make it available.
- _ASSERTE(ppInfo->m_osrMethodCode == (PCODE)NULL);
- ppInfo->m_osrMethodCode = osrMethodCode;
- isNewMethod = true;
+ UNINSTALL_UNWIND_AND_CONTINUE_HANDLER;
+ UNINSTALL_MANAGED_EXCEPTION_DISPATCHER;
+
+ pFrame->Pop(CURRENT_THREAD);
+ }
+ return osrMethodCode;
+
+DONE:
+ return (PCODE)NULL;
+}
+
+static PCODE PatchpointRequiredPolicy(TransitionBlock* pTransitionBlock, int* counter, int ilOffset, PerPatchpointInfo * ppInfo, const EECodeInfo& codeInfo, bool *pIsNewMethod)
+{
+ STATIC_CONTRACT_NOTHROW;
+ STATIC_CONTRACT_GC_TRIGGERS;
+ STATIC_CONTRACT_MODE_COOPERATIVE;
+
+ *pIsNewMethod = false;
+ MethodDesc* pMD = codeInfo.GetMethodDesc();
+ TADDR ip = codeInfo.GetCodeAddress();
+
+#ifdef _DEBUG
+ const int ppId = ppInfo->m_patchpointId;
+#endif
+
+ if ((ppInfo->m_flags & PerPatchpointInfo::patchpoint_invalid) == PerPatchpointInfo::patchpoint_invalid)
+ {
+ LOG((LF_TIEREDCOMPILATION, LL_FATALERROR, "PatchpointRequiredPolicy: invalid patchpoint [%d] (0x%p) in Method=0x%pM (%s::%s) at offset %d\n",
+ ppId, ip, pMD, pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName, ilOffset));
+ EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
+ }
+
+ MAKE_CURRENT_THREAD_AVAILABLE();
+
+#ifdef _DEBUG
+ Thread::ObjectRefFlush(CURRENT_THREAD);
+#endif
+
+ FrameWithCookie frame(pTransitionBlock, 0);
+ DynamicHelperFrame * pFrame = &frame;
+
+ pFrame->Push(CURRENT_THREAD);
+
+ INSTALL_MANAGED_EXCEPTION_DISPATCHER;
+ INSTALL_UNWIND_AND_CONTINUE_HANDLER;
+
+ {
+ GCX_PREEMP();
+
+ DWORD backoffs = 0;
+ while (ppInfo->m_osrMethodCode == (PCODE)NULL)
+ {
+ // Invalid patchpoints are fatal, for partial compilation patchpoints
+ //
+ if ((ppInfo->m_flags & PerPatchpointInfo::patchpoint_invalid) == PerPatchpointInfo::patchpoint_invalid)
+ {
+ LOG((LF_TIEREDCOMPILATION, LL_FATALERROR, "PatchpointRequiredPolicy: invalid patchpoint [%d] (0x%p) in Method=0x%pM (%s::%s) at offset %d\n",
+ ppId, ip, pMD, pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName, ilOffset));
+ EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
+ }
+
+ // Make sure no other thread is trying to create the OSR method.
+ //
+ LONG oldFlags = ppInfo->m_flags;
+ if ((oldFlags & PerPatchpointInfo::patchpoint_triggered) == PerPatchpointInfo::patchpoint_triggered)
+ {
+ LOG((LF_TIEREDCOMPILATION, LL_INFO1000, "PatchpointRequiredPolicy: AWAITING OSR method for patchpoint [%d] (0x%p)\n", ppId, ip));
+ __SwitchToThread(0, backoffs++);
+ continue;
+ }
+
+ // Make sure we win the race to create the OSR method
+ //
+ LONG newFlags = ppInfo->m_flags | PerPatchpointInfo::patchpoint_triggered;
+ BOOL triggerTransition = InterlockedCompareExchange(&ppInfo->m_flags, newFlags, oldFlags) == oldFlags;
+
+ if (!triggerTransition)
+ {
+ LOG((LF_TIEREDCOMPILATION, LL_INFO1000, "PatchpointRequiredPolicy: (lost race) AWAITING OSR method for patchpoint [%d] (0x%p)\n", ppId, ip));
+ __SwitchToThread(0, backoffs++);
+ continue;
+ }
+
+ // Invoke the helper to build the OSR method
+ //
+ // TODO: may not want to optimize this part of the method, if it's truly partial compilation
+ // and can't possibly rejoin into the main flow.
+ //
+ // (but consider: throw path in method with try/catch, OSR method will contain more than just the throw?)
+ //
+ LOG((LF_TIEREDCOMPILATION, LL_INFO10, "PatchpointRequiredPolicy: patchpoint [%d] (0x%p) TRIGGER\n", ppId, ip));
+ PCODE newMethodCode = JitPatchpointWorker(pMD, codeInfo, ilOffset);
+
+ // If that failed, mark the patchpoint as invalid.
+ // This is fatal, for partial compilation patchpoints
+ //
+ if (newMethodCode == (PCODE)NULL)
+ {
+ STRESS_LOG3(LF_TIEREDCOMPILATION, LL_WARNING, "PatchpointRequiredPolicy: patchpoint (0x%p) OSR method creation failed,"
+ " marking patchpoint invalid for Method=0x%pM il offset %d\n", ip, pMD, ilOffset);
+ InterlockedOr(&ppInfo->m_flags, (LONG)PerPatchpointInfo::patchpoint_invalid);
+ EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
+ break;
+ }
+
+ // We've successfully created the osr method; make it available.
+ _ASSERTE(ppInfo->m_osrMethodCode == (PCODE)NULL);
+ ppInfo->m_osrMethodCode = newMethodCode;
+ *pIsNewMethod = true;
+ }
}
+ UNINSTALL_UNWIND_AND_CONTINUE_HANDLER;
+ UNINSTALL_MANAGED_EXCEPTION_DISPATCHER;
+
+ pFrame->Pop(CURRENT_THREAD);
+
// If we get here, we have code to transition to...
+ PCODE osrMethodCode = ppInfo->m_osrMethodCode;
_ASSERTE(osrMethodCode != (PCODE)NULL);
+ return osrMethodCode;
+}
+
+// Jit helper invoked at a patchpoint.
+//
+// Checks to see if this is a known patchpoint, if not,
+// an entry is added to the patchpoint table.
+//
+// When the patchpoint has been hit often enough to trigger
+// a transition, create an OSR method. OR if the first argument
+// is NULL, always create an OSR method and transition to it.
+//
+// Currently, counter(the first argument) is a pointer into the Tier0 method stack
+// frame if it exists so we have exclusive access.
+
+extern "C" void JIT_PatchpointWorkerWorkerWithPolicy(TransitionBlock * pTransitionBlock)
+{
+ // BEGIN_PRESERVE_LAST_ERROR;
+ DWORD dwLastError = ::GetLastError();
+
+ // This method may not return normally
+ STATIC_CONTRACT_NOTHROW;
+ STATIC_CONTRACT_GC_TRIGGERS;
+ STATIC_CONTRACT_MODE_COOPERATIVE;
+
+ PTR_PCODE pReturnAddress = (PTR_PCODE)(((BYTE*)pTransitionBlock) + TransitionBlock::GetOffsetOfReturnAddress());
+ PCODE ip = *pReturnAddress;
+ int* counter = *(int**)GetFirstArgumentRegisterValuePtr(pTransitionBlock);
+ int ilOffset = *(int*)GetSecondArgumentRegisterValuePtr(pTransitionBlock);
+ int hitCount = 1; // This will stay at 1 for forced transition scenarios, but will be updated to the actual hit count for normal patch points
+
+ // Patchpoint identity is the helper return address
+
+ // Fetch or setup patchpoint info for this patchpoint.
+ EECodeInfo codeInfo(ip);
+ MethodDesc* pMD = codeInfo.GetMethodDesc();
+ LoaderAllocator* allocator = pMD->GetLoaderAllocator();
+ OnStackReplacementManager* manager = allocator->GetOnStackReplacementManager();
+ PerPatchpointInfo * ppInfo = manager->GetPerPatchpointInfo(ip);
+
+#ifdef _DEBUG
+ const int ppId = ppInfo->m_patchpointId;
+#endif
+
+ bool isNewMethod = false;
+ PCODE osrMethodCode = (PCODE)NULL;
+
+
+ bool patchpointMustFindOptimizedCode = counter == NULL;
+
+ if (patchpointMustFindOptimizedCode)
+ {
+ osrMethodCode = PatchpointRequiredPolicy(pTransitionBlock, counter, ilOffset, ppInfo, codeInfo, &isNewMethod);
+ }
+ else
+ {
+ osrMethodCode = PatchpointOptimizationPolicy(pTransitionBlock, counter, ilOffset, ppInfo, codeInfo, &isNewMethod);
+ }
+
+ if (osrMethodCode == (PCODE)NULL)
+ {
+ _ASSERTE(!patchpointMustFindOptimizedCode);
+ goto DONE;
+ }
+
+ // If we get here, we have code to transition to...
+
{
Thread *pThread = GetThread();
@@ -2676,243 +2840,10 @@ void JIT_Patchpoint(int* counter, int ilOffset)
::SetLastError(dwLastError);
}
-// Jit helper invoked at a partial compilation patchpoint.
-//
-// Similar to Jit_Patchpoint, but invoked when execution
-// reaches a point in a method where the continuation
-// was never jitted (eg an exceptional path).
-//
-// Unlike regular patchpoints, partial compilation patchpoints
-// must always transition.
-//
-HCIMPL1(VOID, JIT_PartialCompilationPatchpoint, int ilOffset)
-{
- FCALL_CONTRACT;
-
- // BEGIN_PRESERVE_LAST_ERROR;
- DWORD dwLastError = ::GetLastError();
- PerPatchpointInfo* ppInfo = NULL;
- bool isNewMethod = false;
- CONTEXT* pFrameContext = NULL;
-
-#if !defined(TARGET_WINDOWS) || !defined(TARGET_AMD64)
- CONTEXT originalFrameContext;
- originalFrameContext.ContextFlags = CONTEXT_FULL;
- pFrameContext = &originalFrameContext;
-#endif
-
- // Patchpoint identity is the helper return address
- PCODE ip = (PCODE)_ReturnAddress();
-
-#ifdef _DEBUG
- // Friendly ID number
- int ppId = 0;
-#endif
-
- HELPER_METHOD_FRAME_BEGIN_0();
-
- // Fetch or setup patchpoint info for this patchpoint.
- EECodeInfo codeInfo(ip);
- MethodDesc* pMD = codeInfo.GetMethodDesc();
- LoaderAllocator* allocator = pMD->GetLoaderAllocator();
- OnStackReplacementManager* manager = allocator->GetOnStackReplacementManager();
- ppInfo = manager->GetPerPatchpointInfo(ip);
-
-#ifdef _DEBUG
- ppId = ppInfo->m_patchpointId;
-#endif
-
- // See if we have an OSR method for this patchpoint.
- DWORD backoffs = 0;
-
- // Enable GC while we jit or wait for the continuation to be jitted.
- {
- GCX_PREEMP();
-
- while (ppInfo->m_osrMethodCode == (PCODE)NULL)
- {
- // Invalid patchpoints are fatal, for partial compilation patchpoints
- //
- if ((ppInfo->m_flags & PerPatchpointInfo::patchpoint_invalid) == PerPatchpointInfo::patchpoint_invalid)
- {
- LOG((LF_TIEREDCOMPILATION, LL_FATALERROR, "Jit_PartialCompilationPatchpoint: invalid patchpoint [%d] (0x%p) in Method=0x%pM (%s::%s) at offset %d\n",
- ppId, ip, pMD, pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName, ilOffset));
- EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
- }
-
- // Make sure no other thread is trying to create the OSR method.
- //
- LONG oldFlags = ppInfo->m_flags;
- if ((oldFlags & PerPatchpointInfo::patchpoint_triggered) == PerPatchpointInfo::patchpoint_triggered)
- {
- LOG((LF_TIEREDCOMPILATION, LL_INFO1000, "Jit_PartialCompilationPatchpoint: AWAITING OSR method for patchpoint [%d] (0x%p)\n", ppId, ip));
- __SwitchToThread(0, backoffs++);
- continue;
- }
-
- // Make sure we win the race to create the OSR method
- //
- LONG newFlags = ppInfo->m_flags | PerPatchpointInfo::patchpoint_triggered;
- BOOL triggerTransition = InterlockedCompareExchange(&ppInfo->m_flags, newFlags, oldFlags) == oldFlags;
-
- if (!triggerTransition)
- {
- LOG((LF_TIEREDCOMPILATION, LL_INFO1000, "Jit_PartialCompilationPatchpoint: (lost race) AWAITING OSR method for patchpoint [%d] (0x%p)\n", ppId, ip));
- __SwitchToThread(0, backoffs++);
- continue;
- }
-
- // Invoke the helper to build the OSR method
- //
- // TODO: may not want to optimize this part of the method, if it's truly partial compilation
- // and can't possibly rejoin into the main flow.
- //
- // (but consider: throw path in method with try/catch, OSR method will contain more than just the throw?)
- //
- LOG((LF_TIEREDCOMPILATION, LL_INFO10, "Jit_PartialCompilationPatchpoint: patchpoint [%d] (0x%p) TRIGGER\n", ppId, ip));
- PCODE newMethodCode = JitPatchpointWorker(pMD, codeInfo, ilOffset);
-
- // If that failed, mark the patchpoint as invalid.
- // This is fatal, for partial compilation patchpoints
- //
- if (newMethodCode == (PCODE)NULL)
- {
- STRESS_LOG3(LF_TIEREDCOMPILATION, LL_WARNING, "Jit_PartialCompilationPatchpoint: patchpoint (0x%p) OSR method creation failed,"
- " marking patchpoint invalid for Method=0x%pM il offset %d\n", ip, pMD, ilOffset);
- InterlockedOr(&ppInfo->m_flags, (LONG)PerPatchpointInfo::patchpoint_invalid);
- EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
- break;
- }
-
- // We've successfully created the osr method; make it available.
- _ASSERTE(ppInfo->m_osrMethodCode == (PCODE)NULL);
- ppInfo->m_osrMethodCode = newMethodCode;
- isNewMethod = true;
- }
- }
-
- // If we get here, we have code to transition to...
- PCODE osrMethodCode = ppInfo->m_osrMethodCode;
- _ASSERTE(osrMethodCode != (PCODE)NULL);
-
- Thread *pThread = GetThread();
-
-#ifdef FEATURE_HIJACK
- // We can't crawl the stack of a thread that currently has a hijack pending
- // (since the hijack routine won't be recognized by any code manager). So we
- // Undo any hijack, the EE will re-attempt it later.
- pThread->UnhijackThread();
-#endif
-
- // Find context for the original method
-#if defined(TARGET_WINDOWS) && defined(TARGET_AMD64)
- DWORD contextSize = 0;
- ULONG64 xStateCompactionMask = 0;
- DWORD contextFlags = CONTEXT_FULL;
- if (Thread::AreShadowStacksEnabled())
- {
- xStateCompactionMask = XSTATE_MASK_CET_U;
- contextFlags |= CONTEXT_XSTATE;
- }
-
- // The initialize call should fail but return contextSize
- BOOL success = g_pfnInitializeContext2 ?
- g_pfnInitializeContext2(NULL, contextFlags, NULL, &contextSize, xStateCompactionMask) :
- InitializeContext(NULL, contextFlags, NULL, &contextSize);
-
- _ASSERTE(!success && (GetLastError() == ERROR_INSUFFICIENT_BUFFER));
-
- PVOID pBuffer = _alloca(contextSize);
- success = g_pfnInitializeContext2 ?
- g_pfnInitializeContext2(pBuffer, contextFlags, &pFrameContext, &contextSize, xStateCompactionMask) :
- InitializeContext(pBuffer, contextFlags, &pFrameContext, &contextSize);
- _ASSERTE(success);
-#else // TARGET_WINDOWS && TARGET_AMD64
- _ASSERTE(pFrameContext != nullptr);
-#endif // TARGET_WINDOWS && TARGET_AMD64
-
- // Find context for the original method
- RtlCaptureContext(pFrameContext);
-
-#if defined(TARGET_WINDOWS) && defined(TARGET_AMD64)
- if (Thread::AreShadowStacksEnabled())
- {
- pFrameContext->ContextFlags |= CONTEXT_XSTATE;
- SetXStateFeaturesMask(pFrameContext, xStateCompactionMask);
- SetSSP(pFrameContext, _rdsspq());
- }
-#endif // TARGET_WINDOWS && TARGET_AMD64
-
- // Walk back to the original method frame
- Thread::VirtualUnwindToFirstManagedCallFrame(pFrameContext);
-
- // Remember original method FP and SP because new method will inherit them.
- UINT_PTR currentSP = GetSP(pFrameContext);
- UINT_PTR currentFP = GetFP(pFrameContext);
-
- // We expect to be back at the right IP
- if ((UINT_PTR)ip != GetIP(pFrameContext))
- {
- // Should be fatal
- STRESS_LOG2(LF_TIEREDCOMPILATION, LL_INFO10, "Jit_PartialCompilationPatchpoint: patchpoint (0x%p) TRANSITION"
- " unexpected context IP 0x%p\n", ip, GetIP(pFrameContext));
- EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
- }
-
- // Now unwind back to the original method caller frame.
- EECodeInfo callerCodeInfo(GetIP(pFrameContext));
- ULONG_PTR establisherFrame = 0;
- PVOID handlerData = NULL;
- RtlVirtualUnwind(UNW_FLAG_NHANDLER, callerCodeInfo.GetModuleBase(), GetIP(pFrameContext), callerCodeInfo.GetFunctionEntry(),
- pFrameContext, &handlerData, &establisherFrame, NULL);
-
- // Now, set FP and SP back to the values they had just before this helper was called,
- // since the new method must have access to the original method frame.
- //
- // TODO: if we access the patchpointInfo here, we can read out the FP-SP delta from there and
- // use that to adjust the stack, likely saving some stack space.
-
-#if defined(TARGET_AMD64)
- // If calls push the return address, we need to simulate that here, so the OSR
- // method sees the "expected" SP misalgnment on entry.
- _ASSERTE(currentSP % 16 == 0);
- currentSP -= 8;
-
-#if defined(TARGET_WINDOWS)
- DWORD64 ssp = GetSSP(pFrameContext);
- if (ssp != 0)
- {
- SetSSP(pFrameContext, ssp - 8);
- }
-#endif // TARGET_WINDOWS
-
- pFrameContext->Rbp = currentFP;
-#endif // TARGET_AMD64
-
- SetSP(pFrameContext, currentSP);
-
- // Note we can get here w/o triggering, if there is an existing OSR method and
- // we hit the patchpoint.
- const int transitionLogLevel = isNewMethod ? LL_INFO10 : LL_INFO1000;
- LOG((LF_TIEREDCOMPILATION, transitionLogLevel, "Jit_PartialCompilationPatchpoint: patchpoint [%d] (0x%p) TRANSITION to ip 0x%p\n", ppId, ip, osrMethodCode));
-
- // Install new entry point as IP
- SetIP(pFrameContext, osrMethodCode);
-
- // This method doesn't return normally so we have to manually restore things.
- HELPER_METHOD_FRAME_END();
- ENDFORBIDGC();
- ::SetLastError(dwLastError);
-
- // Transition!
- __asan_handle_no_return();
- ClrRestoreNonvolatileContext(pFrameContext);
-}
-HCIMPLEND
#else
-void JIT_Patchpoint(int* counter, int ilOffset)
+HCIMPL2(void, JIT_Patchpoint, int* counter, int ilOffset)
{
// Stub version if OSR feature is disabled
//
@@ -2920,6 +2851,7 @@ void JIT_Patchpoint(int* counter, int ilOffset)
UNREACHABLE();
}
+HCIMPLEND
HCIMPL1(VOID, JIT_PartialCompilationPatchpoint, int ilOffset)
{
diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp
index e284b74639202c..35e06c4041e482 100644
--- a/src/coreclr/vm/jitinterface.cpp
+++ b/src/coreclr/vm/jitinterface.cpp
@@ -14537,7 +14537,7 @@ TADDR EECodeInfo::GetSavedMethodCode()
return GetStartAddress();
}
-TADDR EECodeInfo::GetStartAddress()
+TADDR EECodeInfo::GetStartAddress() const
{
CONTRACTL {
NOTHROW;
@@ -14548,7 +14548,7 @@ TADDR EECodeInfo::GetStartAddress()
return m_pJM->JitTokenToStartAddress(m_methodToken);
}
-NativeCodeVersion EECodeInfo::GetNativeCodeVersion()
+NativeCodeVersion EECodeInfo::GetNativeCodeVersion() const
{
CONTRACTL
{
diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h
index 1d20db72f5f244..7f1835e458a53a 100644
--- a/src/coreclr/vm/jitinterface.h
+++ b/src/coreclr/vm/jitinterface.h
@@ -103,6 +103,10 @@ BOOL LoadDynamicInfoEntry(Module *currentModule,
#endif // TARGET_X86
+// These must be implemented in assembly and generate a TransitionBlock then calling JIT_PatchpointWorkerWithPolicy in order to actually be used.
+EXTERN_C FCDECL2(void, JIT_Patchpoint, int* counter, int ilOffset);
+EXTERN_C FCDECL1(void, JIT_PartialCompilationPatchpoint, int ilOffset);
+
//
// JIT HELPER ALIASING FOR PORTABILITY.
//
diff --git a/src/coreclr/vm/loongarch64/asmhelpers.S b/src/coreclr/vm/loongarch64/asmhelpers.S
index 6be20320f9850c..abf769e7b52e64 100644
--- a/src/coreclr/vm/loongarch64/asmhelpers.S
+++ b/src/coreclr/vm/loongarch64/asmhelpers.S
@@ -1091,6 +1091,22 @@ NESTED_ENTRY OnCallCountThresholdReachedStub, _TEXT, NoHandler
EPILOG_BRANCH_REG $t4
NESTED_END OnCallCountThresholdReachedStub, _TEXT
+NESTED_ENTRY JIT_Patchpoint, _TEXT, NoHandler
+ PROLOG_WITH_TRANSITION_BLOCK
+
+ addi.d $a0, $sp, __PWTB_TransitionBlock // TransitionBlock *
+ bl C_FUNC(JIT_PatchpointWorkerWorkerWithPolicy)
+
+ EPILOG_WITH_TRANSITION_BLOCK_RETURN
+NESTED_END JIT_Patchpoint, _TEXT
+
+// first arg register holds iloffset, which needs to be moved to the second register, and the first register filled with NULL
+LEAF_ENTRY JIT_PartialCompilationPatchpoint, _TEXT
+ move $a1, $a0
+ li.d $a0, 0
+ b C_FUNC(JIT_Patchpoint)
+LEAF_END JIT_PartialCompilationPatchpoint, _TEXT
+
#endif // FEATURE_TIERED_COMPILATION
// ------------------------------------------------------------------
diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp
index a816f93b50c13b..ce0e1049654fe9 100644
--- a/src/coreclr/vm/prestub.cpp
+++ b/src/coreclr/vm/prestub.cpp
@@ -3558,17 +3558,6 @@ static PCODE getHelperForStaticBase(Module * pModule, CORCOMPILE_FIXUP_BLOB_KIND
return pHelper;
}
-TADDR GetFirstArgumentRegisterValuePtr(TransitionBlock * pTransitionBlock)
-{
- TADDR pArgument = (TADDR)pTransitionBlock + TransitionBlock::GetOffsetOfArgumentRegisters();
-#ifdef TARGET_X86
- // x86 is special as always
- pArgument += offsetof(ArgumentRegisters, ECX);
-#endif
-
- return pArgument;
-}
-
void ProcessDynamicDictionaryLookup(TransitionBlock * pTransitionBlock,
Module * pModule,
ModuleBase * pInfoModule,
diff --git a/src/coreclr/vm/riscv64/asmhelpers.S b/src/coreclr/vm/riscv64/asmhelpers.S
index 12b2918ae31e63..75c5f7609c93bf 100644
--- a/src/coreclr/vm/riscv64/asmhelpers.S
+++ b/src/coreclr/vm/riscv64/asmhelpers.S
@@ -958,6 +958,22 @@ NESTED_ENTRY OnCallCountThresholdReachedStub, _TEXT, NoHandler
EPILOG_BRANCH_REG t4
NESTED_END OnCallCountThresholdReachedStub, _TEXT
+NESTED_ENTRY JIT_Patchpoint, _TEXT, NoHandler
+ PROLOG_WITH_TRANSITION_BLOCK
+
+ addi a0, sp, __PWTB_TransitionBlock // TransitionBlock *
+ call C_FUNC(JIT_PatchpointWorkerWorkerWithPolicy)
+
+ EPILOG_WITH_TRANSITION_BLOCK_RETURN
+NESTED_END JIT_Patchpoint, _TEXT
+
+// first arg register holds iloffset, which needs to be moved to the second register, and the first register filled with NULL
+LEAF_ENTRY JIT_PartialCompilationPatchpoint, _TEXT
+ mv a1, a0
+ li a0, 0
+ j C_FUNC(JIT_Patchpoint)
+LEAF_END JIT_PartialCompilationPatchpoint, _TEXT
+
#endif // FEATURE_TIERED_COMPILATION
// ------------------------------------------------------------------
diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.NativeAOT.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.NativeAOT.sfxproj
index 336574ffe10fc7..34587e9fa80607 100644
--- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.NativeAOT.sfxproj
+++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.NativeAOT.sfxproj
@@ -20,8 +20,11 @@
+
+
-To enable the tests marked with [ConditionalFact(nameof(IsLdapConfigurationExist))], you need to setup an LDAP server and provide the needed server info here.
+To enable the tests marked with [ConditionalFact(nameof(IsLdapConfigurationExist))], you need to setup an LDAP server as described below and set the environment variable LDAP_TEST_SERVER_INDEX to the appropriate offset into the XML section found at the end of this file.
To ship, we should test on both an Active Directory LDAP server, and at least one other server, as behaviors are a little different. However for local testing, it is easiest to connect to an OpenDJ LDAP server in a docker container (eg., in WSL2).
-When testing with later of versions of LDAP, the ldapsearch commands below may need to use
-
- -H ldap://localhost:
-
-instead of
-
- -h localhost -p
-
OPENDJ SERVER
=============
@@ -19,7 +11,7 @@ OPENDJ SERVER
test it with this command - it should return some results in WSL2
- ldapsearch -h localhost -p 1389 -D 'cn=admin,dc=example,dc=com' -x -w password
+ ldapsearch -H ldap://localhost:1389 -D 'cn=admin,dc=example,dc=com' -x -w password
this command views the status
@@ -32,16 +24,16 @@ SLAPD OPENLDAP SERVER
and to test and view status
- ldapsearch -h localhost -p 390 -D 'cn=admin,dc=example,dc=com' -x -w password
+ ldapsearch -H ldap://localhost:390 -D 'cn=admin,dc=example,dc=com' -x -w password
docker exec -it slapd01 slapcat
SLAPD OPENLDAP SERVER WITH TLS
==============================
-The osixia/openldap container image automatically creates a TLS lisener with a self-signed certificate. This can be used to test TLS.
+The osixia/openldap container image automatically creates a TLS listener with a self-signed certificate. This can be used to test TLS.
-Start the container, with TLS on port 1636, without client certificate verification:
+Start the container, with TLS on port 1636, but without client certificate verification:
docker run --publish 1389:389 --publish 1636:636 --name ldap --hostname ldap.local --detach --rm --env LDAP_TLS_VERIFY_CLIENT=never --env LDAP_ADMIN_PASSWORD=password osixia/openldap --loglevel debug
@@ -64,6 +56,8 @@ To test and view the status:
ldapsearch -H ldaps://ldap.local:1636 -b dc=example,dc=org -x -D cn=admin,dc=example,dc=org -w password
+use '-d 1' or '-d 2' for debugging.
+
ACTIVE DIRECTORY
================
@@ -73,7 +67,7 @@ When running against Active Directory from a Windows client, you should not see
If you are running your AD server as a VM on the same machine that you are running WSL2, you must execute this command on the host to bridge the two Hyper-V networks so that it is visible from WSL2:
- Get-NetIPInterface | where {$_.InterfaceAlias -eq 'vEthernet (WSL)' -or $_.InterfaceAlias -eq 'vEthernet (Default Switch)'} | Set-NetIPInterface -Forwarding Enabled
+ Get-NetIPInterface | where {$_.InterfaceAlias -eq 'vEthernet (WSL)' -or $_.InterfaceAlias -eq 'vEthernet (Default Switch)'} | Set-NetIPInterface -Forwarding Enabled
The WSL2 VM should now be able to see the AD VM by IP address. To make it visible by host name, it's probably easiest to just add it to /etc/hosts.
@@ -90,7 +84,7 @@ Note:
@@ -113,15 +107,6 @@ Note:
ServerBind,None
False
-
- danmose-ldap.danmose-domain.com
- DC=danmose-domain,DC=com
- 389
- danmose-domain\Administrator
- %TESTPASSWORD%
- ServerBind,None
- True
-
ldap.local
DC=example,DC=org
@@ -132,5 +117,14 @@ Note:
true
False
+
+ danmose-ldap.danmose-domain.com
+ DC=danmose-domain,DC=com
+ 389
+ danmose-domain\Administrator
+ %TESTPASSWORD%
+ ServerBind,None
+ True
+
diff --git a/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs b/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs
index 24f0119fcc29cd..5df454fe3b3bf7 100644
--- a/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs
+++ b/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs
@@ -1302,5 +1302,6 @@ public static partial class ImmutableCollectionsMarshal
{
public static System.Collections.Immutable.ImmutableArray AsImmutableArray(T[]? array) { throw null; }
public static T[]? AsArray(System.Collections.Immutable.ImmutableArray array) { throw null; }
+ public static System.Memory AsMemory(System.Collections.Immutable.ImmutableArray.Builder? builder) { throw null; }
}
}
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs
index e6e36c81339bd8..9f596e8f7578a7 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs
@@ -1095,6 +1095,9 @@ private void RemoveAtRange(ICollection indicesToRemove)
_count -= indicesToRemove.Count;
}
+
+ /// Gets a for the filled portion of the backing array.
+ internal Memory AsMemory() => new(_elements, 0, _count);
}
}
}
diff --git a/src/libraries/System.Collections.Immutable/src/System/Runtime.InteropServices/ImmutableCollectionsMarshal.cs b/src/libraries/System.Collections.Immutable/src/System/Runtime.InteropServices/ImmutableCollectionsMarshal.cs
index 737a3a862a2d47..cb751a4283df5e 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Runtime.InteropServices/ImmutableCollectionsMarshal.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Runtime.InteropServices/ImmutableCollectionsMarshal.cs
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Collections;
using System.Collections.Immutable;
namespace System.Runtime.InteropServices
@@ -54,5 +55,19 @@ public static ImmutableArray AsImmutableArray(T[]? array)
{
return array.array;
}
+
+ ///
+ /// Gets a for the array underlying an input .
+ ///
+ /// The type of elements in the input value.
+ /// The builder.
+ ///
+ /// A for the filled portion of array underlying
+ /// the input .
+ ///
+ public static Memory AsMemory(ImmutableArray.Builder? builder)
+ {
+ return builder?.AsMemory() ?? default;
+ }
}
}
diff --git a/src/libraries/System.Collections.Immutable/tests/ImmutableCollectionsMarshal.cs b/src/libraries/System.Collections.Immutable/tests/ImmutableCollectionsMarshal.cs
index 76ed476ee571ef..6fc463bfd9268c 100644
--- a/src/libraries/System.Collections.Immutable/tests/ImmutableCollectionsMarshal.cs
+++ b/src/libraries/System.Collections.Immutable/tests/ImmutableCollectionsMarshal.cs
@@ -135,6 +135,59 @@ static void Test()
Test();
}
+ [Fact]
+ public void AsMemoryFromNullBuilder()
+ {
+ Memory m = ImmutableCollectionsMarshal.AsMemory(null);
+ Assert.True(m.IsEmpty);
+ Assert.True(MemoryMarshal.TryGetArray(m, out ArraySegment segment));
+ Assert.NotNull(segment.Array);
+ Assert.Equal(0, segment.Array.Length);
+ Assert.Equal(0, segment.Offset);
+ Assert.Equal(0, segment.Count);
+ }
+
+ [Fact]
+ public void AsMemoryFromEmptyBuilder()
+ {
+ Memory m = ImmutableCollectionsMarshal.AsMemory(ImmutableArray.CreateBuilder());
+ Assert.True(m.IsEmpty);
+ Assert.True(MemoryMarshal.TryGetArray(m, out ArraySegment segment));
+ Assert.NotNull(segment.Array);
+ Assert.Equal(0, segment.Offset);
+ Assert.Equal(0, segment.Count);
+ }
+
+ [Fact]
+ public void AsMemoryFromNonEmptyBuilder()
+ {
+ ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(1);
+ builder.Add(42);
+ builder.Add(43);
+ builder.Add(44);
+
+ Memory m1 = ImmutableCollectionsMarshal.AsMemory(builder);
+ Assert.Equal(3, m1.Length);
+
+ Assert.True(MemoryMarshal.TryGetArray(m1, out ArraySegment segment1));
+ Assert.NotNull(segment1.Array);
+ Assert.Equal(0, segment1.Offset);
+ Assert.Equal(3, segment1.Count);
+
+ Span span = m1.Span;
+ Assert.Equal(42, span[0]);
+ Assert.Equal(43, span[1]);
+ Assert.Equal(44, span[2]);
+
+ Memory m2 = ImmutableCollectionsMarshal.AsMemory(builder);
+ Assert.Equal(3, m2.Length);
+ Assert.True(MemoryMarshal.TryGetArray(m2, out ArraySegment segment2));
+
+ Assert.Same(segment1.Array, segment2.Array);
+ Assert.Equal(segment1.Offset, segment2.Offset);
+ Assert.Equal(segment1.Count, segment2.Count);
+ }
+
public class CustomClass
{
public object Foo;
diff --git a/src/libraries/System.DirectoryServices.Protocols/ref/System.DirectoryServices.Protocols.cs b/src/libraries/System.DirectoryServices.Protocols/ref/System.DirectoryServices.Protocols.cs
index cf1b9154d7befe..3559adc9703731 100644
--- a/src/libraries/System.DirectoryServices.Protocols/ref/System.DirectoryServices.Protocols.cs
+++ b/src/libraries/System.DirectoryServices.Protocols/ref/System.DirectoryServices.Protocols.cs
@@ -382,6 +382,8 @@ public partial class LdapSessionOptions
internal LdapSessionOptions() { }
public bool AutoReconnect { get { throw null; } set { } }
public string DomainName { get { throw null; } set { } }
+ [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")]
+ public string TrustedCertificatesDirectory { get { throw null; } set { } }
public string HostName { get { throw null; } set { } }
public bool HostReachable { get { throw null; } }
public System.DirectoryServices.Protocols.LocatorFlags LocatorFlag { get { throw null; } set { } }
@@ -402,6 +404,8 @@ internal LdapSessionOptions() { }
public bool Signing { get { throw null; } set { } }
public System.DirectoryServices.Protocols.SecurityPackageContextConnectionInformation SslInformation { get { throw null; } }
public int SspiFlag { get { throw null; } set { } }
+ [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")]
+ public void StartNewTlsSessionContext() { }
public bool TcpKeepAlive { get { throw null; } set { } }
public System.DirectoryServices.Protocols.VerifyServerCertificateCallback VerifyServerCertificate { get { throw null; } set { } }
public void FastConcurrentBind() { }
diff --git a/src/libraries/System.DirectoryServices.Protocols/src/Resources/Strings.resx b/src/libraries/System.DirectoryServices.Protocols/src/Resources/Strings.resx
index b63f103619fbdb..1f6c9734a7384c 100644
--- a/src/libraries/System.DirectoryServices.Protocols/src/Resources/Strings.resx
+++ b/src/libraries/System.DirectoryServices.Protocols/src/Resources/Strings.resx
@@ -426,4 +426,7 @@
Only ReferralChasingOptions.None and ReferralChasingOptions.All are supported on Linux.
+
+ The directory '{0}' does not exist.
+
\ No newline at end of file
diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.cs
index 1125bfd568d385..facdfc6a484bb9 100644
--- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.cs
+++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.cs
@@ -955,13 +955,13 @@ private unsafe Interop.BOOL ProcessClientCertificate(IntPtr ldapHandle, IntPtr C
private void Connect()
{
- //Ccurrently ldap does not accept more than one certificate.
+ // Currently ldap does not accept more than one certificate.
if (ClientCertificates.Count > 1)
{
throw new InvalidOperationException(SR.InvalidClientCertificates);
}
- // Set the certificate callback routine here if user adds the certifcate to the certificate collection.
+ // Set the certificate callback routine here if user adds the certificate to the certificate collection.
if (ClientCertificates.Count != 0)
{
int certError = LdapPal.SetClientCertOption(_ldapHandle, LdapOption.LDAP_OPT_CLIENT_CERTIFICATE, _clientCertificateRoutine);
diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Linux.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Linux.cs
index e1cfffebb531fc..5059c40499d5c6 100644
--- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Linux.cs
+++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Linux.cs
@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.ComponentModel;
+using System.IO;
+using System.Runtime.Versioning;
namespace System.DirectoryServices.Protocols
{
@@ -11,6 +13,34 @@ public partial class LdapSessionOptions
private bool _secureSocketLayer;
+ ///
+ /// Specifies the path of the directory containing CA certificates in the PEM format.
+ /// Multiple directories may be specified by separating with a semi-colon.
+ ///
+ ///
+ /// The certificate files are looked up by the CA subject name hash value where that hash can be
+ /// obtained by using, for example, openssl x509 -hash -noout -in CA.crt
.
+ /// It is a common practice to have the certificate file be a symbolic link to the actual certificate file
+ /// which can be done by using openssl rehash .
or c_rehash .
in the directory
+ /// containing the certificate files.
+ ///
+ /// The directory not exist.
+ [UnsupportedOSPlatform("windows")]
+ public string TrustedCertificatesDirectory
+ {
+ get => GetStringValueHelper(LdapOption.LDAP_OPT_X_TLS_CACERTDIR, releasePtr: true);
+
+ set
+ {
+ if (!Directory.Exists(value))
+ {
+ throw new DirectoryNotFoundException(SR.Format(SR.DirectoryNotFound, value));
+ }
+
+ SetStringOptionHelper(LdapOption.LDAP_OPT_X_TLS_CACERTDIR, value);
+ }
+ }
+
public bool SecureSocketLayer
{
get
@@ -52,6 +82,16 @@ public ReferralChasingOptions ReferralChasing
}
}
+ ///
+ /// Create a new TLS library context.
+ /// Calling this is necessary after setting TLS-based options, such as TrustedCertificatesDirectory.
+ ///
+ [UnsupportedOSPlatform("windows")]
+ public void StartNewTlsSessionContext()
+ {
+ SetIntValueHelper(LdapOption.LDAP_OPT_X_TLS_NEWCTX, 0);
+ }
+
private bool GetBoolValueHelper(LdapOption option)
{
if (_connection._disposed) throw new ObjectDisposedException(GetType().Name);
@@ -71,5 +111,14 @@ private void SetBoolValueHelper(LdapOption option, bool value)
ErrorChecking.CheckAndSetLdapError(error);
}
+
+ private void SetStringOptionHelper(LdapOption option, string value)
+ {
+ if (_connection._disposed) throw new ObjectDisposedException(GetType().Name);
+
+ int error = LdapPal.SetStringOption(_connection._ldapHandle, option, value);
+
+ ErrorChecking.CheckAndSetLdapError(error);
+ }
}
}
diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Windows.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Windows.cs
index 813005c5ecb72b..cc73449104adf4 100644
--- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Windows.cs
+++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Windows.cs
@@ -10,6 +10,13 @@ public partial class LdapSessionOptions
{
private static void PALCertFreeCRLContext(IntPtr certPtr) => Interop.Ldap.CertFreeCRLContext(certPtr);
+ [UnsupportedOSPlatform("windows")]
+ public string TrustedCertificatesDirectory
+ {
+ get => throw new PlatformNotSupportedException();
+ set => throw new PlatformNotSupportedException();
+ }
+
public bool SecureSocketLayer
{
get
@@ -24,6 +31,9 @@ public bool SecureSocketLayer
}
}
+ [UnsupportedOSPlatform("windows")]
+ public void StartNewTlsSessionContext() => throw new PlatformNotSupportedException();
+
public int ProtocolVersion
{
get => GetIntValueHelper(LdapOption.LDAP_OPT_VERSION);
diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesProtocolsTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesProtocolsTests.cs
index 64c8487c7b481e..4403cb8a702483 100644
--- a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesProtocolsTests.cs
+++ b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesProtocolsTests.cs
@@ -2,12 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
-using System.Diagnostics;
using System.DirectoryServices.Tests;
using System.Globalization;
+using System.IO;
using System.Net;
-using System.Text;
-using System.Threading;
using Xunit;
namespace System.DirectoryServices.Protocols.Tests
@@ -16,6 +14,7 @@ public partial class DirectoryServicesProtocolsTests
{
internal static bool LdapConfigurationExists => LdapConfiguration.Configuration != null;
internal static bool IsActiveDirectoryServer => LdapConfigurationExists && LdapConfiguration.Configuration.IsActiveDirectoryServer;
+ internal static bool UseTls => LdapConfigurationExists && LdapConfiguration.Configuration.UseTls;
internal static bool IsServerSideSortSupported => LdapConfigurationExists && LdapConfiguration.Configuration.SupportsServerSideSort;
@@ -706,6 +705,64 @@ public void TestMultipleServerBind()
connection.Timeout = new TimeSpan(0, 3, 0);
}
+#if NET
+ [ConditionalFact(nameof(UseTls))]
+ [PlatformSpecific(TestPlatforms.Linux)]
+ public void StartNewTlsSessionContext()
+ {
+ using (var connection = GetConnection(bind: false))
+ {
+ // We use "." as the directory since it must be a valid directory for StartNewTlsSessionContext() + Bind() to be successful even
+ // though there are no client certificates in ".".
+ connection.SessionOptions.TrustedCertificatesDirectory = ".";
+
+ // For a real-world scenario, we would call 'StartTransportLayerSecurity(null)' here which would do the TLS handshake including
+ // providing the client certificate to the server and validating the server certificate. However, this requires additional
+ // setup that we don't have including trusting the server certificate and by specifying "demand" in the setup of the server
+ // via 'LDAP_TLS_VERIFY_CLIENT=demand' to force the TLS handshake to occur.
+
+ connection.SessionOptions.StartNewTlsSessionContext();
+ connection.Bind();
+
+ SearchRequest searchRequest = new (LdapConfiguration.Configuration.SearchDn, "(objectClass=*)", SearchScope.Subtree);
+ _ = (SearchResponse)connection.SendRequest(searchRequest);
+ }
+ }
+
+ [ConditionalFact(nameof(UseTls))]
+ [PlatformSpecific(TestPlatforms.Linux)]
+ public void StartNewTlsSessionContext_ThrowsLdapException()
+ {
+ using (var connection = GetConnection(bind: false))
+ {
+ // Create a new session context without setting TrustedCertificatesDirectory.
+ connection.SessionOptions.StartNewTlsSessionContext();
+ Assert.Throws(() => connection.Bind());
+ }
+ }
+
+ [ConditionalFact(nameof(LdapConfigurationExists))]
+ [PlatformSpecific(TestPlatforms.Linux)]
+ public void TrustedCertificatesDirectory_ThrowsDirectoryNotFoundException()
+ {
+ using (var connection = GetConnection(bind: false))
+ {
+ Assert.Throws(() => connection.SessionOptions.TrustedCertificatesDirectory = "nonexistent");
+ }
+ }
+
+ [ConditionalFact(nameof(LdapConfigurationExists))]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void StartNewTlsSessionContext_ThrowsPlatformNotSupportedException()
+ {
+ using (var connection = new LdapConnection("server"))
+ {
+ LdapSessionOptions options = connection.SessionOptions;
+ Assert.Throws(() => options.StartNewTlsSessionContext());
+ }
+ }
+#endif
+
private void DeleteAttribute(LdapConnection connection, string entryDn, string attributeName)
{
string dn = entryDn + "," + LdapConfiguration.Configuration.SearchDn;
@@ -786,24 +843,24 @@ private SearchResultEntry SearchUser(LdapConnection connection, string rootDn, s
return null;
}
- private LdapConnection GetConnection(string server)
+ private static LdapConnection GetConnection(string server)
{
LdapDirectoryIdentifier directoryIdentifier = new LdapDirectoryIdentifier(server, fullyQualifiedDnsHostName: true, connectionless: false);
return GetConnection(directoryIdentifier);
}
- private LdapConnection GetConnection()
+ private static LdapConnection GetConnection(bool bind = true)
{
LdapDirectoryIdentifier directoryIdentifier = string.IsNullOrEmpty(LdapConfiguration.Configuration.Port) ?
new LdapDirectoryIdentifier(LdapConfiguration.Configuration.ServerName, fullyQualifiedDnsHostName: true, connectionless: false) :
new LdapDirectoryIdentifier(LdapConfiguration.Configuration.ServerName,
int.Parse(LdapConfiguration.Configuration.Port, NumberStyles.None, CultureInfo.InvariantCulture),
fullyQualifiedDnsHostName: true, connectionless: false);
- return GetConnection(directoryIdentifier);
+ return GetConnection(directoryIdentifier, bind);
}
- private static LdapConnection GetConnection(LdapDirectoryIdentifier directoryIdentifier)
+ private static LdapConnection GetConnection(LdapDirectoryIdentifier directoryIdentifier, bool bind = true)
{
NetworkCredential credential = new NetworkCredential(LdapConfiguration.Configuration.UserName, LdapConfiguration.Configuration.Password);
@@ -816,7 +873,11 @@ private static LdapConnection GetConnection(LdapDirectoryIdentifier directoryIde
// to LDAP v2, which we do not support, and will return LDAP_PROTOCOL_ERROR
connection.SessionOptions.ProtocolVersion = 3;
connection.SessionOptions.SecureSocketLayer = LdapConfiguration.Configuration.UseTls;
- connection.Bind();
+
+ if (bind)
+ {
+ connection.Bind();
+ }
connection.Timeout = new TimeSpan(0, 3, 0);
return connection;
diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesTestHelpers.cs b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesTestHelpers.cs
index 4a11570d810344..66838588a282a7 100644
--- a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesTestHelpers.cs
+++ b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesTestHelpers.cs
@@ -29,14 +29,18 @@ public static bool IsLibLdapInstalled
}
else
{
- _isLibLdapInstalled = NativeLibrary.TryLoad("libldap-2.4.so.2", out _);
+ _isLibLdapInstalled =
+ NativeLibrary.TryLoad("libldap.so.2", out _) ||
+ NativeLibrary.TryLoad("libldap-2.6.so.0", out _) ||
+ NativeLibrary.TryLoad("libldap-2.5.so.0", out _) ||
+ NativeLibrary.TryLoad("libldap-2.4.so.2", out _);
}
}
- return _isLibLdapInstalled.Value;
#else
_isLibLdapInstalled = true; // In .NET Framework ldap is always installed.
- return _isLibLdapInstalled.Value;
#endif
+
+ return _isLibLdapInstalled.Value;
}
}
}
diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/LdapSessionOptionsTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/LdapSessionOptionsTests.cs
index 5f6a737834ac23..2a8ab23a16d421 100644
--- a/src/libraries/System.DirectoryServices.Protocols/tests/LdapSessionOptionsTests.cs
+++ b/src/libraries/System.DirectoryServices.Protocols/tests/LdapSessionOptionsTests.cs
@@ -7,6 +7,8 @@
namespace System.DirectoryServices.Protocols.Tests
{
+ // To enable these tests locally for Mono, comment out this line in DirectoryServicesTestHelpers.cs:
+ // [assembly: ActiveIssue("https://github.com/dotnet/runtime/issues/35912", TestRuntimes.Mono)]
[ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))]
public class LdapSessionOptionsTests
{
@@ -27,6 +29,7 @@ public void ReferralChasing_Set_GetReturnsExpected_On_Windows(ReferralChasingOpt
}
[Theory]
+ [ActiveIssue("https://github.com/dotnet/runtime/issues/112146")]
[PlatformSpecific(TestPlatforms.Linux)]
[InlineData(ReferralChasingOptions.None)]
[InlineData(ReferralChasingOptions.All)]
@@ -756,5 +759,32 @@ public void StopTransportLayerSecurity_Disposed_ThrowsObjectDisposedException()
Assert.Throws(() => connection.SessionOptions.StopTransportLayerSecurity());
}
+
+#if NET
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Linux)]
+ public void CertificateDirectoryProperty()
+ {
+ using (var connection = new LdapConnection("server"))
+ {
+ LdapSessionOptions options = connection.SessionOptions;
+ Assert.Null(options.TrustedCertificatesDirectory);
+
+ options.TrustedCertificatesDirectory = ".";
+ Assert.Equal(".", options.TrustedCertificatesDirectory);
+ }
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void CertificateDirectoryProperty_ThrowsPlatformNotSupportedException()
+ {
+ using (var connection = new LdapConnection("server"))
+ {
+ LdapSessionOptions options = connection.SessionOptions;
+ Assert.Throws(() => options.TrustedCertificatesDirectory = "CertificateDirectory");
+ }
+ }
+#endif
}
}
diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArrayRecord.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArrayRecord.cs
index c18208668225f8..16fccd99cc1c5f 100644
--- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArrayRecord.cs
+++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArrayRecord.cs
@@ -64,6 +64,11 @@ internal bool IsJagged
///
/// An array filled with the data provided in the serialized records.
/// does not match the data from the payload.
+ ///
+ /// Check the total length of the array by using property before calling this method,
+ /// as an attacker could have sent you a small payload that will require to allocate a very large array
+ /// and potentially cause and Denial of Service.
+ ///
[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
public Array GetArray(Type expectedArrayType, bool allowNulls = true)
{
diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/NrbfDecoder.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/NrbfDecoder.cs
index 76089c07ee0ce0..192fe80c6f5681 100644
--- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/NrbfDecoder.cs
+++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/NrbfDecoder.cs
@@ -16,6 +16,10 @@ namespace System.Formats.Nrbf;
///
/// Provides stateless methods for decoding .NET Remoting Binary Format (NRBF) encoded data.
///
+///
+/// NrbfDecoder is an implementation of an NRBF reader, but its behaviors don't strictly follow BinaryFormatter's implementation.
+/// Thus the output of NrbfDecoder shouldn't be used to determine whether a call to BinaryFormatter would be safe.
+///
public static class NrbfDecoder
{
private static UTF8Encoding ThrowOnInvalidUtf8Encoding { get; } = new(false, throwOnInvalidBytes: true);
diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SZArrayRecord.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SZArrayRecord.cs
index 0eef853a1e18a8..74359693604651 100644
--- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SZArrayRecord.cs
+++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SZArrayRecord.cs
@@ -34,6 +34,11 @@ private protected SZArrayRecord(ArrayInfo arrayInfo) : base(arrayInfo)
/// otherwise, .
///
/// An array filled with the data provided in the serialized records.
+ ///
+ /// Check the total length of the array by using property before calling this method,
+ /// as an attacker could have sent you a small payload that will require to allocate a very large array
+ /// and potentially cause and Denial of Service.
+ ///
public abstract T?[] GetArray(bool allowNulls = true);
#pragma warning disable IL3051 // RequiresDynamicCode is not required in this particualar case
diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecord.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecord.cs
index 43c51d2f864310..fa7d2eda86ca60 100644
--- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecord.cs
+++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecord.cs
@@ -39,6 +39,10 @@ internal SerializationRecord() // others can't derive from this type
/// Gets the name of the serialized type.
///
/// The name of the serialized type.
+ ///
+ /// Since the provided type name may originate from untrusted input,
+ /// it should not be utilized for type loading, as it could potentially load a malicious type.
+ ///
public abstract TypeName TypeName { get; }
///
diff --git a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecordId.cs b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecordId.cs
index a8318cb72d11de..fac6966f6abd49 100644
--- a/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecordId.cs
+++ b/src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/SerializationRecordId.cs
@@ -16,6 +16,9 @@ namespace System.Formats.Nrbf;
///
/// The ID of .
///
+///
+/// It can be used the detect cycles in decoded records.
+///
[DebuggerDisplay("{_id}")]
public readonly struct SerializationRecordId : IEquatable
{
diff --git a/src/libraries/System.Linq/src/System/Linq/Select.cs b/src/libraries/System.Linq/src/System/Linq/Select.cs
index 37a41c450f873c..ac27c8dda22eeb 100644
--- a/src/libraries/System.Linq/src/System/Linq/Select.cs
+++ b/src/libraries/System.Linq/src/System/Linq/Select.cs
@@ -25,7 +25,19 @@ public static IEnumerable Select(
if (source is Iterator iterator)
{
- return iterator.Select(selector);
+ // With native AOT, calling into the `Select` generic virtual method results in NxM
+ // expansion of native code. If the option is enabled, we don't call the generic virtual
+ // for value types. We don't do the same for reference types because reference type
+ // expansion can happen lazily at runtime and the AOT compiler does postpone it (we
+ // don't need more code, just more data structures describing the new types).
+ if (IsSizeOptimized && typeof(TResult).IsValueType)
+ {
+ return new IEnumerableSelectIterator(iterator, selector);
+ }
+ else
+ {
+ return iterator.Select(selector);
+ }
}
if (source is IList ilist)
diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
index f9ca22d194bc5f..0c11aacc65896e 100644
--- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
+++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
@@ -2789,4 +2789,4 @@
-
+
\ No newline at end of file
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.sln b/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.sln
index 9be1cf583e2740..322f5bf805e6b1 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.sln
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.sln
@@ -1,4 +1,8 @@
-Microsoft Visual Studio Solution File, Format Version 12.00
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.12.35229.201
+MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib", "..\..\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj", "{0F7BA062-C34C-41A8-840F-F0B074B18686}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}"
@@ -73,16 +77,21 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{19EA33B4-0E8
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{1A04C5D7-1DE9-47C3-BCC1-147678B9085F}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "tools\gen", "{F81BA54D-38C5-4493-BB5C-344825706D3A}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{F81BA54D-38C5-4493-BB5C-344825706D3A}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "tools\src", "{F0448246-E8A1-49FD-878C-7A6B8486A66B}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F0448246-E8A1-49FD-878C-7A6B8486A66B}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "tools\ref", "{9BB52E31-4890-4F4B-8B2B-6282EF13B8D2}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{9BB52E31-4890-4F4B-8B2B-6282EF13B8D2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{7392B838-42AF-4F54-AD02-366397DAF640}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Checked|Any CPU = Checked|Any CPU
+ Checked|arm = Checked|arm
+ Checked|arm64 = Checked|arm64
+ Checked|x64 = Checked|x64
+ Checked|x86 = Checked|x86
Debug|Any CPU = Debug|Any CPU
Debug|arm = Debug|arm
Debug|arm64 = Debug|arm64
@@ -93,13 +102,18 @@ Global
Release|arm64 = Release|arm64
Release|x64 = Release|x64
Release|x86 = Release|x86
- Checked|Any CPU = Checked|Any CPU
- Checked|arm = Checked|arm
- Checked|arm64 = Checked|arm64
- Checked|x64 = Checked|x64
- Checked|x86 = Checked|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|Any CPU.ActiveCfg = Checked|x64
+ {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|Any CPU.Build.0 = Checked|x64
+ {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|arm.ActiveCfg = Checked|arm
+ {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|arm.Build.0 = Checked|arm
+ {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|arm64.ActiveCfg = Checked|arm64
+ {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|arm64.Build.0 = Checked|arm64
+ {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|x64.ActiveCfg = Checked|x64
+ {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|x64.Build.0 = Checked|x64
+ {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|x86.ActiveCfg = Checked|x86
+ {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|x86.Build.0 = Checked|x86
{0F7BA062-C34C-41A8-840F-F0B074B18686}.Debug|Any CPU.ActiveCfg = Debug|x64
{0F7BA062-C34C-41A8-840F-F0B074B18686}.Debug|Any CPU.Build.0 = Debug|x64
{0F7BA062-C34C-41A8-840F-F0B074B18686}.Debug|arm.ActiveCfg = Debug|arm
@@ -120,16 +134,11 @@ Global
{0F7BA062-C34C-41A8-840F-F0B074B18686}.Release|x64.Build.0 = Release|x64
{0F7BA062-C34C-41A8-840F-F0B074B18686}.Release|x86.ActiveCfg = Release|x86
{0F7BA062-C34C-41A8-840F-F0B074B18686}.Release|x86.Build.0 = Release|x86
- {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|Any CPU.ActiveCfg = Checked|x64
- {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|Any CPU.Build.0 = Checked|x64
- {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|arm.ActiveCfg = Checked|arm
- {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|arm.Build.0 = Checked|arm
- {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|arm64.ActiveCfg = Checked|arm64
- {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|arm64.Build.0 = Checked|arm64
- {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|x64.ActiveCfg = Checked|x64
- {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|x64.Build.0 = Checked|x64
- {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|x86.ActiveCfg = Checked|x86
- {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|x86.Build.0 = Checked|x86
+ {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|x86.ActiveCfg = Debug|Any CPU
{ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -146,11 +155,11 @@ Global
{ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Release|x64.Build.0 = Release|Any CPU
{ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Release|x86.ActiveCfg = Release|Any CPU
{ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Release|x86.Build.0 = Release|Any CPU
- {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|arm.ActiveCfg = Debug|Any CPU
- {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|x64.ActiveCfg = Debug|Any CPU
- {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|x86.ActiveCfg = Debug|Any CPU
{FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -167,11 +176,11 @@ Global
{FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Release|x64.Build.0 = Release|Any CPU
{FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Release|x86.ActiveCfg = Release|Any CPU
{FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Release|x86.Build.0 = Release|Any CPU
- {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|arm.ActiveCfg = Debug|Any CPU
- {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|x64.ActiveCfg = Debug|Any CPU
- {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|x86.ActiveCfg = Debug|Any CPU
{8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -188,11 +197,11 @@ Global
{8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Release|x64.Build.0 = Release|Any CPU
{8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Release|x86.ActiveCfg = Release|Any CPU
{8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Release|x86.Build.0 = Release|Any CPU
- {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|arm.ActiveCfg = Debug|Any CPU
- {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|x64.ActiveCfg = Debug|Any CPU
- {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|x86.ActiveCfg = Debug|Any CPU
{B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -209,11 +218,11 @@ Global
{B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Release|x64.Build.0 = Release|Any CPU
{B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Release|x86.ActiveCfg = Release|Any CPU
{B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Release|x86.Build.0 = Release|Any CPU
- {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|arm.ActiveCfg = Debug|Any CPU
- {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|x64.ActiveCfg = Debug|Any CPU
- {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|x86.ActiveCfg = Debug|Any CPU
{E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -230,11 +239,11 @@ Global
{E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Release|x64.Build.0 = Release|Any CPU
{E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Release|x86.ActiveCfg = Release|Any CPU
{E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Release|x86.Build.0 = Release|Any CPU
- {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|arm.ActiveCfg = Debug|Any CPU
- {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|x64.ActiveCfg = Debug|Any CPU
- {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|x86.ActiveCfg = Debug|Any CPU
{C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -251,11 +260,11 @@ Global
{C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Release|x64.Build.0 = Release|Any CPU
{C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Release|x86.ActiveCfg = Release|Any CPU
{C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Release|x86.Build.0 = Release|Any CPU
- {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|arm.ActiveCfg = Debug|Any CPU
- {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|x64.ActiveCfg = Debug|Any CPU
- {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|x86.ActiveCfg = Debug|Any CPU
{8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -272,11 +281,11 @@ Global
{8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Release|x64.Build.0 = Release|Any CPU
{8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Release|x86.ActiveCfg = Release|Any CPU
{8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Release|x86.Build.0 = Release|Any CPU
- {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|arm.ActiveCfg = Debug|Any CPU
- {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|x64.ActiveCfg = Debug|Any CPU
- {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|x86.ActiveCfg = Debug|Any CPU
{D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -293,11 +302,11 @@ Global
{D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Release|x64.Build.0 = Release|Any CPU
{D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Release|x86.ActiveCfg = Release|Any CPU
{D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Release|x86.Build.0 = Release|Any CPU
- {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|arm.ActiveCfg = Debug|Any CPU
- {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|x64.ActiveCfg = Debug|Any CPU
- {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|x86.ActiveCfg = Debug|Any CPU
{74143A5F-6987-4AB5-B786-DE358F01241B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{74143A5F-6987-4AB5-B786-DE358F01241B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{74143A5F-6987-4AB5-B786-DE358F01241B}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -314,11 +323,11 @@ Global
{74143A5F-6987-4AB5-B786-DE358F01241B}.Release|x64.Build.0 = Release|Any CPU
{74143A5F-6987-4AB5-B786-DE358F01241B}.Release|x86.ActiveCfg = Release|Any CPU
{74143A5F-6987-4AB5-B786-DE358F01241B}.Release|x86.Build.0 = Release|Any CPU
- {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|arm.ActiveCfg = Debug|Any CPU
- {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|x64.ActiveCfg = Debug|Any CPU
- {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|x86.ActiveCfg = Debug|Any CPU
{CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -335,11 +344,11 @@ Global
{CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Release|x64.Build.0 = Release|Any CPU
{CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Release|x86.ActiveCfg = Release|Any CPU
{CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Release|x86.Build.0 = Release|Any CPU
- {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|arm.ActiveCfg = Debug|Any CPU
- {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|x64.ActiveCfg = Debug|Any CPU
- {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|x86.ActiveCfg = Debug|Any CPU
{28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -356,11 +365,11 @@ Global
{28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Release|x64.Build.0 = Release|Any CPU
{28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Release|x86.ActiveCfg = Release|Any CPU
{28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Release|x86.Build.0 = Release|Any CPU
- {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|arm.ActiveCfg = Debug|Any CPU
- {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|x64.ActiveCfg = Debug|Any CPU
- {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|x86.ActiveCfg = Debug|Any CPU
{71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Debug|Any CPU.Build.0 = Debug|Any CPU
{71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -377,11 +386,11 @@ Global
{71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Release|x64.Build.0 = Release|Any CPU
{71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Release|x86.ActiveCfg = Release|Any CPU
{71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Release|x86.Build.0 = Release|Any CPU
- {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|arm.ActiveCfg = Debug|Any CPU
- {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|x64.ActiveCfg = Debug|Any CPU
- {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {E6A30001-84E3-4C7A-9B56-B9DEA71B3CF9}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {E6A30001-84E3-4C7A-9B56-B9DEA71B3CF9}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {E6A30001-84E3-4C7A-9B56-B9DEA71B3CF9}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {E6A30001-84E3-4C7A-9B56-B9DEA71B3CF9}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {E6A30001-84E3-4C7A-9B56-B9DEA71B3CF9}.Checked|x86.ActiveCfg = Debug|Any CPU
{E6A30001-84E3-4C7A-9B56-B9DEA71B3CF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E6A30001-84E3-4C7A-9B56-B9DEA71B3CF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E6A30001-84E3-4C7A-9B56-B9DEA71B3CF9}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -398,11 +407,11 @@ Global
{E6A30001-84E3-4C7A-9B56-B9DEA71B3CF9}.Release|x64.Build.0 = Release|Any CPU
{E6A30001-84E3-4C7A-9B56-B9DEA71B3CF9}.Release|x86.ActiveCfg = Release|Any CPU
{E6A30001-84E3-4C7A-9B56-B9DEA71B3CF9}.Release|x86.Build.0 = Release|Any CPU
- {E6A30001-84E3-4C7A-9B56-B9DEA71B3CF9}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {E6A30001-84E3-4C7A-9B56-B9DEA71B3CF9}.Checked|arm.ActiveCfg = Debug|Any CPU
- {E6A30001-84E3-4C7A-9B56-B9DEA71B3CF9}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {E6A30001-84E3-4C7A-9B56-B9DEA71B3CF9}.Checked|x64.ActiveCfg = Debug|Any CPU
- {E6A30001-84E3-4C7A-9B56-B9DEA71B3CF9}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {BFED925C-18F2-4C98-833E-66F205234598}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {BFED925C-18F2-4C98-833E-66F205234598}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {BFED925C-18F2-4C98-833E-66F205234598}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {BFED925C-18F2-4C98-833E-66F205234598}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {BFED925C-18F2-4C98-833E-66F205234598}.Checked|x86.ActiveCfg = Debug|Any CPU
{BFED925C-18F2-4C98-833E-66F205234598}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BFED925C-18F2-4C98-833E-66F205234598}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BFED925C-18F2-4C98-833E-66F205234598}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -419,11 +428,11 @@ Global
{BFED925C-18F2-4C98-833E-66F205234598}.Release|x64.Build.0 = Release|Any CPU
{BFED925C-18F2-4C98-833E-66F205234598}.Release|x86.ActiveCfg = Release|Any CPU
{BFED925C-18F2-4C98-833E-66F205234598}.Release|x86.Build.0 = Release|Any CPU
- {BFED925C-18F2-4C98-833E-66F205234598}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {BFED925C-18F2-4C98-833E-66F205234598}.Checked|arm.ActiveCfg = Debug|Any CPU
- {BFED925C-18F2-4C98-833E-66F205234598}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {BFED925C-18F2-4C98-833E-66F205234598}.Checked|x64.ActiveCfg = Debug|Any CPU
- {BFED925C-18F2-4C98-833E-66F205234598}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|x86.ActiveCfg = Debug|Any CPU
{765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -440,11 +449,11 @@ Global
{765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Release|x64.Build.0 = Release|Any CPU
{765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Release|x86.ActiveCfg = Release|Any CPU
{765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Release|x86.Build.0 = Release|Any CPU
- {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|arm.ActiveCfg = Debug|Any CPU
- {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|x64.ActiveCfg = Debug|Any CPU
- {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {DE207B2C-A0CC-47C8-AC20-46A8C0970287}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {DE207B2C-A0CC-47C8-AC20-46A8C0970287}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {DE207B2C-A0CC-47C8-AC20-46A8C0970287}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {DE207B2C-A0CC-47C8-AC20-46A8C0970287}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {DE207B2C-A0CC-47C8-AC20-46A8C0970287}.Checked|x86.ActiveCfg = Debug|Any CPU
{DE207B2C-A0CC-47C8-AC20-46A8C0970287}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DE207B2C-A0CC-47C8-AC20-46A8C0970287}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DE207B2C-A0CC-47C8-AC20-46A8C0970287}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -461,11 +470,11 @@ Global
{DE207B2C-A0CC-47C8-AC20-46A8C0970287}.Release|x64.Build.0 = Release|Any CPU
{DE207B2C-A0CC-47C8-AC20-46A8C0970287}.Release|x86.ActiveCfg = Release|Any CPU
{DE207B2C-A0CC-47C8-AC20-46A8C0970287}.Release|x86.Build.0 = Release|Any CPU
- {DE207B2C-A0CC-47C8-AC20-46A8C0970287}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {DE207B2C-A0CC-47C8-AC20-46A8C0970287}.Checked|arm.ActiveCfg = Debug|Any CPU
- {DE207B2C-A0CC-47C8-AC20-46A8C0970287}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {DE207B2C-A0CC-47C8-AC20-46A8C0970287}.Checked|x64.ActiveCfg = Debug|Any CPU
- {DE207B2C-A0CC-47C8-AC20-46A8C0970287}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|x86.ActiveCfg = Debug|Any CPU
{09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -482,11 +491,11 @@ Global
{09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Release|x64.Build.0 = Release|Any CPU
{09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Release|x86.ActiveCfg = Release|Any CPU
{09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Release|x86.Build.0 = Release|Any CPU
- {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|arm.ActiveCfg = Debug|Any CPU
- {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|x64.ActiveCfg = Debug|Any CPU
- {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|x86.ActiveCfg = Debug|Any CPU
{B4E3E774-2C16-4CBF-87EF-88C547529B94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B4E3E774-2C16-4CBF-87EF-88C547529B94}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B4E3E774-2C16-4CBF-87EF-88C547529B94}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -503,11 +512,11 @@ Global
{B4E3E774-2C16-4CBF-87EF-88C547529B94}.Release|x64.Build.0 = Release|Any CPU
{B4E3E774-2C16-4CBF-87EF-88C547529B94}.Release|x86.ActiveCfg = Release|Any CPU
{B4E3E774-2C16-4CBF-87EF-88C547529B94}.Release|x86.Build.0 = Release|Any CPU
- {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|arm.ActiveCfg = Debug|Any CPU
- {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|x64.ActiveCfg = Debug|Any CPU
- {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|x86.ActiveCfg = Debug|Any CPU
{EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -524,11 +533,11 @@ Global
{EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Release|x64.Build.0 = Release|Any CPU
{EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Release|x86.ActiveCfg = Release|Any CPU
{EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Release|x86.Build.0 = Release|Any CPU
- {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|arm.ActiveCfg = Debug|Any CPU
- {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|x64.ActiveCfg = Debug|Any CPU
- {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|x86.ActiveCfg = Debug|Any CPU
{44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -545,11 +554,11 @@ Global
{44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Release|x64.Build.0 = Release|Any CPU
{44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Release|x86.ActiveCfg = Release|Any CPU
{44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Release|x86.Build.0 = Release|Any CPU
- {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|arm.ActiveCfg = Debug|Any CPU
- {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|x64.ActiveCfg = Debug|Any CPU
- {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|x86.ActiveCfg = Debug|Any CPU
{1EB2EBE2-12EA-4545-B390-098F083329A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1EB2EBE2-12EA-4545-B390-098F083329A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1EB2EBE2-12EA-4545-B390-098F083329A1}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -566,11 +575,11 @@ Global
{1EB2EBE2-12EA-4545-B390-098F083329A1}.Release|x64.Build.0 = Release|Any CPU
{1EB2EBE2-12EA-4545-B390-098F083329A1}.Release|x86.ActiveCfg = Release|Any CPU
{1EB2EBE2-12EA-4545-B390-098F083329A1}.Release|x86.Build.0 = Release|Any CPU
- {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|arm.ActiveCfg = Debug|Any CPU
- {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|x64.ActiveCfg = Debug|Any CPU
- {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|x86.ActiveCfg = Debug|Any CPU
{B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -587,11 +596,11 @@ Global
{B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Release|x64.Build.0 = Release|Any CPU
{B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Release|x86.ActiveCfg = Release|Any CPU
{B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Release|x86.Build.0 = Release|Any CPU
- {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|arm.ActiveCfg = Debug|Any CPU
- {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|x64.ActiveCfg = Debug|Any CPU
- {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|x86.ActiveCfg = Debug|Any CPU
{04A40E6C-DD10-473D-AFF8-9033E936DC46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{04A40E6C-DD10-473D-AFF8-9033E936DC46}.Debug|Any CPU.Build.0 = Debug|Any CPU
{04A40E6C-DD10-473D-AFF8-9033E936DC46}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -608,11 +617,11 @@ Global
{04A40E6C-DD10-473D-AFF8-9033E936DC46}.Release|x64.Build.0 = Release|Any CPU
{04A40E6C-DD10-473D-AFF8-9033E936DC46}.Release|x86.ActiveCfg = Release|Any CPU
{04A40E6C-DD10-473D-AFF8-9033E936DC46}.Release|x86.Build.0 = Release|Any CPU
- {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|arm.ActiveCfg = Debug|Any CPU
- {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|x64.ActiveCfg = Debug|Any CPU
- {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|x86.ActiveCfg = Debug|Any CPU
{B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -629,11 +638,11 @@ Global
{B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Release|x64.Build.0 = Release|Any CPU
{B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Release|x86.ActiveCfg = Release|Any CPU
{B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Release|x86.Build.0 = Release|Any CPU
- {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|arm.ActiveCfg = Debug|Any CPU
- {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|x64.ActiveCfg = Debug|Any CPU
- {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|x86.ActiveCfg = Debug|Any CPU
{424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -650,11 +659,11 @@ Global
{424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Release|x64.Build.0 = Release|Any CPU
{424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Release|x86.ActiveCfg = Release|Any CPU
{424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Release|x86.Build.0 = Release|Any CPU
- {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|arm.ActiveCfg = Debug|Any CPU
- {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|x64.ActiveCfg = Debug|Any CPU
- {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|x86.ActiveCfg = Debug|Any CPU
{D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -671,11 +680,11 @@ Global
{D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Release|x64.Build.0 = Release|Any CPU
{D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Release|x86.ActiveCfg = Release|Any CPU
{D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Release|x86.Build.0 = Release|Any CPU
- {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|arm.ActiveCfg = Debug|Any CPU
- {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|x64.ActiveCfg = Debug|Any CPU
- {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|x86.ActiveCfg = Debug|Any CPU
{8683B814-5459-4412-A881-ECAFF9ED1781}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8683B814-5459-4412-A881-ECAFF9ED1781}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8683B814-5459-4412-A881-ECAFF9ED1781}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -692,11 +701,11 @@ Global
{8683B814-5459-4412-A881-ECAFF9ED1781}.Release|x64.Build.0 = Release|Any CPU
{8683B814-5459-4412-A881-ECAFF9ED1781}.Release|x86.ActiveCfg = Release|Any CPU
{8683B814-5459-4412-A881-ECAFF9ED1781}.Release|x86.Build.0 = Release|Any CPU
- {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|arm.ActiveCfg = Debug|Any CPU
- {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|x64.ActiveCfg = Debug|Any CPU
- {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|x86.ActiveCfg = Debug|Any CPU
{4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -713,11 +722,11 @@ Global
{4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Release|x64.Build.0 = Release|Any CPU
{4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Release|x86.ActiveCfg = Release|Any CPU
{4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Release|x86.Build.0 = Release|Any CPU
- {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|arm.ActiveCfg = Debug|Any CPU
- {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|x64.ActiveCfg = Debug|Any CPU
- {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|x86.ActiveCfg = Debug|Any CPU
{6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -734,11 +743,11 @@ Global
{6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Release|x64.Build.0 = Release|Any CPU
{6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Release|x86.ActiveCfg = Release|Any CPU
{6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Release|x86.Build.0 = Release|Any CPU
- {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|arm.ActiveCfg = Debug|Any CPU
- {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|x64.ActiveCfg = Debug|Any CPU
- {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|x86.ActiveCfg = Debug|Any CPU
{B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -755,11 +764,11 @@ Global
{B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Release|x64.Build.0 = Release|Any CPU
{B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Release|x86.ActiveCfg = Release|Any CPU
{B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Release|x86.Build.0 = Release|Any CPU
- {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|arm.ActiveCfg = Debug|Any CPU
- {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|x64.ActiveCfg = Debug|Any CPU
- {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|x86.ActiveCfg = Debug|Any CPU
{42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -776,11 +785,11 @@ Global
{42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Release|x64.Build.0 = Release|Any CPU
{42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Release|x86.ActiveCfg = Release|Any CPU
{42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Release|x86.Build.0 = Release|Any CPU
- {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|arm.ActiveCfg = Debug|Any CPU
- {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|x64.ActiveCfg = Debug|Any CPU
- {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {008873D5-9028-4FF3-8354-71F713748625}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {008873D5-9028-4FF3-8354-71F713748625}.Checked|arm.ActiveCfg = Debug|Any CPU
+ {008873D5-9028-4FF3-8354-71F713748625}.Checked|arm64.ActiveCfg = Debug|Any CPU
+ {008873D5-9028-4FF3-8354-71F713748625}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {008873D5-9028-4FF3-8354-71F713748625}.Checked|x86.ActiveCfg = Debug|Any CPU
{008873D5-9028-4FF3-8354-71F713748625}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{008873D5-9028-4FF3-8354-71F713748625}.Debug|Any CPU.Build.0 = Debug|Any CPU
{008873D5-9028-4FF3-8354-71F713748625}.Debug|arm.ActiveCfg = Debug|Any CPU
@@ -797,54 +806,54 @@ Global
{008873D5-9028-4FF3-8354-71F713748625}.Release|x64.Build.0 = Release|Any CPU
{008873D5-9028-4FF3-8354-71F713748625}.Release|x86.ActiveCfg = Release|Any CPU
{008873D5-9028-4FF3-8354-71F713748625}.Release|x86.Build.0 = Release|Any CPU
- {008873D5-9028-4FF3-8354-71F713748625}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {008873D5-9028-4FF3-8354-71F713748625}.Checked|arm.ActiveCfg = Debug|Any CPU
- {008873D5-9028-4FF3-8354-71F713748625}.Checked|arm64.ActiveCfg = Debug|Any CPU
- {008873D5-9028-4FF3-8354-71F713748625}.Checked|x64.ActiveCfg = Debug|Any CPU
- {008873D5-9028-4FF3-8354-71F713748625}.Checked|x86.ActiveCfg = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{0F7BA062-C34C-41A8-840F-F0B074B18686} = {32733782-56D6-4EAF-B94E-5D10C759DD57}
+ {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272} = {26A72FFB-871A-4F2F-A513-B2F6E09F358C}
{FC1007CC-9E52-49B7-A47B-A8AE76E75986} = {32733782-56D6-4EAF-B94E-5D10C759DD57}
+ {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3} = {19EA33B4-0E87-451F-95E3-8F3959117654}
{B79E5BB4-2595-48BC-A44C-0A7949AFBDEB} = {32733782-56D6-4EAF-B94E-5D10C759DD57}
+ {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8} = {19EA33B4-0E87-451F-95E3-8F3959117654}
{C1C606F3-A246-4EA0-A467-3AC4F31C2AFE} = {32733782-56D6-4EAF-B94E-5D10C759DD57}
+ {8CFB1155-26A2-43E3-B192-1F87D9E543AC} = {1A04C5D7-1DE9-47C3-BCC1-147678B9085F}
+ {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08} = {19EA33B4-0E87-451F-95E3-8F3959117654}
{74143A5F-6987-4AB5-B786-DE358F01241B} = {32733782-56D6-4EAF-B94E-5D10C759DD57}
+ {CE5E53C1-F9B5-41EE-8D00-837913EC57D1} = {1A04C5D7-1DE9-47C3-BCC1-147678B9085F}
+ {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1} = {19EA33B4-0E87-451F-95E3-8F3959117654}
{71A845ED-4344-41FC-8FCA-3AC9B6BA6C45} = {32733782-56D6-4EAF-B94E-5D10C759DD57}
- {1EB2EBE2-12EA-4545-B390-098F083329A1} = {32733782-56D6-4EAF-B94E-5D10C759DD57}
- {04A40E6C-DD10-473D-AFF8-9033E936DC46} = {32733782-56D6-4EAF-B94E-5D10C759DD57}
- {424A7718-F5B7-41FB-A74B-1E23A9BF13EA} = {32733782-56D6-4EAF-B94E-5D10C759DD57}
- {8683B814-5459-4412-A881-ECAFF9ED1781} = {32733782-56D6-4EAF-B94E-5D10C759DD57}
- {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272} = {26A72FFB-871A-4F2F-A513-B2F6E09F358C}
{E6A30001-84E3-4C7A-9B56-B9DEA71B3CF9} = {26A72FFB-871A-4F2F-A513-B2F6E09F358C}
{BFED925C-18F2-4C98-833E-66F205234598} = {26A72FFB-871A-4F2F-A513-B2F6E09F358C}
{765B4AA5-723A-44FF-BC4E-EB0F03103F6D} = {26A72FFB-871A-4F2F-A513-B2F6E09F358C}
+ {DE207B2C-A0CC-47C8-AC20-46A8C0970287} = {1A04C5D7-1DE9-47C3-BCC1-147678B9085F}
+ {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD} = {1A04C5D7-1DE9-47C3-BCC1-147678B9085F}
+ {B4E3E774-2C16-4CBF-87EF-88C547529B94} = {1A04C5D7-1DE9-47C3-BCC1-147678B9085F}
{EC3ADEFA-1FF3-482C-8CCB-FE4C77292532} = {26A72FFB-871A-4F2F-A513-B2F6E09F358C}
- {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3} = {19EA33B4-0E87-451F-95E3-8F3959117654}
- {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8} = {19EA33B4-0E87-451F-95E3-8F3959117654}
- {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08} = {19EA33B4-0E87-451F-95E3-8F3959117654}
- {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1} = {19EA33B4-0E87-451F-95E3-8F3959117654}
{44BAE6F1-94C2-415B-9A16-3B8EC429B09B} = {19EA33B4-0E87-451F-95E3-8F3959117654}
+ {1EB2EBE2-12EA-4545-B390-098F083329A1} = {32733782-56D6-4EAF-B94E-5D10C759DD57}
{B18C5A3A-CAB0-4B62-9C01-7A046E05089F} = {19EA33B4-0E87-451F-95E3-8F3959117654}
+ {04A40E6C-DD10-473D-AFF8-9033E936DC46} = {32733782-56D6-4EAF-B94E-5D10C759DD57}
{B86E4599-88CF-4662-96BA-3FCB926D0BA1} = {19EA33B4-0E87-451F-95E3-8F3959117654}
+ {424A7718-F5B7-41FB-A74B-1E23A9BF13EA} = {32733782-56D6-4EAF-B94E-5D10C759DD57}
{D620CBA3-326B-4E4A-81C2-3D9E9258E45C} = {19EA33B4-0E87-451F-95E3-8F3959117654}
- {8CFB1155-26A2-43E3-B192-1F87D9E543AC} = {1A04C5D7-1DE9-47C3-BCC1-147678B9085F}
- {CE5E53C1-F9B5-41EE-8D00-837913EC57D1} = {1A04C5D7-1DE9-47C3-BCC1-147678B9085F}
- {DE207B2C-A0CC-47C8-AC20-46A8C0970287} = {1A04C5D7-1DE9-47C3-BCC1-147678B9085F}
- {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD} = {1A04C5D7-1DE9-47C3-BCC1-147678B9085F}
- {B4E3E774-2C16-4CBF-87EF-88C547529B94} = {1A04C5D7-1DE9-47C3-BCC1-147678B9085F}
+ {8683B814-5459-4412-A881-ECAFF9ED1781} = {32733782-56D6-4EAF-B94E-5D10C759DD57}
{4D8B7538-D933-4F3A-818D-4E19ABA7E182} = {F81BA54D-38C5-4493-BB5C-344825706D3A}
{6C60944F-4FE1-450F-884B-D523EDFCFAB3} = {F81BA54D-38C5-4493-BB5C-344825706D3A}
- {F81BA54D-38C5-4493-BB5C-344825706D3A} = {7392B838-42AF-4F54-AD02-366397DAF640}
{B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B} = {F0448246-E8A1-49FD-878C-7A6B8486A66B}
{42F9A600-BEC3-4F87-97EE-38E0DCAABC5A} = {F0448246-E8A1-49FD-878C-7A6B8486A66B}
- {F0448246-E8A1-49FD-878C-7A6B8486A66B} = {7392B838-42AF-4F54-AD02-366397DAF640}
{008873D5-9028-4FF3-8354-71F713748625} = {9BB52E31-4890-4F4B-8B2B-6282EF13B8D2}
+ {F81BA54D-38C5-4493-BB5C-344825706D3A} = {7392B838-42AF-4F54-AD02-366397DAF640}
+ {F0448246-E8A1-49FD-878C-7A6B8486A66B} = {7392B838-42AF-4F54-AD02-366397DAF640}
{9BB52E31-4890-4F4B-8B2B-6282EF13B8D2} = {7392B838-42AF-4F54-AD02-366397DAF640}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3FE64246-4AFA-424A-AE5D-7007E20451B5}
EndGlobalSection
+ GlobalSection(SharedMSBuildProjectFiles) = preSolution
+ ..\System.Private.CoreLib\src\System.Private.CoreLib.Shared.projitems*{0f7ba062-c34c-41a8-840f-f0b074b18686}*SharedItemsImports = 5
+ ..\..\tools\illink\src\ILLink.Shared\ILLink.Shared.projitems*{42f9a600-bec3-4f87-97ee-38e0dcaabc5a}*SharedItemsImports = 5
+ ..\..\tools\illink\src\ILLink.Shared\ILLink.Shared.projitems*{6c60944f-4fe1-450f-884b-d523edfcfab3}*SharedItemsImports = 5
+ EndGlobalSection
EndGlobal
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Constants.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Constants.cs
index a5475e27c70a46..5dd5fa98ceb1b4 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Constants.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Constants.cs
@@ -14,6 +14,7 @@ internal static class Constants
public const string JSFunctionSignatureGlobal = "global::System.Runtime.InteropServices.JavaScript.JSFunctionBinding";
public const string JSMarshalerArgumentGlobal = "global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument";
+ public const string JSMarshalerArgument = "System.Runtime.InteropServices.JavaScript.JSMarshalerArgument";
public const string ModuleInitializerAttributeGlobal = "global::System.Runtime.CompilerServices.ModuleInitializerAttribute";
public const string CompilerGeneratedAttributeGlobal = "global::System.Runtime.CompilerServices.CompilerGeneratedAttribute";
public const string DynamicDependencyAttributeGlobal = "global::System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute";
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs
deleted file mode 100644
index 33b08510d4fe8a..00000000000000
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs
+++ /dev/null
@@ -1,236 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Linq;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-
-namespace Microsoft.Interop.JavaScript
-{
- internal sealed class JSExportCodeGenerator : JSCodeGenerator
- {
- private readonly BoundGenerators _marshallers;
-
- private readonly StubIdentifierContext _context;
- private readonly JSExportData _jsExportData;
- private readonly JSSignatureContext _signatureContext;
-
- public JSExportCodeGenerator(
- ImmutableArray argTypes,
- JSExportData attributeData,
- JSSignatureContext signatureContext,
- GeneratorDiagnosticsBag diagnosticsBag,
- IMarshallingGeneratorResolver generatorResolver)
- {
- _signatureContext = signatureContext;
- _jsExportData = attributeData;
-
- _marshallers = BoundGenerators.Create(argTypes, generatorResolver, StubCodeContext.DefaultNativeToManagedStub, new EmptyJSGenerator(), out var bindingFailures);
-
- diagnosticsBag.ReportGeneratorDiagnostics(bindingFailures);
-
- if (_marshallers.ManagedReturnMarshaller.UsesNativeIdentifier)
- {
- // If we need a different native return identifier, then recreate the context with the correct identifier before we generate any code.
- _context = new DefaultIdentifierContext(ReturnIdentifier, ReturnNativeIdentifier, MarshalDirection.UnmanagedToManaged)
- {
- CodeEmitOptions = new(SkipInit: true),
- };
- }
- else
- {
- _context = new DefaultIdentifierContext(ReturnIdentifier, ReturnIdentifier, MarshalDirection.UnmanagedToManaged)
- {
- CodeEmitOptions = new(SkipInit: true),
- };
- }
-
- // validate task + span mix
- if (_marshallers.ManagedReturnMarshaller.TypeInfo.MarshallingAttributeInfo is JSMarshallingInfo(_, JSTaskTypeInfo))
- {
- IBoundMarshallingGenerator spanArg = _marshallers.SignatureMarshallers.FirstOrDefault(m => m.TypeInfo.MarshallingAttributeInfo is JSMarshallingInfo(_, JSSpanTypeInfo));
- if (spanArg != default)
- {
- diagnosticsBag.ReportGeneratorDiagnostic(new GeneratorDiagnostic.NotSupported(spanArg.TypeInfo)
- {
- NotSupportedDetails = SR.SpanAndTaskNotSupported
- });
- }
- }
- }
-
- public BlockSyntax GenerateJSExportBody()
- {
- List invoke = InvokeSyntax();
- GeneratedStatements statements = GeneratedStatements.Create(_marshallers, _context);
- bool shouldInitializeVariables = !statements.GuaranteedUnmarshal.IsEmpty || !statements.CleanupCallerAllocated.IsEmpty || !statements.CleanupCalleeAllocated.IsEmpty;
- VariableDeclarations declarations = VariableDeclarations.GenerateDeclarationsForUnmanagedToManaged(_marshallers, _context, shouldInitializeVariables);
-
- var setupStatements = new List();
- SetupSyntax(setupStatements);
-
- if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty))
- {
- setupStatements.Add(SyntaxFactoryExtensions.Declare(PredefinedType(Token(SyntaxKind.BoolKeyword)), InvokeSucceededIdentifier, initializeToDefault: true));
- }
-
- setupStatements.AddRange(declarations.Initializations);
- setupStatements.AddRange(declarations.Variables);
- setupStatements.AddRange(statements.Setup);
-
- var tryStatements = new List();
- tryStatements.AddRange(statements.Unmarshal);
-
- tryStatements.AddRange(invoke);
-
- if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty))
- {
- tryStatements.Add(ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
- IdentifierName(InvokeSucceededIdentifier),
- LiteralExpression(SyntaxKind.TrueLiteralExpression))));
- }
-
- tryStatements.AddRange(statements.NotifyForSuccessfulInvoke);
- tryStatements.AddRange(statements.PinnedMarshal);
- tryStatements.AddRange(statements.Marshal);
-
- List allStatements = setupStatements;
-
- // Wrap unmarshall, invocation and return value marshalling in try-catch.
- // In case of exception, marshal exception instead of return value.
- var tryInvokeAndMarshal = TryStatement(SingletonList(CatchClause()
- .WithDeclaration(CatchDeclaration(IdentifierName(Constants.ExceptionGlobal)).WithIdentifier(Identifier("ex")))
- .WithBlock(Block(SingletonList(
- ExpressionStatement(InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(Constants.ArgumentException), IdentifierName(Constants.ToJSMethod)))
- .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(IdentifierName("ex")))))))))))
- .WithBlock(Block(tryStatements));
-
- List finallyStatements = new List();
- if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty))
- {
- finallyStatements.Add(IfStatement(IdentifierName(InvokeSucceededIdentifier), Block(statements.GuaranteedUnmarshal.Concat(statements.CleanupCalleeAllocated))));
- }
-
- finallyStatements.AddRange(statements.CleanupCallerAllocated);
-
- if (finallyStatements.Count > 0)
- {
- tryInvokeAndMarshal = TryStatement(Block(tryInvokeAndMarshal), default, FinallyClause(Block(finallyStatements)));
- }
-
- allStatements.Add(tryInvokeAndMarshal);
-
- return Block(allStatements);
- }
-
- public static StatementSyntax[] GenerateJSExportArchitectureCheck()
- {
- return new StatementSyntax[]{
- IfStatement(
- BinaryExpression(SyntaxKind.LogicalOrExpression,
- IdentifierName("initialized"),
- BinaryExpression(SyntaxKind.NotEqualsExpression,
- IdentifierName(Constants.OSArchitectureGlobal),
- IdentifierName(Constants.ArchitectureWasmGlobal))),
- ReturnStatement()),
- ExpressionStatement(
- AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
- IdentifierName("initialized"),
- LiteralExpression(SyntaxKind.TrueLiteralExpression))),
- };
- }
-
- public StatementSyntax GenerateJSExportRegistration()
- {
- var signatureArgs = new List
- {
- Argument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(_signatureContext.QualifiedMethodName))),
- Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(_signatureContext.TypesHash))),
- CreateSignaturesSyntax()
- };
-
- return ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(Constants.JSFunctionSignatureGlobal), IdentifierName(Constants.BindCSFunctionMethod)))
- .WithArgumentList(ArgumentList(SeparatedList(signatureArgs))));
- }
-
- private ArgumentSyntax CreateSignaturesSyntax()
- {
- IEnumerable types = _marshallers.ManagedReturnMarshaller is IJSMarshallingGenerator jsGen ? jsGen.GenerateBind() : [];
- types = types
- .Concat(_marshallers.NativeParameterMarshallers.OfType().SelectMany(p => p.GenerateBind()));
-
- return Argument(ArrayCreationExpression(ArrayType(IdentifierName(Constants.JSMarshalerTypeGlobal))
- .WithRankSpecifiers(SingletonList(ArrayRankSpecifier(SingletonSeparatedList(OmittedArraySizeExpression())))))
- .WithInitializer(InitializerExpression(SyntaxKind.ArrayInitializerExpression, SeparatedList(types))));
- }
-
- private void SetupSyntax(List statementsToUpdate)
- {
- foreach (IBoundMarshallingGenerator marshaller in _marshallers.NativeParameterMarshallers)
- {
- statementsToUpdate.Add(LocalDeclarationStatement(VariableDeclaration(marshaller.TypeInfo.ManagedType.Syntax)
- .WithVariables(SingletonSeparatedList(VariableDeclarator(marshaller.TypeInfo.InstanceIdentifier)))));
- }
-
- statementsToUpdate.Add(LocalDeclarationStatement(VariableDeclaration(RefType(IdentifierName(Constants.JSMarshalerArgumentGlobal)))
- .WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier(Constants.ArgumentException))
- .WithInitializer(EqualsValueClause(RefExpression(ElementAccessExpression(IdentifierName(Constants.ArgumentsBuffer))
- .WithArgumentList(BracketedArgumentList(SingletonSeparatedList(
- Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0)))))))))))));
-
- statementsToUpdate.Add(LocalDeclarationStatement(VariableDeclaration(RefType(IdentifierName(Constants.JSMarshalerArgumentGlobal)))
- .WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier(Constants.ArgumentReturn))
- .WithInitializer(EqualsValueClause(RefExpression(ElementAccessExpression(IdentifierName(Constants.ArgumentsBuffer))
- .WithArgumentList(BracketedArgumentList(SingletonSeparatedList(
- Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(1)))))))))))));
- }
-
- private List InvokeSyntax()
- {
- var statements = new List();
- var arguments = new List();
-
- // Generate code for each parameter for the current stage
- foreach (IBoundMarshallingGenerator marshaller in _marshallers.NativeParameterMarshallers)
- {
- // convert arguments for invocation
- statements.AddRange(marshaller.Generate(_context));
- arguments.Add(Argument(IdentifierName(marshaller.TypeInfo.InstanceIdentifier)));
- }
-
- if (_marshallers.IsManagedVoidReturn)
- {
- statements.Add(ExpressionStatement(InvocationExpression(IdentifierName(_signatureContext.MethodName))
- .WithArgumentList(ArgumentList(SeparatedList(arguments)))));
- }
- else
- {
- ExpressionSyntax invocation = InvocationExpression(IdentifierName(_signatureContext.MethodName))
- .WithArgumentList(ArgumentList(SeparatedList(arguments)));
-
- (string _, string nativeIdentifier) = _context.GetIdentifiers(_marshallers.ManagedReturnMarshaller.TypeInfo);
-
- ExpressionStatementSyntax statement = ExpressionStatement(AssignmentExpression(
- SyntaxKind.SimpleAssignmentExpression,
- IdentifierName(nativeIdentifier), invocation));
-
- statements.Add(statement);
- }
- return statements;
-
- }
-
- public (ParameterListSyntax ParameterList, TypeSyntax ReturnType, AttributeListSyntax? ReturnTypeAttributes) GenerateTargetMethodSignatureData()
- {
- return _marshallers.GenerateTargetMethodSignatureData(_context);
- }
- }
-}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs
index 824bc6b6d6c05e..f5dfa0082aa9e9 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs
@@ -146,7 +146,7 @@ private static MemberDeclarationSyntax PrintGeneratedSource(
.WithAttributeLists(SingletonList(AttributeList(SingletonSeparatedList(
Attribute(IdentifierName(Constants.DebuggerNonUserCodeAttribute))))))
.WithParameterList(ParameterList(SingletonSeparatedList(
- Parameter(Identifier("__arguments_buffer")).WithType(PointerType(ParseTypeName(Constants.JSMarshalerArgumentGlobal))))))
+ Parameter(Identifier(Constants.ArgumentsBuffer)).WithType(PointerType(ParseTypeName(Constants.JSMarshalerArgumentGlobal))))))
.WithBody(wrapperStatements);
MemberDeclarationSyntax toPrint = containingSyntaxContext.WrapMembersInContainingSyntaxWithUnsafeModifier(wrappperMethod);
@@ -225,7 +225,7 @@ private static NamespaceDeclarationSyntax GenerateRegSource(
if (methods.IsEmpty) return NamespaceDeclaration(IdentifierName(generatedNamespace));
var registerStatements = new List();
- registerStatements.AddRange(JSExportCodeGenerator.GenerateJSExportArchitectureCheck());
+ registerStatements.AddRange(GenerateJSExportArchitectureCheck());
var attributes = new List();
foreach (var m in methods)
@@ -302,23 +302,76 @@ private static NamespaceDeclarationSyntax GenerateRegSource(
return ns;
}
+ private static StatementSyntax[] GenerateJSExportArchitectureCheck()
+ {
+ return [
+ IfStatement(
+ BinaryExpression(SyntaxKind.LogicalOrExpression,
+ IdentifierName("initialized"),
+ BinaryExpression(SyntaxKind.NotEqualsExpression,
+ IdentifierName(Constants.OSArchitectureGlobal),
+ IdentifierName(Constants.ArchitectureWasmGlobal))),
+ ReturnStatement()),
+ ExpressionStatement(
+ AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
+ IdentifierName("initialized"),
+ LiteralExpression(SyntaxKind.TrueLiteralExpression))),
+ ];
+ }
+
private static (MemberDeclarationSyntax, StatementSyntax, AttributeListSyntax, ImmutableArray) GenerateSource(
IncrementalStubGenerationContext incrementalContext)
{
var diagnostics = new GeneratorDiagnosticsBag(new DescriptorProvider(), incrementalContext.DiagnosticLocation, SR.ResourceManager, typeof(FxResources.Microsoft.Interop.JavaScript.JSImportGenerator.SR));
// Generate stub code
- var stubGenerator = new JSExportCodeGenerator(
- incrementalContext.SignatureContext.SignatureContext.ElementTypeInformation,
- incrementalContext.JSExportData,
- incrementalContext.SignatureContext,
+ ImmutableArray signatureElements = incrementalContext.SignatureContext.SignatureContext.ElementTypeInformation;
+
+ ImmutableArray allElements = signatureElements
+ .Add(new TypePositionInfo(
+ new ReferenceTypeInfo(Constants.ExceptionGlobal, Constants.ExceptionGlobal),
+ new JSMarshallingInfo(NoMarshallingInfo.Instance, new JSSimpleTypeInfo(KnownManagedType.Exception, ParseTypeName(Constants.ExceptionGlobal)))
+ {
+ JSType = System.Runtime.InteropServices.JavaScript.JSTypeFlags.Error,
+ })
+ {
+ InstanceIdentifier = Constants.ArgumentException,
+ ManagedIndex = TypePositionInfo.ExceptionIndex,
+ NativeIndex = signatureElements.Length, // Insert at the end of the argument list
+ RefKind = RefKind.Out, // We'll treat it as a separate out parameter.
+ });
+
+ for (int i = 0; i < allElements.Length; i++)
+ {
+ if (allElements[i].IsNativeReturnPosition && allElements[i].ManagedType != SpecialTypeInfo.Void)
+ {
+ // The runtime may partially initialize the native return value.
+ // To preserve this information, we must pass the native return value as an out parameter.
+ allElements = allElements.SetItem(i, allElements[i] with
+ {
+ ManagedIndex = TypePositionInfo.ReturnIndex,
+ NativeIndex = allElements.Length, // Insert at the end of the argument list
+ RefKind = RefKind.Out, // We'll treat it as a separate out parameter.
+ });
+ }
+ }
+
+ var stubGenerator = new UnmanagedToManagedStubGenerator(
+ allElements,
diagnostics,
- new JSGeneratorResolver());
+ new CompositeMarshallingGeneratorResolver(
+ new NoSpanAndTaskMixingResolver(),
+ new JSGeneratorResolver()));
var wrapperName = "__Wrapper_" + incrementalContext.StubMethodSyntaxTemplate.Identifier + "_" + incrementalContext.SignatureContext.TypesHash;
- BlockSyntax wrapper = stubGenerator.GenerateJSExportBody();
- StatementSyntax registration = stubGenerator.GenerateJSExportRegistration();
+ const string innerWrapperName = "__Stub";
+
+ BlockSyntax wrapperToInnerStubBlock = Block(
+ CreateWrapperToInnerStubCall(signatureElements, innerWrapperName),
+ GenerateInnerLocalFunction(incrementalContext, innerWrapperName, stubGenerator));
+
+ StatementSyntax registration = GenerateJSExportRegistration(incrementalContext.SignatureContext);
AttributeListSyntax registrationAttribute = AttributeList(SingletonSeparatedList(Attribute(IdentifierName(Constants.DynamicDependencyAttributeGlobal))
.WithArgumentList(AttributeArgumentList(SeparatedList(new[]{
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(wrapperName))),
@@ -327,11 +380,76 @@ private static (MemberDeclarationSyntax, StatementSyntax, AttributeListSyntax, I
}
)))));
- return (PrintGeneratedSource(incrementalContext.ContainingSyntaxContext, wrapper, wrapperName),
+ return (PrintGeneratedSource(incrementalContext.ContainingSyntaxContext, wrapperToInnerStubBlock, wrapperName),
registration, registrationAttribute,
incrementalContext.Diagnostics.Array.AddRange(diagnostics.Diagnostics));
}
+ private static ExpressionStatementSyntax CreateWrapperToInnerStubCall(ImmutableArray signatureElements, string innerWrapperName)
+ {
+ List arguments = [];
+ bool hasReturn = true;
+ foreach (var nativeArg in signatureElements.Where(e => e.NativeIndex != TypePositionInfo.UnsetIndex).OrderBy(e => e.NativeIndex))
+ {
+ if (nativeArg.IsNativeReturnPosition)
+ {
+ if (nativeArg.ManagedType == SpecialTypeInfo.Void)
+ {
+ hasReturn = false;
+ }
+ continue;
+ }
+ arguments.Add(
+ Argument(
+ ElementAccessExpression(
+ IdentifierName(Constants.ArgumentsBuffer),
+ BracketedArgumentList(SingletonSeparatedList(Argument(
+ LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(nativeArg.NativeIndex + 2))))))));
+ }
+
+ arguments.Add(Argument(IdentifierName(Constants.ArgumentsBuffer)));
+
+ if (hasReturn)
+ {
+ arguments.Add(
+ Argument(
+ BinaryExpression(
+ SyntaxKind.AddExpression,
+ IdentifierName(Constants.ArgumentsBuffer),
+ LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(1)))));
+ }
+
+ return ExpressionStatement(
+ InvocationExpression(IdentifierName(innerWrapperName))
+ .WithArgumentList(ArgumentList(SeparatedList(arguments))));
+ }
+
+ private static LocalFunctionStatementSyntax GenerateInnerLocalFunction(IncrementalStubGenerationContext context, string innerFunctionName, UnmanagedToManagedStubGenerator stubGenerator)
+ {
+ var (parameters, returnType, _) = stubGenerator.GenerateAbiMethodSignatureData();
+ return LocalFunctionStatement(
+ returnType,
+ innerFunctionName)
+ .WithBody(stubGenerator.GenerateStubBody(IdentifierName(context.SignatureContext.MethodName)))
+ .WithParameterList(parameters)
+ .WithAttributeLists(SingletonList(AttributeList(SingletonSeparatedList(
+ Attribute(IdentifierName(Constants.DebuggerNonUserCodeAttribute))))));
+ }
+
+ private static ExpressionStatementSyntax GenerateJSExportRegistration(JSSignatureContext context)
+ {
+ var signatureArgs = new List
+ {
+ Argument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(context.QualifiedMethodName))),
+ Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(context.TypesHash))),
+ SignatureBindingHelpers.CreateSignaturesArgument(context.SignatureContext.ElementTypeInformation, StubCodeContext.DefaultNativeToManagedStub)
+ };
+
+ return ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
+ IdentifierName(Constants.JSFunctionSignatureGlobal), IdentifierName(Constants.BindCSFunctionMethod)))
+ .WithArgumentList(ArgumentList(SeparatedList(signatureArgs))));
+ }
+
private static Diagnostic? GetDiagnosticIfInvalidMethodForGeneration(MethodDeclarationSyntax methodSyntax, IMethodSymbol method)
{
// Verify the method has no generic types or defined implementation
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSGeneratorFactory.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSGeneratorFactory.cs
index f5f61c413bc117..51b6d5764b1b76 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSGeneratorFactory.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSGeneratorFactory.cs
@@ -8,6 +8,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Data;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.Interop.JavaScript
{
@@ -16,7 +17,7 @@ internal sealed class JSGeneratorResolver : IMarshallingGeneratorResolver
public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context)
{
Debug.Assert(context != null);
- if (info.IsByRef || info.ByValueContentsMarshalKind != ByValueContentsMarshalKind.Default)
+ if (!info.IsManagedExceptionPosition && !info.IsManagedReturnPosition && (info.IsByRef || info.ByValueContentsMarshalKind != ByValueContentsMarshalKind.Default))
{
// out of scope for Net7.0
return ResolvedGenerator.NotSupported(info, context, new(info)
@@ -24,298 +25,311 @@ public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context)
NotSupportedDetails = SR.InOutRefNotSupported
});
}
- JSMarshallingInfo jsMarshalingInfo = info.MarshallingAttributeInfo as JSMarshallingInfo;
- ResolvedGenerator fail(string failReason)
+ if (MarshallerHelpers.GetMarshalDirection(info, context) != MarshalDirection.UnmanagedToManaged && info.ManagedIndex == TypePositionInfo.UnsetIndex)
{
- return ResolvedGenerator.NotSupported(info, context, new(info)
- {
- NotSupportedDetails = failReason
- });
+ // Use the InitOnlyJSGenerator for native-only parameters.
+ return ResolvedGenerator.Resolved(new ImplicitArgumentGenerator(info, context));
}
- bool isToJs = info.ManagedIndex != TypePositionInfo.ReturnIndex ^ context.Direction == MarshalDirection.UnmanagedToManaged;
+
+ return Create(info, info.MarshallingAttributeInfo as JSMarshallingInfo, context).Generator;
+ }
+
+ public static (MarshalerType BaseType, IEnumerable? SubTypes) GetMarshallerTypeForBinding(TypePositionInfo info, StubCodeContext context)
+ {
+ var (_, baseType, subTypes) = Create(info, info.MarshallingAttributeInfo as JSMarshallingInfo, context);
+ return (baseType, subTypes);
+ }
+
+ private record struct ResolvedGeneratorAndType(ResolvedGenerator Generator, MarshalerType Type, IEnumerable? SubTypes = null);
+
+ private static ResolvedGeneratorAndType Create(TypePositionInfo info, JSMarshallingInfo jsMarshalingInfo, StubCodeContext context)
+ {
+ bool isToJs = MarshallerHelpers.GetMarshalDirection(info, context) == MarshalDirection.ManagedToUnmanaged;
switch (jsMarshalingInfo)
{
// invalid
case { TypeInfo: JSInvalidTypeInfo }:
- return ResolvedGenerator.NotSupported(info, context, new(info));
-
- // void
- case { TypeInfo: JSSimpleTypeInfo(KnownManagedType.Void), JSType: JSTypeFlags.DiscardNoWait }:
- return ResolvedGenerator.Resolved(new VoidGenerator(info, context, MarshalerType.DiscardNoWait));
- case { TypeInfo: JSSimpleTypeInfo(KnownManagedType.Void), JSType: JSTypeFlags.Discard }:
- case { TypeInfo: JSSimpleTypeInfo(KnownManagedType.Void), JSType: JSTypeFlags.Void }:
- case { TypeInfo: JSSimpleTypeInfo(KnownManagedType.Void), JSType: JSTypeFlags.None }:
- case { TypeInfo: JSSimpleTypeInfo(KnownManagedType.Void), JSType: JSTypeFlags.Missing }:
- return ResolvedGenerator.Resolved(new VoidGenerator(info, context, jsMarshalingInfo.JSType == JSTypeFlags.Void ? MarshalerType.Void : MarshalerType.Discard));
-
- // discard no void
- case { JSType: JSTypeFlags.Discard }:
- return fail(SR.DiscardOnlyVoid);
-
- // oneway no void
- case { JSType: JSTypeFlags.DiscardNoWait }:
- return fail(SR.DiscardNoWaitOnlyVoid);
+ return new(ResolvedGenerator.NotSupported(info, context, new(info)), MarshalerType.None);
// primitive
case { TypeInfo: JSSimpleTypeInfo simple }:
- return Create(info, context, isToJs, simple.KnownType, [], jsMarshalingInfo.JSType, Array.Empty(), fail);
+ return Create(info, context, isToJs, simple.KnownType, [], jsMarshalingInfo.JSType, []);
// nullable
case { TypeInfo: JSNullableTypeInfo nullable }:
- return Create(info, context, isToJs, nullable.KnownType, [nullable.ResultTypeInfo.KnownType], jsMarshalingInfo.JSType, null, fail);
+ return Create(info, context, isToJs, nullable.KnownType, [nullable.ResultTypeInfo.KnownType], jsMarshalingInfo.JSType, null);
// array
case { TypeInfo: JSArrayTypeInfo array }:
- return Create(info, context, isToJs, array.KnownType, [array.ElementTypeInfo.KnownType], jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments, fail);
+ return Create(info, context, isToJs, array.KnownType, [array.ElementTypeInfo.KnownType], jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments);
// array segment
case { TypeInfo: JSArraySegmentTypeInfo segment }:
- return Create(info, context, isToJs, segment.KnownType, [segment.ElementTypeInfo.KnownType], jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments, fail);
+ return Create(info, context, isToJs, segment.KnownType, [segment.ElementTypeInfo.KnownType], jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments);
// span
case { TypeInfo: JSSpanTypeInfo span }:
- return Create(info, context, isToJs, span.KnownType, [span.ElementTypeInfo.KnownType], jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments, fail);
+ return Create(info, context, isToJs, span.KnownType, [span.ElementTypeInfo.KnownType], jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments);
// task
case { TypeInfo: JSTaskTypeInfo(JSSimpleTypeInfo(KnownManagedType.Void)) task }:
- return Create(info, context, isToJs, task.KnownType, [], jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments, fail);
+ return Create(info, context, isToJs, task.KnownType, [], jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments);
case { TypeInfo: JSTaskTypeInfo task }:
- return Create(info, context, isToJs, task.KnownType, [task.ResultTypeInfo.KnownType], jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments, fail);
+ return Create(info, context, isToJs, task.KnownType, [task.ResultTypeInfo.KnownType], jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments);
// action + function
case { TypeInfo: JSFunctionTypeInfo function }:
- return Create(info, context, isToJs, function.KnownType, function.ArgsTypeInfo.Select(a => a.KnownType).ToArray(), jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments, fail);
+ return Create(info, context, isToJs, function.KnownType, function.ArgsTypeInfo.Select(a => a.KnownType).ToArray(), jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments);
default:
- return ResolvedGenerator.NotSupported(info, context, new(info));
+ return new(ResolvedGenerator.NotSupported(info, context, new(info)), MarshalerType.None);
}
}
- internal static ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context, bool isToJs, KnownManagedType marshaledType, KnownManagedType[] argumentTypes, JSTypeFlags jsType, JSTypeFlags[] jsTypeArguments, Func failWithReason)
+ private static ResolvedGeneratorAndType Create(TypePositionInfo info, StubCodeContext context, bool isToJs, KnownManagedType marshaledType, KnownManagedType[] argumentTypes, JSTypeFlags jsType, JSTypeFlags[] jsTypeArguments)
{
- switch (marshaledType)
+ return (marshaledType, jsType, argumentTypes, jsTypeArguments) switch
{
+ // void
+ (KnownManagedType.Void, JSTypeFlags.Void, _, _) => resolved(new Forwarder().Bind(info, context), MarshalerType.Void),
+ (KnownManagedType.Void, JSTypeFlags.None or JSTypeFlags.Discard, _, _) => resolved(new Forwarder().Bind(info, context), MarshalerType.Discard),
+ (KnownManagedType.Void, JSTypeFlags.DiscardNoWait, _, _) => resolved(new Forwarder().Bind(info, context), MarshalerType.DiscardNoWait),
+
+ // void missing
+ (KnownManagedType.Void, JSTypeFlags.Missing, _, _) => resolved(new Forwarder().Bind(info, context), MarshalerType.Discard),
+
// primitive
- case KnownManagedType.Boolean when jsType == JSTypeFlags.Boolean: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Boolean));
- case KnownManagedType.Byte when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Byte));
- case KnownManagedType.Char when jsType == JSTypeFlags.String: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Char));
- case KnownManagedType.Int16 when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int16));
- case KnownManagedType.Int32 when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int32));
- case KnownManagedType.Int64 when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int52));
- case KnownManagedType.Int64 when jsType == JSTypeFlags.BigInt: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.BigInt64));
- case KnownManagedType.Single when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Single));
- case KnownManagedType.Double when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Double));
- case KnownManagedType.IntPtr when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.IntPtr));
- case KnownManagedType.DateTime when jsType == JSTypeFlags.Date: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.DateTime));
- case KnownManagedType.DateTimeOffset when jsType == JSTypeFlags.Date: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.DateTimeOffset));
- case KnownManagedType.Exception when jsType == JSTypeFlags.Error: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Exception));
- case KnownManagedType.JSObject when jsType == JSTypeFlags.Object: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.JSObject));
- case KnownManagedType.String when jsType == JSTypeFlags.String: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.String));
- case KnownManagedType.Object when jsType == JSTypeFlags.Any: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Object));
+ (KnownManagedType.Boolean, JSTypeFlags.Boolean, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Boolean), MarshalerType.Boolean),
+ (KnownManagedType.Byte, JSTypeFlags.Number, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Byte), MarshalerType.Byte),
+ (KnownManagedType.Char, JSTypeFlags.String, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Char), MarshalerType.Char),
+ (KnownManagedType.Int16, JSTypeFlags.Number, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int16), MarshalerType.Int16),
+ (KnownManagedType.Int32, JSTypeFlags.Number, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int32), MarshalerType.Int32),
+ (KnownManagedType.Int64, JSTypeFlags.Number, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int52), MarshalerType.Int52),
+ (KnownManagedType.Int64, JSTypeFlags.BigInt, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.BigInt64), MarshalerType.BigInt64),
+ (KnownManagedType.Single, JSTypeFlags.Number, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Single), MarshalerType.Single),
+ (KnownManagedType.Double, JSTypeFlags.Number, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Double), MarshalerType.Double),
+ (KnownManagedType.IntPtr, JSTypeFlags.Number, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.IntPtr), MarshalerType.IntPtr),
+ (KnownManagedType.DateTime, JSTypeFlags.Date, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.DateTime), MarshalerType.DateTime),
+ (KnownManagedType.DateTimeOffset, JSTypeFlags.Date, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.DateTimeOffset), MarshalerType.DateTimeOffset),
+ (KnownManagedType.Exception, JSTypeFlags.Error, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Exception), MarshalerType.Exception),
+ (KnownManagedType.JSObject, JSTypeFlags.Object, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.JSObject), MarshalerType.JSObject),
+ (KnownManagedType.String, JSTypeFlags.String, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.String), MarshalerType.String),
+ (KnownManagedType.Object, JSTypeFlags.Any, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Object), MarshalerType.Object),
// primitive missing
- case KnownManagedType.Boolean when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Boolean));
- case KnownManagedType.Byte when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Byte));
- case KnownManagedType.Char when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Char));
- case KnownManagedType.Int16 when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int16));
- case KnownManagedType.Int32 when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int32));
- case KnownManagedType.Single when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Single));
- case KnownManagedType.Double when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Double));
- case KnownManagedType.IntPtr when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.IntPtr));
- case KnownManagedType.Exception when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Exception));
- case KnownManagedType.JSObject when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.JSObject));
- case KnownManagedType.String when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.String));
+ (KnownManagedType.Boolean, JSTypeFlags.Missing, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Boolean), MarshalerType.Boolean),
+ (KnownManagedType.Byte, JSTypeFlags.Missing, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Byte), MarshalerType.Byte),
+ (KnownManagedType.Char, JSTypeFlags.Missing, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Char), MarshalerType.Char),
+ (KnownManagedType.Int16, JSTypeFlags.Missing, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int16), MarshalerType.Int16),
+ (KnownManagedType.Int32, JSTypeFlags.Missing, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int32), MarshalerType.Int32),
+ (KnownManagedType.Single, JSTypeFlags.Missing, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Single), MarshalerType.Single),
+ (KnownManagedType.Double, JSTypeFlags.Missing, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Double), MarshalerType.Double),
+ (KnownManagedType.IntPtr, JSTypeFlags.Missing, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.IntPtr), MarshalerType.IntPtr),
+ (KnownManagedType.Exception, JSTypeFlags.Missing, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Exception), MarshalerType.Exception),
+ (KnownManagedType.JSObject, JSTypeFlags.Missing, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.JSObject), MarshalerType.JSObject),
+ (KnownManagedType.String, JSTypeFlags.Missing, _, _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.String), MarshalerType.String),
// primitive forced
- case KnownManagedType.Int64 when jsType == JSTypeFlags.Missing:
- case KnownManagedType.DateTime when jsType == JSTypeFlags.Missing:
- case KnownManagedType.DateTimeOffset when jsType == JSTypeFlags.Missing:
- case KnownManagedType.Object when jsType == JSTypeFlags.Missing:
- return failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName));
+ (KnownManagedType.Int64, JSTypeFlags.Missing, _, _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
+ (KnownManagedType.DateTime, JSTypeFlags.Missing, _, _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
+ (KnownManagedType.DateTimeOffset, JSTypeFlags.Missing, _, _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
+ (KnownManagedType.Object, JSTypeFlags.Missing, _, _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
// nullable
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Boolean && jsType == JSTypeFlags.Boolean: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Boolean));
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Byte && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Byte));
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Char && jsType == JSTypeFlags.String: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Byte));
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int16 && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Int16));
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int32 && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Int32));
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int64 && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Int52));
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int64 && jsType == JSTypeFlags.BigInt: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.BigInt64));
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Double && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Double));
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Single && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Single));
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.IntPtr && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.IntPtr));
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.DateTime && jsType == JSTypeFlags.Date: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.DateTime));
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.DateTimeOffset && jsType == JSTypeFlags.Date: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.DateTimeOffset));
+ (KnownManagedType.Nullable, JSTypeFlags.Boolean, [KnownManagedType.Boolean], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Boolean), MarshalerType.Nullable, [MarshalerType.Boolean]),
+ (KnownManagedType.Nullable, JSTypeFlags.Number, [KnownManagedType.Byte], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Byte), MarshalerType.Nullable, [MarshalerType.Byte]),
+ (KnownManagedType.Nullable, JSTypeFlags.String, [KnownManagedType.Char], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Char), MarshalerType.Nullable, [MarshalerType.Char]),
+ (KnownManagedType.Nullable, JSTypeFlags.Number, [KnownManagedType.Int16], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int16), MarshalerType.Nullable, [MarshalerType.Int16]),
+ (KnownManagedType.Nullable, JSTypeFlags.Number, [KnownManagedType.Int32], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int32), MarshalerType.Nullable, [MarshalerType.Int32]),
+ (KnownManagedType.Nullable, JSTypeFlags.Number, [KnownManagedType.Int64], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int52), MarshalerType.Nullable, [MarshalerType.Int52]),
+ (KnownManagedType.Nullable, JSTypeFlags.BigInt, [KnownManagedType.Int64], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.BigInt64), MarshalerType.Nullable, [MarshalerType.BigInt64]),
+ (KnownManagedType.Nullable, JSTypeFlags.Number, [KnownManagedType.Single], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Single), MarshalerType.Nullable, [MarshalerType.Single]),
+ (KnownManagedType.Nullable, JSTypeFlags.Number, [KnownManagedType.Double], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Double), MarshalerType.Nullable, [MarshalerType.Double]),
+ (KnownManagedType.Nullable, JSTypeFlags.Number, [KnownManagedType.IntPtr], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.IntPtr), MarshalerType.Nullable, [MarshalerType.IntPtr]),
+ (KnownManagedType.Nullable, JSTypeFlags.Date, [KnownManagedType.DateTime], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.DateTime), MarshalerType.Nullable, [MarshalerType.DateTime]),
+ (KnownManagedType.Nullable, JSTypeFlags.Date, [KnownManagedType.DateTimeOffset], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.DateTimeOffset), MarshalerType.Nullable, [MarshalerType.DateTimeOffset]),
// nullable missing
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Boolean && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Boolean));
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Byte && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Byte));
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Char && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Byte));
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int16 && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Int16));
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int32 && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Int32));
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Single && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Single));
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Double && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Double));
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.IntPtr && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.IntPtr));
+ (KnownManagedType.Nullable, JSTypeFlags.Missing, [KnownManagedType.Boolean], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Boolean), MarshalerType.Nullable, [MarshalerType.Boolean]),
+ (KnownManagedType.Nullable, JSTypeFlags.Missing, [KnownManagedType.Byte], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Byte), MarshalerType.Nullable, [MarshalerType.Byte]),
+ (KnownManagedType.Nullable, JSTypeFlags.Missing, [KnownManagedType.Char], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Char), MarshalerType.Nullable, [MarshalerType.Char]),
+ (KnownManagedType.Nullable, JSTypeFlags.Missing, [KnownManagedType.Int16], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int16), MarshalerType.Nullable, [MarshalerType.Int16]),
+ (KnownManagedType.Nullable, JSTypeFlags.Missing, [KnownManagedType.Int32], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int32), MarshalerType.Nullable, [MarshalerType.Int32]),
+ (KnownManagedType.Nullable, JSTypeFlags.Missing, [KnownManagedType.Single], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Single), MarshalerType.Nullable, [MarshalerType.Single]),
+ (KnownManagedType.Nullable, JSTypeFlags.Missing, [KnownManagedType.Double], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Double), MarshalerType.Nullable, [MarshalerType.Double]),
+ (KnownManagedType.Nullable, JSTypeFlags.Missing, [KnownManagedType.IntPtr], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.IntPtr), MarshalerType.Nullable, [MarshalerType.IntPtr]),
// nullable forced
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int64 && jsType == JSTypeFlags.Missing:
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.DateTime && jsType == JSTypeFlags.Missing:
- case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.DateTimeOffset && jsType == JSTypeFlags.Missing:
- return failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName));
+ (KnownManagedType.Nullable, JSTypeFlags.Missing, [KnownManagedType.Int64], _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
+ (KnownManagedType.Nullable, JSTypeFlags.Missing, [KnownManagedType.DateTime], _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
+ (KnownManagedType.Nullable, JSTypeFlags.Missing, [KnownManagedType.DateTimeOffset], _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
+
+ (KnownManagedType.Nullable, _, _, _) => failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName)),
- case KnownManagedType.Nullable:
- return failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName));
// task
- case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes.Length == 0 && jsTypeArguments[0] == JSTypeFlags.Void: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Void));
- case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Byte && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Byte));
- case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Boolean && jsTypeArguments[0] == JSTypeFlags.Boolean: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Boolean));
- case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Char && jsTypeArguments[0] == JSTypeFlags.String: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Char));
- case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Int16 && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Int16));
- case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Int32 && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Int32));
- case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Int64 && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Int52));
- case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Int64 && jsTypeArguments[0] == JSTypeFlags.BigInt: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.BigInt64));
- case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.IntPtr && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.IntPtr));
- case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Double && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Double));
- case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Single && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Single));
- case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.JSObject && jsTypeArguments[0] == JSTypeFlags.Object: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.JSObject));
- case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.String && jsTypeArguments[0] == JSTypeFlags.String: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.String));
- case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Exception && jsTypeArguments[0] == JSTypeFlags.Error: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Exception));
- case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.DateTime && jsTypeArguments[0] == JSTypeFlags.Date: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.DateTime));
- case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.DateTimeOffset && jsTypeArguments[0] == JSTypeFlags.Date: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.DateTimeOffset));
- case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Object && jsTypeArguments[0] == JSTypeFlags.Any: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Object));
+ (KnownManagedType.Task, JSTypeFlags.Promise, [], [JSTypeFlags.Void]) => resolved(new TaskJSGenerator(info, context, MarshalerType.Void), MarshalerType.Task, []),
+ (KnownManagedType.Task, JSTypeFlags.Promise, [KnownManagedType.Boolean], [JSTypeFlags.Boolean]) => resolved(new TaskJSGenerator(info, context, MarshalerType.Boolean), MarshalerType.Task, [MarshalerType.Boolean]),
+ (KnownManagedType.Task, JSTypeFlags.Promise, [KnownManagedType.Byte], [JSTypeFlags.Number]) => resolved(new TaskJSGenerator(info, context, MarshalerType.Byte), MarshalerType.Task, [MarshalerType.Byte]),
+ (KnownManagedType.Task, JSTypeFlags.Promise, [KnownManagedType.Char], [JSTypeFlags.String]) => resolved(new TaskJSGenerator(info, context, MarshalerType.Char), MarshalerType.Task, [MarshalerType.Char]),
+ (KnownManagedType.Task, JSTypeFlags.Promise, [KnownManagedType.Int16], [JSTypeFlags.Number]) => resolved(new TaskJSGenerator(info, context, MarshalerType.Int16), MarshalerType.Task, [MarshalerType.Int16]),
+ (KnownManagedType.Task, JSTypeFlags.Promise, [KnownManagedType.Int32], [JSTypeFlags.Number]) => resolved(new TaskJSGenerator(info, context, MarshalerType.Int32), MarshalerType.Task, [MarshalerType.Int32]),
+ (KnownManagedType.Task, JSTypeFlags.Promise, [KnownManagedType.Int64], [JSTypeFlags.Number]) => resolved(new TaskJSGenerator(info, context, MarshalerType.Int52), MarshalerType.Task, [MarshalerType.Int52]),
+ (KnownManagedType.Task, JSTypeFlags.Promise, [KnownManagedType.Int64], [JSTypeFlags.BigInt]) => resolved(new TaskJSGenerator(info, context, MarshalerType.BigInt64), MarshalerType.Task, [MarshalerType.BigInt64]),
+ (KnownManagedType.Task, JSTypeFlags.Promise, [KnownManagedType.Single], [JSTypeFlags.Number]) => resolved(new TaskJSGenerator(info, context, MarshalerType.Single), MarshalerType.Task, [MarshalerType.Single]),
+ (KnownManagedType.Task, JSTypeFlags.Promise, [KnownManagedType.Double], [JSTypeFlags.Number]) => resolved(new TaskJSGenerator(info, context, MarshalerType.Double), MarshalerType.Task, [MarshalerType.Double]),
+ (KnownManagedType.Task, JSTypeFlags.Promise, [KnownManagedType.IntPtr], [JSTypeFlags.Number]) => resolved(new TaskJSGenerator(info, context, MarshalerType.IntPtr), MarshalerType.Task, [MarshalerType.IntPtr]),
+ (KnownManagedType.Task, JSTypeFlags.Promise, [KnownManagedType.DateTime], [JSTypeFlags.Date]) => resolved(new TaskJSGenerator(info, context, MarshalerType.DateTime), MarshalerType.Task, [MarshalerType.DateTime]),
+ (KnownManagedType.Task, JSTypeFlags.Promise, [KnownManagedType.DateTimeOffset], [JSTypeFlags.Date]) => resolved(new TaskJSGenerator(info, context, MarshalerType.DateTimeOffset), MarshalerType.Task, [MarshalerType.DateTimeOffset]),
+ (KnownManagedType.Task, JSTypeFlags.Promise, [KnownManagedType.Exception], [JSTypeFlags.Error]) => resolved(new TaskJSGenerator(info, context, MarshalerType.Exception), MarshalerType.Task, [MarshalerType.Exception]),
+ (KnownManagedType.Task, JSTypeFlags.Promise, [KnownManagedType.JSObject], [JSTypeFlags.Object]) => resolved(new TaskJSGenerator(info, context, MarshalerType.JSObject), MarshalerType.Task, [MarshalerType.JSObject]),
+ (KnownManagedType.Task, JSTypeFlags.Promise, [KnownManagedType.String], [JSTypeFlags.String]) => resolved(new TaskJSGenerator(info, context, MarshalerType.String), MarshalerType.Task, [MarshalerType.String]),
+ (KnownManagedType.Task, JSTypeFlags.Promise, [KnownManagedType.Object], [JSTypeFlags.Any]) => resolved(new TaskJSGenerator(info, context, MarshalerType.Object), MarshalerType.Task, [MarshalerType.Object]),
// task missing
- case KnownManagedType.Task when jsType == JSTypeFlags.Missing && argumentTypes.Length == 0: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Void));
- case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Boolean && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Boolean));
- case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Byte && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Byte));
- case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Char && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Char));
- case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Int16 && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Int16));
- case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Int32 && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Int32));
- case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Single && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Single));
- case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Double && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Double));
- case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.IntPtr && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.IntPtr));
- case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.JSObject && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.JSObject));
- case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.String && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.String));
- case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Exception && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Exception));
+ (KnownManagedType.Task, JSTypeFlags.Missing, [], _) => resolved(new TaskJSGenerator(info, context, MarshalerType.Void), MarshalerType.Task, []),
+ (KnownManagedType.Task, JSTypeFlags.Missing, [KnownManagedType.Boolean], _) => resolved(new TaskJSGenerator(info, context, MarshalerType.Boolean), MarshalerType.Task, [MarshalerType.Boolean]),
+ (KnownManagedType.Task, JSTypeFlags.Missing, [KnownManagedType.Byte], _) => resolved(new TaskJSGenerator(info, context, MarshalerType.Byte), MarshalerType.Task, [MarshalerType.Byte]),
+ (KnownManagedType.Task, JSTypeFlags.Missing, [KnownManagedType.Char], _) => resolved(new TaskJSGenerator(info, context, MarshalerType.Char), MarshalerType.Task, [MarshalerType.Char]),
+ (KnownManagedType.Task, JSTypeFlags.Missing, [KnownManagedType.Int16], _) => resolved(new TaskJSGenerator(info, context, MarshalerType.Int16), MarshalerType.Task, [MarshalerType.Int16]),
+ (KnownManagedType.Task, JSTypeFlags.Missing, [KnownManagedType.Int32], _) => resolved(new TaskJSGenerator(info, context, MarshalerType.Int32), MarshalerType.Task, [MarshalerType.Int32]),
+ (KnownManagedType.Task, JSTypeFlags.Missing, [KnownManagedType.Single], _) => resolved(new TaskJSGenerator(info, context, MarshalerType.Single), MarshalerType.Task, [MarshalerType.Single]),
+ (KnownManagedType.Task, JSTypeFlags.Missing, [KnownManagedType.Double], _) => resolved(new TaskJSGenerator(info, context, MarshalerType.Double), MarshalerType.Task, [MarshalerType.Double]),
+ (KnownManagedType.Task, JSTypeFlags.Missing, [KnownManagedType.IntPtr], _) => resolved(new TaskJSGenerator(info, context, MarshalerType.IntPtr), MarshalerType.Task, [MarshalerType.IntPtr]),
+ (KnownManagedType.Task, JSTypeFlags.Missing, [KnownManagedType.Exception], _) => resolved(new TaskJSGenerator(info, context, MarshalerType.Exception), MarshalerType.Task, [MarshalerType.Exception]),
+ (KnownManagedType.Task, JSTypeFlags.Missing, [KnownManagedType.JSObject], _) => resolved(new TaskJSGenerator(info, context, MarshalerType.JSObject), MarshalerType.Task, [MarshalerType.JSObject]),
+ (KnownManagedType.Task, JSTypeFlags.Missing, [KnownManagedType.String], _) => resolved(new TaskJSGenerator(info, context, MarshalerType.String), MarshalerType.Task, [MarshalerType.String]),
// task forced
- case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Int64 && jsType == JSTypeFlags.Missing:
- case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.DateTime && jsType == JSTypeFlags.Missing:
- case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.DateTimeOffset && jsType == JSTypeFlags.Missing:
- case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Object && jsType == JSTypeFlags.Missing:
- return failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName));
+ (KnownManagedType.Task, JSTypeFlags.Missing, [KnownManagedType.Int64], _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
+ (KnownManagedType.Task, JSTypeFlags.Missing, [KnownManagedType.DateTime], _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
+ (KnownManagedType.Task, JSTypeFlags.Missing, [KnownManagedType.DateTimeOffset], _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
+ (KnownManagedType.Task, JSTypeFlags.Missing, [KnownManagedType.Object], _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
- case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1:
- return failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName));
+ (KnownManagedType.Task, JSTypeFlags.Promise, _, [_]) => failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName)),
// array
- case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Byte && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.Byte));
- case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.String && jsTypeArguments[0] == JSTypeFlags.String: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.String));
- case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Double && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.Double));
- case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Int32 && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.Int32));
- case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.JSObject && jsTypeArguments[0] == JSTypeFlags.Object: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.JSObject));
- case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Object && jsTypeArguments[0] == JSTypeFlags.Any: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.Object));
+ (KnownManagedType.Array, JSTypeFlags.Array, [KnownManagedType.Byte], [JSTypeFlags.Number]) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.Byte]),
+ (KnownManagedType.Array, JSTypeFlags.Array, [KnownManagedType.String], [JSTypeFlags.String]) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.String]),
+ (KnownManagedType.Array, JSTypeFlags.Array, [KnownManagedType.Double], [JSTypeFlags.Number]) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.Double]),
+ (KnownManagedType.Array, JSTypeFlags.Array, [KnownManagedType.Int32], [JSTypeFlags.Number]) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.Int32]),
+ (KnownManagedType.Array, JSTypeFlags.Array, [KnownManagedType.JSObject], [JSTypeFlags.Object]) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.JSObject]),
+ (KnownManagedType.Array, JSTypeFlags.Array, [KnownManagedType.Object], [JSTypeFlags.Any]) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.Object]),
// array missing
- case KnownManagedType.Array when argumentTypes[0] == KnownManagedType.Byte && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.Byte));
- case KnownManagedType.Array when argumentTypes[0] == KnownManagedType.String && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.String));
- case KnownManagedType.Array when argumentTypes[0] == KnownManagedType.Double && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.Double));
- case KnownManagedType.Array when argumentTypes[0] == KnownManagedType.Int32 && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.Int32));
- case KnownManagedType.Array when argumentTypes[0] == KnownManagedType.JSObject && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.JSObject));
- case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1:
- return failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName));
+ (KnownManagedType.Array, JSTypeFlags.Missing, [KnownManagedType.Byte], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.Byte]),
+ (KnownManagedType.Array, JSTypeFlags.Missing, [KnownManagedType.String], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.String]),
+ (KnownManagedType.Array, JSTypeFlags.Missing, [KnownManagedType.Double], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.Double]),
+ (KnownManagedType.Array, JSTypeFlags.Missing, [KnownManagedType.Int32], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.Int32]),
+ (KnownManagedType.Array, JSTypeFlags.Missing, [KnownManagedType.JSObject], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.JSObject]),
+
+ (KnownManagedType.Array, JSTypeFlags.Array, _, [_]) => failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName)),
// array forced
- case KnownManagedType.Array when argumentTypes[0] == KnownManagedType.Object && jsType == JSTypeFlags.Missing:
- return failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName));
+ (KnownManagedType.Array, JSTypeFlags.Missing, [KnownManagedType.Object], _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
// span view
- case KnownManagedType.Span when jsType == JSTypeFlags.MemoryView && jsTypeArguments.Length != 0:
- return failWithReason(null);
- case KnownManagedType.Span when jsType == JSTypeFlags.MemoryView && argumentTypes[0] == KnownManagedType.Byte: return ResolvedGenerator.Resolved(new SpanJSGenerator(info, context, MarshalerType.Byte));
- case KnownManagedType.Span when jsType == JSTypeFlags.MemoryView && argumentTypes[0] == KnownManagedType.Int32: return ResolvedGenerator.Resolved(new SpanJSGenerator(info, context, MarshalerType.Int32));
- case KnownManagedType.Span when jsType == JSTypeFlags.MemoryView && argumentTypes[0] == KnownManagedType.Double: return ResolvedGenerator.Resolved(new SpanJSGenerator(info, context, MarshalerType.Double));
+ (KnownManagedType.Span, JSTypeFlags.MemoryView, _, [_]) => failWithReason(null!),
+ (KnownManagedType.Span, JSTypeFlags.MemoryView, [KnownManagedType.Byte], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Span), MarshalerType.Span, [MarshalerType.Byte]),
+ (KnownManagedType.Span, JSTypeFlags.MemoryView, [KnownManagedType.Int32], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Span), MarshalerType.Span, [MarshalerType.Int32]),
+ (KnownManagedType.Span, JSTypeFlags.MemoryView, [KnownManagedType.Double], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Span), MarshalerType.Span, [MarshalerType.Double]),
- case KnownManagedType.Span when jsType == JSTypeFlags.MemoryView:
- return failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName));
+ (KnownManagedType.Span, JSTypeFlags.MemoryView, _, _) => failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName)),
// span forced
- case KnownManagedType.Span when argumentTypes[0] == KnownManagedType.Byte && jsType == JSTypeFlags.Missing:
- case KnownManagedType.Span when argumentTypes[0] == KnownManagedType.Int32 && jsType == JSTypeFlags.Missing:
- case KnownManagedType.Span when argumentTypes[0] == KnownManagedType.Double && jsType == JSTypeFlags.Missing:
- return failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName));
+ (KnownManagedType.Span, JSTypeFlags.Missing, [KnownManagedType.Byte], _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
+ (KnownManagedType.Span, JSTypeFlags.Missing, [KnownManagedType.Int32], _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
+ (KnownManagedType.Span, JSTypeFlags.Missing, [KnownManagedType.Double], _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
// segment view
- case KnownManagedType.ArraySegment when jsType == JSTypeFlags.MemoryView && jsTypeArguments.Length != 0:
- return failWithReason(null);
- case KnownManagedType.ArraySegment when jsType == JSTypeFlags.MemoryView && argumentTypes[0] == KnownManagedType.Byte: return ResolvedGenerator.Resolved(new ArraySegmentJSGenerator(info, context, MarshalerType.Byte));
- case KnownManagedType.ArraySegment when jsType == JSTypeFlags.MemoryView && argumentTypes[0] == KnownManagedType.Int32: return ResolvedGenerator.Resolved(new ArraySegmentJSGenerator(info, context, MarshalerType.Int32));
- case KnownManagedType.ArraySegment when jsType == JSTypeFlags.MemoryView && argumentTypes[0] == KnownManagedType.Double: return ResolvedGenerator.Resolved(new ArraySegmentJSGenerator(info, context, MarshalerType.Double));
- case KnownManagedType.ArraySegment when jsType == JSTypeFlags.MemoryView:
- return failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName));
+ (KnownManagedType.ArraySegment, JSTypeFlags.MemoryView, _, [_]) => failWithReason(null!),
+ (KnownManagedType.ArraySegment, JSTypeFlags.MemoryView, [KnownManagedType.Byte], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.ArraySegment), MarshalerType.ArraySegment, [MarshalerType.Byte]),
+ (KnownManagedType.ArraySegment, JSTypeFlags.MemoryView, [KnownManagedType.Int32], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.ArraySegment), MarshalerType.ArraySegment, [MarshalerType.Int32]),
+ (KnownManagedType.ArraySegment, JSTypeFlags.MemoryView, [KnownManagedType.Double], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.ArraySegment), MarshalerType.ArraySegment, [MarshalerType.Double]),
+
+ (KnownManagedType.ArraySegment, JSTypeFlags.MemoryView, _, _) => failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName)),
// segment forced
- case KnownManagedType.ArraySegment when argumentTypes[0] == KnownManagedType.Byte && jsType == JSTypeFlags.Missing:
- case KnownManagedType.ArraySegment when argumentTypes[0] == KnownManagedType.Int32 && jsType == JSTypeFlags.Missing:
- case KnownManagedType.ArraySegment when argumentTypes[0] == KnownManagedType.Double && jsType == JSTypeFlags.Missing:
- return failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName));
+ (KnownManagedType.ArraySegment, JSTypeFlags.Missing, [KnownManagedType.Byte], _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
+ (KnownManagedType.ArraySegment, JSTypeFlags.Missing, [KnownManagedType.Int32], _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
+ (KnownManagedType.ArraySegment, JSTypeFlags.Missing, [KnownManagedType.Double], _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
// function + action
- case KnownManagedType.Function when jsType == JSTypeFlags.Function && jsTypeArguments.Length == argumentTypes.Length:
- case KnownManagedType.Action when jsType == JSTypeFlags.Function && jsTypeArguments.Length == argumentTypes.Length:
- var argsMarshalers = new List();
- for (int i = 0; i < argumentTypes.Length; i++)
- {
- var isReturn = marshaledType == KnownManagedType.Function && i == jsTypeArguments.Length - 1;
- if (argumentTypes[i] == KnownManagedType.Array
- || argumentTypes[i] == KnownManagedType.Span
- || argumentTypes[i] == KnownManagedType.ArraySegment
- || argumentTypes[i] == KnownManagedType.Task
- || argumentTypes[i] == KnownManagedType.Function
- || argumentTypes[i] == KnownManagedType.Action
- || argumentTypes[i] == KnownManagedType.Unknown
- )
- {
- return failWithReason(SR.Format(SR.FuncArgumentNotSupported, argumentTypes[i]));
- }
- var gen = Create(info, context, isToJs ^ (!isReturn), argumentTypes[i], Array.Empty(), jsTypeArguments[i], Array.Empty(), failWithReason);
- argsMarshalers.Add(((BaseJSGenerator)gen.Generator).Type);
- }
- var maxArgs = marshaledType == KnownManagedType.Action ? 3 : 4;
- var argsMarshallerTypes = argsMarshalers.ToArray();
- if (argsMarshallerTypes.Length > maxArgs)
- {
- return failWithReason(SR.FuncTooManyArgs);
- }
- return ResolvedGenerator.Resolved(new FuncJSGenerator(info, context, marshaledType == KnownManagedType.Action, argsMarshallerTypes));
- case KnownManagedType.Action when jsType == JSTypeFlags.Function:
- case KnownManagedType.Function when jsType == JSTypeFlags.Function:
- return failWithReason(SR.FuncWrongArgumentCount);
+ (KnownManagedType.Function or KnownManagedType.Action, JSTypeFlags.Function, var argTypes, var argJSTypes) when argTypes.Length != argJSTypes.Length
+ => failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName)),
+
+ (KnownManagedType.Function or KnownManagedType.Action, JSTypeFlags.Function or JSTypeFlags.Missing, var argTypes, _) when FindFirstInvalidArgType(argTypes) is KnownManagedType invalidArgType
+ => failWithReason(SR.Format(SR.FuncArgumentNotSupported, invalidArgType)),
+
+ (KnownManagedType.Function or KnownManagedType.Action, JSTypeFlags.Function, var argTypes, var argJSTypes) => ResolveCallback(marshaledType, argTypes, argJSTypes),
// function + action forced
- case KnownManagedType.Function when jsType == JSTypeFlags.Missing:
- case KnownManagedType.Action when jsType == JSTypeFlags.Missing:
- for (int i = 0; i < argumentTypes.Length; i++)
+ (KnownManagedType.Function or KnownManagedType.Action, JSTypeFlags.Missing, _, _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
+
+ // void only JSType on non-void
+ (not KnownManagedType.Void, JSTypeFlags.Discard, _, _) => failWithReason(SR.DiscardOnlyVoid),
+ (not KnownManagedType.Void, JSTypeFlags.DiscardNoWait, _, _) => failWithReason(SR.DiscardNoWaitOnlyVoid),
+
+
+ _ => failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName)),
+ };
+
+ KnownManagedType? FindFirstInvalidArgType(KnownManagedType[] argumentTypes)
+ {
+ foreach (KnownManagedType type in argumentTypes)
+ {
+ if (type is KnownManagedType.Array
+ or KnownManagedType.Span
+ or KnownManagedType.ArraySegment
+ or KnownManagedType.Task
+ or KnownManagedType.Function
+ or KnownManagedType.Action
+ or KnownManagedType.Unknown
+ )
{
- if (argumentTypes[i] == KnownManagedType.Array
- || argumentTypes[i] == KnownManagedType.Span
- || argumentTypes[i] == KnownManagedType.ArraySegment
- || argumentTypes[i] == KnownManagedType.Task
- || argumentTypes[i] == KnownManagedType.Function
- || argumentTypes[i] == KnownManagedType.Action
- || argumentTypes[i] == KnownManagedType.Unknown
- )
- {
- return failWithReason(SR.Format(SR.FuncArgumentNotSupported, argumentTypes[i]));
- }
+ return type;
}
- return failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName));
+ }
+ return null;
+ }
- default:
- return failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName));
+ ResolvedGeneratorAndType ResolveCallback(KnownManagedType managedType, KnownManagedType[] argTypes, JSTypeFlags[] argJSTypes)
+ {
+ var argsMarshalers = new List();
+ for (int i = 0; i < argTypes.Length; i++)
+ {
+ var isReturn = managedType == KnownManagedType.Function && i == argJSTypes.Length - 1;
+
+ var gen = Create(info, context, isToJs ^ (!isReturn), argTypes[i], Array.Empty(), argJSTypes[i], Array.Empty());
+ argsMarshalers.Add(gen.Type);
+ }
+ var maxArgs = managedType == KnownManagedType.Action ? 3 : 4;
+ MarshalerType[] argsMarshallerTypes = [.. argsMarshalers];
+ if (argsMarshallerTypes.Length > maxArgs)
+ {
+ return failWithReason(SR.FuncTooManyArgs);
+ }
+ return resolved(
+ new FuncJSGenerator(info, context, managedType == KnownManagedType.Action, argsMarshallerTypes),
+ managedType == KnownManagedType.Action ? MarshalerType.Action : MarshalerType.Function,
+ argsMarshallerTypes);
+ }
+
+ ResolvedGeneratorAndType failWithReason(string failReason)
+ {
+ return new(
+ ResolvedGenerator.NotSupported(info, context, new(info)
+ {
+ NotSupportedDetails = failReason
+ }),
+ MarshalerType.None);
+ }
+
+ ResolvedGeneratorAndType resolved(IBoundMarshallingGenerator generator, MarshalerType baseType, IEnumerable? subTypes = null)
+ {
+ return new(ResolvedGenerator.Resolved(generator), baseType, subTypes);
}
}
}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs
deleted file mode 100644
index 7891bec53f2186..00000000000000
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs
+++ /dev/null
@@ -1,212 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.Linq;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-using Microsoft.CodeAnalysis;
-
-namespace Microsoft.Interop.JavaScript
-{
- internal abstract class JSCodeGenerator
- {
- public const string ReturnIdentifier = "__retVal";
- public const string ReturnNativeIdentifier = $"{ReturnIdentifier}{StubIdentifierContext.GeneratedNativeIdentifierSuffix}";
- public const string InvokeSucceededIdentifier = "__invokeSucceeded";
- }
-
- internal sealed class JSImportCodeGenerator : JSCodeGenerator
- {
- private readonly BoundGenerators _marshallers;
-
- private readonly StubIdentifierContext _context;
- private readonly JSImportData _jsImportData;
- private readonly JSSignatureContext _signatureContext;
-
- public JSImportCodeGenerator(
- ImmutableArray argTypes,
- JSImportData attributeData,
- JSSignatureContext signatureContext,
- GeneratorDiagnosticsBag diagnosticsBag,
- IMarshallingGeneratorResolver generatorResolver)
- {
- _jsImportData = attributeData;
- _signatureContext = signatureContext;
-
- _marshallers = BoundGenerators.Create(argTypes, generatorResolver, StubCodeContext.DefaultManagedToNativeStub, new EmptyJSGenerator(), out var bindingFailures);
-
- diagnosticsBag.ReportGeneratorDiagnostics(bindingFailures);
-
- if (_marshallers.ManagedReturnMarshaller.UsesNativeIdentifier)
- {
- // If we need a different native return identifier, then recreate the context with the correct identifier before we generate any code.
- _context = new DefaultIdentifierContext(ReturnIdentifier, ReturnNativeIdentifier, MarshalDirection.ManagedToUnmanaged)
- {
- CodeEmitOptions = new(SkipInit: true)
- };
- }
- else
- {
- _context = new DefaultIdentifierContext(ReturnIdentifier, ReturnIdentifier, MarshalDirection.ManagedToUnmanaged)
- {
- CodeEmitOptions = new(SkipInit: true)
- };
- }
-
- // validate task + span mix
- if (_marshallers.ManagedReturnMarshaller.TypeInfo.MarshallingAttributeInfo is JSMarshallingInfo(_, JSTaskTypeInfo))
- {
- IBoundMarshallingGenerator spanArg = _marshallers.SignatureMarshallers.FirstOrDefault(m => m.TypeInfo.MarshallingAttributeInfo is JSMarshallingInfo(_, JSSpanTypeInfo));
- if (spanArg != default)
- {
- diagnosticsBag.ReportGeneratorDiagnostic(new GeneratorDiagnostic.NotSupported(spanArg.TypeInfo)
- {
- NotSupportedDetails = SR.SpanAndTaskNotSupported
- });
- }
- }
- }
-
- public BlockSyntax GenerateJSImportBody()
- {
- StatementSyntax invoke = InvokeSyntax();
- GeneratedStatements statements = GeneratedStatements.Create(_marshallers, _context);
- bool shouldInitializeVariables = !statements.GuaranteedUnmarshal.IsEmpty || !statements.CleanupCallerAllocated.IsEmpty || !statements.CleanupCalleeAllocated.IsEmpty;
- VariableDeclarations declarations = VariableDeclarations.GenerateDeclarationsForManagedToUnmanaged(_marshallers, _context, shouldInitializeVariables);
-
- var setupStatements = new List();
- BindSyntax(setupStatements);
- SetupSyntax(setupStatements);
-
- if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty))
- {
- setupStatements.Add(SyntaxFactoryExtensions.Declare(PredefinedType(Token(SyntaxKind.BoolKeyword)), InvokeSucceededIdentifier, initializeToDefault: true));
- }
-
- setupStatements.AddRange(declarations.Initializations);
- setupStatements.AddRange(declarations.Variables);
- setupStatements.AddRange(statements.Setup);
-
- var tryStatements = new List();
- tryStatements.AddRange(statements.Marshal);
- tryStatements.AddRange(statements.PinnedMarshal);
-
- tryStatements.Add(invoke);
- if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty))
- {
- tryStatements.Add(ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
- IdentifierName(InvokeSucceededIdentifier),
- LiteralExpression(SyntaxKind.TrueLiteralExpression))));
- }
-
- tryStatements.AddRange(statements.NotifyForSuccessfulInvoke);
- tryStatements.AddRange(statements.Unmarshal);
-
- List allStatements = setupStatements;
- List finallyStatements = new List();
- if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty))
- {
- finallyStatements.Add(IfStatement(IdentifierName(InvokeSucceededIdentifier), Block(statements.GuaranteedUnmarshal.Concat(statements.CleanupCalleeAllocated))));
- }
-
- finallyStatements.AddRange(statements.CleanupCallerAllocated);
- if (finallyStatements.Count > 0)
- {
- // Add try-finally block if there are any statements in the finally block
- allStatements.Add(
- TryStatement(Block(tryStatements), default, FinallyClause(Block(finallyStatements))));
- }
- else
- {
- allStatements.AddRange(tryStatements);
- }
-
- // Return
- if (!_marshallers.IsManagedVoidReturn)
- allStatements.Add(ReturnStatement(IdentifierName(_context.GetIdentifiers(_marshallers.ManagedReturnMarshaller.TypeInfo).managed)));
-
- return Block(allStatements);
- }
-
- private void BindSyntax(List statementsToUpdate)
- {
- var bindingParameters =
- (new ArgumentSyntax[] {
- Argument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(_jsImportData.FunctionName))),
- Argument(
- _jsImportData.ModuleName == null
- ? LiteralExpression(SyntaxKind.NullLiteralExpression)
- : LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(_jsImportData.ModuleName))),
- CreateSignaturesSyntax(),
- });
-
- statementsToUpdate.Add(IfStatement(BinaryExpression(SyntaxKind.EqualsExpression, IdentifierName(_signatureContext.BindingName), LiteralExpression(SyntaxKind.NullLiteralExpression)),
- Block(SingletonList(
- ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
- IdentifierName(_signatureContext.BindingName),
- InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(Constants.JSFunctionSignatureGlobal), IdentifierName(Constants.BindJSFunctionMethod)))
- .WithArgumentList(ArgumentList(SeparatedList(bindingParameters)))))))));
- }
-
- private ArgumentSyntax CreateSignaturesSyntax()
- {
- IEnumerable types = _marshallers.ManagedReturnMarshaller is IJSMarshallingGenerator jsGen ? jsGen.GenerateBind() : [];
- types = types
- .Concat(_marshallers.NativeParameterMarshallers.OfType().SelectMany(p => p.GenerateBind()));
-
- return Argument(ArrayCreationExpression(ArrayType(IdentifierName(Constants.JSMarshalerTypeGlobal))
- .WithRankSpecifiers(SingletonList(ArrayRankSpecifier(SingletonSeparatedList(OmittedArraySizeExpression())))))
- .WithInitializer(InitializerExpression(SyntaxKind.ArrayInitializerExpression, SeparatedList(types))));
- }
-
- private void SetupSyntax(List statementsToUpdate)
- {
- statementsToUpdate.Add(LocalDeclarationStatement(
- VariableDeclaration(GenericName(Identifier(Constants.SpanGlobal)).WithTypeArgumentList(
- TypeArgumentList(SingletonSeparatedList(IdentifierName(Constants.JSMarshalerArgumentGlobal)))))
- .WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier(Constants.ArgumentsBuffer))
- .WithInitializer(EqualsValueClause(StackAllocArrayCreationExpression(ArrayType(IdentifierName(Constants.JSMarshalerArgumentGlobal))
- .WithRankSpecifiers(SingletonList(ArrayRankSpecifier(SingletonSeparatedList(
- LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(2 + _marshallers.NativeParameterMarshallers.Length)))))))))))));
-
- statementsToUpdate.Add(LocalDeclarationStatement(VariableDeclaration(RefType(IdentifierName(Constants.JSMarshalerArgumentGlobal)))
- .WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier(Constants.ArgumentException))
- .WithInitializer(EqualsValueClause(RefExpression(ElementAccessExpression(IdentifierName(Constants.ArgumentsBuffer))
- .WithArgumentList(BracketedArgumentList(SingletonSeparatedList(
- Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0)))))))))))));
-
- statementsToUpdate.Add(ExpressionStatement(
- InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(Constants.ArgumentException), IdentifierName("Initialize")))));
-
- statementsToUpdate.Add(LocalDeclarationStatement(VariableDeclaration(RefType(IdentifierName(Constants.JSMarshalerArgumentGlobal)))
- .WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier(Constants.ArgumentReturn))
- .WithInitializer(EqualsValueClause(RefExpression(ElementAccessExpression(IdentifierName(Constants.ArgumentsBuffer))
- .WithArgumentList(BracketedArgumentList(SingletonSeparatedList(
- Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(1)))))))))))));
-
- statementsToUpdate.Add(ExpressionStatement(
- InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(Constants.ArgumentReturn), IdentifierName("Initialize")))));
- }
-
- private ExpressionStatementSyntax InvokeSyntax()
- {
- return ExpressionStatement(InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName(Constants.JSFunctionSignatureGlobal), IdentifierName("InvokeJS")))
- .WithArgumentList(ArgumentList(SeparatedList(new[]{
- Argument(IdentifierName(_signatureContext.BindingName)),
- Argument(IdentifierName(Constants.ArgumentsBuffer))}))));
- }
-
- public (ParameterListSyntax ParameterList, TypeSyntax ReturnType, AttributeListSyntax? ReturnTypeAttributes) GenerateTargetMethodSignatureData()
- {
- return _marshallers.GenerateTargetMethodSignatureData(_context);
- }
- }
-}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs
index c97f6998de9e69..a92ed80b5dd732 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs
@@ -2,14 +2,17 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
+using System.Runtime.InteropServices.JavaScript;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+using static Microsoft.Interop.SyntaxFactoryExtensions;
[assembly: System.Resources.NeutralResourcesLanguage("en-US")]
@@ -198,17 +201,162 @@ private static (MemberDeclarationSyntax, ImmutableArray) Generat
{
var diagnostics = new GeneratorDiagnosticsBag(new DescriptorProvider(), incrementalContext.DiagnosticLocation, SR.ResourceManager, typeof(FxResources.Microsoft.Interop.JavaScript.JSImportGenerator.SR));
+ // We need to add the implicit exception and return arguments to the signature and ensure they are initialized before we start to do any marshalling.
+ const int NumImplicitArguments = 2;
+
+ ImmutableArray originalElementInfo = incrementalContext.SignatureContext.SignatureContext.ElementTypeInformation;
+
+ ImmutableArray.Builder typeInfoBuilder = ImmutableArray.CreateBuilder(originalElementInfo.Length + NumImplicitArguments);
+
+ TypePositionInfo nativeOnlyParameterTemplate = new TypePositionInfo(
+ SpecialTypeInfo.Void,
+ new JSMarshallingInfo(
+ NoMarshallingInfo.Instance,
+ new JSInvalidTypeInfo()))
+ {
+ ManagedIndex = TypePositionInfo.UnsetIndex,
+ };
+
+ typeInfoBuilder.Add(
+ // Add the exception argument
+ nativeOnlyParameterTemplate with
+ {
+ InstanceIdentifier = Constants.ArgumentException,
+ NativeIndex = 0,
+ });
+
+ typeInfoBuilder.Add(
+ // Add the incoming return argument
+ nativeOnlyParameterTemplate with
+ {
+ InstanceIdentifier = Constants.ArgumentReturn,
+ NativeIndex = 1,
+ });
+
+ bool hasReturn = false;
+
+ foreach (var info in originalElementInfo)
+ {
+ TypePositionInfo updatedInfo = info with
+ {
+ MarshallingAttributeInfo = info.MarshallingAttributeInfo is JSMarshallingInfo jsInfo
+ ? jsInfo.AddElementDependencies([typeInfoBuilder[0], typeInfoBuilder[1]])
+ : info.MarshallingAttributeInfo,
+ };
+
+ if (info.IsManagedReturnPosition)
+ {
+ hasReturn = info.ManagedType != SpecialTypeInfo.Void;
+ }
+
+ if (info.IsNativeReturnPosition)
+ {
+ typeInfoBuilder.Add(updatedInfo);
+ }
+ else
+ {
+ typeInfoBuilder.Add(updatedInfo with
+ {
+ NativeIndex = updatedInfo.NativeIndex + NumImplicitArguments
+ });
+ }
+ }
+
+ ImmutableArray finalElementInfo = typeInfoBuilder.ToImmutable();
+
// Generate stub code
- var stubGenerator = new JSImportCodeGenerator(
- incrementalContext.SignatureContext.SignatureContext.ElementTypeInformation,
+ var stubGenerator = new ManagedToNativeStubGenerator(
+ finalElementInfo,
+ setLastError: false,
+ diagnostics,
+ new CompositeMarshallingGeneratorResolver(
+ new NoSpanAndTaskMixingResolver(),
+ new JSGeneratorResolver()),
+ new CodeEmitOptions(SkipInit: true));
+
+ const string LocalFunctionName = "__InvokeJSFunction";
+
+ BlockSyntax code = stubGenerator.GenerateStubBody(LocalFunctionName);
+
+ StatementSyntax bindStatement = GenerateBindSyntax(
incrementalContext.JSImportData,
incrementalContext.SignatureContext,
- diagnostics,
- new JSGeneratorResolver());
+ SignatureBindingHelpers.CreateSignaturesArgument(incrementalContext.SignatureContext.SignatureContext.ElementTypeInformation, StubCodeContext.DefaultManagedToNativeStub));
- BlockSyntax code = stubGenerator.GenerateJSImportBody();
+ LocalFunctionStatementSyntax localFunction = GenerateInvokeFunction(LocalFunctionName, incrementalContext.SignatureContext, stubGenerator, hasReturn);
+
+ return (PrintGeneratedSource(incrementalContext.StubMethodSyntaxTemplate, incrementalContext.SignatureContext, incrementalContext.ContainingSyntaxContext, Block(bindStatement, code, localFunction)), incrementalContext.Diagnostics.Array.AddRange(diagnostics.Diagnostics));
+ }
+
+ private static IfStatementSyntax GenerateBindSyntax(JSImportData jsImportData, JSSignatureContext signatureContext, ArgumentSyntax signaturesArgument)
+ {
+ var bindingParameters =
+ (new ArgumentSyntax[] {
+ Argument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(jsImportData.FunctionName))),
+ Argument(
+ jsImportData.ModuleName == null
+ ? LiteralExpression(SyntaxKind.NullLiteralExpression)
+ : LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(jsImportData.ModuleName))),
+ signaturesArgument,
+ });
+
+ return IfStatement(BinaryExpression(SyntaxKind.EqualsExpression, IdentifierName(signatureContext.BindingName), LiteralExpression(SyntaxKind.NullLiteralExpression)),
+ Block(SingletonList(
+ ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
+ IdentifierName(signatureContext.BindingName),
+ InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
+ IdentifierName(Constants.JSFunctionSignatureGlobal), IdentifierName(Constants.BindJSFunctionMethod)))
+ .WithArgumentList(ArgumentList(SeparatedList(bindingParameters))))))));
+ }
- return (PrintGeneratedSource(incrementalContext.StubMethodSyntaxTemplate, incrementalContext.SignatureContext, incrementalContext.ContainingSyntaxContext, code), incrementalContext.Diagnostics.Array.AddRange(diagnostics.Diagnostics));
+ private static LocalFunctionStatementSyntax GenerateInvokeFunction(string functionName, JSSignatureContext signatureContext, ManagedToNativeStubGenerator stubGenerator, bool hasReturn)
+ {
+ var (parameters, returnType, _) = stubGenerator.GenerateTargetMethodSignatureData();
+ TypeSyntax jsMarshalerArgument = ParseTypeName(Constants.JSMarshalerArgumentGlobal);
+
+ CollectionExpressionSyntax argumentsBuffer = CollectionExpression(
+ SeparatedList(
+ parameters.Parameters
+ .Select(p => ExpressionElement(IdentifierName(p.Identifier)))));
+
+ List statements = [];
+
+ if (hasReturn)
+ {
+ statements.AddRange([
+ Declare(
+ SpanOf(jsMarshalerArgument),
+ Constants.ArgumentsBuffer,
+ argumentsBuffer),
+ MethodInvocationStatement(
+ IdentifierName(Constants.JSFunctionSignatureGlobal),
+ IdentifierName("InvokeJS"),
+ Argument(IdentifierName(signatureContext.BindingName)),
+ Argument(IdentifierName(Constants.ArgumentsBuffer))),
+ ReturnStatement(
+ ElementAccessExpression(
+ IdentifierName(Constants.ArgumentsBuffer),
+ BracketedArgumentList(SingletonSeparatedList(Argument(
+ LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(1)))))))
+ ]);
+ }
+ else
+ {
+ statements.Add(
+ MethodInvocationStatement(
+ IdentifierName(Constants.JSFunctionSignatureGlobal),
+ IdentifierName("InvokeJS"),
+ Argument(IdentifierName(signatureContext.BindingName)),
+ Argument(argumentsBuffer)));
+ }
+
+ return LocalFunctionStatement(
+ hasReturn ? jsMarshalerArgument : PredefinedType(Token(SyntaxKind.VoidKeyword)),
+ functionName)
+ .WithBody(Block(statements))
+ .WithParameterList(parameters)
+ .WithAttributeLists(SingletonList(AttributeList(SingletonSeparatedList(
+ Attribute(IdentifierName(Constants.DebuggerNonUserCodeAttribute))))));
}
private static Diagnostic? GetDiagnosticIfInvalidMethodForGeneration(MethodDeclarationSyntax methodSyntax, IMethodSymbol method)
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.csproj b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.csproj
index d973b24132c6a8..0af96384ebbe8c 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.csproj
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.csproj
@@ -27,6 +27,7 @@
+
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSMarshallingInfo.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSMarshallingInfo.cs
index edeb7961aadb1e..8d0ed8384486d9 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSMarshallingInfo.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSMarshallingInfo.cs
@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.CodeAnalysis;
+using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Runtime.InteropServices.JavaScript;
namespace Microsoft.Interop.JavaScript
@@ -16,6 +18,14 @@ protected JSMarshallingInfo()
public JSTypeFlags JSType { get; init; }
public JSTypeFlags[] JSTypeArguments { get; init; }
+
+ private ImmutableArray _elementDependencies = ImmutableArray.Empty;
+ public override IEnumerable ElementDependencies => _elementDependencies;
+
+ public JSMarshallingInfo AddElementDependencies(IEnumerable elementDependencies)
+ {
+ return this with { _elementDependencies = _elementDependencies.AddRange(elementDependencies) };
+ }
}
internal sealed record JSMissingMarshallingInfo : JSMarshallingInfo
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/ArrayJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/ArrayJSGenerator.cs
deleted file mode 100644
index 5d7d55c644bd7f..00000000000000
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/ArrayJSGenerator.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.Collections.Generic;
-using System.Runtime.InteropServices.JavaScript;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-
-namespace Microsoft.Interop.JavaScript
-{
- internal sealed class ArrayJSGenerator : PrimitiveJSGenerator
- {
- private readonly MarshalerType _elementMarshalerType;
-
- public ArrayJSGenerator(TypePositionInfo info, StubCodeContext context, MarshalerType elementMarshalerType)
- : base(info, context, MarshalerType.Array)
- {
- _elementMarshalerType = elementMarshalerType;
- }
-
- public override IEnumerable GenerateBind()
- {
- yield return InvocationExpression(MarshalerTypeName(Type),
- ArgumentList(SingletonSeparatedList(Argument(MarshalerTypeName(_elementMarshalerType)))));
- }
- }
-}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/ArraySegmentJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/ArraySegmentJSGenerator.cs
deleted file mode 100644
index f3785d8bf7e121..00000000000000
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/ArraySegmentJSGenerator.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Collections.Generic;
-using System.Runtime.InteropServices.JavaScript;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-
-namespace Microsoft.Interop.JavaScript
-{
- internal sealed class ArraySegmentJSGenerator : PrimitiveJSGenerator
- {
- private readonly MarshalerType _elementMarshalerType;
-
- public ArraySegmentJSGenerator(TypePositionInfo info, StubCodeContext context, MarshalerType elementMarshalerType)
- : base(info, context, MarshalerType.ArraySegment)
- {
- _elementMarshalerType = elementMarshalerType;
- }
-
- public override IEnumerable GenerateBind()
- {
- yield return InvocationExpression(MarshalerTypeName(Type),
- ArgumentList(SingletonSeparatedList(Argument(MarshalerTypeName(_elementMarshalerType)))));
- }
- }
-}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/BaseJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/BaseJSGenerator.cs
index 1f6eef2346545d..ab1cb7c8de5371 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/BaseJSGenerator.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/BaseJSGenerator.cs
@@ -7,65 +7,50 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+using static Microsoft.Interop.SyntaxFactoryExtensions;
+
namespace Microsoft.Interop.JavaScript
{
- internal abstract class BaseJSGenerator : IJSMarshallingGenerator
+ internal abstract class BaseJSGenerator(TypePositionInfo info, StubCodeContext codeContext) : IBoundMarshallingGenerator
{
- protected IBoundMarshallingGenerator _inner;
- public MarshalerType Type;
-
- protected BaseJSGenerator(MarshalerType marshalerType, IBoundMarshallingGenerator inner)
- {
- _inner = inner;
- Type = marshalerType;
- }
+ private static ValueTypeInfo JSMarshalerArgument = new ValueTypeInfo(Constants.JSMarshalerArgumentGlobal, Constants.JSMarshalerArgument, IsByRefLike: false);
- public TypePositionInfo TypeInfo => _inner.TypeInfo;
+ public TypePositionInfo TypeInfo => info;
- public StubCodeContext CodeContext => _inner.CodeContext;
+ public StubCodeContext CodeContext => codeContext;
- public ManagedTypeInfo NativeType => _inner.NativeType;
+ public ManagedTypeInfo NativeType => JSMarshalerArgument;
- public SignatureBehavior NativeSignatureBehavior => _inner.NativeSignatureBehavior;
+ public SignatureBehavior NativeSignatureBehavior => TypeInfo.IsByRef ? SignatureBehavior.PointerToNativeType : SignatureBehavior.NativeType;
- public ValueBoundaryBehavior ValueBoundaryBehavior => _inner.ValueBoundaryBehavior;
+ public ValueBoundaryBehavior ValueBoundaryBehavior => TypeInfo.IsByRef ? ValueBoundaryBehavior.AddressOfNativeIdentifier : ValueBoundaryBehavior.NativeIdentifier;
- public virtual bool UsesNativeIdentifier => _inner.UsesNativeIdentifier;
+ public virtual bool UsesNativeIdentifier => true;
public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, out GeneratorDiagnostic? diagnostic)
- => _inner.SupportsByValueMarshalKind(marshalKind, out diagnostic);
-
- public virtual IEnumerable GenerateBind()
{
- yield return MarshalerTypeName(Type);
+ diagnostic = null;
+ return ByValueMarshalKindSupport.NotSupported;
}
public virtual IEnumerable Generate(StubIdentifierContext context)
{
- string argName = context.GetAdditionalIdentifier(TypeInfo, "js_arg");
-
- if (context.CurrentStage == StubIdentifierContext.Stage.Setup)
+ MarshalDirection marshalDirection = MarshallerHelpers.GetMarshalDirection(TypeInfo, CodeContext);
+ if (context.CurrentStage == StubIdentifierContext.Stage.Setup
+ && marshalDirection == MarshalDirection.ManagedToUnmanaged
+ && !TypeInfo.IsManagedReturnPosition)
{
- if (!TypeInfo.IsManagedReturnPosition)
- {
- yield return LocalDeclarationStatement(VariableDeclaration(RefType(IdentifierName(Constants.JSMarshalerArgumentGlobal)))
- .WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier(argName))
- .WithInitializer(EqualsValueClause(RefExpression(ElementAccessExpression(IdentifierName(Constants.ArgumentsBuffer))
- .WithArgumentList(BracketedArgumentList(SingletonSeparatedList(
- Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(TypeInfo.ManagedIndex + 2))))))))))));
- }
+ var (_, js) = context.GetIdentifiers(TypeInfo);
+ return [
+ ExpressionStatement(
+ MethodInvocation(TypeSyntaxes.System_Runtime_CompilerServices_Unsafe, IdentifierName("SkipInit"),
+ Argument(IdentifierName(js))
+ .WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword))))
+ ];
}
- foreach (var x in _inner.Generate(context))
- {
- yield return x;
- }
- }
-
- protected static IdentifierNameSyntax MarshalerTypeName(MarshalerType marshalerType)
- {
- return IdentifierName(Constants.JSMarshalerTypeGlobalDot + marshalerType.ToString());
+ return [];
}
protected static IdentifierNameSyntax GetToManagedMethod(MarshalerType marshalerType)
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/EmptyJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/EmptyJSGenerator.cs
deleted file mode 100644
index e9704fbdc04d2b..00000000000000
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/EmptyJSGenerator.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.Collections.Generic;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-
-namespace Microsoft.Interop.JavaScript
-{
- internal sealed class EmptyJSGenerator : IUnboundMarshallingGenerator
- {
- public ManagedTypeInfo AsNativeType(TypePositionInfo info) => info.ManagedType;
- public IEnumerable Generate(TypePositionInfo info, StubCodeContext codeContext, StubIdentifierContext identifierContext) => Array.Empty();
- public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) => SignatureBehavior.ManagedTypeAndAttributes;
- public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) => ValueBoundaryBehavior.ManagedIdentifier;
- public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, out GeneratorDiagnostic? diagnostic)
- => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, out diagnostic);
- public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => false;
- }
-}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/FuncJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/FuncJSGenerator.cs
index d4d7f785c55367..f92bc3a4b7691f 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/FuncJSGenerator.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/FuncJSGenerator.cs
@@ -11,34 +11,16 @@
namespace Microsoft.Interop.JavaScript
{
- internal sealed class FuncJSGenerator : BaseJSGenerator
+ internal sealed class FuncJSGenerator(TypePositionInfo info, StubCodeContext context, bool isAction, MarshalerType[] argumentMarshalerTypes) : BaseJSGenerator(info, context)
{
- private readonly bool _isAction;
- private readonly MarshalerType[] _argumentMarshalerTypes;
-
- public FuncJSGenerator(TypePositionInfo info, StubCodeContext context, bool isAction, MarshalerType[] argumentMarshalerTypes)
- : base(isAction ? MarshalerType.Action : MarshalerType.Function, new Forwarder().Bind(info, context))
- {
- _isAction = isAction;
- _argumentMarshalerTypes = argumentMarshalerTypes;
- }
-
- public override IEnumerable GenerateBind()
- {
- var args = _argumentMarshalerTypes.Select(x => Argument(MarshalerTypeName(x))).ToList();
- yield return InvocationExpression(MarshalerTypeName(Type), ArgumentList(SeparatedList(args)));
- }
-
public override IEnumerable Generate(StubIdentifierContext context)
{
- string argName = context.GetAdditionalIdentifier(TypeInfo, "js_arg");
- var target = TypeInfo.IsManagedReturnPosition
- ? Constants.ArgumentReturn
- : argName;
+ foreach (var statement in base.Generate(context))
+ {
+ yield return statement;
+ }
- var source = TypeInfo.IsManagedReturnPosition
- ? Argument(IdentifierName(context.GetIdentifiers(TypeInfo).native))
- : _inner.AsArgument(context);
+ var (managed, js) = context.GetIdentifiers(TypeInfo);
var jsty = (JSFunctionTypeInfo)((JSMarshallingInfo)TypeInfo.MarshallingAttributeInfo).TypeInfo;
var sourceTypes = jsty.ArgsTypeInfo
@@ -47,27 +29,22 @@ public override IEnumerable Generate(StubIdentifierContext cont
if (context.CurrentStage == StubIdentifierContext.Stage.UnmarshalCapture && CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && TypeInfo.IsManagedReturnPosition)
{
- yield return ToManagedMethod(target, source, jsty);
+ yield return ToManagedMethod(js, Argument(IdentifierName(managed)), jsty);
}
if (context.CurrentStage == StubIdentifierContext.Stage.Marshal && CodeContext.Direction == MarshalDirection.UnmanagedToManaged && TypeInfo.IsManagedReturnPosition)
{
- yield return ToJSMethod(target, source, jsty);
- }
-
- foreach (var x in base.Generate(context))
- {
- yield return x;
+ yield return ToJSMethod(js, Argument(IdentifierName(managed)), jsty);
}
if (context.CurrentStage == StubIdentifierContext.Stage.PinnedMarshal && CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && !TypeInfo.IsManagedReturnPosition)
{
- yield return ToJSMethod(target, source, jsty);
+ yield return ToJSMethod(js, Argument(IdentifierName(managed)), jsty);
}
if (context.CurrentStage == StubIdentifierContext.Stage.Unmarshal && CodeContext.Direction == MarshalDirection.UnmanagedToManaged && !TypeInfo.IsManagedReturnPosition)
{
- yield return ToManagedMethod(target, source, jsty);
+ yield return ToManagedMethod(js, Argument(IdentifierName(managed)), jsty);
}
}
@@ -77,18 +54,18 @@ private ExpressionStatementSyntax ToManagedMethod(string target, ArgumentSyntax
for (int i = 0; i < info.ArgsTypeInfo.Length; i++)
{
var sourceType = info.ArgsTypeInfo[i];
- if (!_isAction && i + 1 == info.ArgsTypeInfo.Length)
+ if (!isAction && i + 1 == info.ArgsTypeInfo.Length)
{
- arguments.Add(ArgToManaged(i, sourceType.Syntax, _argumentMarshalerTypes[i]));
+ arguments.Add(ArgToManaged(i, sourceType.Syntax, argumentMarshalerTypes[i]));
}
else
{
- arguments.Add(ArgToJS(i, sourceType.Syntax, _argumentMarshalerTypes[i]));
+ arguments.Add(ArgToJS(i, sourceType.Syntax, argumentMarshalerTypes[i]));
}
}
return ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(target), GetToManagedMethod(Type)))
+ IdentifierName(target), GetToManagedMethod(isAction ? MarshalerType.Action : MarshalerType.Function)))
.WithArgumentList(ArgumentList(SeparatedList(arguments))));
}
@@ -98,18 +75,18 @@ private ExpressionStatementSyntax ToJSMethod(string target, ArgumentSyntax sourc
for (int i = 0; i < info.ArgsTypeInfo.Length; i++)
{
var sourceType = info.ArgsTypeInfo[i];
- if (!_isAction && i + 1 == info.ArgsTypeInfo.Length)
+ if (!isAction && i + 1 == info.ArgsTypeInfo.Length)
{
- arguments.Add(ArgToJS(i, sourceType.Syntax, _argumentMarshalerTypes[i]));
+ arguments.Add(ArgToJS(i, sourceType.Syntax, argumentMarshalerTypes[i]));
}
else
{
- arguments.Add(ArgToManaged(i, sourceType.Syntax, _argumentMarshalerTypes[i]));
+ arguments.Add(ArgToManaged(i, sourceType.Syntax, argumentMarshalerTypes[i]));
}
}
return ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(target), GetToJSMethod(Type)))
+ IdentifierName(target), GetToJSMethod(isAction ? MarshalerType.Action : MarshalerType.Function)))
.WithArgumentList(ArgumentList(SeparatedList(arguments))));
}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/IJSMarshallingGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/IJSMarshallingGenerator.cs
deleted file mode 100644
index f60406b21e8695..00000000000000
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/IJSMarshallingGenerator.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Collections.Generic;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-
-namespace Microsoft.Interop.JavaScript
-{
- internal interface IJSMarshallingGenerator : IBoundMarshallingGenerator
- {
- IEnumerable GenerateBind();
- }
-}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/ImplicitArgumentGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/ImplicitArgumentGenerator.cs
new file mode 100644
index 00000000000000..346dfb173f1f8c
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/ImplicitArgumentGenerator.cs
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+using static Microsoft.Interop.SyntaxFactoryExtensions;
+
+
+namespace Microsoft.Interop.JavaScript
+{
+ internal sealed class ImplicitArgumentGenerator(TypePositionInfo info, StubCodeContext codeContext) : BaseJSGenerator(info, codeContext)
+ {
+ public override IEnumerable Generate(StubIdentifierContext context)
+ {
+ if (context.CurrentStage == StubIdentifierContext.Stage.Setup)
+ {
+ var (_, js) = context.GetIdentifiers(TypeInfo);
+ return [
+ ExpressionStatement(
+ MethodInvocation(TypeSyntaxes.System_Runtime_CompilerServices_Unsafe, IdentifierName("SkipInit"),
+ Argument(IdentifierName(js))
+ .WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword)))),
+ // Unlike the other arguments, we need to initialize the implicit arguments
+ // as they can set some ambient state necessary for the JSImport logic to function.
+ ExpressionStatement(
+ InvocationExpression(
+ MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
+ IdentifierName(js),
+ IdentifierName("Initialize")),
+ ArgumentList()))
+ ];
+ }
+
+ return [];
+ }
+ }
+}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/NullableJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/NullableJSGenerator.cs
deleted file mode 100644
index 191c475f1330fa..00000000000000
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/NullableJSGenerator.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Collections.Generic;
-using System.Runtime.InteropServices.JavaScript;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-
-namespace Microsoft.Interop.JavaScript
-{
- internal sealed class NullableJSGenerator : PrimitiveJSGenerator
- {
- public NullableJSGenerator(TypePositionInfo info, StubCodeContext context, MarshalerType resultMarshalerType)
- : base(info, context, resultMarshalerType)
- {
- }
-
- public override IEnumerable GenerateBind()
- {
- yield return InvocationExpression(MarshalerTypeName(MarshalerType.Nullable),
- ArgumentList(SingletonSeparatedList(Argument(MarshalerTypeName(Type)))));
- }
- }
-}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/PrimitiveJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/PrimitiveJSGenerator.cs
index 5da5c9db179751..ab7830a642ab71 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/PrimitiveJSGenerator.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/PrimitiveJSGenerator.cs
@@ -9,78 +9,43 @@
namespace Microsoft.Interop.JavaScript
{
- internal class PrimitiveJSGenerator : BaseJSGenerator
+ internal sealed class PrimitiveJSGenerator(TypePositionInfo info, StubCodeContext context, MarshalerType elementMarshallerType) : BaseJSGenerator(info, context)
{
- public PrimitiveJSGenerator(MarshalerType marshalerType, IBoundMarshallingGenerator inner)
- : base(marshalerType, inner)
- {
- }
-
- public PrimitiveJSGenerator(TypePositionInfo info, StubCodeContext context, MarshalerType marshalerType)
- : base(marshalerType, new Forwarder().Bind(info, context))
- {
- }
-
// TODO order parameters in such way that affinity capturing parameters are emitted first
public override IEnumerable Generate(StubIdentifierContext context)
{
- string argName = context.GetAdditionalIdentifier(TypeInfo, "js_arg");
- var target = TypeInfo.IsManagedReturnPosition
- ? Constants.ArgumentReturn
- : argName;
-
- var source = TypeInfo.IsManagedReturnPosition
- ? Argument(IdentifierName(context.GetIdentifiers(TypeInfo).native))
- : _inner.AsArgument(context);
-
- if (context.CurrentStage == StubIdentifierContext.Stage.UnmarshalCapture && CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && TypeInfo.IsManagedReturnPosition)
+ foreach (var statement in base.Generate(context))
{
- yield return ToManagedMethod(target, source);
+ yield return statement;
}
- if (context.CurrentStage == StubIdentifierContext.Stage.Marshal && CodeContext.Direction == MarshalDirection.UnmanagedToManaged && TypeInfo.IsManagedReturnPosition)
- {
- yield return ToJSMethod(target, source);
- }
+ var (managed, js) = context.GetIdentifiers(TypeInfo);
- foreach (var x in base.Generate(context))
- {
- yield return x;
- }
+ MarshalDirection marshalDirection = MarshallerHelpers.GetMarshalDirection(TypeInfo, CodeContext);
- if (context.CurrentStage == StubIdentifierContext.Stage.PinnedMarshal && CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && !TypeInfo.IsManagedReturnPosition)
+ if (context.CurrentStage == StubIdentifierContext.Stage.UnmarshalCapture && marshalDirection is MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional)
{
- yield return ToJSMethod(target, source);
+ yield return ToManagedMethod(js, Argument(IdentifierName(managed)));
}
- if (context.CurrentStage == StubIdentifierContext.Stage.Unmarshal && CodeContext.Direction == MarshalDirection.UnmanagedToManaged && !TypeInfo.IsManagedReturnPosition)
+ if (context.CurrentStage == StubIdentifierContext.Stage.Marshal && marshalDirection is MarshalDirection.ManagedToUnmanaged or MarshalDirection.Bidirectional)
{
- yield return ToManagedMethod(target, source);
+ yield return ToJSMethod(js, Argument(IdentifierName(managed)));
}
}
- protected virtual ArgumentSyntax ToManagedMethodRefOrOut(ArgumentSyntax argument)
- {
- return argument.WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword));
- }
-
- protected virtual ArgumentSyntax ToJSMethodRefOrOut(ArgumentSyntax argument)
- {
- return argument;
- }
-
private ExpressionStatementSyntax ToManagedMethod(string target, ArgumentSyntax source)
{
return ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(target), GetToManagedMethod(Type)))
- .WithArgumentList(ArgumentList(SingletonSeparatedList(ToManagedMethodRefOrOut(source)))));
+ IdentifierName(target), GetToManagedMethod(elementMarshallerType)))
+ .WithArgumentList(ArgumentList(SingletonSeparatedList(source.WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword))))));
}
private ExpressionStatementSyntax ToJSMethod(string target, ArgumentSyntax source)
{
return ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(target), GetToJSMethod(Type)))
- .WithArgumentList(ArgumentList(SingletonSeparatedList(ToJSMethodRefOrOut(source)))));
+ IdentifierName(target), GetToJSMethod(elementMarshallerType)))
+ .WithArgumentList(ArgumentList(SingletonSeparatedList(source))));
}
}
}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/SpanJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/SpanJSGenerator.cs
deleted file mode 100644
index afaedf597b6fe5..00000000000000
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/SpanJSGenerator.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Collections.Generic;
-using System.Runtime.InteropServices.JavaScript;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-
-namespace Microsoft.Interop.JavaScript
-{
- internal sealed class SpanJSGenerator : PrimitiveJSGenerator
- {
- private readonly MarshalerType _elementMarshalerType;
-
- public SpanJSGenerator(TypePositionInfo info, StubCodeContext context, MarshalerType elementMarshalerType)
- : base(info, context, MarshalerType.Span)
- {
- _elementMarshalerType = elementMarshalerType;
- }
-
- public override IEnumerable GenerateBind()
- {
- yield return InvocationExpression(MarshalerTypeName(Type),
- ArgumentList(SingletonSeparatedList(Argument(MarshalerTypeName(_elementMarshalerType)))));
- }
- }
-}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/TaskJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/TaskJSGenerator.cs
index 381f4dac813740..2a05d2a7dff92f 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/TaskJSGenerator.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/TaskJSGenerator.cs
@@ -9,95 +9,66 @@
namespace Microsoft.Interop.JavaScript
{
- internal sealed class TaskJSGenerator : BaseJSGenerator
+ internal sealed class TaskJSGenerator(TypePositionInfo info, StubCodeContext context, MarshalerType resultMarshalerType) : BaseJSGenerator(info, context)
{
- private readonly MarshalerType _resultMarshalerType;
-
- public TaskJSGenerator(TypePositionInfo info, StubCodeContext context, MarshalerType resultMarshalerType)
- : base(MarshalerType.Task, new Forwarder().Bind(info, context))
- {
- _resultMarshalerType = resultMarshalerType;
- }
-
- public override IEnumerable GenerateBind()
+ public override IEnumerable Generate(StubIdentifierContext context)
{
- var jsty = (JSTaskTypeInfo)((JSMarshallingInfo)TypeInfo.MarshallingAttributeInfo).TypeInfo;
- if (jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void))
- {
- yield return InvocationExpression(MarshalerTypeName(MarshalerType.Task), ArgumentList());
- }
- else
+ foreach (var statement in base.Generate(context))
{
- yield return InvocationExpression(MarshalerTypeName(MarshalerType.Task),
- ArgumentList(SingletonSeparatedList(Argument(MarshalerTypeName(_resultMarshalerType)))));
+ yield return statement;
}
- }
- public override IEnumerable Generate(StubIdentifierContext context)
- {
var jsty = (JSTaskTypeInfo)((JSMarshallingInfo)TypeInfo.MarshallingAttributeInfo).TypeInfo;
- string argName = context.GetAdditionalIdentifier(TypeInfo, "js_arg");
- var target = TypeInfo.IsManagedReturnPosition
- ? Constants.ArgumentReturn
- : argName;
-
- var source = TypeInfo.IsManagedReturnPosition
- ? Argument(IdentifierName(context.GetIdentifiers(TypeInfo).native))
- : _inner.AsArgument(context);
+ var (managed, js) = context.GetIdentifiers(TypeInfo);
if (context.CurrentStage == StubIdentifierContext.Stage.UnmarshalCapture && CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && TypeInfo.IsManagedReturnPosition)
{
yield return jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void)
- ? ToManagedMethodVoid(target, source)
- : ToManagedMethod(target, source, jsty.ResultTypeInfo.Syntax);
+ ? ToManagedMethodVoid(js, Argument(IdentifierName(managed)))
+ : ToManagedMethod(js, Argument(IdentifierName(managed)), jsty.ResultTypeInfo.Syntax);
}
if (context.CurrentStage == StubIdentifierContext.Stage.Marshal && CodeContext.Direction == MarshalDirection.UnmanagedToManaged && TypeInfo.IsManagedReturnPosition)
{
yield return jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void)
- ? ToJSMethodVoid(target, source)
- : ToJSMethod(target, source, jsty.ResultTypeInfo.Syntax);
- }
-
- foreach (var x in base.Generate(context))
- {
- yield return x;
+ ? ToJSMethodVoid(js, Argument(IdentifierName(managed)))
+ : ToJSMethod(js, Argument(IdentifierName(managed)), jsty.ResultTypeInfo.Syntax);
}
if (context.CurrentStage == StubIdentifierContext.Stage.PinnedMarshal && CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && !TypeInfo.IsManagedReturnPosition)
{
yield return jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void)
- ? ToJSMethodVoid(target, source)
- : ToJSMethod(target, source, jsty.ResultTypeInfo.Syntax);
+ ? ToJSMethodVoid(js, Argument(IdentifierName(managed)))
+ : ToJSMethod(js, Argument(IdentifierName(managed)), jsty.ResultTypeInfo.Syntax);
}
if (context.CurrentStage == StubIdentifierContext.Stage.Unmarshal && CodeContext.Direction == MarshalDirection.UnmanagedToManaged && !TypeInfo.IsManagedReturnPosition)
{
yield return jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void)
- ? ToManagedMethodVoid(target, source)
- : ToManagedMethod(target, source, jsty.ResultTypeInfo.Syntax);
+ ? ToManagedMethodVoid(js, Argument(IdentifierName(managed)))
+ : ToManagedMethod(js, Argument(IdentifierName(managed)), jsty.ResultTypeInfo.Syntax);
}
}
- private ExpressionStatementSyntax ToManagedMethodVoid(string target, ArgumentSyntax source)
+ private static ExpressionStatementSyntax ToManagedMethodVoid(string target, ArgumentSyntax source)
{
return ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(target), GetToManagedMethod(Type)))
+ IdentifierName(target), GetToManagedMethod(MarshalerType.Task)))
.WithArgumentList(ArgumentList(SingletonSeparatedList(source.WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword))))));
}
- private ExpressionStatementSyntax ToJSMethodVoid(string target, ArgumentSyntax source)
+ private static ExpressionStatementSyntax ToJSMethodVoid(string target, ArgumentSyntax source)
{
return ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(target), GetToJSMethod(Type)))
+ IdentifierName(target), GetToJSMethod(MarshalerType.Task)))
.WithArgumentList(ArgumentList(SingletonSeparatedList(source))));
}
private ExpressionStatementSyntax ToManagedMethod(string target, ArgumentSyntax source, TypeSyntax sourceType)
{
return ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(target), GetToManagedMethod(Type)))
+ IdentifierName(target), GetToManagedMethod(MarshalerType.Task)))
.WithArgumentList(ArgumentList(SeparatedList(new[]{
source.WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword)),
Argument(ParenthesizedLambdaExpression()
@@ -111,7 +82,7 @@ private ExpressionStatementSyntax ToManagedMethod(string target, ArgumentSyntax
.WithType(sourceType)})))
.WithBlock(Block(SingletonList(ExpressionStatement(
InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName("__task_result_arg"), GetToManagedMethod(_resultMarshalerType)))
+ IdentifierName("__task_result_arg"), GetToManagedMethod(resultMarshalerType)))
.WithArgumentList(ArgumentList(SeparatedList(new[]{
Argument(IdentifierName("__task_result")).WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword)),
}))))))))}))));
@@ -120,7 +91,7 @@ private ExpressionStatementSyntax ToManagedMethod(string target, ArgumentSyntax
private ExpressionStatementSyntax ToJSMethod(string target, ArgumentSyntax source, TypeSyntax sourceType)
{
return ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(target), GetToJSMethod(Type)))
+ IdentifierName(target), GetToJSMethod(MarshalerType.Task)))
.WithArgumentList(ArgumentList(SeparatedList(new[]{
source,
Argument(ParenthesizedLambdaExpression()
@@ -133,7 +104,7 @@ private ExpressionStatementSyntax ToJSMethod(string target, ArgumentSyntax sourc
.WithType(sourceType)})))
.WithBlock(Block(SingletonList(ExpressionStatement(
InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName("__task_result_arg"), GetToJSMethod(_resultMarshalerType)))
+ IdentifierName("__task_result_arg"), GetToJSMethod(resultMarshalerType)))
.WithArgumentList(ArgumentList(SeparatedList(new[]{
Argument(IdentifierName("__task_result")),
}))))))))}))));
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/VoidGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/VoidGenerator.cs
deleted file mode 100644
index 2177f5436e431e..00000000000000
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/VoidGenerator.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Runtime.InteropServices.JavaScript;
-
-namespace Microsoft.Interop.JavaScript
-{
- internal sealed class VoidGenerator(TypePositionInfo info, StubCodeContext context, MarshalerType marshalerType) : BaseJSGenerator(marshalerType, new Forwarder().Bind(info, context));
-}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/NoSpanAndTaskMixingResolver.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/NoSpanAndTaskMixingResolver.cs
new file mode 100644
index 00000000000000..1d46d530a958ea
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/NoSpanAndTaskMixingResolver.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Microsoft.Interop.JavaScript
+{
+ internal sealed class NoSpanAndTaskMixingResolver : IMarshallingGeneratorResolver
+ {
+ private bool _hasSpan;
+ private bool _hasTask;
+
+ public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context)
+ {
+ bool foundInteresting = false;
+ if (info.MarshallingAttributeInfo is JSMarshallingInfo(_, JSSpanTypeInfo))
+ {
+ _hasSpan = true;
+ foundInteresting = true;
+ }
+
+ if (info.MarshallingAttributeInfo is JSMarshallingInfo(_, JSTaskTypeInfo) && info.IsManagedReturnPosition)
+ {
+ _hasTask = true;
+ foundInteresting = true;
+ }
+
+ if (foundInteresting && _hasSpan && _hasTask)
+ {
+ return ResolvedGenerator.NotSupported(info, context,
+ new GeneratorDiagnostic.NotSupported(info)
+ {
+ NotSupportedDetails = SR.SpanAndTaskNotSupported
+ });
+ }
+
+ return ResolvedGenerator.UnresolvedGenerator;
+ }
+ }
+}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/SignatureBindingHelpers.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/SignatureBindingHelpers.cs
new file mode 100644
index 00000000000000..d8a3a8231904fc
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/SignatureBindingHelpers.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Runtime.InteropServices.JavaScript;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+
+namespace Microsoft.Interop.JavaScript
+{
+ internal static class SignatureBindingHelpers
+ {
+ public static ArgumentSyntax CreateSignaturesArgument(ImmutableArray elements, StubCodeContext context)
+ {
+ List arguments = [];
+
+ foreach (TypePositionInfo element in elements.Where(e => e.NativeIndex != TypePositionInfo.UnsetIndex).OrderBy(e => e.NativeIndex))
+ {
+ var (baseType, subTypes) = JSGeneratorResolver.GetMarshallerTypeForBinding(element, context);
+ ExpressionSyntax bindSyntax = MarshalerTypeName(baseType);
+ if (subTypes is not null)
+ {
+ bindSyntax = InvocationExpression(bindSyntax,
+ ArgumentList(SeparatedList(subTypes.Select(s => Argument(MarshalerTypeName(s))))));
+ }
+ arguments.Add(ExpressionElement(bindSyntax));
+ }
+
+ return Argument(CollectionExpression(SeparatedList(arguments)));
+ }
+
+ private static IdentifierNameSyntax MarshalerTypeName(MarshalerType marshalerType)
+ {
+ return IdentifierName(Constants.JSMarshalerTypeGlobalDot + marshalerType.ToString());
+ }
+
+ }
+}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs
index f6be095eecab92..7f1447673f85e6 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs
@@ -261,19 +261,22 @@ internal static unsafe void DispatchJSFunctionSync(JSObject jsFunction, Span arguments)
{
- var args = (nint)Unsafe.AsPointer(ref arguments[0]);
- var sig = (nint)signature.Header;
+ fixed (JSMarshalerArgument* argsPtr = arguments)
+ {
+ var args = (nint)argsPtr;
+ var sig = (nint)signature.Header;
- ref JSMarshalerArgument exc = ref arguments[0];
+ ref JSMarshalerArgument exc = ref arguments[0];
- // we already know that we are not on the right thread
- // this will be blocking until resolved by that thread
- Interop.Runtime.InvokeJSImportSyncSend(targetContext.JSNativeTID, sig, args);
+ // we already know that we are not on the right thread
+ // this will be blocking until resolved by that thread
+ Interop.Runtime.InvokeJSImportSyncSend(targetContext.JSNativeTID, sig, args);
- if (exc.slot.Type != MarshalerType.None)
- {
- JSHostImplementation.ThrowException(ref exc);
+ if (exc.slot.Type != MarshalerType.None)
+ {
+ JSHostImplementation.ThrowException(ref exc);
+ }
}
}
@@ -412,8 +418,7 @@ internal static unsafe void DispatchJSImportAsyncPost(JSFunctionBinding signatur
var bytes = sizeof(JSMarshalerArgument) * arguments.Length;
void* cpy = (void*)Marshal.AllocHGlobal(bytes);
- void* src = Unsafe.AsPointer(ref arguments[0]);
- Unsafe.CopyBlock(cpy, src, (uint)bytes);
+ arguments.CopyTo(new Span(cpy, arguments.Length));
var sig = (nint)signature.Header;
// we already know that we are not on the right thread
@@ -476,8 +481,7 @@ internal static unsafe void ResolveOrRejectPromise(JSProxyContext targetContext,
// this copy is freed in mono_wasm_resolve_or_reject_promise
var bytes = sizeof(JSMarshalerArgument) * arguments.Length;
void* cpy = (void*)Marshal.AllocHGlobal(bytes);
- void* src = Unsafe.AsPointer(ref arguments[0]);
- Unsafe.CopyBlock(cpy, src, (uint)bytes);
+ arguments.CopyTo(new Span(cpy, arguments.Length));
// async
Interop.Runtime.ResolveOrRejectPromisePost(targetContext.JSNativeTID, (nint)cpy);
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Compiles.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Compiles.cs
index 466cd3072f1ef4..b376bb096b6fb1 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Compiles.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Compiles.cs
@@ -51,7 +51,7 @@ public void ValidateSnippets(string source)
}
[Fact]
- public async Task ValidateGeneratedSourceOutput()
+ public async Task ValidateGeneratedSourceOutput_AllAnnotatedParameters()
{
var test = new Test()
{
@@ -71,70 +71,97 @@ internal static partial void Annotated(object a1, long a2, long a3, global::Syst
{
if (__signature_Annotated_1583225186 == null)
{
- __signature_Annotated_1583225186 = global::System.Runtime.InteropServices.JavaScript.JSFunctionBinding.BindJSFunction("DoesNotExist", null, new global::System.Runtime.InteropServices.JavaScript.JSMarshalerType[] { global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Discard, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Object, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Int52, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.BigInt64, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Action(), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Function(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Int32), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Span(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Byte), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.ArraySegment(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Byte), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Object), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Array(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Object), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.DateTime, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.DateTimeOffset, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.DateTime), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.DateTimeOffset), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Int52), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.BigInt64) });
+ __signature_Annotated_1583225186 = global::System.Runtime.InteropServices.JavaScript.JSFunctionBinding.BindJSFunction("DoesNotExist", null, [global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Discard, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Object, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Int52, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.BigInt64, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Action(), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Function(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Int32), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Span(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Byte), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.ArraySegment(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Byte), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Object), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Array(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Object), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.DateTime, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.DateTimeOffset, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.DateTime), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.DateTimeOffset), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Int52), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.BigInt64)]);
}
- global::System.Span __arguments_buffer = stackalloc global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument[17];
- ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __arg_exception = ref __arguments_buffer[0];
- __arg_exception.Initialize();
- ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __arg_return = ref __arguments_buffer[1];
- __arg_return.Initialize();
- // Setup - Perform required setup.
- ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a15_native__js_arg = ref __arguments_buffer[16];
- ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a14_native__js_arg = ref __arguments_buffer[15];
- ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a13_native__js_arg = ref __arguments_buffer[14];
- ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a12_native__js_arg = ref __arguments_buffer[13];
- ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a11_native__js_arg = ref __arguments_buffer[12];
- ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a10_native__js_arg = ref __arguments_buffer[11];
- ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a9_native__js_arg = ref __arguments_buffer[10];
- ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a8_native__js_arg = ref __arguments_buffer[9];
- ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a7_native__js_arg = ref __arguments_buffer[8];
- ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a6_native__js_arg = ref __arguments_buffer[7];
- ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a5_native__js_arg = ref __arguments_buffer[6];
- ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a4_native__js_arg = ref __arguments_buffer[5];
- ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a3_native__js_arg = ref __arguments_buffer[4];
- ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a2_native__js_arg = ref __arguments_buffer[3];
- ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a1_native__js_arg = ref __arguments_buffer[2];
- // PinnedMarshal - Convert managed data to native data that requires the managed data to be pinned.
- __a15_native__js_arg.ToJS(a15, static (ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __task_result_arg, long __task_result) =>
{
- __task_result_arg.ToJSBig(__task_result);
- });
- __a14_native__js_arg.ToJS(a14, static (ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __task_result_arg, long __task_result) =>
- {
- __task_result_arg.ToJS(__task_result);
- });
- __a13_native__js_arg.ToJS(a13, static (ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __task_result_arg, global::System.DateTimeOffset __task_result) =>
- {
- __task_result_arg.ToJS(__task_result);
- });
- __a12_native__js_arg.ToJS(a12, static (ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __task_result_arg, global::System.DateTime __task_result) =>
- {
- __task_result_arg.ToJS(__task_result);
- });
- __a11_native__js_arg.ToJS(a11);
- __a10_native__js_arg.ToJS(a10);
- __a9_native__js_arg.ToJS(a9);
- __a8_native__js_arg.ToJS(a8, static (ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __task_result_arg, object __task_result) =>
- {
- __task_result_arg.ToJS(__task_result);
- });
- __a7_native__js_arg.ToJS(a7);
- __a6_native__js_arg.ToJS(a6);
- __a5_native__js_arg.ToJS(a5, static (ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __delegate_arg_arg1, int __delegate_arg1) =>
+ global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument ____arg_exception_native;
+ global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument ____arg_return_native;
+ global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a1_native;
+ global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a2_native;
+ global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a3_native;
+ global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a4_native;
+ global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a5_native;
+ global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a6_native;
+ global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a7_native;
+ global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a8_native;
+ global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a9_native;
+ global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a10_native;
+ global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a11_native;
+ global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a12_native;
+ global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a13_native;
+ global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a14_native;
+ global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a15_native;
+ // Setup - Perform required setup.
+ global::System.Runtime.CompilerServices.Unsafe.SkipInit(out ____arg_return_native);
+ ____arg_return_native.Initialize();
+ global::System.Runtime.CompilerServices.Unsafe.SkipInit(out ____arg_exception_native);
+ ____arg_exception_native.Initialize();
+ global::System.Runtime.CompilerServices.Unsafe.SkipInit(out __a15_native);
+ global::System.Runtime.CompilerServices.Unsafe.SkipInit(out __a14_native);
+ global::System.Runtime.CompilerServices.Unsafe.SkipInit(out __a13_native);
+ global::System.Runtime.CompilerServices.Unsafe.SkipInit(out __a12_native);
+ global::System.Runtime.CompilerServices.Unsafe.SkipInit(out __a11_native);
+ global::System.Runtime.CompilerServices.Unsafe.SkipInit(out __a10_native);
+ global::System.Runtime.CompilerServices.Unsafe.SkipInit(out __a9_native);
+ global::System.Runtime.CompilerServices.Unsafe.SkipInit(out __a8_native);
+ global::System.Runtime.CompilerServices.Unsafe.SkipInit(out __a7_native);
+ global::System.Runtime.CompilerServices.Unsafe.SkipInit(out __a6_native);
+ global::System.Runtime.CompilerServices.Unsafe.SkipInit(out __a5_native);
+ global::System.Runtime.CompilerServices.Unsafe.SkipInit(out __a4_native);
+ global::System.Runtime.CompilerServices.Unsafe.SkipInit(out __a3_native);
+ global::System.Runtime.CompilerServices.Unsafe.SkipInit(out __a2_native);
+ global::System.Runtime.CompilerServices.Unsafe.SkipInit(out __a1_native);
+ // Marshal - Convert managed data to native data.
+ __a11_native.ToJS(a11);
+ __a10_native.ToJS(a10);
+ __a9_native.ToJS(a9);
+ __a7_native.ToJS(a7);
+ __a6_native.ToJS(a6);
+ __a3_native.ToJSBig(a3);
+ __a2_native.ToJS(a2);
+ __a1_native.ToJS(a1);
+ {
+ // PinnedMarshal - Convert managed data to native data that requires the managed data to be pinned.
+ __a15_native.ToJS(a15, static (ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __task_result_arg, long __task_result) =>
+ {
+ __task_result_arg.ToJSBig(__task_result);
+ });
+ __a14_native.ToJS(a14, static (ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __task_result_arg, long __task_result) =>
+ {
+ __task_result_arg.ToJS(__task_result);
+ });
+ __a13_native.ToJS(a13, static (ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __task_result_arg, global::System.DateTimeOffset __task_result) =>
+ {
+ __task_result_arg.ToJS(__task_result);
+ });
+ __a12_native.ToJS(a12, static (ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __task_result_arg, global::System.DateTime __task_result) =>
+ {
+ __task_result_arg.ToJS(__task_result);
+ });
+ __a8_native.ToJS(a8, static (ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __task_result_arg, object __task_result) =>
+ {
+ __task_result_arg.ToJS(__task_result);
+ });
+ __a5_native.ToJS(a5, static (ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __delegate_arg_arg1, int __delegate_arg1) =>
+ {
+ __delegate_arg_arg1.ToJS(__delegate_arg1);
+ });
+ __a4_native.ToJS(a4);
+ __InvokeJSFunction(____arg_exception_native, ____arg_return_native, __a1_native, __a2_native, __a3_native, __a4_native, __a5_native, __a6_native, __a7_native, __a8_native, __a9_native, __a10_native, __a11_native, __a12_native, __a13_native, __a14_native, __a15_native);
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCode]
+ void __InvokeJSFunction(global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument ____arg_exception_native, global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument ____arg_return_native, global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a1_native, global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a2_native, global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a3_native, global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a4_native, global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a5_native, global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a6_native, global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a7_native, global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a8_native, global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a9_native, global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a10_native, global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a11_native, global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a12_native, global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a13_native, global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a14_native, global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument __a15_native)
{
- __delegate_arg_arg1.ToJS(__delegate_arg1);
- });
- __a4_native__js_arg.ToJS(a4);
- __a3_native__js_arg.ToJSBig(a3);
- __a2_native__js_arg.ToJS(a2);
- __a1_native__js_arg.ToJS(a1);
- global::System.Runtime.InteropServices.JavaScript.JSFunctionBinding.InvokeJS(__signature_Annotated_1583225186, __arguments_buffer);
+ global::System.Runtime.InteropServices.JavaScript.JSFunctionBinding.InvokeJS(__signature_Annotated_1583225186, [____arg_exception_native, ____arg_return_native, __a1_native, __a2_native, __a3_native, __a4_native, __a5_native, __a6_native, __a7_native, __a8_native, __a9_native, __a10_native, __a11_native, __a12_native, __a13_native, __a14_native, __a15_native]);
+ }
}
static global::System.Runtime.InteropServices.JavaScript.JSFunctionBinding __signature_Annotated_1583225186;
}
-
+
""".ReplaceLineEndings("\r\n"), Encoding.UTF8)),
(typeof(Microsoft.Interop.JavaScript.JSExportGenerator),
"JSExports.g.cs",
@@ -158,7 +185,7 @@ static void __Register_()
if (initialized || global::System.Runtime.InteropServices.RuntimeInformation.OSArchitecture != global::System.Runtime.InteropServices.Architecture.Wasm)
return;
initialized = true;
- global::System.Runtime.InteropServices.JavaScript.JSFunctionBinding.BindManagedFunction("[TestProject]Basic:AnnotatedExport", 1583225186, new global::System.Runtime.InteropServices.JavaScript.JSMarshalerType[] { global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Discard, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Object, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Int52, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.BigInt64, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Action(), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Function(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Int32), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Span(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Byte), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.ArraySegment(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Byte), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Object), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Array(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Object), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.DateTime, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.DateTimeOffset, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.DateTime), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.DateTimeOffset), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Int52), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.BigInt64) });
+ global::System.Runtime.InteropServices.JavaScript.JSFunctionBinding.BindManagedFunction("[TestProject]Basic:AnnotatedExport", 1583225186, [global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Discard, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Object, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Int52, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.BigInt64, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Action(), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Function(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Int32), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Span(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Byte), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.ArraySegment(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Byte), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Object), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Array(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Object), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.DateTime, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.DateTimeOffset, global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.DateTime), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.DateTimeOffset), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Int52), global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.Task(global::System.Runtime.InteropServices.JavaScript.JSMarshalerType.BigInt64)]);
}
}
}
@@ -167,84 +194,195 @@ unsafe partial class Basic
[global::System.Diagnostics.DebuggerNonUserCode]
internal static unsafe void __Wrapper_AnnotatedExport_1583225186(global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument* __arguments_buffer)
{
- object a1;
- long a2;
- long a3;
- global::System.Action a4;
- global::System.Func a5;
- global::System.Span a6;
- global::System.ArraySegment a7;
- global::System.Threading.Tasks.Task