Skip to content

Commit

Permalink
Enable devirtualization in more scenarios on crossgen2 (#53567)
Browse files Browse the repository at this point in the history
Address deficiencies in current devirtualization infrastructure

- Remove the responsibility of creating a CORINFO_RESOLVED_TOKEN structure from the JIT and make it a responsibility of the VM side of the jit interface.
  - This enables the component (crossgen2) which has deeper understanding of the requirements here to correctly handle scenarios that would otherwise require expressing crossgen2 specific details across the jit interface.
- Add a new set of fixups (`READYTORUN_FIXUP_Check_VirtualFunctionOverride` and `READYTORUN_FIXUP_Verify_VirtualFunctionOverride`) these are used to validate that the behavior of the runtime and crossgen2 compiler is equivalent for a virtual resolution event
  - `READYTORUN_FIXUP_Check_VirtualFunctionOverride` will ensure that the virtual resolution decision is the same at crossgen2 time and runtime, and if the decision differs, any generated code affected by the decision will not be used.
  - `READYTORUN_FIXUP_Verify_VirtualFunctionOverride` will perform the same checks as `READYTORUN_FIXUP_Check_VirtualFunctionOverride`, but if it fails the check, the process will be terminated with a fail-fast. It is intended for use under the `--verify-type-and-field-layout` stress mode.
  - Currently only the `READYTORUN_FIXUP_Verify_VirtualFunctionOverride` is actually generated, and it is only generated when using the `--verify-type-and-field-layout` switch to crossgen2. Future work will identify if there are scenarios where we need to generate the `READYTORUN_FIXUP_Check_VirtualFunctionOverride` flag. One area of possible concern is around covariant returns, another is around handling of type equivalence.
- In order to express the fixup signature for the VirtualFunctionOverride fixups, a new flag has been added to `ReadyToRunMethodSigFlags`. `READYTORUN_METHOD_SIG_UpdateContext` will allow the method signature to internally specify the assembly which is associated with the method token, instead of relying on the ambient context.
- R2RDump and the ReadyToRun format documentation have been updated with the details of the new fixups/flags.
- Update the rules for handling unboxing stubs
  - See #51918 for details. This adds a new test, as well as proper handling for unboxing stubs to match the JIT behavior
  - Also revert #52605, which avoided the problem by simply disabling devirtualization in the presence of structs
- Adjust the rules for when it is legal to devirtualize and maintain version resiliency
  - The VersionsWithCode and VersionsWithType rules are unnecessarily restrictive.
  - Instead Validate that the metadata is safely checkable, and rely on the canInline logic to ensure that no IL that can't be handled is inlined.
  - This also involved adding a check that the chain of types from the implementation type to the declaration method table type is within the version bubble.
  - And changing the `VersionsWithType` check on the implementation type, to a new `VersionsWithTypeReference` check which can be used to validate that the type can be referred to, in combination with using `VersionsWithType` on the type definition.
  - By adjusting the way that the declMethod is referred to, it becomes possible to use the declMethod without checking the full method is `VersionsWithCode`, and it just needs a relationship to version matching code.
- In `resolveVirtualMethod` generate the `CORINFO_RESOLVED_TOKEN` structures for the jit
  - In particular we are now able to resolve to methods where the decl method is the resolution result but is not within the version bubble itself. This can happen if we can prove that the decl method is the only method which can possibly implement a virtual.
- Add support for devirtualization reasons to crossgen2
- Port all devirtualization abort conditions to crossgen2 from runtime that were not already present
- Fix devirtualization from a canonical virtual method when the actual implementation is more exact
- Fix variant interface override scenario where there is an interface that requires implementation of the variant interface as well as the variant interface itself.
  • Loading branch information
davidwrighton authored Jun 11, 2021
1 parent e4751ae commit d07f911
Show file tree
Hide file tree
Showing 49 changed files with 1,452 additions and 179 deletions.
16 changes: 16 additions & 0 deletions docs/design/coreclr/botr/readytorun-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Revisions:
* 3.1 - [Tomas Rylek](https://github.com/trylek) - 2019
* 4.1 - [Tomas Rylek](https://github.com/trylek) - 2020
* 5.3 - [Tomas Rylek](https://github.com/trylek) - 2021
* 5.4 - [David Wrighton](https://github.com/davidwrighton) - 2021

# Introduction

Expand Down Expand Up @@ -251,6 +252,10 @@ fixup kind, the rest of the signature varies based on the fixup kind.
| READYTORUN_FIXUP_IndirectPInvokeTarget | 0x2E | Target (indirect) of an inlined PInvoke. Followed by method signature.
| READYTORUN_FIXUP_PInvokeTarget | 0x2F | Target of an inlined PInvoke. Followed by method signature.
| READYTORUN_FIXUP_Check_InstructionSetSupport | 0x30 | Specify the instruction sets that must be supported/unsupported to use the R2R code associated with the fixup.
| READYTORUN_FIXUP_Verify_FieldOffset | 0x31 | Generate a runtime check to ensure that the field offset matches between compile and runtime. Unlike CheckFieldOffset, this will generate a runtime exception on failure instead of silently dropping the method
| READYTORUN_FIXUP_Verify_TypeLayout | 0x32 | Generate a runtime check to ensure that the field offset matches between compile and runtime. Unlike CheckFieldOffset, this will generate a runtime exception on failure instead of silently dropping the method
| READYTORUN_FIXUP_Check_VirtualFunctionOverride | 0x33 | Generate a runtime check to ensure that virtual function resolution has equivalent behavior at runtime as at compile time. If not equivalent, code will not be used. See [Virtual override signatures](virtual-override-signatures) for details of the signature used.
| READYTORUN_FIXUP_Verify_VirtualFunctionOverride | 0x33 | Generate a runtime check to ensure that virtual function resolution has equivalent behavior at runtime as at compile time. If not equivalent, generate runtime failure. See [Virtual override signatures](virtual-override-signatures) for details of the signature used.
| READYTORUN_FIXUP_ModuleOverride | 0x80 | When or-ed to the fixup ID, the fixup byte in the signature is followed by an encoded uint with assemblyref index, either within the MSIL metadata of the master context module for the signature or within the manifest metadata R2R header table (used in cases inlining brings in references to assemblies not seen in the input MSIL).

#### Method Signatures
Expand All @@ -268,6 +273,7 @@ token, and additional data determined by the flags.
| READYTORUN_METHOD_SIG_MemberRefToken | 0x10 | If set, the token is memberref token. If not set, the token is methoddef token.
| READYTORUN_METHOD_SIG_Constrained | 0x20 | Constrained type for method resolution. Typespec appended as additional data.
| READYTORUN_METHOD_SIG_OwnerType | 0x40 | Method type. Typespec appended as additional data.
| READYTORUN_METHOD_SIG_UpdateContext | 0x80 | If set, update the module which is used to parse tokens before performing any token processing. A uint index into the modules table immediately follows the flags

#### Field Signatures

Expand All @@ -281,6 +287,16 @@ additional data determined by the flags.
| READYTORUN_FIELD_SIG_MemberRefToken | 0x10 | If set, the token is memberref token. If not set, the token is fielddef token.
| READYTORUN_FIELD_SIG_OwnerType | 0x40 | Field type. Typespec appended as additional data.

#### Virtual override signatures

ECMA 335 does not have a natural encoding for describing an overriden method. These signatures are encoded as a ReadyToRunVirtualFunctionOverrideFlags byte, followed by a method signature representing the declaration method, a type signature representing the type which is being devirtualized, and (optionally) a method signature indicating the implementation method.

| ReadyToRunVirtualFunctionOverrideFlags | Value | Description
|:------------------------------------------------------|------:|:-----------
| READYTORUN_VIRTUAL_OVERRIDE_None | 0x00 | No flags are set
| READYTORUN_VIRTUAL_OVERRIDE_VirtualFunctionOverriden | 0x01 | If set, then the virtual function has an implementation, which is encoded in the optional method implementation signature.


### READYTORUN_IMPORT_SECTIONS::AuxiliaryData

For slots resolved lazily via `READYTORUN_HELPER_DelayLoad_MethodCall` helper, auxiliary data are
Expand Down
20 changes: 12 additions & 8 deletions src/coreclr/ToolBox/superpmi/superpmi-shared/agnostic.h
Original file line number Diff line number Diff line change
Expand Up @@ -557,18 +557,22 @@ struct Agnostic_GetSystemVAmd64PassStructInRegisterDescriptor

struct Agnostic_ResolveVirtualMethodKey
{
DWORDLONG virtualMethod;
DWORDLONG objClass;
DWORDLONG context;
DWORDLONG virtualMethod;
DWORDLONG objClass;
DWORDLONG context;
DWORD pResolvedTokenVirtualMethodNonNull;
Agnostic_CORINFO_RESOLVED_TOKEN pResolvedTokenVirtualMethod;
};

struct Agnostic_ResolveVirtualMethodResult
{
bool returnValue;
DWORDLONG devirtualizedMethod;
bool requiresInstMethodTableArg;
DWORDLONG exactContext;
DWORD detail;
bool returnValue;
DWORDLONG devirtualizedMethod;
bool requiresInstMethodTableArg;
DWORDLONG exactContext;
DWORD detail;
Agnostic_CORINFO_RESOLVED_TOKEN resolvedTokenDevirtualizedMethod;
Agnostic_CORINFO_RESOLVED_TOKEN resolvedTokenDevirtualizedUnboxedMethod;
};

struct ResolveTokenValue
Expand Down
15 changes: 15 additions & 0 deletions src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3167,12 +3167,20 @@ void MethodContext::recResolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO * info
key.virtualMethod = CastHandle(info->virtualMethod);
key.objClass = CastHandle(info->objClass);
key.context = CastHandle(info->context);

ZeroMemory(&key.pResolvedTokenVirtualMethod, sizeof(key.pResolvedTokenVirtualMethod)); // Zero token including any struct padding
key.pResolvedTokenVirtualMethodNonNull = info->pResolvedTokenVirtualMethod != NULL ? 1 : 0;
if (key.pResolvedTokenVirtualMethodNonNull)
key.pResolvedTokenVirtualMethod = SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKEN(info->pResolvedTokenVirtualMethod, ResolveToken);

Agnostic_ResolveVirtualMethodResult result;
result.returnValue = returnValue;
result.devirtualizedMethod = CastHandle(info->devirtualizedMethod);
result.requiresInstMethodTableArg = info->requiresInstMethodTableArg;
result.exactContext = CastHandle(info->exactContext);
result.detail = (DWORD) info->detail;
result.resolvedTokenDevirtualizedMethod = SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKEN(&info->resolvedTokenDevirtualizedMethod, ResolveToken);
result.resolvedTokenDevirtualizedUnboxedMethod = SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKEN(&info->resolvedTokenDevirtualizedUnboxedMethod, ResolveToken);
ResolveVirtualMethod->Add(key, result);
DEBUG_REC(dmpResolveVirtualMethod(key, result));
}
Expand All @@ -3191,6 +3199,11 @@ bool MethodContext::repResolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO * info
key.objClass = CastHandle(info->objClass);
key.context = CastHandle(info->context);

ZeroMemory(&key.pResolvedTokenVirtualMethod, sizeof(key.pResolvedTokenVirtualMethod)); // Zero token including any struct padding
key.pResolvedTokenVirtualMethodNonNull = info->pResolvedTokenVirtualMethod != NULL ? 1 : 0;
if (key.pResolvedTokenVirtualMethodNonNull)
key.pResolvedTokenVirtualMethod = SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKEN(info->pResolvedTokenVirtualMethod, ResolveToken);

AssertMapAndKeyExist(ResolveVirtualMethod, key, ": %016llX-%016llX-%016llX", key.virtualMethod, key.objClass, key.context);

Agnostic_ResolveVirtualMethodResult result = ResolveVirtualMethod->Get(key);
Expand All @@ -3200,6 +3213,8 @@ bool MethodContext::repResolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO * info
info->requiresInstMethodTableArg = result.requiresInstMethodTableArg;
info->exactContext = (CORINFO_CONTEXT_HANDLE) result.exactContext;
info->detail = (CORINFO_DEVIRTUALIZATION_DETAIL) result.detail;
info->resolvedTokenDevirtualizedMethod = SpmiRecordsHelper::Restore_CORINFO_RESOLVED_TOKEN(&result.resolvedTokenDevirtualizedMethod, ResolveToken);
info->resolvedTokenDevirtualizedUnboxedMethod = SpmiRecordsHelper::Restore_CORINFO_RESOLVED_TOKEN(&result.resolvedTokenDevirtualizedUnboxedMethod, ResolveToken);
return result.returnValue;
}

Expand Down
20 changes: 20 additions & 0 deletions src/coreclr/ToolBox/superpmi/superpmi-shared/spmirecordhelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ class SpmiRecordsHelper
static Agnostic_CORINFO_RESOLVED_TOKEN RestoreAgnostic_CORINFO_RESOLVED_TOKEN(
CORINFO_RESOLVED_TOKEN* pResolvedToken, LightWeightMap<key, value>* buffers);

template <typename key, typename value>
static CORINFO_RESOLVED_TOKEN Restore_CORINFO_RESOLVED_TOKEN(
Agnostic_CORINFO_RESOLVED_TOKEN* pResolvedTokenAgnostic, LightWeightMap<key, value>* buffers);

// Restore the out values in the first argument from the second.
// Can't just return whole CORINFO_RESOLVED_TOKEN because [in] values in it are important too.
template <typename key, typename value>
Expand Down Expand Up @@ -200,6 +204,22 @@ inline Agnostic_CORINFO_RESOLVED_TOKEN SpmiRecordsHelper::RestoreAgnostic_CORINF
return token;
}

template <typename key, typename value>
inline CORINFO_RESOLVED_TOKEN SpmiRecordsHelper::Restore_CORINFO_RESOLVED_TOKEN(
Agnostic_CORINFO_RESOLVED_TOKEN* pResolvedTokenAgnostic, LightWeightMap<key, value>* buffers)
{
CORINFO_RESOLVED_TOKEN token;
ZeroMemory(&token, sizeof(token));

token.tokenContext = (CORINFO_CONTEXT_HANDLE)pResolvedTokenAgnostic->inValue.tokenContext;
token.tokenScope = (CORINFO_MODULE_HANDLE)pResolvedTokenAgnostic->inValue.tokenScope;
token.token = (mdToken)pResolvedTokenAgnostic->inValue.token;
token.tokenType = (CorInfoTokenKind)pResolvedTokenAgnostic->inValue.tokenType;

Restore_CORINFO_RESOLVED_TOKENout(&token, pResolvedTokenAgnostic->outValue, buffers);
return token;
}

template <typename key, typename value>
inline void SpmiRecordsHelper::Restore_CORINFO_RESOLVED_TOKENout(
CORINFO_RESOLVED_TOKEN* pResolvedToken,
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/crossgen-corelib.proj
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
<CrossGenDllCmd>$(CrossGenDllCmd) --targetarch:$(TargetArchitecture)</CrossGenDllCmd>
<CrossGenDllCmd Condition="'$(UsingToolIbcOptimization)' != 'true' and '$(EnableNgenOptimization)' == 'true'">$(CrossGenDllCmd) -m:$(MergedMibcPath) --embed-pgo-data</CrossGenDllCmd>
<CrossGenDllCmd>$(CrossGenDllCmd) -O</CrossGenDllCmd>
<CrossGenDllCmd Condition="'$(Configuration)' == 'Debug' or '$(Configuration)' == 'Checked'">$(CrossGenDllCmd) --verify-type-and-field-layout</CrossGenDllCmd>
<CrossGenDllCmd>$(CrossGenDllCmd) $(CoreLibInputPath)</CrossGenDllCmd>
</PropertyGroup>

Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/inc/corcompile.h
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,9 @@ enum CORCOMPILE_FIXUP_BLOB_KIND
ENCODE_VERIFY_FIELD_OFFSET, /* Used for the R2R compiler can generate a check against the real field offset used at runtime */
ENCODE_VERIFY_TYPE_LAYOUT, /* Used for the R2R compiler can generate a check against the real type layout used at runtime */

ENCODE_CHECK_VIRTUAL_FUNCTION_OVERRIDE, /* Generate a runtime check to ensure that virtual function resolution has equivalent behavior at runtime as at compile time. If not equivalent, code will not be used */
ENCODE_VERIFY_VIRTUAL_FUNCTION_OVERRIDE, /* Generate a runtime check to ensure that virtual function resolution has equivalent behavior at runtime as at compile time. If not equivalent, generate runtime failure. */

ENCODE_MODULE_HANDLE = 0x50, /* Module token */
ENCODE_STATIC_FIELD_ADDRESS, /* For accessing a static field */
ENCODE_MODULE_ID_FOR_STATICS, /* For accessing static fields */
Expand All @@ -724,6 +727,7 @@ enum EncodeMethodSigFlags
ENCODE_METHOD_SIG_MemberRefToken = 0x10,
ENCODE_METHOD_SIG_Constrained = 0x20,
ENCODE_METHOD_SIG_OwnerType = 0x40,
ENCODE_METHOD_SIG_UpdateContext = 0x80,
};

enum EncodeFieldSigFlags
Expand Down
35 changes: 23 additions & 12 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -1604,18 +1604,24 @@ struct CORINFO_CALL_INFO

enum CORINFO_DEVIRTUALIZATION_DETAIL
{
CORINFO_DEVIRTUALIZATION_UNKNOWN, // no details available
CORINFO_DEVIRTUALIZATION_SUCCESS, // devirtualization was successful
CORINFO_DEVIRTUALIZATION_FAILED_CANON, // object class was canonical
CORINFO_DEVIRTUALIZATION_FAILED_COM, // object class was com
CORINFO_DEVIRTUALIZATION_FAILED_CAST, // object class could not be cast to interface class
CORINFO_DEVIRTUALIZATION_FAILED_LOOKUP, // interface method could not be found
CORINFO_DEVIRTUALIZATION_FAILED_DIM, // interface method was default interface method
CORINFO_DEVIRTUALIZATION_FAILED_SUBCLASS, // object not subclass of base class
CORINFO_DEVIRTUALIZATION_FAILED_SLOT, // virtual method installed via explicit override
CORINFO_DEVIRTUALIZATION_FAILED_BUBBLE, // devirtualization crossed version bubble
CORINFO_DEVIRTUALIZATION_MULTIPLE_IMPL, // object has multiple implementations of interface class
CORINFO_DEVIRTUALIZATION_COUNT, // sentinel for maximum value
CORINFO_DEVIRTUALIZATION_UNKNOWN, // no details available
CORINFO_DEVIRTUALIZATION_SUCCESS, // devirtualization was successful
CORINFO_DEVIRTUALIZATION_FAILED_CANON, // object class was canonical
CORINFO_DEVIRTUALIZATION_FAILED_COM, // object class was com
CORINFO_DEVIRTUALIZATION_FAILED_CAST, // object class could not be cast to interface class
CORINFO_DEVIRTUALIZATION_FAILED_LOOKUP, // interface method could not be found
CORINFO_DEVIRTUALIZATION_FAILED_DIM, // interface method was default interface method
CORINFO_DEVIRTUALIZATION_FAILED_SUBCLASS, // object not subclass of base class
CORINFO_DEVIRTUALIZATION_FAILED_SLOT, // virtual method installed via explicit override
CORINFO_DEVIRTUALIZATION_FAILED_BUBBLE, // devirtualization crossed version bubble
CORINFO_DEVIRTUALIZATION_MULTIPLE_IMPL, // object has multiple implementations of interface class
CORINFO_DEVIRTUALIZATION_FAILED_BUBBLE_CLASS_DECL, // decl method is defined on class and decl method not in version bubble, and decl method not in closest to version bubble
CORINFO_DEVIRTUALIZATION_FAILED_BUBBLE_INTERFACE_DECL, // decl method is defined on interface and not in version bubble, and implementation type not entirely defined in bubble
CORINFO_DEVIRTUALIZATION_FAILED_BUBBLE_IMPL, // object class not defined within version bubble
CORINFO_DEVIRTUALIZATION_FAILED_BUBBLE_IMPL_NOT_REFERENCEABLE, // object class cannot be referenced from R2R code due to missing tokens
CORINFO_DEVIRTUALIZATION_FAILED_DUPLICATE_INTERFACE, // crossgen2 virtual method algorithm and runtime algorithm differ in the presence of duplicate interface implementations
CORINFO_DEVIRTUALIZATION_FAILED_DECL_NOT_REPRESENTABLE, // Decl method cannot be represented in R2R image
CORINFO_DEVIRTUALIZATION_COUNT, // sentinel for maximum value
};

struct CORINFO_DEVIRTUALIZATION_INFO
Expand All @@ -1626,6 +1632,7 @@ struct CORINFO_DEVIRTUALIZATION_INFO
CORINFO_METHOD_HANDLE virtualMethod;
CORINFO_CLASS_HANDLE objClass;
CORINFO_CONTEXT_HANDLE context;
CORINFO_RESOLVED_TOKEN *pResolvedTokenVirtualMethod;

//
// [Out] results of resolveVirtualMethod.
Expand All @@ -1634,11 +1641,15 @@ struct CORINFO_DEVIRTUALIZATION_INFO
// - requiresInstMethodTableArg is set to TRUE if the devirtualized method requires a type handle arg.
// - exactContext is set to wrapped CORINFO_CLASS_HANDLE of devirt'ed method table.
// - details on the computation done by the jit host
// - If pResolvedTokenDevirtualizedMethod is not set to NULL and targetting an R2R image
// use it as the parameter to getCallInfo
//
CORINFO_METHOD_HANDLE devirtualizedMethod;
bool requiresInstMethodTableArg;
CORINFO_CONTEXT_HANDLE exactContext;
CORINFO_DEVIRTUALIZATION_DETAIL detail;
CORINFO_RESOLVED_TOKEN resolvedTokenDevirtualizedMethod;
CORINFO_RESOLVED_TOKEN resolvedTokenDevirtualizedUnboxedMethod;
};

//----------------------------------------------------------------------------
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
#define GUID_DEFINED
#endif // !GUID_DEFINED

constexpr GUID JITEEVersionIdentifier = { /* 1052f490-cad7-4610-99bb-6f2bd91a1d19 */
0x1052f490,
0xcad7,
0x4610,
{0x99, 0xbb, 0x6f, 0x2b, 0xd9, 0x1a, 0x1d, 0x19}
constexpr GUID JITEEVersionIdentifier = { /* de9a9a0e-c66a-4d97-a268-92a31f99d919 */
0xde9a9a0e,
0xc66a,
0x4d97,
{0xa2, 0x68, 0x92, 0xa3, 0x1f, 0x99, 0xd9, 0x19}
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
12 changes: 11 additions & 1 deletion src/coreclr/inc/readytorun.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

// Keep these in sync with src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs
#define READYTORUN_MAJOR_VERSION 0x0005
#define READYTORUN_MINOR_VERSION 0x0003
#define READYTORUN_MINOR_VERSION 0x0004

#define MINIMUM_READYTORUN_MAJOR_VERSION 0x003

Expand Down Expand Up @@ -134,6 +134,7 @@ enum ReadyToRunMethodSigFlags
READYTORUN_METHOD_SIG_MemberRefToken = 0x10,
READYTORUN_METHOD_SIG_Constrained = 0x20,
READYTORUN_METHOD_SIG_OwnerType = 0x40,
READYTORUN_METHOD_SIG_UpdateContext = 0x80,
};

enum ReadyToRunFieldSigFlags
Expand All @@ -152,6 +153,12 @@ enum ReadyToRunTypeLayoutFlags
READYTORUN_LAYOUT_GCLayout_Empty = 0x10,
};

enum ReadyToRunVirtualFunctionOverrideFlags
{
READYTORUN_VIRTUAL_OVERRIDE_None = 0x00,
READYTORUN_VIRTUAL_OVERRIDE_VirtualFunctionOverriden = 0x01,
};

//
// Constants for fixup signature encoding
//
Expand Down Expand Up @@ -211,6 +218,9 @@ enum ReadyToRunFixupKind

READYTORUN_FIXUP_Verify_FieldOffset = 0x31, /* Generate a runtime check to ensure that the field offset matches between compile and runtime. Unlike Check_FieldOffset, this will generate a runtime failure instead of silently dropping the method */
READYTORUN_FIXUP_Verify_TypeLayout = 0x32, /* Generate a runtime check to ensure that the type layout (size, alignment, HFA, reference map) matches between compile and runtime. Unlike Check_TypeLayout, this will generate a runtime failure instead of silently dropping the method */

READYTORUN_FIXUP_Check_VirtualFunctionOverride = 0x33, /* Generate a runtime check to ensure that virtual function resolution has equivalent behavior at runtime as at compile time. If not equivalent, code will not be used */
READYTORUN_FIXUP_Verify_VirtualFunctionOverride = 0x34, /* Generate a runtime check to ensure that virtual function resolution has equivalent behavior at runtime as at compile time. If not equivalent, generate runtime failure. */
};

//
Expand Down
Loading

0 comments on commit d07f911

Please sign in to comment.