mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-09 17:44:48 +09:00
Make normal statics simpler (#99183)
This change makes access to statics much simpler to document and also removes some performance penalties that we've had for a long time due to the old model. Most statics access should be equivalent or faster. This change converts static variables from a model where statics are associated with the module that defined the metadata of the static to a model where each individual type allocates its statics independently. In addition, it moves the flags that indicate whether or not a type is initialized, and whether or not its statics have been allocated to the `MethodTable` structures instead of storing them in a `DomainLocalModule` as was done before. # Particularly notable changes - All statics are now considered "dynamic" statics. - Statics for collectible assemblies now have an identical path for lookup of the static variable addresses as compared to statics for non-collectible assemblies. It is now reasonable for the process of reading static variables to be inlined into shared generic code, although this PR does not attempt to do so. - Lifetime management for collectible non-thread local statics is managed via a combination of a `LOADERHANDLE` to keep the static alive, and a new handle type called a `HNDTYPE_WEAK_INTERIOR_POINTER` which will keep the pointers to managed objects in the `MethodTable` structures up to date with the latest addresses of the static variables. - Each individual type in thread statics has a unique object holding the statics for the type. This means that each type has a separate object[](for gc statics), and/or double[](for non-gc statics) per thread for TLS statics. This isn't necessarily ideal for non-collectible types, but its not terrible either. - Thread statics for collectible types are reported directly to the GC instead of being handled via a GCHandle. While needed to avoid complex lifetime rules for collectible types, this may not be ideal for non-collectable types. - Since the `DomainLocalModule` no longer exists, the `ISOSDacInterface` has been augmented with a new api called `ISOSDacInterface14` which adds the ability to query for the static base/initialization status of an individual type directly. - Significant changes for generated code include - All the helpers are renamed - The statics of generics which have not yet been initialized can now be referenced using a single constant pointer + a helper call instead of needing a pair of pointers. In practice, this was a rare condition in perf-critical code due to the presence of tiered compilation, so this is not a significant change to optimized code. - The pre-initialization of statics can now occur for types which have non-primitive valuetype statics as long as the type does not have a class constructor. - Thread static non-gc statics are now returned as byrefs. (It turns out that for collectible assemblies, there is currently a small GC hole if a function returns the address of a non-gc threadstatic. CoreCLR at this time does not attempt to keep the collectible assembly alive if that is the only live pointer to the collectible static in the system) With this change, the pointers to normal static data are located at a fixed offset from the start of the `MethodTableAuxiliaryData`, and indices for Thread Static variables are stored also stored in such a fixed offset. Concepts such as the `DomainLocalModule` , `ThreadLocalModule`, `ModuleId` and `ModuleIndex` no longer exist. # Lifetime management for collectible statics - For normal collectible statics, each type will allocate a separate object[] for the GC statics and a double[] for the non-GC statics. A pointer to the data of these arrays will be stored in the `DynamicStaticsInfo` structure, and when relocation occurs, if the collectible types managed `LoaderAllocator` is still alive, the static field address will be relocated if the object moves. This is done by means of the new Weak Interior Pointer GC handle type. - For collectible thread-local statics, the lifetime management is substantially more complicated due the issue that it is possible for either a thread or a collectible type to be collected first. Thus the collection algorithm is as follows. - The system shall maintain a global mapping of TLS indices to MethodTable structures - When a native `LoaderAllocator` is being cleaned up, before the WeakTrackResurrection GCHandle that points at the the managed `LoaderAllocator` object is destroyed, the mapping from TLS indices to collectible `LoaderAllocator` structures shall be cleared of all relevant entries (and the current GC index shall be stored in the TLS to MethodTable mapping) - When a GC promotion or collection scan occurs, for every TLS index which was freed to point at a GC index the relevant entry in the TLS table shall be set to NULL in preparation for that entry in the table being reused in the future. In addition, if the TLS index refers to a `MethodTable` which is in a collectible assembly, and the associated `LoaderAllocator` has been freed, then set the relevant entry to NULL. - When allocating new entries from the TLS mapping table for new collectible thread local structures, do not re-use an entry in the table until at least 2 GCs have occurred. This is to allow every thread to have NULL'd out the relevant entry in its thread local table. - When allocating new TLS entries for collectible TLS statics on a per-thread basis allocate a `LOADERHANDLE` for each object allocated, and associate it with the TLS index on that thread. - When cleaning up a thread, for each collectible thread static which is still allocated, we will have a `LOADERHANDLE`. If the collectible type still has a live managed `LoaderAllocator` free the `LOADERHANDLE`. # Expected cost model for extra GC interactions associated with this change This change adds 3 possible ways in which the GC may have to perform additional work beyond what it used to do. 1. For normal statics on collectible types, it uses the a weak interior pointer GC handle for each of these that is allocated. This is purely pay for play and trades off performance of accessing collectible statics at runtime to the cost of maintaining a GCHandle in the GC. As the number of statics increases, this could in theory become a performance problem, but given the typical usages of collectible assemblies, we do not expect this to be significant. 2. For non-collectible thread statics, there is 1 GC pointer that is unconditionally reported for each thread. Usage of this removes a single indirection from every non-collectible thread local access. Given that this pointer is reported unconditionally, and is only a single pointer, this is not expected to be a significant cost. 3. For collectible thread statics, there is a complex protocol to keep thread statics alive for just long enough, and to clean them up as needed. This is expected to be completely pay for play with regard to usage of thread local variables in collectible assemblies, and while slightly more expensive to run than the current logic, will reduce the cost of creation/destruction of threads by a much more significant factor. In addition, if there are no collectible thread statics used on the thread, the cost of this is only a few branches per lookup. # Perf impact of this change I've run the .NET Microbenchmark suite as well as a variety of ASP.NET Benchmarks. (Unfortunately the publicly visible infrastructure for running tests is incompatible with this change, so results are not public). The results are generally quite hard to interpret. ASP.NET Benchmarks are generally (very) slightly better, and the microbenchmarks are generally equivalent in performance, although there is variability in some tests that had not previously shown variability, and the differences in performance are contained within the margin of error in our perf testing for tests with any significant amount of code. When performance differences have been examined in detail, they tend to be in code which has not changed in any way due to this change, and when run in isolation the performance deltas have disappeared in all cases that I have examined. Thus, I assume they are caching side effect changes. Performance testing has led me to add a change such that all NonGC, NonCollectible statics are allocated in a separate LoaderHeap which appears to have reduced the variability in some of the tests by a small fraction, although results are not consistent enough for me to be extremely confident in that statement.
This commit is contained in:
parent
bfb028b80f
commit
eb8f54d92b
106 changed files with 3551 additions and 6140 deletions
|
@ -193,19 +193,143 @@ This is enforced via an extensive and complicated set of enforcements within the
|
|||
- **ISSUE:** The signature walks performed are done with the normal signature walking code. This code is designed to load types as it walks the signature, but in this case the type load functionality is used with the assumption that no type load will actually be triggered.
|
||||
- **ISSUE:** Stackwalker requirements require support from not just the type system, but also the assembly loader. The Loader has had a number of issues meeting the needs of the type system here.
|
||||
|
||||
Type System and NGEN
|
||||
--------------------
|
||||
## Static variables
|
||||
|
||||
The type system data structures are a core part of what is saved into NGEN images. Unfortunately, these data structures logically have pointers within them that point to other NGEN images. In order to handle this situation, the type system data structures implement a concept known as restoration.
|
||||
Static variables in CoreCLR are handled by a combination of getting the "static base", and then adjusting it by an offset to get a pointer to the actual value.
|
||||
We define the statics base as either non-gc or gc for each field.
|
||||
Currently non-gc statics are any statics which are represented by primitive types (byte, sbyte, char, int, uint, long, ulong, float, double, pointers of various forms), and enums.
|
||||
GC statics are any statics which are represented by classes or by non-primitive valuetypes.
|
||||
For valuetype statics which are GC statics, the static variable is actually a pointer to a boxed instance of the valuetype.
|
||||
|
||||
In restoration, when a type system data structure is first needed, the data structure is fixed up with correct pointers. This is tied into the type loading levels described in the [Type Loader](type-loader.md) Book of the Runtime chapter.
|
||||
### Per type static variable information
|
||||
As of .NET 9, the static variable bases are now all associated with their particular type.
|
||||
As you can see from this diagram, the data for statics can be acquired by starting at a `MethodTable` and then getting either the `DynamicStaticsInfo` to get a statics pointer, or by getting a `ThreadStaticsInfo` to get a TLSIndex, which then can be used with the thread static variable system to get the actual thread static base.
|
||||
|
||||
There also exists the concept of pre-restored data structures. This means that the data structure is sufficiently correct at NGEN image load time (after intra-module pointer fixups and eager load type fixups), that the data structure may be used as is. This optimization requires that the NGEN image be "hard bound" to its dependent assemblies. See NGEN documentation for further details.
|
||||
```mermaid
|
||||
classDiagram
|
||||
MethodTable : MethodTableAuxiliaryData* m_pAuxData
|
||||
MethodTable --> MethodTableAuxiliaryData
|
||||
MethodTableAuxiliaryData --> DynamicStaticsInfo : If has static variables
|
||||
MethodTableAuxiliaryData --> GenericStaticsInfo : If is generic and has static variables
|
||||
MethodTableAuxiliaryData --> ThreadStaticsInfo : If has thread local static variables
|
||||
|
||||
Type System and Domain Neutral Loading
|
||||
--------------------------------------
|
||||
DynamicStaticsInfo : StaticsPointer m_pGCStatics
|
||||
DynamicStaticsInfo : StaticsPointer m_pNonGCStatics
|
||||
|
||||
The type system is a core part of the implementation of domain neutral loading. This is exposed to customers through the LoaderOptimization options available at AppDomain creation. Mscorlib is always loaded as domain neutral. The core requirement of this feature is that the type system data structures must not require pointers to domain specific state. Primarily this manifests itself in requirements around static fields and class constructors. In particular, whether or not a class constructor has been run is not a part of the core MethodTable data structure for this reason, and there is a mechanism for storing static data attached to the DomainFile data structure instead of the MethodTable data structure.
|
||||
GenericStaticsInfo : FieldDesc* m_pFieldDescs
|
||||
|
||||
ThreadStaticsInfo : TLSIndex NonGCTlsIndex
|
||||
ThreadStaticsInfo : TLSIndex GCTlsIndex
|
||||
```
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
|
||||
note for StaticsPointer "StaticsPointer is a pointer sized integer"
|
||||
StaticsPointer : void* PointerToStaticBase
|
||||
StaticsPointer : bool HasClassConstructorBeenRun
|
||||
|
||||
note for TLSIndex "TLSIndex is a 32bit integer"
|
||||
TLSIndex : TLSIndexType indexType
|
||||
TLSIndex : 24bit int indexOffset
|
||||
```
|
||||
|
||||
In the above diagram, you can see that we have separate fields for non-gc and gc statics, as well as thread and normal statics.
|
||||
For normal statics, we use a single pointer sized field, which also happens to encode whether or not the class constructor has been run.
|
||||
This is done to allow lock free atomic access to both get the static field address as well as determine if the class constructor needs to be triggered.
|
||||
For TLS statics, handling of detecting whether or not the class constructor has been run is a more complex process described as part of the thread statics infrastructure.
|
||||
The `DynamicStaticsInfo` and `ThreadStaticsInfo` structures are accessed without any locks, so it is important to ensure that access to fields on these structures can be done with a single memory access, to avoid memory order tearing issues.
|
||||
|
||||
Also, notably, for generic types, each field has a `FieldDesc` which is allocated per type instance, and is not shared by multiple canonical instances.
|
||||
|
||||
#### Lifetime management for collectible statics
|
||||
|
||||
Finally we have a concept of collectible assemblies in the CoreCLR runtime, so we need to handle lifetime management for static variables.
|
||||
The approach chosen was to build a special GC handle type which will allow the runtime to have a pointer in the runtime data structures to the interior of a managed object on the GC heap.
|
||||
|
||||
The requirement of behavior here is that a static variable cannot keep its own collectible assembly alive, and so collectible statics have the peculiar property that they can exist and be finalized before the collectible assembly is finally collected.
|
||||
If there is some resurrection scenario, this can lead to very surprising behavior.
|
||||
|
||||
### Thread Statics
|
||||
|
||||
Thread statics are static variables which have a lifetime which is defined to be the shorter of the lifetime of the type containing the static, and the lifetime of the thread on which the static variable is accessed.
|
||||
They are created by having a static variable on a type which is attributed with `[System.Runtime.CompilerServices.ThreadStaticAttribute]`.
|
||||
The general scheme of how this works is to assign an "index" to the type which is the same on all threads, and then on each thread hold a data structure which is efficiently accessed by means of this index.
|
||||
However, we have a few peculiarities in our approach.
|
||||
|
||||
1. We segregate collectible and non-collectible thread statics (`TLSIndexType::NonCollectible` and `TLSIndexType::Collectible`)
|
||||
2. We provide an ability to share a non-gc thread static between native CoreCLR code and managed code (Subset of `TLSIndexType::DirectOnThreadLocalData`)
|
||||
3. We provide an extremely efficient means to access a small number of non-gc thread statics. (The rest of the usage of `TLSIndexType::DirectOnThreadLocalData`)
|
||||
|
||||
#### Per-Thread Statics Data structures
|
||||
```mermaid
|
||||
classDiagram
|
||||
|
||||
note for ThreadLocalInfo "There is 1 of these per thread, and it is managed by the C++ compiler/OS using standard mechanisms.
|
||||
It can be found as the t_ThreadStatics variable in a C++ compiler, and is also pointed at by the native Thread class."
|
||||
ThreadLocalInfo : int cNonCollectibleTlsData
|
||||
ThreadLocalInfo : void** pNonCollectibleTlsArrayData
|
||||
ThreadLocalInfo : int cCollectibleTlsData
|
||||
ThreadLocalInfo : void** pCollectibleTlsArrayData
|
||||
ThreadLocalInfo : InFlightTLSData *pInFightData
|
||||
ThreadLocalInfo : Thread* pThread
|
||||
ThreadLocalInfo : Special Thread Statics Shared Between Native and Managed code
|
||||
ThreadLocalInfo : byte[N] ExtendedDirectThreadLocalTLSData
|
||||
|
||||
InFlightTLSData : InFlightTLSData* pNext
|
||||
InFlightTLSData : TLSIndex tlsIndex
|
||||
InFlightTLSData : OBJECTHANDLE hTLSData
|
||||
|
||||
ThreadLocalInfo --> InFlightTLSData : For TLS statics which have their memory allocated, but have not been accessed since the class finished running its class constructor
|
||||
InFlightTLSData --> InFlightTLSData : linked list
|
||||
```
|
||||
|
||||
#### Access patterns for getting the thread statics address
|
||||
|
||||
This is the pattern that the JIT will use to access a thread static which is not `DirectOnThreadLocalData`.
|
||||
|
||||
0. Get the TLS index somehow
|
||||
1. Get TLS pointer to OS managed TLS block for the current thread ie. `pThreadLocalData = &t_ThreadStatics`
|
||||
2. Read 1 integer value `pThreadLocalData->cCollectibleTlsData OR pThreadLocalData->cNonCollectibleTlsData`
|
||||
3. Compare cTlsData against the index we're looking up `if (cTlsData < index.GetIndexOffset())`
|
||||
4. If the index is not within range, jump to step 11.
|
||||
5. Read 1 pointer value from TLS block `pThreadLocalData->pCollectibleTlsArrayData` OR `pThreadLocalData->pNonCollectibleTlsArrayData`
|
||||
6. Read 1 pointer from within the TLS Array. `pTLSBaseAddress = *(intptr_t*)(((uint8_t*)pTlsArrayData) + index.GetIndexOffset()`
|
||||
7. If pointer is NULL jump to step 11 `if pTLSBaseAddress == NULL`
|
||||
8. If TLS index not a Collectible index, return pTLSBaseAddress
|
||||
9. if `ObjectFromHandle((OBJECTHANDLE)pTLSBaseAddress)` is NULL, jump to step 11
|
||||
10. Return `ObjectFromHandle((OBJECTHANDLE)pTLSBaseAddress)`
|
||||
11. Tail-call a helper `return GetThreadLocalStaticBase(index)`
|
||||
|
||||
This is the pattern that the JIT will use to access a thread static which is on `DirectOnThreadLocalData`
|
||||
0. Get the TLS index somehow
|
||||
1. Get TLS pointer to OS managed TLS block for the current thread ie. `pThreadLocalData = &t_ThreadStatics`
|
||||
2. Add the index offset to the start of the ThreadLocalData structure `pTLSBaseAddress = ((uint8_t*)pThreadLocalData) + index.GetIndexOffset()`
|
||||
|
||||
#### Lifetime management for thread static variables
|
||||
We distinguish between collectible and non-collectible thread static variables for efficiency purposes.
|
||||
|
||||
A non-collectible thread static is a thread static defined on a type which cannot be collected by the runtime.
|
||||
This describes most thread statics in actual observed practice.
|
||||
The `DirectOnThreadLocalData` statics are a subset of this category which has a speical optimized form and does not need any GC reporting.
|
||||
For non-collectible thread statics, the pointer (`pNonCollectibleTlsArrayData`) in the `ThreadLocalData` is a pointer to a managed `object[]` which points at either `object[]`, `byte[]`, or `double[]` arrays.
|
||||
At GC scan time, the pointer to the initial object[] is the only detail which needs to be reported to the GC.
|
||||
|
||||
A collectible thread static is a thread static which can be collected by the runtime.
|
||||
This describes the static variables defined on types which can be collected by the runtime.
|
||||
The pointer (`pCollectibleTlsArrayData`) in the `ThreadLocalData` is a pointer to a chunk of memory allocated via `malloc`, and holds pointers to `object[]`, `byte[]`, or `double[]` arrays.
|
||||
At GC scan time, each managed object must individually be kept alive only if the type and thread is still alive. This requires properly handling several situations.
|
||||
1. If a collectible assembly becomes unreferenced, but a thread static variable associated with it has a finalizer, the object must move to the finalization queue.
|
||||
2. If a thread static variable associated with a collectible assembly refers to the collectible assembly `LoaderAllocator` via a series of object references, it must not provide a reason for the collectible assembly to be considered referenced.
|
||||
3. If a collectible assembly is collected, then the associated static variables no longer exist, and the TLSIndex values associated with that collectible assembly becomes re-useable.
|
||||
4. If a thread is no longer executing, then all thread statics associated with that thread are no longer kept alive.
|
||||
|
||||
The approach chosen is to use a pair of different handle types.
|
||||
For efficient access, the handle type stored in the dynamically adjusted array is a WeakTrackResurrection GCHandle.
|
||||
This handle instance is associated with the slot in the TLS data, not with the exact instantiation, so it can be re-used when the if the associated collectible assembly is collected, and then the slot is re-used.
|
||||
In addition, each slot that is in use will have a `LOADERHANDLE` which will keep the object alive until the `LoaderAllocator` is freed.
|
||||
This `LOADERHANDLE` will be abandoned if the `LoaderAllocator` is collected, but that's ok, as `LOADERHANDLE` only needs to be cleaned up if the `LoaderAllocator` isn't collected.
|
||||
On thread destroy, for each collectible slot in the tls array, we will explicitly free the `LOADERHANDLE` on the correct `LoaderAllocator`.
|
||||
|
||||
Physical Architecture
|
||||
=====================
|
||||
|
@ -221,6 +345,7 @@ Major parts of the type system are found in:
|
|||
- Array – Code for handling the special cases required for array processing
|
||||
- VirtualStubDispatch.cpp/h/inl – Code for virtual stub dispatch
|
||||
- VirtualCallStubCpu.hpp – Processor specific code for virtual stub dispatch.
|
||||
- threadstatics.cpp/h - Handling for thread static variables.
|
||||
|
||||
Major entry points are BuildMethodTable, LoadTypeHandleThrowing, CanCastTo\*, GetMethodDescFromMemberDefOrRefOrSpecThrowing, GetFieldDescFromMemberRefThrowing, CompareSigs, and VirtualCallStubManager::ResolveWorkerStatic.
|
||||
|
||||
|
|
|
@ -693,8 +693,8 @@ namespace System.Runtime.CompilerServices
|
|||
[FieldOffset(0)]
|
||||
private uint Flags;
|
||||
|
||||
private const uint enum_flag_CanCompareBitsOrUseFastGetHashCode = 0x0001; // Is any field type or sub field type overrode Equals or GetHashCode
|
||||
private const uint enum_flag_HasCheckedCanCompareBitsOrUseFastGetHashCode = 0x0002; // Whether we have checked the overridden Equals or GetHashCode
|
||||
private const uint enum_flag_CanCompareBitsOrUseFastGetHashCode = 0x0004; // Is any field type or sub field type overridden Equals or GetHashCode
|
||||
|
||||
public bool HasCheckedCanCompareBitsOrUseFastGetHashCode => (Flags & enum_flag_HasCheckedCanCompareBitsOrUseFastGetHashCode) != 0;
|
||||
|
||||
|
|
|
@ -1715,8 +1715,8 @@ ClrDataAccess::GetModuleData(CLRDATA_ADDRESS addr, struct DacpModuleData *Module
|
|||
ModuleData->bIsReflection = pModule->IsReflection();
|
||||
ModuleData->bIsPEFile = pModule->IsPEFile();
|
||||
ModuleData->Assembly = HOST_CDADDR(pModule->GetAssembly());
|
||||
ModuleData->dwModuleID = pModule->GetModuleID();
|
||||
ModuleData->dwModuleIndex = pModule->GetModuleIndex().m_dwIndex;
|
||||
ModuleData->dwModuleID = 0; // CoreCLR no longer has this concept
|
||||
ModuleData->dwModuleIndex = 0; // CoreCLR no longer has this concept
|
||||
ModuleData->dwTransientFlags = pModule->m_dwTransientFlags;
|
||||
ModuleData->LoaderAllocator = HOST_CDADDR(pModule->m_loaderAllocator);
|
||||
ModuleData->ThunkHeap = HOST_CDADDR(pModule->m_pThunkHeap);
|
||||
|
@ -3246,47 +3246,16 @@ ClrDataAccess::GetNestedExceptionData(CLRDATA_ADDRESS exception, CLRDATA_ADDRESS
|
|||
HRESULT
|
||||
ClrDataAccess::GetDomainLocalModuleData(CLRDATA_ADDRESS addr, struct DacpDomainLocalModuleData *pLocalModuleData)
|
||||
{
|
||||
if (addr == 0 || pLocalModuleData == NULL)
|
||||
return E_INVALIDARG;
|
||||
|
||||
SOSDacEnter();
|
||||
|
||||
DomainLocalModule* pLocalModule = PTR_DomainLocalModule(TO_TADDR(addr));
|
||||
|
||||
pLocalModuleData->pGCStaticDataStart = TO_CDADDR(PTR_TO_TADDR(pLocalModule->GetPrecomputedGCStaticsBasePointer()));
|
||||
pLocalModuleData->pNonGCStaticDataStart = TO_CDADDR(pLocalModule->GetPrecomputedNonGCStaticsBasePointer());
|
||||
pLocalModuleData->pDynamicClassTable = PTR_CDADDR(pLocalModule->m_pDynamicClassTable.Load());
|
||||
pLocalModuleData->pClassData = (TADDR) (PTR_HOST_MEMBER_TADDR(DomainLocalModule, pLocalModule, m_pDataBlob));
|
||||
|
||||
SOSDacLeave();
|
||||
return hr;
|
||||
// CoreCLR does not use domain local modules anymore
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
||||
HRESULT
|
||||
ClrDataAccess::GetDomainLocalModuleDataFromModule(CLRDATA_ADDRESS addr, struct DacpDomainLocalModuleData *pLocalModuleData)
|
||||
{
|
||||
if (addr == 0 || pLocalModuleData == NULL)
|
||||
return E_INVALIDARG;
|
||||
|
||||
SOSDacEnter();
|
||||
|
||||
Module* pModule = PTR_Module(TO_TADDR(addr));
|
||||
DomainLocalModule* pLocalModule = PTR_DomainLocalModule(pModule->GetDomainLocalModule());
|
||||
if (!pLocalModule)
|
||||
{
|
||||
hr = E_INVALIDARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
pLocalModuleData->pGCStaticDataStart = TO_CDADDR(PTR_TO_TADDR(pLocalModule->GetPrecomputedGCStaticsBasePointer()));
|
||||
pLocalModuleData->pNonGCStaticDataStart = TO_CDADDR(pLocalModule->GetPrecomputedNonGCStaticsBasePointer());
|
||||
pLocalModuleData->pDynamicClassTable = PTR_CDADDR(pLocalModule->m_pDynamicClassTable.Load());
|
||||
pLocalModuleData->pClassData = (TADDR) (PTR_HOST_MEMBER_TADDR(DomainLocalModule, pLocalModule, m_pDataBlob));
|
||||
}
|
||||
|
||||
SOSDacLeave();
|
||||
return hr;
|
||||
// CoreCLR does not use domain local modules anymore
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
|
@ -3299,31 +3268,8 @@ ClrDataAccess::GetDomainLocalModuleDataFromAppDomain(CLRDATA_ADDRESS appDomainAd
|
|||
HRESULT
|
||||
ClrDataAccess::GetThreadLocalModuleData(CLRDATA_ADDRESS thread, unsigned int index, struct DacpThreadLocalModuleData *pLocalModuleData)
|
||||
{
|
||||
if (pLocalModuleData == NULL)
|
||||
return E_INVALIDARG;
|
||||
|
||||
SOSDacEnter();
|
||||
|
||||
pLocalModuleData->threadAddr = thread;
|
||||
pLocalModuleData->ModuleIndex = index;
|
||||
|
||||
PTR_Thread pThread = PTR_Thread(TO_TADDR(thread));
|
||||
PTR_ThreadLocalBlock pLocalBlock = ThreadStatics::GetCurrentTLB(pThread);
|
||||
PTR_ThreadLocalModule pLocalModule = pLocalBlock->GetTLMIfExists(ModuleIndex(index));
|
||||
if (!pLocalModule)
|
||||
{
|
||||
hr = E_INVALIDARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
pLocalModuleData->pGCStaticDataStart = TO_CDADDR(PTR_TO_TADDR(pLocalModule->GetPrecomputedGCStaticsBasePointer()));
|
||||
pLocalModuleData->pNonGCStaticDataStart = TO_CDADDR(pLocalModule->GetPrecomputedNonGCStaticsBasePointer());
|
||||
pLocalModuleData->pDynamicClassTable = PTR_CDADDR(pLocalModule->m_pDynamicClassTable);
|
||||
pLocalModuleData->pClassData = (TADDR) (PTR_HOST_MEMBER_TADDR(ThreadLocalModule, pLocalModule, m_pDataBlob));
|
||||
}
|
||||
|
||||
SOSDacLeave();
|
||||
return hr;
|
||||
// CoreCLR does not use thread local modules anymore
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3656,6 +3602,7 @@ static const char *LoaderAllocatorLoaderHeapNames[] =
|
|||
{
|
||||
"LowFrequencyHeap",
|
||||
"HighFrequencyHeap",
|
||||
"StaticsHeap",
|
||||
"StubHeap",
|
||||
"ExecutableHeap",
|
||||
"FixupPrecodeHeap",
|
||||
|
@ -3690,6 +3637,7 @@ HRESULT ClrDataAccess::GetLoaderAllocatorHeaps(CLRDATA_ADDRESS loaderAllocatorAd
|
|||
int i = 0;
|
||||
pLoaderHeaps[i++] = HOST_CDADDR(pLoaderAllocator->GetLowFrequencyHeap());
|
||||
pLoaderHeaps[i++] = HOST_CDADDR(pLoaderAllocator->GetHighFrequencyHeap());
|
||||
pLoaderHeaps[i++] = HOST_CDADDR(pLoaderAllocator->GetStaticsHeap());
|
||||
pLoaderHeaps[i++] = HOST_CDADDR(pLoaderAllocator->GetStubHeap());
|
||||
pLoaderHeaps[i++] = HOST_CDADDR(pLoaderAllocator->GetExecutableHeap());
|
||||
pLoaderHeaps[i++] = HOST_CDADDR(pLoaderAllocator->GetFixupPrecodeHeap());
|
||||
|
|
|
@ -185,7 +185,7 @@ End
|
|||
Crst DelegateToFPtrHash
|
||||
End
|
||||
|
||||
Crst DomainLocalBlock
|
||||
Crst GenericDictionaryExpansion
|
||||
AcquiredBefore PinnedHeapHandleTable IbcProfile LoaderHeap SystemDomainDelayedUnloadList UniqueStack
|
||||
End
|
||||
|
||||
|
@ -265,7 +265,7 @@ Crst InstMethodHashTable
|
|||
End
|
||||
|
||||
Crst Interop
|
||||
AcquiredBefore PinnedHeapHandleTable AvailableParamTypes ClassInit DeadlockDetection DomainLocalBlock
|
||||
AcquiredBefore PinnedHeapHandleTable AvailableParamTypes ClassInit DeadlockDetection GenericDictionaryExpansion
|
||||
HandleTable InstMethodHashTable InteropData JitGenericHandleCache LoaderHeap SigConvert
|
||||
StubDispatchCache StubUnwindInfoHeapSegments SyncBlockCache TypeIDMap UnresolvedClassLock
|
||||
PendingTypeLoadEntry
|
||||
|
@ -315,7 +315,7 @@ End
|
|||
|
||||
Crst LoaderAllocator
|
||||
AcquiredBefore PinnedHeapHandleTable HandleTable UniqueStack ThreadStore
|
||||
AcquiredAfter DomainLocalBlock
|
||||
AcquiredAfter GenericDictionaryExpansion
|
||||
End
|
||||
|
||||
Crst LoaderAllocatorReferences
|
||||
|
@ -364,7 +364,7 @@ End
|
|||
Crst PendingTypeLoadEntry
|
||||
AcquiredBefore AppDomainCache PinnedHeapHandleTable AssemblyLoader AvailableClass AvailableParamTypes
|
||||
BaseDomain ClassInit DeadlockDetection DebuggerController DebuggerJitInfo DebuggerMutex
|
||||
DomainLocalBlock Exception ExecuteManRangeLock FuncPtrStubs
|
||||
GenericDictionaryExpansion Exception ExecuteManRangeLock FuncPtrStubs
|
||||
FusionAppCtx GlobalStrLiteralMap HandleTable IbcProfile
|
||||
IJWFixupData IJWHash ISymUnmanagedReader Jit JumpStubCache LoaderHeap
|
||||
Module ModuleLookupTable PEImage
|
||||
|
@ -476,6 +476,10 @@ End
|
|||
Crst SystemDomainDelayedUnloadList
|
||||
End
|
||||
|
||||
Crst ThreadLocalStorageLock
|
||||
AcquiredBefore ModuleLookupTable
|
||||
End
|
||||
|
||||
Crst ThreadIdDispenser
|
||||
End
|
||||
|
||||
|
@ -541,7 +545,7 @@ End
|
|||
|
||||
Crst EventPipe
|
||||
AcquiredAfter PendingTypeLoadEntry
|
||||
AcquiredBefore ThreadIdDispenser ThreadStore DomainLocalBlock InstMethodHashTable
|
||||
AcquiredBefore ThreadIdDispenser ThreadStore GenericDictionaryExpansion InstMethodHashTable
|
||||
End
|
||||
|
||||
Crst NotifyGdb
|
||||
|
@ -574,10 +578,6 @@ Crst PgoData
|
|||
AcquiredBefore LoaderHeap
|
||||
End
|
||||
|
||||
Crst StaticBoxInit
|
||||
AcquiredBefore LoaderHeap FrozenObjectHeap AssemblyLoader
|
||||
End
|
||||
|
||||
Crst PerfMap
|
||||
AcquiredAfter CodeVersioning AssemblyList
|
||||
End
|
||||
|
|
|
@ -163,8 +163,6 @@ enum CORCOMPILE_FIXUP_BLOB_KIND
|
|||
ENCODE_VERIFY_IL_BODY, /* Verify an IL body is defined the same at compile time and runtime. A failed match will cause a hard runtime failure. */
|
||||
|
||||
ENCODE_MODULE_HANDLE = 0x50, /* Module token */
|
||||
ENCODE_MODULE_ID_FOR_GENERIC_STATICS, /* For accessing static fields */
|
||||
ENCODE_CLASS_ID_FOR_STATICS, /* For accessing static fields */
|
||||
ENCODE_SYNC_LOCK, /* For synchronizing access to a type */
|
||||
ENCODE_PROFILING_HANDLE, /* For the method's profiling counter */
|
||||
ENCODE_VARARGS_METHODDEF, /* For calling a varargs method */
|
||||
|
|
|
@ -528,28 +528,31 @@ enum CorInfoHelpFunc
|
|||
// ICorClassInfo::getSharedStaticsOrCCtorHelper to determine which helper to use
|
||||
|
||||
// Helpers for regular statics
|
||||
CORINFO_HELP_GETGENERICS_GCSTATIC_BASE,
|
||||
CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE,
|
||||
CORINFO_HELP_GETSHARED_GCSTATIC_BASE,
|
||||
CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE,
|
||||
CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS,
|
||||
CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS,
|
||||
// Helper to class initialize shared generic with dynamicclass, but not get static field address
|
||||
CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS,
|
||||
CORINFO_HELP_GET_GCSTATIC_BASE,
|
||||
CORINFO_HELP_GET_NONGCSTATIC_BASE,
|
||||
CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE,
|
||||
CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE,
|
||||
CORINFO_HELP_GETPINNED_GCSTATIC_BASE,
|
||||
CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE,
|
||||
CORINFO_HELP_GET_GCSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GET_NONGCSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETPINNED_GCSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE_NOCTOR,
|
||||
|
||||
// Helpers for thread statics
|
||||
CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE,
|
||||
CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE,
|
||||
CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE,
|
||||
CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE,
|
||||
CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS,
|
||||
CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS,
|
||||
CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED,
|
||||
CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED,
|
||||
CORINFO_HELP_GET_GCTHREADSTATIC_BASE,
|
||||
CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE,
|
||||
CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE,
|
||||
CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE,
|
||||
CORINFO_HELP_GET_GCTHREADSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED,
|
||||
CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED,
|
||||
CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED2,
|
||||
|
||||
/* Debugger */
|
||||
|
||||
|
@ -1698,7 +1701,7 @@ struct CORINFO_THREAD_STATIC_BLOCKS_INFO
|
|||
uint32_t offsetOfThreadLocalStoragePointer; // windows specific
|
||||
uint32_t offsetOfMaxThreadStaticBlocks;
|
||||
uint32_t offsetOfThreadStaticBlocks;
|
||||
uint32_t offsetOfGCDataPointer;
|
||||
uint32_t offsetOfBaseOfThreadLocalData;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -2403,18 +2406,20 @@ public:
|
|||
virtual void* LongLifetimeMalloc(size_t sz) = 0;
|
||||
virtual void LongLifetimeFree(void* obj) = 0;
|
||||
|
||||
virtual size_t getClassModuleIdForStatics (
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
CORINFO_MODULE_HANDLE * pModule,
|
||||
void ** ppIndirection
|
||||
) = 0;
|
||||
|
||||
virtual bool getIsClassInitedFlagAddress(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
CORINFO_CONST_LOOKUP* addr,
|
||||
int* offset
|
||||
) = 0;
|
||||
|
||||
virtual size_t getClassStaticDynamicInfo (
|
||||
CORINFO_CLASS_HANDLE cls
|
||||
) = 0;
|
||||
|
||||
virtual size_t getClassThreadStaticDynamicInfo (
|
||||
CORINFO_CLASS_HANDLE cls
|
||||
) = 0;
|
||||
|
||||
virtual bool getStaticBaseAddress(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
bool isGc,
|
||||
|
@ -2824,8 +2829,7 @@ public:
|
|||
|
||||
// Returns the thread static block information like offsets, etc. from current TLS.
|
||||
virtual void getThreadLocalStaticBlocksInfo (
|
||||
CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo,
|
||||
bool isGCType
|
||||
CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo
|
||||
) = 0;
|
||||
|
||||
virtual void getThreadLocalStaticInfo_NativeAOT(
|
||||
|
@ -3245,12 +3249,6 @@ public:
|
|||
CORINFO_CALL_INFO *pResult
|
||||
) = 0;
|
||||
|
||||
// Returns the class's domain ID for accessing shared statics
|
||||
virtual unsigned getClassDomainID (
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
void **ppIndirection = NULL
|
||||
) = 0;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// getStaticFieldContent: returns true and the actual field's value if the given
|
||||
// field represents a statically initialized readonly field of any type.
|
||||
|
|
|
@ -41,20 +41,20 @@ enum CrstType
|
|||
CrstDebuggerJitInfo = 23,
|
||||
CrstDebuggerMutex = 24,
|
||||
CrstDelegateToFPtrHash = 25,
|
||||
CrstDomainLocalBlock = 26,
|
||||
CrstDynamicIL = 27,
|
||||
CrstDynamicMT = 28,
|
||||
CrstEtwTypeLogHash = 29,
|
||||
CrstEventPipe = 30,
|
||||
CrstEventStore = 31,
|
||||
CrstException = 32,
|
||||
CrstExecutableAllocatorLock = 33,
|
||||
CrstExecuteManRangeLock = 34,
|
||||
CrstFCall = 35,
|
||||
CrstFrozenObjectHeap = 36,
|
||||
CrstFuncPtrStubs = 37,
|
||||
CrstFusionAppCtx = 38,
|
||||
CrstGCCover = 39,
|
||||
CrstDynamicIL = 26,
|
||||
CrstDynamicMT = 27,
|
||||
CrstEtwTypeLogHash = 28,
|
||||
CrstEventPipe = 29,
|
||||
CrstEventStore = 30,
|
||||
CrstException = 31,
|
||||
CrstExecutableAllocatorLock = 32,
|
||||
CrstExecuteManRangeLock = 33,
|
||||
CrstFCall = 34,
|
||||
CrstFrozenObjectHeap = 35,
|
||||
CrstFuncPtrStubs = 36,
|
||||
CrstFusionAppCtx = 37,
|
||||
CrstGCCover = 38,
|
||||
CrstGenericDictionaryExpansion = 39,
|
||||
CrstGlobalStrLiteralMap = 40,
|
||||
CrstHandleTable = 41,
|
||||
CrstIbcProfile = 42,
|
||||
|
@ -111,17 +111,17 @@ enum CrstType
|
|||
CrstSingleUseLock = 93,
|
||||
CrstSpecialStatics = 94,
|
||||
CrstStackSampler = 95,
|
||||
CrstStaticBoxInit = 96,
|
||||
CrstStressLog = 97,
|
||||
CrstStubCache = 98,
|
||||
CrstStubDispatchCache = 99,
|
||||
CrstStubUnwindInfoHeapSegments = 100,
|
||||
CrstSyncBlockCache = 101,
|
||||
CrstSyncHashLock = 102,
|
||||
CrstSystemBaseDomain = 103,
|
||||
CrstSystemDomain = 104,
|
||||
CrstSystemDomainDelayedUnloadList = 105,
|
||||
CrstThreadIdDispenser = 106,
|
||||
CrstStressLog = 96,
|
||||
CrstStubCache = 97,
|
||||
CrstStubDispatchCache = 98,
|
||||
CrstStubUnwindInfoHeapSegments = 99,
|
||||
CrstSyncBlockCache = 100,
|
||||
CrstSyncHashLock = 101,
|
||||
CrstSystemBaseDomain = 102,
|
||||
CrstSystemDomain = 103,
|
||||
CrstSystemDomainDelayedUnloadList = 104,
|
||||
CrstThreadIdDispenser = 105,
|
||||
CrstThreadLocalStorageLock = 106,
|
||||
CrstThreadStore = 107,
|
||||
CrstTieredCompilation = 108,
|
||||
CrstTypeEquivalenceMap = 109,
|
||||
|
@ -170,7 +170,6 @@ int g_rgCrstLevelMap[] =
|
|||
4, // CrstDebuggerJitInfo
|
||||
13, // CrstDebuggerMutex
|
||||
0, // CrstDelegateToFPtrHash
|
||||
18, // CrstDomainLocalBlock
|
||||
0, // CrstDynamicIL
|
||||
10, // CrstDynamicMT
|
||||
0, // CrstEtwTypeLogHash
|
||||
|
@ -184,6 +183,7 @@ int g_rgCrstLevelMap[] =
|
|||
7, // CrstFuncPtrStubs
|
||||
10, // CrstFusionAppCtx
|
||||
10, // CrstGCCover
|
||||
18, // CrstGenericDictionaryExpansion
|
||||
17, // CrstGlobalStrLiteralMap
|
||||
1, // CrstHandleTable
|
||||
0, // CrstIbcProfile
|
||||
|
@ -240,7 +240,6 @@ int g_rgCrstLevelMap[] =
|
|||
5, // CrstSingleUseLock
|
||||
0, // CrstSpecialStatics
|
||||
0, // CrstStackSampler
|
||||
15, // CrstStaticBoxInit
|
||||
-1, // CrstStressLog
|
||||
5, // CrstStubCache
|
||||
0, // CrstStubDispatchCache
|
||||
|
@ -251,6 +250,7 @@ int g_rgCrstLevelMap[] =
|
|||
15, // CrstSystemDomain
|
||||
0, // CrstSystemDomainDelayedUnloadList
|
||||
0, // CrstThreadIdDispenser
|
||||
5, // CrstThreadLocalStorageLock
|
||||
14, // CrstThreadStore
|
||||
8, // CrstTieredCompilation
|
||||
4, // CrstTypeEquivalenceMap
|
||||
|
@ -293,7 +293,6 @@ LPCSTR g_rgCrstNameMap[] =
|
|||
"CrstDebuggerJitInfo",
|
||||
"CrstDebuggerMutex",
|
||||
"CrstDelegateToFPtrHash",
|
||||
"CrstDomainLocalBlock",
|
||||
"CrstDynamicIL",
|
||||
"CrstDynamicMT",
|
||||
"CrstEtwTypeLogHash",
|
||||
|
@ -307,6 +306,7 @@ LPCSTR g_rgCrstNameMap[] =
|
|||
"CrstFuncPtrStubs",
|
||||
"CrstFusionAppCtx",
|
||||
"CrstGCCover",
|
||||
"CrstGenericDictionaryExpansion",
|
||||
"CrstGlobalStrLiteralMap",
|
||||
"CrstHandleTable",
|
||||
"CrstIbcProfile",
|
||||
|
@ -363,7 +363,6 @@ LPCSTR g_rgCrstNameMap[] =
|
|||
"CrstSingleUseLock",
|
||||
"CrstSpecialStatics",
|
||||
"CrstStackSampler",
|
||||
"CrstStaticBoxInit",
|
||||
"CrstStressLog",
|
||||
"CrstStubCache",
|
||||
"CrstStubDispatchCache",
|
||||
|
@ -374,6 +373,7 @@ LPCSTR g_rgCrstNameMap[] =
|
|||
"CrstSystemDomain",
|
||||
"CrstSystemDomainDelayedUnloadList",
|
||||
"CrstThreadIdDispenser",
|
||||
"CrstThreadLocalStorageLock",
|
||||
"CrstThreadStore",
|
||||
"CrstTieredCompilation",
|
||||
"CrstTypeEquivalenceMap",
|
||||
|
|
|
@ -145,7 +145,6 @@ DEFINE_DACVAR(gc_alloc_context, dac__g_global_alloc_context, ::g_global_alloc_co
|
|||
DEFINE_DACVAR(IGCHeap, dac__g_pGCHeap, ::g_pGCHeap)
|
||||
|
||||
DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pThinLockThreadIdDispenser, ::g_pThinLockThreadIdDispenser)
|
||||
DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pModuleIndexDispenser, ::g_pModuleIndexDispenser)
|
||||
DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pObjectClass, ::g_pObjectClass)
|
||||
DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pRuntimeTypeClass, ::g_pRuntimeTypeClass)
|
||||
DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pCanonMethodTableClass, ::g_pCanonMethodTableClass)
|
||||
|
|
|
@ -49,4 +49,10 @@ inline auto operator ^= (T& left, T right) -> const decltype(T::support_use_as_f
|
|||
return left;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool HasFlag(T value, decltype(T::support_use_as_flags) flag)
|
||||
{
|
||||
return (value & flag) == flag;
|
||||
}
|
||||
|
||||
#endif /* ENUM_CLASS_FLAGS_OPERATORS */
|
|
@ -208,16 +208,17 @@ void* LongLifetimeMalloc(
|
|||
void LongLifetimeFree(
|
||||
void* obj) override;
|
||||
|
||||
size_t getClassModuleIdForStatics(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
CORINFO_MODULE_HANDLE* pModule,
|
||||
void** ppIndirection) override;
|
||||
|
||||
bool getIsClassInitedFlagAddress(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
CORINFO_CONST_LOOKUP* addr,
|
||||
int* offset) override;
|
||||
|
||||
size_t getClassThreadStaticDynamicInfo(
|
||||
CORINFO_CLASS_HANDLE clr) override;
|
||||
|
||||
size_t getClassStaticDynamicInfo(
|
||||
CORINFO_CLASS_HANDLE clr) override;
|
||||
|
||||
bool getStaticBaseAddress(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
bool isGc,
|
||||
|
@ -404,8 +405,7 @@ uint32_t getThreadLocalFieldInfo(
|
|||
bool isGCtype) override;
|
||||
|
||||
void getThreadLocalStaticBlocksInfo(
|
||||
CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo,
|
||||
bool isGCType) override;
|
||||
CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo) override;
|
||||
|
||||
void getThreadLocalStaticInfo_NativeAOT(
|
||||
CORINFO_THREAD_STATIC_INFO_NATIVEAOT* pInfo) override;
|
||||
|
@ -600,10 +600,6 @@ void getCallInfo(
|
|||
CORINFO_CALLINFO_FLAGS flags,
|
||||
CORINFO_CALL_INFO* pResult) override;
|
||||
|
||||
unsigned getClassDomainID(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
void** ppIndirection) override;
|
||||
|
||||
bool getStaticFieldContent(
|
||||
CORINFO_FIELD_HANDLE field,
|
||||
uint8_t* buffer,
|
||||
|
|
|
@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
|
|||
#define GUID_DEFINED
|
||||
#endif // !GUID_DEFINED
|
||||
|
||||
constexpr GUID JITEEVersionIdentifier = { /* 6e0b439f-0d18-4836-a486-4962af0cc948 */
|
||||
0x6e0b439f,
|
||||
0x0d18,
|
||||
0x4836,
|
||||
{0xa4, 0x86, 0x49, 0x62, 0xaf, 0x0c, 0xc9, 0x48}
|
||||
constexpr GUID JITEEVersionIdentifier = { /* de0cd36d-3094-4110-af7d-31eb36234e46 */
|
||||
0xde0cd36d,
|
||||
0x3094,
|
||||
0x4110,
|
||||
{0xaf, 0x7d, 0x31, 0xeb, 0x36, 0x23, 0x4e, 0x46}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -177,35 +177,31 @@
|
|||
JITHELPER(CORINFO_HELP_GETSTATICFIELDADDR, JIT_GetStaticFieldAddr,CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GETSTATICFIELDADDR_TLS, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB)
|
||||
|
||||
JITHELPER(CORINFO_HELP_GETGENERICS_GCSTATIC_BASE, JIT_GetGenericsGCStaticBase,CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE, JIT_GetGenericsNonGCStaticBase,CORINFO_HELP_SIG_REG_ONLY)
|
||||
|
||||
#ifdef TARGET_X86
|
||||
DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_GCSTATIC_BASE, NULL, CORINFO_HELP_SIG_REG_ONLY)
|
||||
DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE, NULL, CORINFO_HELP_SIG_REG_ONLY)
|
||||
DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR, NULL, CORINFO_HELP_SIG_REG_ONLY)
|
||||
DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR,NULL, CORINFO_HELP_SIG_REG_ONLY)
|
||||
#else
|
||||
DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_GCSTATIC_BASE, JIT_GetSharedGCStaticBase, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB)
|
||||
DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE, JIT_GetSharedNonGCStaticBase, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB)
|
||||
DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR, JIT_GetSharedGCStaticBaseNoCtor, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB)
|
||||
DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR,JIT_GetSharedNonGCStaticBaseNoCtor, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB)
|
||||
#endif
|
||||
JITHELPER(CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS, JIT_GetSharedGCStaticBaseDynamicClass,CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS, JIT_GetSharedNonGCStaticBaseDynamicClass,CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS, JIT_ClassInitDynamicClass,CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GET_GCSTATIC_BASE, JIT_GetGCStaticBase, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB)
|
||||
JITHELPER(CORINFO_HELP_GET_NONGCSTATIC_BASE, JIT_GetNonGCStaticBase, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB)
|
||||
JITHELPER(CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE, JIT_GetDynamicGCStaticBase, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB)
|
||||
JITHELPER(CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE, JIT_GetDynamicNonGCStaticBase, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB)
|
||||
JITHELPER(CORINFO_HELP_GETPINNED_GCSTATIC_BASE, JIT_GetDynamicGCStaticBase, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB)
|
||||
JITHELPER(CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE, JIT_GetDynamicNonGCStaticBase, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB)
|
||||
JITHELPER(CORINFO_HELP_GET_GCSTATIC_BASE_NOCTOR, JIT_GetGCStaticBaseNoCtor, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB)
|
||||
JITHELPER(CORINFO_HELP_GET_NONGCSTATIC_BASE_NOCTOR, JIT_GetNonGCStaticBaseNoCtor, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB)
|
||||
JITHELPER(CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE_NOCTOR, JIT_GetDynamicGCStaticBaseNoCtor, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB)
|
||||
JITHELPER(CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE_NOCTOR,JIT_GetDynamicNonGCStaticBaseNoCtor, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB)
|
||||
JITHELPER(CORINFO_HELP_GETPINNED_GCSTATIC_BASE_NOCTOR, JIT_GetDynamicGCStaticBaseNoCtor, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB)
|
||||
JITHELPER(CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE_NOCTOR,JIT_GetDynamicNonGCStaticBaseNoCtor, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB)
|
||||
|
||||
// Thread statics
|
||||
JITHELPER(CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE, JIT_GetGenericsGCThreadStaticBase,CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE, JIT_GetGenericsNonGCThreadStaticBase,CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE, JIT_GetSharedGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE, JIT_GetSharedNonGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR, JIT_GetSharedGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR, JIT_GetSharedNonGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS, JIT_GetSharedGCThreadStaticBaseDynamicClass, CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS, JIT_GetSharedNonGCThreadStaticBaseDynamicClass, CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED, JIT_GetSharedGCThreadStaticBaseOptimized, CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED, JIT_GetSharedNonGCThreadStaticBaseOptimized, CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GET_GCTHREADSTATIC_BASE, JIT_GetGCThreadStaticBase,CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE, JIT_GetNonGCThreadStaticBase,CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE, JIT_GetDynamicGCThreadStaticBase,CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE, JIT_GetDynamicNonGCThreadStaticBase,CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GET_GCTHREADSTATIC_BASE_NOCTOR, JIT_GetGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE_NOCTOR, JIT_GetNonGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR, JIT_GetDynamicGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR,JIT_GetDynamicNonGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED,JIT_GetGCThreadStaticBaseOptimized, CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED,JIT_GetNonGCThreadStaticBaseOptimized, CORINFO_HELP_SIG_REG_ONLY)
|
||||
JITHELPER(CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED2,JIT_GetNonGCThreadStaticBaseOptimized2, CORINFO_HELP_SIG_REG_ONLY)
|
||||
|
||||
// Debugger
|
||||
JITHELPER(CORINFO_HELP_DBG_IS_JUST_MY_CODE, JIT_DbgIsJustMyCode,CORINFO_HELP_SIG_REG_ONLY)
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
// src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h
|
||||
// If you update this, ensure you run `git grep MINIMUM_READYTORUN_MAJOR_VERSION`
|
||||
// and handle pending work.
|
||||
#define READYTORUN_MAJOR_VERSION 0x0009
|
||||
#define READYTORUN_MINOR_VERSION 0x0003
|
||||
#define READYTORUN_MAJOR_VERSION 10
|
||||
#define READYTORUN_MINOR_VERSION 0x0000
|
||||
|
||||
#define MINIMUM_READYTORUN_MAJOR_VERSION 0x009
|
||||
#define MINIMUM_READYTORUN_MAJOR_VERSION 10
|
||||
|
||||
// R2R Version 2.1 adds the InliningInfo section
|
||||
// R2R Version 2.2 adds the ProfileDataInfo section
|
||||
|
@ -36,6 +36,7 @@
|
|||
// R2R Version 9.2 adds MemZero and NativeMemSet helpers
|
||||
// R2R Version 9.3 adds BulkWriteBarrier helper
|
||||
// uses GCInfo v3, which makes safe points in partially interruptible code interruptible.
|
||||
// R2R Version 10.0 adds support for the statics being allocated on a per type basis instead of on a per module basis
|
||||
|
||||
struct READYTORUN_CORE_HEADER
|
||||
{
|
||||
|
|
|
@ -51,10 +51,10 @@ HELPER(READYTORUN_HELPER_NewArray, CORINFO_HELP_NEWARR_1_DIRECT
|
|||
HELPER(READYTORUN_HELPER_CheckCastAny, CORINFO_HELP_CHKCASTANY, )
|
||||
HELPER(READYTORUN_HELPER_CheckInstanceAny, CORINFO_HELP_ISINSTANCEOFANY, )
|
||||
|
||||
HELPER(READYTORUN_HELPER_GenericGcStaticBase, CORINFO_HELP_GETGENERICS_GCSTATIC_BASE, )
|
||||
HELPER(READYTORUN_HELPER_GenericNonGcStaticBase, CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE, )
|
||||
HELPER(READYTORUN_HELPER_GenericGcTlsBase, CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE, )
|
||||
HELPER(READYTORUN_HELPER_GenericNonGcTlsBase, CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE,)
|
||||
HELPER(READYTORUN_HELPER_GenericGcStaticBase, CORINFO_HELP_GET_GCSTATIC_BASE, )
|
||||
HELPER(READYTORUN_HELPER_GenericNonGcStaticBase, CORINFO_HELP_GET_NONGCSTATIC_BASE, )
|
||||
HELPER(READYTORUN_HELPER_GenericGcTlsBase, CORINFO_HELP_GET_GCTHREADSTATIC_BASE, )
|
||||
HELPER(READYTORUN_HELPER_GenericNonGcTlsBase, CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE, )
|
||||
|
||||
HELPER(READYTORUN_HELPER_VirtualFuncPtr, CORINFO_HELP_VIRTUAL_FUNC_PTR, )
|
||||
HELPER(READYTORUN_HELPER_IsInstanceOfException, CORINFO_HELP_ISINSTANCEOF_EXCEPTION, )
|
||||
|
|
|
@ -444,7 +444,7 @@ interface ISOSDacInterface8 : IUnknown
|
|||
// Increment anytime there is a change in the data structures that SOS depends on like
|
||||
// stress log structs (StressMsg, StressLogChunck, ThreadStressLog, etc), exception
|
||||
// stack traces (StackTraceElement), the PredefinedTlsSlots enums, etc.
|
||||
cpp_quote("#define SOS_BREAKING_CHANGE_VERSION 4")
|
||||
cpp_quote("#define SOS_BREAKING_CHANGE_VERSION 5")
|
||||
|
||||
[
|
||||
object,
|
||||
|
|
|
@ -50,8 +50,9 @@ DEF_CLR_API(getModuleAssembly)
|
|||
DEF_CLR_API(getAssemblyName)
|
||||
DEF_CLR_API(LongLifetimeMalloc)
|
||||
DEF_CLR_API(LongLifetimeFree)
|
||||
DEF_CLR_API(getClassModuleIdForStatics)
|
||||
DEF_CLR_API(getIsClassInitedFlagAddress)
|
||||
DEF_CLR_API(getClassThreadStaticDynamicInfo)
|
||||
DEF_CLR_API(getClassStaticDynamicInfo)
|
||||
DEF_CLR_API(getStaticBaseAddress)
|
||||
DEF_CLR_API(getClassSize)
|
||||
DEF_CLR_API(getHeapClassSize)
|
||||
|
@ -148,7 +149,6 @@ DEF_CLR_API(canGetCookieForPInvokeCalliSig)
|
|||
DEF_CLR_API(getJustMyCodeHandle)
|
||||
DEF_CLR_API(GetProfilingHandle)
|
||||
DEF_CLR_API(getCallInfo)
|
||||
DEF_CLR_API(getClassDomainID)
|
||||
DEF_CLR_API(getStaticFieldContent)
|
||||
DEF_CLR_API(getObjectContent)
|
||||
DEF_CLR_API(getStaticFieldCurrentClass)
|
||||
|
|
|
@ -460,17 +460,6 @@ void WrapICorJitInfo::LongLifetimeFree(
|
|||
API_LEAVE(LongLifetimeFree);
|
||||
}
|
||||
|
||||
size_t WrapICorJitInfo::getClassModuleIdForStatics(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
CORINFO_MODULE_HANDLE* pModule,
|
||||
void** ppIndirection)
|
||||
{
|
||||
API_ENTER(getClassModuleIdForStatics);
|
||||
size_t temp = wrapHnd->getClassModuleIdForStatics(cls, pModule, ppIndirection);
|
||||
API_LEAVE(getClassModuleIdForStatics);
|
||||
return temp;
|
||||
}
|
||||
|
||||
bool WrapICorJitInfo::getIsClassInitedFlagAddress(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
CORINFO_CONST_LOOKUP* addr,
|
||||
|
@ -482,6 +471,24 @@ bool WrapICorJitInfo::getIsClassInitedFlagAddress(
|
|||
return temp;
|
||||
}
|
||||
|
||||
size_t WrapICorJitInfo::getClassThreadStaticDynamicInfo(
|
||||
CORINFO_CLASS_HANDLE clr)
|
||||
{
|
||||
API_ENTER(getClassThreadStaticDynamicInfo);
|
||||
size_t temp = wrapHnd->getClassThreadStaticDynamicInfo(clr);
|
||||
API_LEAVE(getClassThreadStaticDynamicInfo);
|
||||
return temp;
|
||||
}
|
||||
|
||||
size_t WrapICorJitInfo::getClassStaticDynamicInfo(
|
||||
CORINFO_CLASS_HANDLE clr)
|
||||
{
|
||||
API_ENTER(getClassStaticDynamicInfo);
|
||||
size_t temp = wrapHnd->getClassStaticDynamicInfo(clr);
|
||||
API_LEAVE(getClassStaticDynamicInfo);
|
||||
return temp;
|
||||
}
|
||||
|
||||
bool WrapICorJitInfo::getStaticBaseAddress(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
bool isGc,
|
||||
|
@ -953,11 +960,10 @@ uint32_t WrapICorJitInfo::getThreadLocalFieldInfo(
|
|||
}
|
||||
|
||||
void WrapICorJitInfo::getThreadLocalStaticBlocksInfo(
|
||||
CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo,
|
||||
bool isGCType)
|
||||
CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo)
|
||||
{
|
||||
API_ENTER(getThreadLocalStaticBlocksInfo);
|
||||
wrapHnd->getThreadLocalStaticBlocksInfo(pInfo, isGCType);
|
||||
wrapHnd->getThreadLocalStaticBlocksInfo(pInfo);
|
||||
API_LEAVE(getThreadLocalStaticBlocksInfo);
|
||||
}
|
||||
|
||||
|
@ -1419,16 +1425,6 @@ void WrapICorJitInfo::getCallInfo(
|
|||
API_LEAVE(getCallInfo);
|
||||
}
|
||||
|
||||
unsigned WrapICorJitInfo::getClassDomainID(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
void** ppIndirection)
|
||||
{
|
||||
API_ENTER(getClassDomainID);
|
||||
unsigned temp = wrapHnd->getClassDomainID(cls, ppIndirection);
|
||||
API_LEAVE(getClassDomainID);
|
||||
return temp;
|
||||
}
|
||||
|
||||
bool WrapICorJitInfo::getStaticFieldContent(
|
||||
CORINFO_FIELD_HANDLE field,
|
||||
uint8_t* buffer,
|
||||
|
|
|
@ -2000,7 +2000,7 @@ void Compiler::compInit(ArenaAllocator* pAlloc,
|
|||
|
||||
// check that HelperCallProperties are initialized
|
||||
|
||||
assert(s_helperCallProperties.IsPure(CORINFO_HELP_GETSHARED_GCSTATIC_BASE));
|
||||
assert(s_helperCallProperties.IsPure(CORINFO_HELP_GET_GCSTATIC_BASE));
|
||||
assert(!s_helperCallProperties.IsPure(CORINFO_HELP_GETFIELDOBJ)); // quick sanity check
|
||||
|
||||
// We start with the flow graph in tree-order
|
||||
|
|
|
@ -3881,13 +3881,15 @@ inline bool Compiler::IsStaticHelperEligibleForExpansion(GenTree* tree, bool* is
|
|||
switch (eeGetHelperNum(tree->AsCall()->gtCallMethHnd))
|
||||
{
|
||||
case CORINFO_HELP_READYTORUN_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETSHARED_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GET_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETPINNED_GCSTATIC_BASE:
|
||||
result = true;
|
||||
gc = true;
|
||||
retVal = SHRV_STATIC_BASE_PTR;
|
||||
break;
|
||||
case CORINFO_HELP_READYTORUN_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_GET_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE:
|
||||
result = true;
|
||||
gc = false;
|
||||
retVal = SHRV_STATIC_BASE_PTR;
|
||||
|
@ -3925,30 +3927,17 @@ inline bool Compiler::IsSharedStaticHelper(GenTree* tree)
|
|||
helper == CORINFO_HELP_STRCNS || helper == CORINFO_HELP_BOX ||
|
||||
|
||||
// helpers being added to IsSharedStaticHelper
|
||||
helper == CORINFO_HELP_GETSTATICFIELDADDR_TLS || helper == CORINFO_HELP_GETGENERICS_GCSTATIC_BASE ||
|
||||
helper == CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE || helper == CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE ||
|
||||
helper == CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE ||
|
||||
helper == CORINFO_HELP_GETSTATICFIELDADDR_TLS ||
|
||||
|
||||
helper == CORINFO_HELP_GETSHARED_GCSTATIC_BASE || helper == CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE ||
|
||||
helper == CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR ||
|
||||
helper == CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR ||
|
||||
helper == CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS ||
|
||||
helper == CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS ||
|
||||
helper == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE ||
|
||||
helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE ||
|
||||
helper == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR ||
|
||||
helper == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED ||
|
||||
helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR ||
|
||||
helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED ||
|
||||
helper == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS ||
|
||||
helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS ||
|
||||
(helper >= CORINFO_HELP_GET_GCSTATIC_BASE &&
|
||||
helper <= CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED2)
|
||||
#ifdef FEATURE_READYTORUN
|
||||
helper == CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE || helper == CORINFO_HELP_READYTORUN_GCSTATIC_BASE ||
|
||||
|| helper == CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE || helper == CORINFO_HELP_READYTORUN_GCSTATIC_BASE ||
|
||||
helper == CORINFO_HELP_READYTORUN_NONGCSTATIC_BASE || helper == CORINFO_HELP_READYTORUN_THREADSTATIC_BASE ||
|
||||
helper == CORINFO_HELP_READYTORUN_THREADSTATIC_BASE_NOCTOR ||
|
||||
helper == CORINFO_HELP_READYTORUN_NONGCTHREADSTATIC_BASE ||
|
||||
helper == CORINFO_HELP_READYTORUN_NONGCTHREADSTATIC_BASE
|
||||
#endif
|
||||
helper == CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS;
|
||||
|| helper == CORINFO_HELP_INITCLASS;
|
||||
#if 0
|
||||
// See above TODO-Cleanup
|
||||
bool result2 = s_helperCallProperties.IsPure(helper) && s_helperCallProperties.NonNullReturn(helper);
|
||||
|
|
|
@ -2833,8 +2833,8 @@ bool emitter::emitNoGChelper(CorInfoHelpFunc helpFunc)
|
|||
case CORINFO_HELP_CHECKED_ASSIGN_REF:
|
||||
case CORINFO_HELP_ASSIGN_BYREF:
|
||||
|
||||
case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GET_GCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GET_NONGCSTATIC_BASE_NOCTOR:
|
||||
|
||||
case CORINFO_HELP_INIT_PINVOKE_FRAME:
|
||||
|
||||
|
|
|
@ -679,8 +679,9 @@ bool Compiler::fgIsCommaThrow(GenTree* tree, bool forFolding /* = false */)
|
|||
// cls - The class handle
|
||||
// helper - The helper function
|
||||
// typeIndex - The static block type index. Used only for
|
||||
// CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED or
|
||||
// CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED to cache
|
||||
// CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED,
|
||||
// CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED, or
|
||||
// CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED2 to cache
|
||||
// the static block in an array at index typeIndex.
|
||||
//
|
||||
// Return Value:
|
||||
|
@ -696,57 +697,50 @@ GenTreeCall* Compiler::fgGetStaticsCCtorHelper(CORINFO_CLASS_HANDLE cls, CorInfo
|
|||
// We need the return type.
|
||||
switch (helper)
|
||||
{
|
||||
case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED:
|
||||
bNeedClassID = false;
|
||||
FALLTHROUGH;
|
||||
|
||||
case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GET_GCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GET_NONGCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GET_GCTHREADSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED:
|
||||
callFlags |= GTF_CALL_HOISTABLE;
|
||||
FALLTHROUGH;
|
||||
|
||||
case CORINFO_HELP_GETSHARED_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS:
|
||||
case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS:
|
||||
case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS:
|
||||
case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS:
|
||||
case CORINFO_HELP_GET_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GET_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_GET_GCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE:
|
||||
// type = TYP_BYREF;
|
||||
break;
|
||||
|
||||
case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED:
|
||||
case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR:
|
||||
bNeedClassID = false;
|
||||
FALLTHROUGH;
|
||||
|
||||
case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETPINNED_GCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED2:
|
||||
callFlags |= GTF_CALL_HOISTABLE;
|
||||
FALLTHROUGH;
|
||||
|
||||
case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS:
|
||||
case CORINFO_HELP_GETPINNED_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE:
|
||||
type = TYP_I_IMPL;
|
||||
break;
|
||||
|
||||
case CORINFO_HELP_INITCLASS:
|
||||
type = TYP_VOID;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(!"unknown shared statics helper");
|
||||
break;
|
||||
}
|
||||
|
||||
GenTree* opModuleIDArg;
|
||||
GenTree* opClassIDArg;
|
||||
|
||||
// Get the class ID
|
||||
unsigned clsID;
|
||||
size_t moduleID;
|
||||
void* pclsID;
|
||||
void* pmoduleID;
|
||||
|
||||
clsID = info.compCompHnd->getClassDomainID(cls, &pclsID);
|
||||
|
||||
moduleID = info.compCompHnd->getClassModuleIdForStatics(cls, nullptr, &pmoduleID);
|
||||
|
||||
if (!(callFlags & GTF_CALL_HOISTABLE))
|
||||
{
|
||||
if (info.compCompHnd->getClassAttribs(cls) & CORINFO_FLG_BEFOREFIELDINIT)
|
||||
|
@ -755,37 +749,36 @@ GenTreeCall* Compiler::fgGetStaticsCCtorHelper(CORINFO_CLASS_HANDLE cls, CorInfo
|
|||
}
|
||||
}
|
||||
|
||||
if (pmoduleID)
|
||||
{
|
||||
opModuleIDArg = gtNewIndOfIconHandleNode(TYP_I_IMPL, (size_t)pmoduleID, GTF_ICON_CIDMID_HDL, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
opModuleIDArg = gtNewIconNode((size_t)moduleID, TYP_I_IMPL);
|
||||
}
|
||||
|
||||
GenTreeCall* result;
|
||||
if (bNeedClassID)
|
||||
{
|
||||
if (pclsID)
|
||||
{
|
||||
opClassIDArg = gtNewIndOfIconHandleNode(TYP_INT, (size_t)pclsID, GTF_ICON_CIDMID_HDL, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
opClassIDArg = gtNewIconNode(clsID, TYP_INT);
|
||||
}
|
||||
|
||||
result = gtNewHelperCallNode(helper, type, opModuleIDArg, opClassIDArg);
|
||||
}
|
||||
else if ((helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED) ||
|
||||
(helper == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED))
|
||||
if ((helper == CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED) ||
|
||||
(helper == CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED) ||
|
||||
(helper == CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED2))
|
||||
{
|
||||
result = gtNewHelperCallNode(helper, type, gtNewIconNode(typeIndex));
|
||||
}
|
||||
else if (helper == CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR ||
|
||||
helper == CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR ||
|
||||
helper == CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE ||
|
||||
helper == CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE)
|
||||
{
|
||||
result = gtNewHelperCallNode(helper, type,
|
||||
gtNewIconNode((size_t)info.compCompHnd->getClassThreadStaticDynamicInfo(cls),
|
||||
TYP_I_IMPL));
|
||||
}
|
||||
else if (helper == CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE || helper == CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE ||
|
||||
helper == CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE_NOCTOR ||
|
||||
helper == CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE_NOCTOR ||
|
||||
helper == CORINFO_HELP_GETPINNED_GCSTATIC_BASE || helper == CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE ||
|
||||
helper == CORINFO_HELP_GETPINNED_GCSTATIC_BASE_NOCTOR ||
|
||||
helper == CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE_NOCTOR)
|
||||
{
|
||||
result = gtNewHelperCallNode(helper, type,
|
||||
gtNewIconNode(info.compCompHnd->getClassStaticDynamicInfo(cls), TYP_I_IMPL));
|
||||
}
|
||||
else
|
||||
{
|
||||
result = gtNewHelperCallNode(helper, type, opModuleIDArg);
|
||||
result = gtNewHelperCallNode(helper, type, gtNewIconEmbClsHndNode(cls));
|
||||
}
|
||||
|
||||
if (IsStaticHelperEligibleForExpansion(result))
|
||||
|
|
|
@ -454,8 +454,9 @@ bool Compiler::fgExpandRuntimeLookupsForCall(BasicBlock** pBlock, Statement* stm
|
|||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// fgExpandThreadLocalAccess: Inline the CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED
|
||||
// or CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED helper. See
|
||||
// fgExpandThreadLocalAccess: Inline the CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED,
|
||||
// CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED, or
|
||||
// CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED2 helper. See
|
||||
// fgExpandThreadLocalAccessForCall for details.
|
||||
//
|
||||
// Returns:
|
||||
|
@ -763,8 +764,8 @@ bool Compiler::fgExpandThreadLocalAccessForCallNativeAOT(BasicBlock** pBlock, St
|
|||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// fgExpandThreadLocalAccessForCall : Expand the CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED
|
||||
// or CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED, that access fields marked with [ThreadLocal].
|
||||
// fgExpandThreadLocalAccessForCall : Expand the CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED
|
||||
// or CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED, that access fields marked with [ThreadLocal].
|
||||
//
|
||||
// Arguments:
|
||||
// pBlock - Block containing the helper call to expand. If expansion is performed,
|
||||
|
@ -793,11 +794,13 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement*
|
|||
|
||||
CorInfoHelpFunc helper = call->GetHelperNum();
|
||||
|
||||
if ((helper != CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED) &&
|
||||
(helper != CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED))
|
||||
if ((helper != CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED) &&
|
||||
(helper != CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED) &&
|
||||
(helper != CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
assert(!opts.IsReadyToRun());
|
||||
|
||||
if (TargetOS::IsUnix)
|
||||
{
|
||||
|
@ -822,15 +825,12 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement*
|
|||
DISPTREE(call);
|
||||
JITDUMP("\n");
|
||||
|
||||
bool isGCThreadStatic =
|
||||
eeGetHelperNum(call->gtCallMethHnd) == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED;
|
||||
|
||||
CORINFO_THREAD_STATIC_BLOCKS_INFO threadStaticBlocksInfo;
|
||||
memset(&threadStaticBlocksInfo, 0, sizeof(CORINFO_THREAD_STATIC_BLOCKS_INFO));
|
||||
|
||||
info.compCompHnd->getThreadLocalStaticBlocksInfo(&threadStaticBlocksInfo, isGCThreadStatic);
|
||||
info.compCompHnd->getThreadLocalStaticBlocksInfo(&threadStaticBlocksInfo);
|
||||
|
||||
JITDUMP("getThreadLocalStaticBlocksInfo (%s)\n:", isGCThreadStatic ? "GC" : "Non-GC");
|
||||
JITDUMP("getThreadLocalStaticBlocksInfo\n:");
|
||||
JITDUMP("tlsIndex= %p\n", dspPtr(threadStaticBlocksInfo.tlsIndex.addr));
|
||||
JITDUMP("tlsGetAddrFtnPtr= %p\n", dspPtr(threadStaticBlocksInfo.tlsGetAddrFtnPtr));
|
||||
JITDUMP("tlsIndexObject= %p\n", dspPtr(threadStaticBlocksInfo.tlsIndexObject));
|
||||
|
@ -839,7 +839,7 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement*
|
|||
dspOffset(threadStaticBlocksInfo.offsetOfThreadLocalStoragePointer));
|
||||
JITDUMP("offsetOfMaxThreadStaticBlocks= %u\n", dspOffset(threadStaticBlocksInfo.offsetOfMaxThreadStaticBlocks));
|
||||
JITDUMP("offsetOfThreadStaticBlocks= %u\n", dspOffset(threadStaticBlocksInfo.offsetOfThreadStaticBlocks));
|
||||
JITDUMP("offsetOfGCDataPointer= %u\n", dspOffset(threadStaticBlocksInfo.offsetOfGCDataPointer));
|
||||
JITDUMP("offsetOfBaseOfThreadLocalData= %u\n", dspOffset(threadStaticBlocksInfo.offsetOfBaseOfThreadLocalData));
|
||||
|
||||
assert(call->gtArgs.CountArgs() == 1);
|
||||
|
||||
|
@ -989,7 +989,54 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement*
|
|||
// Cache the tls value
|
||||
tlsValueDef = gtNewStoreLclVarNode(tlsLclNum, tlsValue);
|
||||
GenTree* tlsLclValueUse = gtNewLclVarNode(tlsLclNum);
|
||||
GenTree* typeThreadStaticBlockIndexValue = call->gtArgs.GetArgByIndex(0)->GetNode();
|
||||
|
||||
if (helper == CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED2)
|
||||
{
|
||||
// In this case we can entirely remove the block which uses the helper call, and just get the TLS pointer
|
||||
// directly
|
||||
|
||||
// prevBb (BBJ_NONE): [weight: 1.0]
|
||||
// ...
|
||||
//
|
||||
// tlsBaseComputeBB (BBJ_COND): [weight: 1.0]
|
||||
// tlsRoot = [tlsRootAddress]
|
||||
//
|
||||
// block (...): [weight: 1.0]
|
||||
// use(tlsRoot);
|
||||
// ...
|
||||
|
||||
GenTree* typeThreadStaticBlockIndexValue = call->gtArgs.GetArgByIndex(0)->GetNode();
|
||||
GenTree* threadStaticBase =
|
||||
gtNewOperNode(GT_ADD, TYP_I_IMPL,
|
||||
gtNewOperNode(GT_ADD, TYP_I_IMPL, gtCloneExpr(tlsLclValueUse),
|
||||
gtCloneExpr(typeThreadStaticBlockIndexValue)),
|
||||
gtNewIconNode(threadStaticBlocksInfo.offsetOfBaseOfThreadLocalData, TYP_I_IMPL));
|
||||
GenTree* tlsStaticBaseStoreLcl = gtNewStoreLclVarNode(threadStaticBlockLclNum, threadStaticBase);
|
||||
|
||||
BasicBlock* tlsBaseComputeBB = fgNewBBFromTreeAfter(BBJ_ALWAYS, prevBb, tlsValueDef, debugInfo, true);
|
||||
fgInsertStmtAfter(tlsBaseComputeBB, tlsBaseComputeBB->firstStmt(), fgNewStmtFromTree(tlsStaticBaseStoreLcl));
|
||||
|
||||
//
|
||||
// Update preds in all new blocks
|
||||
//
|
||||
|
||||
FlowEdge* const newEdge = fgAddRefPred(block, tlsBaseComputeBB);
|
||||
tlsBaseComputeBB->SetTargetEdge(newEdge);
|
||||
|
||||
assert(prevBb->KindIs(BBJ_ALWAYS));
|
||||
fgRedirectTargetEdge(prevBb, tlsBaseComputeBB);
|
||||
|
||||
// Inherit the weights
|
||||
block->inheritWeight(prevBb);
|
||||
tlsBaseComputeBB->inheritWeight(prevBb);
|
||||
|
||||
// All blocks are expected to be in the same EH region
|
||||
assert(BasicBlock::sameEHRegion(prevBb, block));
|
||||
assert(BasicBlock::sameEHRegion(prevBb, tlsBaseComputeBB));
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t offsetOfThreadStaticBlocksVal = threadStaticBlocksInfo.offsetOfThreadStaticBlocks;
|
||||
size_t offsetOfMaxThreadStaticBlocksVal = threadStaticBlocksInfo.offsetOfMaxThreadStaticBlocks;
|
||||
|
||||
|
@ -997,29 +1044,30 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement*
|
|||
GenTree* offsetOfMaxThreadStaticBlocks = gtNewIconNode(offsetOfMaxThreadStaticBlocksVal, TYP_I_IMPL);
|
||||
GenTree* maxThreadStaticBlocksRef =
|
||||
gtNewOperNode(GT_ADD, TYP_I_IMPL, gtCloneExpr(tlsLclValueUse), offsetOfMaxThreadStaticBlocks);
|
||||
maxThreadStaticBlocksValue = gtNewIndir(TYP_INT, maxThreadStaticBlocksRef, GTF_IND_NONFAULTING | GTF_IND_INVARIANT);
|
||||
maxThreadStaticBlocksValue =
|
||||
gtNewIndir(TYP_INT, maxThreadStaticBlocksRef, GTF_IND_NONFAULTING | GTF_IND_INVARIANT);
|
||||
|
||||
GenTree* threadStaticBlocksRef = gtNewOperNode(GT_ADD, TYP_I_IMPL, gtCloneExpr(tlsLclValueUse),
|
||||
gtNewIconNode(offsetOfThreadStaticBlocksVal, TYP_I_IMPL));
|
||||
threadStaticBlocksValue = gtNewIndir(TYP_I_IMPL, threadStaticBlocksRef, GTF_IND_NONFAULTING | GTF_IND_INVARIANT);
|
||||
threadStaticBlocksValue = gtNewIndir(TYP_REF, threadStaticBlocksRef, GTF_IND_NONFAULTING | GTF_IND_INVARIANT);
|
||||
|
||||
// Create tree for "if (maxThreadStaticBlocks < typeIndex)"
|
||||
GenTree* typeThreadStaticBlockIndexValue = call->gtArgs.GetArgByIndex(0)->GetNode();
|
||||
GenTree* maxThreadStaticBlocksCond =
|
||||
gtNewOperNode(GT_LT, TYP_INT, maxThreadStaticBlocksValue, gtCloneExpr(typeThreadStaticBlockIndexValue));
|
||||
gtNewOperNode(GT_LE, TYP_INT, maxThreadStaticBlocksValue, gtCloneExpr(typeThreadStaticBlockIndexValue));
|
||||
maxThreadStaticBlocksCond = gtNewOperNode(GT_JTRUE, TYP_VOID, maxThreadStaticBlocksCond);
|
||||
|
||||
// Create tree to "threadStaticBlockValue = threadStaticBlockBase[typeIndex]"
|
||||
typeThreadStaticBlockIndexValue = gtNewOperNode(GT_MUL, TYP_INT, gtCloneExpr(typeThreadStaticBlockIndexValue),
|
||||
gtNewIconNode(TARGET_POINTER_SIZE, TYP_INT));
|
||||
GenTree* typeThreadStaticBlockRef =
|
||||
gtNewOperNode(GT_ADD, TYP_I_IMPL, threadStaticBlocksValue, typeThreadStaticBlockIndexValue);
|
||||
GenTree* typeThreadStaticBlockValue = gtNewIndir(TYP_I_IMPL, typeThreadStaticBlockRef, GTF_IND_NONFAULTING);
|
||||
gtNewOperNode(GT_ADD, TYP_BYREF, threadStaticBlocksValue, typeThreadStaticBlockIndexValue);
|
||||
GenTree* typeThreadStaticBlockValue = gtNewIndir(TYP_BYREF, typeThreadStaticBlockRef, GTF_IND_NONFAULTING);
|
||||
|
||||
// Cache the threadStaticBlock value
|
||||
unsigned threadStaticBlockBaseLclNum = lvaGrabTemp(true DEBUGARG("ThreadStaticBlockBase access"));
|
||||
lvaTable[threadStaticBlockBaseLclNum].lvType = TYP_I_IMPL;
|
||||
GenTree* threadStaticBlockBaseDef = gtNewStoreLclVarNode(threadStaticBlockBaseLclNum, typeThreadStaticBlockValue);
|
||||
lvaTable[threadStaticBlockBaseLclNum].lvType = TYP_BYREF;
|
||||
GenTree* threadStaticBlockBaseDef =
|
||||
gtNewStoreLclVarNode(threadStaticBlockBaseLclNum, typeThreadStaticBlockValue);
|
||||
GenTree* threadStaticBlockBaseLclValueUse = gtNewLclVarNode(threadStaticBlockBaseLclNum);
|
||||
|
||||
// Create tree for "if (threadStaticBlockValue != nullptr)"
|
||||
|
@ -1032,7 +1080,7 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement*
|
|||
//
|
||||
// maxThreadStaticBlocksCondBB (BBJ_COND): [weight: 1.0]
|
||||
// tlsValue = tls_access_code
|
||||
// if (maxThreadStaticBlocks < typeIndex)
|
||||
// if (maxThreadStaticBlocks <= typeIndex)
|
||||
// goto fallbackBb;
|
||||
//
|
||||
// threadStaticBlockNullCondBB (BBJ_COND): [weight: 1.0]
|
||||
|
@ -1070,17 +1118,6 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement*
|
|||
BasicBlock* fallbackBb =
|
||||
fgNewBBFromTreeAfter(BBJ_ALWAYS, threadStaticBlockNullCondBB, fallbackValueDef, debugInfo, true);
|
||||
|
||||
// fastPathBb
|
||||
if (isGCThreadStatic)
|
||||
{
|
||||
// Need to add extra indirection to access the data pointer.
|
||||
|
||||
threadStaticBlockBaseLclValueUse = gtNewIndir(callType, threadStaticBlockBaseLclValueUse, GTF_IND_NONFAULTING);
|
||||
threadStaticBlockBaseLclValueUse =
|
||||
gtNewOperNode(GT_ADD, callType, threadStaticBlockBaseLclValueUse,
|
||||
gtNewIconNode(threadStaticBlocksInfo.offsetOfGCDataPointer, TYP_I_IMPL));
|
||||
}
|
||||
|
||||
GenTree* fastPathValueDef =
|
||||
gtNewStoreLclVarNode(threadStaticBlockLclNum, gtCloneExpr(threadStaticBlockBaseLclValueUse));
|
||||
BasicBlock* fastPathBb = fgNewBBFromTreeAfter(BBJ_ALWAYS, fallbackBb, fastPathValueDef, debugInfo, true);
|
||||
|
@ -1133,6 +1170,7 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement*
|
|||
assert(BasicBlock::sameEHRegion(prevBb, maxThreadStaticBlocksCondBB));
|
||||
assert(BasicBlock::sameEHRegion(prevBb, threadStaticBlockNullCondBB));
|
||||
assert(BasicBlock::sameEHRegion(prevBb, fastPathBb));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -3798,12 +3798,10 @@ GenTree* Compiler::impImportStaticFieldAddress(CORINFO_RESOLVED_TOKEN* pResolved
|
|||
|
||||
switch (pFieldInfo->helper)
|
||||
{
|
||||
case CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE:
|
||||
type = TYP_I_IMPL;
|
||||
break;
|
||||
case CORINFO_HELP_GETGENERICS_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GET_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GET_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_GET_GCTHREADSTATIC_BASE:
|
||||
break;
|
||||
default:
|
||||
assert(!"unknown generic statics helper");
|
||||
|
@ -3813,6 +3811,11 @@ GenTree* Compiler::impImportStaticFieldAddress(CORINFO_RESOLVED_TOKEN* pResolved
|
|||
isHoistable = !s_helperCallProperties.MayRunCctor(pFieldInfo->helper) ||
|
||||
(info.compCompHnd->getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_BEFOREFIELDINIT);
|
||||
op1 = gtNewHelperCallNode(pFieldInfo->helper, type, op1);
|
||||
if (IsStaticHelperEligibleForExpansion(op1))
|
||||
{
|
||||
// Mark the helper call with the initClsHnd so that rewriting it for expansion can reliably fail
|
||||
op1->AsCall()->gtInitClsHnd = pResolvedToken->hClass;
|
||||
}
|
||||
op1 = gtNewOperNode(GT_ADD, type, op1, gtNewIconNode(pFieldInfo->offset, innerFldSeq));
|
||||
}
|
||||
break;
|
||||
|
@ -3823,13 +3826,14 @@ GenTree* Compiler::impImportStaticFieldAddress(CORINFO_RESOLVED_TOKEN* pResolved
|
|||
if (!opts.IsReadyToRun())
|
||||
#endif // FEATURE_READYTORUN
|
||||
{
|
||||
if (pFieldInfo->helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED)
|
||||
if ((pFieldInfo->helper == CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED) ||
|
||||
(pFieldInfo->helper == CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED2))
|
||||
{
|
||||
typeIndex = info.compCompHnd->getThreadLocalFieldInfo(pResolvedToken->hField, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(pFieldInfo->helper == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED);
|
||||
assert(pFieldInfo->helper == CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED);
|
||||
typeIndex = info.compCompHnd->getThreadLocalFieldInfo(pResolvedToken->hField, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1691,20 +1691,17 @@ void HelperCallProperties::init()
|
|||
// Helpers that load the base address for static variables.
|
||||
// We divide these between those that may and may not invoke
|
||||
// static class constructors.
|
||||
case CORINFO_HELP_GETSHARED_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS:
|
||||
case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS:
|
||||
case CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS:
|
||||
case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS:
|
||||
case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS:
|
||||
case CORINFO_HELP_GET_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GET_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETPINNED_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_GET_GCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GETSTATICFIELDADDR_TLS:
|
||||
case CORINFO_HELP_GETGENERICS_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_READYTORUN_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_READYTORUN_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_READYTORUN_THREADSTATIC_BASE:
|
||||
|
@ -1719,12 +1716,25 @@ void HelperCallProperties::init()
|
|||
mayRunCctor = true;
|
||||
break;
|
||||
|
||||
case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED:
|
||||
case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED:
|
||||
case CORINFO_HELP_INITCLASS:
|
||||
case CORINFO_HELP_INITINSTCLASS:
|
||||
isPure = true;
|
||||
mayRunCctor = true;
|
||||
break;
|
||||
|
||||
case CORINFO_HELP_GET_GCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GET_NONGCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETPINNED_GCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GET_GCTHREADSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED2:
|
||||
case CORINFO_HELP_READYTORUN_THREADSTATIC_BASE_NOCTOR:
|
||||
|
||||
// These do not invoke static class constructors
|
||||
|
|
|
@ -13189,23 +13189,35 @@ VNFunc Compiler::fgValueNumberJitHelperMethodVNFunc(CorInfoHelpFunc helpFunc)
|
|||
vnf = opts.IsReadyToRun() ? VNF_JitReadyToRunNewArr : VNF_JitNewArr;
|
||||
break;
|
||||
|
||||
case CORINFO_HELP_GETGENERICS_GCSTATIC_BASE:
|
||||
vnf = VNF_GetgenericsGcstaticBase;
|
||||
case CORINFO_HELP_GET_GCSTATIC_BASE:
|
||||
vnf = VNF_GetGcstaticBase;
|
||||
break;
|
||||
case CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE:
|
||||
vnf = VNF_GetgenericsNongcstaticBase;
|
||||
case CORINFO_HELP_GET_NONGCSTATIC_BASE:
|
||||
vnf = VNF_GetNongcstaticBase;
|
||||
break;
|
||||
case CORINFO_HELP_GETSHARED_GCSTATIC_BASE:
|
||||
vnf = VNF_GetsharedGcstaticBase;
|
||||
case CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE:
|
||||
vnf = VNF_GetdynamicGcstaticBase;
|
||||
break;
|
||||
case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE:
|
||||
vnf = VNF_GetsharedNongcstaticBase;
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE:
|
||||
vnf = VNF_GetdynamicNongcstaticBase;
|
||||
break;
|
||||
case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR:
|
||||
vnf = VNF_GetsharedGcstaticBaseNoctor;
|
||||
case CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE_NOCTOR:
|
||||
vnf = VNF_GetdynamicGcstaticBaseNoctor;
|
||||
break;
|
||||
case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR:
|
||||
vnf = VNF_GetsharedNongcstaticBaseNoctor;
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE_NOCTOR:
|
||||
vnf = VNF_GetdynamicNongcstaticBaseNoctor;
|
||||
break;
|
||||
case CORINFO_HELP_GETPINNED_GCSTATIC_BASE:
|
||||
vnf = VNF_GetpinnedGcstaticBase;
|
||||
break;
|
||||
case CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE:
|
||||
vnf = VNF_GetpinnedNongcstaticBase;
|
||||
break;
|
||||
case CORINFO_HELP_GETPINNED_GCSTATIC_BASE_NOCTOR:
|
||||
vnf = VNF_GetpinnedGcstaticBaseNoctor;
|
||||
break;
|
||||
case CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE_NOCTOR:
|
||||
vnf = VNF_GetpinnedNongcstaticBaseNoctor;
|
||||
break;
|
||||
case CORINFO_HELP_READYTORUN_GCSTATIC_BASE:
|
||||
vnf = VNF_ReadyToRunStaticBaseGC;
|
||||
|
@ -13225,44 +13237,38 @@ VNFunc Compiler::fgValueNumberJitHelperMethodVNFunc(CorInfoHelpFunc helpFunc)
|
|||
case CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE:
|
||||
vnf = VNF_ReadyToRunGenericStaticBase;
|
||||
break;
|
||||
case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS:
|
||||
vnf = VNF_GetsharedGcstaticBaseDynamicclass;
|
||||
case CORINFO_HELP_GET_GCTHREADSTATIC_BASE:
|
||||
vnf = VNF_GetGcthreadstaticBase;
|
||||
break;
|
||||
case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS:
|
||||
vnf = VNF_GetsharedNongcstaticBaseDynamicclass;
|
||||
case CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE:
|
||||
vnf = VNF_GetNongcthreadstaticBase;
|
||||
break;
|
||||
case CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS:
|
||||
vnf = VNF_ClassinitSharedDynamicclass;
|
||||
case CORINFO_HELP_GET_GCTHREADSTATIC_BASE_NOCTOR:
|
||||
vnf = VNF_GetGcthreadstaticBaseNoctor;
|
||||
break;
|
||||
case CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE:
|
||||
vnf = VNF_GetgenericsGcthreadstaticBase;
|
||||
case CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE_NOCTOR:
|
||||
vnf = VNF_GetNongcthreadstaticBaseNoctor;
|
||||
break;
|
||||
case CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE:
|
||||
vnf = VNF_GetgenericsNongcthreadstaticBase;
|
||||
case CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE:
|
||||
vnf = VNF_GetdynamicGcthreadstaticBase;
|
||||
break;
|
||||
case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE:
|
||||
vnf = VNF_GetsharedGcthreadstaticBase;
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE:
|
||||
vnf = VNF_GetdynamicNongcthreadstaticBase;
|
||||
break;
|
||||
case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE:
|
||||
vnf = VNF_GetsharedNongcthreadstaticBase;
|
||||
case CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR:
|
||||
vnf = VNF_GetdynamicGcthreadstaticBaseNoctor;
|
||||
break;
|
||||
case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR:
|
||||
vnf = VNF_GetsharedGcthreadstaticBaseNoctor;
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR:
|
||||
vnf = VNF_GetdynamicNongcthreadstaticBaseNoctor;
|
||||
break;
|
||||
case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED:
|
||||
vnf = VNF_GetsharedGcthreadstaticBaseNoctorOptimized;
|
||||
case CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED:
|
||||
vnf = VNF_GetdynamicGcthreadstaticBaseNoctorOptimized;
|
||||
break;
|
||||
case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR:
|
||||
vnf = VNF_GetsharedNongcthreadstaticBaseNoctor;
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED:
|
||||
vnf = VNF_GetdynamicNongcthreadstaticBaseNoctorOptimized;
|
||||
break;
|
||||
case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED:
|
||||
vnf = VNF_GetsharedNongcthreadstaticBaseNoctorOptimized;
|
||||
break;
|
||||
case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS:
|
||||
vnf = VNF_GetsharedGcthreadstaticBaseDynamicclass;
|
||||
break;
|
||||
case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS:
|
||||
vnf = VNF_GetsharedNongcthreadstaticBaseDynamicclass;
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED2:
|
||||
vnf = VNF_GetdynamicNongcthreadstaticBaseNoctorOptimized2;
|
||||
break;
|
||||
case CORINFO_HELP_GETSTATICFIELDADDR_TLS:
|
||||
vnf = VNF_GetStaticAddrTLS;
|
||||
|
@ -13450,33 +13456,6 @@ bool Compiler::fgValueNumberHelperCall(GenTreeCall* call)
|
|||
break;
|
||||
}
|
||||
|
||||
case CORINFO_HELP_GETSHARED_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS:
|
||||
case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS:
|
||||
case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS:
|
||||
case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS:
|
||||
case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS:
|
||||
// These all take (Module*, class ID) as parameters.
|
||||
//
|
||||
// Strictly speaking the exact possible exception thrown by the
|
||||
// static constructor depends on heap state too, but given that
|
||||
// the constructor is only invoked once we can model that for
|
||||
// the same class the same exceptions are thrown. Downstream
|
||||
// code like CSE/copy prop that makes use VNs innately need to
|
||||
// establish some form of dominance around the individual trees
|
||||
// that makes this ok.
|
||||
//
|
||||
vnpExc = vnStore->VNPExcSetSingleton(
|
||||
vnStore->VNPairForFunc(TYP_REF, VNF_ClassInitExc,
|
||||
vnStore->VNPNormalPair(
|
||||
call->gtArgs.GetUserArgByIndex(0)->GetNode()->gtVNPair),
|
||||
vnStore->VNPNormalPair(
|
||||
call->gtArgs.GetUserArgByIndex(1)->GetNode()->gtVNPair)));
|
||||
break;
|
||||
|
||||
#ifdef FEATURE_READYTORUN
|
||||
case CORINFO_HELP_READYTORUN_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_READYTORUN_NONGCSTATIC_BASE:
|
||||
|
@ -13493,10 +13472,14 @@ bool Compiler::fgValueNumberHelperCall(GenTreeCall* call)
|
|||
}
|
||||
#endif
|
||||
|
||||
case CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GETGENERICS_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_GET_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GET_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_GET_GCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GET_NONGCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GET_GCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GET_GCTHREADSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE_NOCTOR:
|
||||
// These take class handles as parameters.
|
||||
vnpExc = vnStore->VNPExcSetSingleton(
|
||||
vnStore->VNPairForFunc(TYP_REF, VNF_ClassInitGenericExc,
|
||||
|
@ -13504,6 +13487,32 @@ bool Compiler::fgValueNumberHelperCall(GenTreeCall* call)
|
|||
call->gtArgs.GetUserArgByIndex(0)->GetNode()->gtVNPair)));
|
||||
break;
|
||||
|
||||
case CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETPINNED_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETPINNED_GCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE_NOCTOR:
|
||||
// These take DynamicClassInfo handles as parameters.
|
||||
vnpExc = vnStore->VNPExcSetSingleton(
|
||||
vnStore->VNPairForFunc(TYP_REF, VNF_DynamicClassInitExc,
|
||||
vnStore->VNPNormalPair(
|
||||
call->gtArgs.GetUserArgByIndex(0)->GetNode()->gtVNPair)));
|
||||
break;
|
||||
|
||||
case CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR:
|
||||
// These take ThreadStaticInfo as parameters.
|
||||
vnpExc = vnStore->VNPExcSetSingleton(
|
||||
vnStore->VNPairForFunc(TYP_REF, VNF_ThreadClassInitExc,
|
||||
vnStore->VNPNormalPair(
|
||||
call->gtArgs.GetUserArgByIndex(0)->GetNode()->gtVNPair)));
|
||||
break;
|
||||
|
||||
case CORINFO_HELP_DIV:
|
||||
case CORINFO_HELP_LDIV:
|
||||
vnpExc = fgValueNumberDivisionExceptions(GT_DIV, call->gtArgs.GetUserArgByIndex(0)->GetNode(),
|
||||
|
|
|
@ -68,9 +68,10 @@ ValueNumFuncDef(IndexOutOfRangeExc, 2, false, false, false, false) // Array boun
|
|||
ValueNumFuncDef(InvalidCastExc, 2, false, false, false, false) // CastClass check, Args: 0: ref value being cast; 1: handle of type being cast to
|
||||
ValueNumFuncDef(R2RInvalidCastExc, 2, false, false, false, false) // CastClass check, Args: 0: ref value being cast; 1: entry point of R2R cast helper
|
||||
ValueNumFuncDef(NewArrOverflowExc, 1, false, false, false, false) // Raises Integer overflow when Arg 0 is negative
|
||||
ValueNumFuncDef(ClassInitExc, 2, false, false, false, false) // Represents exceptions thrown by static constructor for class. Args: 0: VN of module, 1: VN of class ID
|
||||
ValueNumFuncDef(DynamicClassInitExc, 1, false, false, false, false) // Represents exceptions thrown by static constructor for class. Args: 0: VN of DynamicStaticsInfo
|
||||
ValueNumFuncDef(ThreadClassInitExc, 1, false, false, false, false) // Represents exceptions thrown by static constructor for class. Args: 0: VN of ThreadStaticsInfo
|
||||
ValueNumFuncDef(R2RClassInitExc, 1, false, false, false, false) // Represents exceptions thrown by static constructor for class. Args: 0: VN of R2R entry point
|
||||
ValueNumFuncDef(ClassInitGenericExc, 2, false, false, false, false)// Represents exceptions thrown by static constructor for generic class. Args: 0: VN of class handle
|
||||
ValueNumFuncDef(ClassInitGenericExc, 2, false, false, false, false)// Represents exceptions thrown by static constructor for class. Args: 0: VN of class handle
|
||||
ValueNumFuncDef(HelperOpaqueExc, 1, false, false, false, false) // Represents opaque exceptions could be thrown by a JIT helper.
|
||||
// Args: 0: Input to helper that uniquely determines exceptions thrown.
|
||||
|
||||
|
@ -114,32 +115,34 @@ ValueNumFuncDef(Truncate, 1, false, false, false, false)
|
|||
ValueNumFuncDef(ManagedThreadId, 0, false, false, false, false)
|
||||
|
||||
ValueNumFuncDef(ObjGetType, 1, false, true, false, false)
|
||||
ValueNumFuncDef(GetgenericsGcstaticBase, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetgenericsNongcstaticBase, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedGcstaticBase, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedNongcstaticBase, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedGcstaticBaseNoctor, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedNongcstaticBaseNoctor, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetGcstaticBase, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetNongcstaticBase, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetdynamicGcstaticBase, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetdynamicNongcstaticBase, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetdynamicGcstaticBaseNoctor, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetdynamicNongcstaticBaseNoctor, 1, false, true, true, false)
|
||||
ValueNumFuncDef(ReadyToRunStaticBaseGC, 1, false, true, true, false)
|
||||
ValueNumFuncDef(ReadyToRunStaticBaseNonGC, 1, false, true, true, false)
|
||||
ValueNumFuncDef(ReadyToRunStaticBaseThread, 1, false, true, true, false)
|
||||
ValueNumFuncDef(ReadyToRunStaticBaseThreadNoctor, 1, false, true, true, false)
|
||||
ValueNumFuncDef(ReadyToRunStaticBaseThreadNonGC, 1, false, true, true, false)
|
||||
ValueNumFuncDef(ReadyToRunGenericStaticBase, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedGcstaticBaseDynamicclass, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedNongcstaticBaseDynamicclass, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetgenericsGcthreadstaticBase, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetgenericsNongcthreadstaticBase, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedGcthreadstaticBase, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedNongcthreadstaticBase, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedGcthreadstaticBaseNoctor, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedGcthreadstaticBaseNoctorOptimized, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedNongcthreadstaticBaseNoctor, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedNongcthreadstaticBaseNoctorOptimized, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedGcthreadstaticBaseDynamicclass, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetsharedNongcthreadstaticBaseDynamicclass, 2, false, true, true, false)
|
||||
ValueNumFuncDef(GetpinnedGcstaticBase, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetpinnedNongcstaticBase, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetpinnedGcstaticBaseNoctor, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetpinnedNongcstaticBaseNoctor, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetGcthreadstaticBase, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetNongcthreadstaticBase, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetGcthreadstaticBaseNoctor, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetNongcthreadstaticBaseNoctor, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetdynamicGcthreadstaticBase, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetdynamicNongcthreadstaticBase, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetdynamicGcthreadstaticBaseNoctor, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetdynamicGcthreadstaticBaseNoctorOptimized, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetdynamicNongcthreadstaticBaseNoctor, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetdynamicNongcthreadstaticBaseNoctorOptimized, 1, false, true, true, false)
|
||||
ValueNumFuncDef(GetdynamicNongcthreadstaticBaseNoctorOptimized2, 1, false, true, true, false)
|
||||
|
||||
ValueNumFuncDef(ClassinitSharedDynamicclass, 2, false, false, false, false)
|
||||
ValueNumFuncDef(RuntimeHandleMethod, 2, false, true, false, false)
|
||||
ValueNumFuncDef(RuntimeHandleClass, 2, false, true, false, false)
|
||||
ValueNumFuncDef(ReadyToRunGenericHandle, 2, false, true, false, false)
|
||||
|
|
|
@ -11,8 +11,8 @@ struct ReadyToRunHeaderConstants
|
|||
{
|
||||
static const uint32_t Signature = 0x00525452; // 'RTR'
|
||||
|
||||
static const uint32_t CurrentMajorVersion = 9;
|
||||
static const uint32_t CurrentMinorVersion = 3;
|
||||
static const uint32_t CurrentMajorVersion = 10;
|
||||
static const uint32_t CurrentMinorVersion = 0;
|
||||
};
|
||||
|
||||
struct ReadyToRunHeader
|
||||
|
|
|
@ -2802,7 +2802,7 @@ EXTERN_C const IID IID_ISOSDacInterface8;
|
|||
/* interface __MIDL_itf_sospriv_0000_0012 */
|
||||
/* [local] */
|
||||
|
||||
#define SOS_BREAKING_CHANGE_VERSION 4
|
||||
#define SOS_BREAKING_CHANGE_VERSION 5
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_sospriv_0000_0012_v0_0_c_ifspec;
|
||||
|
|
|
@ -15,8 +15,8 @@ namespace Internal.Runtime
|
|||
{
|
||||
public const uint Signature = 0x00525452; // 'RTR'
|
||||
|
||||
public const ushort CurrentMajorVersion = 9;
|
||||
public const ushort CurrentMinorVersion = 3;
|
||||
public const ushort CurrentMajorVersion = 10;
|
||||
public const ushort CurrentMinorVersion = 0;
|
||||
}
|
||||
#if READYTORUN
|
||||
#pragma warning disable 0169
|
||||
|
|
|
@ -170,29 +170,31 @@ namespace Internal.JitInterface
|
|||
// ICorClassInfo::getSharedStaticsOrCCtorHelper to determine which helper to use
|
||||
|
||||
// Helpers for regular statics
|
||||
CORINFO_HELP_GETGENERICS_GCSTATIC_BASE,
|
||||
CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE,
|
||||
CORINFO_HELP_GETSHARED_GCSTATIC_BASE,
|
||||
CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE,
|
||||
CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS,
|
||||
CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS,
|
||||
// Helper to class initialize shared generic with dynamicclass, but not get static field address
|
||||
CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS,
|
||||
CORINFO_HELP_GET_GCSTATIC_BASE,
|
||||
CORINFO_HELP_GET_NONGCSTATIC_BASE,
|
||||
CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE,
|
||||
CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE,
|
||||
CORINFO_HELP_GETPINNED_GCSTATIC_BASE,
|
||||
CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE,
|
||||
CORINFO_HELP_GET_GCSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GET_NONGCSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETPINNED_GCSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE_NOCTOR,
|
||||
|
||||
// Helpers for thread statics
|
||||
CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE,
|
||||
CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE,
|
||||
CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE,
|
||||
CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE,
|
||||
CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS,
|
||||
CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS,
|
||||
CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED,
|
||||
CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED,
|
||||
|
||||
CORINFO_HELP_GET_GCTHREADSTATIC_BASE,
|
||||
CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE,
|
||||
CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE,
|
||||
CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE,
|
||||
CORINFO_HELP_GET_GCTHREADSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR,
|
||||
CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED,
|
||||
CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED,
|
||||
CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED2,
|
||||
/* Debugger */
|
||||
|
||||
CORINFO_HELP_DBG_IS_JUST_MY_CODE, // Check if this is "JustMyCode" and needs to be stepped through.
|
||||
|
|
|
@ -2118,8 +2118,10 @@ namespace Internal.JitInterface
|
|||
Marshal.FreeCoTaskMem((IntPtr)obj);
|
||||
}
|
||||
|
||||
private UIntPtr getClassModuleIdForStatics(CORINFO_CLASS_STRUCT_* cls, CORINFO_MODULE_STRUCT_** pModule, void** ppIndirection)
|
||||
{ throw new NotImplementedException("getClassModuleIdForStatics"); }
|
||||
private UIntPtr getClassStaticDynamicInfo(CORINFO_CLASS_STRUCT_* cls)
|
||||
{ throw new NotImplementedException("getClassStaticDynamicInfo"); }
|
||||
private UIntPtr getClassThreadStaticDynamicInfo(CORINFO_CLASS_STRUCT_* cls)
|
||||
{ throw new NotImplementedException("getClassThreadStaticDynamicInfo"); }
|
||||
|
||||
private uint getClassSize(CORINFO_CLASS_STRUCT_* cls)
|
||||
{
|
||||
|
@ -2632,17 +2634,15 @@ namespace Internal.JitInterface
|
|||
MethodDesc md = method == null ? MethodBeingCompiled : HandleToObject(method);
|
||||
TypeDesc type = fd != null ? fd.OwningType : typeFromContext(context);
|
||||
|
||||
#if !READYTORUN
|
||||
if (
|
||||
#if READYTORUN
|
||||
IsClassPreInited(type)
|
||||
#else
|
||||
_isFallbackBodyCompilation ||
|
||||
!_compilation.HasLazyStaticConstructor(type)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return CorInfoInitClassResult.CORINFO_INITCLASS_NOT_REQUIRED;
|
||||
}
|
||||
#endif
|
||||
|
||||
MetadataType typeToInit = (MetadataType)type;
|
||||
|
||||
|
@ -3069,7 +3069,7 @@ namespace Internal.JitInterface
|
|||
}
|
||||
|
||||
#pragma warning disable CA1822 // Mark members as static
|
||||
private void getThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType)
|
||||
private void getThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo)
|
||||
#pragma warning restore CA1822 // Mark members as static
|
||||
{
|
||||
// Implemented for JIT only for now.
|
||||
|
@ -3568,9 +3568,6 @@ namespace Internal.JitInterface
|
|||
return constLookup;
|
||||
}
|
||||
|
||||
private uint getClassDomainID(CORINFO_CLASS_STRUCT_* cls, ref void* ppIndirection)
|
||||
{ throw new NotImplementedException("getClassDomainID"); }
|
||||
|
||||
private CORINFO_CLASS_STRUCT_* getStaticFieldCurrentClass(CORINFO_FIELD_STRUCT_* field, byte* pIsSpeculative)
|
||||
{
|
||||
if (pIsSpeculative != null)
|
||||
|
|
|
@ -688,12 +688,12 @@ namespace Internal.JitInterface
|
|||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
private static UIntPtr _getClassModuleIdForStatics(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls, CORINFO_MODULE_STRUCT_** pModule, void** ppIndirection)
|
||||
private static byte _getIsClassInitedFlagAddress(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls, CORINFO_CONST_LOOKUP* addr, int* offset)
|
||||
{
|
||||
var _this = GetThis(thisHandle);
|
||||
try
|
||||
{
|
||||
return _this.getClassModuleIdForStatics(cls, pModule, ppIndirection);
|
||||
return _this.getIsClassInitedFlagAddress(cls, ref *addr, ref *offset) ? (byte)1 : (byte)0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -703,12 +703,27 @@ namespace Internal.JitInterface
|
|||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
private static byte _getIsClassInitedFlagAddress(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls, CORINFO_CONST_LOOKUP* addr, int* offset)
|
||||
private static UIntPtr _getClassThreadStaticDynamicInfo(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* clr)
|
||||
{
|
||||
var _this = GetThis(thisHandle);
|
||||
try
|
||||
{
|
||||
return _this.getIsClassInitedFlagAddress(cls, ref *addr, ref *offset) ? (byte)1 : (byte)0;
|
||||
return _this.getClassThreadStaticDynamicInfo(clr);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
*ppException = _this.AllocException(ex);
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
private static UIntPtr _getClassStaticDynamicInfo(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* clr)
|
||||
{
|
||||
var _this = GetThis(thisHandle);
|
||||
try
|
||||
{
|
||||
return _this.getClassStaticDynamicInfo(clr);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -1435,12 +1450,12 @@ namespace Internal.JitInterface
|
|||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
private static void _getThreadLocalStaticBlocksInfo(IntPtr thisHandle, IntPtr* ppException, CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, byte isGCType)
|
||||
private static void _getThreadLocalStaticBlocksInfo(IntPtr thisHandle, IntPtr* ppException, CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo)
|
||||
{
|
||||
var _this = GetThis(thisHandle);
|
||||
try
|
||||
{
|
||||
_this.getThreadLocalStaticBlocksInfo(pInfo, isGCType != 0);
|
||||
_this.getThreadLocalStaticBlocksInfo(pInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -2136,21 +2151,6 @@ namespace Internal.JitInterface
|
|||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
private static uint _getClassDomainID(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls, void** ppIndirection)
|
||||
{
|
||||
var _this = GetThis(thisHandle);
|
||||
try
|
||||
{
|
||||
return _this.getClassDomainID(cls, ref *ppIndirection);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
*ppException = _this.AllocException(ex);
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
private static byte _getStaticFieldContent(IntPtr thisHandle, IntPtr* ppException, CORINFO_FIELD_STRUCT_* field, byte* buffer, int bufferSize, int valueOffset, byte ignoreMovableObjects)
|
||||
{
|
||||
|
@ -2642,105 +2642,105 @@ namespace Internal.JitInterface
|
|||
callbacks[43] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_ASSEMBLY_STRUCT_*, byte*>)&_getAssemblyName;
|
||||
callbacks[44] = (delegate* unmanaged<IntPtr, IntPtr*, UIntPtr, void*>)&_LongLifetimeMalloc;
|
||||
callbacks[45] = (delegate* unmanaged<IntPtr, IntPtr*, void*, void>)&_LongLifetimeFree;
|
||||
callbacks[46] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_MODULE_STRUCT_**, void**, UIntPtr>)&_getClassModuleIdForStatics;
|
||||
callbacks[47] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_CONST_LOOKUP*, int*, byte>)&_getIsClassInitedFlagAddress;
|
||||
callbacks[48] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, byte, CORINFO_CONST_LOOKUP*, byte>)&_getStaticBaseAddress;
|
||||
callbacks[49] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, uint>)&_getClassSize;
|
||||
callbacks[50] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, uint>)&_getHeapClassSize;
|
||||
callbacks[51] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, byte>)&_canAllocateOnStack;
|
||||
callbacks[52] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, byte, uint>)&_getClassAlignmentRequirement;
|
||||
callbacks[53] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, byte*, uint>)&_getClassGClayout;
|
||||
callbacks[54] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, uint>)&_getClassNumInstanceFields;
|
||||
callbacks[55] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, int, CORINFO_FIELD_STRUCT_*>)&_getFieldInClass;
|
||||
callbacks[56] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_TYPE_LAYOUT_NODE*, UIntPtr*, GetTypeLayoutResult>)&_getTypeLayout;
|
||||
callbacks[57] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, byte*, byte, byte>)&_checkMethodModifier;
|
||||
callbacks[58] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, bool*, CorInfoHelpFunc>)&_getNewHelper;
|
||||
callbacks[59] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CorInfoHelpFunc>)&_getNewArrHelper;
|
||||
callbacks[60] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_RESOLVED_TOKEN*, byte, CorInfoHelpFunc>)&_getCastingHelper;
|
||||
callbacks[61] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CorInfoHelpFunc>)&_getSharedCCtorHelper;
|
||||
callbacks[62] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_CLASS_STRUCT_*>)&_getTypeForBox;
|
||||
callbacks[63] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CorInfoHelpFunc>)&_getBoxHelper;
|
||||
callbacks[64] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CorInfoHelpFunc>)&_getUnBoxHelper;
|
||||
callbacks[65] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_OBJECT_STRUCT_*>)&_getRuntimeTypePointer;
|
||||
callbacks[66] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_OBJECT_STRUCT_*, byte>)&_isObjectImmutable;
|
||||
callbacks[67] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_OBJECT_STRUCT_*, int, ushort*, byte>)&_getStringChar;
|
||||
callbacks[68] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_OBJECT_STRUCT_*, CORINFO_CLASS_STRUCT_*>)&_getObjectType;
|
||||
callbacks[69] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_RESOLVED_TOKEN*, CORINFO_LOOKUP_KIND*, CorInfoHelpFunc, CORINFO_METHOD_STRUCT_*, CORINFO_CONST_LOOKUP*, byte>)&_getReadyToRunHelper;
|
||||
callbacks[70] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_RESOLVED_TOKEN*, mdToken, CORINFO_CLASS_STRUCT_*, CORINFO_METHOD_STRUCT_*, CORINFO_LOOKUP*, void>)&_getReadyToRunDelegateCtorHelper;
|
||||
callbacks[71] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, CORINFO_METHOD_STRUCT_*, CORINFO_CONTEXT_STRUCT*, CorInfoInitClassResult>)&_initClass;
|
||||
callbacks[72] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, void>)&_classMustBeLoadedBeforeCodeIsRun;
|
||||
callbacks[73] = (delegate* unmanaged<IntPtr, IntPtr*, CorInfoClassId, CORINFO_CLASS_STRUCT_*>)&_getBuiltinClass;
|
||||
callbacks[74] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CorInfoType>)&_getTypeForPrimitiveValueClass;
|
||||
callbacks[75] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CorInfoType>)&_getTypeForPrimitiveNumericClass;
|
||||
callbacks[76] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_CLASS_STRUCT_*, byte>)&_canCast;
|
||||
callbacks[77] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_CLASS_STRUCT_*, TypeCompareState>)&_compareTypesForCast;
|
||||
callbacks[78] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_CLASS_STRUCT_*, TypeCompareState>)&_compareTypesForEquality;
|
||||
callbacks[79] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_CLASS_STRUCT_*, byte>)&_isMoreSpecificType;
|
||||
callbacks[80] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, byte>)&_isExactType;
|
||||
callbacks[81] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, TypeCompareState>)&_isNullableType;
|
||||
callbacks[82] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_CLASS_STRUCT_**, TypeCompareState>)&_isEnum;
|
||||
callbacks[83] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_CLASS_STRUCT_*>)&_getParentType;
|
||||
callbacks[84] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_CLASS_STRUCT_**, CorInfoType>)&_getChildType;
|
||||
callbacks[85] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, byte>)&_isSDArray;
|
||||
callbacks[86] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, uint>)&_getArrayRank;
|
||||
callbacks[87] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, CorInfoArrayIntrinsic>)&_getArrayIntrinsicID;
|
||||
callbacks[88] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, uint, void*>)&_getArrayInitializationData;
|
||||
callbacks[89] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_RESOLVED_TOKEN*, CORINFO_METHOD_STRUCT_*, CORINFO_HELPER_DESC*, CorInfoIsAccessAllowedResult>)&_canAccessClass;
|
||||
callbacks[90] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, byte*, UIntPtr, UIntPtr*, UIntPtr>)&_printFieldName;
|
||||
callbacks[91] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, CORINFO_CLASS_STRUCT_*>)&_getFieldClass;
|
||||
callbacks[92] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, CORINFO_CLASS_STRUCT_**, CORINFO_CLASS_STRUCT_*, CorInfoType>)&_getFieldType;
|
||||
callbacks[93] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, uint>)&_getFieldOffset;
|
||||
callbacks[94] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_RESOLVED_TOKEN*, CORINFO_METHOD_STRUCT_*, CORINFO_ACCESS_FLAGS, CORINFO_FIELD_INFO*, void>)&_getFieldInfo;
|
||||
callbacks[95] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, byte, uint>)&_getThreadLocalFieldInfo;
|
||||
callbacks[96] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_THREAD_STATIC_BLOCKS_INFO*, byte, void>)&_getThreadLocalStaticBlocksInfo;
|
||||
callbacks[97] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_THREAD_STATIC_INFO_NATIVEAOT*, void>)&_getThreadLocalStaticInfo_NativeAOT;
|
||||
callbacks[98] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, byte>)&_isFieldStatic;
|
||||
callbacks[99] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_OBJECT_STRUCT_*, int>)&_getArrayOrStringLength;
|
||||
callbacks[100] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, uint*, uint**, BoundaryTypes*, void>)&_getBoundaries;
|
||||
callbacks[101] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, uint, OffsetMapping*, void>)&_setBoundaries;
|
||||
callbacks[102] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, uint*, ILVarInfo**, bool*, void>)&_getVars;
|
||||
callbacks[103] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, uint, NativeVarInfo*, void>)&_setVars;
|
||||
callbacks[104] = (delegate* unmanaged<IntPtr, IntPtr*, InlineTreeNode*, uint, RichOffsetMapping*, uint, void>)&_reportRichMappings;
|
||||
callbacks[105] = (delegate* unmanaged<IntPtr, IntPtr*, byte*, void*, UIntPtr, void>)&_reportMetadata;
|
||||
callbacks[106] = (delegate* unmanaged<IntPtr, IntPtr*, UIntPtr, void*>)&_allocateArray;
|
||||
callbacks[107] = (delegate* unmanaged<IntPtr, IntPtr*, void*, void>)&_freeArray;
|
||||
callbacks[108] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_ARG_LIST_STRUCT_*, CORINFO_ARG_LIST_STRUCT_*>)&_getArgNext;
|
||||
callbacks[109] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_SIG_INFO*, CORINFO_ARG_LIST_STRUCT_*, CORINFO_CLASS_STRUCT_**, CorInfoTypeWithMod>)&_getArgType;
|
||||
callbacks[110] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, int, CORINFO_CLASS_STRUCT_**, int>)&_getExactClasses;
|
||||
callbacks[111] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_SIG_INFO*, CORINFO_ARG_LIST_STRUCT_*, CORINFO_CLASS_STRUCT_*>)&_getArgClass;
|
||||
callbacks[112] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CorInfoHFAElemType>)&_getHFAType;
|
||||
callbacks[113] = (delegate* unmanaged<IntPtr, IntPtr*, void*, void*, byte>)&_runWithErrorTrap;
|
||||
callbacks[114] = (delegate* unmanaged<IntPtr, IntPtr*, void*, void*, byte>)&_runWithSPMIErrorTrap;
|
||||
callbacks[115] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_EE_INFO*, void>)&_getEEInfo;
|
||||
callbacks[116] = (delegate* unmanaged<IntPtr, IntPtr*, char*>)&_getJitTimeLogFilename;
|
||||
callbacks[117] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, mdToken>)&_getMethodDefFromMethod;
|
||||
callbacks[118] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, byte*, UIntPtr, UIntPtr*, UIntPtr>)&_printMethodName;
|
||||
callbacks[119] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, byte**, byte**, byte**, byte*>)&_getMethodNameFromMetadata;
|
||||
callbacks[120] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, uint>)&_getMethodHash;
|
||||
callbacks[121] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR*, byte>)&_getSystemVAmd64PassStructInRegisterDescriptor;
|
||||
callbacks[122] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_SWIFT_LOWERING*, void>)&_getSwiftLowering;
|
||||
callbacks[123] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, uint>)&_getLoongArch64PassStructInRegisterFlags;
|
||||
callbacks[124] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, uint>)&_getRISCV64PassStructInRegisterFlags;
|
||||
callbacks[125] = (delegate* unmanaged<IntPtr, IntPtr*, void**, uint>)&_getThreadTLSIndex;
|
||||
callbacks[126] = (delegate* unmanaged<IntPtr, IntPtr*, void**, int*>)&_getAddrOfCaptureThreadGlobal;
|
||||
callbacks[127] = (delegate* unmanaged<IntPtr, IntPtr*, CorInfoHelpFunc, void**, void*>)&_getHelperFtn;
|
||||
callbacks[128] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, CORINFO_CONST_LOOKUP*, CORINFO_ACCESS_FLAGS, void>)&_getFunctionEntryPoint;
|
||||
callbacks[129] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, byte, CORINFO_CONST_LOOKUP*, void>)&_getFunctionFixedEntryPoint;
|
||||
callbacks[130] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, void**, void*>)&_getMethodSync;
|
||||
callbacks[131] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_MODULE_STRUCT_*, CorInfoHelpFunc>)&_getLazyStringLiteralHelper;
|
||||
callbacks[132] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_MODULE_STRUCT_*, void**, CORINFO_MODULE_STRUCT_*>)&_embedModuleHandle;
|
||||
callbacks[133] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, void**, CORINFO_CLASS_STRUCT_*>)&_embedClassHandle;
|
||||
callbacks[134] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, void**, CORINFO_METHOD_STRUCT_*>)&_embedMethodHandle;
|
||||
callbacks[135] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, void**, CORINFO_FIELD_STRUCT_*>)&_embedFieldHandle;
|
||||
callbacks[136] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_RESOLVED_TOKEN*, byte, CORINFO_METHOD_STRUCT_*, CORINFO_GENERICHANDLE_RESULT*, void>)&_embedGenericHandle;
|
||||
callbacks[137] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, CORINFO_LOOKUP_KIND*, void>)&_getLocationOfThisType;
|
||||
callbacks[138] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, CORINFO_CONST_LOOKUP*, void>)&_getAddressOfPInvokeTarget;
|
||||
callbacks[139] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_SIG_INFO*, void**, void*>)&_GetCookieForPInvokeCalliSig;
|
||||
callbacks[140] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_SIG_INFO*, byte>)&_canGetCookieForPInvokeCalliSig;
|
||||
callbacks[141] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, CORINFO_JUST_MY_CODE_HANDLE_**, CORINFO_JUST_MY_CODE_HANDLE_*>)&_getJustMyCodeHandle;
|
||||
callbacks[142] = (delegate* unmanaged<IntPtr, IntPtr*, bool*, void**, bool*, void>)&_GetProfilingHandle;
|
||||
callbacks[143] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_RESOLVED_TOKEN*, CORINFO_RESOLVED_TOKEN*, CORINFO_METHOD_STRUCT_*, CORINFO_CALLINFO_FLAGS, CORINFO_CALL_INFO*, void>)&_getCallInfo;
|
||||
callbacks[144] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, void**, uint>)&_getClassDomainID;
|
||||
callbacks[46] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_CONST_LOOKUP*, int*, byte>)&_getIsClassInitedFlagAddress;
|
||||
callbacks[47] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, UIntPtr>)&_getClassThreadStaticDynamicInfo;
|
||||
callbacks[48] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, UIntPtr>)&_getClassStaticDynamicInfo;
|
||||
callbacks[49] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, byte, CORINFO_CONST_LOOKUP*, byte>)&_getStaticBaseAddress;
|
||||
callbacks[50] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, uint>)&_getClassSize;
|
||||
callbacks[51] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, uint>)&_getHeapClassSize;
|
||||
callbacks[52] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, byte>)&_canAllocateOnStack;
|
||||
callbacks[53] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, byte, uint>)&_getClassAlignmentRequirement;
|
||||
callbacks[54] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, byte*, uint>)&_getClassGClayout;
|
||||
callbacks[55] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, uint>)&_getClassNumInstanceFields;
|
||||
callbacks[56] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, int, CORINFO_FIELD_STRUCT_*>)&_getFieldInClass;
|
||||
callbacks[57] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_TYPE_LAYOUT_NODE*, UIntPtr*, GetTypeLayoutResult>)&_getTypeLayout;
|
||||
callbacks[58] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, byte*, byte, byte>)&_checkMethodModifier;
|
||||
callbacks[59] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, bool*, CorInfoHelpFunc>)&_getNewHelper;
|
||||
callbacks[60] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CorInfoHelpFunc>)&_getNewArrHelper;
|
||||
callbacks[61] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_RESOLVED_TOKEN*, byte, CorInfoHelpFunc>)&_getCastingHelper;
|
||||
callbacks[62] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CorInfoHelpFunc>)&_getSharedCCtorHelper;
|
||||
callbacks[63] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_CLASS_STRUCT_*>)&_getTypeForBox;
|
||||
callbacks[64] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CorInfoHelpFunc>)&_getBoxHelper;
|
||||
callbacks[65] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CorInfoHelpFunc>)&_getUnBoxHelper;
|
||||
callbacks[66] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_OBJECT_STRUCT_*>)&_getRuntimeTypePointer;
|
||||
callbacks[67] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_OBJECT_STRUCT_*, byte>)&_isObjectImmutable;
|
||||
callbacks[68] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_OBJECT_STRUCT_*, int, ushort*, byte>)&_getStringChar;
|
||||
callbacks[69] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_OBJECT_STRUCT_*, CORINFO_CLASS_STRUCT_*>)&_getObjectType;
|
||||
callbacks[70] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_RESOLVED_TOKEN*, CORINFO_LOOKUP_KIND*, CorInfoHelpFunc, CORINFO_METHOD_STRUCT_*, CORINFO_CONST_LOOKUP*, byte>)&_getReadyToRunHelper;
|
||||
callbacks[71] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_RESOLVED_TOKEN*, mdToken, CORINFO_CLASS_STRUCT_*, CORINFO_METHOD_STRUCT_*, CORINFO_LOOKUP*, void>)&_getReadyToRunDelegateCtorHelper;
|
||||
callbacks[72] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, CORINFO_METHOD_STRUCT_*, CORINFO_CONTEXT_STRUCT*, CorInfoInitClassResult>)&_initClass;
|
||||
callbacks[73] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, void>)&_classMustBeLoadedBeforeCodeIsRun;
|
||||
callbacks[74] = (delegate* unmanaged<IntPtr, IntPtr*, CorInfoClassId, CORINFO_CLASS_STRUCT_*>)&_getBuiltinClass;
|
||||
callbacks[75] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CorInfoType>)&_getTypeForPrimitiveValueClass;
|
||||
callbacks[76] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CorInfoType>)&_getTypeForPrimitiveNumericClass;
|
||||
callbacks[77] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_CLASS_STRUCT_*, byte>)&_canCast;
|
||||
callbacks[78] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_CLASS_STRUCT_*, TypeCompareState>)&_compareTypesForCast;
|
||||
callbacks[79] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_CLASS_STRUCT_*, TypeCompareState>)&_compareTypesForEquality;
|
||||
callbacks[80] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_CLASS_STRUCT_*, byte>)&_isMoreSpecificType;
|
||||
callbacks[81] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, byte>)&_isExactType;
|
||||
callbacks[82] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, TypeCompareState>)&_isNullableType;
|
||||
callbacks[83] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_CLASS_STRUCT_**, TypeCompareState>)&_isEnum;
|
||||
callbacks[84] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_CLASS_STRUCT_*>)&_getParentType;
|
||||
callbacks[85] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_CLASS_STRUCT_**, CorInfoType>)&_getChildType;
|
||||
callbacks[86] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, byte>)&_isSDArray;
|
||||
callbacks[87] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, uint>)&_getArrayRank;
|
||||
callbacks[88] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, CorInfoArrayIntrinsic>)&_getArrayIntrinsicID;
|
||||
callbacks[89] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, uint, void*>)&_getArrayInitializationData;
|
||||
callbacks[90] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_RESOLVED_TOKEN*, CORINFO_METHOD_STRUCT_*, CORINFO_HELPER_DESC*, CorInfoIsAccessAllowedResult>)&_canAccessClass;
|
||||
callbacks[91] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, byte*, UIntPtr, UIntPtr*, UIntPtr>)&_printFieldName;
|
||||
callbacks[92] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, CORINFO_CLASS_STRUCT_*>)&_getFieldClass;
|
||||
callbacks[93] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, CORINFO_CLASS_STRUCT_**, CORINFO_CLASS_STRUCT_*, CorInfoType>)&_getFieldType;
|
||||
callbacks[94] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, uint>)&_getFieldOffset;
|
||||
callbacks[95] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_RESOLVED_TOKEN*, CORINFO_METHOD_STRUCT_*, CORINFO_ACCESS_FLAGS, CORINFO_FIELD_INFO*, void>)&_getFieldInfo;
|
||||
callbacks[96] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, byte, uint>)&_getThreadLocalFieldInfo;
|
||||
callbacks[97] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_THREAD_STATIC_BLOCKS_INFO*, void>)&_getThreadLocalStaticBlocksInfo;
|
||||
callbacks[98] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_THREAD_STATIC_INFO_NATIVEAOT*, void>)&_getThreadLocalStaticInfo_NativeAOT;
|
||||
callbacks[99] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, byte>)&_isFieldStatic;
|
||||
callbacks[100] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_OBJECT_STRUCT_*, int>)&_getArrayOrStringLength;
|
||||
callbacks[101] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, uint*, uint**, BoundaryTypes*, void>)&_getBoundaries;
|
||||
callbacks[102] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, uint, OffsetMapping*, void>)&_setBoundaries;
|
||||
callbacks[103] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, uint*, ILVarInfo**, bool*, void>)&_getVars;
|
||||
callbacks[104] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, uint, NativeVarInfo*, void>)&_setVars;
|
||||
callbacks[105] = (delegate* unmanaged<IntPtr, IntPtr*, InlineTreeNode*, uint, RichOffsetMapping*, uint, void>)&_reportRichMappings;
|
||||
callbacks[106] = (delegate* unmanaged<IntPtr, IntPtr*, byte*, void*, UIntPtr, void>)&_reportMetadata;
|
||||
callbacks[107] = (delegate* unmanaged<IntPtr, IntPtr*, UIntPtr, void*>)&_allocateArray;
|
||||
callbacks[108] = (delegate* unmanaged<IntPtr, IntPtr*, void*, void>)&_freeArray;
|
||||
callbacks[109] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_ARG_LIST_STRUCT_*, CORINFO_ARG_LIST_STRUCT_*>)&_getArgNext;
|
||||
callbacks[110] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_SIG_INFO*, CORINFO_ARG_LIST_STRUCT_*, CORINFO_CLASS_STRUCT_**, CorInfoTypeWithMod>)&_getArgType;
|
||||
callbacks[111] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, int, CORINFO_CLASS_STRUCT_**, int>)&_getExactClasses;
|
||||
callbacks[112] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_SIG_INFO*, CORINFO_ARG_LIST_STRUCT_*, CORINFO_CLASS_STRUCT_*>)&_getArgClass;
|
||||
callbacks[113] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CorInfoHFAElemType>)&_getHFAType;
|
||||
callbacks[114] = (delegate* unmanaged<IntPtr, IntPtr*, void*, void*, byte>)&_runWithErrorTrap;
|
||||
callbacks[115] = (delegate* unmanaged<IntPtr, IntPtr*, void*, void*, byte>)&_runWithSPMIErrorTrap;
|
||||
callbacks[116] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_EE_INFO*, void>)&_getEEInfo;
|
||||
callbacks[117] = (delegate* unmanaged<IntPtr, IntPtr*, char*>)&_getJitTimeLogFilename;
|
||||
callbacks[118] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, mdToken>)&_getMethodDefFromMethod;
|
||||
callbacks[119] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, byte*, UIntPtr, UIntPtr*, UIntPtr>)&_printMethodName;
|
||||
callbacks[120] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, byte**, byte**, byte**, byte*>)&_getMethodNameFromMetadata;
|
||||
callbacks[121] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, uint>)&_getMethodHash;
|
||||
callbacks[122] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR*, byte>)&_getSystemVAmd64PassStructInRegisterDescriptor;
|
||||
callbacks[123] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_SWIFT_LOWERING*, void>)&_getSwiftLowering;
|
||||
callbacks[124] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, uint>)&_getLoongArch64PassStructInRegisterFlags;
|
||||
callbacks[125] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, uint>)&_getRISCV64PassStructInRegisterFlags;
|
||||
callbacks[126] = (delegate* unmanaged<IntPtr, IntPtr*, void**, uint>)&_getThreadTLSIndex;
|
||||
callbacks[127] = (delegate* unmanaged<IntPtr, IntPtr*, void**, int*>)&_getAddrOfCaptureThreadGlobal;
|
||||
callbacks[128] = (delegate* unmanaged<IntPtr, IntPtr*, CorInfoHelpFunc, void**, void*>)&_getHelperFtn;
|
||||
callbacks[129] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, CORINFO_CONST_LOOKUP*, CORINFO_ACCESS_FLAGS, void>)&_getFunctionEntryPoint;
|
||||
callbacks[130] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, byte, CORINFO_CONST_LOOKUP*, void>)&_getFunctionFixedEntryPoint;
|
||||
callbacks[131] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, void**, void*>)&_getMethodSync;
|
||||
callbacks[132] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_MODULE_STRUCT_*, CorInfoHelpFunc>)&_getLazyStringLiteralHelper;
|
||||
callbacks[133] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_MODULE_STRUCT_*, void**, CORINFO_MODULE_STRUCT_*>)&_embedModuleHandle;
|
||||
callbacks[134] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, void**, CORINFO_CLASS_STRUCT_*>)&_embedClassHandle;
|
||||
callbacks[135] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, void**, CORINFO_METHOD_STRUCT_*>)&_embedMethodHandle;
|
||||
callbacks[136] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, void**, CORINFO_FIELD_STRUCT_*>)&_embedFieldHandle;
|
||||
callbacks[137] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_RESOLVED_TOKEN*, byte, CORINFO_METHOD_STRUCT_*, CORINFO_GENERICHANDLE_RESULT*, void>)&_embedGenericHandle;
|
||||
callbacks[138] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, CORINFO_LOOKUP_KIND*, void>)&_getLocationOfThisType;
|
||||
callbacks[139] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, CORINFO_CONST_LOOKUP*, void>)&_getAddressOfPInvokeTarget;
|
||||
callbacks[140] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_SIG_INFO*, void**, void*>)&_GetCookieForPInvokeCalliSig;
|
||||
callbacks[141] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_SIG_INFO*, byte>)&_canGetCookieForPInvokeCalliSig;
|
||||
callbacks[142] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, CORINFO_JUST_MY_CODE_HANDLE_**, CORINFO_JUST_MY_CODE_HANDLE_*>)&_getJustMyCodeHandle;
|
||||
callbacks[143] = (delegate* unmanaged<IntPtr, IntPtr*, bool*, void**, bool*, void>)&_GetProfilingHandle;
|
||||
callbacks[144] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_RESOLVED_TOKEN*, CORINFO_RESOLVED_TOKEN*, CORINFO_METHOD_STRUCT_*, CORINFO_CALLINFO_FLAGS, CORINFO_CALL_INFO*, void>)&_getCallInfo;
|
||||
callbacks[145] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, byte*, int, int, byte, byte>)&_getStaticFieldContent;
|
||||
callbacks[146] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_OBJECT_STRUCT_*, byte*, int, int, byte>)&_getObjectContent;
|
||||
callbacks[147] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, byte*, CORINFO_CLASS_STRUCT_*>)&_getStaticFieldCurrentClass;
|
||||
|
|
|
@ -1162,7 +1162,7 @@ namespace Internal.JitInterface
|
|||
public uint offsetOfThreadLocalStoragePointer;
|
||||
public uint offsetOfMaxThreadStaticBlocks;
|
||||
public uint offsetOfThreadStaticBlocks;
|
||||
public uint offsetOfGCDataPointer;
|
||||
public uint offsetOfBaseOfThreadLocalData;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -209,8 +209,9 @@ FUNCTIONS
|
|||
const char* getAssemblyName(CORINFO_ASSEMBLY_HANDLE assem)
|
||||
void* LongLifetimeMalloc(size_t sz)
|
||||
void LongLifetimeFree(void* obj)
|
||||
size_t getClassModuleIdForStatics(CORINFO_CLASS_HANDLE cls, CORINFO_MODULE_HANDLE* pModule, VOIDSTARSTAR ppIndirection)
|
||||
bool getIsClassInitedFlagAddress(CORINFO_CLASS_HANDLE cls, CORINFO_CONST_LOOKUP* addr, int* offset)
|
||||
size_t getClassThreadStaticDynamicInfo(CORINFO_CLASS_HANDLE clr)
|
||||
size_t getClassStaticDynamicInfo(CORINFO_CLASS_HANDLE clr)
|
||||
bool getStaticBaseAddress(CORINFO_CLASS_HANDLE cls, bool isGc, CORINFO_CONST_LOOKUP* addr)
|
||||
unsigned getClassSize(CORINFO_CLASS_HANDLE cls)
|
||||
unsigned getHeapClassSize(CORINFO_CLASS_HANDLE cls)
|
||||
|
@ -259,7 +260,7 @@ FUNCTIONS
|
|||
unsigned getFieldOffset(CORINFO_FIELD_HANDLE field)
|
||||
void getFieldInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_ACCESS_FLAGS flags, CORINFO_FIELD_INFO* pResult)
|
||||
uint32_t getThreadLocalFieldInfo (CORINFO_FIELD_HANDLE field, bool isGCtype)
|
||||
void getThreadLocalStaticBlocksInfo (CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType)
|
||||
void getThreadLocalStaticBlocksInfo (CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo)
|
||||
void getThreadLocalStaticInfo_NativeAOT(CORINFO_THREAD_STATIC_INFO_NATIVEAOT* pInfo)
|
||||
bool isFieldStatic(CORINFO_FIELD_HANDLE fldHnd)
|
||||
int getArrayOrStringLength(CORINFO_OBJECT_HANDLE objHnd)
|
||||
|
@ -307,7 +308,6 @@ FUNCTIONS
|
|||
CORINFO_JUST_MY_CODE_HANDLE getJustMyCodeHandle(CORINFO_METHOD_HANDLE method, CORINFO_JUST_MY_CODE_HANDLE**ppIndirection);
|
||||
void GetProfilingHandle(bool* pbHookFunction, void **pProfilerHandle, bool* pbIndirectedHandles);
|
||||
void getCallInfo(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN_PTR pConstrainedResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_CALLINFO_FLAGS flags, CORINFO_CALL_INFO *pResult);
|
||||
unsigned getClassDomainID (CORINFO_CLASS_HANDLE cls, void **ppIndirection);
|
||||
bool getStaticFieldContent(CORINFO_FIELD_HANDLE field, uint8_t *buffer, int bufferSize, int valueOffset, bool ignoreMovableObjects);
|
||||
bool getObjectContent(CORINFO_OBJECT_HANDLE obj, uint8_t *buffer, int bufferSize, int valueOffset);
|
||||
CORINFO_CLASS_HANDLE getStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, BoolStar pIsSpeculative);
|
||||
|
|
|
@ -57,27 +57,8 @@ namespace ILCompiler
|
|||
{
|
||||
// ECMA types are the only ones that can have statics
|
||||
ModuleFieldLayout moduleFieldLayout = _moduleFieldLayoutMap.GetOrCreateValue(ecmaType.EcmaModule);
|
||||
layout.GcStatics = moduleFieldLayout.GcStatics;
|
||||
layout.NonGcStatics = moduleFieldLayout.NonGcStatics;
|
||||
layout.ThreadGcStatics = moduleFieldLayout.ThreadGcStatics;
|
||||
layout.ThreadNonGcStatics = moduleFieldLayout.ThreadNonGcStatics;
|
||||
if (defType is EcmaType nonGenericType)
|
||||
{
|
||||
OffsetsForType offsetsForType;
|
||||
if (moduleFieldLayout.TypeOffsets.TryGetValue(nonGenericType.Handle, out offsetsForType))
|
||||
{
|
||||
layout.Offsets = _moduleFieldLayoutMap.CalculateTypeLayout(defType, moduleFieldLayout.Module, offsetsForType);
|
||||
}
|
||||
}
|
||||
else if (defType is InstantiatedType instantiatedType)
|
||||
{
|
||||
layout.Offsets = _moduleFieldLayoutMap.GetOrAddDynamicLayout(defType, moduleFieldLayout);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
return layout;
|
||||
}
|
||||
|
||||
|
@ -86,46 +67,6 @@ namespace ILCompiler
|
|||
/// </summary>
|
||||
private class ModuleFieldLayoutMap : LockFreeReaderHashtable<EcmaModule, ModuleFieldLayout>
|
||||
{
|
||||
/// <summary>
|
||||
/// CoreCLR DomainLocalModule::OffsetOfDataBlob() / sizeof(void *)
|
||||
/// </summary>
|
||||
private const int DomainLocalModuleDataBlobOffsetAsIntPtrCount = 6;
|
||||
|
||||
/// <summary>
|
||||
/// CoreCLR ThreadLocalModule::OffsetOfDataBlob() / sizeof(void *)
|
||||
/// </summary>
|
||||
private const int ThreadLocalModuleDataBlobOffsetAsIntPtrCount = 3;
|
||||
|
||||
/// <summary>
|
||||
/// CoreCLR DomainLocalModule::NormalDynamicEntry::OffsetOfDataBlob for X86
|
||||
/// </summary>
|
||||
private const int DomainLocalModuleNormalDynamicEntryOffsetOfDataBlobX86 = 4;
|
||||
|
||||
/// <summary>
|
||||
/// CoreCLR DomainLocalModule::NormalDynamicEntry::OffsetOfDataBlob for Amd64
|
||||
/// </summary>
|
||||
private const int DomainLocalModuleNormalDynamicEntryOffsetOfDataBlobAmd64 = 8;
|
||||
|
||||
/// <summary>
|
||||
/// CoreCLR DomainLocalModule::NormalDynamicEntry::OffsetOfDataBlob for Arm64
|
||||
/// </summary>
|
||||
private const int DomainLocalModuleNormalDynamicEntryOffsetOfDataBlobArm64 = 8;
|
||||
|
||||
/// <summary>
|
||||
/// CoreCLR DomainLocalModule::NormalDynamicEntry::OffsetOfDataBlob for Arm
|
||||
/// </summary>
|
||||
private const int DomainLocalModuleNormalDynamicEntryOffsetOfDataBlobArm = 8;
|
||||
|
||||
/// <summary>
|
||||
/// CoreCLR DomainLocalModule::NormalDynamicEntry::OffsetOfDataBlob for LoongArch64
|
||||
/// </summary>
|
||||
private const int DomainLocalModuleNormalDynamicEntryOffsetOfDataBlobLoongArch64 = 8;
|
||||
|
||||
/// <summary>
|
||||
/// CoreCLR DomainLocalModule::NormalDynamicEntry::OffsetOfDataBlob for RISCV64
|
||||
/// </summary>
|
||||
private const int DomainLocalModuleNormalDynamicEntryOffsetOfDataBlobRISCV64 = 8;
|
||||
|
||||
protected override bool CompareKeyToValue(EcmaModule key, ModuleFieldLayout value)
|
||||
{
|
||||
return key == value.Module;
|
||||
|
@ -138,107 +79,7 @@ namespace ILCompiler
|
|||
|
||||
protected override ModuleFieldLayout CreateValueFromKey(EcmaModule module)
|
||||
{
|
||||
int typeCountInModule = module.MetadataReader.GetTableRowCount(TableIndex.TypeDef);
|
||||
int pointerSize = module.Context.Target.PointerSize;
|
||||
|
||||
// 0 corresponds to "normal" statics, 1 to thread-local statics
|
||||
LayoutInt[] gcStatics = new LayoutInt[StaticIndex.Count]
|
||||
{
|
||||
LayoutInt.Zero,
|
||||
LayoutInt.Zero
|
||||
};
|
||||
|
||||
LayoutInt[] nonGcStatics = new LayoutInt[StaticIndex.Count]
|
||||
{
|
||||
new LayoutInt(DomainLocalModuleDataBlobOffsetAsIntPtrCount * pointerSize + typeCountInModule),
|
||||
new LayoutInt(ThreadLocalModuleDataBlobOffsetAsIntPtrCount * pointerSize + typeCountInModule),
|
||||
};
|
||||
|
||||
Dictionary<TypeDefinitionHandle, OffsetsForType> typeOffsets = new Dictionary<TypeDefinitionHandle, OffsetsForType>();
|
||||
|
||||
foreach (TypeDefinitionHandle typeDefHandle in module.MetadataReader.TypeDefinitions)
|
||||
{
|
||||
TypeDefinition typeDef = module.MetadataReader.GetTypeDefinition(typeDefHandle);
|
||||
if (typeDef.GetGenericParameters().Count != 0)
|
||||
{
|
||||
// Generic types are exempt from the static field layout algorithm, see
|
||||
// <a href="https://github.com/dotnet/runtime/blob/17154bd7b8f21d6d8d6fca71b89d7dcb705ec32b/src/coreclr/vm/ceeload.cpp#L931">this check</a>.
|
||||
continue;
|
||||
}
|
||||
|
||||
// 0 corresponds to "normal" statics, 1 to thread-local statics
|
||||
int[] nonGcAlignment = new int[StaticIndex.Count] { 1, 1, };
|
||||
int[] nonGcBytes = new int[StaticIndex.Count] { 0, 0, };
|
||||
int[] gcBytes = new int[StaticIndex.Count] { 0, 0, };
|
||||
|
||||
foreach (FieldDefinitionHandle fieldDefHandle in typeDef.GetFields())
|
||||
{
|
||||
FieldDefinition fieldDef = module.MetadataReader.GetFieldDefinition(fieldDefHandle);
|
||||
if ((fieldDef.Attributes & (FieldAttributes.Static | FieldAttributes.Literal)) == FieldAttributes.Static)
|
||||
{
|
||||
// Static RVA fields are included when approximating offsets and sizes for the module field layout, see
|
||||
// <a href="https://github.com/dotnet/runtime/blob/17154bd7b8f21d6d8d6fca71b89d7dcb705ec32b/src/coreclr/vm/ceeload.cpp#L939">this loop</a>.
|
||||
|
||||
int index = (IsFieldThreadStatic(in fieldDef, module.MetadataReader) ? StaticIndex.ThreadLocal : StaticIndex.Regular);
|
||||
int alignment;
|
||||
int size;
|
||||
bool isGcPointerField;
|
||||
bool isGcBoxedField;
|
||||
|
||||
CorElementType corElementType;
|
||||
EntityHandle valueTypeHandle;
|
||||
|
||||
GetFieldElementTypeAndValueTypeHandle(in fieldDef, module.MetadataReader, out corElementType, out valueTypeHandle);
|
||||
FieldDesc fieldDesc = module.GetField(fieldDefHandle);
|
||||
|
||||
GetElementTypeInfo(module, fieldDesc, valueTypeHandle, corElementType, pointerSize, moduleLayout: true,
|
||||
out alignment, out size, out isGcPointerField, out isGcBoxedField);
|
||||
|
||||
if (size != 0)
|
||||
{
|
||||
nonGcBytes[index] += size;
|
||||
nonGcAlignment[index] = Math.Max(nonGcAlignment[index], alignment);
|
||||
}
|
||||
if (isGcPointerField || isGcBoxedField)
|
||||
{
|
||||
gcBytes[index] += pointerSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nonGcBytes[StaticIndex.Regular] != 0 ||
|
||||
nonGcBytes[StaticIndex.ThreadLocal] != 0 ||
|
||||
gcBytes[StaticIndex.Regular] != 0 ||
|
||||
gcBytes[StaticIndex.ThreadLocal] != 0)
|
||||
{
|
||||
OffsetsForType offsetsForType = new OffsetsForType(LayoutInt.Indeterminate, LayoutInt.Indeterminate, LayoutInt.Indeterminate, LayoutInt.Indeterminate);
|
||||
for (int staticIndex = 0; staticIndex < StaticIndex.Count; staticIndex++)
|
||||
{
|
||||
if (nonGcBytes[staticIndex] != 0)
|
||||
{
|
||||
offsetsForType.NonGcOffsets[staticIndex] = LayoutInt.AlignUp(nonGcStatics[staticIndex], new LayoutInt(nonGcAlignment[staticIndex]), module.Context.Target);
|
||||
nonGcStatics[staticIndex] = offsetsForType.NonGcOffsets[staticIndex] + new LayoutInt(nonGcBytes[staticIndex]);
|
||||
}
|
||||
if (gcBytes[staticIndex] != 0)
|
||||
{
|
||||
offsetsForType.GcOffsets[staticIndex] = gcStatics[staticIndex];
|
||||
gcStatics[staticIndex] += new LayoutInt(gcBytes[staticIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
typeOffsets.Add(typeDefHandle, offsetsForType);
|
||||
}
|
||||
}
|
||||
|
||||
LayoutInt blockAlignment = new LayoutInt(TargetDetails.MaximumPrimitiveSize);
|
||||
|
||||
return new ModuleFieldLayout(
|
||||
module,
|
||||
gcStatics: new StaticsBlock() { Size = gcStatics[StaticIndex.Regular], LargestAlignment = blockAlignment },
|
||||
nonGcStatics: new StaticsBlock() { Size = nonGcStatics[StaticIndex.Regular], LargestAlignment = blockAlignment },
|
||||
threadGcStatics: new StaticsBlock() { Size = gcStatics[StaticIndex.ThreadLocal], LargestAlignment = blockAlignment },
|
||||
threadNonGcStatics: new StaticsBlock() { Size = nonGcStatics[StaticIndex.ThreadLocal], LargestAlignment = blockAlignment },
|
||||
typeOffsets: typeOffsets);
|
||||
return new ModuleFieldLayout(module);
|
||||
}
|
||||
|
||||
private void GetElementTypeInfoGeneric(
|
||||
|
@ -405,42 +246,11 @@ namespace ILCompiler
|
|||
FieldAndOffset[] fieldsForType;
|
||||
if (!moduleFieldLayout.TryGetDynamicLayout(defType, out fieldsForType))
|
||||
{
|
||||
int nonGcOffset;
|
||||
switch (moduleFieldLayout.Module.Context.Target.Architecture)
|
||||
{
|
||||
case TargetArchitecture.X86:
|
||||
nonGcOffset = DomainLocalModuleNormalDynamicEntryOffsetOfDataBlobX86;
|
||||
break;
|
||||
|
||||
case TargetArchitecture.X64:
|
||||
nonGcOffset = DomainLocalModuleNormalDynamicEntryOffsetOfDataBlobAmd64;
|
||||
break;
|
||||
|
||||
case TargetArchitecture.ARM64:
|
||||
nonGcOffset = DomainLocalModuleNormalDynamicEntryOffsetOfDataBlobArm64;
|
||||
break;
|
||||
|
||||
case TargetArchitecture.ARM:
|
||||
nonGcOffset = DomainLocalModuleNormalDynamicEntryOffsetOfDataBlobArm;
|
||||
break;
|
||||
|
||||
case TargetArchitecture.LoongArch64:
|
||||
nonGcOffset = DomainLocalModuleNormalDynamicEntryOffsetOfDataBlobLoongArch64;
|
||||
break;
|
||||
|
||||
case TargetArchitecture.RiscV64:
|
||||
nonGcOffset = DomainLocalModuleNormalDynamicEntryOffsetOfDataBlobRISCV64;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
OffsetsForType offsetsForType = new OffsetsForType(
|
||||
nonGcOffset: new LayoutInt(nonGcOffset),
|
||||
tlsNonGcOffset: new LayoutInt(nonGcOffset),
|
||||
nonGcOffset: LayoutInt.Zero,
|
||||
tlsNonGcOffset: new LayoutInt(2 * defType.Context.Target.PointerSize),
|
||||
gcOffset: LayoutInt.Zero,
|
||||
tlsGcOffset: LayoutInt.Zero);
|
||||
tlsGcOffset: new LayoutInt(2 * defType.Context.Target.PointerSize));
|
||||
|
||||
fieldsForType = moduleFieldLayout.GetOrAddDynamicLayout(
|
||||
defType,
|
||||
|
@ -773,44 +583,24 @@ namespace ILCompiler
|
|||
{
|
||||
public EcmaModule Module { get; }
|
||||
|
||||
public StaticsBlock GcStatics { get; }
|
||||
|
||||
public StaticsBlock NonGcStatics { get; }
|
||||
|
||||
public StaticsBlock ThreadGcStatics { get; }
|
||||
|
||||
public StaticsBlock ThreadNonGcStatics { get; }
|
||||
|
||||
public IReadOnlyDictionary<TypeDefinitionHandle, OffsetsForType> TypeOffsets { get; }
|
||||
|
||||
private ConcurrentDictionary<DefType, FieldAndOffset[]> _genericTypeToFieldMap;
|
||||
private ConcurrentDictionary<DefType, FieldAndOffset[]> _typeToFieldMap;
|
||||
|
||||
public ModuleFieldLayout(
|
||||
EcmaModule module,
|
||||
StaticsBlock gcStatics,
|
||||
StaticsBlock nonGcStatics,
|
||||
StaticsBlock threadGcStatics,
|
||||
StaticsBlock threadNonGcStatics,
|
||||
IReadOnlyDictionary<TypeDefinitionHandle, OffsetsForType> typeOffsets)
|
||||
EcmaModule module)
|
||||
{
|
||||
Module = module;
|
||||
GcStatics = gcStatics;
|
||||
NonGcStatics = nonGcStatics;
|
||||
ThreadGcStatics = threadGcStatics;
|
||||
ThreadNonGcStatics = threadNonGcStatics;
|
||||
TypeOffsets = typeOffsets;
|
||||
|
||||
_genericTypeToFieldMap = new ConcurrentDictionary<DefType, FieldAndOffset[]>();
|
||||
_typeToFieldMap = new ConcurrentDictionary<DefType, FieldAndOffset[]>();
|
||||
}
|
||||
|
||||
public bool TryGetDynamicLayout(DefType instantiatedType, out FieldAndOffset[] fieldMap)
|
||||
{
|
||||
return _genericTypeToFieldMap.TryGetValue(instantiatedType, out fieldMap);
|
||||
return _typeToFieldMap.TryGetValue(instantiatedType, out fieldMap);
|
||||
}
|
||||
|
||||
public FieldAndOffset[] GetOrAddDynamicLayout(DefType instantiatedType, FieldAndOffset[] fieldMap)
|
||||
{
|
||||
return _genericTypeToFieldMap.GetOrAdd(instantiatedType, fieldMap);
|
||||
return _typeToFieldMap.GetOrAdd(instantiatedType, fieldMap);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1012,19 +1012,19 @@ namespace Internal.JitInterface
|
|||
break;
|
||||
|
||||
|
||||
case CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_GCSTATIC_BASE:
|
||||
case CorInfoHelpFunc.CORINFO_HELP_GET_GCSTATIC_BASE:
|
||||
id = ReadyToRunHelper.GenericGcStaticBase;
|
||||
break;
|
||||
|
||||
case CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE:
|
||||
case CorInfoHelpFunc.CORINFO_HELP_GET_NONGCSTATIC_BASE:
|
||||
id = ReadyToRunHelper.GenericNonGcStaticBase;
|
||||
break;
|
||||
|
||||
case CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE:
|
||||
case CorInfoHelpFunc.CORINFO_HELP_GET_GCTHREADSTATIC_BASE:
|
||||
id = ReadyToRunHelper.GenericGcTlsBase;
|
||||
break;
|
||||
|
||||
case CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE:
|
||||
case CorInfoHelpFunc.CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE:
|
||||
id = ReadyToRunHelper.GenericNonGcTlsBase;
|
||||
break;
|
||||
|
||||
|
@ -1714,14 +1714,14 @@ namespace Internal.JitInterface
|
|||
if (field.IsThreadStatic)
|
||||
{
|
||||
pResult->helper = (field.HasGCStaticBase ?
|
||||
CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE :
|
||||
CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE);
|
||||
CorInfoHelpFunc.CORINFO_HELP_GET_GCTHREADSTATIC_BASE :
|
||||
CorInfoHelpFunc.CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pResult->helper = (field.HasGCStaticBase ?
|
||||
CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_GCSTATIC_BASE :
|
||||
CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE);
|
||||
CorInfoHelpFunc.CORINFO_HELP_GET_GCSTATIC_BASE :
|
||||
CorInfoHelpFunc.CORINFO_HELP_GET_NONGCSTATIC_BASE);
|
||||
}
|
||||
|
||||
if (_compilation.SymbolNodeFactory.VerifyTypeAndFieldLayout && (fieldOffset <= FieldFixupSignature.MaxCheckableOffset))
|
||||
|
|
|
@ -57,8 +57,9 @@ struct JitInterfaceCallbacks
|
|||
const char* (* getAssemblyName)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_ASSEMBLY_HANDLE assem);
|
||||
void* (* LongLifetimeMalloc)(void * thisHandle, CorInfoExceptionClass** ppException, size_t sz);
|
||||
void (* LongLifetimeFree)(void * thisHandle, CorInfoExceptionClass** ppException, void* obj);
|
||||
size_t (* getClassModuleIdForStatics)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls, CORINFO_MODULE_HANDLE* pModule, void** ppIndirection);
|
||||
bool (* getIsClassInitedFlagAddress)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls, CORINFO_CONST_LOOKUP* addr, int* offset);
|
||||
size_t (* getClassThreadStaticDynamicInfo)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE clr);
|
||||
size_t (* getClassStaticDynamicInfo)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE clr);
|
||||
bool (* getStaticBaseAddress)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls, bool isGc, CORINFO_CONST_LOOKUP* addr);
|
||||
unsigned (* getClassSize)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls);
|
||||
unsigned (* getHeapClassSize)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls);
|
||||
|
@ -107,7 +108,7 @@ struct JitInterfaceCallbacks
|
|||
unsigned (* getFieldOffset)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field);
|
||||
void (* getFieldInfo)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_ACCESS_FLAGS flags, CORINFO_FIELD_INFO* pResult);
|
||||
uint32_t (* getThreadLocalFieldInfo)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, bool isGCtype);
|
||||
void (* getThreadLocalStaticBlocksInfo)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType);
|
||||
void (* getThreadLocalStaticBlocksInfo)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo);
|
||||
void (* getThreadLocalStaticInfo_NativeAOT)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_THREAD_STATIC_INFO_NATIVEAOT* pInfo);
|
||||
bool (* isFieldStatic)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE fldHnd);
|
||||
int (* getArrayOrStringLength)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_OBJECT_HANDLE objHnd);
|
||||
|
@ -155,7 +156,6 @@ struct JitInterfaceCallbacks
|
|||
CORINFO_JUST_MY_CODE_HANDLE (* getJustMyCodeHandle)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE method, CORINFO_JUST_MY_CODE_HANDLE** ppIndirection);
|
||||
void (* GetProfilingHandle)(void * thisHandle, CorInfoExceptionClass** ppException, bool* pbHookFunction, void** pProfilerHandle, bool* pbIndirectedHandles);
|
||||
void (* getCallInfo)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_CALLINFO_FLAGS flags, CORINFO_CALL_INFO* pResult);
|
||||
unsigned (* getClassDomainID)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls, void** ppIndirection);
|
||||
bool (* getStaticFieldContent)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, uint8_t* buffer, int bufferSize, int valueOffset, bool ignoreMovableObjects);
|
||||
bool (* getObjectContent)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_OBJECT_HANDLE obj, uint8_t* buffer, int bufferSize, int valueOffset);
|
||||
CORINFO_CLASS_HANDLE (* getStaticFieldCurrentClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, bool* pIsSpeculative);
|
||||
|
@ -649,17 +649,6 @@ public:
|
|||
if (pException != nullptr) throw pException;
|
||||
}
|
||||
|
||||
virtual size_t getClassModuleIdForStatics(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
CORINFO_MODULE_HANDLE* pModule,
|
||||
void** ppIndirection)
|
||||
{
|
||||
CorInfoExceptionClass* pException = nullptr;
|
||||
size_t temp = _callbacks->getClassModuleIdForStatics(_thisHandle, &pException, cls, pModule, ppIndirection);
|
||||
if (pException != nullptr) throw pException;
|
||||
return temp;
|
||||
}
|
||||
|
||||
virtual bool getIsClassInitedFlagAddress(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
CORINFO_CONST_LOOKUP* addr,
|
||||
|
@ -671,6 +660,24 @@ public:
|
|||
return temp;
|
||||
}
|
||||
|
||||
virtual size_t getClassThreadStaticDynamicInfo(
|
||||
CORINFO_CLASS_HANDLE clr)
|
||||
{
|
||||
CorInfoExceptionClass* pException = nullptr;
|
||||
size_t temp = _callbacks->getClassThreadStaticDynamicInfo(_thisHandle, &pException, clr);
|
||||
if (pException != nullptr) throw pException;
|
||||
return temp;
|
||||
}
|
||||
|
||||
virtual size_t getClassStaticDynamicInfo(
|
||||
CORINFO_CLASS_HANDLE clr)
|
||||
{
|
||||
CorInfoExceptionClass* pException = nullptr;
|
||||
size_t temp = _callbacks->getClassStaticDynamicInfo(_thisHandle, &pException, clr);
|
||||
if (pException != nullptr) throw pException;
|
||||
return temp;
|
||||
}
|
||||
|
||||
virtual bool getStaticBaseAddress(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
bool isGc,
|
||||
|
@ -1142,11 +1149,10 @@ public:
|
|||
}
|
||||
|
||||
virtual void getThreadLocalStaticBlocksInfo(
|
||||
CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo,
|
||||
bool isGCType)
|
||||
CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo)
|
||||
{
|
||||
CorInfoExceptionClass* pException = nullptr;
|
||||
_callbacks->getThreadLocalStaticBlocksInfo(_thisHandle, &pException, pInfo, isGCType);
|
||||
_callbacks->getThreadLocalStaticBlocksInfo(_thisHandle, &pException, pInfo);
|
||||
if (pException != nullptr) throw pException;
|
||||
}
|
||||
|
||||
|
@ -1596,16 +1602,6 @@ public:
|
|||
if (pException != nullptr) throw pException;
|
||||
}
|
||||
|
||||
virtual unsigned getClassDomainID(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
void** ppIndirection)
|
||||
{
|
||||
CorInfoExceptionClass* pException = nullptr;
|
||||
unsigned temp = _callbacks->getClassDomainID(_thisHandle, &pException, cls, ppIndirection);
|
||||
if (pException != nullptr) throw pException;
|
||||
return temp;
|
||||
}
|
||||
|
||||
virtual bool getStaticFieldContent(
|
||||
CORINFO_FIELD_HANDLE field,
|
||||
uint8_t* buffer,
|
||||
|
|
|
@ -541,7 +541,7 @@ struct Agnostic_GetThreadLocalStaticBlocksInfo
|
|||
DWORD offsetOfThreadLocalStoragePointer;
|
||||
DWORD offsetOfMaxThreadStaticBlocks;
|
||||
DWORD offsetOfThreadStaticBlocks;
|
||||
DWORD offsetOfGCDataPointer;
|
||||
DWORD offsetOfBaseOfThreadLocalData;
|
||||
};
|
||||
|
||||
struct Agnostic_GetThreadStaticInfo_NativeAOT
|
||||
|
|
|
@ -60,7 +60,8 @@ LWM(GetCastingHelper, Agnostic_GetCastingHelper, DWORD)
|
|||
LWM(GetChildType, DWORDLONG, DLD)
|
||||
LWM(GetClassAlignmentRequirement, DLD, DWORD)
|
||||
LWM(GetClassAttribs, DWORDLONG, DWORD)
|
||||
LWM(GetClassDomainID, DWORDLONG, DLD)
|
||||
LWM(GetClassStaticDynamicInfo, DWORDLONG, DLD)
|
||||
LWM(GetClassThreadStaticDynamicInfo, DWORDLONG, DLD)
|
||||
LWM(GetClassGClayout, DWORDLONG, Agnostic_GetClassGClayout)
|
||||
LWM(GetClassModuleIdForStatics, DWORDLONG, Agnostic_GetClassModuleIdForStatics)
|
||||
LWM(GetIsClassInitedFlagAddress, DWORDLONG, Agnostic_GetIsClassInitedFlagAddress)
|
||||
|
|
|
@ -3620,7 +3620,7 @@ uint32_t MethodContext::repGetThreadLocalFieldInfo(CORINFO_FIELD_HANDLE field, b
|
|||
return value;
|
||||
}
|
||||
|
||||
void MethodContext::recGetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType)
|
||||
void MethodContext::recGetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo)
|
||||
{
|
||||
if (GetThreadLocalStaticBlocksInfo == nullptr)
|
||||
GetThreadLocalStaticBlocksInfo = new LightWeightMap<DWORD, Agnostic_GetThreadLocalStaticBlocksInfo>();
|
||||
|
@ -3635,10 +3635,10 @@ void MethodContext::recGetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOC
|
|||
value.offsetOfThreadLocalStoragePointer = pInfo->offsetOfThreadLocalStoragePointer;
|
||||
value.offsetOfMaxThreadStaticBlocks = pInfo->offsetOfMaxThreadStaticBlocks;
|
||||
value.offsetOfThreadStaticBlocks = pInfo->offsetOfThreadStaticBlocks;
|
||||
value.offsetOfGCDataPointer = pInfo->offsetOfGCDataPointer;
|
||||
value.offsetOfBaseOfThreadLocalData = pInfo->offsetOfBaseOfThreadLocalData;
|
||||
|
||||
// This data is same for entire process, so just add it against key '0'.
|
||||
DWORD key = isGCType ? 0 : 1;
|
||||
DWORD key = 0;
|
||||
GetThreadLocalStaticBlocksInfo->Add(key, value);
|
||||
DEBUG_REC(dmpGetThreadLocalStaticBlocksInfo(key, value));
|
||||
}
|
||||
|
@ -3648,16 +3648,18 @@ void MethodContext::dmpGetThreadLocalStaticBlocksInfo(DWORD key, const Agnostic_
|
|||
printf("GetThreadLocalStaticBlocksInfo key %u, tlsIndex-%s, "
|
||||
", tlsGetAddrFtnPtr-%016" PRIX64 ", tlsIndexObject - %016" PRIX64
|
||||
", threadVarsSection - %016" PRIX64
|
||||
", offsetOfThreadLocalStoragePointer-%u, offsetOfMaxThreadStaticBlocks-%u"
|
||||
", offsetOfThreadStaticBlocks-%u, offsetOfGCDataPointer-%u",
|
||||
", offsetOfThreadLocalStoragePointer-%u"
|
||||
", offsetOfMaxThreadStaticBlocks-%u"
|
||||
", offsetOfThreadStaticBlocks-%u"
|
||||
", offsetOfBaseOfThreadLocalData-%u",
|
||||
key, SpmiDumpHelper::DumpAgnostic_CORINFO_CONST_LOOKUP(value.tlsIndex).c_str(), value.tlsGetAddrFtnPtr,
|
||||
value.tlsIndexObject, value.threadVarsSection, value.offsetOfThreadLocalStoragePointer,
|
||||
value.offsetOfMaxThreadStaticBlocks, value.offsetOfThreadStaticBlocks, value.offsetOfGCDataPointer);
|
||||
value.offsetOfMaxThreadStaticBlocks, value.offsetOfThreadStaticBlocks, value.offsetOfBaseOfThreadLocalData);
|
||||
}
|
||||
|
||||
void MethodContext::repGetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType)
|
||||
void MethodContext::repGetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo)
|
||||
{
|
||||
int key = isGCType ? 0 : 1;
|
||||
int key = 0;
|
||||
Agnostic_GetThreadLocalStaticBlocksInfo value = LookupByKeyOrMiss(GetThreadLocalStaticBlocksInfo, key, ": key %u", key);
|
||||
|
||||
DEBUG_REP(dmpGetThreadLocalStaticBlocksInfo(key, value));
|
||||
|
@ -3669,7 +3671,7 @@ void MethodContext::repGetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOC
|
|||
pInfo->offsetOfThreadLocalStoragePointer = value.offsetOfThreadLocalStoragePointer;
|
||||
pInfo->offsetOfMaxThreadStaticBlocks = value.offsetOfMaxThreadStaticBlocks;
|
||||
pInfo->offsetOfThreadStaticBlocks = value.offsetOfThreadStaticBlocks;
|
||||
pInfo->offsetOfGCDataPointer = value.offsetOfGCDataPointer;
|
||||
pInfo->offsetOfBaseOfThreadLocalData = value.offsetOfBaseOfThreadLocalData;
|
||||
}
|
||||
|
||||
void MethodContext::recGetThreadLocalStaticInfo_NativeAOT(CORINFO_THREAD_STATIC_INFO_NATIVEAOT* pInfo)
|
||||
|
@ -4647,37 +4649,60 @@ int32_t* MethodContext::repGetAddrOfCaptureThreadGlobal(void** ppIndirection)
|
|||
return (int32_t*)value.B;
|
||||
}
|
||||
|
||||
void MethodContext::recGetClassDomainID(CORINFO_CLASS_HANDLE cls, void** ppIndirection, unsigned result)
|
||||
void MethodContext::recGetClassStaticDynamicInfo(CORINFO_CLASS_HANDLE cls, size_t result)
|
||||
{
|
||||
if (GetClassDomainID == nullptr)
|
||||
GetClassDomainID = new LightWeightMap<DWORDLONG, DLD>();
|
||||
if (GetClassStaticDynamicInfo == nullptr)
|
||||
GetClassStaticDynamicInfo = new LightWeightMap<DWORDLONG, DLD>();
|
||||
|
||||
DLD value;
|
||||
|
||||
if (ppIndirection != nullptr)
|
||||
value.A = CastPointer(*ppIndirection);
|
||||
else
|
||||
value.A = 0;
|
||||
value.B = (DWORD)result;
|
||||
value.A = result;
|
||||
value.B = 0;
|
||||
|
||||
DWORDLONG key = CastHandle(cls);
|
||||
GetClassDomainID->Add(key, value);
|
||||
DEBUG_REC(dmpGetClassDomainID(key, value));
|
||||
GetClassStaticDynamicInfo->Add(key, value);
|
||||
DEBUG_REC(dmpGetClassStaticDynamicInfo(key, value));
|
||||
}
|
||||
void MethodContext::dmpGetClassDomainID(DWORDLONG key, DLD value)
|
||||
void MethodContext::dmpGetClassStaticDynamicInfo(DWORDLONG key, DLD value)
|
||||
{
|
||||
printf("GetClassDomainID key cls-%016" PRIX64 ", value pp-%016" PRIX64 " res-%u", key, value.A, value.B);
|
||||
printf("GetClassStaticDynamicInfo key cls-%016" PRIX64 ", value pp-%016" PRIX64 " res-%u", key, value.A, value.B);
|
||||
}
|
||||
unsigned MethodContext::repGetClassDomainID(CORINFO_CLASS_HANDLE cls, void** ppIndirection)
|
||||
size_t MethodContext::repGetClassStaticDynamicInfo(CORINFO_CLASS_HANDLE cls)
|
||||
{
|
||||
DWORDLONG key = CastHandle(cls);
|
||||
DLD value = LookupByKeyOrMiss(GetClassDomainID, key, ": key %016" PRIX64 "", key);
|
||||
DLD value = LookupByKeyOrMiss(GetClassStaticDynamicInfo, key, ": key %016" PRIX64 "", key);
|
||||
|
||||
DEBUG_REP(dmpGetClassDomainID(key, value));
|
||||
DEBUG_REP(dmpGetClassStaticDynamicInfo(key, value));
|
||||
|
||||
if (ppIndirection != nullptr)
|
||||
*ppIndirection = (void*)value.A;
|
||||
return (unsigned)value.B;
|
||||
return (size_t)value.A;
|
||||
}
|
||||
|
||||
void MethodContext::recGetClassThreadStaticDynamicInfo(CORINFO_CLASS_HANDLE cls, size_t result)
|
||||
{
|
||||
if (GetClassThreadStaticDynamicInfo == nullptr)
|
||||
GetClassThreadStaticDynamicInfo = new LightWeightMap<DWORDLONG, DLD>();
|
||||
|
||||
DLD value;
|
||||
|
||||
value.A = result;
|
||||
value.B = 0;
|
||||
|
||||
DWORDLONG key = CastHandle(cls);
|
||||
GetClassThreadStaticDynamicInfo->Add(key, value);
|
||||
DEBUG_REC(dmpGetClassThreadStaticDynamicInfo(key, value));
|
||||
}
|
||||
void MethodContext::dmpGetClassThreadStaticDynamicInfo(DWORDLONG key, DLD value)
|
||||
{
|
||||
printf("GetClassThreadStaticDynamicInfo key cls-%016" PRIX64 ", value pp-%016" PRIX64 " res-%u", key, value.A, value.B);
|
||||
}
|
||||
size_t MethodContext::repGetClassThreadStaticDynamicInfo(CORINFO_CLASS_HANDLE cls)
|
||||
{
|
||||
DWORDLONG key = CastHandle(cls);
|
||||
DLD value = LookupByKeyOrMiss(GetClassThreadStaticDynamicInfo, key, ": key %016" PRIX64 "", key);
|
||||
|
||||
DEBUG_REP(dmpGetClassThreadStaticDynamicInfo(key, value));
|
||||
|
||||
return (size_t)value.A;
|
||||
}
|
||||
|
||||
void MethodContext::recGetLocationOfThisType(CORINFO_METHOD_HANDLE context, CORINFO_LOOKUP_KIND* result)
|
||||
|
|
|
@ -484,9 +484,9 @@ public:
|
|||
void dmpGetThreadLocalFieldInfo(DLD key, DWORD value);
|
||||
uint32_t repGetThreadLocalFieldInfo(CORINFO_FIELD_HANDLE field, bool isGCType);
|
||||
|
||||
void recGetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType);
|
||||
void recGetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo);
|
||||
void dmpGetThreadLocalStaticBlocksInfo(DWORD key, const Agnostic_GetThreadLocalStaticBlocksInfo& value);
|
||||
void repGetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType);
|
||||
void repGetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo);
|
||||
|
||||
void recGetThreadLocalStaticInfo_NativeAOT(CORINFO_THREAD_STATIC_INFO_NATIVEAOT* pInfo);
|
||||
void dmpGetThreadLocalStaticInfo_NativeAOT(DWORDLONG key, const Agnostic_GetThreadStaticInfo_NativeAOT& value);
|
||||
|
@ -592,9 +592,13 @@ public:
|
|||
void dmpGetAddrOfCaptureThreadGlobal(DWORD key, DLDL value);
|
||||
int32_t* repGetAddrOfCaptureThreadGlobal(void** ppIndirection);
|
||||
|
||||
void recGetClassDomainID(CORINFO_CLASS_HANDLE cls, void** ppIndirection, unsigned result);
|
||||
void dmpGetClassDomainID(DWORDLONG key, DLD value);
|
||||
unsigned repGetClassDomainID(CORINFO_CLASS_HANDLE cls, void** ppIndirection);
|
||||
void recGetClassStaticDynamicInfo(CORINFO_CLASS_HANDLE cls, size_t result);
|
||||
void dmpGetClassStaticDynamicInfo(DWORDLONG key, DLD value);
|
||||
size_t repGetClassStaticDynamicInfo(CORINFO_CLASS_HANDLE cls);
|
||||
|
||||
void recGetClassThreadStaticDynamicInfo(CORINFO_CLASS_HANDLE cls, size_t result);
|
||||
void dmpGetClassThreadStaticDynamicInfo(DWORDLONG key, DLD value);
|
||||
size_t repGetClassThreadStaticDynamicInfo(CORINFO_CLASS_HANDLE cls);
|
||||
|
||||
void recGetLocationOfThisType(CORINFO_METHOD_HANDLE context, CORINFO_LOOKUP_KIND* result);
|
||||
void dmpGetLocationOfThisType(DWORDLONG key, const Agnostic_CORINFO_LOOKUP_KIND& value);
|
||||
|
@ -998,7 +1002,7 @@ enum mcPackets
|
|||
Packet_GetChildType = 39,
|
||||
Packet_GetClassAlignmentRequirement = 40,
|
||||
Packet_GetClassAttribs = 41,
|
||||
Packet_GetClassDomainID = 42,
|
||||
//Packet_GetClassDomainID = 42,
|
||||
Packet_GetClassGClayout = 43,
|
||||
Packet_GetClassModuleIdForStatics = 44,
|
||||
Packet_GetClassName = 45,
|
||||
|
@ -1170,6 +1174,8 @@ enum mcPackets
|
|||
Packet_IsExactType = 215,
|
||||
Packet_GetSwiftLowering = 216,
|
||||
Packet_IsNullableType = 217,
|
||||
Packet_GetClassStaticDynamicInfo = 218,
|
||||
Packet_GetClassThreadStaticDynamicInfo = 219,
|
||||
};
|
||||
|
||||
void SetDebugDumpVariables();
|
||||
|
|
|
@ -530,15 +530,6 @@ void interceptor_ICJI::LongLifetimeFree(void* obj)
|
|||
original_ICorJitInfo->LongLifetimeFree(obj);
|
||||
}
|
||||
|
||||
size_t interceptor_ICJI::getClassModuleIdForStatics(CORINFO_CLASS_HANDLE cls,
|
||||
CORINFO_MODULE_HANDLE* pModule,
|
||||
void** ppIndirection)
|
||||
{
|
||||
mc->cr->AddCall("getClassModuleIdForStatics");
|
||||
size_t temp = original_ICorJitInfo->getClassModuleIdForStatics(cls, pModule, ppIndirection);
|
||||
mc->recGetClassModuleIdForStatics(cls, pModule, ppIndirection, temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
bool interceptor_ICJI::getIsClassInitedFlagAddress(CORINFO_CLASS_HANDLE cls,
|
||||
CORINFO_CONST_LOOKUP* addr,
|
||||
|
@ -1082,11 +1073,11 @@ uint32_t interceptor_ICJI::getThreadLocalFieldInfo(CORINFO_FIELD_HANDLE field, b
|
|||
return result;
|
||||
}
|
||||
|
||||
void interceptor_ICJI::getThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType)
|
||||
void interceptor_ICJI::getThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo)
|
||||
{
|
||||
mc->cr->AddCall("getThreadLocalStaticBlocksInfo");
|
||||
original_ICorJitInfo->getThreadLocalStaticBlocksInfo(pInfo, isGCType);
|
||||
mc->recGetThreadLocalStaticBlocksInfo(pInfo, isGCType);
|
||||
original_ICorJitInfo->getThreadLocalStaticBlocksInfo(pInfo);
|
||||
mc->recGetThreadLocalStaticBlocksInfo(pInfo);
|
||||
}
|
||||
|
||||
void interceptor_ICJI::getThreadLocalStaticInfo_NativeAOT(CORINFO_THREAD_STATIC_INFO_NATIVEAOT* pInfo)
|
||||
|
@ -1640,12 +1631,19 @@ void interceptor_ICJI::getCallInfo(
|
|||
});
|
||||
}
|
||||
|
||||
// returns the class's domain ID for accessing shared statics
|
||||
unsigned interceptor_ICJI::getClassDomainID(CORINFO_CLASS_HANDLE cls, void** ppIndirection)
|
||||
size_t interceptor_ICJI::getClassStaticDynamicInfo(CORINFO_CLASS_HANDLE cls)
|
||||
{
|
||||
mc->cr->AddCall("getClassDomainID");
|
||||
unsigned temp = original_ICorJitInfo->getClassDomainID(cls, ppIndirection);
|
||||
mc->recGetClassDomainID(cls, ppIndirection, temp);
|
||||
mc->cr->AddCall("getClassStaticDynamicInfo");
|
||||
size_t temp = original_ICorJitInfo->getClassStaticDynamicInfo(cls);
|
||||
mc->recGetClassStaticDynamicInfo(cls, temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
size_t interceptor_ICJI::getClassThreadStaticDynamicInfo(CORINFO_CLASS_HANDLE cls)
|
||||
{
|
||||
mc->cr->AddCall("getClassThreadStaticDynamicInfo");
|
||||
size_t temp = original_ICorJitInfo->getClassThreadStaticDynamicInfo(cls);
|
||||
mc->recGetClassThreadStaticDynamicInfo(cls, temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
|
|
@ -383,15 +383,6 @@ void interceptor_ICJI::LongLifetimeFree(
|
|||
original_ICorJitInfo->LongLifetimeFree(obj);
|
||||
}
|
||||
|
||||
size_t interceptor_ICJI::getClassModuleIdForStatics(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
CORINFO_MODULE_HANDLE* pModule,
|
||||
void** ppIndirection)
|
||||
{
|
||||
mcs->AddCall("getClassModuleIdForStatics");
|
||||
return original_ICorJitInfo->getClassModuleIdForStatics(cls, pModule, ppIndirection);
|
||||
}
|
||||
|
||||
bool interceptor_ICJI::getIsClassInitedFlagAddress(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
CORINFO_CONST_LOOKUP* addr,
|
||||
|
@ -401,6 +392,20 @@ bool interceptor_ICJI::getIsClassInitedFlagAddress(
|
|||
return original_ICorJitInfo->getIsClassInitedFlagAddress(cls, addr, offset);
|
||||
}
|
||||
|
||||
size_t interceptor_ICJI::getClassThreadStaticDynamicInfo(
|
||||
CORINFO_CLASS_HANDLE clr)
|
||||
{
|
||||
mcs->AddCall("getClassThreadStaticDynamicInfo");
|
||||
return original_ICorJitInfo->getClassThreadStaticDynamicInfo(clr);
|
||||
}
|
||||
|
||||
size_t interceptor_ICJI::getClassStaticDynamicInfo(
|
||||
CORINFO_CLASS_HANDLE clr)
|
||||
{
|
||||
mcs->AddCall("getClassStaticDynamicInfo");
|
||||
return original_ICorJitInfo->getClassStaticDynamicInfo(clr);
|
||||
}
|
||||
|
||||
bool interceptor_ICJI::getStaticBaseAddress(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
bool isGc,
|
||||
|
@ -779,11 +784,10 @@ uint32_t interceptor_ICJI::getThreadLocalFieldInfo(
|
|||
}
|
||||
|
||||
void interceptor_ICJI::getThreadLocalStaticBlocksInfo(
|
||||
CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo,
|
||||
bool isGCType)
|
||||
CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo)
|
||||
{
|
||||
mcs->AddCall("getThreadLocalStaticBlocksInfo");
|
||||
original_ICorJitInfo->getThreadLocalStaticBlocksInfo(pInfo, isGCType);
|
||||
original_ICorJitInfo->getThreadLocalStaticBlocksInfo(pInfo);
|
||||
}
|
||||
|
||||
void interceptor_ICJI::getThreadLocalStaticInfo_NativeAOT(
|
||||
|
@ -1167,14 +1171,6 @@ void interceptor_ICJI::getCallInfo(
|
|||
original_ICorJitInfo->getCallInfo(pResolvedToken, pConstrainedResolvedToken, callerHandle, flags, pResult);
|
||||
}
|
||||
|
||||
unsigned interceptor_ICJI::getClassDomainID(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
void** ppIndirection)
|
||||
{
|
||||
mcs->AddCall("getClassDomainID");
|
||||
return original_ICorJitInfo->getClassDomainID(cls, ppIndirection);
|
||||
}
|
||||
|
||||
bool interceptor_ICJI::getStaticFieldContent(
|
||||
CORINFO_FIELD_HANDLE field,
|
||||
uint8_t* buffer,
|
||||
|
|
|
@ -337,14 +337,6 @@ void interceptor_ICJI::LongLifetimeFree(
|
|||
original_ICorJitInfo->LongLifetimeFree(obj);
|
||||
}
|
||||
|
||||
size_t interceptor_ICJI::getClassModuleIdForStatics(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
CORINFO_MODULE_HANDLE* pModule,
|
||||
void** ppIndirection)
|
||||
{
|
||||
return original_ICorJitInfo->getClassModuleIdForStatics(cls, pModule, ppIndirection);
|
||||
}
|
||||
|
||||
bool interceptor_ICJI::getIsClassInitedFlagAddress(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
CORINFO_CONST_LOOKUP* addr,
|
||||
|
@ -353,6 +345,18 @@ bool interceptor_ICJI::getIsClassInitedFlagAddress(
|
|||
return original_ICorJitInfo->getIsClassInitedFlagAddress(cls, addr, offset);
|
||||
}
|
||||
|
||||
size_t interceptor_ICJI::getClassThreadStaticDynamicInfo(
|
||||
CORINFO_CLASS_HANDLE clr)
|
||||
{
|
||||
return original_ICorJitInfo->getClassThreadStaticDynamicInfo(clr);
|
||||
}
|
||||
|
||||
size_t interceptor_ICJI::getClassStaticDynamicInfo(
|
||||
CORINFO_CLASS_HANDLE clr)
|
||||
{
|
||||
return original_ICorJitInfo->getClassStaticDynamicInfo(clr);
|
||||
}
|
||||
|
||||
bool interceptor_ICJI::getStaticBaseAddress(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
bool isGc,
|
||||
|
@ -683,10 +687,9 @@ uint32_t interceptor_ICJI::getThreadLocalFieldInfo(
|
|||
}
|
||||
|
||||
void interceptor_ICJI::getThreadLocalStaticBlocksInfo(
|
||||
CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo,
|
||||
bool isGCType)
|
||||
CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo)
|
||||
{
|
||||
original_ICorJitInfo->getThreadLocalStaticBlocksInfo(pInfo, isGCType);
|
||||
original_ICorJitInfo->getThreadLocalStaticBlocksInfo(pInfo);
|
||||
}
|
||||
|
||||
void interceptor_ICJI::getThreadLocalStaticInfo_NativeAOT(
|
||||
|
@ -1023,13 +1026,6 @@ void interceptor_ICJI::getCallInfo(
|
|||
original_ICorJitInfo->getCallInfo(pResolvedToken, pConstrainedResolvedToken, callerHandle, flags, pResult);
|
||||
}
|
||||
|
||||
unsigned interceptor_ICJI::getClassDomainID(
|
||||
CORINFO_CLASS_HANDLE cls,
|
||||
void** ppIndirection)
|
||||
{
|
||||
return original_ICorJitInfo->getClassDomainID(cls, ppIndirection);
|
||||
}
|
||||
|
||||
bool interceptor_ICJI::getStaticFieldContent(
|
||||
CORINFO_FIELD_HANDLE field,
|
||||
uint8_t* buffer,
|
||||
|
|
|
@ -455,12 +455,16 @@ void MyICJI::LongLifetimeFree(void* obj)
|
|||
DebugBreakorAV(33);
|
||||
}
|
||||
|
||||
size_t MyICJI::getClassModuleIdForStatics(CORINFO_CLASS_HANDLE cls,
|
||||
CORINFO_MODULE_HANDLE* pModule,
|
||||
void** ppIndirection)
|
||||
size_t MyICJI::getClassThreadStaticDynamicInfo(CORINFO_CLASS_HANDLE cls)
|
||||
{
|
||||
jitInstance->mc->cr->AddCall("getClassModuleIdForStatics");
|
||||
return jitInstance->mc->repGetClassModuleIdForStatics(cls, pModule, ppIndirection);
|
||||
jitInstance->mc->cr->AddCall("getClassThreadStaticDynamicInfo");
|
||||
return jitInstance->mc->repGetClassThreadStaticDynamicInfo(cls);
|
||||
}
|
||||
|
||||
size_t MyICJI::getClassStaticDynamicInfo(CORINFO_CLASS_HANDLE cls)
|
||||
{
|
||||
jitInstance->mc->cr->AddCall("getClassStaticDynamicInfo");
|
||||
return jitInstance->mc->repGetClassStaticDynamicInfo(cls);
|
||||
}
|
||||
|
||||
bool MyICJI::getIsClassInitedFlagAddress(CORINFO_CLASS_HANDLE cls,
|
||||
|
@ -898,10 +902,10 @@ uint32_t MyICJI::getThreadLocalFieldInfo(CORINFO_FIELD_HANDLE field, bool isGCTy
|
|||
return jitInstance->mc->repGetThreadLocalFieldInfo(field, isGCType);
|
||||
}
|
||||
|
||||
void MyICJI::getThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType)
|
||||
void MyICJI::getThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo)
|
||||
{
|
||||
jitInstance->mc->cr->AddCall("getThreadLocalStaticBlocksInfo");
|
||||
jitInstance->mc->repGetThreadLocalStaticBlocksInfo(pInfo, isGCType);
|
||||
jitInstance->mc->repGetThreadLocalStaticBlocksInfo(pInfo);
|
||||
}
|
||||
|
||||
void MyICJI::getThreadLocalStaticInfo_NativeAOT(CORINFO_THREAD_STATIC_INFO_NATIVEAOT* pInfo)
|
||||
|
@ -1433,13 +1437,6 @@ void MyICJI::getCallInfo(
|
|||
ThrowRecordedException(exceptionCode);
|
||||
}
|
||||
|
||||
// returns the class's domain ID for accessing shared statics
|
||||
unsigned MyICJI::getClassDomainID(CORINFO_CLASS_HANDLE cls, void** ppIndirection)
|
||||
{
|
||||
jitInstance->mc->cr->AddCall("getClassDomainID");
|
||||
return jitInstance->mc->repGetClassDomainID(cls, ppIndirection);
|
||||
}
|
||||
|
||||
bool MyICJI::getStaticFieldContent(CORINFO_FIELD_HANDLE field, uint8_t* buffer, int bufferSize, int valueOffset, bool ignoreMovableObjects)
|
||||
{
|
||||
jitInstance->mc->cr->AddCall("getStaticFieldContent");
|
||||
|
|
|
@ -3,9 +3,6 @@
|
|||
|
||||
; ***********************************************************************
|
||||
; File: JitHelpers_SingleAppDomain.asm
|
||||
;
|
||||
; Notes: JIT Static access helpers when coreclr host specifies single
|
||||
; appdomain flag
|
||||
; ***********************************************************************
|
||||
|
||||
include AsmMacros.inc
|
||||
|
@ -14,45 +11,34 @@ include asmconstants.inc
|
|||
; Min amount of stack space that a nested function should allocate.
|
||||
MIN_SIZE equ 28h
|
||||
|
||||
extern JIT_GetSharedNonGCStaticBase_Helper:proc
|
||||
extern JIT_GetSharedGCStaticBase_Helper:proc
|
||||
extern JIT_GetDynamicNonGCStaticBase_Portable:proc
|
||||
extern JIT_GetDynamicGCStaticBase_Portable:proc
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedNonGCStaticBase_SingleAppDomain, _TEXT
|
||||
LEAF_ENTRY JIT_GetDynamicNonGCStaticBase_SingleAppDomain, _TEXT
|
||||
; If class is not initialized, bail to C++ helper
|
||||
test byte ptr [rcx + OFFSETOF__DomainLocalModule__m_pDataBlob + rdx], 1
|
||||
jz CallHelper
|
||||
mov rax, rcx
|
||||
mov rax, [rcx + OFFSETOF__DynamicStaticsInfo__m_pNonGCStatics]
|
||||
test al, 1
|
||||
jnz CallHelper
|
||||
REPRET
|
||||
|
||||
align 16
|
||||
CallHelper:
|
||||
; Tail call JIT_GetSharedNonGCStaticBase_Helper
|
||||
jmp JIT_GetSharedNonGCStaticBase_Helper
|
||||
LEAF_END JIT_GetSharedNonGCStaticBase_SingleAppDomain, _TEXT
|
||||
; Tail call JIT_GetDynamicNonGCStaticBase_Portable
|
||||
jmp JIT_GetDynamicNonGCStaticBase_Portable
|
||||
LEAF_END JIT_GetDynamicNonGCStaticBase_SingleAppDomain, _TEXT
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
mov rax, rcx
|
||||
ret
|
||||
LEAF_END JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedGCStaticBase_SingleAppDomain, _TEXT
|
||||
LEAF_ENTRY JIT_GetDynamicGCStaticBase_SingleAppDomain, _TEXT
|
||||
; If class is not initialized, bail to C++ helper
|
||||
test byte ptr [rcx + OFFSETOF__DomainLocalModule__m_pDataBlob + rdx], 1
|
||||
jz CallHelper
|
||||
|
||||
mov rax, [rcx + OFFSETOF__DomainLocalModule__m_pGCStatics]
|
||||
mov rax, [rcx + OFFSETOF__DynamicStaticsInfo__m_pGCStatics]
|
||||
test al, 1
|
||||
jnz CallHelper
|
||||
REPRET
|
||||
|
||||
align 16
|
||||
CallHelper:
|
||||
; Tail call Jit_GetSharedGCStaticBase_Helper
|
||||
jmp JIT_GetSharedGCStaticBase_Helper
|
||||
LEAF_END JIT_GetSharedGCStaticBase_SingleAppDomain, _TEXT
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
mov rax, [rcx + OFFSETOF__DomainLocalModule__m_pGCStatics]
|
||||
ret
|
||||
LEAF_END JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
; Tail call JIT_GetDynamicGCStaticBase_Portable
|
||||
jmp JIT_GetDynamicGCStaticBase_Portable
|
||||
LEAF_END JIT_GetDynamicGCStaticBase_SingleAppDomain, _TEXT
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -55,9 +55,6 @@ extern g_pStringClass:QWORD
|
|||
extern FramedAllocateString:proc
|
||||
extern JIT_NewArr1:proc
|
||||
|
||||
extern JIT_GetSharedNonGCStaticBase_Helper:proc
|
||||
extern JIT_GetSharedGCStaticBase_Helper:proc
|
||||
|
||||
extern JIT_InternalThrow:proc
|
||||
|
||||
ifdef _DEBUG
|
||||
|
|
|
@ -194,22 +194,15 @@ ASMCONSTANTS_C_ASSERT(OFFSETOF__InterfaceInfo_t__m_pMethodTable
|
|||
ASMCONSTANTS_C_ASSERT(SIZEOF__InterfaceInfo_t
|
||||
== sizeof(InterfaceInfo_t));
|
||||
|
||||
#define OFFSETOF__DomainLocalModule__m_pDataBlob 0x030
|
||||
ASMCONSTANTS_C_ASSERT(OFFSETOF__DomainLocalModule__m_pDataBlob
|
||||
== offsetof(DomainLocalModule, m_pDataBlob));
|
||||
ASMCONSTANTS_C_ASSERT(MethodTableAuxiliaryData::enum_flag_Initialized == 0x1);
|
||||
|
||||
// If this changes then we can't just test one bit in the assembly code.
|
||||
ASMCONSTANTS_C_ASSERT(ClassInitFlags::INITIALIZED_FLAG == 1);
|
||||
#define OFFSETOF__DynamicStaticsInfo__m_pNonGCStatics 0x8
|
||||
ASMCONSTANTS_C_ASSERT(OFFSETOF__DynamicStaticsInfo__m_pNonGCStatics
|
||||
== offsetof(DynamicStaticsInfo, m_pNonGCStatics));
|
||||
|
||||
// End for JIT_GetSharedNonGCStaticBaseWorker
|
||||
|
||||
// For JIT_GetSharedGCStaticBaseWorker
|
||||
|
||||
#define OFFSETOF__DomainLocalModule__m_pGCStatics 0x020
|
||||
ASMCONSTANTS_C_ASSERT(OFFSETOF__DomainLocalModule__m_pGCStatics
|
||||
== offsetof(DomainLocalModule, m_pGCStatics));
|
||||
|
||||
// End for JIT_GetSharedGCStaticBaseWorker
|
||||
#define OFFSETOF__DynamicStaticsInfo__m_pGCStatics 0
|
||||
ASMCONSTANTS_C_ASSERT(OFFSETOF__DynamicStaticsInfo__m_pGCStatics
|
||||
== offsetof(DynamicStaticsInfo, m_pGCStatics));
|
||||
|
||||
#define CORINFO_NullReferenceException_ASM 0
|
||||
ASMCONSTANTS_C_ASSERT( CORINFO_NullReferenceException_ASM
|
||||
|
|
|
@ -609,11 +609,7 @@ inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode, bool
|
|||
//
|
||||
// Create alias for optimized implementations of helpers provided on this platform
|
||||
//
|
||||
#define JIT_GetSharedGCStaticBase JIT_GetSharedGCStaticBase_SingleAppDomain
|
||||
#define JIT_GetSharedNonGCStaticBase JIT_GetSharedNonGCStaticBase_SingleAppDomain
|
||||
#define JIT_GetSharedGCStaticBaseNoCtor JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain
|
||||
#define JIT_GetSharedNonGCStaticBaseNoCtor JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain
|
||||
|
||||
|
||||
#define JIT_GetDynamicGCStaticBase JIT_GetDynamicGCStaticBase_SingleAppDomain
|
||||
#define JIT_GetDynamicNonGCStaticBase JIT_GetDynamicNonGCStaticBase_SingleAppDomain
|
||||
|
||||
#endif // __cgencpu_h__
|
||||
|
|
|
@ -10,39 +10,29 @@
|
|||
// appdomain flag
|
||||
//
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedNonGCStaticBase_SingleAppDomain, _TEXT
|
||||
LEAF_ENTRY JIT_GetDynamicNonGCStaticBase_SingleAppDomain, _TEXT
|
||||
// If class is not initialized, bail to C++ helper
|
||||
test byte ptr [rdi + OFFSETOF__DomainLocalModule__m_pDataBlob + rsi], 1
|
||||
jz CallHelper
|
||||
mov rax, rdi
|
||||
mov rax, [rdi + OFFSETOF__DynamicStaticsInfo__m_pNonGCStatics]
|
||||
test al, 1
|
||||
jnz CallHelper
|
||||
rep ret
|
||||
|
||||
.balign 16
|
||||
CallHelper:
|
||||
// Tail call JIT_GetSharedNonGCStaticBase_Helper
|
||||
jmp C_FUNC(JIT_GetSharedNonGCStaticBase_Helper)
|
||||
LEAF_END_MARKED JIT_GetSharedNonGCStaticBase_SingleAppDomain, _TEXT
|
||||
jmp C_FUNC(JIT_GetDynamicNonGCStaticBase_Portable)
|
||||
LEAF_END_MARKED JIT_GetDynamicNonGCStaticBase_SingleAppDomain, _TEXT
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
mov rax, rdi
|
||||
ret
|
||||
LEAF_END JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedGCStaticBase_SingleAppDomain, _TEXT
|
||||
LEAF_ENTRY JIT_GetDynamicGCStaticBase_SingleAppDomain, _TEXT
|
||||
// If class is not initialized, bail to C++ helper
|
||||
test byte ptr [rdi + OFFSETOF__DomainLocalModule__m_pDataBlob + rsi], 1
|
||||
jz CallHelper1
|
||||
|
||||
mov rax, [rdi + OFFSETOF__DomainLocalModule__m_pGCStatics]
|
||||
mov rax, [rdi + OFFSETOF__DynamicStaticsInfo__m_pGCStatics]
|
||||
test al, 1
|
||||
jnz CallHelper1
|
||||
rep ret
|
||||
|
||||
.balign 16
|
||||
CallHelper1:
|
||||
// Tail call Jit_GetSharedGCStaticBase_Helper
|
||||
jmp C_FUNC(JIT_GetSharedGCStaticBase_Helper)
|
||||
LEAF_END JIT_GetSharedGCStaticBase_SingleAppDomain, _TEXT
|
||||
jmp C_FUNC(JIT_GetDynamicGCStaticBase_Portable)
|
||||
LEAF_END JIT_GetDynamicGCStaticBase_SingleAppDomain, _TEXT
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
mov rax, [rdi + OFFSETOF__DomainLocalModule__m_pGCStatics]
|
||||
ret
|
||||
LEAF_END JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
|
|
|
@ -439,118 +439,6 @@ void PinnedHeapHandleTable::EnumStaticGCRefs(promote_func* fn, ScanContext* sc)
|
|||
}
|
||||
}
|
||||
|
||||
// Constructor for the ThreadStaticHandleBucket class.
|
||||
ThreadStaticHandleBucket::ThreadStaticHandleBucket(ThreadStaticHandleBucket *pNext, DWORD Size, BaseDomain *pDomain)
|
||||
: m_pNext(pNext)
|
||||
, m_ArraySize(Size)
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
MODE_COOPERATIVE;
|
||||
PRECONDITION(CheckPointer(pDomain));
|
||||
INJECT_FAULT(COMPlusThrowOM(););
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
PTRARRAYREF HandleArrayObj;
|
||||
|
||||
// Allocate the array on the GC heap.
|
||||
OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
|
||||
HandleArrayObj = (PTRARRAYREF)AllocateObjectArray(Size, g_pObjectClass);
|
||||
|
||||
// Store the array in a strong handle to keep it alive.
|
||||
m_hndHandleArray = pDomain->CreateStrongHandle((OBJECTREF)HandleArrayObj);
|
||||
}
|
||||
|
||||
// Destructor for the ThreadStaticHandleBucket class.
|
||||
ThreadStaticHandleBucket::~ThreadStaticHandleBucket()
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
NOTHROW;
|
||||
GC_NOTRIGGER;
|
||||
MODE_COOPERATIVE;
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
if (m_hndHandleArray)
|
||||
{
|
||||
DestroyStrongHandle(m_hndHandleArray);
|
||||
m_hndHandleArray = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate handles from the bucket.
|
||||
OBJECTHANDLE ThreadStaticHandleBucket::GetHandles()
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
NOTHROW;
|
||||
GC_NOTRIGGER;
|
||||
MODE_COOPERATIVE;
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
return m_hndHandleArray;
|
||||
}
|
||||
|
||||
// Constructor for the ThreadStaticHandleTable class.
|
||||
ThreadStaticHandleTable::ThreadStaticHandleTable(BaseDomain *pDomain)
|
||||
: m_pHead(NULL)
|
||||
, m_pDomain(pDomain)
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
NOTHROW;
|
||||
GC_NOTRIGGER;
|
||||
MODE_ANY;
|
||||
PRECONDITION(CheckPointer(pDomain));
|
||||
}
|
||||
CONTRACTL_END;
|
||||
}
|
||||
|
||||
// Destructor for the ThreadStaticHandleTable class.
|
||||
ThreadStaticHandleTable::~ThreadStaticHandleTable()
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
NOTHROW;
|
||||
GC_NOTRIGGER;
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
// Delete the buckets.
|
||||
while (m_pHead)
|
||||
{
|
||||
ThreadStaticHandleBucket *pOld = m_pHead;
|
||||
m_pHead = pOld->GetNext();
|
||||
delete pOld;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate handles from the large heap handle table.
|
||||
OBJECTHANDLE ThreadStaticHandleTable::AllocateHandles(DWORD nRequested)
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
MODE_COOPERATIVE;
|
||||
PRECONDITION(nRequested > 0);
|
||||
INJECT_FAULT(COMPlusThrowOM(););
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
// create a new bucket for this allocation
|
||||
m_pHead = new ThreadStaticHandleBucket(m_pHead, nRequested, m_pDomain);
|
||||
|
||||
return m_pHead->GetHandles();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
// BaseDomain
|
||||
//*****************************************************************************
|
||||
|
@ -612,7 +500,7 @@ void BaseDomain::Init()
|
|||
m_DomainCrst.Init(CrstBaseDomain);
|
||||
|
||||
m_DomainCacheCrst.Init(CrstAppDomainCache);
|
||||
m_DomainLocalBlockCrst.Init(CrstDomainLocalBlock);
|
||||
m_crstGenericDictionaryExpansionLock.Init(CrstGenericDictionaryExpansion);
|
||||
|
||||
// NOTE: CRST_UNSAFE_COOPGC prevents a GC mode switch to preemptive when entering this crst.
|
||||
// If you remove this flag, we will switch to preemptive mode when entering
|
||||
|
@ -637,7 +525,6 @@ void BaseDomain::Init()
|
|||
m_NativeTypeLoadLock.Init(CrstInteropData, CrstFlags(CRST_REENTRANCY), TRUE);
|
||||
|
||||
m_crstLoaderAllocatorReferences.Init(CrstLoaderAllocatorReferences);
|
||||
m_crstStaticBoxInitLock.Init(CrstStaticBoxInit);
|
||||
// Has to switch thread to GC_NOTRIGGER while being held (see code:BaseDomain#AssemblyListLock)
|
||||
m_crstAssemblyList.Init(CrstAssemblyList, CrstFlags(
|
||||
CRST_GC_NOTRIGGER_WHEN_TAKEN | CRST_DEBUGGER_THREAD | CRST_TAKEN_DURING_SHUTDOWN));
|
||||
|
@ -665,14 +552,6 @@ void BaseDomain::InitVSD()
|
|||
GetLoaderAllocator()->InitVirtualCallStubManager(this);
|
||||
}
|
||||
|
||||
void BaseDomain::InitThreadStaticBlockTypeMap()
|
||||
{
|
||||
STANDARD_VM_CONTRACT;
|
||||
|
||||
m_NonGCThreadStaticBlockTypeIDMap.Init();
|
||||
m_GCThreadStaticBlockTypeIDMap.Init();
|
||||
}
|
||||
|
||||
void BaseDomain::ClearBinderContext()
|
||||
{
|
||||
CONTRACTL
|
||||
|
@ -793,7 +672,7 @@ void AppDomain::SetNativeDllSearchDirectories(LPCWSTR wszNativeDllSearchDirector
|
|||
}
|
||||
}
|
||||
|
||||
OBJECTREF* BaseDomain::AllocateObjRefPtrsInLargeTable(int nRequested, OBJECTREF** ppLazyAllocate)
|
||||
OBJECTREF* BaseDomain::AllocateObjRefPtrsInLargeTable(int nRequested, DynamicStaticsInfo* pStaticsInfo, MethodTable *pMTToFillWithStaticBoxes)
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
|
@ -805,10 +684,10 @@ OBJECTREF* BaseDomain::AllocateObjRefPtrsInLargeTable(int nRequested, OBJECTREF*
|
|||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
if (ppLazyAllocate && *ppLazyAllocate)
|
||||
if (pStaticsInfo && pStaticsInfo->GetGCStaticsPointer() != NULL)
|
||||
{
|
||||
// Allocation already happened
|
||||
return *ppLazyAllocate;
|
||||
return pStaticsInfo->GetGCStaticsPointer();
|
||||
}
|
||||
|
||||
GCX_COOP();
|
||||
|
@ -819,15 +698,21 @@ OBJECTREF* BaseDomain::AllocateObjRefPtrsInLargeTable(int nRequested, OBJECTREF*
|
|||
|
||||
// Allocate the handles.
|
||||
OBJECTREF* result = m_pPinnedHeapHandleTable->AllocateHandles(nRequested);
|
||||
if (ppLazyAllocate)
|
||||
if (pMTToFillWithStaticBoxes != NULL)
|
||||
{
|
||||
GCPROTECT_BEGININTERIOR(result);
|
||||
pMTToFillWithStaticBoxes->AllocateRegularStaticBoxes(&result);
|
||||
GCPROTECT_END();
|
||||
}
|
||||
if (pStaticsInfo)
|
||||
{
|
||||
// race with other threads that might be doing the same concurrent allocation
|
||||
if (InterlockedCompareExchangeT<OBJECTREF*>(ppLazyAllocate, result, NULL) != NULL)
|
||||
if (!pStaticsInfo->InterlockedUpdateStaticsPointer(/*isGCPointer*/ true, (TADDR)result))
|
||||
{
|
||||
// we lost the race, release our handles and use the handles from the
|
||||
// winning thread
|
||||
m_pPinnedHeapHandleTable->ReleaseHandles(result, nRequested);
|
||||
result = *ppLazyAllocate;
|
||||
result = pStaticsInfo->GetGCStaticsPointer();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -970,9 +855,6 @@ void SystemDomain::Attach()
|
|||
m_SystemDomainCrst.Init(CrstSystemDomain, (CrstFlags)(CRST_REENTRANCY | CRST_TAKEN_DURING_SHUTDOWN));
|
||||
m_DelayedUnloadCrst.Init(CrstSystemDomainDelayedUnloadList, CRST_UNSAFE_COOPGC);
|
||||
|
||||
// Initialize the ID dispenser that is used for domain neutral module IDs
|
||||
g_pModuleIndexDispenser = new IdDispenser();
|
||||
|
||||
// Create the global SystemDomain and initialize it.
|
||||
m_pSystemDomain = new (&g_pSystemDomainMemory[0]) SystemDomain();
|
||||
// No way it can fail since g_pSystemDomainMemory is a static array.
|
||||
|
@ -1329,9 +1211,6 @@ void SystemDomain::LoadBaseSystemClasses()
|
|||
// Load the Object array class.
|
||||
g_pPredefinedArrayTypes[ELEMENT_TYPE_OBJECT] = ClassLoader::LoadArrayTypeThrowing(TypeHandle(g_pObjectClass));
|
||||
|
||||
// We have delayed allocation of CoreLib's static handles until we load the object class
|
||||
CoreLibBinder::GetModule()->AllocateRegularStaticHandles();
|
||||
|
||||
// Boolean has to be loaded first to break cycle in IComparisonOperations and IEqualityOperators
|
||||
CoreLibBinder::LoadPrimitiveType(ELEMENT_TYPE_BOOLEAN);
|
||||
|
||||
|
@ -1776,9 +1655,6 @@ void AppDomain::Create()
|
|||
// allocate a Virtual Call Stub Manager for the default domain
|
||||
pDomain->InitVSD();
|
||||
|
||||
// allocate a thread static block to index map
|
||||
pDomain->InitThreadStaticBlockTypeMap();
|
||||
|
||||
pDomain->SetStage(AppDomain::STAGE_OPEN);
|
||||
pDomain->CreateDefaultBinder();
|
||||
|
||||
|
@ -3057,18 +2933,16 @@ void AppDomain::SetupSharedStatics()
|
|||
// Because we are allocating/referencing objects, need to be in cooperative mode
|
||||
GCX_COOP();
|
||||
|
||||
DomainLocalModule *pLocalModule = CoreLibBinder::GetModule()->GetDomainLocalModule();
|
||||
|
||||
// This is a convenient place to initialize String.Empty.
|
||||
// It is treated as intrinsic by the JIT as so the static constructor would never run.
|
||||
// Leaving it uninitialized would confuse debuggers.
|
||||
|
||||
// String should not have any static constructors.
|
||||
_ASSERTE(g_pStringClass->IsClassPreInited());
|
||||
// String should not have any static constructors, so this should be safe. It will just ensure that statics are allocated
|
||||
g_pStringClass->CheckRunClassInitThrowing();
|
||||
|
||||
FieldDesc * pEmptyStringFD = CoreLibBinder::GetField(FIELD__STRING__EMPTY);
|
||||
OBJECTREF* pEmptyStringHandle = (OBJECTREF*)
|
||||
((TADDR)pLocalModule->GetPrecomputedGCStaticsBasePointer()+pEmptyStringFD->GetOffset());
|
||||
((TADDR)g_pStringClass->GetDynamicStaticsInfo()->m_pGCStatics+pEmptyStringFD->GetOffset());
|
||||
SetObjectReference( pEmptyStringHandle, StringObject::GetEmptyString());
|
||||
}
|
||||
|
||||
|
@ -4082,284 +3956,8 @@ void AppDomain::ExceptionUnwind(Frame *pFrame)
|
|||
|
||||
#endif // !DACCESS_COMPILE
|
||||
|
||||
DWORD DomainLocalModule::GetClassFlags(MethodTable* pMT, DWORD iClassIndex /*=(DWORD)-1*/)
|
||||
{
|
||||
CONTRACTL {
|
||||
NOTHROW;
|
||||
GC_NOTRIGGER;
|
||||
} CONTRACTL_END;
|
||||
|
||||
{
|
||||
CONSISTENCY_CHECK(GetDomainAssembly()->GetModule() == pMT->GetModuleForStatics());
|
||||
}
|
||||
|
||||
if (pMT->IsDynamicStatics())
|
||||
{
|
||||
_ASSERTE(!pMT->ContainsGenericVariables());
|
||||
DWORD dynamicClassID = pMT->GetModuleDynamicEntryID();
|
||||
if(m_aDynamicEntries <= dynamicClassID)
|
||||
return FALSE;
|
||||
return (m_pDynamicClassTable[dynamicClassID].m_dwFlags);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (iClassIndex == (DWORD)-1)
|
||||
iClassIndex = pMT->GetClassIndex();
|
||||
return GetPrecomputedStaticsClassData()[iClassIndex];
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
|
||||
void DomainLocalModule::SetClassInitialized(MethodTable* pMT)
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
MODE_ANY;
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
BaseDomain::DomainLocalBlockLockHolder lh(AppDomain::GetCurrentDomain());
|
||||
|
||||
_ASSERTE(!IsClassInitialized(pMT));
|
||||
_ASSERTE(!IsClassInitError(pMT));
|
||||
|
||||
SetClassFlags(pMT, ClassInitFlags::INITIALIZED_FLAG);
|
||||
}
|
||||
|
||||
void DomainLocalModule::SetClassInitError(MethodTable* pMT)
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
|
||||
BaseDomain::DomainLocalBlockLockHolder lh(AppDomain::GetCurrentDomain());
|
||||
|
||||
SetClassFlags(pMT, ClassInitFlags::ERROR_FLAG);
|
||||
}
|
||||
|
||||
void DomainLocalModule::SetClassFlags(MethodTable* pMT, DWORD dwFlags)
|
||||
{
|
||||
CONTRACTL {
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
PRECONDITION(GetDomainAssembly()->GetModule() == pMT->GetModuleForStatics());
|
||||
// Assumes BaseDomain::DomainLocalBlockLockHolder is taken
|
||||
PRECONDITION(AppDomain::GetCurrentDomain()->OwnDomainLocalBlockLock());
|
||||
} CONTRACTL_END;
|
||||
|
||||
if (pMT->IsDynamicStatics())
|
||||
{
|
||||
_ASSERTE(!pMT->ContainsGenericVariables());
|
||||
DWORD dwID = pMT->GetModuleDynamicEntryID();
|
||||
EnsureDynamicClassIndex(dwID);
|
||||
m_pDynamicClassTable[dwID].m_dwFlags |= dwFlags;
|
||||
}
|
||||
else
|
||||
{
|
||||
GetPrecomputedStaticsClassData()[pMT->GetClassIndex()] |= dwFlags;
|
||||
}
|
||||
}
|
||||
|
||||
void DomainLocalModule::EnsureDynamicClassIndex(DWORD dwID)
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
MODE_ANY;
|
||||
INJECT_FAULT(COMPlusThrowOM(););
|
||||
// Assumes BaseDomain::DomainLocalBlockLockHolder is taken
|
||||
PRECONDITION(AppDomain::GetCurrentDomain()->OwnDomainLocalBlockLock());
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
SIZE_T oldDynamicEntries = m_aDynamicEntries.Load();
|
||||
|
||||
if (dwID < oldDynamicEntries)
|
||||
{
|
||||
_ASSERTE(m_pDynamicClassTable.Load() != NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
SIZE_T aDynamicEntries = max<SIZE_T>(16, oldDynamicEntries);
|
||||
while (aDynamicEntries <= dwID)
|
||||
{
|
||||
aDynamicEntries *= 2;
|
||||
}
|
||||
|
||||
DynamicClassInfo* pNewDynamicClassTable;
|
||||
pNewDynamicClassTable = (DynamicClassInfo*)
|
||||
(void*)GetDomainAssembly()->GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(
|
||||
S_SIZE_T(sizeof(DynamicClassInfo)) * S_SIZE_T(aDynamicEntries));
|
||||
|
||||
if (oldDynamicEntries != 0)
|
||||
{
|
||||
memcpy((void*)pNewDynamicClassTable, m_pDynamicClassTable, sizeof(DynamicClassInfo) * oldDynamicEntries);
|
||||
}
|
||||
|
||||
// Note: Memory allocated on loader heap is zero filled
|
||||
// memset(pNewDynamicClassTable + m_aDynamicEntries, 0, (aDynamicEntries - m_aDynamicEntries) * sizeof(DynamicClassInfo));
|
||||
|
||||
_ASSERTE(m_aDynamicEntries%2 == 0);
|
||||
|
||||
// Commit new dynamic table. The lock-free helpers depend on the order.
|
||||
MemoryBarrier();
|
||||
m_pDynamicClassTable = pNewDynamicClassTable;
|
||||
MemoryBarrier();
|
||||
m_aDynamicEntries = aDynamicEntries;
|
||||
}
|
||||
|
||||
void DomainLocalModule::AllocateDynamicClass(MethodTable *pMT)
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
// Assumes BaseDomain::DomainLocalBlockLockHolder is taken
|
||||
PRECONDITION(AppDomain::GetCurrentDomain()->OwnDomainLocalBlockLock());
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
_ASSERTE(!pMT->ContainsGenericVariables());
|
||||
_ASSERTE(!pMT->IsSharedByGenericInstantiations());
|
||||
_ASSERTE(GetDomainAssembly()->GetModule() == pMT->GetModuleForStatics());
|
||||
_ASSERTE(pMT->IsDynamicStatics());
|
||||
|
||||
DWORD dynamicEntryIDIndex = pMT->GetModuleDynamicEntryID();
|
||||
|
||||
EnsureDynamicClassIndex(dynamicEntryIDIndex);
|
||||
|
||||
_ASSERTE(m_aDynamicEntries > dynamicEntryIDIndex);
|
||||
|
||||
EEClass *pClass = pMT->GetClass();
|
||||
|
||||
DWORD dwStaticBytes = pClass->GetNonGCRegularStaticFieldBytes();
|
||||
DWORD dwNumHandleStatics = pClass->GetNumHandleRegularStatics();
|
||||
|
||||
_ASSERTE(!IsClassAllocated(pMT));
|
||||
_ASSERTE(!IsClassInitialized(pMT));
|
||||
_ASSERTE(!IsClassInitError(pMT));
|
||||
|
||||
DynamicEntry *pDynamicStatics = m_pDynamicClassTable[dynamicEntryIDIndex].m_pDynamicEntry;
|
||||
|
||||
// We need this check because maybe a class had a cctor but no statics
|
||||
if (dwStaticBytes > 0 || dwNumHandleStatics > 0)
|
||||
{
|
||||
if (pDynamicStatics == NULL)
|
||||
{
|
||||
LoaderHeap * pLoaderAllocator = GetDomainAssembly()->GetLoaderAllocator()->GetHighFrequencyHeap();
|
||||
|
||||
if (pMT->Collectible())
|
||||
{
|
||||
pDynamicStatics = (DynamicEntry*)(void*)pLoaderAllocator->AllocMem(S_SIZE_T(sizeof(CollectibleDynamicEntry)));
|
||||
}
|
||||
else
|
||||
{
|
||||
SIZE_T dynamicEntrySize = DynamicEntry::GetOffsetOfDataBlob() + dwStaticBytes;
|
||||
|
||||
#ifdef FEATURE_64BIT_ALIGNMENT
|
||||
// Allocate memory with extra alignment only if it is really necessary
|
||||
if (dwStaticBytes >= MAX_PRIMITIVE_FIELD_SIZE)
|
||||
{
|
||||
static_assert_no_msg(sizeof(NormalDynamicEntry) % MAX_PRIMITIVE_FIELD_SIZE == 0);
|
||||
pDynamicStatics = (DynamicEntry*)(void*)pLoaderAllocator->AllocAlignedMem(dynamicEntrySize, MAX_PRIMITIVE_FIELD_SIZE);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
pDynamicStatics = (DynamicEntry*)(void*)pLoaderAllocator->AllocMem(S_SIZE_T(dynamicEntrySize));
|
||||
}
|
||||
|
||||
// Note: Memory allocated on loader heap is zero filled
|
||||
|
||||
m_pDynamicClassTable[dynamicEntryIDIndex].m_pDynamicEntry = pDynamicStatics;
|
||||
}
|
||||
|
||||
if (pMT->Collectible() && (dwStaticBytes != 0))
|
||||
{
|
||||
GCX_COOP();
|
||||
OBJECTREF nongcStaticsArray = NULL;
|
||||
GCPROTECT_BEGIN(nongcStaticsArray);
|
||||
#ifdef FEATURE_64BIT_ALIGNMENT
|
||||
// Allocate memory with extra alignment only if it is really necessary
|
||||
if (dwStaticBytes >= MAX_PRIMITIVE_FIELD_SIZE)
|
||||
nongcStaticsArray = AllocatePrimitiveArray(ELEMENT_TYPE_I8, (dwStaticBytes + (sizeof(CLR_I8)-1)) / (sizeof(CLR_I8)));
|
||||
else
|
||||
#endif
|
||||
nongcStaticsArray = AllocatePrimitiveArray(ELEMENT_TYPE_U1, dwStaticBytes);
|
||||
((CollectibleDynamicEntry *)pDynamicStatics)->m_hNonGCStatics = GetDomainAssembly()->GetModule()->GetLoaderAllocator()->AllocateHandle(nongcStaticsArray);
|
||||
GCPROTECT_END();
|
||||
}
|
||||
if (dwNumHandleStatics > 0)
|
||||
{
|
||||
if (!pMT->Collectible())
|
||||
{
|
||||
GetAppDomain()->AllocateStaticFieldObjRefPtrs(dwNumHandleStatics,
|
||||
&((NormalDynamicEntry *)pDynamicStatics)->m_pGCStatics);
|
||||
}
|
||||
else
|
||||
{
|
||||
GCX_COOP();
|
||||
OBJECTREF gcStaticsArray = NULL;
|
||||
GCPROTECT_BEGIN(gcStaticsArray);
|
||||
gcStaticsArray = AllocateObjectArray(dwNumHandleStatics, g_pObjectClass);
|
||||
((CollectibleDynamicEntry *)pDynamicStatics)->m_hGCStatics = GetDomainAssembly()->GetModule()->GetLoaderAllocator()->AllocateHandle(gcStaticsArray);
|
||||
GCPROTECT_END();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DomainLocalModule::PopulateClass(MethodTable *pMT)
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
_ASSERTE(!pMT->ContainsGenericVariables());
|
||||
|
||||
// <todo> the only work actually done here for non-dynamics is the freezing related work.
|
||||
// See if we can eliminate this and make this a dynamic-only path </todo>
|
||||
DWORD iClassIndex = pMT->GetClassIndex();
|
||||
|
||||
if (!IsClassAllocated(pMT, iClassIndex))
|
||||
{
|
||||
BaseDomain::DomainLocalBlockLockHolder lh(AppDomain::GetCurrentDomain());
|
||||
|
||||
if (!IsClassAllocated(pMT, iClassIndex))
|
||||
{
|
||||
// Allocate dynamic space if necessary
|
||||
if (pMT->IsDynamicStatics())
|
||||
AllocateDynamicClass(pMT);
|
||||
|
||||
// determine flags to set on the statics block
|
||||
DWORD dwFlags = ClassInitFlags::ALLOCATECLASS_FLAG;
|
||||
|
||||
if (!pMT->HasClassConstructor() && !pMT->HasBoxedRegularStatics())
|
||||
{
|
||||
_ASSERTE(!IsClassInitialized(pMT));
|
||||
_ASSERTE(!IsClassInitError(pMT));
|
||||
dwFlags |= ClassInitFlags::INITIALIZED_FLAG;
|
||||
}
|
||||
|
||||
if (pMT->Collectible())
|
||||
{
|
||||
dwFlags |= ClassInitFlags::COLLECTIBLE_FLAG;
|
||||
}
|
||||
|
||||
// Set all flags at the same time to avoid races
|
||||
SetClassFlags(pMT, dwFlags);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
DomainAssembly* AppDomain::RaiseTypeResolveEventThrowing(DomainAssembly* pAssembly, LPCSTR szName, ASSEMBLYREF *pResultingAssemblyRef)
|
||||
{
|
||||
CONTRACTL
|
||||
|
@ -4660,55 +4258,6 @@ PTR_MethodTable BaseDomain::LookupType(UINT32 id) {
|
|||
return pMT;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
UINT32 BaseDomain::GetNonGCThreadStaticTypeIndex(PTR_MethodTable pMT)
|
||||
{
|
||||
CONTRACTL {
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
} CONTRACTL_END;
|
||||
|
||||
return m_NonGCThreadStaticBlockTypeIDMap.GetTypeID(pMT, false);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
PTR_MethodTable BaseDomain::LookupNonGCThreadStaticBlockType(UINT32 id) {
|
||||
CONTRACTL {
|
||||
NOTHROW;
|
||||
WRAPPER(GC_TRIGGERS);
|
||||
CONSISTENCY_CHECK(id != TYPE_ID_THIS_CLASS);
|
||||
} CONTRACTL_END;
|
||||
|
||||
PTR_MethodTable pMT = m_NonGCThreadStaticBlockTypeIDMap.LookupType(id);
|
||||
|
||||
CONSISTENCY_CHECK(CheckPointer(pMT));
|
||||
return pMT;
|
||||
}
|
||||
//------------------------------------------------------------------------
|
||||
UINT32 BaseDomain::GetGCThreadStaticTypeIndex(PTR_MethodTable pMT)
|
||||
{
|
||||
CONTRACTL {
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
} CONTRACTL_END;
|
||||
|
||||
return m_GCThreadStaticBlockTypeIDMap.GetTypeID(pMT, false);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
PTR_MethodTable BaseDomain::LookupGCThreadStaticBlockType(UINT32 id) {
|
||||
CONTRACTL {
|
||||
NOTHROW;
|
||||
WRAPPER(GC_TRIGGERS);
|
||||
CONSISTENCY_CHECK(id != TYPE_ID_THIS_CLASS);
|
||||
} CONTRACTL_END;
|
||||
|
||||
PTR_MethodTable pMT = m_GCThreadStaticBlockTypeIDMap.LookupType(id);
|
||||
|
||||
CONSISTENCY_CHECK(CheckPointer(pMT));
|
||||
return pMT;
|
||||
}
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
//---------------------------------------------------------------------------------------
|
||||
void BaseDomain::RemoveTypesFromTypeIDMap(LoaderAllocator* pLoaderAllocator)
|
||||
|
@ -5113,40 +4662,6 @@ size_t AppDomain::EstimateSize()
|
|||
|
||||
#ifdef DACCESS_COMPILE
|
||||
|
||||
void
|
||||
DomainLocalModule::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
|
||||
{
|
||||
SUPPORTS_DAC;
|
||||
|
||||
// Enumerate the DomainLocalModule itself. DLMs are allocated to be larger than
|
||||
// sizeof(DomainLocalModule) to make room for ClassInit flags and non-GC statics.
|
||||
// "DAC_ENUM_DTHIS()" probably does not account for this, so we might not enumerate
|
||||
// all of the ClassInit flags and non-GC statics.
|
||||
// sizeof(DomainLocalModule) == 0x28
|
||||
DAC_ENUM_DTHIS();
|
||||
|
||||
if (m_pDomainAssembly.IsValid())
|
||||
{
|
||||
m_pDomainAssembly->EnumMemoryRegions(flags);
|
||||
}
|
||||
|
||||
if (m_pDynamicClassTable.Load().IsValid())
|
||||
{
|
||||
DacEnumMemoryRegion(dac_cast<TADDR>(m_pDynamicClassTable.Load()),
|
||||
m_aDynamicEntries * sizeof(DynamicClassInfo));
|
||||
|
||||
for (SIZE_T i = 0; i < m_aDynamicEntries; i++)
|
||||
{
|
||||
PTR_DynamicEntry entry = dac_cast<PTR_DynamicEntry>(m_pDynamicClassTable[i].m_pDynamicEntry.Load());
|
||||
if (entry.IsValid())
|
||||
{
|
||||
// sizeof(DomainLocalModule::DynamicEntry) == 8
|
||||
entry.EnumMem();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AppDomain::EnumMemoryRegions(CLRDataEnumMemoryFlags flags, bool enumThis)
|
||||
{
|
||||
|
|
|
@ -58,406 +58,6 @@ class RCWRefCache;
|
|||
#endif
|
||||
|
||||
|
||||
GPTR_DECL(IdDispenser, g_pModuleIndexDispenser);
|
||||
|
||||
// We would like *ALLOCATECLASS_FLAG to AV (in order to catch errors), so don't change it
|
||||
struct ClassInitFlags {
|
||||
enum
|
||||
{
|
||||
INITIALIZED_FLAG_BIT = 0,
|
||||
INITIALIZED_FLAG = 1<<INITIALIZED_FLAG_BIT,
|
||||
ERROR_FLAG_BIT = 1,
|
||||
ERROR_FLAG = 1<<ERROR_FLAG_BIT,
|
||||
ALLOCATECLASS_FLAG_BIT = 2, // Bit to avoid racing for InstantiateStaticHandles
|
||||
ALLOCATECLASS_FLAG = 1<<ALLOCATECLASS_FLAG_BIT,
|
||||
COLLECTIBLE_FLAG_BIT = 3,
|
||||
COLLECTIBLE_FLAG = 1<<COLLECTIBLE_FLAG_BIT
|
||||
};
|
||||
};
|
||||
|
||||
struct DomainLocalModule
|
||||
{
|
||||
friend class ClrDataAccess;
|
||||
friend class CheckAsmOffsets;
|
||||
friend struct ThreadLocalModule;
|
||||
|
||||
// After these macros complete, they may have returned an interior pointer into a gc object. This pointer will have been cast to a byte pointer
|
||||
// It is critically important that no GC is allowed to occur before this pointer is used.
|
||||
#define GET_DYNAMICENTRY_GCSTATICS_BASEPOINTER(pLoaderAllocator, dynamicClassInfoParam, pGCStatics) \
|
||||
{\
|
||||
DomainLocalModule::PTR_DynamicClassInfo dynamicClassInfo = dac_cast<DomainLocalModule::PTR_DynamicClassInfo>(dynamicClassInfoParam);\
|
||||
DomainLocalModule::PTR_DynamicEntry pDynamicEntry = dac_cast<DomainLocalModule::PTR_DynamicEntry>((DomainLocalModule::DynamicEntry*)dynamicClassInfo->m_pDynamicEntry.Load()); \
|
||||
if ((dynamicClassInfo->m_dwFlags) & ClassInitFlags::COLLECTIBLE_FLAG) \
|
||||
{\
|
||||
PTRARRAYREF objArray;\
|
||||
objArray = (PTRARRAYREF)pLoaderAllocator->GetHandleValueFastCannotFailType2( \
|
||||
(dac_cast<DomainLocalModule::PTR_CollectibleDynamicEntry>(pDynamicEntry))->m_hGCStatics);\
|
||||
*(pGCStatics) = dac_cast<PTR_BYTE>(PTR_READ(PTR_TO_TADDR(OBJECTREFToObject( objArray )) + offsetof(PtrArray, m_Array), objArray->GetNumComponents() * sizeof(void*))) ;\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
*(pGCStatics) = (dac_cast<DomainLocalModule::PTR_NormalDynamicEntry>(pDynamicEntry))->GetGCStaticsBasePointer();\
|
||||
}\
|
||||
}\
|
||||
|
||||
#define GET_DYNAMICENTRY_NONGCSTATICS_BASEPOINTER(pLoaderAllocator, dynamicClassInfoParam, pNonGCStatics) \
|
||||
{\
|
||||
DomainLocalModule::PTR_DynamicClassInfo dynamicClassInfo = dac_cast<DomainLocalModule::PTR_DynamicClassInfo>(dynamicClassInfoParam);\
|
||||
DomainLocalModule::PTR_DynamicEntry pDynamicEntry = dac_cast<DomainLocalModule::PTR_DynamicEntry>((DomainLocalModule::DynamicEntry*)(dynamicClassInfo)->m_pDynamicEntry.Load()); \
|
||||
if (((dynamicClassInfo)->m_dwFlags) & ClassInitFlags::COLLECTIBLE_FLAG) \
|
||||
{\
|
||||
if ((dac_cast<DomainLocalModule::PTR_CollectibleDynamicEntry>(pDynamicEntry))->m_hNonGCStatics != 0) \
|
||||
{ \
|
||||
U1ARRAYREF objArray;\
|
||||
objArray = (U1ARRAYREF)pLoaderAllocator->GetHandleValueFastCannotFailType2( \
|
||||
(dac_cast<DomainLocalModule::PTR_CollectibleDynamicEntry>(pDynamicEntry))->m_hNonGCStatics);\
|
||||
*(pNonGCStatics) = dac_cast<PTR_BYTE>(PTR_READ( \
|
||||
PTR_TO_TADDR(OBJECTREFToObject( objArray )) + sizeof(ArrayBase) - DomainLocalModule::DynamicEntry::GetOffsetOfDataBlob(), \
|
||||
objArray->GetNumComponents() * (DWORD)objArray->GetComponentSize() + DomainLocalModule::DynamicEntry::GetOffsetOfDataBlob())); \
|
||||
} else (*pNonGCStatics) = NULL; \
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
*(pNonGCStatics) = dac_cast<DomainLocalModule::PTR_NormalDynamicEntry>(pDynamicEntry)->GetNonGCStaticsBasePointer();\
|
||||
}\
|
||||
}\
|
||||
|
||||
struct DynamicEntry
|
||||
{
|
||||
static DWORD GetOffsetOfDataBlob();
|
||||
};
|
||||
typedef DPTR(DynamicEntry) PTR_DynamicEntry;
|
||||
|
||||
struct CollectibleDynamicEntry : public DynamicEntry
|
||||
{
|
||||
LOADERHANDLE m_hGCStatics;
|
||||
LOADERHANDLE m_hNonGCStatics;
|
||||
};
|
||||
typedef DPTR(CollectibleDynamicEntry) PTR_CollectibleDynamicEntry;
|
||||
|
||||
struct NormalDynamicEntry : public DynamicEntry
|
||||
{
|
||||
PTR_OBJECTREF m_pGCStatics;
|
||||
#ifdef FEATURE_64BIT_ALIGNMENT
|
||||
// Padding to make m_pDataBlob aligned at MAX_PRIMITIVE_FIELD_SIZE
|
||||
// code:MethodTableBuilder::PlaceRegularStaticFields assumes that the start of the data blob is aligned
|
||||
SIZE_T m_padding;
|
||||
#endif
|
||||
BYTE m_pDataBlob[0];
|
||||
|
||||
inline PTR_BYTE GetGCStaticsBasePointer()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
SUPPORTS_DAC;
|
||||
return dac_cast<PTR_BYTE>(m_pGCStatics);
|
||||
}
|
||||
inline PTR_BYTE GetNonGCStaticsBasePointer()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT
|
||||
SUPPORTS_DAC;
|
||||
return dac_cast<PTR_BYTE>(this);
|
||||
}
|
||||
};
|
||||
typedef DPTR(NormalDynamicEntry) PTR_NormalDynamicEntry;
|
||||
|
||||
struct DynamicClassInfo
|
||||
{
|
||||
VolatilePtr<DynamicEntry, PTR_DynamicEntry> m_pDynamicEntry;
|
||||
Volatile<DWORD> m_dwFlags;
|
||||
};
|
||||
typedef DPTR(DynamicClassInfo) PTR_DynamicClassInfo;
|
||||
|
||||
inline UMEntryThunk * GetADThunkTable()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT
|
||||
return m_pADThunkTable;
|
||||
}
|
||||
|
||||
inline void SetADThunkTable(UMEntryThunk* pADThunkTable)
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT
|
||||
InterlockedCompareExchangeT(m_pADThunkTable.GetPointer(), pADThunkTable, NULL);
|
||||
}
|
||||
|
||||
// Note the difference between:
|
||||
//
|
||||
// GetPrecomputedNonGCStaticsBasePointer() and
|
||||
// GetPrecomputedStaticsClassData()
|
||||
//
|
||||
// GetPrecomputedNonGCStaticsBasePointer returns the pointer that should be added to field offsets to retrieve statics
|
||||
// GetPrecomputedStaticsClassData returns a pointer to the first byte of the precomputed statics block
|
||||
inline TADDR GetPrecomputedNonGCStaticsBasePointer()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT
|
||||
return dac_cast<TADDR>(this);
|
||||
}
|
||||
|
||||
inline PTR_BYTE GetPrecomputedStaticsClassData()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT
|
||||
return dac_cast<PTR_BYTE>(this) + offsetof(DomainLocalModule, m_pDataBlob);
|
||||
}
|
||||
|
||||
static SIZE_T GetOffsetOfDataBlob() { return offsetof(DomainLocalModule, m_pDataBlob); }
|
||||
static SIZE_T GetOffsetOfGCStaticPointer() { return offsetof(DomainLocalModule, m_pGCStatics); }
|
||||
|
||||
inline DomainAssembly* GetDomainAssembly()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT
|
||||
SUPPORTS_DAC;
|
||||
return m_pDomainAssembly;
|
||||
}
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
inline void SetDomainAssembly(DomainAssembly* pDomainAssembly)
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT
|
||||
m_pDomainAssembly = pDomainAssembly;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline PTR_OBJECTREF GetPrecomputedGCStaticsBasePointer()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT
|
||||
return m_pGCStatics;
|
||||
}
|
||||
|
||||
inline PTR_OBJECTREF * GetPrecomputedGCStaticsBasePointerAddress()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT
|
||||
return &m_pGCStatics;
|
||||
}
|
||||
|
||||
// Returns bytes so we can add offsets
|
||||
inline PTR_BYTE GetGCStaticsBasePointer(MethodTable * pMT)
|
||||
{
|
||||
WRAPPER_NO_CONTRACT
|
||||
SUPPORTS_DAC;
|
||||
|
||||
if (pMT->IsDynamicStatics())
|
||||
{
|
||||
_ASSERTE(GetDomainAssembly()->GetModule() == pMT->GetModuleForStatics());
|
||||
return GetDynamicEntryGCStaticsBasePointer(pMT->GetModuleDynamicEntryID(), pMT->GetLoaderAllocator());
|
||||
}
|
||||
else
|
||||
{
|
||||
return dac_cast<PTR_BYTE>(m_pGCStatics);
|
||||
}
|
||||
}
|
||||
|
||||
inline PTR_BYTE GetNonGCStaticsBasePointer(MethodTable * pMT)
|
||||
{
|
||||
WRAPPER_NO_CONTRACT
|
||||
SUPPORTS_DAC;
|
||||
|
||||
if (pMT->IsDynamicStatics())
|
||||
{
|
||||
_ASSERTE(GetDomainAssembly()->GetModule() == pMT->GetModuleForStatics());
|
||||
return GetDynamicEntryNonGCStaticsBasePointer(pMT->GetModuleDynamicEntryID(), pMT->GetLoaderAllocator());
|
||||
}
|
||||
else
|
||||
{
|
||||
return dac_cast<PTR_BYTE>(this);
|
||||
}
|
||||
}
|
||||
|
||||
inline DynamicClassInfo* GetDynamicClassInfo(DWORD n)
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT
|
||||
SUPPORTS_DAC;
|
||||
_ASSERTE(m_pDynamicClassTable.Load() && m_aDynamicEntries > n);
|
||||
dac_cast<PTR_DynamicEntry>(m_pDynamicClassTable[n].m_pDynamicEntry.Load());
|
||||
|
||||
return &m_pDynamicClassTable[n];
|
||||
}
|
||||
|
||||
// These helpers can now return null, as the debugger may do queries on a type
|
||||
// before the calls to PopulateClass happen
|
||||
inline PTR_BYTE GetDynamicEntryGCStaticsBasePointer(DWORD n, PTR_LoaderAllocator pLoaderAllocator)
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
NOTHROW;
|
||||
GC_NOTRIGGER;
|
||||
MODE_COOPERATIVE;
|
||||
SUPPORTS_DAC;
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
|
||||
if (n >= m_aDynamicEntries)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DynamicClassInfo* pClassInfo = GetDynamicClassInfo(n);
|
||||
if (!pClassInfo->m_pDynamicEntry)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PTR_BYTE retval = NULL;
|
||||
|
||||
GET_DYNAMICENTRY_GCSTATICS_BASEPOINTER(pLoaderAllocator, pClassInfo, &retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
inline PTR_BYTE GetDynamicEntryNonGCStaticsBasePointer(DWORD n, PTR_LoaderAllocator pLoaderAllocator)
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
NOTHROW;
|
||||
GC_NOTRIGGER;
|
||||
MODE_COOPERATIVE;
|
||||
SUPPORTS_DAC;
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
|
||||
if (n >= m_aDynamicEntries)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DynamicClassInfo* pClassInfo = GetDynamicClassInfo(n);
|
||||
if (!pClassInfo->m_pDynamicEntry)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PTR_BYTE retval = NULL;
|
||||
|
||||
GET_DYNAMICENTRY_NONGCSTATICS_BASEPOINTER(pLoaderAllocator, pClassInfo, &retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
FORCEINLINE PTR_DynamicClassInfo GetDynamicClassInfoIfInitialized(DWORD n)
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
|
||||
// m_aDynamicEntries is set last, it needs to be checked first
|
||||
if (n >= m_aDynamicEntries)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_ASSERTE(m_pDynamicClassTable.Load() != NULL);
|
||||
PTR_DynamicClassInfo pDynamicClassInfo = (PTR_DynamicClassInfo)(m_pDynamicClassTable.Load() + n);
|
||||
|
||||
// INITIALIZED_FLAG is set last, it needs to be checked first
|
||||
if ((pDynamicClassInfo->m_dwFlags & ClassInitFlags::INITIALIZED_FLAG) == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PREFIX_ASSUME(pDynamicClassInfo != NULL);
|
||||
return pDynamicClassInfo;
|
||||
}
|
||||
|
||||
// iClassIndex is slightly expensive to compute, so if we already know
|
||||
// it, we can use this helper
|
||||
inline BOOL IsClassInitialized(MethodTable* pMT, DWORD iClassIndex = (DWORD)-1)
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
return (GetClassFlags(pMT, iClassIndex) & ClassInitFlags::INITIALIZED_FLAG) != 0;
|
||||
}
|
||||
|
||||
inline BOOL IsPrecomputedClassInitialized(DWORD classID)
|
||||
{
|
||||
return GetPrecomputedStaticsClassData()[classID] & ClassInitFlags::INITIALIZED_FLAG;
|
||||
}
|
||||
|
||||
inline BOOL IsClassAllocated(MethodTable* pMT, DWORD iClassIndex = (DWORD)-1)
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
return (GetClassFlags(pMT, iClassIndex) & ClassInitFlags::ALLOCATECLASS_FLAG) != 0;
|
||||
}
|
||||
|
||||
BOOL IsClassInitError(MethodTable* pMT, DWORD iClassIndex = (DWORD)-1)
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
return (GetClassFlags(pMT, iClassIndex) & ClassInitFlags::ERROR_FLAG) != 0;
|
||||
}
|
||||
|
||||
void SetClassInitialized(MethodTable* pMT);
|
||||
void SetClassInitError(MethodTable* pMT);
|
||||
|
||||
void EnsureDynamicClassIndex(DWORD dwID);
|
||||
|
||||
void AllocateDynamicClass(MethodTable *pMT);
|
||||
|
||||
void PopulateClass(MethodTable *pMT);
|
||||
|
||||
#ifdef DACCESS_COMPILE
|
||||
void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
|
||||
#endif
|
||||
|
||||
static DWORD OffsetOfDataBlob()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
return offsetof(DomainLocalModule, m_pDataBlob);
|
||||
}
|
||||
|
||||
FORCEINLINE MethodTable * GetMethodTableFromClassDomainID(DWORD dwClassDomainID)
|
||||
{
|
||||
DWORD rid = (DWORD)(dwClassDomainID) + 1;
|
||||
TypeHandle th = GetDomainAssembly()->GetModule()->LookupTypeDef(TokenFromRid(rid, mdtTypeDef));
|
||||
_ASSERTE(!th.IsNull());
|
||||
MethodTable * pMT = th.AsMethodTable();
|
||||
PREFIX_ASSUME(pMT != NULL);
|
||||
return pMT;
|
||||
}
|
||||
|
||||
private:
|
||||
friend void EmitFastGetSharedStaticBase(CPUSTUBLINKER *psl, CodeLabel *init, bool bCCtorCheck);
|
||||
|
||||
void SetClassFlags(MethodTable* pMT, DWORD dwFlags);
|
||||
DWORD GetClassFlags(MethodTable* pMT, DWORD iClassIndex);
|
||||
|
||||
PTR_DomainAssembly m_pDomainAssembly;
|
||||
VolatilePtr<DynamicClassInfo, PTR_DynamicClassInfo> m_pDynamicClassTable; // used for generics and reflection.emit in memory
|
||||
Volatile<SIZE_T> m_aDynamicEntries; // number of entries in dynamic table
|
||||
VolatilePtr<UMEntryThunk> m_pADThunkTable;
|
||||
PTR_OBJECTREF m_pGCStatics; // Handle to GC statics of the module
|
||||
|
||||
// In addition to storing the ModuleIndex in the Module class, we also
|
||||
// keep a copy of the ModuleIndex in the DomainLocalModule class. This
|
||||
// allows the thread static JIT helpers to quickly convert a pointer to
|
||||
// a DomainLocalModule into a ModuleIndex.
|
||||
ModuleIndex m_ModuleIndex;
|
||||
|
||||
// Note that the static offset calculation in code:Module::BuildStaticsOffsets takes the offset m_pDataBlob
|
||||
// into consideration for alignment so we do not need any padding to ensure that the start of the data blob is aligned
|
||||
|
||||
BYTE m_pDataBlob[0]; // First byte of the statics blob
|
||||
|
||||
// Layout of m_pDataBlob is:
|
||||
// ClassInit bytes (hold flags for cctor run, cctor error, etc)
|
||||
// Non GC Statics
|
||||
|
||||
public:
|
||||
|
||||
// The Module class need to be able to initialized ModuleIndex,
|
||||
// so for now I will make it a friend..
|
||||
friend class Module;
|
||||
|
||||
FORCEINLINE ModuleIndex GetModuleIndex()
|
||||
{
|
||||
LIMITED_METHOD_DAC_CONTRACT;
|
||||
return m_ModuleIndex;
|
||||
}
|
||||
|
||||
}; // struct DomainLocalModule
|
||||
|
||||
#define OFFSETOF__DomainLocalModule__m_pDataBlob_ (6 * TARGET_POINTER_SIZE)
|
||||
#ifdef FEATURE_64BIT_ALIGNMENT
|
||||
#define OFFSETOF__DomainLocalModule__NormalDynamicEntry__m_pDataBlob (TARGET_POINTER_SIZE /* m_pGCStatics */ + TARGET_POINTER_SIZE /* m_padding */)
|
||||
#else
|
||||
#define OFFSETOF__DomainLocalModule__NormalDynamicEntry__m_pDataBlob TARGET_POINTER_SIZE /* m_pGCStatics */
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
@ -604,60 +204,6 @@ FORCEINLINE void PinnedHeapHandleBlockHolder__StaticFree(PinnedHeapHandleBlockH
|
|||
pHolder->FreeData();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// The large heap handle bucket class is used to contain handles allocated
|
||||
// from an array contained in the large heap.
|
||||
class ThreadStaticHandleBucket
|
||||
{
|
||||
public:
|
||||
// Constructor and desctructor.
|
||||
ThreadStaticHandleBucket(ThreadStaticHandleBucket *pNext, DWORD Size, BaseDomain *pDomain);
|
||||
~ThreadStaticHandleBucket();
|
||||
|
||||
// This returns the next bucket.
|
||||
ThreadStaticHandleBucket *GetNext()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
|
||||
return m_pNext;
|
||||
}
|
||||
|
||||
// Allocate handles from the bucket.
|
||||
OBJECTHANDLE GetHandles();
|
||||
|
||||
private:
|
||||
ThreadStaticHandleBucket *m_pNext;
|
||||
int m_ArraySize;
|
||||
OBJECTHANDLE m_hndHandleArray;
|
||||
};
|
||||
|
||||
|
||||
// The large heap handle table is used to allocate handles that are pointers
|
||||
// to objects stored in an array in the large object heap.
|
||||
class ThreadStaticHandleTable
|
||||
{
|
||||
public:
|
||||
// Constructor and desctructor.
|
||||
ThreadStaticHandleTable(BaseDomain *pDomain);
|
||||
~ThreadStaticHandleTable();
|
||||
|
||||
// Allocate handles from the large heap handle table.
|
||||
OBJECTHANDLE AllocateHandles(DWORD nRequested);
|
||||
|
||||
private:
|
||||
// The buckets of object handles.
|
||||
ThreadStaticHandleBucket *m_pHead;
|
||||
|
||||
// We need to know the containing domain so we know where to allocate handles
|
||||
BaseDomain *m_pDomain;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Base class for domains. It provides an abstract way of finding the first assembly and
|
||||
// for creating assemblies in the domain. The system domain only has one assembly, it
|
||||
|
@ -675,12 +221,15 @@ private:
|
|||
#define LOW_FREQUENCY_HEAP_RESERVE_SIZE (3 * GetOsPageSize())
|
||||
#define LOW_FREQUENCY_HEAP_COMMIT_SIZE (1 * GetOsPageSize())
|
||||
|
||||
#define HIGH_FREQUENCY_HEAP_RESERVE_SIZE (10 * GetOsPageSize())
|
||||
#define HIGH_FREQUENCY_HEAP_RESERVE_SIZE (8 * GetOsPageSize())
|
||||
#define HIGH_FREQUENCY_HEAP_COMMIT_SIZE (1 * GetOsPageSize())
|
||||
|
||||
#define STUB_HEAP_RESERVE_SIZE (3 * GetOsPageSize())
|
||||
#define STUB_HEAP_COMMIT_SIZE (1 * GetOsPageSize())
|
||||
|
||||
#define STATIC_FIELD_HEAP_RESERVE_SIZE (2 * GetOsPageSize())
|
||||
#define STATIC_FIELD_HEAP_COMMIT_SIZE (1 * GetOsPageSize())
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// PE File List lock - for creating list locks on PE files
|
||||
// --------------------------------------------------------------------------------
|
||||
|
@ -938,15 +487,6 @@ public:
|
|||
return m_pMngStdInterfacesInfo;
|
||||
}
|
||||
#endif // FEATURE_COMINTEROP
|
||||
#ifdef _DEBUG
|
||||
BOOL OwnDomainLocalBlockLock()
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
|
||||
return m_DomainLocalBlockCrst.OwnedByCurrentThread();
|
||||
}
|
||||
#endif
|
||||
|
||||
//****************************************************************************************
|
||||
// Get the class init lock. The method is limited to friends because inappropriate use
|
||||
// will cause deadlocks in the system
|
||||
|
@ -980,9 +520,9 @@ public:
|
|||
|
||||
// Returns an array of OBJECTREF* that can be used to store domain specific data.
|
||||
// Statics and reflection info (Types, MemberInfo,..) are stored this way
|
||||
// If ppLazyAllocate != 0, allocation will only take place if *ppLazyAllocate != 0 (and the allocation
|
||||
// If pStaticsInfo != 0, allocation will only take place if GC statics in the DynamicStaticsInfo are NULL (and the allocation
|
||||
// will be properly serialized)
|
||||
OBJECTREF *AllocateObjRefPtrsInLargeTable(int nRequested, OBJECTREF** ppLazyAllocate = NULL);
|
||||
OBJECTREF *AllocateObjRefPtrsInLargeTable(int nRequested, DynamicStaticsInfo* pStaticsInfo = NULL, MethodTable *pMTToFillWithStaticBoxes = NULL);
|
||||
|
||||
//****************************************************************************************
|
||||
// Handles
|
||||
|
@ -1085,10 +625,10 @@ public:
|
|||
return &m_crstLoaderAllocatorReferences;
|
||||
}
|
||||
|
||||
CrstExplicitInit* GetStaticBoxInitLock()
|
||||
CrstExplicitInit* GetGenericDictionaryExpansionLock()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
return &m_crstStaticBoxInitLock;
|
||||
return &m_crstGenericDictionaryExpansionLock;
|
||||
}
|
||||
|
||||
static CrstStatic* GetMethodTableExposedClassObjectLock()
|
||||
|
@ -1112,10 +652,9 @@ protected:
|
|||
PEFileListLock m_FileLoadLock; // Protects the list of assemblies in the domain
|
||||
CrstExplicitInit m_DomainCrst; // General Protection for the Domain
|
||||
CrstExplicitInit m_DomainCacheCrst; // Protects the Assembly and Unmanaged caches
|
||||
CrstExplicitInit m_DomainLocalBlockCrst;
|
||||
// Used to protect the reference lists in the collectible loader allocators attached to this appdomain
|
||||
CrstExplicitInit m_crstLoaderAllocatorReferences;
|
||||
CrstExplicitInit m_crstStaticBoxInitLock;
|
||||
CrstExplicitInit m_crstGenericDictionaryExpansionLock;
|
||||
|
||||
//#AssemblyListLock
|
||||
// Used to protect the assembly list. Taken also by GC or debugger thread, therefore we have to avoid
|
||||
|
@ -1184,17 +723,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class DomainLocalBlockLockHolder : public CrstHolder
|
||||
{
|
||||
public:
|
||||
DomainLocalBlockLockHolder(BaseDomain *pD)
|
||||
: CrstHolder(&pD->m_DomainLocalBlockCrst)
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
}
|
||||
};
|
||||
friend class DomainLocalBlockLockHolder;
|
||||
|
||||
class LoadLockHolder : public PEFileListLockHolder
|
||||
{
|
||||
public:
|
||||
|
@ -1218,21 +746,8 @@ public:
|
|||
private:
|
||||
TypeIDMap m_typeIDMap;
|
||||
|
||||
// MethodTable to `typeIndex` map. `typeIndex` is embedded in the code during codegen.
|
||||
// During execution corresponding thread static data blocks are stored in `t_NonGCThreadStaticBlocks`
|
||||
// and `t_GCThreadStaticBlocks` array at the `typeIndex`.
|
||||
TypeIDMap m_NonGCThreadStaticBlockTypeIDMap;
|
||||
TypeIDMap m_GCThreadStaticBlockTypeIDMap;
|
||||
|
||||
public:
|
||||
|
||||
void InitThreadStaticBlockTypeMap();
|
||||
|
||||
UINT32 GetNonGCThreadStaticTypeIndex(PTR_MethodTable pMT);
|
||||
UINT32 GetGCThreadStaticTypeIndex(PTR_MethodTable pMT);
|
||||
|
||||
PTR_MethodTable LookupNonGCThreadStaticBlockType(UINT32 id);
|
||||
PTR_MethodTable LookupGCThreadStaticBlockType(UINT32 id);
|
||||
|
||||
UINT32 GetTypeID(PTR_MethodTable pMT);
|
||||
UINT32 LookupTypeID(PTR_MethodTable pMT);
|
||||
|
@ -1921,11 +1436,11 @@ public:
|
|||
#endif // DEBUGGING_SUPPORTED
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
OBJECTREF* AllocateStaticFieldObjRefPtrs(int nRequested, OBJECTREF** ppLazyAllocate = NULL)
|
||||
OBJECTREF* AllocateStaticFieldObjRefPtrs(int nRequested)
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
|
||||
return AllocateObjRefPtrsInLargeTable(nRequested, ppLazyAllocate);
|
||||
return AllocateObjRefPtrsInLargeTable(nRequested);
|
||||
}
|
||||
#endif // DACCESS_COMPILE
|
||||
|
||||
|
|
|
@ -78,14 +78,5 @@ inline PTR_LoaderHeap AppDomain::GetStubHeap()
|
|||
return GetLoaderAllocator()->GetStubHeap();
|
||||
}
|
||||
|
||||
/* static */
|
||||
inline DWORD DomainLocalModule::DynamicEntry::GetOffsetOfDataBlob()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
_ASSERTE(DWORD(offsetof(NormalDynamicEntry, m_pDataBlob)) == offsetof(NormalDynamicEntry, m_pDataBlob));
|
||||
return (DWORD)offsetof(NormalDynamicEntry, m_pDataBlob);
|
||||
}
|
||||
|
||||
|
||||
#endif // _APPDOMAIN_I
|
||||
|
||||
|
|
|
@ -142,13 +142,6 @@ ASMCONSTANTS_C_ASSERT(Thread__m_fPreemptiveGCDisabled == offsetof(Thread, m_fPre
|
|||
ASMCONSTANTS_C_ASSERT(Thread__m_pFrame == offsetof(Thread, m_pFrame));
|
||||
#define Thread_m_pFrame Thread__m_pFrame
|
||||
|
||||
#define DomainLocalModule__m_pDataBlob 0x18
|
||||
ASMCONSTANTS_C_ASSERT(DomainLocalModule__m_pDataBlob == offsetof(DomainLocalModule, m_pDataBlob));
|
||||
|
||||
#define DomainLocalModule__m_pGCStatics 0x10
|
||||
ASMCONSTANTS_C_ASSERT(DomainLocalModule__m_pGCStatics == offsetof(DomainLocalModule, m_pGCStatics));
|
||||
|
||||
|
||||
#define ASM__VTABLE_SLOTS_PER_CHUNK 8
|
||||
ASMCONSTANTS_C_ASSERT(ASM__VTABLE_SLOTS_PER_CHUNK == VTABLE_SLOTS_PER_CHUNK)
|
||||
|
||||
|
|
|
@ -586,71 +586,6 @@ LOCAL_LABEL(stackProbe_loop):
|
|||
NESTED_END JIT_RareDisableHelper, _TEXT
|
||||
|
||||
|
||||
#ifdef FEATURE_CORECLR
|
||||
//
|
||||
// JIT Static access helpers for single appdomain case
|
||||
//
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// void* JIT_GetSharedNonGCStaticBase(SIZE_T moduleDomainID, DWORD dwClassDomainID)
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedNonGCStaticBase_SingleAppDomain, _TEXT
|
||||
|
||||
// If class is not initialized, bail to C++ helper
|
||||
add r2, r0, #DomainLocalModule__m_pDataBlob
|
||||
ldrb r2, [r2, r1]
|
||||
tst r2, #1
|
||||
beq LOCAL_LABEL(CallCppHelper1)
|
||||
|
||||
bx lr
|
||||
|
||||
LOCAL_LABEL(CallCppHelper1):
|
||||
// Tail call JIT_GetSharedNonGCStaticBase_Helper
|
||||
b C_FUNC(JIT_GetSharedNonGCStaticBase_Helper)
|
||||
LEAF_END JIT_GetSharedNonGCStaticBase_SingleAppDomain, _TEXT
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// void* JIT_GetSharedNonGCStaticBaseNoCtor(SIZE_T moduleDomainID, DWORD dwClassDomainID)
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
|
||||
bx lr
|
||||
LEAF_END JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// void* JIT_GetSharedGCStaticBase(SIZE_T moduleDomainID, DWORD dwClassDomainID)
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedGCStaticBase_SingleAppDomain, _TEXT
|
||||
|
||||
// If class is not initialized, bail to C++ helper
|
||||
add r2, r0, #DomainLocalModule__m_pDataBlob
|
||||
ldrb r2, [r2, r1]
|
||||
tst r2, #1
|
||||
beq LOCAL_LABEL(CallCppHelper3)
|
||||
|
||||
ldr r0, [r0, #DomainLocalModule__m_pGCStatics]
|
||||
bx lr
|
||||
|
||||
LOCAL_LABEL(CallCppHelper3):
|
||||
// Tail call Jit_GetSharedGCStaticBase_Helper
|
||||
b C_FUNC(JIT_GetSharedGCStaticBase_Helper)
|
||||
LEAF_END JIT_GetSharedGCStaticBase_SingleAppDomain, _TEXT
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// void* JIT_GetSharedGCStaticBaseNoCtor(SIZE_T moduleDomainID, DWORD dwClassDomainID)
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
|
||||
ldr r0, [r0, #DomainLocalModule__m_pGCStatics]
|
||||
bx lr
|
||||
LEAF_END JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define __wbScratch r3
|
||||
#define pShadow r7
|
||||
|
||||
|
|
|
@ -1023,11 +1023,6 @@ inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode, bool
|
|||
//
|
||||
// Create alias for optimized implementations of helpers provided on this platform
|
||||
//
|
||||
#define JIT_GetSharedGCStaticBase JIT_GetSharedGCStaticBase_SingleAppDomain
|
||||
#define JIT_GetSharedNonGCStaticBase JIT_GetSharedNonGCStaticBase_SingleAppDomain
|
||||
#define JIT_GetSharedGCStaticBaseNoCtor JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain
|
||||
#define JIT_GetSharedNonGCStaticBaseNoCtor JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
|
|
|
@ -191,11 +191,13 @@ ASMCONSTANTS_C_ASSERT(MethodDesc_ALIGNMENT_SHIFT == MethodDesc::ALIGNMENT_SHIFT)
|
|||
ASMCONSTANTS_C_ASSERT(ResolveCacheElem__target == offsetof(ResolveCacheElem, target));
|
||||
ASMCONSTANTS_C_ASSERT(ResolveCacheElem__pNext == offsetof(ResolveCacheElem, pNext));
|
||||
|
||||
#define DomainLocalModule__m_pDataBlob 0x30
|
||||
#define DomainLocalModule__m_pGCStatics 0x20
|
||||
ASMCONSTANTS_C_ASSERT(DomainLocalModule__m_pDataBlob == offsetof(DomainLocalModule, m_pDataBlob));
|
||||
ASMCONSTANTS_C_ASSERT(DomainLocalModule__m_pGCStatics == offsetof(DomainLocalModule, m_pGCStatics));
|
||||
#define OFFSETOF__DynamicStaticsInfo__m_pNonGCStatics 0x8
|
||||
ASMCONSTANTS_C_ASSERT(OFFSETOF__DynamicStaticsInfo__m_pNonGCStatics
|
||||
== offsetof(DynamicStaticsInfo, m_pNonGCStatics));
|
||||
|
||||
#define OFFSETOF__DynamicStaticsInfo__m_pGCStatics 0
|
||||
ASMCONSTANTS_C_ASSERT(OFFSETOF__DynamicStaticsInfo__m_pGCStatics
|
||||
== offsetof(DynamicStaticsInfo, m_pGCStatics));
|
||||
|
||||
// For JIT_PInvokeBegin and JIT_PInvokeEnd helpers
|
||||
#define Frame__m_Next 0x08
|
||||
|
|
|
@ -659,58 +659,34 @@ DynamicHelper DynamicHelperFrameFlags_ObjectArg | DynamicHelperFrameFlags_Object
|
|||
//
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// void* JIT_GetSharedNonGCStaticBase(SIZE_T moduleDomainID, DWORD dwClassDomainID)
|
||||
// void* JIT_GetDynamicNonGCStaticBase(DynamicStaticsInfo* pStaticsInfo)
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedNonGCStaticBase_SingleAppDomain, _TEXT
|
||||
LEAF_ENTRY JIT_GetDynamicNonGCStaticBase_SingleAppDomain, _TEXT
|
||||
// If class is not initialized, bail to C++ helper
|
||||
add x2, x0, #DomainLocalModule__m_pDataBlob
|
||||
ldrb w2, [x2, w1, UXTW]
|
||||
tst w2, #1
|
||||
beq LOCAL_LABEL(JIT_GetSharedNonGCStaticBase_SingleAppDomain_CallHelper)
|
||||
|
||||
ldr x1, [x0, #OFFSETOF__DynamicStaticsInfo__m_pNonGCStatics]
|
||||
tbnz x1, #0, LOCAL_LABEL(JIT_GetDynamicNonGCStaticBase_SingleAppDomain_CallHelper)
|
||||
mov x0, x1
|
||||
ret lr
|
||||
|
||||
LOCAL_LABEL(JIT_GetSharedNonGCStaticBase_SingleAppDomain_CallHelper):
|
||||
// Tail call JIT_GetSharedNonGCStaticBase_Helper
|
||||
b C_FUNC(JIT_GetSharedNonGCStaticBase_Helper)
|
||||
LEAF_END JIT_GetSharedNonGCStaticBase_SingleAppDomain, _TEXT
|
||||
|
||||
LOCAL_LABEL(JIT_GetDynamicNonGCStaticBase_SingleAppDomain_CallHelper):
|
||||
// Tail call JIT_GetDynamicNonGCStaticBase_Portable
|
||||
b C_FUNC(JIT_GetDynamicNonGCStaticBase_Portable)
|
||||
LEAF_END JIT_GetDynamicNonGCStaticBase_SingleAppDomain, _TEXT
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// void* JIT_GetSharedNonGCStaticBaseNoCtor(SIZE_T moduleDomainID, DWORD dwClassDomainID)
|
||||
// void* JIT_GetDynamicGCStaticBase(DynamicStaticsInfo* pStaticsInfo)
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
ret lr
|
||||
LEAF_END JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// void* JIT_GetSharedGCStaticBase(SIZE_T moduleDomainID, DWORD dwClassDomainID)
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedGCStaticBase_SingleAppDomain, _TEXT
|
||||
LEAF_ENTRY JIT_GetDynamicGCStaticBase_SingleAppDomain, _TEXT
|
||||
// If class is not initialized, bail to C++ helper
|
||||
add x2, x0, #DomainLocalModule__m_pDataBlob
|
||||
ldrb w2, [x2, w1, UXTW]
|
||||
tst w2, #1
|
||||
beq LOCAL_LABEL(JIT_GetSharedGCStaticBase_SingleAppDomain_CallHelper)
|
||||
|
||||
ldr x0, [x0, #DomainLocalModule__m_pGCStatics]
|
||||
ldr x1, [x0, #OFFSETOF__DynamicStaticsInfo__m_pGCStatics]
|
||||
tbnz x1, #0, LOCAL_LABEL(JIT_GetDynamicGCStaticBase_SingleAppDomain_CallHelper)
|
||||
mov x0, x1
|
||||
ret lr
|
||||
|
||||
LOCAL_LABEL(JIT_GetSharedGCStaticBase_SingleAppDomain_CallHelper):
|
||||
// Tail call Jit_GetSharedGCStaticBase_Helper
|
||||
b C_FUNC(JIT_GetSharedGCStaticBase_Helper)
|
||||
LEAF_END JIT_GetSharedGCStaticBase_SingleAppDomain, _TEXT
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// void* JIT_GetSharedGCStaticBaseNoCtor(SIZE_T moduleDomainID, DWORD dwClassDomainID)
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
ldr x0, [x0, #DomainLocalModule__m_pGCStatics]
|
||||
ret lr
|
||||
LEAF_END JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
|
||||
LOCAL_LABEL(JIT_GetDynamicGCStaticBase_SingleAppDomain_CallHelper):
|
||||
// Tail call JIT_GetDynamicGCStaticBase_Portable
|
||||
b C_FUNC(JIT_GetDynamicGCStaticBase_Portable)
|
||||
LEAF_END JIT_GetDynamicGCStaticBase_SingleAppDomain, _TEXT
|
||||
|
||||
#ifdef PROFILING_SUPPORTED
|
||||
|
||||
|
|
|
@ -46,8 +46,8 @@
|
|||
IMPORT $g_GCShadowEnd
|
||||
#endif // WRITE_BARRIER_CHECK
|
||||
|
||||
IMPORT JIT_GetSharedNonGCStaticBase_Helper
|
||||
IMPORT JIT_GetSharedGCStaticBase_Helper
|
||||
IMPORT JIT_GetDynamicNonGCStaticBase_Portable
|
||||
IMPORT JIT_GetDynamicGCStaticBase_Portable
|
||||
|
||||
#ifdef FEATURE_COMINTEROP
|
||||
IMPORT CLRToCOMWorker
|
||||
|
@ -1026,59 +1026,35 @@ Fail
|
|||
;
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; void* JIT_GetSharedNonGCStaticBase(SIZE_T moduleDomainID, DWORD dwClassDomainID)
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedNonGCStaticBase_SingleAppDomain
|
||||
; void* JIT_GetDynamicNonGCStaticBase(DynamicStaticsInfo *dynamicInfo)
|
||||
|
||||
LEAF_ENTRY JIT_GetDynamicNonGCStaticBase_SingleAppDomain
|
||||
; If class is not initialized, bail to C++ helper
|
||||
add x2, x0, #DomainLocalModule__m_pDataBlob
|
||||
ldrb w2, [x2, w1]
|
||||
tst w2, #1
|
||||
beq CallHelper1
|
||||
|
||||
ldr x1, [x0, #OFFSETOF__DynamicStaticsInfo__m_pNonGCStatics]
|
||||
tbnz x1, #0, CallHelper1
|
||||
mov x0, x1
|
||||
ret lr
|
||||
|
||||
CallHelper1
|
||||
; Tail call JIT_GetSharedNonGCStaticBase_Helper
|
||||
b JIT_GetSharedNonGCStaticBase_Helper
|
||||
; Tail call JIT_GetDynamicNonGCStaticBase_Portable
|
||||
b JIT_GetDynamicNonGCStaticBase_Portable
|
||||
LEAF_END
|
||||
|
||||
; void* JIT_GetDynamicGCStaticBase(DynamicStaticsInfo *dynamicInfo)
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; void* JIT_GetSharedNonGCStaticBaseNoCtor(SIZE_T moduleDomainID, DWORD dwClassDomainID)
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain
|
||||
ret lr
|
||||
LEAF_END
|
||||
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; void* JIT_GetSharedGCStaticBase(SIZE_T moduleDomainID, DWORD dwClassDomainID)
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedGCStaticBase_SingleAppDomain
|
||||
LEAF_ENTRY JIT_GetDynamicGCStaticBase_SingleAppDomain
|
||||
; If class is not initialized, bail to C++ helper
|
||||
add x2, x0, #DomainLocalModule__m_pDataBlob
|
||||
ldrb w2, [x2, w1]
|
||||
tst w2, #1
|
||||
beq CallHelper2
|
||||
|
||||
ldr x0, [x0, #DomainLocalModule__m_pGCStatics]
|
||||
ldr x1, [x0, #OFFSETOF__DynamicStaticsInfo__m_pGCStatics]
|
||||
tbnz x1, #0, CallHelper2
|
||||
mov x0, x1
|
||||
ret lr
|
||||
|
||||
CallHelper2
|
||||
; Tail call Jit_GetSharedGCStaticBase_Helper
|
||||
b JIT_GetSharedGCStaticBase_Helper
|
||||
; Tail call JIT_GetDynamicGCStaticBase_Portable
|
||||
b JIT_GetDynamicGCStaticBase_Portable
|
||||
LEAF_END
|
||||
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; void* JIT_GetSharedGCStaticBaseNoCtor(SIZE_T moduleDomainID, DWORD dwClassDomainID)
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain
|
||||
ldr x0, [x0, #DomainLocalModule__m_pGCStatics]
|
||||
ret lr
|
||||
LEAF_END
|
||||
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; __declspec(naked) void F_CALL_CONV JIT_WriteBarrier_Callable(Object **dst, Object* val)
|
||||
LEAF_ENTRY JIT_WriteBarrier_Callable
|
||||
|
|
|
@ -131,10 +131,8 @@ inline unsigned StackElemSize(unsigned parmSize, bool isValueType, bool isFloatH
|
|||
//
|
||||
// Create alias for optimized implementations of helpers provided on this platform
|
||||
//
|
||||
#define JIT_GetSharedGCStaticBase JIT_GetSharedGCStaticBase_SingleAppDomain
|
||||
#define JIT_GetSharedNonGCStaticBase JIT_GetSharedNonGCStaticBase_SingleAppDomain
|
||||
#define JIT_GetSharedGCStaticBaseNoCtor JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain
|
||||
#define JIT_GetSharedNonGCStaticBaseNoCtor JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain
|
||||
#define JIT_GetDynamicGCStaticBase JIT_GetDynamicGCStaticBase_SingleAppDomain
|
||||
#define JIT_GetDynamicNonGCStaticBase JIT_GetDynamicNonGCStaticBase_SingleAppDomain
|
||||
|
||||
//**********************************************************************
|
||||
// Frames
|
||||
|
|
|
@ -334,7 +334,7 @@ MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementTy
|
|||
MethodTable* pMT = (MethodTable *) pMTHead;
|
||||
|
||||
// Allocate the private data block ("private" during runtime in the ngen'ed case).
|
||||
pMT->AllocateAuxiliaryData(pAllocator, this, pamTracker, false, static_cast<WORD>(numNonVirtualSlots));
|
||||
pMT->AllocateAuxiliaryData(pAllocator, this, pamTracker, MethodTableStaticsFlags::None, static_cast<WORD>(numNonVirtualSlots));
|
||||
pMT->SetLoaderAllocator(pAllocator);
|
||||
pMT->SetModule(elemTypeHnd.GetModule());
|
||||
|
||||
|
@ -406,7 +406,7 @@ MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementTy
|
|||
}
|
||||
#endif // FEATURE_TYPEEQUIVALENCE
|
||||
|
||||
_ASSERTE(pMT->IsClassPreInited());
|
||||
pMT->SetClassInited();
|
||||
|
||||
// Set BaseSize to be size of non-data portion of the array
|
||||
DWORD baseSize = ARRAYBASE_BASESIZE;
|
||||
|
|
|
@ -421,7 +421,6 @@ void Module::Initialize(AllocMemTracker *pamTracker, LPCWSTR szName)
|
|||
m_FixupCrst.Init(CrstModuleFixup, (CrstFlags)(CRST_HOST_BREAKABLE|CRST_REENTRANCY));
|
||||
m_InstMethodHashTableCrst.Init(CrstInstMethodHashTable, CRST_REENTRANCY);
|
||||
m_ISymUnmanagedReaderCrst.Init(CrstISymUnmanagedReader, CRST_DEBUGGER_THREAD);
|
||||
m_DictionaryCrst.Init(CrstDomainLocalBlock);
|
||||
|
||||
AllocateMaps();
|
||||
m_dwTransientFlags &= ~((DWORD)CLASSES_FREED); // Set flag indicating LookupMaps are now in a consistent and destructable state
|
||||
|
@ -473,19 +472,12 @@ void Module::Initialize(AllocMemTracker *pamTracker, LPCWSTR szName)
|
|||
m_pInstMethodHashTable = InstMethodHashTable::Create(GetLoaderAllocator(), this, PARAMMETHODS_HASH_BUCKETS, pamTracker);
|
||||
}
|
||||
|
||||
// this will be initialized a bit later.
|
||||
m_ModuleID = NULL;
|
||||
m_ModuleIndex.m_dwIndex = (SIZE_T)-1;
|
||||
|
||||
// These will be initialized in NotifyProfilerLoadFinished, set them to
|
||||
// a safe initial value now.
|
||||
m_dwTypeCount = 0;
|
||||
m_dwExportedTypeCount = 0;
|
||||
m_dwCustomAttributeCount = 0;
|
||||
|
||||
// Prepare statics that are known at module load time
|
||||
AllocateStatics(pamTracker);
|
||||
|
||||
if (m_AssemblyRefByNameTable == NULL)
|
||||
{
|
||||
Module::CreateAssemblyRefByNameTable(pamTracker);
|
||||
|
@ -765,10 +757,6 @@ void Module::Destruct()
|
|||
#if defined(PROFILING_SUPPORTED)
|
||||
delete m_pJitInlinerTrackingMap;
|
||||
#endif
|
||||
|
||||
// If this module was loaded as domain-specific, then
|
||||
// we must free its ModuleIndex so that it can be reused
|
||||
FreeModuleIndex();
|
||||
}
|
||||
|
||||
bool Module::NeedsGlobalMethodTable()
|
||||
|
@ -853,365 +841,12 @@ DomainAssembly* Module::GetDomainAssembly()
|
|||
{
|
||||
LIMITED_METHOD_DAC_CONTRACT;
|
||||
|
||||
return dac_cast<PTR_DomainAssembly>(m_ModuleID->GetDomainAssembly());
|
||||
return m_pDomainAssembly;
|
||||
}
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
#include "staticallocationhelpers.inl"
|
||||
|
||||
// Parses metadata and initializes offsets of per-class static blocks.
|
||||
void Module::BuildStaticsOffsets(AllocMemTracker *pamTracker)
|
||||
{
|
||||
STANDARD_VM_CONTRACT;
|
||||
|
||||
// Trade off here. We want a slot for each type. That way we can get to 2 bits per class and
|
||||
// index directly and not need a mapping from ClassID to MethodTable (we will use the RID
|
||||
// as the mapping)
|
||||
IMDInternalImport *pImport = GetMDImport();
|
||||
|
||||
DWORD * pRegularStaticOffsets = NULL;
|
||||
DWORD * pThreadStaticOffsets = NULL;
|
||||
|
||||
// Get the number of types/classes defined in this module. Add 1 to count the module itself
|
||||
DWORD dwNumTypes = pImport->GetCountWithTokenKind(mdtTypeDef) + 1; // +1 for module type
|
||||
|
||||
// [0] covers regular statics, [1] covers thread statics
|
||||
DWORD dwGCHandles[2] = { 0, 0 };
|
||||
|
||||
// Organization in memory of the static block
|
||||
//
|
||||
//
|
||||
// | GC Statics |
|
||||
// |
|
||||
// |
|
||||
// | Class Data (one byte per class) | pointer to gc statics | primitive type statics |
|
||||
//
|
||||
//
|
||||
#ifndef CROSSBITNESS_COMPILE
|
||||
// The assertions must hold in every non-crossbitness scenario
|
||||
_ASSERTE(OFFSETOF__DomainLocalModule__m_pDataBlob_ == DomainLocalModule::OffsetOfDataBlob());
|
||||
_ASSERTE(OFFSETOF__ThreadLocalModule__m_pDataBlob == ThreadLocalModule::OffsetOfDataBlob());
|
||||
#endif
|
||||
|
||||
DWORD dwNonGCBytes[2] = {
|
||||
DomainLocalModule::OffsetOfDataBlob() + (DWORD)(sizeof(BYTE)*dwNumTypes),
|
||||
ThreadLocalModule::OffsetOfDataBlob() + (DWORD)(sizeof(BYTE)*dwNumTypes)
|
||||
};
|
||||
|
||||
HENUMInternalHolder hTypeEnum(pImport);
|
||||
hTypeEnum.EnumAllInit(mdtTypeDef);
|
||||
|
||||
mdTypeDef type;
|
||||
// Parse each type of the class
|
||||
while (pImport->EnumNext(&hTypeEnum, &type))
|
||||
{
|
||||
// Set offset for this type
|
||||
DWORD dwIndex = RidFromToken(type) - 1;
|
||||
|
||||
// [0] covers regular statics, [1] covers thread statics
|
||||
DWORD dwAlignment[2] = { 1, 1 };
|
||||
DWORD dwClassNonGCBytes[2] = { 0, 0 };
|
||||
DWORD dwClassGCHandles[2] = { 0, 0 };
|
||||
|
||||
// need to check if the type is generic and if so exclude it from iteration as we don't know the size
|
||||
if (!m_pTypeGenericInfoMap->IsGeneric(type, pImport))
|
||||
{
|
||||
HENUMInternalHolder hFieldEnum(pImport);
|
||||
hFieldEnum.EnumInit(mdtFieldDef, type);
|
||||
|
||||
mdFieldDef field;
|
||||
// Parse each field of the type
|
||||
while (pImport->EnumNext(&hFieldEnum, &field))
|
||||
{
|
||||
BOOL fSkip = FALSE;
|
||||
|
||||
CorElementType ElementType = ELEMENT_TYPE_END;
|
||||
mdToken tkValueTypeToken = 0;
|
||||
int kk; // Use one set of variables for regular statics, and the other set for thread statics
|
||||
|
||||
fSkip = GetStaticFieldElementTypeForFieldDef(this, pImport, field, &ElementType, &tkValueTypeToken, &kk);
|
||||
if (fSkip)
|
||||
continue;
|
||||
|
||||
// We account for "regular statics" and "thread statics" separately.
|
||||
// Currently we are lumping RVA into "regular statics",
|
||||
// but we probably shouldn't.
|
||||
switch (ElementType)
|
||||
{
|
||||
case ELEMENT_TYPE_I1:
|
||||
case ELEMENT_TYPE_U1:
|
||||
case ELEMENT_TYPE_BOOLEAN:
|
||||
dwClassNonGCBytes[kk] += 1;
|
||||
break;
|
||||
case ELEMENT_TYPE_I2:
|
||||
case ELEMENT_TYPE_U2:
|
||||
case ELEMENT_TYPE_CHAR:
|
||||
dwAlignment[kk] = max<DWORD>(2, dwAlignment[kk]);
|
||||
dwClassNonGCBytes[kk] += 2;
|
||||
break;
|
||||
case ELEMENT_TYPE_I4:
|
||||
case ELEMENT_TYPE_U4:
|
||||
case ELEMENT_TYPE_R4:
|
||||
dwAlignment[kk] = max<DWORD>(4, dwAlignment[kk]);
|
||||
dwClassNonGCBytes[kk] += 4;
|
||||
break;
|
||||
case ELEMENT_TYPE_FNPTR:
|
||||
case ELEMENT_TYPE_PTR:
|
||||
case ELEMENT_TYPE_I:
|
||||
case ELEMENT_TYPE_U:
|
||||
dwAlignment[kk] = max<DWORD>((1 << LOG2_PTRSIZE), dwAlignment[kk]);
|
||||
dwClassNonGCBytes[kk] += (1 << LOG2_PTRSIZE);
|
||||
break;
|
||||
case ELEMENT_TYPE_I8:
|
||||
case ELEMENT_TYPE_U8:
|
||||
case ELEMENT_TYPE_R8:
|
||||
dwAlignment[kk] = max<DWORD>(8, dwAlignment[kk]);
|
||||
dwClassNonGCBytes[kk] += 8;
|
||||
break;
|
||||
case ELEMENT_TYPE_VAR:
|
||||
case ELEMENT_TYPE_MVAR:
|
||||
case ELEMENT_TYPE_STRING:
|
||||
case ELEMENT_TYPE_SZARRAY:
|
||||
case ELEMENT_TYPE_ARRAY:
|
||||
case ELEMENT_TYPE_CLASS:
|
||||
case ELEMENT_TYPE_OBJECT:
|
||||
dwClassGCHandles[kk] += 1;
|
||||
break;
|
||||
case ELEMENT_TYPE_VALUETYPE:
|
||||
// Statics for valuetypes where the valuetype is defined in this module are handled here. Other valuetype statics utilize the pessimistic model below.
|
||||
dwClassGCHandles[kk] += 1;
|
||||
break;
|
||||
case ELEMENT_TYPE_END:
|
||||
default:
|
||||
// The actual element type was ELEMENT_TYPE_VALUETYPE, but the as we don't want to load additional assemblies
|
||||
// to determine these static offsets, we've fallen back to a pessimistic model.
|
||||
if (tkValueTypeToken != 0)
|
||||
{
|
||||
// We'll have to be pessimistic here
|
||||
dwClassNonGCBytes[kk] += MAX_PRIMITIVE_FIELD_SIZE;
|
||||
dwAlignment[kk] = max<DWORD>(MAX_PRIMITIVE_FIELD_SIZE, dwAlignment[kk]);
|
||||
|
||||
dwClassGCHandles[kk] += 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// field has an unexpected type
|
||||
ThrowHR(VER_E_FIELD_SIG);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pRegularStaticOffsets == NULL && (dwClassGCHandles[0] != 0 || dwClassNonGCBytes[0] != 0))
|
||||
{
|
||||
// Lazily allocate table for offsets. We need offsets for GC and non GC areas. We add +1 to use as a sentinel.
|
||||
pRegularStaticOffsets = (PTR_DWORD)pamTracker->Track(
|
||||
GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(
|
||||
(S_SIZE_T(2 * sizeof(DWORD))*(S_SIZE_T(dwNumTypes)+S_SIZE_T(1)))));
|
||||
|
||||
for (DWORD i = 0; i < dwIndex; i++) {
|
||||
pRegularStaticOffsets[i * 2 ] = dwGCHandles[0]*TARGET_POINTER_SIZE;
|
||||
pRegularStaticOffsets[i * 2 + 1] = dwNonGCBytes[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (pThreadStaticOffsets == NULL && (dwClassGCHandles[1] != 0 || dwClassNonGCBytes[1] != 0))
|
||||
{
|
||||
// Lazily allocate table for offsets. We need offsets for GC and non GC areas. We add +1 to use as a sentinel.
|
||||
pThreadStaticOffsets = (PTR_DWORD)pamTracker->Track(
|
||||
GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(
|
||||
(S_SIZE_T(2 * sizeof(DWORD))*(S_SIZE_T(dwNumTypes)+S_SIZE_T(1)))));
|
||||
|
||||
for (DWORD i = 0; i < dwIndex; i++) {
|
||||
pThreadStaticOffsets[i * 2 ] = dwGCHandles[1]*TARGET_POINTER_SIZE;
|
||||
pThreadStaticOffsets[i * 2 + 1] = dwNonGCBytes[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pRegularStaticOffsets != NULL)
|
||||
{
|
||||
// Align the offset of non gc statics
|
||||
dwNonGCBytes[0] = (DWORD) ALIGN_UP(dwNonGCBytes[0], dwAlignment[0]);
|
||||
|
||||
// Save current offsets
|
||||
pRegularStaticOffsets[dwIndex*2] = dwGCHandles[0]*TARGET_POINTER_SIZE;
|
||||
pRegularStaticOffsets[dwIndex*2 + 1] = dwNonGCBytes[0];
|
||||
|
||||
// Increment for next class
|
||||
dwGCHandles[0] += dwClassGCHandles[0];
|
||||
dwNonGCBytes[0] += dwClassNonGCBytes[0];
|
||||
}
|
||||
|
||||
if (pThreadStaticOffsets != NULL)
|
||||
{
|
||||
// Align the offset of non gc statics
|
||||
dwNonGCBytes[1] = (DWORD) ALIGN_UP(dwNonGCBytes[1], dwAlignment[1]);
|
||||
|
||||
// Save current offsets
|
||||
pThreadStaticOffsets[dwIndex*2] = dwGCHandles[1]*TARGET_POINTER_SIZE;
|
||||
pThreadStaticOffsets[dwIndex*2 + 1] = dwNonGCBytes[1];
|
||||
|
||||
// Increment for next class
|
||||
dwGCHandles[1] += dwClassGCHandles[1];
|
||||
dwNonGCBytes[1] += dwClassNonGCBytes[1];
|
||||
}
|
||||
}
|
||||
|
||||
m_maxTypeRidStaticsAllocated = dwNumTypes;
|
||||
|
||||
if (pRegularStaticOffsets != NULL)
|
||||
{
|
||||
pRegularStaticOffsets[dwNumTypes*2] = dwGCHandles[0]*TARGET_POINTER_SIZE;
|
||||
pRegularStaticOffsets[dwNumTypes*2 + 1] = dwNonGCBytes[0];
|
||||
}
|
||||
|
||||
if (pThreadStaticOffsets != NULL)
|
||||
{
|
||||
pThreadStaticOffsets[dwNumTypes*2] = dwGCHandles[1]*TARGET_POINTER_SIZE;
|
||||
pThreadStaticOffsets[dwNumTypes*2 + 1] = dwNonGCBytes[1];
|
||||
}
|
||||
|
||||
m_pRegularStaticOffsets = pRegularStaticOffsets;
|
||||
m_pThreadStaticOffsets = pThreadStaticOffsets;
|
||||
|
||||
m_dwMaxGCRegularStaticHandles = dwGCHandles[0];
|
||||
m_dwMaxGCThreadStaticHandles = dwGCHandles[1];
|
||||
|
||||
m_dwRegularStaticsBlockSize = dwNonGCBytes[0];
|
||||
m_dwThreadStaticsBlockSize = dwNonGCBytes[1];
|
||||
}
|
||||
|
||||
void Module::GetOffsetsForRegularStaticData(
|
||||
mdToken cl,
|
||||
BOOL bDynamic, DWORD dwGCStaticHandles,
|
||||
DWORD dwNonGCStaticBytes,
|
||||
DWORD * pOutStaticHandleOffset,
|
||||
DWORD * pOutNonGCStaticOffset)
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
INJECT_FAULT(COMPlusThrowOM());
|
||||
}
|
||||
CONTRACTL_END
|
||||
|
||||
*pOutStaticHandleOffset = 0;
|
||||
*pOutNonGCStaticOffset = 0;
|
||||
|
||||
if (!dwGCStaticHandles && !dwNonGCStaticBytes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef CROSSBITNESS_COMPILE
|
||||
_ASSERTE(OFFSETOF__DomainLocalModule__NormalDynamicEntry__m_pDataBlob == DomainLocalModule::DynamicEntry::GetOffsetOfDataBlob());
|
||||
#endif
|
||||
// Statics for instantiated types are allocated dynamically per-instantiation
|
||||
if (bDynamic)
|
||||
{
|
||||
// Non GC statics are embedded in the Dynamic Entry.
|
||||
*pOutNonGCStaticOffset = OFFSETOF__DomainLocalModule__NormalDynamicEntry__m_pDataBlob;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_pRegularStaticOffsets == NULL)
|
||||
{
|
||||
THROW_BAD_FORMAT(BFA_METADATA_CORRUPT, this);
|
||||
}
|
||||
_ASSERTE(m_pRegularStaticOffsets != (PTR_DWORD) NGEN_STATICS_ALLCLASSES_WERE_LOADED);
|
||||
|
||||
// We allocate in the big blob.
|
||||
DWORD index = RidFromToken(cl) - 1;
|
||||
|
||||
*pOutStaticHandleOffset = m_pRegularStaticOffsets[index*2];
|
||||
|
||||
*pOutNonGCStaticOffset = m_pRegularStaticOffsets[index*2 + 1];
|
||||
#ifdef CROSSBITNESS_COMPILE
|
||||
*pOutNonGCStaticOffset += OFFSETOF__DomainLocalModule__m_pDataBlob_ - DomainLocalModule::OffsetOfDataBlob();
|
||||
#endif
|
||||
|
||||
// Check we didnt go out of what we predicted we would need for the class
|
||||
if (*pOutStaticHandleOffset + TARGET_POINTER_SIZE*dwGCStaticHandles >
|
||||
m_pRegularStaticOffsets[(index+1)*2] ||
|
||||
*pOutNonGCStaticOffset + dwNonGCStaticBytes >
|
||||
m_pRegularStaticOffsets[(index+1)*2 + 1])
|
||||
{ // It's most likely that this is due to bad metadata, thus the exception. However, the
|
||||
// previous comments for this bit of code mentioned that this could be a corner case bug
|
||||
// with static field size estimation, though this is entirely unlikely since the code has
|
||||
// been this way for at least two releases.
|
||||
THROW_BAD_FORMAT(BFA_METADATA_CORRUPT, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Module::GetOffsetsForThreadStaticData(
|
||||
mdToken cl,
|
||||
BOOL bDynamic, DWORD dwGCStaticHandles,
|
||||
DWORD dwNonGCStaticBytes,
|
||||
DWORD * pOutStaticHandleOffset,
|
||||
DWORD * pOutNonGCStaticOffset)
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
INJECT_FAULT(COMPlusThrowOM());
|
||||
}
|
||||
CONTRACTL_END
|
||||
|
||||
*pOutStaticHandleOffset = 0;
|
||||
*pOutNonGCStaticOffset = 0;
|
||||
|
||||
if (!dwGCStaticHandles && !dwNonGCStaticBytes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef CROSSBITNESS_COMPILE
|
||||
_ASSERTE(OFFSETOF__ThreadLocalModule__DynamicEntry__m_pDataBlob == ThreadLocalModule::DynamicEntry::GetOffsetOfDataBlob());
|
||||
#endif
|
||||
// Statics for instantiated types are allocated dynamically per-instantiation
|
||||
if (bDynamic)
|
||||
{
|
||||
// Non GC thread statics are embedded in the Dynamic Entry.
|
||||
*pOutNonGCStaticOffset = OFFSETOF__ThreadLocalModule__DynamicEntry__m_pDataBlob;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_pThreadStaticOffsets == NULL)
|
||||
{
|
||||
THROW_BAD_FORMAT(BFA_METADATA_CORRUPT, this);
|
||||
}
|
||||
_ASSERTE(m_pThreadStaticOffsets != (PTR_DWORD) NGEN_STATICS_ALLCLASSES_WERE_LOADED);
|
||||
|
||||
// We allocate in the big blob.
|
||||
DWORD index = RidFromToken(cl) - 1;
|
||||
|
||||
*pOutStaticHandleOffset = m_pThreadStaticOffsets[index*2];
|
||||
|
||||
*pOutNonGCStaticOffset = m_pThreadStaticOffsets[index*2 + 1];
|
||||
#ifdef CROSSBITNESS_COMPILE
|
||||
*pOutNonGCStaticOffset += OFFSETOF__ThreadLocalModule__m_pDataBlob - ThreadLocalModule::GetOffsetOfDataBlob();
|
||||
#endif
|
||||
|
||||
// Check we didnt go out of what we predicted we would need for the class
|
||||
if (*pOutStaticHandleOffset + TARGET_POINTER_SIZE*dwGCStaticHandles >
|
||||
m_pThreadStaticOffsets[(index+1)*2] ||
|
||||
*pOutNonGCStaticOffset + dwNonGCStaticBytes >
|
||||
m_pThreadStaticOffsets[(index+1)*2 + 1])
|
||||
{
|
||||
// It's most likely that this is due to bad metadata, thus the exception. However, the
|
||||
// previous comments for this bit of code mentioned that this could be a corner case bug
|
||||
// with static field size estimation, though this is entirely unlikely since the code has
|
||||
// been this way for at least two releases.
|
||||
THROW_BAD_FORMAT(BFA_METADATA_CORRUPT, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// initialize Crst controlling the Dynamic IL hashtable
|
||||
void Module::InitializeDynamicILCrst()
|
||||
{
|
||||
|
@ -1514,240 +1149,11 @@ BOOL Module::IsRuntimeMarshallingEnabled()
|
|||
return hr != S_OK;
|
||||
}
|
||||
|
||||
|
||||
DWORD Module::AllocateDynamicEntry(MethodTable *pMT)
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
PRECONDITION(pMT->GetModuleForStatics() == this);
|
||||
PRECONDITION(pMT->IsDynamicStatics());
|
||||
PRECONDITION(!pMT->ContainsGenericVariables());
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
CrstHolder ch(&m_Crst);
|
||||
DWORD newId = (LONG)m_cDynamicEntries++;
|
||||
|
||||
if (newId >= m_maxDynamicEntries)
|
||||
{
|
||||
SIZE_T maxDynamicEntries = max<SIZE_T>(16, m_maxDynamicEntries);
|
||||
while (maxDynamicEntries <= newId)
|
||||
{
|
||||
maxDynamicEntries *= 2;
|
||||
}
|
||||
|
||||
DynamicStaticsInfo* pNewDynamicStaticsInfo = (DynamicStaticsInfo*)
|
||||
(void*)GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(DynamicStaticsInfo)) * S_SIZE_T(maxDynamicEntries));
|
||||
|
||||
if (m_pDynamicStaticsInfo)
|
||||
memcpy(pNewDynamicStaticsInfo, m_pDynamicStaticsInfo, sizeof(DynamicStaticsInfo) * m_maxDynamicEntries);
|
||||
|
||||
VolatileStore(&m_pDynamicStaticsInfo, pNewDynamicStaticsInfo);
|
||||
m_maxDynamicEntries = maxDynamicEntries;
|
||||
}
|
||||
|
||||
m_pDynamicStaticsInfo[newId].pEnclosingMT = pMT;
|
||||
|
||||
LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Assigned dynamic ID %d to %s\n", newId, pMT->GetDebugClassName()));
|
||||
|
||||
return newId;
|
||||
}
|
||||
|
||||
void Module::FreeModuleIndex()
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
NOTHROW;
|
||||
GC_NOTRIGGER;
|
||||
MODE_ANY;
|
||||
}
|
||||
CONTRACTL_END;
|
||||
if (m_ModuleID != NULL)
|
||||
{
|
||||
_ASSERTE(m_ModuleIndex == m_ModuleID->GetModuleIndex());
|
||||
|
||||
if (IsCollectible())
|
||||
{
|
||||
ThreadStoreLockHolder tsLock;
|
||||
Thread *pThread = NULL;
|
||||
while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL)
|
||||
{
|
||||
pThread->DeleteThreadStaticData(m_ModuleIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the ModuleIndex from the DLM and free it
|
||||
Module::FreeModuleIndex(m_ModuleIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This was an empty, short-lived Module object that
|
||||
// was never assigned a ModuleIndex...
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ModuleIndex Module::AllocateModuleIndex()
|
||||
{
|
||||
DWORD val;
|
||||
g_pModuleIndexDispenser->NewId(NULL, val);
|
||||
|
||||
// For various reasons, the IDs issued by the IdDispenser start at 1.
|
||||
// Domain neutral module IDs have historically started at 0, and we
|
||||
// have always assigned ID 0 to CoreLib. Thus, to make it so that
|
||||
// domain neutral module IDs start at 0, we will subtract 1 from the
|
||||
// ID that we got back from the ID dispenser.
|
||||
ModuleIndex index((SIZE_T)(val-1));
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void Module::FreeModuleIndex(ModuleIndex index)
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
// We subtracted 1 after we allocated this ID, so we need to
|
||||
// add 1 before we free it.
|
||||
SIZE_T val = index.m_dwIndex + 1;
|
||||
|
||||
_ASSERTE(val <= MAXDWORD);
|
||||
g_pModuleIndexDispenser->DisposeId((DWORD)val);
|
||||
}
|
||||
|
||||
|
||||
void Module::AllocateRegularStaticHandles()
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
// Allocate the handles we will need. Note that AllocateStaticFieldObjRefPtrs will only
|
||||
// allocate if pModuleData->GetGCStaticsBasePointerAddress(pMT) != 0, avoiding creating
|
||||
// handles more than once for a given MT or module
|
||||
|
||||
DomainLocalModule *pModuleData = GetDomainLocalModule();
|
||||
|
||||
_ASSERTE(pModuleData->GetPrecomputedGCStaticsBasePointerAddress() != NULL);
|
||||
if (this->m_dwMaxGCRegularStaticHandles > 0)
|
||||
{
|
||||
AppDomain::GetCurrentDomain()->AllocateStaticFieldObjRefPtrs(this->m_dwMaxGCRegularStaticHandles,
|
||||
pModuleData->GetPrecomputedGCStaticsBasePointerAddress());
|
||||
|
||||
// We should throw if we fail to allocate and never hit this assert
|
||||
_ASSERTE(pModuleData->GetPrecomputedGCStaticsBasePointer() != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL Module::IsStaticStoragePrepared(mdTypeDef tkType)
|
||||
void Module::SetDomainAssembly(DomainAssembly *pDomainAssembly)
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
|
||||
// Right now the design is that we do one static allocation pass during NGEN,
|
||||
// and a 2nd pass for it at module init time for modules that weren't NGENed or the NGEN
|
||||
// pass was unsuccessful. If we are loading types after that then we must use dynamic
|
||||
// static storage. These dynamic statics require an additional indirection so they
|
||||
// don't perform quite as well.
|
||||
//
|
||||
// This check was created for the scenario where a profiler adds additional types
|
||||
// however it seems likely this check would also accurately handle other dynamic
|
||||
// scenarios such as ref.emit and EnC as long as they are adding new types and
|
||||
// not new statics to existing types.
|
||||
_ASSERTE(TypeFromToken(tkType) == mdtTypeDef);
|
||||
return m_maxTypeRidStaticsAllocated >= RidFromToken(tkType);
|
||||
}
|
||||
|
||||
void Module::AllocateStatics(AllocMemTracker *pamTracker)
|
||||
{
|
||||
STANDARD_VM_CONTRACT;
|
||||
|
||||
LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Allocating statics for module %s\n", GetSimpleName()));
|
||||
|
||||
// Build the offset table, which will tell us what the offsets for the statics of each class are (one offset for gc handles, one offset
|
||||
// for non gc types)
|
||||
BuildStaticsOffsets(pamTracker);
|
||||
}
|
||||
|
||||
void Module::SetDomainAssembly(DomainAssembly *pDomainAssembly)
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
INSTANCE_CHECK;
|
||||
PRECONDITION(CheckPointer(pDomainAssembly));
|
||||
PRECONDITION(IsManifest());
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
MODE_ANY;
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
DomainLocalModule* pModuleData = 0;
|
||||
|
||||
// Do we need to allocate memory for the non GC statics?
|
||||
if (m_ModuleID == NULL)
|
||||
{
|
||||
// Allocate memory for the module statics.
|
||||
LoaderAllocator *pLoaderAllocator = NULL;
|
||||
if (GetAssembly()->IsCollectible())
|
||||
{
|
||||
pLoaderAllocator = GetAssembly()->GetLoaderAllocator();
|
||||
}
|
||||
else
|
||||
{
|
||||
pLoaderAllocator = AppDomain::GetCurrentDomain()->GetLoaderAllocator();
|
||||
}
|
||||
|
||||
SIZE_T size = GetDomainLocalModuleSize();
|
||||
|
||||
LOG((LF_CLASSLOADER, LL_INFO10, "STATICS: Allocating %zi bytes for precomputed statics in module %s in LoaderAllocator %p\n",
|
||||
size, this->GetDebugName(), pLoaderAllocator));
|
||||
|
||||
// We guarantee alignment for 64-bit regular statics on 32-bit platforms even without FEATURE_64BIT_ALIGNMENT for performance reasons.
|
||||
|
||||
_ASSERTE(size >= DomainLocalModule::OffsetOfDataBlob());
|
||||
|
||||
pModuleData = (DomainLocalModule*)(void*)
|
||||
pLoaderAllocator->GetHighFrequencyHeap()->AllocAlignedMem(
|
||||
size, MAX_PRIMITIVE_FIELD_SIZE);
|
||||
|
||||
// Note: Memory allocated on loader heap is zero filled
|
||||
// memset(pModuleData, 0, size);
|
||||
|
||||
// Verify that the space is really zero initialized
|
||||
_ASSERTE(pModuleData->GetPrecomputedGCStaticsBasePointer() == NULL);
|
||||
|
||||
// If the module was loaded as domain-specific, then we need to assign
|
||||
// this module a domain-neutral module ID.
|
||||
pModuleData->m_ModuleIndex = Module::AllocateModuleIndex();
|
||||
m_ModuleIndex = pModuleData->m_ModuleIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
pModuleData = this->m_ModuleID;
|
||||
LOG((LF_CLASSLOADER, LL_INFO10, "STATICS: Allocation not needed for ngened non shared module %s in Appdomain %08x\n"));
|
||||
}
|
||||
|
||||
// Non shared case, module points directly to the statics. In ngen case
|
||||
// m_pDomainModule is already set for the non shared case
|
||||
if (m_ModuleID == NULL)
|
||||
{
|
||||
m_ModuleID = pModuleData;
|
||||
}
|
||||
|
||||
m_ModuleID->SetDomainAssembly(pDomainAssembly);
|
||||
|
||||
// Allocate static handles now.
|
||||
// NOTE: Bootstrapping issue with CoreLib - we will manually allocate later
|
||||
// If the assembly is collectible, we don't initialize static handles for them
|
||||
// as it is currently initialized through the DomainLocalModule::PopulateClass in MethodTable::CheckRunClassInitThrowing
|
||||
// (If we don't do this, it would allocate here unused regular static handles that will be overridden later)
|
||||
if (g_pPredefinedArrayTypes[ELEMENT_TYPE_OBJECT] != NULL && !GetAssembly()->IsCollectible())
|
||||
AllocateRegularStaticHandles();
|
||||
m_pDomainAssembly = pDomainAssembly;
|
||||
}
|
||||
|
||||
OBJECTREF Module::GetExposedObject()
|
||||
|
@ -5099,10 +4505,9 @@ void Module::EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
|
|||
EMEM_OUT(("MEM: %p Module\n", dac_cast<TADDR>(this)));
|
||||
}
|
||||
|
||||
//Save module id data only if it a real pointer, not a tagged sugestion to use ModuleIndex.
|
||||
if (m_ModuleID.IsValid())
|
||||
if (m_pDomainAssembly.IsValid())
|
||||
{
|
||||
m_ModuleID->EnumMemoryRegions(flags);
|
||||
m_pDomainAssembly->EnumMemoryRegions(flags);
|
||||
}
|
||||
if (m_pPEAssembly.IsValid())
|
||||
{
|
||||
|
|
|
@ -57,7 +57,6 @@ class Assembly;
|
|||
class BaseDomain;
|
||||
class AppDomain;
|
||||
class DomainModule;
|
||||
struct DomainLocalModule;
|
||||
class SystemDomain;
|
||||
class Module;
|
||||
class SString;
|
||||
|
@ -426,8 +425,6 @@ typedef DPTR(DynamicILBlobTable) PTR_DynamicILBlobTable;
|
|||
typedef DPTR(class ReadyToRunInfo) PTR_ReadyToRunInfo;
|
||||
#endif
|
||||
|
||||
struct ThreadLocalModule;
|
||||
|
||||
// A ModuleBase represents the ability to reference code via tokens
|
||||
// This abstraction exists to allow the R2R manifest metadata to have
|
||||
// tokens which can be resolved at runtime.
|
||||
|
@ -1508,73 +1505,11 @@ public:
|
|||
InstrumentedILOffsetMapping GetInstrumentedILOffsetMapping(mdMethodDef token);
|
||||
|
||||
public:
|
||||
// This helper returns to offsets for the slots/bytes/handles. They return the offset in bytes from the beginning
|
||||
// of the 1st GC pointer in the statics block for the module.
|
||||
void GetOffsetsForRegularStaticData(
|
||||
mdTypeDef cl,
|
||||
BOOL bDynamic,
|
||||
DWORD dwGCStaticHandles,
|
||||
DWORD dwNonGCStaticBytes,
|
||||
DWORD * pOutStaticHandleOffset,
|
||||
DWORD * pOutNonGCStaticOffset);
|
||||
|
||||
void GetOffsetsForThreadStaticData(
|
||||
mdTypeDef cl,
|
||||
BOOL bDynamic,
|
||||
DWORD dwGCStaticHandles,
|
||||
DWORD dwNonGCStaticBytes,
|
||||
DWORD * pOutStaticHandleOffset,
|
||||
DWORD * pOutNonGCStaticOffset);
|
||||
|
||||
|
||||
BOOL IsStaticStoragePrepared(mdTypeDef tkType);
|
||||
|
||||
DWORD GetNumGCThreadStaticHandles()
|
||||
{
|
||||
return m_dwMaxGCThreadStaticHandles;;
|
||||
}
|
||||
|
||||
CrstBase* GetFixupCrst()
|
||||
{
|
||||
return &m_FixupCrst;
|
||||
}
|
||||
|
||||
void AllocateRegularStaticHandles();
|
||||
|
||||
void FreeModuleIndex();
|
||||
|
||||
DWORD GetDomainLocalModuleSize()
|
||||
{
|
||||
return m_dwRegularStaticsBlockSize;
|
||||
}
|
||||
|
||||
DWORD GetThreadLocalModuleSize()
|
||||
{
|
||||
return m_dwThreadStaticsBlockSize;
|
||||
}
|
||||
|
||||
DWORD AllocateDynamicEntry(MethodTable *pMT);
|
||||
|
||||
// We need this for the jitted shared case,
|
||||
inline MethodTable* GetDynamicClassMT(DWORD dynamicClassID);
|
||||
|
||||
static ModuleIndex AllocateModuleIndex();
|
||||
static void FreeModuleIndex(ModuleIndex index);
|
||||
|
||||
ModuleIndex GetModuleIndex()
|
||||
{
|
||||
LIMITED_METHOD_DAC_CONTRACT;
|
||||
return m_ModuleIndex;
|
||||
}
|
||||
|
||||
SIZE_T GetModuleID()
|
||||
{
|
||||
LIMITED_METHOD_DAC_CONTRACT;
|
||||
return dac_cast<TADDR>(m_ModuleID);
|
||||
}
|
||||
|
||||
PTR_DomainLocalModule GetDomainLocalModule();
|
||||
|
||||
// LoaderHeap for storing IJW thunks
|
||||
PTR_LoaderHeap m_pThunkHeap;
|
||||
|
||||
|
@ -1588,46 +1523,7 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
void BuildStaticsOffsets (AllocMemTracker *pamTracker);
|
||||
void AllocateStatics (AllocMemTracker *pamTracker);
|
||||
|
||||
// ModuleID is quite ugly. We should try to switch to using ModuleIndex instead
|
||||
// where appropriate, and we should clean up code that uses ModuleID
|
||||
PTR_DomainLocalModule m_ModuleID; // MultiDomain case: tagged (low bit 1) ModuleIndex
|
||||
// SingleDomain case: pointer to domain local module
|
||||
|
||||
ModuleIndex m_ModuleIndex;
|
||||
|
||||
// reusing the statics area of a method table to store
|
||||
// these for the non domain neutral case, but they're now unified
|
||||
// it so that we don't have different code paths for this.
|
||||
PTR_DWORD m_pRegularStaticOffsets; // Offset of statics in each class
|
||||
PTR_DWORD m_pThreadStaticOffsets; // Offset of ThreadStatics in each class
|
||||
|
||||
// All types with RID <= this value have static storage allocated within the module by AllocateStatics
|
||||
// If AllocateStatics hasn't run yet, the value is 0
|
||||
RID m_maxTypeRidStaticsAllocated;
|
||||
|
||||
// @NICE: see if we can remove these fields
|
||||
DWORD m_dwMaxGCRegularStaticHandles; // Max number of handles we can have.
|
||||
DWORD m_dwMaxGCThreadStaticHandles;
|
||||
|
||||
// Size of the precomputed statics block. This includes class init bytes, gc handles and non gc statics
|
||||
DWORD m_dwRegularStaticsBlockSize;
|
||||
DWORD m_dwThreadStaticsBlockSize;
|
||||
|
||||
// For 'dynamic' statics (Reflection and generics)
|
||||
SIZE_T m_cDynamicEntries; // Number of used entries in DynamicStaticsInfo table
|
||||
SIZE_T m_maxDynamicEntries; // Size of table itself, including unused entries
|
||||
|
||||
// Info we need for dynamic statics that we can store per-module (ie, no need for it to be duplicated
|
||||
// per appdomain)
|
||||
struct DynamicStaticsInfo
|
||||
{
|
||||
MethodTable* pEnclosingMT; // Enclosing type; necessarily in this loader module
|
||||
};
|
||||
DynamicStaticsInfo* m_pDynamicStaticsInfo; // Table with entry for each dynamic ID
|
||||
|
||||
PTR_DomainAssembly m_pDomainAssembly;
|
||||
|
||||
public:
|
||||
//-----------------------------------------------------------------------------------------
|
||||
|
@ -1742,9 +1638,6 @@ public:
|
|||
|
||||
uint32_t GetNativeMetadataAssemblyCount();
|
||||
#endif // !defined(DACCESS_COMPILE)
|
||||
|
||||
// For protecting dictionary layout slot expansions
|
||||
CrstExplicitInit m_DictionaryCrst;
|
||||
};
|
||||
|
||||
//
|
||||
|
|
|
@ -337,14 +337,6 @@ inline mdAssemblyRef Module::FindAssemblyRef(Assembly *targetAssembly)
|
|||
|
||||
#endif //DACCESS_COMPILE
|
||||
|
||||
FORCEINLINE PTR_DomainLocalModule Module::GetDomainLocalModule()
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
SUPPORTS_DAC;
|
||||
|
||||
return m_ModuleID;
|
||||
}
|
||||
|
||||
#include "nibblestream.h"
|
||||
|
||||
FORCEINLINE BOOL Module::FixupDelayList(TADDR pFixupList, BOOL mayUsePrecompiledNDirectMethods)
|
||||
|
@ -475,13 +467,6 @@ BOOL Module::FixupDelayListAux(TADDR pFixupList,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
inline MethodTable* Module::GetDynamicClassMT(DWORD dynamicClassID)
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
_ASSERTE(m_cDynamicEntries > dynamicClassID);
|
||||
return VolatileLoadWithoutBarrier(&m_pDynamicStaticsInfo)[dynamicClassID].pEnclosingMT;
|
||||
}
|
||||
|
||||
#ifdef FEATURE_CODE_VERSIONING
|
||||
inline CodeVersionManager * Module::GetCodeVersionManager()
|
||||
{
|
||||
|
|
|
@ -933,6 +933,8 @@ void EEStartupHelper()
|
|||
|
||||
SystemDomain::System()->DefaultDomain()->SetupSharedStatics();
|
||||
|
||||
InitializeThreadStaticData();
|
||||
|
||||
#ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
|
||||
// retrieve configured max size for the mini-metadata buffer (defaults to 64KB)
|
||||
g_MiniMetaDataBuffMaxSize = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MiniMdBufferCapacity);
|
||||
|
@ -1720,10 +1722,27 @@ struct TlsDestructionMonitor
|
|||
thread->m_pFrame = FRAME_TOP;
|
||||
GCX_COOP_NO_DTOR_END();
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
BOOL oldGCOnTransitionsOK = thread->m_GCOnTransitionsOK;
|
||||
thread->m_GCOnTransitionsOK = FALSE;
|
||||
#endif
|
||||
if (!IsAtProcessExit() && !g_fEEShutDown)
|
||||
{
|
||||
GCX_COOP_NO_DTOR();
|
||||
FreeThreadStaticData(&t_ThreadStatics, thread);
|
||||
GCX_COOP_NO_DTOR_END();
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
thread->m_GCOnTransitionsOK = oldGCOnTransitionsOK;
|
||||
#endif
|
||||
thread->DetachThread(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Since we don't actually cleanup the TLS data along this path, verify that it is already cleaned up
|
||||
AssertThreadStaticDataFreed(&t_ThreadStatics);
|
||||
}
|
||||
|
||||
DeleteThreadLocalMemory();
|
||||
ThreadDetaching();
|
||||
}
|
||||
}
|
||||
|
@ -1738,30 +1757,6 @@ void EnsureTlsDestructionMonitor()
|
|||
tls_destructionMonitor.Activate();
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__declspec(thread) ThreadStaticBlockInfo t_ThreadStatics;
|
||||
#else
|
||||
__thread ThreadStaticBlockInfo t_ThreadStatics;
|
||||
#endif // _MSC_VER
|
||||
|
||||
// Delete the thread local memory only if we the current thread
|
||||
// is the one executing this code. If we do not guard it, it will
|
||||
// end up deleting the thread local memory of the calling thread.
|
||||
void DeleteThreadLocalMemory()
|
||||
{
|
||||
t_NonGCThreadStaticBlocksSize = 0;
|
||||
t_GCThreadStaticBlocksSize = 0;
|
||||
|
||||
t_ThreadStatics.NonGCMaxThreadStaticBlocks = 0;
|
||||
t_ThreadStatics.GCMaxThreadStaticBlocks = 0;
|
||||
|
||||
delete[] t_ThreadStatics.NonGCThreadStaticBlocks;
|
||||
t_ThreadStatics.NonGCThreadStaticBlocks = nullptr;
|
||||
|
||||
delete[] t_ThreadStatics.GCThreadStaticBlocks;
|
||||
t_ThreadStatics.GCThreadStaticBlocks = nullptr;
|
||||
}
|
||||
|
||||
#ifdef DEBUGGING_SUPPORTED
|
||||
//
|
||||
// InitializeDebugger initialized the Runtime-side COM+ Debugging Services
|
||||
|
|
|
@ -47,8 +47,6 @@ void ThreadDetaching();
|
|||
|
||||
void EnsureTlsDestructionMonitor();
|
||||
|
||||
void DeleteThreadLocalMemory();
|
||||
|
||||
void SetLatchedExitCode (INT32 code);
|
||||
INT32 GetLatchedExitCode (void);
|
||||
|
||||
|
|
|
@ -590,9 +590,6 @@ class EEClassOptionalFields
|
|||
// MISC FIELDS
|
||||
//
|
||||
|
||||
#define MODULE_NON_DYNAMIC_STATICS ((DWORD)-1)
|
||||
DWORD m_cbModuleDynamicID;
|
||||
|
||||
#if defined(UNIX_AMD64_ABI)
|
||||
// Number of eightBytes in the following arrays
|
||||
int m_numberEightBytes;
|
||||
|
@ -905,22 +902,6 @@ public:
|
|||
m_NumThreadStaticFields = wNumThreadStaticFields;
|
||||
}
|
||||
|
||||
// Statics are stored in a big chunk inside the module
|
||||
|
||||
inline DWORD GetModuleDynamicID()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
SUPPORTS_DAC;
|
||||
return HasOptionalFields() ? GetOptionalFields()->m_cbModuleDynamicID : MODULE_NON_DYNAMIC_STATICS;
|
||||
}
|
||||
|
||||
inline void SetModuleDynamicID(DWORD cbModuleDynamicID)
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
_ASSERTE(HasOptionalFields());
|
||||
GetOptionalFields()->m_cbModuleDynamicID = cbModuleDynamicID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Difference between the InterfaceMap ptr and Vtable in the
|
||||
* MethodTable used to indicate the number of static bytes
|
||||
|
|
|
@ -28,7 +28,6 @@ inline void EEClassOptionalFields::Init()
|
|||
m_pClassFactory = NULL;
|
||||
#endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
|
||||
#endif // FEATURE_COMINTEROP
|
||||
m_cbModuleDynamicID = MODULE_NON_DYNAMIC_STATICS;
|
||||
#if defined(UNIX_AMD64_ABI)
|
||||
m_numberEightBytes = 0;
|
||||
#endif // UNIX_AMD64_ABI
|
||||
|
|
|
@ -119,7 +119,6 @@ typedef DPTR(struct FailedAssembly) PTR_FailedAssembly;
|
|||
typedef VPTR(class EditAndContinueModule) PTR_EditAndContinueModule;
|
||||
typedef DPTR(class EEClass) PTR_EEClass;
|
||||
typedef DPTR(class DelegateEEClass) PTR_DelegateEEClass;
|
||||
typedef DPTR(struct DomainLocalModule) PTR_DomainLocalModule;
|
||||
typedef VPTR(class EECodeManager) PTR_EECodeManager;
|
||||
typedef DPTR(class RangeSectionMap) PTR_RangeSectionMap;
|
||||
typedef DPTR(class EEConfig) PTR_EEConfig;
|
||||
|
|
|
@ -509,6 +509,7 @@ void BulkStaticsLogger::LogAllStatics()
|
|||
CONTRACTL_END;
|
||||
|
||||
{
|
||||
// TODO: This code does not appear to find all generic instantiations of types, and thus does not log ALL statics
|
||||
AppDomain *domain = ::GetAppDomain(); // There is only 1 AppDomain, so no iterator here.
|
||||
|
||||
AppDomain::AssemblyIterator assemblyIter = domain->IterateAssembliesEx((AssemblyIterationFlags)(kIncludeLoaded|kIncludeExecution));
|
||||
|
@ -533,10 +534,6 @@ void BulkStaticsLogger::LogAllStatics()
|
|||
if (!domainAssembly->IsActive())
|
||||
continue;
|
||||
|
||||
DomainLocalModule *domainModule = module->GetDomainLocalModule();
|
||||
if (domainModule == NULL)
|
||||
continue;
|
||||
|
||||
// Now iterate all types with
|
||||
LookupMap<PTR_MethodTable>::Iterator mtIter = module->EnumerateTypeDefs();
|
||||
while (mtIter.Next())
|
||||
|
@ -566,7 +563,7 @@ void BulkStaticsLogger::LogAllStatics()
|
|||
if (fieldType != ELEMENT_TYPE_CLASS && fieldType != ELEMENT_TYPE_VALUETYPE)
|
||||
continue;
|
||||
|
||||
BYTE *base = field->GetBaseInDomainLocalModule(domainModule);
|
||||
BYTE *base = field->GetBase();
|
||||
if (base == NULL)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -392,20 +392,6 @@ public:
|
|||
return GetApproxEnclosingMethodTable()->GetNumGenericArgs();
|
||||
}
|
||||
|
||||
PTR_BYTE GetBaseInDomainLocalModule(DomainLocalModule * pLocalModule)
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
|
||||
if (GetFieldType() == ELEMENT_TYPE_CLASS || GetFieldType() == ELEMENT_TYPE_VALUETYPE)
|
||||
{
|
||||
return pLocalModule->GetGCStaticsBasePointer(GetEnclosingMethodTable());
|
||||
}
|
||||
else
|
||||
{
|
||||
return pLocalModule->GetNonGCStaticsBasePointer(GetEnclosingMethodTable());
|
||||
}
|
||||
}
|
||||
|
||||
PTR_BYTE GetBase()
|
||||
{
|
||||
CONTRACTL
|
||||
|
@ -417,7 +403,14 @@ public:
|
|||
|
||||
MethodTable *pMT = GetEnclosingMethodTable();
|
||||
|
||||
return GetBaseInDomainLocalModule(pMT->GetDomainLocalModule());
|
||||
if (GetFieldType() == ELEMENT_TYPE_CLASS || GetFieldType() == ELEMENT_TYPE_VALUETYPE)
|
||||
{
|
||||
return pMT->GetGCStaticsBasePointer();
|
||||
}
|
||||
else
|
||||
{
|
||||
return pMT->GetNonGCStaticsBasePointer();
|
||||
}
|
||||
}
|
||||
|
||||
// returns the address of the field
|
||||
|
@ -521,7 +514,10 @@ public:
|
|||
else {
|
||||
PTR_BYTE base = 0;
|
||||
if (!IsRVA()) // for RVA the base is ignored
|
||||
{
|
||||
GetEnclosingMethodTable()->EnsureStaticDataAllocated();
|
||||
base = GetBase();
|
||||
}
|
||||
return GetStaticAddress((void *)dac_cast<TADDR>(base));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -302,6 +302,7 @@ void GCToEEInterface::GcScanRoots(promote_func* fn, int condemned, int max_gen,
|
|||
#endif // FEATURE_EVENT_TRACE
|
||||
ScanStackRoots(pThread, fn, sc);
|
||||
ScanTailCallArgBufferRoots(pThread, fn, sc);
|
||||
ScanThreadStaticRoots(pThread, fn, sc);
|
||||
#ifdef FEATURE_EVENT_TRACE
|
||||
sc->dwEtwRootKind = kEtwGCRootKindOther;
|
||||
#endif // FEATURE_EVENT_TRACE
|
||||
|
@ -620,6 +621,7 @@ void GcScanRootsForProfilerAndETW(promote_func* fn, int condemned, int max_gen,
|
|||
#endif // FEATURE_EVENT_TRACE
|
||||
ScanStackRoots(pThread, fn, sc);
|
||||
ScanTailCallArgBufferRoots(pThread, fn, sc);
|
||||
ScanThreadStaticRoots(pThread, fn, sc);
|
||||
#ifdef FEATURE_EVENT_TRACE
|
||||
sc->dwEtwRootKind = kEtwGCRootKindOther;
|
||||
#endif // FEATURE_EVENT_TRACE
|
||||
|
|
|
@ -48,6 +48,14 @@ inline OBJECTREF ObjectFromHandle(OBJECTHANDLE handle)
|
|||
return UNCHECKED_OBJECTREF_TO_OBJECTREF(*PTR_UNCHECKED_OBJECTREF(handle));
|
||||
}
|
||||
|
||||
// Given a handle, returns an OBJECTREF for the object it refers to.
|
||||
inline _UNCHECKED_OBJECTREF ObjectFromHandleUnchecked(OBJECTHANDLE handle)
|
||||
{
|
||||
_ASSERTE(handle);
|
||||
|
||||
return (*PTR_UNCHECKED_OBJECTREF(handle));
|
||||
}
|
||||
|
||||
// Quick inline check for whether a handle is null
|
||||
inline BOOL IsHandleNullUnchecked(OBJECTHANDLE handle)
|
||||
{
|
||||
|
|
|
@ -233,7 +233,7 @@ BOOL DictionaryLayout::FindTokenWorker(LoaderAllocator* pAllocat
|
|||
}
|
||||
|
||||
// A lock should be taken by FindToken before being allowed to use an empty slot in the layout
|
||||
_ASSERT(SystemDomain::SystemModule()->m_DictionaryCrst.OwnedByCurrentThread());
|
||||
_ASSERT(GetAppDomain()->GetGenericDictionaryExpansionLock()->OwnedByCurrentThread());
|
||||
|
||||
PVOID pResultSignature = pSigBuilder == NULL ? pSig : CreateSignatureWithSlotData(pSigBuilder, pAllocator, slot);
|
||||
pDictLayout->m_slots[iSlot].m_signature = pResultSignature;
|
||||
|
@ -270,7 +270,7 @@ DictionaryLayout* DictionaryLayout::ExpandDictionaryLayout(LoaderAllocator*
|
|||
{
|
||||
STANDARD_VM_CHECK;
|
||||
INJECT_FAULT(ThrowOutOfMemory(););
|
||||
PRECONDITION(SystemDomain::SystemModule()->m_DictionaryCrst.OwnedByCurrentThread());
|
||||
PRECONDITION(GetAppDomain()->GetGenericDictionaryExpansionLock()->OwnedByCurrentThread());
|
||||
PRECONDITION(CheckPointer(pResult) && CheckPointer(pSlotOut));
|
||||
}
|
||||
CONTRACTL_END
|
||||
|
@ -337,7 +337,7 @@ BOOL DictionaryLayout::FindToken(MethodTable* pMT,
|
|||
if (FindTokenWorker(pAllocator, pMT->GetNumGenericArgs(), pMT->GetClass()->GetDictionaryLayout(), pSigBuilder, pSig, cbSig, nFirstOffset, signatureSource, pResult, pSlotOut, 0, FALSE))
|
||||
return TRUE;
|
||||
|
||||
CrstHolder ch(&SystemDomain::SystemModule()->m_DictionaryCrst);
|
||||
CrstHolder ch(GetAppDomain()->GetGenericDictionaryExpansionLock());
|
||||
{
|
||||
// Try again under lock in case another thread already expanded the dictionaries or filled an empty slot
|
||||
if (FindTokenWorker(pMT->GetLoaderAllocator(), pMT->GetNumGenericArgs(), pMT->GetClass()->GetDictionaryLayout(), pSigBuilder, pSig, cbSig, nFirstOffset, signatureSource, pResult, pSlotOut, *pSlotOut, TRUE))
|
||||
|
@ -384,7 +384,7 @@ BOOL DictionaryLayout::FindToken(MethodDesc* pMD,
|
|||
if (FindTokenWorker(pAllocator, pMD->GetNumGenericMethodArgs(), pMD->GetDictionaryLayout(), pSigBuilder, pSig, cbSig, nFirstOffset, signatureSource, pResult, pSlotOut, 0, FALSE))
|
||||
return TRUE;
|
||||
|
||||
CrstHolder ch(&SystemDomain::SystemModule()->m_DictionaryCrst);
|
||||
CrstHolder ch(GetAppDomain()->GetGenericDictionaryExpansionLock());
|
||||
{
|
||||
// Try again under lock in case another thread already expanded the dictionaries or filled an empty slot
|
||||
if (FindTokenWorker(pAllocator, pMD->GetNumGenericMethodArgs(), pMD->GetDictionaryLayout(), pSigBuilder, pSig, cbSig, nFirstOffset, signatureSource, pResult, pSlotOut, *pSlotOut, TRUE))
|
||||
|
@ -502,7 +502,7 @@ Dictionary* Dictionary::GetMethodDictionaryWithSizeCheck(MethodDesc* pMD, ULONG
|
|||
// Only expand the dictionary if the current slot we're trying to use is beyond the size of the dictionary
|
||||
|
||||
// Take lock and check for size again, just in case another thread already resized the dictionary
|
||||
CrstHolder ch(&SystemDomain::SystemModule()->m_DictionaryCrst);
|
||||
CrstHolder ch(GetAppDomain()->GetGenericDictionaryExpansionLock());
|
||||
|
||||
pDictionary = pMD->GetMethodDictionary();
|
||||
currentDictionarySize = pDictionary->GetDictionarySlotsSize(numGenericArgs);
|
||||
|
@ -560,7 +560,7 @@ Dictionary* Dictionary::GetTypeDictionaryWithSizeCheck(MethodTable* pMT, ULONG s
|
|||
// Only expand the dictionary if the current slot we're trying to use is beyond the size of the dictionary
|
||||
|
||||
// Take lock and check for size again, just in case another thread already resized the dictionary
|
||||
CrstHolder ch(&SystemDomain::SystemModule()->m_DictionaryCrst);
|
||||
CrstHolder ch(GetAppDomain()->GetGenericDictionaryExpansionLock());
|
||||
|
||||
pDictionary = pMT->GetDictionary();
|
||||
currentDictionarySize = pDictionary->GetDictionarySlotsSize(numGenericArgs);
|
||||
|
@ -783,7 +783,7 @@ Dictionary::PopulateEntry(
|
|||
|
||||
#if _DEBUG
|
||||
// Lock is needed because dictionary pointers can get updated during dictionary size expansion
|
||||
CrstHolder ch(&SystemDomain::SystemModule()->m_DictionaryCrst);
|
||||
CrstHolder ch(GetAppDomain()->GetGenericDictionaryExpansionLock());
|
||||
|
||||
// MethodTable is expected to be normalized
|
||||
Dictionary* pDictionary = pMT->GetDictionary();
|
||||
|
|
|
@ -278,7 +278,13 @@ ClassLoader::CreateTypeHandleForNonCanonicalGenericInstantiation(
|
|||
memcpy((BYTE*)pMT - cbGC, (BYTE*) pOldMT - cbGC, cbGC);
|
||||
|
||||
// Allocate the private data block
|
||||
pMT->AllocateAuxiliaryData(pAllocator, pLoaderModule, pamTracker, fHasGenericsStaticsInfo);
|
||||
MethodTableStaticsFlags staticsFlags = MethodTableStaticsFlags::None;
|
||||
if (fHasGenericsStaticsInfo)
|
||||
staticsFlags |= MethodTableStaticsFlags::Generic | MethodTableStaticsFlags::Present;
|
||||
if (pOldMT->GetNumThreadStaticFields() > 0)
|
||||
staticsFlags |= MethodTableStaticsFlags::Thread;
|
||||
|
||||
pMT->AllocateAuxiliaryData(pAllocator, pLoaderModule, pamTracker, staticsFlags);
|
||||
pMT->SetModule(pOldMT->GetModule());
|
||||
|
||||
pMT->GetAuxiliaryDataForWrite()->SetIsNotFullyLoadedForBuildMethodTable();
|
||||
|
@ -334,15 +340,16 @@ ClassLoader::CreateTypeHandleForNonCanonicalGenericInstantiation(
|
|||
if (fContainsGenericVariables)
|
||||
pMT->SetContainsGenericVariables();
|
||||
|
||||
if (fHasGenericsStaticsInfo)
|
||||
pMT->SetDynamicStatics(TRUE);
|
||||
|
||||
// Since we are fabricating a new MT based on an existing one, the per-inst info should
|
||||
// be non-null
|
||||
_ASSERTE(pOldMT->HasPerInstInfo());
|
||||
|
||||
// Fill in per-inst map pointer (which points to the array of generic dictionary pointers)
|
||||
pMT->SetPerInstInfo((MethodTable::PerInstInfoElem_t *) (pMemory + cbMT + cbOptional + cbIMap + sizeof(GenericsDictInfo)));
|
||||
|
||||
if (fHasGenericsStaticsInfo)
|
||||
pMT->SetDynamicStatics();
|
||||
|
||||
_ASSERTE(FitsIn<WORD>(pOldMT->GetNumDicts()));
|
||||
_ASSERTE(FitsIn<WORD>(pOldMT->GetNumGenericArgs()));
|
||||
pMT->SetDictInfo(static_cast<WORD>(pOldMT->GetNumDicts()), static_cast<WORD>(pOldMT->GetNumGenericArgs()));
|
||||
|
|
|
@ -770,113 +770,6 @@ void *JIT_TrialAlloc::GenAllocString(Flags flags)
|
|||
|
||||
return (void *)pStub->GetEntryPoint();
|
||||
}
|
||||
// For this helper,
|
||||
// If bCCtorCheck == true
|
||||
// ECX contains the domain neutral module ID
|
||||
// EDX contains the class domain ID, and the
|
||||
// else
|
||||
// ECX contains the domain neutral module ID
|
||||
// EDX is junk
|
||||
// shared static base is returned in EAX.
|
||||
|
||||
// "init" should be the address of a routine which takes an argument of
|
||||
// the module domain ID, the class domain ID, and returns the static base pointer
|
||||
void EmitFastGetSharedStaticBase(CPUSTUBLINKER *psl, CodeLabel *init, bool bCCtorCheck, bool bGCStatic)
|
||||
{
|
||||
STANDARD_VM_CONTRACT;
|
||||
|
||||
CodeLabel *DoInit = 0;
|
||||
if (bCCtorCheck)
|
||||
{
|
||||
DoInit = psl->NewCodeLabel();
|
||||
}
|
||||
|
||||
// mov eax, ecx
|
||||
psl->Emit8(0x89);
|
||||
psl->Emit8(0xc8);
|
||||
|
||||
if (bCCtorCheck)
|
||||
{
|
||||
// test [eax + edx + offsetof(DomainLocalModule, m_pDataBlob], ClassInitFlags::INITIALIZED_FLAG // Is class inited
|
||||
_ASSERTE(FitsInI1(ClassInitFlags::INITIALIZED_FLAG));
|
||||
_ASSERTE(FitsInI1(DomainLocalModule::GetOffsetOfDataBlob()));
|
||||
|
||||
BYTE testClassInit[] = { 0xF6, 0x44, 0x10,
|
||||
(BYTE) DomainLocalModule::GetOffsetOfDataBlob(), (BYTE)ClassInitFlags::INITIALIZED_FLAG };
|
||||
|
||||
psl->EmitBytes(testClassInit, sizeof(testClassInit));
|
||||
|
||||
// jz init // no, init it
|
||||
psl->X86EmitCondJump(DoInit, X86CondCode::kJZ);
|
||||
}
|
||||
|
||||
if (bGCStatic)
|
||||
{
|
||||
// Indirect to get the pointer to the first GC Static
|
||||
psl->X86EmitIndexRegLoad(kEAX, kEAX, (int32_t) DomainLocalModule::GetOffsetOfGCStaticPointer());
|
||||
}
|
||||
|
||||
// ret
|
||||
psl->X86EmitReturn(0);
|
||||
|
||||
if (bCCtorCheck)
|
||||
{
|
||||
// DoInit:
|
||||
psl->EmitLabel(DoInit);
|
||||
|
||||
psl->X86EmitPushEBPframe();
|
||||
|
||||
#ifdef UNIX_X86_ABI
|
||||
#define STACK_ALIGN_PADDING 4
|
||||
// sub esp, STACK_ALIGN_PADDING; to align the stack
|
||||
psl->X86EmitSubEsp(STACK_ALIGN_PADDING);
|
||||
#endif // UNIX_X86_ABI
|
||||
|
||||
// push edx (must be preserved)
|
||||
psl->X86EmitPushReg(kEDX);
|
||||
|
||||
// call init
|
||||
psl->X86EmitCall(init, 0);
|
||||
|
||||
// pop edx
|
||||
psl->X86EmitPopReg(kEDX);
|
||||
|
||||
#ifdef UNIX_X86_ABI
|
||||
// add esp, STACK_ALIGN_PADDING
|
||||
psl->X86EmitAddEsp(STACK_ALIGN_PADDING);
|
||||
#undef STACK_ALIGN_PADDING
|
||||
#endif // UNIX_X86_ABI
|
||||
|
||||
psl->X86EmitPopReg(kEBP);
|
||||
|
||||
// ret
|
||||
psl->X86EmitReturn(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void *GenFastGetSharedStaticBase(bool bCheckCCtor, bool bGCStatic)
|
||||
{
|
||||
STANDARD_VM_CONTRACT;
|
||||
|
||||
CPUSTUBLINKER sl;
|
||||
|
||||
CodeLabel *init;
|
||||
if (bGCStatic)
|
||||
{
|
||||
init = sl.NewExternalCodeLabel((LPVOID)JIT_GetSharedGCStaticBase);
|
||||
}
|
||||
else
|
||||
{
|
||||
init = sl.NewExternalCodeLabel((LPVOID)JIT_GetSharedNonGCStaticBase);
|
||||
}
|
||||
|
||||
EmitFastGetSharedStaticBase(&sl, init, bCheckCCtor, bGCStatic);
|
||||
|
||||
Stub *pStub = sl.Link(SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap());
|
||||
|
||||
return (void*) pStub->GetEntryPoint();
|
||||
}
|
||||
|
||||
#define NUM_WRITE_BARRIERS 6
|
||||
|
||||
|
@ -969,16 +862,6 @@ void InitJITHelpers1()
|
|||
ECall::DynamicallyAssignFCallImpl((PCODE) JIT_TrialAlloc::GenAllocString(flags), ECall::FastAllocateString);
|
||||
}
|
||||
|
||||
// Replace static helpers with faster assembly versions
|
||||
pMethodAddresses[6] = GenFastGetSharedStaticBase(true, true);
|
||||
SetJitHelperFunction(CORINFO_HELP_GETSHARED_GCSTATIC_BASE, pMethodAddresses[6]);
|
||||
pMethodAddresses[7] = GenFastGetSharedStaticBase(true, false);
|
||||
SetJitHelperFunction(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE, pMethodAddresses[7]);
|
||||
pMethodAddresses[8] = GenFastGetSharedStaticBase(false, true);
|
||||
SetJitHelperFunction(CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR, pMethodAddresses[8]);
|
||||
pMethodAddresses[9] = GenFastGetSharedStaticBase(false, false);
|
||||
SetJitHelperFunction(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR, pMethodAddresses[9]);
|
||||
|
||||
ETW::MethodLog::StubsInitialized(pMethodAddresses, (PVOID *)pHelperNames, ETW_NUM_JIT_HELPERS);
|
||||
|
||||
// All write barrier helpers should fit into one page.
|
||||
|
|
|
@ -1017,9 +1017,8 @@ HCIMPL1(void, JIT_InitClass, CORINFO_CLASS_HANDLE typeHnd_)
|
|||
|
||||
TypeHandle typeHnd(typeHnd_);
|
||||
MethodTable *pMT = typeHnd.AsMethodTable();
|
||||
_ASSERTE(!pMT->IsClassPreInited());
|
||||
|
||||
if (pMT->GetDomainLocalModule()->IsClassInitialized(pMT))
|
||||
if (pMT->IsClassInited())
|
||||
return;
|
||||
|
||||
// Tailcall to the slow helper
|
||||
|
@ -1070,57 +1069,107 @@ HCIMPLEND
|
|||
|
||||
#include <optsmallperfcritical.h>
|
||||
|
||||
HCIMPL2(void*, JIT_GetSharedNonGCStaticBase_Portable, DomainLocalModule *pLocalModule, DWORD dwClassDomainID)
|
||||
HCIMPL1(void*, JIT_GetNonGCStaticBase_Portable, MethodTable* pMT)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
// If type doesn't have a class constructor, the contents of this if statement may
|
||||
// still get executed. JIT_GetSharedNonGCStaticBaseNoCtor should be used in this case.
|
||||
if (pLocalModule->IsPrecomputedClassInitialized(dwClassDomainID))
|
||||
PTR_BYTE pBase;
|
||||
if (pMT->GetDynamicStaticsInfo()->GetIsInitedAndNonGCStaticsPointerIfInited(&pBase))
|
||||
{
|
||||
return (void*)pLocalModule->GetPrecomputedNonGCStaticsBasePointer();
|
||||
return pBase;
|
||||
}
|
||||
|
||||
// Tailcall to the slow helper
|
||||
ENDFORBIDGC();
|
||||
return HCCALL2(JIT_GetSharedNonGCStaticBase_Helper, pLocalModule, dwClassDomainID);
|
||||
return HCCALL1(JIT_GetNonGCStaticBase_Helper, pMT);
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
|
||||
HCIMPL1(void*, JIT_GetDynamicNonGCStaticBase_Portable, DynamicStaticsInfo* pStaticsInfo)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
PTR_BYTE pBase;
|
||||
if (pStaticsInfo->GetIsInitedAndNonGCStaticsPointerIfInited(&pBase))
|
||||
{
|
||||
return pBase;
|
||||
}
|
||||
|
||||
// Tailcall to the slow helper
|
||||
ENDFORBIDGC();
|
||||
return HCCALL1(JIT_GetNonGCStaticBase_Helper, pStaticsInfo->GetMethodTable());
|
||||
}
|
||||
HCIMPLEND
|
||||
// No constructor version of JIT_GetSharedNonGCStaticBase. Does not check if class has
|
||||
// been initialized.
|
||||
HCIMPL1(void*, JIT_GetNonGCStaticBaseNoCtor_Portable, MethodTable* pMT)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
return pMT->GetDynamicStaticsInfo()->GetNonGCStaticsPointerAssumeIsInited();
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
// No constructor version of JIT_GetSharedNonGCStaticBase. Does not check if class has
|
||||
// been initialized.
|
||||
HCIMPL1(void*, JIT_GetSharedNonGCStaticBaseNoCtor_Portable, DomainLocalModule *pLocalModule)
|
||||
HCIMPL1(void*, JIT_GetDynamicNonGCStaticBaseNoCtor_Portable, DynamicStaticsInfo* pDynamicStaticsInfo)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
return (void*)pLocalModule->GetPrecomputedNonGCStaticsBasePointer();
|
||||
return pDynamicStaticsInfo->GetNonGCStaticsPointerAssumeIsInited();
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
HCIMPL2(void*, JIT_GetSharedGCStaticBase_Portable, DomainLocalModule *pLocalModule, DWORD dwClassDomainID)
|
||||
HCIMPL1(void*, JIT_GetGCStaticBase_Portable, MethodTable* pMT)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
// If type doesn't have a class constructor, the contents of this if statement may
|
||||
// still get executed. JIT_GetSharedGCStaticBaseNoCtor should be used in this case.
|
||||
if (pLocalModule->IsPrecomputedClassInitialized(dwClassDomainID))
|
||||
PTR_OBJECTREF pBase;
|
||||
if (pMT->GetDynamicStaticsInfo()->GetIsInitedAndGCStaticsPointerIfInited(&pBase))
|
||||
{
|
||||
return (void*)pLocalModule->GetPrecomputedGCStaticsBasePointer();
|
||||
return pBase;
|
||||
}
|
||||
|
||||
// Tailcall to the slow helper
|
||||
ENDFORBIDGC();
|
||||
return HCCALL2(JIT_GetSharedGCStaticBase_Helper, pLocalModule, dwClassDomainID);
|
||||
return HCCALL1(JIT_GetGCStaticBase_Helper, pMT);
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
HCIMPL1(void*, JIT_GetDynamicGCStaticBase_Portable, DynamicStaticsInfo* pStaticsInfo)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
PTR_OBJECTREF pBase;
|
||||
if (pStaticsInfo->GetIsInitedAndGCStaticsPointerIfInited(&pBase))
|
||||
{
|
||||
return pBase;
|
||||
}
|
||||
|
||||
// Tailcall to the slow helper
|
||||
ENDFORBIDGC();
|
||||
return HCCALL1(JIT_GetGCStaticBase_Helper, pStaticsInfo->GetMethodTable());
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
// No constructor version of JIT_GetSharedGCStaticBase. Does not check if class has been
|
||||
// initialized.
|
||||
HCIMPL1(void*, JIT_GetSharedGCStaticBaseNoCtor_Portable, DomainLocalModule *pLocalModule)
|
||||
HCIMPL1(void*, JIT_GetGCStaticBaseNoCtor_Portable, MethodTable* pMT)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
return (void*)pLocalModule->GetPrecomputedGCStaticsBasePointer();
|
||||
return pMT->GetDynamicStaticsInfo()->GetGCStaticsPointerAssumeIsInited();
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
// No constructor version of JIT_GetSharedGCStaticBase. Does not check if class has been
|
||||
// initialized.
|
||||
HCIMPL1(void*, JIT_GetDynamicGCStaticBaseNoCtor_Portable, DynamicStaticsInfo* pDynamicStaticsInfo)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
return pDynamicStaticsInfo->GetGCStaticsPointerAssumeIsInited();
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
|
@ -1129,309 +1178,86 @@ HCIMPLEND
|
|||
|
||||
// The following two functions can be tail called from platform dependent versions of
|
||||
// JIT_GetSharedGCStaticBase and JIT_GetShareNonGCStaticBase
|
||||
HCIMPL2(void*, JIT_GetSharedNonGCStaticBase_Helper, DomainLocalModule *pLocalModule, DWORD dwClassDomainID)
|
||||
HCIMPL1(void*, JIT_GetNonGCStaticBase_Helper, MethodTable* pMT)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
HELPER_METHOD_FRAME_BEGIN_RET_0();
|
||||
|
||||
// Obtain Method table
|
||||
MethodTable * pMT = pLocalModule->GetMethodTableFromClassDomainID(dwClassDomainID);
|
||||
|
||||
PREFIX_ASSUME(pMT != NULL);
|
||||
pMT->CheckRunClassInitThrowing();
|
||||
HELPER_METHOD_FRAME_END();
|
||||
|
||||
return (void*)pLocalModule->GetPrecomputedNonGCStaticsBasePointer();
|
||||
return (void*)pMT->GetDynamicStaticsInfo()->GetNonGCStaticsPointer();
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
HCIMPL2(void*, JIT_GetSharedGCStaticBase_Helper, DomainLocalModule *pLocalModule, DWORD dwClassDomainID)
|
||||
HCIMPL1(void*, JIT_GetGCStaticBase_Helper, MethodTable* pMT)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
HELPER_METHOD_FRAME_BEGIN_RET_0();
|
||||
|
||||
// Obtain Method table
|
||||
MethodTable * pMT = pLocalModule->GetMethodTableFromClassDomainID(dwClassDomainID);
|
||||
|
||||
PREFIX_ASSUME(pMT != NULL);
|
||||
pMT->CheckRunClassInitThrowing();
|
||||
HELPER_METHOD_FRAME_END();
|
||||
|
||||
return (void*)pLocalModule->GetPrecomputedGCStaticsBasePointer();
|
||||
return (void*)pMT->GetDynamicStaticsInfo()->GetGCStaticsPointer();
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
/*********************************************************************/
|
||||
// Slow helper to tail call from the fast one
|
||||
HCIMPL2(void*, JIT_GetSharedNonGCStaticBaseDynamicClass_Helper, DomainLocalModule *pLocalModule, DWORD dwDynamicClassDomainID)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
void* result = NULL;
|
||||
|
||||
HELPER_METHOD_FRAME_BEGIN_RET_0();
|
||||
|
||||
MethodTable *pMT = pLocalModule->GetDomainAssembly()->GetModule()->GetDynamicClassMT(dwDynamicClassDomainID);
|
||||
_ASSERTE(pMT);
|
||||
|
||||
pMT->CheckRunClassInitThrowing();
|
||||
|
||||
result = (void*)pLocalModule->GetDynamicEntryNonGCStaticsBasePointer(dwDynamicClassDomainID, pMT->GetLoaderAllocator());
|
||||
HELPER_METHOD_FRAME_END();
|
||||
|
||||
return result;
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
/*************************************************************/
|
||||
#include <optsmallperfcritical.h>
|
||||
HCIMPL2(void*, JIT_GetSharedNonGCStaticBaseDynamicClass, DomainLocalModule *pLocalModule, DWORD dwDynamicClassDomainID)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
DomainLocalModule::PTR_DynamicClassInfo pLocalInfo = pLocalModule->GetDynamicClassInfoIfInitialized(dwDynamicClassDomainID);
|
||||
if (pLocalInfo != NULL)
|
||||
{
|
||||
PTR_BYTE retval;
|
||||
GET_DYNAMICENTRY_NONGCSTATICS_BASEPOINTER(pLocalModule->GetDomainAssembly()->GetModule()->GetLoaderAllocator(),
|
||||
pLocalInfo,
|
||||
&retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
// Tailcall to the slow helper
|
||||
ENDFORBIDGC();
|
||||
return HCCALL2(JIT_GetSharedNonGCStaticBaseDynamicClass_Helper, pLocalModule, dwDynamicClassDomainID);
|
||||
}
|
||||
HCIMPLEND
|
||||
#include <optdefault.h>
|
||||
|
||||
/*************************************************************/
|
||||
// Slow helper to tail call from the fast one
|
||||
HCIMPL2(void, JIT_ClassInitDynamicClass_Helper, DomainLocalModule *pLocalModule, DWORD dwDynamicClassDomainID)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
HELPER_METHOD_FRAME_BEGIN_0();
|
||||
|
||||
MethodTable *pMT = pLocalModule->GetDomainAssembly()->GetModule()->GetDynamicClassMT(dwDynamicClassDomainID);
|
||||
_ASSERTE(pMT);
|
||||
|
||||
pMT->CheckRunClassInitThrowing();
|
||||
|
||||
HELPER_METHOD_FRAME_END();
|
||||
|
||||
return;
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
#include <optsmallperfcritical.h>
|
||||
HCIMPL2(void, JIT_ClassInitDynamicClass, DomainLocalModule *pLocalModule, DWORD dwDynamicClassDomainID)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
DomainLocalModule::PTR_DynamicClassInfo pLocalInfo = pLocalModule->GetDynamicClassInfoIfInitialized(dwDynamicClassDomainID);
|
||||
if (pLocalInfo != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Tailcall to the slow helper
|
||||
ENDFORBIDGC();
|
||||
return HCCALL2(JIT_ClassInitDynamicClass_Helper, pLocalModule, dwDynamicClassDomainID);
|
||||
}
|
||||
HCIMPLEND
|
||||
#include <optdefault.h>
|
||||
|
||||
/*************************************************************/
|
||||
// Slow helper to tail call from the fast one
|
||||
HCIMPL2(void*, JIT_GetSharedGCStaticBaseDynamicClass_Helper, DomainLocalModule *pLocalModule, DWORD dwDynamicClassDomainID)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
void* result = NULL;
|
||||
|
||||
HELPER_METHOD_FRAME_BEGIN_RET_0();
|
||||
|
||||
MethodTable *pMT = pLocalModule->GetDomainAssembly()->GetModule()->GetDynamicClassMT(dwDynamicClassDomainID);
|
||||
_ASSERTE(pMT);
|
||||
|
||||
pMT->CheckRunClassInitThrowing();
|
||||
|
||||
result = (void*)pLocalModule->GetDynamicEntryGCStaticsBasePointer(dwDynamicClassDomainID, pMT->GetLoaderAllocator());
|
||||
HELPER_METHOD_FRAME_END();
|
||||
|
||||
return result;
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
/*************************************************************/
|
||||
#include <optsmallperfcritical.h>
|
||||
HCIMPL2(void*, JIT_GetSharedGCStaticBaseDynamicClass, DomainLocalModule *pLocalModule, DWORD dwDynamicClassDomainID)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
DomainLocalModule::PTR_DynamicClassInfo pLocalInfo = pLocalModule->GetDynamicClassInfoIfInitialized(dwDynamicClassDomainID);
|
||||
if (pLocalInfo != NULL)
|
||||
{
|
||||
PTR_BYTE retval;
|
||||
GET_DYNAMICENTRY_GCSTATICS_BASEPOINTER(pLocalModule->GetDomainAssembly()->GetModule()->GetLoaderAllocator(),
|
||||
pLocalInfo,
|
||||
&retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
// Tailcall to the slow helper
|
||||
ENDFORBIDGC();
|
||||
return HCCALL2(JIT_GetSharedGCStaticBaseDynamicClass_Helper, pLocalModule, dwDynamicClassDomainID);
|
||||
}
|
||||
HCIMPLEND
|
||||
#include <optdefault.h>
|
||||
|
||||
/*********************************************************************/
|
||||
// Slow helper to tail call from the fast one
|
||||
NOINLINE HCIMPL1(void*, JIT_GetGenericsGCStaticBase_Framed, MethodTable *pMT)
|
||||
{
|
||||
CONTRACTL {
|
||||
FCALL_CHECK;
|
||||
PRECONDITION(CheckPointer(pMT));
|
||||
PRECONDITION(pMT->HasGenericsStaticsInfo());
|
||||
} CONTRACTL_END;
|
||||
|
||||
void* base = NULL;
|
||||
|
||||
HELPER_METHOD_FRAME_BEGIN_RET_0();
|
||||
|
||||
_ASSERTE(pMT->IsFullyLoaded());
|
||||
|
||||
pMT->CheckRunClassInitThrowing();
|
||||
|
||||
base = (void*) pMT->GetGCStaticsBasePointer();
|
||||
CONSISTENCY_CHECK(base != NULL);
|
||||
|
||||
HELPER_METHOD_FRAME_END();
|
||||
|
||||
return base;
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
/*********************************************************************/
|
||||
#include <optsmallperfcritical.h>
|
||||
HCIMPL1(void*, JIT_GetGenericsGCStaticBase, MethodTable *pMT)
|
||||
{
|
||||
CONTRACTL {
|
||||
FCALL_CHECK;
|
||||
PRECONDITION(CheckPointer(pMT));
|
||||
PRECONDITION(pMT->HasGenericsStaticsInfo());
|
||||
} CONTRACTL_END;
|
||||
|
||||
DWORD dwDynamicClassDomainID;
|
||||
PTR_Module pModuleForStatics = pMT->GetGenericsStaticsModuleAndID(&dwDynamicClassDomainID);
|
||||
|
||||
DomainLocalModule *pLocalModule = pModuleForStatics->GetDomainLocalModule();
|
||||
_ASSERTE(pLocalModule);
|
||||
|
||||
DomainLocalModule::PTR_DynamicClassInfo pLocalInfo = pLocalModule->GetDynamicClassInfoIfInitialized(dwDynamicClassDomainID);
|
||||
if (pLocalInfo != NULL)
|
||||
{
|
||||
PTR_BYTE retval;
|
||||
GET_DYNAMICENTRY_GCSTATICS_BASEPOINTER(pMT->GetLoaderAllocator(),
|
||||
pLocalInfo,
|
||||
&retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
// Tailcall to the slow helper
|
||||
ENDFORBIDGC();
|
||||
return HCCALL1(JIT_GetGenericsGCStaticBase_Framed, pMT);
|
||||
}
|
||||
HCIMPLEND
|
||||
#include <optdefault.h>
|
||||
|
||||
/*********************************************************************/
|
||||
// Slow helper to tail call from the fast one
|
||||
NOINLINE HCIMPL1(void*, JIT_GetGenericsNonGCStaticBase_Framed, MethodTable *pMT)
|
||||
{
|
||||
CONTRACTL {
|
||||
FCALL_CHECK;
|
||||
PRECONDITION(CheckPointer(pMT));
|
||||
PRECONDITION(pMT->HasGenericsStaticsInfo());
|
||||
} CONTRACTL_END;
|
||||
|
||||
void* base = NULL;
|
||||
|
||||
HELPER_METHOD_FRAME_BEGIN_RET_0();
|
||||
|
||||
_ASSERTE(pMT->IsFullyLoaded());
|
||||
|
||||
// If pMT refers to a method table that requires some initialization work,
|
||||
// then pMT cannot to a method table that is shared by generic instantiations,
|
||||
// because method tables that are shared by generic instantiations do not have
|
||||
// a base for statics to live in.
|
||||
_ASSERTE(pMT->IsClassPreInited() || !pMT->IsSharedByGenericInstantiations());
|
||||
|
||||
pMT->CheckRunClassInitThrowing();
|
||||
|
||||
// We could just return null here instead of returning base when this helper is called just to trigger the cctor
|
||||
base = (void*) pMT->GetNonGCStaticsBasePointer();
|
||||
|
||||
HELPER_METHOD_FRAME_END();
|
||||
|
||||
return base;
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
/*********************************************************************/
|
||||
#include <optsmallperfcritical.h>
|
||||
HCIMPL1(void*, JIT_GetGenericsNonGCStaticBase, MethodTable *pMT)
|
||||
{
|
||||
CONTRACTL {
|
||||
FCALL_CHECK;
|
||||
PRECONDITION(CheckPointer(pMT));
|
||||
PRECONDITION(pMT->HasGenericsStaticsInfo());
|
||||
} CONTRACTL_END;
|
||||
|
||||
// This fast path will typically always be taken once the slow framed path below
|
||||
// has executed once. Sometimes the slow path will be executed more than once,
|
||||
// e.g. if static fields are accessed during the call to CheckRunClassInitThrowing()
|
||||
// in the slow path.
|
||||
|
||||
DWORD dwDynamicClassDomainID;
|
||||
PTR_Module pModuleForStatics = pMT->GetGenericsStaticsModuleAndID(&dwDynamicClassDomainID);
|
||||
|
||||
DomainLocalModule *pLocalModule = pModuleForStatics->GetDomainLocalModule();
|
||||
_ASSERTE(pLocalModule);
|
||||
|
||||
DomainLocalModule::PTR_DynamicClassInfo pLocalInfo = pLocalModule->GetDynamicClassInfoIfInitialized(dwDynamicClassDomainID);
|
||||
if (pLocalInfo != NULL)
|
||||
{
|
||||
PTR_BYTE retval;
|
||||
GET_DYNAMICENTRY_NONGCSTATICS_BASEPOINTER(pMT->GetLoaderAllocator(),
|
||||
pLocalInfo,
|
||||
&retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
// Tailcall to the slow helper
|
||||
ENDFORBIDGC();
|
||||
return HCCALL1(JIT_GetGenericsNonGCStaticBase_Framed, pMT);
|
||||
}
|
||||
HCIMPLEND
|
||||
#include <optdefault.h>
|
||||
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// THREAD STATIC FIELD HELPERS
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
// Define the t_ThreadStatics variable here, so that these helpers can use
|
||||
// the most optimal TLS access pattern for the platform when inlining the
|
||||
// GetThreadLocalStaticBaseIfExistsAndInitialized function
|
||||
#ifdef _MSC_VER
|
||||
__declspec(selectany) __declspec(thread) ThreadLocalData t_ThreadStatics;
|
||||
#else
|
||||
__thread ThreadLocalData t_ThreadStatics;
|
||||
#endif // _MSC_VER
|
||||
|
||||
// This is the routine used by the JIT helpers for the fast path. It is not used by the JIT for the slow path, or by the EE for any path.
|
||||
// This is inlined in the header to improve code gen quality
|
||||
FORCEINLINE void* GetThreadLocalStaticBaseIfExistsAndInitialized(TLSIndex index)
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
TADDR pTLSBaseAddress = (TADDR)NULL;
|
||||
|
||||
if (index.GetTLSIndexType() == TLSIndexType::NonCollectible)
|
||||
{
|
||||
PTRARRAYREF tlsArray = (PTRARRAYREF)UNCHECKED_OBJECTREF_TO_OBJECTREF(t_ThreadStatics.pNonCollectibleTlsArrayData);
|
||||
if (t_ThreadStatics.cNonCollectibleTlsData <= index.GetIndexOffset())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
pTLSBaseAddress = (TADDR)OBJECTREFToObject(tlsArray->GetAt(index.GetIndexOffset() - NUMBER_OF_TLSOFFSETS_NOT_USED_IN_NONCOLLECTIBLE_ARRAY));
|
||||
}
|
||||
else if (index.GetTLSIndexType() == TLSIndexType::DirectOnThreadLocalData)
|
||||
{
|
||||
return ((BYTE*)&t_ThreadStatics) + index.GetIndexOffset();
|
||||
}
|
||||
else
|
||||
{
|
||||
int32_t cCollectibleTlsData = t_ThreadStatics.cCollectibleTlsData;
|
||||
if (cCollectibleTlsData <= index.GetIndexOffset())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OBJECTHANDLE* pCollectibleTlsArrayData = t_ThreadStatics.pCollectibleTlsArrayData;
|
||||
pCollectibleTlsArrayData += index.GetIndexOffset();
|
||||
OBJECTHANDLE objHandle = *pCollectibleTlsArrayData;
|
||||
if (IsHandleNullUnchecked(objHandle))
|
||||
return NULL;
|
||||
pTLSBaseAddress = dac_cast<TADDR>(OBJECTREFToObject(ObjectFromHandle(objHandle)));
|
||||
}
|
||||
return reinterpret_cast<void*>(pTLSBaseAddress);
|
||||
}
|
||||
|
||||
// *** These framed helpers get called if allocation needs to occur or
|
||||
// if the class constructor needs to run
|
||||
|
@ -1447,14 +1273,8 @@ HCIMPL1(void*, JIT_GetNonGCThreadStaticBase_Helper, MethodTable * pMT)
|
|||
|
||||
HELPER_METHOD_FRAME_BEGIN_RET_0();
|
||||
|
||||
_ASSERTE(pMT->IsFullyLoaded());
|
||||
|
||||
// Get the TLM
|
||||
ThreadLocalModule * pThreadLocalModule = ThreadStatics::GetTLM(pMT);
|
||||
_ASSERTE(pThreadLocalModule != NULL);
|
||||
|
||||
// Check if the class constructor needs to be run
|
||||
pThreadLocalModule->CheckRunClassInitThrowing(pMT);
|
||||
pMT->CheckRunClassInitThrowing();
|
||||
|
||||
// Lookup the non-GC statics base pointer
|
||||
base = (void*) pMT->GetNonGCThreadStaticsBasePointer();
|
||||
|
@ -1477,14 +1297,8 @@ HCIMPL1(void*, JIT_GetGCThreadStaticBase_Helper, MethodTable * pMT)
|
|||
|
||||
HELPER_METHOD_FRAME_BEGIN_RET_0();
|
||||
|
||||
_ASSERTE(pMT->IsFullyLoaded());
|
||||
|
||||
// Get the TLM
|
||||
ThreadLocalModule * pThreadLocalModule = ThreadStatics::GetTLM(pMT);
|
||||
_ASSERTE(pThreadLocalModule != NULL);
|
||||
|
||||
// Check if the class constructor needs to be run
|
||||
pThreadLocalModule->CheckRunClassInitThrowing(pMT);
|
||||
pMT->CheckRunClassInitThrowing();
|
||||
|
||||
// Lookup the GC statics base pointer
|
||||
base = (void*) pMT->GetGCThreadStaticsBasePointer();
|
||||
|
@ -1496,14 +1310,6 @@ HCIMPL1(void*, JIT_GetGCThreadStaticBase_Helper, MethodTable * pMT)
|
|||
}
|
||||
HCIMPLEND
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__declspec(thread) uint32_t t_NonGCThreadStaticBlocksSize;
|
||||
__declspec(thread) uint32_t t_GCThreadStaticBlocksSize;
|
||||
#else
|
||||
__thread uint32_t t_NonGCThreadStaticBlocksSize;
|
||||
__thread uint32_t t_GCThreadStaticBlocksSize;
|
||||
#endif // !_MSC_VER
|
||||
|
||||
// *** This helper corresponds to both CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE and
|
||||
// CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR. Even though we always check
|
||||
// if the class constructor has been run, we have a separate helper ID for the "no ctor"
|
||||
|
@ -1511,90 +1317,69 @@ __thread uint32_t t_GCThreadStaticBlocksSize;
|
|||
// possible.
|
||||
|
||||
#include <optsmallperfcritical.h>
|
||||
HCIMPL2(void*, JIT_GetSharedNonGCThreadStaticBase, DomainLocalModule *pDomainLocalModule, DWORD dwClassDomainID)
|
||||
HCIMPL1(void*, JIT_GetNonGCThreadStaticBase, MethodTable *pMT)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
// Get the ModuleIndex
|
||||
ModuleIndex index = pDomainLocalModule->GetModuleIndex();
|
||||
|
||||
// Get the relevant ThreadLocalModule
|
||||
ThreadLocalModule * pThreadLocalModule = ThreadStatics::GetTLMIfExists(index);
|
||||
|
||||
// If the TLM has been allocated and the class has been marked as initialized,
|
||||
// get the pointer to the non-GC statics base and return
|
||||
if (pThreadLocalModule != NULL && pThreadLocalModule->IsPrecomputedClassInitialized(dwClassDomainID))
|
||||
return (void*)pThreadLocalModule->GetPrecomputedNonGCStaticsBasePointer();
|
||||
|
||||
// If the TLM was not allocated or if the class was not marked as initialized
|
||||
// then we have to go through the slow path
|
||||
|
||||
// Obtain the MethodTable
|
||||
MethodTable * pMT = pDomainLocalModule->GetMethodTableFromClassDomainID(dwClassDomainID);
|
||||
_ASSERTE(!pMT->HasGenericsStaticsInfo());
|
||||
void* pThreadStaticBase = GetThreadLocalStaticBaseIfExistsAndInitialized(pMT->GetThreadStaticsInfo()->NonGCTlsIndex);
|
||||
if (pThreadStaticBase != NULL)
|
||||
{
|
||||
return pThreadStaticBase;
|
||||
}
|
||||
|
||||
ENDFORBIDGC();
|
||||
return HCCALL1(JIT_GetNonGCThreadStaticBase_Helper, pMT);
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
HCIMPL1(void*, JIT_GetDynamicNonGCThreadStaticBase, ThreadStaticsInfo *pThreadStaticsInfo)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
void* pThreadStaticBase = GetThreadLocalStaticBaseIfExistsAndInitialized(pThreadStaticsInfo->NonGCTlsIndex);
|
||||
if (pThreadStaticBase != NULL)
|
||||
{
|
||||
return pThreadStaticBase;
|
||||
}
|
||||
|
||||
ENDFORBIDGC();
|
||||
return HCCALL1(JIT_GetNonGCThreadStaticBase_Helper, pThreadStaticsInfo->m_genericStatics.m_DynamicStatics.GetMethodTable());
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
// *** This helper corresponds CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED.
|
||||
// Even though we always check if the class constructor has been run, we have a separate
|
||||
// helper ID for the "no ctor" version because it allows the JIT to do some reordering that
|
||||
// otherwise wouldn't be possible.
|
||||
HCIMPL1(void*, JIT_GetSharedNonGCThreadStaticBaseOptimized, UINT32 staticBlockIndex)
|
||||
HCIMPL1(void*, JIT_GetNonGCThreadStaticBaseOptimized, UINT32 staticBlockIndex)
|
||||
{
|
||||
void* staticBlock = nullptr;
|
||||
|
||||
FCALL_CONTRACT;
|
||||
|
||||
HELPER_METHOD_FRAME_BEGIN_RET_0(); // Set up a frame
|
||||
|
||||
MethodTable * pMT = AppDomain::GetCurrentDomain()->LookupNonGCThreadStaticBlockType(staticBlockIndex);
|
||||
_ASSERTE(!pMT->HasGenericsStaticsInfo());
|
||||
|
||||
// Get the TLM
|
||||
ThreadLocalModule * pThreadLocalModule = ThreadStatics::GetTLM(pMT);
|
||||
_ASSERTE(pThreadLocalModule != NULL);
|
||||
|
||||
TLSIndex tlsIndex(staticBlockIndex);
|
||||
// Check if the class constructor needs to be run
|
||||
pThreadLocalModule->CheckRunClassInitThrowing(pMT);
|
||||
MethodTable *pMT = LookupMethodTableForThreadStaticKnownToBeAllocated(tlsIndex);
|
||||
pMT->CheckRunClassInitThrowing();
|
||||
|
||||
// Lookup the non-GC statics base pointer
|
||||
staticBlock = (void*) pMT->GetNonGCThreadStaticsBasePointer();
|
||||
CONSISTENCY_CHECK(staticBlock != NULL);
|
||||
|
||||
if (t_NonGCThreadStaticBlocksSize <= staticBlockIndex)
|
||||
{
|
||||
UINT32 newThreadStaticBlocksSize = max(2 * t_NonGCThreadStaticBlocksSize, staticBlockIndex + 1);
|
||||
void** newThreadStaticBlocks = (void**) new PTR_BYTE[newThreadStaticBlocksSize * sizeof(PTR_BYTE)];
|
||||
memset(newThreadStaticBlocks + t_NonGCThreadStaticBlocksSize, 0, (newThreadStaticBlocksSize - t_NonGCThreadStaticBlocksSize) * sizeof(PTR_BYTE));
|
||||
|
||||
if (t_NonGCThreadStaticBlocksSize > 0)
|
||||
{
|
||||
memcpy(newThreadStaticBlocks, t_ThreadStatics.NonGCThreadStaticBlocks, t_NonGCThreadStaticBlocksSize * sizeof(PTR_BYTE));
|
||||
delete[] t_ThreadStatics.NonGCThreadStaticBlocks;
|
||||
}
|
||||
|
||||
t_NonGCThreadStaticBlocksSize = newThreadStaticBlocksSize;
|
||||
t_ThreadStatics.NonGCThreadStaticBlocks = newThreadStaticBlocks;
|
||||
}
|
||||
|
||||
void* currentEntry = t_ThreadStatics.NonGCThreadStaticBlocks[staticBlockIndex];
|
||||
// We could be coming here 2nd time after running the ctor when we try to get the static block.
|
||||
// In such case, just avoid adding the same entry.
|
||||
if (currentEntry != staticBlock)
|
||||
{
|
||||
_ASSERTE(currentEntry == nullptr);
|
||||
t_ThreadStatics.NonGCThreadStaticBlocks[staticBlockIndex] = staticBlock;
|
||||
t_ThreadStatics.NonGCMaxThreadStaticBlocks = max(t_ThreadStatics.NonGCMaxThreadStaticBlocks, staticBlockIndex);
|
||||
}
|
||||
HELPER_METHOD_FRAME_END();
|
||||
|
||||
return staticBlock;
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
// *** This helper corresponds CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED2.
|
||||
HCIMPL1(void*, JIT_GetNonGCThreadStaticBaseOptimized2, UINT32 staticBlockIndex)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
return ((BYTE*)&t_ThreadStatics) + staticBlockIndex;
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
#include <optdefault.h>
|
||||
|
||||
// *** This helper corresponds to both CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE and
|
||||
|
@ -1604,39 +1389,43 @@ HCIMPLEND
|
|||
// possible.
|
||||
|
||||
#include <optsmallperfcritical.h>
|
||||
HCIMPL2(void*, JIT_GetSharedGCThreadStaticBase, DomainLocalModule *pDomainLocalModule, DWORD dwClassDomainID)
|
||||
HCIMPL1(void*, JIT_GetGCThreadStaticBase, MethodTable *pMT)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
// Get the ModuleIndex
|
||||
ModuleIndex index = pDomainLocalModule->GetModuleIndex();
|
||||
|
||||
// Get the relevant ThreadLocalModule
|
||||
ThreadLocalModule * pThreadLocalModule = ThreadStatics::GetTLMIfExists(index);
|
||||
|
||||
// If the TLM has been allocated and the class has been marked as initialized,
|
||||
// get the pointer to the GC statics base and return
|
||||
if (pThreadLocalModule != NULL && pThreadLocalModule->IsPrecomputedClassInitialized(dwClassDomainID))
|
||||
return (void*)pThreadLocalModule->GetPrecomputedGCStaticsBasePointer();
|
||||
|
||||
// If the TLM was not allocated or if the class was not marked as initialized
|
||||
// then we have to go through the slow path
|
||||
|
||||
// Obtain the MethodTable
|
||||
MethodTable * pMT = pDomainLocalModule->GetMethodTableFromClassDomainID(dwClassDomainID);
|
||||
_ASSERTE(!pMT->HasGenericsStaticsInfo());
|
||||
void* pThreadStaticBase = GetThreadLocalStaticBaseIfExistsAndInitialized(pMT->GetThreadStaticsInfo()->GCTlsIndex);
|
||||
if (pThreadStaticBase != NULL)
|
||||
{
|
||||
return pThreadStaticBase;
|
||||
}
|
||||
|
||||
ENDFORBIDGC();
|
||||
return HCCALL1(JIT_GetGCThreadStaticBase_Helper, pMT);
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
HCIMPL1(void*, JIT_GetDynamicGCThreadStaticBase, ThreadStaticsInfo *pThreadStaticsInfo)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
void* pThreadStaticBase = GetThreadLocalStaticBaseIfExistsAndInitialized(pThreadStaticsInfo->GCTlsIndex);
|
||||
if (pThreadStaticBase != NULL)
|
||||
{
|
||||
return pThreadStaticBase;
|
||||
}
|
||||
|
||||
ENDFORBIDGC();
|
||||
return HCCALL1(JIT_GetGCThreadStaticBase_Helper, pThreadStaticsInfo->m_genericStatics.m_DynamicStatics.GetMethodTable());
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
#include <optdefault.h>
|
||||
|
||||
// *** This helper corresponds CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED.
|
||||
// Even though we always check if the class constructor has been run, we have a separate
|
||||
// helper ID for the "no ctor" version because it allows the JIT to do some reordering that
|
||||
// otherwise wouldn't be possible.
|
||||
HCIMPL1(void*, JIT_GetSharedGCThreadStaticBaseOptimized, UINT32 staticBlockIndex)
|
||||
HCIMPL1(void*, JIT_GetGCThreadStaticBaseOptimized, UINT32 staticBlockIndex)
|
||||
{
|
||||
void* staticBlock = nullptr;
|
||||
|
||||
|
@ -1644,254 +1433,19 @@ HCIMPL1(void*, JIT_GetSharedGCThreadStaticBaseOptimized, UINT32 staticBlockIndex
|
|||
|
||||
HELPER_METHOD_FRAME_BEGIN_RET_0(); // Set up a frame
|
||||
|
||||
MethodTable * pMT = AppDomain::GetCurrentDomain()->LookupGCThreadStaticBlockType(staticBlockIndex);
|
||||
_ASSERTE(!pMT->HasGenericsStaticsInfo());
|
||||
|
||||
// Get the TLM
|
||||
ThreadLocalModule * pThreadLocalModule = ThreadStatics::GetTLM(pMT);
|
||||
_ASSERTE(pThreadLocalModule != NULL);
|
||||
|
||||
TLSIndex tlsIndex(staticBlockIndex);
|
||||
// Check if the class constructor needs to be run
|
||||
pThreadLocalModule->CheckRunClassInitThrowing(pMT);
|
||||
MethodTable *pMT = LookupMethodTableForThreadStaticKnownToBeAllocated(tlsIndex);
|
||||
pMT->CheckRunClassInitThrowing();
|
||||
|
||||
// Lookup the GC statics base handle and cache it
|
||||
staticBlock = (void*) pMT->GetGCThreadStaticsBaseHandle();
|
||||
CONSISTENCY_CHECK(staticBlock != NULL);
|
||||
|
||||
if (t_GCThreadStaticBlocksSize <= staticBlockIndex)
|
||||
{
|
||||
UINT32 newThreadStaticBlocksSize = max(2 * t_GCThreadStaticBlocksSize, staticBlockIndex + 1);
|
||||
void** newThreadStaticBlocks = (void**) new PTR_BYTE[newThreadStaticBlocksSize * sizeof(PTR_BYTE)];
|
||||
memset(newThreadStaticBlocks + t_GCThreadStaticBlocksSize, 0, (newThreadStaticBlocksSize - t_GCThreadStaticBlocksSize) * sizeof(PTR_BYTE));
|
||||
|
||||
if (t_GCThreadStaticBlocksSize > 0)
|
||||
{
|
||||
memcpy(newThreadStaticBlocks, t_ThreadStatics.GCThreadStaticBlocks, t_GCThreadStaticBlocksSize * sizeof(PTR_BYTE));
|
||||
delete[] t_ThreadStatics.GCThreadStaticBlocks;
|
||||
}
|
||||
|
||||
t_GCThreadStaticBlocksSize = newThreadStaticBlocksSize;
|
||||
t_ThreadStatics.GCThreadStaticBlocks = newThreadStaticBlocks;
|
||||
}
|
||||
|
||||
void* currentEntry = t_ThreadStatics.GCThreadStaticBlocks[staticBlockIndex];
|
||||
// We could be coming here 2nd time after running the ctor when we try to get the static block.
|
||||
// In such case, just avoid adding the same entry.
|
||||
if (currentEntry != staticBlock)
|
||||
{
|
||||
_ASSERTE(currentEntry == nullptr);
|
||||
t_ThreadStatics.GCThreadStaticBlocks[staticBlockIndex] = staticBlock;
|
||||
t_ThreadStatics.GCMaxThreadStaticBlocks = max(t_ThreadStatics.GCMaxThreadStaticBlocks, staticBlockIndex);
|
||||
}
|
||||
|
||||
// Get the data pointer of static block
|
||||
// Lookup the non-GC statics base pointer
|
||||
staticBlock = (void*) pMT->GetGCThreadStaticsBasePointer();
|
||||
|
||||
HELPER_METHOD_FRAME_END();
|
||||
|
||||
return staticBlock;
|
||||
}
|
||||
HCIMPLEND
|
||||
|
||||
// *** This helper corresponds to CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS
|
||||
|
||||
#include <optsmallperfcritical.h>
|
||||
HCIMPL2(void*, JIT_GetSharedNonGCThreadStaticBaseDynamicClass, DomainLocalModule *pDomainLocalModule, DWORD dwDynamicClassDomainID)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
// Get the ModuleIndex
|
||||
ModuleIndex index = pDomainLocalModule->GetModuleIndex();
|
||||
|
||||
// Get the relevant ThreadLocalModule
|
||||
ThreadLocalModule * pThreadLocalModule = ThreadStatics::GetTLMIfExists(index);
|
||||
|
||||
// If the TLM has been allocated and the class has been marked as initialized,
|
||||
// get the pointer to the non-GC statics base and return
|
||||
if (pThreadLocalModule != NULL)
|
||||
{
|
||||
ThreadLocalModule::PTR_DynamicClassInfo pLocalInfo = pThreadLocalModule->GetDynamicClassInfoIfInitialized(dwDynamicClassDomainID);
|
||||
if (pLocalInfo != NULL)
|
||||
{
|
||||
PTR_BYTE retval;
|
||||
GET_DYNAMICENTRY_NONGCTHREADSTATICS_BASEPOINTER(pDomainLocalModule->GetDomainAssembly()->GetModule()->GetLoaderAllocator(),
|
||||
pLocalInfo,
|
||||
&retval);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
// If the TLM was not allocated or if the class was not marked as initialized
|
||||
// then we have to go through the slow path
|
||||
|
||||
// Obtain the Module
|
||||
Module * pModule = pDomainLocalModule->GetDomainAssembly()->GetModule();
|
||||
|
||||
// Obtain the MethodTable
|
||||
MethodTable * pMT = pModule->GetDynamicClassMT(dwDynamicClassDomainID);
|
||||
_ASSERTE(pMT != NULL);
|
||||
_ASSERTE(!pMT->IsSharedByGenericInstantiations());
|
||||
|
||||
// Tailcall to the slow helper
|
||||
ENDFORBIDGC();
|
||||
|
||||
return HCCALL1(JIT_GetNonGCThreadStaticBase_Helper, pMT);
|
||||
|
||||
}
|
||||
HCIMPLEND
|
||||
#include <optdefault.h>
|
||||
|
||||
// *** This helper corresponds to CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS
|
||||
|
||||
#include <optsmallperfcritical.h>
|
||||
HCIMPL2(void*, JIT_GetSharedGCThreadStaticBaseDynamicClass, DomainLocalModule *pDomainLocalModule, DWORD dwDynamicClassDomainID)
|
||||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
// Get the ModuleIndex
|
||||
ModuleIndex index = pDomainLocalModule->GetModuleIndex();
|
||||
|
||||
// Get the relevant ThreadLocalModule
|
||||
ThreadLocalModule * pThreadLocalModule = ThreadStatics::GetTLMIfExists(index);
|
||||
|
||||
// If the TLM has been allocated and the class has been marked as initialized,
|
||||
// get the pointer to the GC statics base and return
|
||||
if (pThreadLocalModule != NULL)
|
||||
{
|
||||
ThreadLocalModule::PTR_DynamicClassInfo pLocalInfo = pThreadLocalModule->GetDynamicClassInfoIfInitialized(dwDynamicClassDomainID);
|
||||
if (pLocalInfo != NULL)
|
||||
{
|
||||
PTR_BYTE retval;
|
||||
GET_DYNAMICENTRY_GCTHREADSTATICS_BASEPOINTER(pDomainLocalModule->GetDomainAssembly()->GetModule()->GetLoaderAllocator(),
|
||||
pLocalInfo,
|
||||
&retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
// If the TLM was not allocated or if the class was not marked as initialized
|
||||
// then we have to go through the slow path
|
||||
|
||||
// Obtain the Module
|
||||
Module * pModule = pDomainLocalModule->GetDomainAssembly()->GetModule();
|
||||
|
||||
// Obtain the MethodTable
|
||||
MethodTable * pMT = pModule->GetDynamicClassMT(dwDynamicClassDomainID);
|
||||
_ASSERTE(pMT != NULL);
|
||||
_ASSERTE(!pMT->IsSharedByGenericInstantiations());
|
||||
|
||||
// Tailcall to the slow helper
|
||||
ENDFORBIDGC();
|
||||
return HCCALL1(JIT_GetGCThreadStaticBase_Helper, pMT);
|
||||
}
|
||||
HCIMPLEND
|
||||
#include <optdefault.h>
|
||||
|
||||
// *** This helper corresponds to CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE
|
||||
|
||||
#include <optsmallperfcritical.h>
|
||||
HCIMPL1(void*, JIT_GetGenericsNonGCThreadStaticBase, MethodTable *pMT)
|
||||
{
|
||||
CONTRACTL {
|
||||
FCALL_CHECK;
|
||||
PRECONDITION(CheckPointer(pMT));
|
||||
PRECONDITION(pMT->HasGenericsStaticsInfo());
|
||||
} CONTRACTL_END;
|
||||
|
||||
// This fast path will typically always be taken once the slow framed path below
|
||||
// has executed once. Sometimes the slow path will be executed more than once,
|
||||
// e.g. if static fields are accessed during the call to CheckRunClassInitThrowing()
|
||||
// in the slow path.
|
||||
|
||||
// Get the Module and dynamic class ID
|
||||
DWORD dwDynamicClassDomainID;
|
||||
PTR_Module pModule = pMT->GetGenericsStaticsModuleAndID(&dwDynamicClassDomainID);
|
||||
|
||||
// Get ModuleIndex
|
||||
ModuleIndex index = pModule->GetModuleIndex();
|
||||
|
||||
// Get the relevant ThreadLocalModule
|
||||
ThreadLocalModule * pThreadLocalModule = ThreadStatics::GetTLMIfExists(index);
|
||||
|
||||
// If the TLM has been allocated and the class has been marked as initialized,
|
||||
// get the pointer to the non-GC statics base and return
|
||||
if (pThreadLocalModule != NULL)
|
||||
{
|
||||
ThreadLocalModule::PTR_DynamicClassInfo pLocalInfo = pThreadLocalModule->GetDynamicClassInfoIfInitialized(dwDynamicClassDomainID);
|
||||
if (pLocalInfo != NULL)
|
||||
{
|
||||
PTR_BYTE retval;
|
||||
GET_DYNAMICENTRY_NONGCSTATICS_BASEPOINTER(pMT->GetLoaderAllocator(),
|
||||
pLocalInfo,
|
||||
&retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
// If the TLM was not allocated or if the class was not marked as initialized
|
||||
// then we have to go through the slow path
|
||||
|
||||
// Tailcall to the slow helper
|
||||
ENDFORBIDGC();
|
||||
return HCCALL1(JIT_GetNonGCThreadStaticBase_Helper, pMT);
|
||||
}
|
||||
HCIMPLEND
|
||||
#include <optdefault.h>
|
||||
|
||||
// *** This helper corresponds to CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE
|
||||
|
||||
#include <optsmallperfcritical.h>
|
||||
HCIMPL1(void*, JIT_GetGenericsGCThreadStaticBase, MethodTable *pMT)
|
||||
{
|
||||
CONTRACTL {
|
||||
FCALL_CHECK;
|
||||
PRECONDITION(CheckPointer(pMT));
|
||||
PRECONDITION(pMT->HasGenericsStaticsInfo());
|
||||
} CONTRACTL_END;
|
||||
|
||||
// This fast path will typically always be taken once the slow framed path below
|
||||
// has executed once. Sometimes the slow path will be executed more than once,
|
||||
// e.g. if static fields are accessed during the call to CheckRunClassInitThrowing()
|
||||
// in the slow path.
|
||||
|
||||
// Get the Module and dynamic class ID
|
||||
DWORD dwDynamicClassDomainID;
|
||||
PTR_Module pModule = pMT->GetGenericsStaticsModuleAndID(&dwDynamicClassDomainID);
|
||||
|
||||
// Get ModuleIndex
|
||||
ModuleIndex index = pModule->GetModuleIndex();
|
||||
|
||||
// Get the relevant ThreadLocalModule
|
||||
ThreadLocalModule * pThreadLocalModule = ThreadStatics::GetTLMIfExists(index);
|
||||
|
||||
// If the TLM has been allocated and the class has been marked as initialized,
|
||||
// get the pointer to the GC statics base and return
|
||||
if (pThreadLocalModule != NULL)
|
||||
{
|
||||
ThreadLocalModule::PTR_DynamicClassInfo pLocalInfo = pThreadLocalModule->GetDynamicClassInfoIfInitialized(dwDynamicClassDomainID);
|
||||
if (pLocalInfo != NULL)
|
||||
{
|
||||
PTR_BYTE retval;
|
||||
GET_DYNAMICENTRY_GCTHREADSTATICS_BASEPOINTER(pMT->GetLoaderAllocator(),
|
||||
pLocalInfo,
|
||||
&retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
// If the TLM was not allocated or if the class was not marked as initialized
|
||||
// then we have to go through the slow path
|
||||
|
||||
// Tailcall to the slow helper
|
||||
ENDFORBIDGC();
|
||||
return HCCALL1(JIT_GetGCThreadStaticBase_Helper, pMT);
|
||||
}
|
||||
HCIMPLEND
|
||||
#include <optdefault.h>
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// STATIC FIELD DYNAMIC HELPERS
|
||||
|
@ -1903,7 +1457,7 @@ HCIMPL1_RAW(TADDR, JIT_StaticFieldAddress_Dynamic, StaticFieldAddressArgs * pArg
|
|||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
TADDR base = HCCALL2(pArgs->staticBaseHelper, pArgs->arg0, pArgs->arg1);
|
||||
TADDR base = HCCALL1(pArgs->staticBaseHelper, pArgs->arg0);
|
||||
return base + pArgs->offset;
|
||||
}
|
||||
HCIMPLEND_RAW
|
||||
|
@ -1914,7 +1468,7 @@ HCIMPL1_RAW(TADDR, JIT_StaticFieldAddressUnbox_Dynamic, StaticFieldAddressArgs *
|
|||
{
|
||||
FCALL_CONTRACT;
|
||||
|
||||
TADDR base = HCCALL2(pArgs->staticBaseHelper, pArgs->arg0, pArgs->arg1);
|
||||
TADDR base = HCCALL1(pArgs->staticBaseHelper, pArgs->arg0);
|
||||
return *(TADDR *)(base + pArgs->offset) + Object::GetOffsetOfFirstField();
|
||||
}
|
||||
HCIMPLEND_RAW
|
||||
|
|
|
@ -65,14 +65,6 @@
|
|||
|
||||
#include "tailcallhelp.h"
|
||||
|
||||
#ifdef TARGET_WINDOWS
|
||||
EXTERN_C uint32_t _tls_index;
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
extern "C" void* __tls_get_addr(void* ti);
|
||||
#endif // !_MSC_VER
|
||||
|
||||
// The Stack Overflow probe takes place in the COOPERATIVE_TRANSITION_BEGIN() macro
|
||||
//
|
||||
|
||||
|
@ -1153,78 +1145,137 @@ static CorInfoHelpFunc getGenericStaticsHelper(FieldDesc * pField)
|
|||
{
|
||||
STANDARD_VM_CONTRACT;
|
||||
|
||||
int helper = CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE;
|
||||
int helper = CORINFO_HELP_GET_NONGCSTATIC_BASE;
|
||||
|
||||
if (pField->GetFieldType() == ELEMENT_TYPE_CLASS ||
|
||||
pField->GetFieldType() == ELEMENT_TYPE_VALUETYPE)
|
||||
{
|
||||
helper = CORINFO_HELP_GETGENERICS_GCSTATIC_BASE;
|
||||
helper = CORINFO_HELP_GET_GCSTATIC_BASE;
|
||||
}
|
||||
|
||||
if (pField->IsThreadStatic())
|
||||
{
|
||||
const int delta = CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE - CORINFO_HELP_GETGENERICS_GCSTATIC_BASE;
|
||||
|
||||
static_assert_no_msg(CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE
|
||||
== CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE + delta);
|
||||
|
||||
helper += (CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE - CORINFO_HELP_GETGENERICS_GCSTATIC_BASE);
|
||||
if (helper == CORINFO_HELP_GET_NONGCSTATIC_BASE)
|
||||
helper = CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE;
|
||||
else
|
||||
helper = CORINFO_HELP_GET_GCTHREADSTATIC_BASE;
|
||||
}
|
||||
|
||||
return (CorInfoHelpFunc)helper;
|
||||
}
|
||||
|
||||
size_t CEEInfo::getClassThreadStaticDynamicInfo(CORINFO_CLASS_HANDLE cls)
|
||||
{
|
||||
CONTRACTL {
|
||||
NOTHROW;
|
||||
GC_NOTRIGGER;
|
||||
MODE_PREEMPTIVE;
|
||||
} CONTRACTL_END;
|
||||
|
||||
size_t result;
|
||||
|
||||
JIT_TO_EE_TRANSITION_LEAF();
|
||||
|
||||
TypeHandle clsTypeHandle(cls);
|
||||
PTR_MethodTable pMT = clsTypeHandle.AsMethodTable();
|
||||
result = (size_t)pMT->GetThreadStaticsInfo();
|
||||
|
||||
EE_TO_JIT_TRANSITION_LEAF();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t CEEInfo::getClassStaticDynamicInfo(CORINFO_CLASS_HANDLE cls)
|
||||
{
|
||||
CONTRACTL {
|
||||
NOTHROW;
|
||||
GC_NOTRIGGER;
|
||||
MODE_PREEMPTIVE;
|
||||
} CONTRACTL_END;
|
||||
|
||||
size_t result;
|
||||
|
||||
JIT_TO_EE_TRANSITION_LEAF();
|
||||
|
||||
TypeHandle clsTypeHandle(cls);
|
||||
PTR_MethodTable pMT = clsTypeHandle.AsMethodTable();
|
||||
result = (size_t)pMT->GetDynamicStaticsInfo();
|
||||
|
||||
EE_TO_JIT_TRANSITION_LEAF();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CorInfoHelpFunc CEEInfo::getSharedStaticsHelper(FieldDesc * pField, MethodTable * pFieldMT)
|
||||
{
|
||||
STANDARD_VM_CONTRACT;
|
||||
|
||||
int helper = CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE;
|
||||
pFieldMT->AttemptToPreinit();
|
||||
bool GCStatic = (pField->GetFieldType() == ELEMENT_TYPE_CLASS ||
|
||||
pField->GetFieldType() == ELEMENT_TYPE_VALUETYPE);
|
||||
bool noCtor = pFieldMT->IsClassInited();
|
||||
bool threadStatic = pField->IsThreadStatic();
|
||||
bool isInexactMT = pFieldMT->IsSharedByGenericInstantiations();
|
||||
bool isCollectible = pFieldMT->Collectible();
|
||||
_ASSERTE(!isInexactMT);
|
||||
CorInfoHelpFunc helper;
|
||||
|
||||
if (pField->GetFieldType() == ELEMENT_TYPE_CLASS ||
|
||||
pField->GetFieldType() == ELEMENT_TYPE_VALUETYPE)
|
||||
if (threadStatic)
|
||||
{
|
||||
helper = CORINFO_HELP_GETSHARED_GCSTATIC_BASE;
|
||||
}
|
||||
|
||||
if (pFieldMT->IsDynamicStatics())
|
||||
if (GCStatic)
|
||||
{
|
||||
const int delta = CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS - CORINFO_HELP_GETSHARED_GCSTATIC_BASE;
|
||||
|
||||
static_assert_no_msg(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS
|
||||
== CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE + delta);
|
||||
|
||||
helper += delta;
|
||||
if (noCtor)
|
||||
helper = CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR;
|
||||
else
|
||||
helper = CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE;
|
||||
}
|
||||
else
|
||||
if ((!pFieldMT->HasClassConstructor() && !pFieldMT->HasBoxedRegularStatics()) || pFieldMT->IsClassInited())
|
||||
{
|
||||
const int delta = CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR - CORINFO_HELP_GETSHARED_GCSTATIC_BASE;
|
||||
|
||||
static_assert_no_msg(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR
|
||||
== CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE + delta);
|
||||
|
||||
helper += delta;
|
||||
if (noCtor)
|
||||
helper = CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR;
|
||||
else
|
||||
helper = CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GCStatic)
|
||||
{
|
||||
if (noCtor)
|
||||
{
|
||||
if (isCollectible)
|
||||
helper = CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE_NOCTOR;
|
||||
else
|
||||
helper = CORINFO_HELP_GETPINNED_GCSTATIC_BASE_NOCTOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isCollectible)
|
||||
helper = CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE;
|
||||
else
|
||||
helper = CORINFO_HELP_GETPINNED_GCSTATIC_BASE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (noCtor)
|
||||
{
|
||||
if (isCollectible)
|
||||
helper = CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE_NOCTOR;
|
||||
else
|
||||
helper = CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE_NOCTOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isCollectible)
|
||||
helper = CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE;
|
||||
else
|
||||
helper = CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pField->IsThreadStatic())
|
||||
{
|
||||
const int delta = CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE - CORINFO_HELP_GETSHARED_GCSTATIC_BASE;
|
||||
|
||||
static_assert_no_msg(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE
|
||||
== CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE + delta);
|
||||
static_assert_no_msg(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR
|
||||
== CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR + delta);
|
||||
static_assert_no_msg(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR
|
||||
== CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR + delta);
|
||||
static_assert_no_msg(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS
|
||||
== CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS + delta);
|
||||
static_assert_no_msg(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS
|
||||
== CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS + delta);
|
||||
|
||||
helper += delta;
|
||||
}
|
||||
|
||||
return (CorInfoHelpFunc)helper;
|
||||
return helper;
|
||||
}
|
||||
|
||||
static CorInfoHelpFunc getInstanceFieldHelper(FieldDesc * pField, CORINFO_ACCESS_FLAGS flags)
|
||||
|
@ -1313,14 +1364,16 @@ uint32_t CEEInfo::getThreadLocalFieldInfo (CORINFO_FIELD_HANDLE field, bool isG
|
|||
|
||||
FieldDesc* fieldDesc = (FieldDesc*)field;
|
||||
_ASSERTE(fieldDesc->IsThreadStatic());
|
||||
MethodTable *pMT = fieldDesc->GetEnclosingMethodTable();
|
||||
pMT->EnsureTlsIndexAllocated();
|
||||
|
||||
if (isGCType)
|
||||
{
|
||||
typeIndex = AppDomain::GetCurrentDomain()->GetGCThreadStaticTypeIndex(fieldDesc->GetEnclosingMethodTable());
|
||||
typeIndex = MethodTableAuxiliaryData::GetThreadStaticsInfo(pMT->GetAuxiliaryData())->GCTlsIndex.GetIndexOffset();
|
||||
}
|
||||
else
|
||||
{
|
||||
typeIndex = AppDomain::GetCurrentDomain()->GetNonGCThreadStaticTypeIndex(fieldDesc->GetEnclosingMethodTable());
|
||||
typeIndex = MethodTableAuxiliaryData::GetThreadStaticsInfo(pMT->GetAuxiliaryData())->NonGCTlsIndex.GetIndexOffset();
|
||||
}
|
||||
|
||||
assert(typeIndex != TypeIDProvider::INVALID_TYPE_ID);
|
||||
|
@ -1329,144 +1382,17 @@ uint32_t CEEInfo::getThreadLocalFieldInfo (CORINFO_FIELD_HANDLE field, bool isG
|
|||
return typeIndex;
|
||||
}
|
||||
|
||||
#if defined(TARGET_WINDOWS)
|
||||
/*********************************************************************/
|
||||
static uint32_t ThreadLocalOffset(void* p)
|
||||
{
|
||||
PTEB Teb = NtCurrentTeb();
|
||||
uint8_t** pTls = (uint8_t**)Teb->ThreadLocalStoragePointer;
|
||||
uint8_t* pOurTls = pTls[_tls_index];
|
||||
return (uint32_t)((uint8_t*)p - pOurTls);
|
||||
}
|
||||
#elif defined(TARGET_OSX)
|
||||
extern "C" void* GetThreadVarsAddress();
|
||||
|
||||
static void* GetThreadVarsSectionAddressFromDesc(uint8_t* p)
|
||||
{
|
||||
_ASSERT(p[0] == 0x48 && p[1] == 0x8d && p[2] == 0x3d);
|
||||
|
||||
// At this point, `p` contains the instruction pointer and is pointing to the above opcodes.
|
||||
// These opcodes are patched by the dynamic linker.
|
||||
// Move beyond the opcodes that we have already checked above.
|
||||
p += 3;
|
||||
|
||||
// The descriptor address is located at *p at this point.
|
||||
// (p + 4) below skips the descriptor address bytes embedded in the instruction and
|
||||
// add it to the `instruction pointer` to find out the address.
|
||||
return *(uint32_t*)p + (p + 4);
|
||||
}
|
||||
|
||||
static void* GetThreadVarsSectionAddress()
|
||||
{
|
||||
#ifdef TARGET_AMD64
|
||||
// On x64, the address is related to rip, so, disassemble the function,
|
||||
// read the offset, and then relative to the IP, find the final address of
|
||||
// __thread_vars section.
|
||||
uint8_t* p = reinterpret_cast<uint8_t*>(&GetThreadVarsAddress);
|
||||
return GetThreadVarsSectionAddressFromDesc(p);
|
||||
#else
|
||||
return GetThreadVarsAddress();
|
||||
#endif // TARGET_AMD64
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Linux
|
||||
|
||||
#ifdef TARGET_AMD64
|
||||
|
||||
extern "C" void* GetTlsIndexObjectDescOffset();
|
||||
|
||||
static void* GetThreadStaticDescriptor(uint8_t* p)
|
||||
{
|
||||
if (!(p[0] == 0x66 && p[1] == 0x48 && p[2] == 0x8d && p[3] == 0x3d))
|
||||
{
|
||||
// The optimization is disabled if coreclr is not compiled in .so format.
|
||||
_ASSERTE(false && "Unexpected code sequence");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// At this point, `p` contains the instruction pointer and is pointing to the above opcodes.
|
||||
// These opcodes are patched by the dynamic linker.
|
||||
// Move beyond the opcodes that we have already checked above.
|
||||
p += 4;
|
||||
|
||||
// The descriptor address is located at *p at this point. Read that and add
|
||||
// it to the instruction pointer to locate the address of `ti` that will be used
|
||||
// to pass to __tls_get_addr during execution.
|
||||
// (p + 4) below skips the descriptor address bytes embedded in the instruction and
|
||||
// add it to the `instruction pointer` to find out the address.
|
||||
return *(uint32_t*)p + (p + 4);
|
||||
}
|
||||
|
||||
static void* GetTlsIndexObjectAddress()
|
||||
{
|
||||
uint8_t* p = reinterpret_cast<uint8_t*>(&GetTlsIndexObjectDescOffset);
|
||||
return GetThreadStaticDescriptor(p);
|
||||
}
|
||||
|
||||
#elif defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
|
||||
|
||||
extern "C" size_t GetThreadStaticsVariableOffset();
|
||||
|
||||
#endif // TARGET_ARM64 || TARGET_LOONGARCH64 || TARGET_RISCV64
|
||||
#endif // TARGET_WINDOWS
|
||||
|
||||
|
||||
void CEEInfo::getThreadLocalStaticBlocksInfo (CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType)
|
||||
void CEEInfo::getThreadLocalStaticBlocksInfo (CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo)
|
||||
{
|
||||
CONTRACTL {
|
||||
NOTHROW;
|
||||
GC_NOTRIGGER;
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
MODE_PREEMPTIVE;
|
||||
} CONTRACTL_END;
|
||||
|
||||
JIT_TO_EE_TRANSITION_LEAF();
|
||||
|
||||
size_t threadStaticBaseOffset = 0;
|
||||
|
||||
#if defined(TARGET_WINDOWS)
|
||||
pInfo->tlsIndex.addr = (void*)static_cast<uintptr_t>(_tls_index);
|
||||
pInfo->tlsIndex.accessType = IAT_VALUE;
|
||||
|
||||
pInfo->offsetOfThreadLocalStoragePointer = offsetof(_TEB, ThreadLocalStoragePointer);
|
||||
threadStaticBaseOffset = ThreadLocalOffset(&t_ThreadStatics);
|
||||
|
||||
#elif defined(TARGET_OSX)
|
||||
|
||||
pInfo->threadVarsSection = GetThreadVarsSectionAddress();
|
||||
|
||||
#elif defined(TARGET_AMD64)
|
||||
|
||||
// For Linux/x64, get the address of tls_get_addr system method and the base address
|
||||
// of struct that we will pass to it.
|
||||
pInfo->tlsGetAddrFtnPtr = reinterpret_cast<void*>(&__tls_get_addr);
|
||||
pInfo->tlsIndexObject = GetTlsIndexObjectAddress();
|
||||
|
||||
#elif defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
|
||||
|
||||
// For Linux arm64/loongarch64/riscv64, just get the offset of thread static variable, and during execution,
|
||||
// this offset, arm64 taken from trpid_elp0 system register gives back the thread variable address.
|
||||
// this offset, loongarch64 taken from $tp register gives back the thread variable address.
|
||||
threadStaticBaseOffset = GetThreadStaticsVariableOffset();
|
||||
|
||||
#else
|
||||
_ASSERTE_MSG(false, "Unsupported scenario of optimizing TLS access on Linux Arm32/x86");
|
||||
#endif // TARGET_WINDOWS
|
||||
|
||||
if (isGCType)
|
||||
{
|
||||
pInfo->offsetOfMaxThreadStaticBlocks = (uint32_t)(threadStaticBaseOffset + offsetof(ThreadStaticBlockInfo, GCMaxThreadStaticBlocks));
|
||||
pInfo->offsetOfThreadStaticBlocks = (uint32_t)(threadStaticBaseOffset + offsetof(ThreadStaticBlockInfo, GCThreadStaticBlocks));
|
||||
}
|
||||
else
|
||||
{
|
||||
pInfo->offsetOfMaxThreadStaticBlocks = (uint32_t)(threadStaticBaseOffset + offsetof(ThreadStaticBlockInfo, NonGCMaxThreadStaticBlocks));
|
||||
pInfo->offsetOfThreadStaticBlocks = (uint32_t)(threadStaticBaseOffset + offsetof(ThreadStaticBlockInfo, NonGCThreadStaticBlocks));
|
||||
}
|
||||
pInfo->offsetOfGCDataPointer = static_cast<uint32_t>(PtrArray::GetDataOffset());
|
||||
|
||||
EE_TO_JIT_TRANSITION_LEAF();
|
||||
JIT_TO_EE_TRANSITION();
|
||||
GetThreadLocalStaticBlocksInfo(pInfo);
|
||||
EE_TO_JIT_TRANSITION();
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
|
@ -1573,42 +1499,35 @@ void CEEInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken,
|
|||
fieldAccessor = CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER;
|
||||
|
||||
pResult->helper = getSharedStaticsHelper(pField, pFieldMT);
|
||||
#if defined(TARGET_ARM)
|
||||
// Optimization is disabled for linux/windows arm
|
||||
#elif !defined(TARGET_WINDOWS) && defined(TARGET_X86)
|
||||
// Optimization is disabled for linux/x86
|
||||
#elif defined(TARGET_LINUX_MUSL) && defined(TARGET_ARM64)
|
||||
// Optimization is disabled for linux musl arm64
|
||||
#elif defined(TARGET_FREEBSD) && defined(TARGET_ARM64)
|
||||
// Optimization is disabled for FreeBSD/arm64
|
||||
#else
|
||||
bool optimizeThreadStaticAccess = true;
|
||||
#if !defined(TARGET_OSX) && defined(TARGET_UNIX) && defined(TARGET_AMD64)
|
||||
// For linux/x64, check if compiled coreclr as .so file and not single file.
|
||||
// For single file, the `tls_index` might not be accurate.
|
||||
// Do not perform this optimization in such case.
|
||||
optimizeThreadStaticAccess = GetTlsIndexObjectAddress() != nullptr;
|
||||
#endif // !TARGET_OSX && TARGET_UNIX && TARGET_AMD64
|
||||
|
||||
if (optimizeThreadStaticAccess)
|
||||
if (CanJITOptimizeTLSAccess())
|
||||
{
|
||||
// For windows x64/x86/arm64, linux x64/arm64/loongarch64/riscv64:
|
||||
// We convert the TLS access to the optimized helper where we will store
|
||||
// the static blocks in TLS directly and access them via inline code.
|
||||
if ((pResult->helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR) ||
|
||||
(pResult->helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE))
|
||||
if ((pResult->helper == CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE_NOCTOR) ||
|
||||
(pResult->helper == CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE) ||
|
||||
(pResult->helper == CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR) ||
|
||||
(pResult->helper == CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE))
|
||||
{
|
||||
fieldAccessor = CORINFO_FIELD_STATIC_TLS_MANAGED;
|
||||
pResult->helper = CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED;
|
||||
pResult->helper = CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED;
|
||||
|
||||
// Check for highly optimized DirectOnThreadLocalData case
|
||||
pFieldMT->EnsureTlsIndexAllocated();
|
||||
if (pFieldMT->GetThreadStaticsInfo()->NonGCTlsIndex.GetTLSIndexType() == TLSIndexType::DirectOnThreadLocalData)
|
||||
{
|
||||
pResult->helper = CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED2;
|
||||
}
|
||||
else if ((pResult->helper == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR) ||
|
||||
(pResult->helper == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE))
|
||||
}
|
||||
else if ((pResult->helper == CORINFO_HELP_GET_GCTHREADSTATIC_BASE_NOCTOR) ||
|
||||
(pResult->helper == CORINFO_HELP_GET_GCTHREADSTATIC_BASE) ||
|
||||
(pResult->helper == CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR) ||
|
||||
(pResult->helper == CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE))
|
||||
{
|
||||
fieldAccessor = CORINFO_FIELD_STATIC_TLS_MANAGED;
|
||||
pResult->helper = CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED;
|
||||
pResult->helper = CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED;
|
||||
}
|
||||
}
|
||||
#endif // TARGET_ARM
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1616,8 +1535,8 @@ void CEEInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken,
|
|||
|
||||
// Allocate space for the local class if necessary, but don't trigger
|
||||
// class construction.
|
||||
DomainLocalModule* pLocalModule = pFieldMT->GetDomainLocalModule();
|
||||
pLocalModule->PopulateClass(pFieldMT);
|
||||
pFieldMT->EnsureStaticDataAllocated();
|
||||
pFieldMT->AttemptToPreinit();
|
||||
|
||||
// We are not going through a helper. The constructor has to be triggered explicitly.
|
||||
if (!pFieldMT->IsClassInited())
|
||||
|
@ -1632,14 +1551,6 @@ void CEEInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken,
|
|||
if (fieldFlags & CORINFO_FLG_FIELD_STATIC_IN_HEAP)
|
||||
{
|
||||
Object* frozenObj = VolatileLoad((Object**)pResult->fieldLookup.addr);
|
||||
|
||||
if (frozenObj == nullptr)
|
||||
{
|
||||
// Boxed static is not yet set, allocate it
|
||||
pFieldMT->AllocateRegularStaticBox(pField, (Object**)pResult->fieldLookup.addr);
|
||||
frozenObj = VolatileLoad((Object**)pResult->fieldLookup.addr);
|
||||
}
|
||||
|
||||
_ASSERT(frozenObj != nullptr);
|
||||
|
||||
// ContainsPointers here is unnecessary but it's cheaper than IsInFrozenSegment
|
||||
|
@ -3725,37 +3636,6 @@ void CEEInfo::LongLifetimeFree(void* obj)
|
|||
EE_TO_JIT_TRANSITION_LEAF();
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
size_t CEEInfo::getClassModuleIdForStatics(CORINFO_CLASS_HANDLE clsHnd, CORINFO_MODULE_HANDLE *pModuleHandle, void **ppIndirection)
|
||||
{
|
||||
CONTRACTL {
|
||||
NOTHROW;
|
||||
GC_NOTRIGGER;
|
||||
MODE_PREEMPTIVE;
|
||||
} CONTRACTL_END;
|
||||
|
||||
size_t result = 0;
|
||||
|
||||
JIT_TO_EE_TRANSITION_LEAF();
|
||||
|
||||
TypeHandle VMClsHnd(clsHnd);
|
||||
Module *pModule = VMClsHnd.AsMethodTable()->GetModuleForStatics();
|
||||
|
||||
if (ppIndirection != NULL)
|
||||
*ppIndirection = NULL;
|
||||
|
||||
// The zapper needs the module handle. The jit should not use it at all.
|
||||
if (pModuleHandle)
|
||||
*pModuleHandle = CORINFO_MODULE_HANDLE(pModule);
|
||||
|
||||
result = pModule->GetModuleID();
|
||||
|
||||
_ASSERTE(result);
|
||||
|
||||
EE_TO_JIT_TRANSITION_LEAF();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
bool CEEInfo::getIsClassInitedFlagAddress(CORINFO_CLASS_HANDLE cls, CORINFO_CONST_LOOKUP* addr, int* offset)
|
||||
|
@ -3767,54 +3647,63 @@ bool CEEInfo::getIsClassInitedFlagAddress(CORINFO_CLASS_HANDLE cls, CORINFO_CONS
|
|||
} CONTRACTL_END;
|
||||
|
||||
_ASSERTE(addr);
|
||||
bool result;
|
||||
|
||||
JIT_TO_EE_TRANSITION_LEAF();
|
||||
|
||||
TypeHandle clsTypeHandle(cls);
|
||||
PTR_MethodTable pMT = clsTypeHandle.AsMethodTable();
|
||||
|
||||
// Impl is based on IsPrecomputedClassInitialized()
|
||||
UINT32 clsIndex = 0;
|
||||
if (pMT->IsDynamicStatics())
|
||||
if (pMT->IsSharedByGenericInstantiations())
|
||||
{
|
||||
clsIndex = (UINT32)pMT->GetModuleDynamicEntryID();
|
||||
// If the MT is shared by generic instantiations, then we don't have an exact flag to check
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
clsIndex = (UINT32)pMT->GetClassIndex();
|
||||
}
|
||||
|
||||
size_t moduleId = pMT->GetModuleForStatics()->GetModuleID();
|
||||
addr->addr = (UINT8*)moduleId + DomainLocalModule::GetOffsetOfDataBlob() + clsIndex;
|
||||
addr->addr = (UINT8*)pMT->getIsClassInitedFlagAddress();
|
||||
addr->accessType = IAT_VALUE;
|
||||
*offset = 0;
|
||||
result = true;
|
||||
}
|
||||
|
||||
EE_TO_JIT_TRANSITION_LEAF();
|
||||
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
bool CEEInfo::getStaticBaseAddress(CORINFO_CLASS_HANDLE cls, bool isGc, CORINFO_CONST_LOOKUP* addr)
|
||||
{
|
||||
CONTRACTL {
|
||||
NOTHROW;
|
||||
GC_NOTRIGGER;
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
MODE_PREEMPTIVE;
|
||||
} CONTRACTL_END;
|
||||
|
||||
JIT_TO_EE_TRANSITION_LEAF();
|
||||
bool result = false;
|
||||
|
||||
JIT_TO_EE_TRANSITION();
|
||||
|
||||
TypeHandle clsTypeHandle(cls);
|
||||
PTR_MethodTable pMT = clsTypeHandle.AsMethodTable();
|
||||
|
||||
if (pMT->IsSharedByGenericInstantiations())
|
||||
{
|
||||
// If the MT is shared by generic instantiations, then we don't have an exact flag to check
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
GCX_COOP();
|
||||
pMT->EnsureStaticDataAllocated();
|
||||
addr->addr = isGc ? pMT->GetGCStaticsBasePointer() : pMT->GetNonGCStaticsBasePointer();
|
||||
addr->accessType = IAT_VALUE;
|
||||
result = true;
|
||||
}
|
||||
|
||||
EE_TO_JIT_TRANSITION_LEAF();
|
||||
EE_TO_JIT_TRANSITION();
|
||||
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
|
@ -3981,6 +3870,7 @@ CorInfoInitClassResult CEEInfo::initClass(
|
|||
|
||||
MethodTable *pTypeToInitMT = typeToInitTH.AsMethodTable();
|
||||
|
||||
pTypeToInitMT->AttemptToPreinit();
|
||||
if (pTypeToInitMT->IsClassInited())
|
||||
{
|
||||
// If the type is initialized there really is nothing to do.
|
||||
|
@ -4094,8 +3984,7 @@ CorInfoInitClassResult CEEInfo::initClass(
|
|||
|
||||
// Allocate space for the local class if necessary, but don't trigger
|
||||
// class construction.
|
||||
DomainLocalModule *pModule = pTypeToInitMT->GetDomainLocalModule();
|
||||
pModule->PopulateClass(pTypeToInitMT);
|
||||
pTypeToInitMT->EnsureStaticDataAllocated();
|
||||
|
||||
if (pTypeToInitMT->IsClassInited())
|
||||
{
|
||||
|
@ -5767,39 +5656,6 @@ void CEEInfo::getCallInfo(
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************/
|
||||
unsigned CEEInfo::getClassDomainID (CORINFO_CLASS_HANDLE clsHnd,
|
||||
void **ppIndirection)
|
||||
{
|
||||
CONTRACTL {
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
MODE_PREEMPTIVE;
|
||||
} CONTRACTL_END;
|
||||
|
||||
unsigned result = 0;
|
||||
|
||||
if (ppIndirection != NULL)
|
||||
*ppIndirection = NULL;
|
||||
|
||||
JIT_TO_EE_TRANSITION();
|
||||
|
||||
TypeHandle VMClsHnd(clsHnd);
|
||||
|
||||
if (VMClsHnd.AsMethodTable()->IsDynamicStatics())
|
||||
{
|
||||
result = (unsigned)VMClsHnd.AsMethodTable()->GetModuleDynamicEntryID();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = (unsigned)VMClsHnd.AsMethodTable()->GetClassIndex();
|
||||
}
|
||||
|
||||
EE_TO_JIT_TRANSITION();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
//
|
||||
// Used by the JIT to determine whether the profiler is tracking object
|
||||
|
@ -6153,22 +6009,20 @@ CorInfoHelpFunc CEEInfo::getSharedCCtorHelper(CORINFO_CLASS_HANDLE clsHnd)
|
|||
MODE_PREEMPTIVE;
|
||||
} CONTRACTL_END;
|
||||
|
||||
CorInfoHelpFunc result = CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE;
|
||||
TypeHandle VMClsHnd(clsHnd);
|
||||
|
||||
JIT_TO_EE_TRANSITION_LEAF();
|
||||
|
||||
TypeHandle cls(clsHnd);
|
||||
MethodTable* pMT = cls.AsMethodTable();
|
||||
|
||||
if (pMT->IsDynamicStatics())
|
||||
CorInfoHelpFunc result;
|
||||
if (VMClsHnd.GetMethodTable()->IsDynamicStatics())
|
||||
{
|
||||
_ASSERTE(!cls.ContainsGenericVariables());
|
||||
_ASSERTE(pMT->GetModuleDynamicEntryID() != (unsigned) -1);
|
||||
|
||||
result = CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS;
|
||||
if (VMClsHnd.GetMethodTable()->GetClass()->GetNonGCRegularStaticFieldBytes() > 0)
|
||||
result = CORINFO_HELP_GET_NONGCSTATIC_BASE;
|
||||
else if (VMClsHnd.GetMethodTable()->GetClass()->GetNumHandleRegularStatics() > 0)
|
||||
result = CORINFO_HELP_GET_GCSTATIC_BASE;
|
||||
else
|
||||
result = CORINFO_HELP_INITCLASS;
|
||||
}
|
||||
|
||||
EE_TO_JIT_TRANSITION_LEAF();
|
||||
else
|
||||
result = CORINFO_HELP_INITCLASS;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -11772,8 +11626,7 @@ bool CEEInfo::getStaticFieldContent(CORINFO_FIELD_HANDLE fieldHnd, uint8_t* buff
|
|||
|
||||
// Allocate space for the local class if necessary, but don't trigger
|
||||
// class construction.
|
||||
DomainLocalModule* pLocalModule = pEnclosingMT->GetDomainLocalModule();
|
||||
pLocalModule->PopulateClass(pEnclosingMT);
|
||||
pEnclosingMT->EnsureStaticDataAllocated();
|
||||
|
||||
if (!field->IsThreadStatic() && pEnclosingMT->IsClassInited() && IsFdInitOnly(field->GetAttributes()))
|
||||
{
|
||||
|
@ -11955,8 +11808,7 @@ CORINFO_CLASS_HANDLE CEEJitInfo::getStaticFieldCurrentClass(CORINFO_FIELD_HANDLE
|
|||
{
|
||||
// Allocate space for the local class if necessary, but don't trigger
|
||||
// class construction.
|
||||
DomainLocalModule *pLocalModule = pEnclosingMT->GetDomainLocalModule();
|
||||
pLocalModule->PopulateClass(pEnclosingMT);
|
||||
pEnclosingMT->EnsureStaticDataAllocated();
|
||||
|
||||
GCX_COOP();
|
||||
|
||||
|
@ -13700,33 +13552,6 @@ BOOL LoadDynamicInfoEntry(Module *currentModule,
|
|||
result = pMgr->GetCallStub(ownerType, slot);
|
||||
}
|
||||
break;
|
||||
|
||||
case ENCODE_CLASS_ID_FOR_STATICS:
|
||||
{
|
||||
TypeHandle th = ZapSig::DecodeType(currentModule, pInfoModule, pBlob);
|
||||
|
||||
MethodTable * pMT = th.AsMethodTable();
|
||||
if (pMT->IsDynamicStatics())
|
||||
{
|
||||
result = pMT->GetModuleDynamicEntryID();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = pMT->GetClassIndex();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ENCODE_MODULE_ID_FOR_GENERIC_STATICS:
|
||||
{
|
||||
TypeHandle th = ZapSig::DecodeType(currentModule, pInfoModule, pBlob);
|
||||
|
||||
MethodTable * pMT = th.AsMethodTable();
|
||||
|
||||
result = pMT->GetModuleForStatics()->GetModuleID();
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef FEATURE_READYTORUN
|
||||
case ENCODE_READYTORUN_HELPER:
|
||||
{
|
||||
|
|
|
@ -101,26 +101,6 @@ BOOL LoadDynamicInfoEntry(Module *currentModule,
|
|||
|
||||
#endif // TARGET_X86
|
||||
|
||||
// thread local struct to store the "thread static blocks"
|
||||
struct ThreadStaticBlockInfo
|
||||
{
|
||||
uint32_t NonGCMaxThreadStaticBlocks;
|
||||
void** NonGCThreadStaticBlocks;
|
||||
|
||||
uint32_t GCMaxThreadStaticBlocks;
|
||||
void** GCThreadStaticBlocks;
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
EXTERN_C __declspec(thread) ThreadStaticBlockInfo t_ThreadStatics;
|
||||
EXTERN_C __declspec(thread) uint32_t t_NonGCThreadStaticBlocksSize;
|
||||
EXTERN_C __declspec(thread) uint32_t t_GCThreadStaticBlocksSize;
|
||||
#else
|
||||
EXTERN_C __thread ThreadStaticBlockInfo t_ThreadStatics;
|
||||
EXTERN_C __thread uint32_t t_NonGCThreadStaticBlocksSize;
|
||||
EXTERN_C __thread uint32_t t_GCThreadStaticBlocksSize;
|
||||
#endif // _MSC_VER
|
||||
|
||||
//
|
||||
// JIT HELPER ALIASING FOR PORTABILITY.
|
||||
//
|
||||
|
@ -175,30 +155,53 @@ EXTERN_C FCDECL_MONHELPER(JIT_MonEnterStatic_Portable, AwareLock *lock);
|
|||
EXTERN_C FCDECL_MONHELPER(JIT_MonExitStatic, AwareLock *lock);
|
||||
EXTERN_C FCDECL_MONHELPER(JIT_MonExitStatic_Portable, AwareLock *lock);
|
||||
|
||||
|
||||
#ifndef JIT_GetSharedGCStaticBase
|
||||
#define JIT_GetSharedGCStaticBase JIT_GetSharedGCStaticBase_Portable
|
||||
#ifndef JIT_GetGCStaticBase
|
||||
#define JIT_GetGCStaticBase JIT_GetGCStaticBase_Portable
|
||||
#endif
|
||||
EXTERN_C FCDECL2(void*, JIT_GetSharedGCStaticBase, DomainLocalModule *pLocalModule, DWORD dwModuleClassID);
|
||||
EXTERN_C FCDECL2(void*, JIT_GetSharedGCStaticBase_Portable, DomainLocalModule *pLocalModule, DWORD dwModuleClassID);
|
||||
EXTERN_C FCDECL1(void*, JIT_GetGCStaticBase, MethodTable *pMT);
|
||||
EXTERN_C FCDECL1(void*, JIT_GetGCStaticBase_Portable, MethodTable *pMT);
|
||||
|
||||
#ifndef JIT_GetSharedNonGCStaticBase
|
||||
#define JIT_GetSharedNonGCStaticBase JIT_GetSharedNonGCStaticBase_Portable
|
||||
#ifndef JIT_GetNonGCStaticBase
|
||||
#define JIT_GetNonGCStaticBase JIT_GetNonGCStaticBase_Portable
|
||||
#endif
|
||||
EXTERN_C FCDECL2(void*, JIT_GetSharedNonGCStaticBase, DomainLocalModule *pLocalModule, DWORD dwModuleClassID);
|
||||
EXTERN_C FCDECL2(void*, JIT_GetSharedNonGCStaticBase_Portable, DomainLocalModule *pLocalModule, DWORD dwModuleClassID);
|
||||
EXTERN_C FCDECL1(void*, JIT_GetNonGCStaticBase, MethodTable *pMT);
|
||||
EXTERN_C FCDECL1(void*, JIT_GetNonGCStaticBase_Portable, MethodTable *pMT);
|
||||
|
||||
#ifndef JIT_GetSharedGCStaticBaseNoCtor
|
||||
#define JIT_GetSharedGCStaticBaseNoCtor JIT_GetSharedGCStaticBaseNoCtor_Portable
|
||||
#ifndef JIT_GetGCStaticBaseNoCtor
|
||||
#define JIT_GetGCStaticBaseNoCtor JIT_GetGCStaticBaseNoCtor_Portable
|
||||
#endif
|
||||
EXTERN_C FCDECL1(void*, JIT_GetSharedGCStaticBaseNoCtor, DomainLocalModule *pLocalModule);
|
||||
EXTERN_C FCDECL1(void*, JIT_GetSharedGCStaticBaseNoCtor_Portable, DomainLocalModule *pLocalModule);
|
||||
EXTERN_C FCDECL1(void*, JIT_GetGCStaticBaseNoCtor, MethodTable *pMT);
|
||||
EXTERN_C FCDECL1(void*, JIT_GetGCStaticBaseNoCtor_Portable, MethodTable *pMT);
|
||||
|
||||
#ifndef JIT_GetSharedNonGCStaticBaseNoCtor
|
||||
#define JIT_GetSharedNonGCStaticBaseNoCtor JIT_GetSharedNonGCStaticBaseNoCtor_Portable
|
||||
#ifndef JIT_GetNonGCStaticBaseNoCtor
|
||||
#define JIT_GetNonGCStaticBaseNoCtor JIT_GetNonGCStaticBaseNoCtor_Portable
|
||||
#endif
|
||||
EXTERN_C FCDECL1(void*, JIT_GetSharedNonGCStaticBaseNoCtor, DomainLocalModule *pLocalModule);
|
||||
EXTERN_C FCDECL1(void*, JIT_GetSharedNonGCStaticBaseNoCtor_Portable, DomainLocalModule *pLocalModule);
|
||||
EXTERN_C FCDECL1(void*, JIT_GetNonGCStaticBaseNoCtor, MethodTable *pMT);
|
||||
EXTERN_C FCDECL1(void*, JIT_GetNonGCStaticBaseNoCtor_Portable, MethodTable *pMT);
|
||||
|
||||
#ifndef JIT_GetDynamicGCStaticBase
|
||||
#define JIT_GetDynamicGCStaticBase JIT_GetDynamicGCStaticBase_Portable
|
||||
#endif
|
||||
EXTERN_C FCDECL1(void*, JIT_GetDynamicGCStaticBase, DynamicStaticsInfo* pStaticsInfo);
|
||||
EXTERN_C FCDECL1(void*, JIT_GetDynamicGCStaticBase_Portable, DynamicStaticsInfo* pStaticsInfo);
|
||||
|
||||
#ifndef JIT_GetDynamicNonGCStaticBase
|
||||
#define JIT_GetDynamicNonGCStaticBase JIT_GetDynamicNonGCStaticBase_Portable
|
||||
#endif
|
||||
EXTERN_C FCDECL1(void*, JIT_GetDynamicNonGCStaticBase, DynamicStaticsInfo* pStaticsInfo);
|
||||
EXTERN_C FCDECL1(void*, JIT_GetDynamicNonGCStaticBase_Portable, DynamicStaticsInfo* pStaticsInfo);
|
||||
|
||||
#ifndef JIT_GetDynamicGCStaticBaseNoCtor
|
||||
#define JIT_GetDynamicGCStaticBaseNoCtor JIT_GetDynamicGCStaticBaseNoCtor_Portable
|
||||
#endif
|
||||
EXTERN_C FCDECL1(void*, JIT_GetDynamicGCStaticBaseNoCtor, DynamicStaticsInfo* pStaticsInfo);
|
||||
EXTERN_C FCDECL1(void*, JIT_GetDynamicGCStaticBaseNoCtor_Portable, DynamicStaticsInfo* pStaticsInfo);
|
||||
|
||||
#ifndef JIT_GetDynamicNonGCStaticBaseNoCtor
|
||||
#define JIT_GetDynamicNonGCStaticBaseNoCtor JIT_GetDynamicNonGCStaticBaseNoCtor_Portable
|
||||
#endif
|
||||
EXTERN_C FCDECL1(void*, JIT_GetDynamicNonGCStaticBaseNoCtor, DynamicStaticsInfo* pStaticsInfo);
|
||||
EXTERN_C FCDECL1(void*, JIT_GetDynamicNonGCStaticBaseNoCtor_Portable, DynamicStaticsInfo* pStaticsInfo);
|
||||
|
||||
extern FCDECL1(Object*, JIT_NewS_MP_FastPortable, CORINFO_CLASS_HANDLE typeHnd_);
|
||||
extern FCDECL1(Object*, JIT_New, CORINFO_CLASS_HANDLE typeHnd_);
|
||||
|
@ -219,8 +222,8 @@ EXTERN_C FCDECL_MONHELPER(JITutil_MonSignal, AwareLock* lock);
|
|||
EXTERN_C FCDECL_MONHELPER(JITutil_MonContention, AwareLock* awarelock);
|
||||
EXTERN_C FCDECL2(void, JITutil_MonReliableContention, AwareLock* awarelock, BYTE* pbLockTaken);
|
||||
|
||||
EXTERN_C FCDECL2(void*, JIT_GetSharedNonGCStaticBase_Helper, DomainLocalModule *pLocalModule, DWORD dwClassDomainID);
|
||||
EXTERN_C FCDECL2(void*, JIT_GetSharedGCStaticBase_Helper, DomainLocalModule *pLocalModule, DWORD dwClassDomainID);
|
||||
EXTERN_C FCDECL1(void*, JIT_GetNonGCStaticBase_Helper, MethodTable *pMT);
|
||||
EXTERN_C FCDECL1(void*, JIT_GetGCStaticBase_Helper, MethodTable *pMT);
|
||||
|
||||
EXTERN_C void DoJITFailFast ();
|
||||
EXTERN_C FCDECL0(void, JIT_FailFast);
|
||||
|
@ -1098,13 +1101,12 @@ struct VirtualFunctionPointerArgs
|
|||
|
||||
FCDECL2(CORINFO_MethodPtr, JIT_VirtualFunctionPointer_Dynamic, Object * objectUNSAFE, VirtualFunctionPointerArgs * pArgs);
|
||||
|
||||
typedef HCCALL2_PTR(TADDR, FnStaticBaseHelper, TADDR arg0, TADDR arg1);
|
||||
typedef HCCALL1_PTR(TADDR, FnStaticBaseHelper, TADDR arg0);
|
||||
|
||||
struct StaticFieldAddressArgs
|
||||
{
|
||||
FnStaticBaseHelper staticBaseHelper;
|
||||
TADDR arg0;
|
||||
TADDR arg1;
|
||||
SIZE_T offset;
|
||||
};
|
||||
|
||||
|
|
|
@ -1078,6 +1078,7 @@ void LoaderAllocator::Init(BaseDomain *pDomain, BYTE *pExecutableHeapMemory)
|
|||
|
||||
DWORD dwLowFrequencyHeapReserveSize;
|
||||
DWORD dwHighFrequencyHeapReserveSize;
|
||||
DWORD dwStaticsHeapReserveSize;
|
||||
DWORD dwStubHeapReserveSize;
|
||||
DWORD dwExecutableHeapReserveSize;
|
||||
DWORD dwCodeHeapReserveSize;
|
||||
|
@ -1092,12 +1093,14 @@ void LoaderAllocator::Init(BaseDomain *pDomain, BYTE *pExecutableHeapMemory)
|
|||
dwStubHeapReserveSize = COLLECTIBLE_STUB_HEAP_SIZE;
|
||||
dwCodeHeapReserveSize = COLLECTIBLE_CODEHEAP_SIZE;
|
||||
dwVSDHeapReserveSize = COLLECTIBLE_VIRTUALSTUBDISPATCH_HEAP_SPACE;
|
||||
dwStaticsHeapReserveSize = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
dwLowFrequencyHeapReserveSize = LOW_FREQUENCY_HEAP_RESERVE_SIZE;
|
||||
dwHighFrequencyHeapReserveSize = HIGH_FREQUENCY_HEAP_RESERVE_SIZE;
|
||||
dwStubHeapReserveSize = STUB_HEAP_RESERVE_SIZE;
|
||||
dwStaticsHeapReserveSize = STATIC_FIELD_HEAP_RESERVE_SIZE;
|
||||
|
||||
// Non-collectible assemblies do not reserve space for these heaps.
|
||||
dwCodeHeapReserveSize = 0;
|
||||
|
@ -1116,6 +1119,7 @@ void LoaderAllocator::Init(BaseDomain *pDomain, BYTE *pExecutableHeapMemory)
|
|||
|
||||
DWORD dwTotalReserveMemSize = dwLowFrequencyHeapReserveSize
|
||||
+ dwHighFrequencyHeapReserveSize
|
||||
+ dwStaticsHeapReserveSize
|
||||
+ dwStubHeapReserveSize
|
||||
+ dwCodeHeapReserveSize
|
||||
+ dwVSDHeapReserveSize
|
||||
|
@ -1181,6 +1185,20 @@ void LoaderAllocator::Init(BaseDomain *pDomain, BYTE *pExecutableHeapMemory)
|
|||
m_pHighFrequencyHeap->m_fPermitStubsWithUnwindInfo = TRUE;
|
||||
#endif
|
||||
|
||||
if (dwStaticsHeapReserveSize != 0)
|
||||
{
|
||||
m_pStaticsHeap = new (&m_StaticsHeapInstance) LoaderHeap(STATIC_FIELD_HEAP_RESERVE_SIZE,
|
||||
STATIC_FIELD_HEAP_COMMIT_SIZE,
|
||||
initReservedMem,
|
||||
dwStaticsHeapReserveSize);
|
||||
initReservedMem += dwStaticsHeapReserveSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ASSERTE(m_pHighFrequencyHeap != NULL);
|
||||
m_pStaticsHeap = m_pHighFrequencyHeap;
|
||||
}
|
||||
|
||||
m_pStubHeap = new (&m_StubHeapInstance) LoaderHeap(STUB_HEAP_RESERVE_SIZE,
|
||||
STUB_HEAP_COMMIT_SIZE,
|
||||
initReservedMem,
|
||||
|
@ -1368,6 +1386,12 @@ void LoaderAllocator::Terminate()
|
|||
m_pLowFrequencyHeap = NULL;
|
||||
}
|
||||
|
||||
if ((m_pStaticsHeap != NULL) && (m_pStaticsHeap != m_pHighFrequencyHeap))
|
||||
{
|
||||
m_pStaticsHeap->~LoaderHeap();
|
||||
m_pStaticsHeap = NULL;
|
||||
}
|
||||
|
||||
if (m_pHighFrequencyHeap != NULL)
|
||||
{
|
||||
#ifdef STUBLINKER_GENERATES_UNWIND_INFO
|
||||
|
@ -1462,6 +1486,10 @@ void LoaderAllocator::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
|
|||
{
|
||||
m_pHighFrequencyHeap->EnumMemoryRegions(flags);
|
||||
}
|
||||
if (m_pStaticsHeap.IsValid())
|
||||
{
|
||||
m_pStaticsHeap->EnumMemoryRegions(flags);
|
||||
}
|
||||
if (m_pStubHeap.IsValid())
|
||||
{
|
||||
m_pStubHeap->EnumMemoryRegions(flags);
|
||||
|
@ -1501,6 +1529,8 @@ SIZE_T LoaderAllocator::EstimateSize()
|
|||
SIZE_T retval=0;
|
||||
if(m_pHighFrequencyHeap)
|
||||
retval+=m_pHighFrequencyHeap->GetSize();
|
||||
if(m_pStaticsHeap)
|
||||
retval+=m_pStaticsHeap->GetSize();
|
||||
if(m_pLowFrequencyHeap)
|
||||
retval+=m_pLowFrequencyHeap->GetSize();
|
||||
if(m_pStubHeap)
|
||||
|
@ -1906,6 +1936,12 @@ void AssemblyLoaderAllocator::CleanupHandles()
|
|||
|
||||
_ASSERTE(GetDomain()->IsAppDomain());
|
||||
|
||||
if (m_hLoaderAllocatorObjectHandle != NULL)
|
||||
{
|
||||
GCX_COOP();
|
||||
FreeTLSIndicesForLoaderAllocator(this);
|
||||
}
|
||||
|
||||
// This method doesn't take a lock around RemoveHead because it's supposed to
|
||||
// be called only from Terminate
|
||||
while (!m_handleCleanupList.IsEmpty())
|
||||
|
@ -2217,6 +2253,140 @@ PTR_OnStackReplacementManager LoaderAllocator::GetOnStackReplacementManager()
|
|||
#endif //
|
||||
#endif // FEATURE_ON_STACK_REPLACEMENT
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
void LoaderAllocator::AllocateBytesForStaticVariables(DynamicStaticsInfo* pStaticsInfo, uint32_t cbMem)
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
INJECT_FAULT(COMPlusThrowOM());
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
if (cbMem == 0)
|
||||
return;
|
||||
|
||||
if (IsCollectible())
|
||||
{
|
||||
GCX_COOP();
|
||||
uint32_t doubleSlots = AlignUp(cbMem, sizeof(double)) / sizeof(double);
|
||||
BASEARRAYREF ptrArray = (BASEARRAYREF)AllocatePrimitiveArray(ELEMENT_TYPE_R8, doubleSlots);
|
||||
GCPROTECT_BEGIN(ptrArray);
|
||||
// Keep this allocation alive till the LoaderAllocator is collected
|
||||
AllocateHandle(ptrArray);
|
||||
CrstHolder cs(&m_crstLoaderAllocator);
|
||||
{
|
||||
if (pStaticsInfo->GetNonGCStaticsPointer() == NULL)
|
||||
{
|
||||
GCX_FORBID();
|
||||
// Allocating a weak interior handle is a tricky thing.
|
||||
// 1. If there are multiple weak interior handles that point at a given interior pointer location, there will be heap corruption
|
||||
// 2. If the interior handle is created, but not registered for cleanup, it is a memory leak
|
||||
// 3. Since the weak interior handle doesn't actually keep the object alive, it needs to be kept alive by some other means
|
||||
//
|
||||
// We work around these details by the following means
|
||||
// 1. We use a LOADERHANDLE to keep the object alive until the LoaderAllocator is freed.
|
||||
// 2. We hold the crstLoaderAllocatorLock, and double check to wnsure that the data is ready to be filled in
|
||||
// 3. We create the weak interior handle, and register it for cleanup (which can fail with an OOM) before updating the statics data to have the pointer
|
||||
// 4. Registration for cleanup cannot trigger a GC
|
||||
// 5. We then unconditionally set the statics pointer.
|
||||
WeakInteriorHandleHolder weakHandleHolder = GetAppDomain()->CreateWeakInteriorHandle(ptrArray, &pStaticsInfo->m_pNonGCStatics);
|
||||
RegisterHandleForCleanupLocked(weakHandleHolder.GetValue());
|
||||
weakHandleHolder.SuppressRelease();
|
||||
bool didUpdateStaticsPointer = pStaticsInfo->InterlockedUpdateStaticsPointer(/* isGCPointer */false, (TADDR)ptrArray->GetDataPtr());
|
||||
_ASSERTE(didUpdateStaticsPointer);
|
||||
}
|
||||
}
|
||||
GCPROTECT_END();
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t initialcbMem = cbMem;
|
||||
if (initialcbMem >= 8)
|
||||
{
|
||||
cbMem = ALIGN_UP(cbMem, sizeof(double));
|
||||
#ifndef TARGET_64BIT
|
||||
cbMem += 4; // We need to align the memory to 8 bytes so that static doubles, and static int64's work
|
||||
// and this allocator doesn't guarantee 8 byte alignment, so allocate 4 bytes extra, and alignup.
|
||||
// Technically this isn't necessary on X86, but it's simpler to do it unconditionally.
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// Always allocate in multiples of pointer size
|
||||
cbMem = ALIGN_UP(cbMem, sizeof(TADDR));
|
||||
}
|
||||
uint8_t* pbMem = (uint8_t*)(void*)GetStaticsHeap()->AllocMem(S_SIZE_T(cbMem));
|
||||
#ifndef TARGET_64BIT // Second part of alignment work
|
||||
if (initialcbMem >= 8)
|
||||
{
|
||||
pbMem = (uint8_t*)ALIGN_UP(pbMem, 8);
|
||||
}
|
||||
#endif
|
||||
pStaticsInfo->InterlockedUpdateStaticsPointer(/* isGCPointer */false, (TADDR)pbMem);
|
||||
}
|
||||
}
|
||||
|
||||
void LoaderAllocator::AllocateGCHandlesBytesForStaticVariables(DynamicStaticsInfo* pStaticsInfo, uint32_t cSlots, MethodTable* pMTToFillWithStaticBoxes)
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
INJECT_FAULT(COMPlusThrowOM());
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
if (cSlots == 0)
|
||||
return;
|
||||
|
||||
if (IsCollectible())
|
||||
{
|
||||
GCX_COOP();
|
||||
BASEARRAYREF ptrArray = (BASEARRAYREF)AllocateObjectArray(cSlots, g_pObjectClass, /* bAllocateInPinnedHeap = */FALSE);
|
||||
GCPROTECT_BEGIN(ptrArray);
|
||||
if (pMTToFillWithStaticBoxes != NULL)
|
||||
{
|
||||
OBJECTREF* pArray = (OBJECTREF*)ptrArray->GetDataPtr();
|
||||
GCPROTECT_BEGININTERIOR(pArray);
|
||||
pMTToFillWithStaticBoxes->AllocateRegularStaticBoxes(&pArray);
|
||||
GCPROTECT_END();
|
||||
}
|
||||
// Keep this allocation alive till the LoaderAllocator is collected
|
||||
AllocateHandle(ptrArray);
|
||||
CrstHolder cs(&m_crstLoaderAllocator);
|
||||
{
|
||||
if (pStaticsInfo->GetGCStaticsPointer() == NULL)
|
||||
{
|
||||
GCX_FORBID();
|
||||
// Allocating a weak interior handle is a tricky thing.
|
||||
// 1. If there are multiple weak interior handles that point at a given interior pointer location, there will be heap corruption
|
||||
// 2. If the interior handle is created, but not registered for cleanup, it is a memory leak
|
||||
// 3. Since the weak interior handle doesn't actually keep the object alive, it needs to be kept alive by some other means
|
||||
//
|
||||
// We work around these details by the following means
|
||||
// 1. We use a LOADERHANDLE to keep the object alive until the LoaderAllocator is freed.
|
||||
// 2. We hold the crstLoaderAllocatorLock, and double check to wnsure that the data is ready to be filled in
|
||||
// 3. We create the weak interior handle, and register it for cleanup (which can fail with an OOM) before updating the statics data to have the pointer
|
||||
// 4. Registration for cleanup cannot trigger a GC
|
||||
// 5. We then unconditionally set the statics pointer.
|
||||
WeakInteriorHandleHolder weakHandleHolder = GetAppDomain()->CreateWeakInteriorHandle(ptrArray, &pStaticsInfo->m_pGCStatics);
|
||||
RegisterHandleForCleanupLocked(weakHandleHolder.GetValue());
|
||||
weakHandleHolder.SuppressRelease();
|
||||
bool didUpdateStaticsPointer = pStaticsInfo->InterlockedUpdateStaticsPointer(/* isGCPointer */true, (TADDR)ptrArray->GetDataPtr());
|
||||
_ASSERTE(didUpdateStaticsPointer);
|
||||
}
|
||||
}
|
||||
GCPROTECT_END();
|
||||
}
|
||||
else
|
||||
{
|
||||
GetDomain()->AllocateObjRefPtrsInLargeTable(cSlots, pStaticsInfo, pMTToFillWithStaticBoxes);
|
||||
}
|
||||
}
|
||||
#endif // !DACCESS_COMPILE
|
||||
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
bool LoaderAllocator::InsertObjectIntoFieldWithLifetimeOfCollectibleLoaderAllocator(OBJECTREF value, Object** pField)
|
||||
|
|
|
@ -306,8 +306,10 @@ protected:
|
|||
BYTE m_PrecodeHeapInstance[sizeof(CodeFragmentHeap)];
|
||||
BYTE m_FixupPrecodeHeapInstance[sizeof(LoaderHeap)];
|
||||
BYTE m_NewStubPrecodeHeapInstance[sizeof(LoaderHeap)];
|
||||
BYTE m_StaticsHeapInstance[sizeof(LoaderHeap)];
|
||||
PTR_LoaderHeap m_pLowFrequencyHeap;
|
||||
PTR_LoaderHeap m_pHighFrequencyHeap;
|
||||
PTR_LoaderHeap m_pStaticsHeap;
|
||||
PTR_LoaderHeap m_pStubHeap; // stubs for PInvoke, remoting, etc
|
||||
PTR_CodeFragmentHeap m_pPrecodeHeap;
|
||||
PTR_LoaderHeap m_pExecutableHeap;
|
||||
|
@ -349,6 +351,8 @@ protected:
|
|||
Volatile<PgoManager *> m_pgoManager;
|
||||
#endif // FEATURE_PGO
|
||||
|
||||
SArray<TLSIndex> m_tlsIndices;
|
||||
|
||||
public:
|
||||
BYTE *GetVSDHeapInitialBlock(DWORD *pSize);
|
||||
BYTE *GetCodeHeapInitialBlock(const BYTE * loAddr, const BYTE * hiAddr, DWORD minimumSize, DWORD *pSize);
|
||||
|
@ -389,6 +393,12 @@ protected:
|
|||
|
||||
PTR_VirtualCallStubManager m_pVirtualCallStubManager;
|
||||
|
||||
public:
|
||||
SArray<TLSIndex>& GetTLSIndexList()
|
||||
{
|
||||
return m_tlsIndices;
|
||||
}
|
||||
|
||||
private:
|
||||
LoaderAllocatorSet m_LoaderAllocatorReferences;
|
||||
Volatile<UINT32> m_cReferences;
|
||||
|
@ -582,6 +592,12 @@ public:
|
|||
return m_pHighFrequencyHeap;
|
||||
}
|
||||
|
||||
PTR_LoaderHeap GetStaticsHeap()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
return m_pStaticsHeap;
|
||||
}
|
||||
|
||||
PTR_LoaderHeap GetStubHeap()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
|
@ -631,6 +647,7 @@ public:
|
|||
}
|
||||
|
||||
LOADERALLOCATORREF GetExposedObject();
|
||||
bool IsExposedObjectLive();
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
bool InsertObjectIntoFieldWithLifetimeOfCollectibleLoaderAllocator(OBJECTREF value, Object** pField);
|
||||
|
@ -732,6 +749,8 @@ public:
|
|||
LIMITED_METHOD_CONTRACT;
|
||||
return m_nGCCount;
|
||||
}
|
||||
void AllocateBytesForStaticVariables(DynamicStaticsInfo* pStaticsInfo, uint32_t cbMem);
|
||||
void AllocateGCHandlesBytesForStaticVariables(DynamicStaticsInfo* pStaticsInfo, uint32_t cSlots, MethodTable* pMTWithStaticBoxes);
|
||||
|
||||
static BOOL Destroy(QCall::LoaderAllocatorHandle pLoaderAllocator);
|
||||
|
||||
|
|
|
@ -16,6 +16,14 @@ inline LOADERALLOCATORREF LoaderAllocator::GetExposedObject()
|
|||
}
|
||||
#endif
|
||||
|
||||
inline bool LoaderAllocator::IsExposedObjectLive()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
if (m_hLoaderAllocatorObjectHandle == 0)
|
||||
return false;
|
||||
return !ObjectHandleIsNull(m_hLoaderAllocatorObjectHandle);
|
||||
}
|
||||
|
||||
inline void GlobalLoaderAllocator::Init(BaseDomain *pDomain)
|
||||
{
|
||||
LoaderAllocator::Init(pDomain, m_ExecutableHeapInstance);
|
||||
|
|
|
@ -206,11 +206,6 @@ ASMCONSTANTS_C_ASSERT((1<<FixupPrecode_ALIGNMENT_SHIFT_1) == sizeof(FixupPrecode
|
|||
ASMCONSTANTS_C_ASSERT(ResolveCacheElem__target == offsetof(ResolveCacheElem, target));
|
||||
ASMCONSTANTS_C_ASSERT(ResolveCacheElem__pNext == offsetof(ResolveCacheElem, pNext));
|
||||
|
||||
#define DomainLocalModule__m_pDataBlob 0x30
|
||||
#define DomainLocalModule__m_pGCStatics 0x20
|
||||
ASMCONSTANTS_C_ASSERT(DomainLocalModule__m_pDataBlob == offsetof(DomainLocalModule, m_pDataBlob));
|
||||
ASMCONSTANTS_C_ASSERT(DomainLocalModule__m_pGCStatics == offsetof(DomainLocalModule, m_pGCStatics));
|
||||
|
||||
// For JIT_PInvokeBegin and JIT_PInvokeEnd helpers
|
||||
#define Frame__m_Next 0x08
|
||||
ASMCONSTANTS_C_ASSERT(Frame__m_Next == offsetof(Frame, m_Next))
|
||||
|
|
|
@ -611,26 +611,6 @@ NESTED_ENTRY TheUMEntryPrestub, _TEXT, UnhandledExceptionHandlerUnix
|
|||
EPILOG_BRANCH_REG $t4
|
||||
NESTED_END TheUMEntryPrestub, _TEXT
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// void* JIT_GetSharedGCStaticBase(SIZE_T moduleDomainID, DWORD dwClassDomainID)
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedGCStaticBase_SingleAppDomain, _TEXT
|
||||
// If class is not initialized, bail to C++ helper
|
||||
addi.d $a2, $a0, DomainLocalModule__m_pDataBlob
|
||||
add.d $a2, $a2, $a1
|
||||
ld.b $a2, $a2, 0
|
||||
andi $t8, $a2, 1
|
||||
beq $t8, $zero, 1f //LOCAL_LABEL(JIT_GetSharedGCStaticBase_SingleAppDomain_CallHelper)
|
||||
|
||||
ld.d $a0, $a0, DomainLocalModule__m_pGCStatics
|
||||
jirl $r0, $ra, 0
|
||||
|
||||
1:
|
||||
//LOCAL_LABEL(JIT_GetSharedGCStaticBase_SingleAppDomain_CallHelper):
|
||||
// Tail call JIT_GetSharedGCStaticBase_Helper
|
||||
bl JIT_GetSharedGCStaticBase_Helper
|
||||
LEAF_END JIT_GetSharedGCStaticBase_SingleAppDomain, _TEXT
|
||||
|
||||
// Make sure the `FaultingExceptionFrame_StackAlloc` is 16-byte aligned.
|
||||
#define FaultingExceptionFrame_StackAlloc (SIZEOF__GSCookie + SIZEOF__FaultingExceptionFrame + 0x8)
|
||||
#define FaultingExceptionFrame_FrameOffset SIZEOF__GSCookie
|
||||
|
@ -793,22 +773,6 @@ NESTED_ENTRY ResolveWorkerAsmStub, _TEXT, NoHandler
|
|||
EPILOG_BRANCH_REG $t4
|
||||
NESTED_END ResolveWorkerAsmStub, _TEXT
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// void* JIT_GetSharedNonGCStaticBaseNoCtor(SIZE_T moduleDomainID, DWORD dwClassDomainID)
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
jirl $r0, $ra, 0
|
||||
LEAF_END JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// void* JIT_GetSharedGCStaticBaseNoCtor(SIZE_T moduleDomainID, DWORD dwClassDomainID)
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
ld.d $a0, $a0, DomainLocalModule__m_pGCStatics
|
||||
jirl $r0, $ra, 0
|
||||
LEAF_END JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
|
||||
|
||||
#ifdef FEATURE_HIJACK
|
||||
// ------------------------------------------------------------------
|
||||
// Hijack function for functions which return a scalar type or a struct (value type)
|
||||
|
|
|
@ -98,11 +98,6 @@ inline unsigned StackElemSize(unsigned parmSize, bool isValueType, bool isFloatH
|
|||
//
|
||||
// Create alias for optimized implementations of helpers provided on this platform
|
||||
//
|
||||
#define JIT_GetSharedGCStaticBase JIT_GetSharedGCStaticBase_SingleAppDomain
|
||||
#define JIT_GetSharedNonGCStaticBase JIT_GetSharedNonGCStaticBase_SingleAppDomain
|
||||
#define JIT_GetSharedGCStaticBaseNoCtor JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain
|
||||
#define JIT_GetSharedNonGCStaticBaseNoCtor JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain
|
||||
|
||||
|
||||
//**********************************************************************
|
||||
// Frames
|
||||
|
|
|
@ -2995,7 +2995,7 @@ public:
|
|||
LIMITED_METHOD_CONTRACT;
|
||||
MethodTable * pMT = GetMethodTable();
|
||||
// Try to avoid touching the EEClass if possible
|
||||
if (pMT->IsClassPreInited())
|
||||
if (!pMT->HasClassConstructor())
|
||||
return FALSE;
|
||||
return !pMT->GetClass()->IsBeforeFieldInit();
|
||||
}
|
||||
|
|
|
@ -367,52 +367,6 @@ BOOL MethodTable::ValidateWithPossibleAV()
|
|||
}
|
||||
|
||||
|
||||
//==========================================================================================
|
||||
BOOL MethodTable::IsClassInited()
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
|
||||
if (IsClassPreInited())
|
||||
return TRUE;
|
||||
|
||||
if (IsSharedByGenericInstantiations())
|
||||
return FALSE;
|
||||
|
||||
PTR_DomainLocalModule pLocalModule = GetDomainLocalModule();
|
||||
|
||||
_ASSERTE(pLocalModule != NULL);
|
||||
|
||||
return pLocalModule->IsClassInitialized(this);
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
BOOL MethodTable::IsInitError()
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
|
||||
PTR_DomainLocalModule pLocalModule = GetDomainLocalModule();
|
||||
_ASSERTE(pLocalModule != NULL);
|
||||
|
||||
return pLocalModule->IsClassInitError(this);
|
||||
}
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
//==========================================================================================
|
||||
// mark the class as having its .cctor run
|
||||
void MethodTable::SetClassInited()
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
_ASSERTE(!IsClassPreInited());
|
||||
GetDomainLocalModule()->SetClassInitialized(this);
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
void MethodTable::SetClassInitError()
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
GetDomainLocalModule()->SetClassInitError(this);
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
// mark as COM object type (System.__ComObject and types deriving from it)
|
||||
void MethodTable::SetComObjectType()
|
||||
|
@ -457,8 +411,6 @@ void MethodTable::SetIsTrackedReferenceWithFinalizer()
|
|||
SetFlag(enum_flag_IsTrackedReferenceWithFinalizer);
|
||||
}
|
||||
|
||||
#endif // !DACCESS_COMPILE
|
||||
|
||||
BOOL MethodTable::IsTrackedReferenceWithFinalizer()
|
||||
{
|
||||
LIMITED_METHOD_DAC_CONTRACT;
|
||||
|
@ -682,16 +634,30 @@ MethodDesc *MethodTable::GetMethodDescForComInterfaceMethod(MethodDesc *pItfMD,
|
|||
}
|
||||
#endif // FEATURE_COMINTEROP
|
||||
|
||||
void MethodTable::AllocateAuxiliaryData(LoaderAllocator *pAllocator, Module *pLoaderModule, AllocMemTracker *pamTracker, bool hasGenericStatics, WORD nonVirtualSlots, S_SIZE_T extraAllocation)
|
||||
void MethodTable::AllocateAuxiliaryData(LoaderAllocator *pAllocator, Module *pLoaderModule, AllocMemTracker *pamTracker, MethodTableStaticsFlags staticsFlags, WORD nonVirtualSlots, S_SIZE_T extraAllocation)
|
||||
{
|
||||
S_SIZE_T cbAuxiliaryData = S_SIZE_T(sizeof(MethodTableAuxiliaryData));
|
||||
|
||||
size_t prependedAllocationSpace = 0;
|
||||
size_t prependedAllocationSpace = nonVirtualSlots * sizeof(TADDR);
|
||||
|
||||
prependedAllocationSpace = nonVirtualSlots * sizeof(TADDR);
|
||||
int16_t sizeofStaticsStructure = 0;
|
||||
|
||||
if (hasGenericStatics)
|
||||
prependedAllocationSpace = prependedAllocationSpace + sizeof(GenericsStaticsInfo);
|
||||
if (HasFlag(staticsFlags, MethodTableStaticsFlags::Thread))
|
||||
{
|
||||
_ASSERTE(HasFlag(staticsFlags, MethodTableStaticsFlags::Present));
|
||||
sizeofStaticsStructure = sizeof(ThreadStaticsInfo);
|
||||
}
|
||||
else if (HasFlag(staticsFlags, MethodTableStaticsFlags::Generic))
|
||||
{
|
||||
_ASSERTE(HasFlag(staticsFlags, MethodTableStaticsFlags::Present));
|
||||
sizeofStaticsStructure = sizeof(GenericsStaticsInfo);
|
||||
}
|
||||
else if (HasFlag(staticsFlags, MethodTableStaticsFlags::Present))
|
||||
{
|
||||
sizeofStaticsStructure = sizeof(DynamicStaticsInfo);
|
||||
}
|
||||
|
||||
prependedAllocationSpace = prependedAllocationSpace + sizeofStaticsStructure;
|
||||
|
||||
cbAuxiliaryData = cbAuxiliaryData + S_SIZE_T(prependedAllocationSpace) + extraAllocation;
|
||||
if (cbAuxiliaryData.IsOverflow())
|
||||
|
@ -704,8 +670,32 @@ void MethodTable::AllocateAuxiliaryData(LoaderAllocator *pAllocator, Module *pLo
|
|||
pMTAuxiliaryData = (MethodTableAuxiliaryData *)(pAuxiliaryDataRegion + prependedAllocationSpace);
|
||||
|
||||
pMTAuxiliaryData->SetLoaderModule(pLoaderModule);
|
||||
pMTAuxiliaryData->SetOffsetToNonVirtualSlots(hasGenericStatics ? -(int16_t)sizeof(GenericsStaticsInfo) : 0);
|
||||
|
||||
// NOTE: There is a - sign here making it so that the offset points to BEFORE the MethodTableAuxiliaryData
|
||||
pMTAuxiliaryData->SetOffsetToNonVirtualSlots(-sizeofStaticsStructure);
|
||||
|
||||
m_pAuxiliaryData = pMTAuxiliaryData;
|
||||
|
||||
if (HasFlag(staticsFlags, MethodTableStaticsFlags::Present))
|
||||
{
|
||||
MethodTableAuxiliaryData::GetDynamicStaticsInfo(pMTAuxiliaryData)->Init(this);
|
||||
#ifdef _DEBUG
|
||||
pMTAuxiliaryData->m_debugOnlyDynamicStatics = MethodTableAuxiliaryData::GetDynamicStaticsInfo(pMTAuxiliaryData);
|
||||
#endif
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
if (HasFlag(staticsFlags, MethodTableStaticsFlags::Generic))
|
||||
{
|
||||
pMTAuxiliaryData->m_debugOnlyGenericStatics = MethodTableAuxiliaryData::GetGenericStaticsInfo(pMTAuxiliaryData);
|
||||
}
|
||||
#endif
|
||||
if (HasFlag(staticsFlags, MethodTableStaticsFlags::Thread))
|
||||
{
|
||||
MethodTableAuxiliaryData::GetThreadStaticsInfo(pMTAuxiliaryData)->Init();
|
||||
#ifdef _DEBUG
|
||||
pMTAuxiliaryData->m_debugOnlyThreadStatics = MethodTableAuxiliaryData::GetThreadStaticsInfo(pMTAuxiliaryData);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1048,22 +1038,7 @@ void MethodTable::SetupGenericsStaticsInfo(FieldDesc* pStaticFieldDescs)
|
|||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
// No need to generate IDs for open types. Indeed since we don't save them
|
||||
// in the NGEN image it would be actively incorrect to do so. However
|
||||
// we still leave the optional member in the MethodTable holding the value -1 for the ID.
|
||||
|
||||
GenericsStaticsInfo *pInfo = GetGenericsStaticsInfo();
|
||||
if (!ContainsGenericVariables() && !IsSharedByGenericInstantiations())
|
||||
{
|
||||
Module * pModuleForStatics = GetLoaderModule();
|
||||
|
||||
pInfo->m_DynamicTypeID = pModuleForStatics->AllocateDynamicEntry(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
pInfo->m_DynamicTypeID = (SIZE_T)-1;
|
||||
}
|
||||
|
||||
pInfo->m_pFieldDescs = pStaticFieldDescs;
|
||||
}
|
||||
|
||||
|
@ -1102,43 +1077,6 @@ void MethodTable::EnumMemoryRegionsForExtraInterfaceInfo()
|
|||
}
|
||||
#endif // DACCESS_COMPILE
|
||||
|
||||
//==========================================================================================
|
||||
Module* MethodTable::GetModuleForStatics()
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
SUPPORTS_DAC;
|
||||
|
||||
if (HasGenericsStaticsInfo())
|
||||
{
|
||||
DWORD dwDynamicClassDomainID;
|
||||
return GetGenericsStaticsModuleAndID(&dwDynamicClassDomainID);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetLoaderModule();
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
DWORD MethodTable::GetModuleDynamicEntryID()
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
SUPPORTS_DAC;
|
||||
|
||||
_ASSERTE(IsDynamicStatics() && "Only memory reflection emit types and generics can have a dynamic ID");
|
||||
|
||||
if (HasGenericsStaticsInfo())
|
||||
{
|
||||
DWORD dwDynamicClassDomainID;
|
||||
GetGenericsStaticsModuleAndID(&dwDynamicClassDomainID);
|
||||
return dwDynamicClassDomainID;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetClass()->GetModuleDynamicID();
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
|
||||
#ifdef FEATURE_TYPEEQUIVALENCE
|
||||
|
@ -2027,42 +1965,6 @@ DWORD MethodTable::GetIndexForFieldDesc(FieldDesc *pField)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
#ifdef _MSC_VER
|
||||
#pragma optimize("t", on)
|
||||
#endif // _MSC_VER
|
||||
// compute whether the type can be considered to have had its
|
||||
// static initialization run without doing anything at all, i.e. whether we know
|
||||
// immediately that the type requires nothing to do for initialization
|
||||
//
|
||||
// If a type used as a representiative during JITting is PreInit then
|
||||
// any types that it may represent within a code-sharing
|
||||
// group are also PreInit. For example, if List<object> is PreInit then List<string>
|
||||
// and List<MyType> are also PreInit. This is because the dynamicStatics, staticRefHandles
|
||||
// and hasCCtor are all identical given a head type, and weakening the domainNeutrality
|
||||
// to DomainSpecific only makes more types PreInit.
|
||||
BOOL MethodTable::IsClassPreInited()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
|
||||
if (ContainsGenericVariables())
|
||||
return TRUE;
|
||||
|
||||
if (HasClassConstructor())
|
||||
return FALSE;
|
||||
|
||||
if (HasBoxedRegularStatics())
|
||||
return FALSE;
|
||||
|
||||
if (IsDynamicStatics())
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
#pragma optimize("", on)
|
||||
#endif // _MSC_VER
|
||||
|
||||
//========================================================================================
|
||||
|
||||
namespace
|
||||
|
@ -3397,26 +3299,20 @@ void MethodTable::GetNativeSwiftPhysicalLowering(CORINFO_SWIFT_LOWERING* pSwiftL
|
|||
|
||||
#if !defined(DACCESS_COMPILE)
|
||||
//==========================================================================================
|
||||
void MethodTable::AllocateRegularStaticBoxes()
|
||||
void MethodTable::AllocateRegularStaticBoxes(OBJECTREF** ppStaticBase)
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
PRECONDITION(!ContainsGenericVariables());
|
||||
PRECONDITION(HasBoxedRegularStatics());
|
||||
MODE_ANY;
|
||||
MODE_COOPERATIVE;
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Instantiating static handles for %s\n", GetDebugClassName()));
|
||||
|
||||
GCX_COOP();
|
||||
|
||||
PTR_BYTE pStaticBase = GetGCStaticsBasePointer();
|
||||
|
||||
GCPROTECT_BEGININTERIOR(pStaticBase);
|
||||
|
||||
if (HasBoxedRegularStatics())
|
||||
{
|
||||
FieldDesc *pField = HasGenericsStaticsInfo() ?
|
||||
GetGenericsStaticFieldDescs() : (GetApproxFieldDescListRaw() + GetNumIntroducedInstanceFields());
|
||||
|
@ -3428,13 +3324,12 @@ void MethodTable::AllocateRegularStaticBoxes()
|
|||
|
||||
if (!pField->IsSpecialStatic() && pField->IsByValue())
|
||||
{
|
||||
AllocateRegularStaticBox(pField, (Object**)(pStaticBase + pField->GetOffset()));
|
||||
AllocateRegularStaticBox(pField, (Object**)(((PTR_BYTE)*ppStaticBase) + pField->GetOffset()));
|
||||
}
|
||||
|
||||
pField++;
|
||||
}
|
||||
}
|
||||
GCPROTECT_END();
|
||||
}
|
||||
|
||||
void MethodTable::AllocateRegularStaticBox(FieldDesc* pField, Object** boxedStaticHandle)
|
||||
|
@ -3451,24 +3346,14 @@ void MethodTable::AllocateRegularStaticBox(FieldDesc* pField, Object** boxedStat
|
|||
|
||||
// Static fields are not pinned in collectible types so we need to protect the address
|
||||
GCPROTECT_BEGININTERIOR(boxedStaticHandle);
|
||||
if (VolatileLoad(boxedStaticHandle) == nullptr)
|
||||
{
|
||||
// Grab field's type handle before we enter lock
|
||||
MethodTable* pFieldMT = pField->GetFieldTypeHandleThrowing().GetMethodTable();
|
||||
_ASSERTE(*boxedStaticHandle == nullptr);
|
||||
MethodTable* pFieldMT = pField->GetFieldTypeHandleThrowing(CLASS_DEPENDENCIES_LOADED).GetMethodTable();
|
||||
bool hasFixedAddr = HasFixedAddressVTStatics();
|
||||
|
||||
// Taking a lock since we might come here from multiple threads/places
|
||||
CrstHolder crst(GetAppDomain()->GetStaticBoxInitLock());
|
||||
|
||||
// double-checked locking
|
||||
if (VolatileLoad(boxedStaticHandle) == nullptr)
|
||||
{
|
||||
LOG((LF_CLASSLOADER, LL_INFO10000, "\tInstantiating static of type %s\n", pFieldMT->GetDebugClassName()));
|
||||
const bool canBeFrozen = !pFieldMT->ContainsPointers() && !Collectible();
|
||||
OBJECTREF obj = AllocateStaticBox(pFieldMT, hasFixedAddr, canBeFrozen);
|
||||
SetObjectReference((OBJECTREF*)(boxedStaticHandle), obj);
|
||||
}
|
||||
}
|
||||
GCPROTECT_END();
|
||||
}
|
||||
|
||||
|
@ -3728,11 +3613,7 @@ void MethodTable::DoRunClassInitThrowing()
|
|||
{
|
||||
if (pEntry->m_hrResultCode == S_FALSE)
|
||||
{
|
||||
if (HasBoxedRegularStatics())
|
||||
{
|
||||
// First, instantiate any objects needed for value type statics
|
||||
AllocateRegularStaticBoxes();
|
||||
}
|
||||
EnsureStaticDataAllocated();
|
||||
|
||||
// Nobody has run the .cctor yet
|
||||
if (HasClassConstructor())
|
||||
|
@ -3802,9 +3683,7 @@ void MethodTable::DoRunClassInitThrowing()
|
|||
|
||||
pEntry->m_hrResultCode = S_OK;
|
||||
|
||||
// Set the initialization flags in the DLS and on domain-specific types.
|
||||
// Note we also set the flag for dynamic statics, which use the DynamicStatics part
|
||||
// of the DLS irrespective of whether the type is domain neutral or not.
|
||||
// Set the initialization flag
|
||||
SetClassInited();
|
||||
|
||||
}
|
||||
|
@ -3867,26 +3746,114 @@ void MethodTable::CheckRunClassInitThrowing()
|
|||
// To find GC hole easier...
|
||||
TRIGGERSGC();
|
||||
|
||||
if (IsClassPreInited())
|
||||
return;
|
||||
|
||||
// Don't initialize shared generic instantiations (e.g. MyClass<__Canon>)
|
||||
if (IsSharedByGenericInstantiations())
|
||||
return;
|
||||
|
||||
DomainLocalModule *pLocalModule = GetDomainLocalModule();
|
||||
_ASSERTE(pLocalModule);
|
||||
|
||||
DWORD iClassIndex = GetClassIndex();
|
||||
|
||||
// Check to see if we have already run the .cctor for this class.
|
||||
if (!pLocalModule->IsClassAllocated(this, iClassIndex))
|
||||
pLocalModule->PopulateClass(this);
|
||||
|
||||
if (!pLocalModule->IsClassInitialized(this, iClassIndex))
|
||||
EnsureStaticDataAllocated();
|
||||
DoRunClassInitThrowing();
|
||||
}
|
||||
|
||||
void MethodTable::EnsureStaticDataAllocated()
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
INJECT_FAULT(COMPlusThrowOM());
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
PTR_MethodTableAuxiliaryData pAuxiliaryData = GetAuxiliaryDataForWrite();
|
||||
if (!pAuxiliaryData->IsStaticDataAllocated() && IsDynamicStatics())
|
||||
{
|
||||
DynamicStaticsInfo *pDynamicStaticsInfo = GetDynamicStaticsInfo();
|
||||
// Allocate space for normal statics if we might have them
|
||||
if (pDynamicStaticsInfo->GetNonGCStaticsPointer() == NULL)
|
||||
GetLoaderAllocator()->AllocateBytesForStaticVariables(pDynamicStaticsInfo, GetClass()->GetNonGCRegularStaticFieldBytes());
|
||||
|
||||
if (pDynamicStaticsInfo->GetGCStaticsPointer() == NULL)
|
||||
GetLoaderAllocator()->AllocateGCHandlesBytesForStaticVariables(pDynamicStaticsInfo, GetClass()->GetNumHandleRegularStatics(), this->HasBoxedRegularStatics() ? this : NULL);
|
||||
}
|
||||
pAuxiliaryData->SetIsStaticDataAllocated();
|
||||
}
|
||||
|
||||
void MethodTable::AttemptToPreinit()
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
INJECT_FAULT(COMPlusThrowOM());
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
if (IsClassInited())
|
||||
return;
|
||||
|
||||
if (HasClassConstructor())
|
||||
{
|
||||
// If there is a class constructor, then the class cannot be preinitted.
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetClass()->GetNonGCRegularStaticFieldBytes() == 0 && GetClass()->GetNumHandleRegularStatics() == 0)
|
||||
{
|
||||
// If there are static fields that are not thread statics, then the class is preinitted.
|
||||
SetClassInited();
|
||||
return;
|
||||
}
|
||||
|
||||
// At this point, we are looking at a class that has no class constructor, but does have static fields
|
||||
|
||||
if (IsSharedByGenericInstantiations())
|
||||
{
|
||||
// If we don't know the exact type, we can't pre-allocate the fields
|
||||
return;
|
||||
}
|
||||
|
||||
// All this class needs to be initialized is to allocate the memory for the static fields. Do so, and mark the type as initialized
|
||||
EnsureStaticDataAllocated();
|
||||
SetClassInited();
|
||||
return;
|
||||
}
|
||||
|
||||
void MethodTable::EnsureTlsIndexAllocated()
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
THROWS;
|
||||
GC_NOTRIGGER;
|
||||
MODE_ANY;
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
PTR_MethodTableAuxiliaryData pAuxiliaryData = GetAuxiliaryDataForWrite();
|
||||
if (!pAuxiliaryData->IsTlsIndexAllocated() && GetNumThreadStaticFields() > 0)
|
||||
{
|
||||
ThreadStaticsInfo *pThreadStaticsInfo = MethodTableAuxiliaryData::GetThreadStaticsInfo(GetAuxiliaryDataForWrite());
|
||||
// Allocate space for normal statics if we might have them
|
||||
if (!pThreadStaticsInfo->NonGCTlsIndex.IsAllocated())
|
||||
{
|
||||
DWORD bytesNeeded = GetClass()->GetNonGCThreadStaticFieldBytes();
|
||||
if (bytesNeeded > 0)
|
||||
{
|
||||
GetTLSIndexForThreadStatic(this, false, &pThreadStaticsInfo->NonGCTlsIndex, bytesNeeded);
|
||||
}
|
||||
}
|
||||
|
||||
if (!pThreadStaticsInfo->GCTlsIndex.IsAllocated())
|
||||
{
|
||||
DWORD bytesNeeded = GetClass()->GetNumHandleThreadStatics() * sizeof(OBJECTREF);
|
||||
if (bytesNeeded > 0)
|
||||
{
|
||||
GetTLSIndexForThreadStatic(this, true, &pThreadStaticsInfo->GCTlsIndex, bytesNeeded);
|
||||
}
|
||||
}
|
||||
}
|
||||
pAuxiliaryData->SetIsTlsIndexAllocated();
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
void MethodTable::CheckRunClassInitAsIfConstructingThrowing()
|
||||
{
|
||||
|
@ -4439,6 +4406,17 @@ void MethodTable::DoFullyLoad(Generics::RecursionGraph * const pVisited, const
|
|||
ClassLoader::ValidateMethodsWithCovariantReturnTypes(this);
|
||||
}
|
||||
|
||||
if ((level == CLASS_LOADED) && CORDisableJITOptimizations(this->GetModule()->GetDebuggerInfoBits()) && !HasInstantiation())
|
||||
{
|
||||
if (g_fEEStarted)
|
||||
{
|
||||
// If the module is DEBUG, then allocate static variable memory now, so that the debugger will always be able to examine
|
||||
// the static variables of the type. Never do this in the EEStartup path, as it can cause incorrect load orders to happen.
|
||||
// (This only happens in practice in DEBUG builds of coreclr, or when the profiler disables all optimizations.)
|
||||
EnsureStaticDataAllocated();
|
||||
}
|
||||
}
|
||||
|
||||
if (IsArray())
|
||||
{
|
||||
Generics::RecursionGraph newVisited(pVisited, TypeHandle(this));
|
||||
|
@ -8685,3 +8663,18 @@ PTR_MethodTable MethodTable::InterfaceMapIterator::GetInterface(MethodTable* pMT
|
|||
RETURN (pResult);
|
||||
}
|
||||
#endif // DACCESS_COMPILE
|
||||
|
||||
void MethodTable::GetStaticsOffsets(StaticsOffsetType offsetType, bool fGenericStatics, uint32_t *dwGCOffset, uint32_t *dwNonGCOffset)
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
if (offsetType == StaticsOffsetType::Normal)
|
||||
{
|
||||
*dwNonGCOffset = 0;
|
||||
*dwGCOffset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dwNonGCOffset = (uint32_t)sizeof(TADDR) * 2;
|
||||
*dwGCOffset = (uint32_t)sizeof(TADDR) * 2;
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@
|
|||
#include "generics.h"
|
||||
#include "gcinfotypes.h"
|
||||
#include "enum_class_flags.h"
|
||||
#include "threadstatics.h"
|
||||
|
||||
/*
|
||||
* Forward Declarations
|
||||
|
@ -68,6 +69,12 @@ struct MethodTableAuxiliaryData;
|
|||
typedef DPTR(MethodTableAuxiliaryData) PTR_MethodTableAuxiliaryData;
|
||||
typedef DPTR(MethodTableAuxiliaryData const) PTR_Const_MethodTableAuxiliaryData;
|
||||
|
||||
enum class StaticsOffsetType
|
||||
{
|
||||
Normal,
|
||||
ThreadLocal
|
||||
};
|
||||
|
||||
enum class ResolveVirtualStaticMethodFlags
|
||||
{
|
||||
None = 0,
|
||||
|
@ -90,6 +97,16 @@ enum class FindDefaultInterfaceImplementationFlags
|
|||
support_use_as_flags // Enable the template functions in enum_class_flags.h
|
||||
};
|
||||
|
||||
enum class MethodTableStaticsFlags
|
||||
{
|
||||
None = 0,
|
||||
Present = 0x1,
|
||||
Generic = 0x2,
|
||||
Thread = 0x4,
|
||||
|
||||
support_use_as_flags // Enable the template functions in enum_class_flags.h
|
||||
};
|
||||
|
||||
enum class MethodDataComputeOptions
|
||||
{
|
||||
NoCache, // Do not place the results of getting the MethodData into the cache, but use it if it is there
|
||||
|
@ -279,15 +296,16 @@ struct GenericsDictInfo
|
|||
}; // struct GenericsDictInfo
|
||||
typedef DPTR(GenericsDictInfo) PTR_GenericsDictInfo;
|
||||
|
||||
struct GenericsStaticsInfo
|
||||
{
|
||||
// Pointer to field descs for statics
|
||||
PTR_FieldDesc m_pFieldDescs;
|
||||
|
||||
// Method table ID for statics
|
||||
SIZE_T m_DynamicTypeID;
|
||||
// These various statics structures exist directly before the MethodTableAuxiliaryData
|
||||
|
||||
}; // struct GenericsStaticsInfo
|
||||
// Any MethodTable which has static variables has this structure
|
||||
struct DynamicStaticsInfo;
|
||||
struct ThreadStaticsInfo;
|
||||
struct GenericsStaticsInfo;
|
||||
|
||||
typedef DPTR(DynamicStaticsInfo) PTR_DynamicStaticsInfo;
|
||||
typedef DPTR(ThreadStaticsInfo) PTR_ThreadStaticsInfo;
|
||||
typedef DPTR(GenericsStaticsInfo) PTR_GenericsStaticsInfo;
|
||||
|
||||
//
|
||||
|
@ -309,20 +327,20 @@ struct MethodTableAuxiliaryData
|
|||
// TO BE UPDATED IN ORDER TO ENSURE THAT METHODTABLES DUPLICATED FOR GENERIC INSTANTIATIONS
|
||||
// CARRY THE CORRECT INITIAL FLAGS.
|
||||
|
||||
enum_flag_CanCompareBitsOrUseFastGetHashCode = 0x0001, // Is any field type or sub field type overrode Equals or GetHashCode
|
||||
enum_flag_Initialized = 0x0001,
|
||||
enum_flag_HasCheckedCanCompareBitsOrUseFastGetHashCode = 0x0002, // Whether we have checked the overridden Equals or GetHashCode
|
||||
enum_flag_CanCompareBitsOrUseFastGetHashCode = 0x0004, // Is any field type or sub field type overridden Equals or GetHashCode
|
||||
|
||||
// enum_unused = 0x0004,
|
||||
enum_flag_HasApproxParent = 0x0010,
|
||||
// enum_unused = 0x0020,
|
||||
enum_flag_IsNotFullyLoaded = 0x0040,
|
||||
enum_flag_DependenciesLoaded = 0x0080, // class and all dependencies loaded up to CLASS_LOADED_BUT_NOT_VERIFIED
|
||||
|
||||
enum_flag_MayHaveOpenInterfaceInInterfaceMap = 0x0100,
|
||||
// enum_unused = 0x0200,
|
||||
// enum_unused = 0x0400,
|
||||
// enum_unused = 0x0800,
|
||||
// enum_unused = 0x1000,
|
||||
enum_flag_IsInitError = 0x0100,
|
||||
enum_flag_IsStaticDataAllocated = 0x0200,
|
||||
// unum_unused = 0x0400,
|
||||
enum_flag_IsTlsIndexAllocated = 0x0800,
|
||||
enum_flag_MayHaveOpenInterfaceInInterfaceMap = 0x1000,
|
||||
// enum_unused = 0x2000,
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
@ -358,6 +376,10 @@ struct MethodTableAuxiliaryData
|
|||
DWORD m_dwPadding; // Just to keep the size a multiple of 8
|
||||
#endif
|
||||
|
||||
// These pointers make it easier to examine the various statics structures in the debugger
|
||||
PTR_DynamicStaticsInfo m_debugOnlyDynamicStatics;
|
||||
PTR_GenericsStaticsInfo m_debugOnlyGenericStatics;
|
||||
PTR_ThreadStaticsInfo m_debugOnlyThreadStatics;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
@ -388,6 +410,67 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
inline BOOL IsInitError() const
|
||||
{
|
||||
LIMITED_METHOD_DAC_CONTRACT;
|
||||
return (VolatileLoad(&m_dwFlags) & enum_flag_IsInitError);
|
||||
}
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
inline void SetInitError()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
InterlockedOr((LONG*)&m_dwFlags, (LONG)enum_flag_IsInitError);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline BOOL IsTlsIndexAllocated() const
|
||||
{
|
||||
LIMITED_METHOD_DAC_CONTRACT;
|
||||
return (VolatileLoad(&m_dwFlags) & enum_flag_IsTlsIndexAllocated);
|
||||
}
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
inline void SetIsTlsIndexAllocated()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
InterlockedOr((LONG*)&m_dwFlags, (LONG)enum_flag_IsTlsIndexAllocated);
|
||||
}
|
||||
#endif
|
||||
|
||||
DWORD* getIsClassInitedFlagAddress()
|
||||
{
|
||||
LIMITED_METHOD_DAC_CONTRACT;
|
||||
_ASSERTE(enum_flag_Initialized == 1); // This is an assumption in the JIT and in hand-written assembly at this time.
|
||||
return &m_dwFlags;
|
||||
}
|
||||
|
||||
inline BOOL IsClassInited() const
|
||||
{
|
||||
return VolatileLoad(&m_dwFlags) & enum_flag_Initialized;
|
||||
}
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
inline void SetClassInited()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
InterlockedOr((LONG*)&m_dwFlags, (LONG)enum_flag_Initialized);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline BOOL IsStaticDataAllocated() const
|
||||
{
|
||||
LIMITED_METHOD_DAC_CONTRACT;
|
||||
return (VolatileLoad(&m_dwFlags) & enum_flag_IsStaticDataAllocated);
|
||||
}
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
inline void SetIsStaticDataAllocated()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
InterlockedOr((LONG*)&m_dwFlags, (LONG)enum_flag_IsStaticDataAllocated);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline RUNTIMETYPEHANDLE GetExposedClassObjectHandle() const
|
||||
{
|
||||
|
@ -431,6 +514,9 @@ public:
|
|||
m_offsetToNonVirtualSlots = offset;
|
||||
}
|
||||
|
||||
static inline PTR_DynamicStaticsInfo GetDynamicStaticsInfo(PTR_Const_MethodTableAuxiliaryData pAuxiliaryData);
|
||||
static inline PTR_GenericsStaticsInfo GetGenericStaticsInfo(PTR_Const_MethodTableAuxiliaryData pAuxiliaryData);
|
||||
static inline PTR_ThreadStaticsInfo GetThreadStaticsInfo(PTR_Const_MethodTableAuxiliaryData pAuxiliaryData);
|
||||
inline void SetMayHaveOpenInterfacesInInterfaceMap()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
|
@ -441,12 +527,126 @@ public:
|
|||
{
|
||||
return !!(m_dwFlags & MethodTableAuxiliaryData::enum_flag_MayHaveOpenInterfaceInInterfaceMap);
|
||||
}
|
||||
}; // struct MethodTableAuxiliaryData
|
||||
|
||||
static inline PTR_GenericsStaticsInfo GetGenericStaticsInfo(PTR_Const_MethodTableAuxiliaryData pAuxiliaryData)
|
||||
// All MethodTables which have static variables will have one of these. It contains the pointers necessary to
|
||||
// find the normal (non-thread) static variables of the type.
|
||||
struct DynamicStaticsInfo
|
||||
{
|
||||
private:
|
||||
// The detail of whether or not the class has been initialized is stored in the statics pointers as well as in
|
||||
// its normal flag location. This is done so that when getting the statics base for a class, we can get the statics
|
||||
// base address and check to see if it is initialized without needing a barrier between reading the flag and reading
|
||||
// the static field address.
|
||||
static constexpr TADDR ISCLASSNOTINITED = 1;
|
||||
static constexpr TADDR ISCLASSNOTINITEDMASK = ISCLASSNOTINITED;
|
||||
static constexpr TADDR STATICSPOINTERMASK = ~ISCLASSNOTINITEDMASK;
|
||||
|
||||
void InterlockedSetClassInited(bool isGC)
|
||||
{
|
||||
TADDR oldVal;
|
||||
TADDR oldValFromInterlockedOp;
|
||||
TADDR *pAddr = isGC ? &m_pGCStatics : &m_pNonGCStatics;
|
||||
do
|
||||
{
|
||||
oldVal = VolatileLoadWithoutBarrier(pAddr);
|
||||
// Mask off the ISCLASSNOTINITED bit
|
||||
oldValFromInterlockedOp = InterlockedCompareExchangeT(pAddr, oldVal & STATICSPOINTERMASK, oldVal);
|
||||
} while(oldValFromInterlockedOp != oldVal); // We can loop if we happened to allocate the statics pointer in the middle of this operation
|
||||
}
|
||||
|
||||
public:
|
||||
TADDR m_pGCStatics; // Always access through helper methods to properly handle the ISCLASSNOTINITED bit
|
||||
TADDR m_pNonGCStatics; // Always access through helper methods to properly handle the ISCLASSNOTINITED bit
|
||||
PTR_MethodTable m_pMethodTable;
|
||||
PTR_OBJECTREF GetGCStaticsPointer() { TADDR staticsVal = VolatileLoadWithoutBarrier(&m_pGCStatics); return dac_cast<PTR_OBJECTREF>(staticsVal & STATICSPOINTERMASK); }
|
||||
PTR_BYTE GetNonGCStaticsPointer() { TADDR staticsVal = VolatileLoadWithoutBarrier(&m_pNonGCStatics); return dac_cast<PTR_BYTE>(staticsVal & STATICSPOINTERMASK); }
|
||||
PTR_OBJECTREF GetGCStaticsPointerAssumeIsInited() { TADDR staticsVal = m_pGCStatics; _ASSERTE(staticsVal != 0); _ASSERTE((staticsVal & (ISCLASSNOTINITEDMASK)) == 0); return dac_cast<PTR_OBJECTREF>(staticsVal); }
|
||||
PTR_BYTE GetNonGCStaticsPointerAssumeIsInited() { TADDR staticsVal = m_pNonGCStatics; _ASSERTE(staticsVal != 0); _ASSERTE((staticsVal & (ISCLASSNOTINITEDMASK)) == 0); return dac_cast<PTR_BYTE>(staticsVal); }
|
||||
bool GetIsInitedAndGCStaticsPointerIfInited(PTR_OBJECTREF *ptrResult) { TADDR staticsVal = VolatileLoadWithoutBarrier(&m_pGCStatics); *ptrResult = dac_cast<PTR_OBJECTREF>(staticsVal); return !(staticsVal & ISCLASSNOTINITED); }
|
||||
bool GetIsInitedAndNonGCStaticsPointerIfInited(PTR_BYTE *ptrResult) { TADDR staticsVal = VolatileLoadWithoutBarrier(&m_pNonGCStatics); *ptrResult = dac_cast<PTR_BYTE>(staticsVal); return !(staticsVal & ISCLASSNOTINITED); }
|
||||
|
||||
// This function sets the pointer portion of a statics pointer. It returns false if the statics value was already set.
|
||||
bool InterlockedUpdateStaticsPointer(bool isGC, TADDR newVal)
|
||||
{
|
||||
TADDR oldVal;
|
||||
TADDR oldValFromInterlockedOp;
|
||||
TADDR *pAddr = isGC ? &m_pGCStatics : &m_pNonGCStatics;
|
||||
do
|
||||
{
|
||||
oldVal = VolatileLoad(pAddr);
|
||||
|
||||
// Check to see if statics value has already been set
|
||||
if ((oldVal & STATICSPOINTERMASK) != 0)
|
||||
{
|
||||
// If it has, then we don't need to do anything
|
||||
return false;
|
||||
}
|
||||
|
||||
oldValFromInterlockedOp = InterlockedCompareExchangeT(pAddr, newVal | oldVal, oldVal);
|
||||
} while(oldValFromInterlockedOp != oldVal);
|
||||
return true;
|
||||
}
|
||||
void SetClassInited()
|
||||
{
|
||||
InterlockedSetClassInited(true);
|
||||
InterlockedSetClassInited(false);
|
||||
}
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
void Init(MethodTable* pMT)
|
||||
{
|
||||
m_pGCStatics = ISCLASSNOTINITED;
|
||||
m_pNonGCStatics = ISCLASSNOTINITED;
|
||||
m_pMethodTable = pMT;
|
||||
}
|
||||
#endif
|
||||
|
||||
PTR_MethodTable GetMethodTable() const { return m_pMethodTable; }
|
||||
};
|
||||
|
||||
/* static */ inline PTR_DynamicStaticsInfo MethodTableAuxiliaryData::GetDynamicStaticsInfo(PTR_Const_MethodTableAuxiliaryData pAuxiliaryData)
|
||||
{
|
||||
return dac_cast<PTR_DynamicStaticsInfo>(dac_cast<TADDR>(pAuxiliaryData) - sizeof(DynamicStaticsInfo));
|
||||
}
|
||||
|
||||
// Any Generic MethodTable which has static variables has this structure. Note that it ends
|
||||
// with a DynamicStatics structure so that lookups for just DynamicStatics will find that structure
|
||||
// when looking for statics pointers
|
||||
// In addition, for simplicity in access, all MethodTables which have a ThreadStaticsInfo have this structure
|
||||
// but it is unitialized and should not be used if the type is not generic
|
||||
struct GenericsStaticsInfo
|
||||
{
|
||||
// Pointer to field descs for statics
|
||||
PTR_FieldDesc m_pFieldDescs;
|
||||
|
||||
DynamicStaticsInfo m_DynamicStatics;
|
||||
}; // struct GenericsStaticsInfo
|
||||
|
||||
/* static */ inline PTR_GenericsStaticsInfo MethodTableAuxiliaryData::GetGenericStaticsInfo(PTR_Const_MethodTableAuxiliaryData pAuxiliaryData)
|
||||
{
|
||||
return dac_cast<PTR_GenericsStaticsInfo>(dac_cast<TADDR>(pAuxiliaryData) - sizeof(GenericsStaticsInfo));
|
||||
}
|
||||
}; // struct MethodTableAuxiliaryData
|
||||
|
||||
// And MethodTable with Thread Statics has this structure. NOTE: This structure includes
|
||||
// GenericsStatics which may not actually have the m_pFieldDescs filled in if the MethodTable
|
||||
// is not actually Generic
|
||||
struct ThreadStaticsInfo
|
||||
{
|
||||
TLSIndex NonGCTlsIndex;
|
||||
TLSIndex GCTlsIndex;
|
||||
GenericsStaticsInfo m_genericStatics;
|
||||
void Init()
|
||||
{
|
||||
NonGCTlsIndex = TLSIndex::Unallocated();
|
||||
GCTlsIndex = TLSIndex::Unallocated();
|
||||
}
|
||||
};
|
||||
|
||||
/* static */ inline PTR_ThreadStaticsInfo MethodTableAuxiliaryData::GetThreadStaticsInfo(PTR_Const_MethodTableAuxiliaryData pAuxiliaryData)
|
||||
{
|
||||
return dac_cast<PTR_ThreadStaticsInfo>(dac_cast<TADDR>(pAuxiliaryData) - sizeof(ThreadStaticsInfo));
|
||||
}
|
||||
|
||||
#ifdef UNIX_AMD64_ABI_ITF
|
||||
inline
|
||||
|
@ -638,16 +838,11 @@ public:
|
|||
// is accessed lives in a "loader module". The rule for determining the loader module must ensure
|
||||
// that a type never outlives its loader module with respect to app-domain unloading
|
||||
//
|
||||
// GetModuleForStatics() is the third kind of module. GetModuleForStatics() is module that
|
||||
// statics are attached to.
|
||||
PTR_Module GetLoaderModule();
|
||||
PTR_LoaderAllocator GetLoaderAllocator();
|
||||
|
||||
void SetLoaderAllocator(LoaderAllocator* pAllocator);
|
||||
|
||||
// Get the domain local module - useful for static init checks
|
||||
PTR_DomainLocalModule GetDomainLocalModule();
|
||||
|
||||
MethodTable *LoadEnclosingMethodTable(ClassLoadLevel targetLevel = CLASS_DEPENDENCIES_LOADED);
|
||||
|
||||
LPCWSTR GetPathForErrorMessages();
|
||||
|
@ -806,14 +1001,6 @@ public:
|
|||
|
||||
BOOL HasExplicitOrImplicitPublicDefaultConstructor();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// THE CLASS INITIALIZATION CONDITION
|
||||
// (and related DomainLocalModule storage)
|
||||
//
|
||||
// - populate the DomainLocalModule if needed
|
||||
// - run the cctor
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
// checks whether the class initialiser should be run on this class, and runs it if necessary
|
||||
|
@ -851,15 +1038,40 @@ public:
|
|||
// Init the m_dwFlags field for an array
|
||||
void SetIsArray(CorElementType arrayType);
|
||||
|
||||
BOOL IsClassPreInited();
|
||||
|
||||
// mark the class as having its cctor run.
|
||||
#ifndef DACCESS_COMPILE
|
||||
void SetClassInited();
|
||||
void SetClassInitError();
|
||||
void SetClassInited()
|
||||
{
|
||||
GetAuxiliaryDataForWrite()->SetClassInited();
|
||||
if (IsDynamicStatics())
|
||||
{
|
||||
GetDynamicStaticsInfo()->SetClassInited();
|
||||
}
|
||||
}
|
||||
|
||||
void AttemptToPreinit();
|
||||
#endif
|
||||
|
||||
BOOL IsClassInited()
|
||||
{
|
||||
return GetAuxiliaryDataForWrite()->IsClassInited();
|
||||
}
|
||||
|
||||
// Allocate any memory needed for statics, acquire TLSIndex for TLS statics, and check to see if the class can be considered pre-inited, and if so, set the initialized flag
|
||||
void EnsureStaticDataAllocated();
|
||||
void EnsureTlsIndexAllocated();
|
||||
|
||||
BOOL IsInitError()
|
||||
{
|
||||
return GetAuxiliaryData()->IsInitError();
|
||||
}
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
void SetClassInitError()
|
||||
{
|
||||
return GetAuxiliaryDataForWrite()->SetInitError();
|
||||
}
|
||||
#endif
|
||||
BOOL IsClassInited();
|
||||
BOOL IsInitError();
|
||||
|
||||
inline BOOL IsGlobalClass()
|
||||
{
|
||||
|
@ -867,9 +1079,6 @@ public:
|
|||
return (GetTypeDefRid() == RidFromToken(COR_GLOBAL_PARENT_TOKEN));
|
||||
}
|
||||
|
||||
// uniquely identifes this type in the Domain table
|
||||
DWORD GetClassIndex();
|
||||
|
||||
private:
|
||||
|
||||
#if defined(UNIX_AMD64_ABI_ITF)
|
||||
|
@ -878,12 +1087,6 @@ private:
|
|||
bool ClassifyEightBytesWithManagedLayout(SystemVStructRegisterPassingHelperPtr helperPtr, unsigned int nestingLevel, unsigned int startOffsetOfStruct, bool isNativeStruct, MethodTable** pByValueClassCache);
|
||||
#endif // defined(UNIX_AMD64_ABI_ITF)
|
||||
|
||||
DWORD GetClassIndexFromToken(mdTypeDef typeToken)
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
return RidFromToken(typeToken) - 1;
|
||||
}
|
||||
|
||||
// called from CheckRunClassInitThrowing(). The type wasn't marked as
|
||||
// inited while we were there, so let's attempt to do the work.
|
||||
void DoRunClassInitThrowing();
|
||||
|
@ -901,7 +1104,7 @@ public:
|
|||
void SetHasClassConstructor();
|
||||
WORD GetClassConstructorSlot();
|
||||
|
||||
void AllocateRegularStaticBoxes();
|
||||
void AllocateRegularStaticBoxes(OBJECTREF** ppStaticBase);
|
||||
void AllocateRegularStaticBox(FieldDesc* pField, Object** boxedStaticHandle);
|
||||
static OBJECTREF AllocateStaticBox(MethodTable* pFieldMT, BOOL fPinned, bool canBeFrozen = false);
|
||||
|
||||
|
@ -2233,22 +2436,27 @@ public:
|
|||
#ifndef DACCESS_COMPILE
|
||||
inline PTR_BYTE GetNonGCThreadStaticsBasePointer();
|
||||
inline PTR_BYTE GetGCThreadStaticsBasePointer();
|
||||
inline PTR_BYTE GetGCThreadStaticsBaseHandle();
|
||||
#endif //!DACCESS_COMPILE
|
||||
|
||||
// Do not use except in DAC and profiler scenarios.
|
||||
// These apis are difficult to use correctly. Users must
|
||||
// 1. Be aware that a GC may make the address returned invalid
|
||||
// 2. Be aware that a thread shutdown may make the address returned invalid
|
||||
// 3. Be aware that a collectible assembly could be collected, thus rendering the address returned invalid
|
||||
// This is particularly relevant as a problem for profiler developers, but they are given the tools (such as GC events) to be notified of situations where these invariants may not hold
|
||||
inline PTR_BYTE GetNonGCThreadStaticsBasePointer(PTR_Thread pThread);
|
||||
inline PTR_BYTE GetGCThreadStaticsBasePointer(PTR_Thread pThread);
|
||||
|
||||
inline DWORD IsDynamicStatics()
|
||||
{
|
||||
LIMITED_METHOD_DAC_CONTRACT;
|
||||
return !TestFlagWithMask(enum_flag_StaticsMask, enum_flag_StaticsMask_NonDynamic);
|
||||
return GetFlag(enum_flag_DynamicStatics);
|
||||
}
|
||||
|
||||
inline void SetDynamicStatics(BOOL fGeneric)
|
||||
inline void SetDynamicStatics()
|
||||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
SetFlag(fGeneric ? enum_flag_StaticsMask_Generics : enum_flag_StaticsMask_Dynamic);
|
||||
SetFlag(enum_flag_DynamicStatics);
|
||||
}
|
||||
|
||||
inline void SetHasBoxedRegularStatics()
|
||||
|
@ -2292,7 +2500,7 @@ public:
|
|||
BOOL HasGenericsStaticsInfo()
|
||||
{
|
||||
LIMITED_METHOD_DAC_CONTRACT;
|
||||
return GetFlag(enum_flag_StaticsMask_Generics);
|
||||
return IsDynamicStatics() && HasInstantiation();
|
||||
}
|
||||
|
||||
PTR_FieldDesc GetGenericsStaticFieldDescs()
|
||||
|
@ -2302,24 +2510,8 @@ public:
|
|||
return GetGenericsStaticsInfo()->m_pFieldDescs;
|
||||
}
|
||||
|
||||
BOOL HasCrossModuleGenericStaticsInfo()
|
||||
{
|
||||
LIMITED_METHOD_DAC_CONTRACT;
|
||||
return TestFlagWithMask(enum_flag_StaticsMask, enum_flag_StaticsMask_CrossModuleGenerics);
|
||||
}
|
||||
|
||||
PTR_Module GetGenericsStaticsModuleAndID(DWORD * pID);
|
||||
|
||||
WORD GetNumHandleRegularStatics();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// DYNAMIC ID
|
||||
//
|
||||
|
||||
// Used for generics and reflection emit in memory
|
||||
DWORD GetModuleDynamicEntryID();
|
||||
Module* GetModuleForStatics();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// GENERICS DICT INFO
|
||||
//
|
||||
|
@ -2681,7 +2873,7 @@ public:
|
|||
// ------------------------------------------------------------------
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
void AllocateAuxiliaryData(LoaderAllocator *pAllocator, Module *pLoaderModule, AllocMemTracker *pamTracker, bool hasGenericStatics = false, WORD nonVirtualSlots = 0, S_SIZE_T extraAllocation = S_SIZE_T(0));
|
||||
void AllocateAuxiliaryData(LoaderAllocator *pAllocator, Module *pLoaderModule, AllocMemTracker *pamTracker, MethodTableStaticsFlags staticsFlags = MethodTableStaticsFlags::None, WORD nonVirtualSlots = 0, S_SIZE_T extraAllocation = S_SIZE_T(0));
|
||||
#endif
|
||||
|
||||
inline PTR_Const_MethodTableAuxiliaryData GetAuxiliaryData() const
|
||||
|
@ -2696,6 +2888,12 @@ public:
|
|||
return MethodTable::m_pAuxiliaryData;
|
||||
}
|
||||
|
||||
DWORD* getIsClassInitedFlagAddress()
|
||||
{
|
||||
LIMITED_METHOD_DAC_CONTRACT;
|
||||
return GetAuxiliaryDataForWrite()->getIsClassInitedFlagAddress();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// The GUID Info
|
||||
// Used by COM interop to get GUIDs (IIDs and CLSIDs)
|
||||
|
@ -3278,12 +3476,6 @@ private:
|
|||
enum_flag_UNUSED_ComponentSize_1 = 0x00000001,
|
||||
// GC depends on this bit
|
||||
enum_flag_HasCriticalFinalizer = 0x00000002, // finalizer must be run on Appdomain Unload
|
||||
enum_flag_StaticsMask = 0x0000000C,
|
||||
enum_flag_StaticsMask_NonDynamic = 0x00000000,
|
||||
enum_flag_StaticsMask_Dynamic = 0x00000008, // dynamic statics (EnC, reflection.emit)
|
||||
enum_flag_StaticsMask_Generics = 0x00000004, // generics statics
|
||||
enum_flag_StaticsMask_CrossModuleGenerics = 0x0000000C, // cross module generics statics (NGen)
|
||||
enum_flag_StaticsMask_IfGenericsThenCrossModule = 0x00000008, // helper constant to get rid of unnecessary check
|
||||
|
||||
|
||||
enum_flag_GenericsMask = 0x00000030,
|
||||
|
@ -3329,7 +3521,6 @@ private:
|
|||
// to be up to date to reflect the default values of those flags for the
|
||||
// case where this MethodTable is for a String or Array
|
||||
enum_flag_StringArrayValues = SET_FALSE(enum_flag_HasCriticalFinalizer) |
|
||||
SET_TRUE(enum_flag_StaticsMask_NonDynamic) |
|
||||
SET_FALSE(enum_flag_HasBoxedRegularStatics) |
|
||||
SET_FALSE(enum_flag_HasBoxedThreadStatics) |
|
||||
SET_TRUE(enum_flag_GenericsMask_NonGeneric) |
|
||||
|
@ -3415,10 +3606,8 @@ private:
|
|||
// TO BE UPDATED IN ORDER TO ENSURE THAT METHODTABLES DUPLICATED FOR GENERIC INSTANTIATIONS
|
||||
// CARRY THE CORECT FLAGS.
|
||||
|
||||
// The following bits describe usage of optional slots. They have to stay
|
||||
// together because of we index using them into offset arrays.
|
||||
enum_flag_HasPerInstInfo = 0x0001,
|
||||
enum_flag_wflags2_unused_1 = 0x0002,
|
||||
enum_flag_DynamicStatics = 0x0002,
|
||||
enum_flag_HasDispatchMapSlot = 0x0004,
|
||||
|
||||
enum_flag_wflags2_unused_2 = 0x0008,
|
||||
|
@ -3570,9 +3759,26 @@ private:
|
|||
PTR_GenericsStaticsInfo GetGenericsStaticsInfo()
|
||||
{
|
||||
PTR_MethodTableAuxiliaryData AuxiliaryData = GetAuxiliaryDataForWrite();
|
||||
_ASSERTE(HasGenericsStaticsInfo());
|
||||
return MethodTableAuxiliaryData::GetGenericStaticsInfo(AuxiliaryData);
|
||||
}
|
||||
|
||||
public:
|
||||
PTR_DynamicStaticsInfo GetDynamicStaticsInfo()
|
||||
{
|
||||
PTR_MethodTableAuxiliaryData AuxiliaryData = GetAuxiliaryDataForWrite();
|
||||
_ASSERTE(IsDynamicStatics());
|
||||
return MethodTableAuxiliaryData::GetDynamicStaticsInfo(AuxiliaryData);
|
||||
}
|
||||
|
||||
PTR_ThreadStaticsInfo GetThreadStaticsInfo()
|
||||
{
|
||||
PTR_MethodTableAuxiliaryData AuxiliaryData = GetAuxiliaryDataForWrite();
|
||||
_ASSERTE(GetNumThreadStaticFields() > 0);
|
||||
return MethodTableAuxiliaryData::GetThreadStaticsInfo(AuxiliaryData);
|
||||
}
|
||||
private:
|
||||
|
||||
// Optional members. These are used for fields in the data structure where
|
||||
// the fields are (a) known when MT is created and (b) there is a default
|
||||
// value for the field in the common case. That is, they are normally used
|
||||
|
@ -3650,6 +3856,8 @@ private:
|
|||
public:
|
||||
|
||||
BOOL Validate ();
|
||||
|
||||
static void GetStaticsOffsets(StaticsOffsetType staticsOffsetType, bool fGenericsStatics, uint32_t *dwGCOffset, uint32_t *dwNonGCOffset);
|
||||
}; // class MethodTable
|
||||
|
||||
#ifndef CROSSBITNESS_COMPILE
|
||||
|
|
|
@ -1083,68 +1083,45 @@ inline DWORD MethodTable::GetOptionalMembersSize()
|
|||
inline PTR_BYTE MethodTable::GetNonGCStaticsBasePointer()
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
return GetDomainLocalModule()->GetNonGCStaticsBasePointer(this);
|
||||
if (!IsDynamicStatics())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetDynamicStaticsInfo()->GetNonGCStaticsPointer();
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
inline PTR_BYTE MethodTable::GetGCStaticsBasePointer()
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
return GetDomainLocalModule()->GetGCStaticsBasePointer(this);
|
||||
if (!IsDynamicStatics())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (PTR_BYTE)GetDynamicStaticsInfo()->GetGCStaticsPointer();
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
|
||||
//==========================================================================================
|
||||
inline PTR_BYTE MethodTable::GetNonGCThreadStaticsBasePointer()
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
NOTHROW;
|
||||
GC_NOTRIGGER;
|
||||
MODE_ANY;
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
// Get the current thread
|
||||
PTR_Thread pThread = dac_cast<PTR_Thread>(GetThread());
|
||||
|
||||
// Get the current module's ModuleIndex
|
||||
ModuleIndex index = GetModuleForStatics()->GetModuleIndex();
|
||||
|
||||
PTR_ThreadLocalBlock pTLB = ThreadStatics::GetCurrentTLB(pThread);
|
||||
|
||||
PTR_ThreadLocalModule pTLM = pTLB->GetTLMIfExists(index);
|
||||
if (pTLM == NULL)
|
||||
return NULL;
|
||||
|
||||
return pTLM->GetNonGCStaticsBasePointer(this);
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
inline PTR_BYTE MethodTable::GetGCThreadStaticsBaseHandle()
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
NOTHROW;
|
||||
GC_NOTRIGGER;
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
MODE_COOPERATIVE;
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
// Get the current thread
|
||||
PTR_Thread pThread = dac_cast<PTR_Thread>(GetThread());
|
||||
|
||||
// Get the current module's ModuleIndex
|
||||
ModuleIndex index = GetModuleForStatics()->GetModuleIndex();
|
||||
|
||||
PTR_ThreadLocalBlock pTLB = ThreadStatics::GetCurrentTLB(pThread);
|
||||
|
||||
PTR_ThreadLocalModule pTLM = pTLB->GetTLMIfExists(index);
|
||||
if (pTLM == NULL)
|
||||
return NULL;
|
||||
|
||||
return dac_cast<PTR_BYTE>(pTLM->GetPrecomputedGCStaticsBaseHandle());
|
||||
EnsureTlsIndexAllocated();
|
||||
TLSIndex tlsIndex = GetThreadStaticsInfo()->NonGCTlsIndex;
|
||||
return (PTR_BYTE)GetThreadLocalStaticBase(tlsIndex);
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
|
@ -1152,25 +1129,15 @@ inline PTR_BYTE MethodTable::GetGCThreadStaticsBasePointer()
|
|||
{
|
||||
CONTRACTL
|
||||
{
|
||||
NOTHROW;
|
||||
GC_NOTRIGGER;
|
||||
THROWS;
|
||||
GC_TRIGGERS;
|
||||
MODE_COOPERATIVE;
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
// Get the current thread
|
||||
PTR_Thread pThread = dac_cast<PTR_Thread>(GetThread());
|
||||
|
||||
// Get the current module's ModuleIndex
|
||||
ModuleIndex index = GetModuleForStatics()->GetModuleIndex();
|
||||
|
||||
PTR_ThreadLocalBlock pTLB = ThreadStatics::GetCurrentTLB(pThread);
|
||||
|
||||
PTR_ThreadLocalModule pTLM = pTLB->GetTLMIfExists(index);
|
||||
if (pTLM == NULL)
|
||||
return NULL;
|
||||
|
||||
return pTLM->GetGCStaticsBasePointer(this);
|
||||
EnsureTlsIndexAllocated();
|
||||
TLSIndex tlsIndex = GetThreadStaticsInfo()->GCTlsIndex;
|
||||
return (PTR_BYTE)GetThreadLocalStaticBase(tlsIndex);
|
||||
}
|
||||
|
||||
#endif //!DACCESS_COMPILE
|
||||
|
@ -1180,16 +1147,11 @@ inline PTR_BYTE MethodTable::GetNonGCThreadStaticsBasePointer(PTR_Thread pThread
|
|||
{
|
||||
LIMITED_METHOD_DAC_CONTRACT;
|
||||
|
||||
// Get the current module's ModuleIndex
|
||||
ModuleIndex index = GetModuleForStatics()->GetModuleIndex();
|
||||
|
||||
PTR_ThreadLocalBlock pTLB = ThreadStatics::GetCurrentTLB(pThread);
|
||||
|
||||
PTR_ThreadLocalModule pTLM = pTLB->GetTLMIfExists(index);
|
||||
if (pTLM == NULL)
|
||||
TLSIndex tlsIndex = GetThreadStaticsInfo()->NonGCTlsIndex;
|
||||
if (!tlsIndex.IsAllocated())
|
||||
return NULL;
|
||||
|
||||
return pTLM->GetNonGCStaticsBasePointer(this);
|
||||
return (PTR_BYTE)GetThreadLocalStaticBaseNoCreate(pThread, tlsIndex);
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
|
@ -1197,23 +1159,11 @@ inline PTR_BYTE MethodTable::GetGCThreadStaticsBasePointer(PTR_Thread pThread)
|
|||
{
|
||||
LIMITED_METHOD_DAC_CONTRACT;
|
||||
|
||||
// Get the current module's ModuleIndex
|
||||
ModuleIndex index = GetModuleForStatics()->GetModuleIndex();
|
||||
|
||||
PTR_ThreadLocalBlock pTLB = ThreadStatics::GetCurrentTLB(pThread);
|
||||
|
||||
PTR_ThreadLocalModule pTLM = pTLB->GetTLMIfExists(index);
|
||||
if (pTLM == NULL)
|
||||
TLSIndex tlsIndex = GetThreadStaticsInfo()->GCTlsIndex;
|
||||
if (!tlsIndex.IsAllocated())
|
||||
return NULL;
|
||||
|
||||
return pTLM->GetGCStaticsBasePointer(this);
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
inline PTR_DomainLocalModule MethodTable::GetDomainLocalModule()
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
return GetModuleForStatics()->GetDomainLocalModule();
|
||||
return (PTR_BYTE)GetThreadLocalStaticBaseNoCreate(pThread, tlsIndex);
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
|
@ -1237,13 +1187,6 @@ inline OBJECTREF MethodTable::AllocateNoChecks()
|
|||
}
|
||||
|
||||
|
||||
//==========================================================================================
|
||||
inline DWORD MethodTable::GetClassIndex()
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
return GetClassIndexFromToken(GetCl());
|
||||
}
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
//==========================================================================================
|
||||
// unbox src into dest, making sure src is of the correct type.
|
||||
|
@ -1297,27 +1240,6 @@ inline void MethodTable::UnBoxIntoUnchecked(void *dest, OBJECTREF src)
|
|||
}
|
||||
#endif
|
||||
|
||||
//==========================================================================================
|
||||
FORCEINLINE PTR_Module MethodTable::GetGenericsStaticsModuleAndID(DWORD * pID)
|
||||
{
|
||||
CONTRACTL
|
||||
{
|
||||
NOTHROW;
|
||||
GC_NOTRIGGER;
|
||||
MODE_ANY;
|
||||
SUPPORTS_DAC;
|
||||
}
|
||||
CONTRACTL_END
|
||||
|
||||
_ASSERTE(HasGenericsStaticsInfo());
|
||||
|
||||
PTR_MethodTableAuxiliaryData AuxiliaryData = GetAuxiliaryDataForWrite();
|
||||
PTR_GenericsStaticsInfo staticsInfo = MethodTableAuxiliaryData::GetGenericStaticsInfo(AuxiliaryData);
|
||||
_ASSERTE(FitsIn<DWORD>(staticsInfo->m_DynamicTypeID) || staticsInfo->m_DynamicTypeID == (SIZE_T)-1);
|
||||
*pID = (DWORD)staticsInfo->m_DynamicTypeID;
|
||||
return AuxiliaryData->GetLoaderModule();
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
inline OBJECTHANDLE MethodTable::GetLoaderAllocatorObjectHandle()
|
||||
{
|
||||
|
|
|
@ -1673,21 +1673,10 @@ MethodTableBuilder::BuildMethodTableThrowing(
|
|||
//
|
||||
|
||||
// We decide here if we need a dynamic entry for our statics. We need it here because
|
||||
// the offsets of our fields will depend on this. For the dynamic case (which requires
|
||||
// an extra indirection (indirect depending of methodtable) we'll allocate the slot
|
||||
// in setupmethodtable
|
||||
if (((pAllocator->IsCollectible() || pModule->IsReflection() || bmtGenerics->HasInstantiation() || !pModule->IsStaticStoragePrepared(cl)) &&
|
||||
(bmtVT->GetClassCtorSlotIndex() != INVALID_SLOT_INDEX || bmtEnumFields->dwNumStaticFields !=0))
|
||||
#ifdef FEATURE_METADATA_UPDATER
|
||||
// Classes in modules that have been edited (would do on class level if there were a
|
||||
// way to tell if the class had been edited) also have dynamic statics as the number
|
||||
// of statics might have changed, so can't use the static module-wide storage
|
||||
|| (pModule->IsEditAndContinueEnabled() &&
|
||||
((EditAndContinueModule*)pModule)->GetApplyChangesCount() > CorDB_DEFAULT_ENC_FUNCTION_VERSION)
|
||||
#endif // FEATURE_METADATA_UPDATER
|
||||
)
|
||||
// the offsets of our fields will depend on this.
|
||||
if (bmtEnumFields->dwNumStaticFields != 0)
|
||||
{
|
||||
// We will need a dynamic id
|
||||
// We will need static variables
|
||||
bmtProp->fDynamicStatics = true;
|
||||
|
||||
if (bmtGenerics->HasInstantiation())
|
||||
|
@ -1911,15 +1900,6 @@ MethodTableBuilder::BuildMethodTableThrowing(
|
|||
|
||||
pMT->SetupGenericsStaticsInfo(pStaticFieldDescs);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get an id for the dynamic class. We store it in the class because
|
||||
// no class that is persisted in ngen should have it (ie, if the class is ngened
|
||||
// The id is stored in an optional field so we need to ensure an optional field descriptor has
|
||||
// been allocated for this EEClass instance.
|
||||
EnsureOptionalFieldsAreAllocated(GetHalfBakedClass(), m_pAllocMemTracker, pAllocator->GetLowFrequencyHeap());
|
||||
SetModuleDynamicID(GetModule()->AllocateDynamicEntry(pMT));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -7910,11 +7890,8 @@ VOID MethodTableBuilder::PlaceRegularStaticFields()
|
|||
|
||||
// Tell the module to give us the offsets we'll be using and commit space for us
|
||||
// if necessary
|
||||
DWORD dwNonGCOffset, dwGCOffset;
|
||||
GetModule()->GetOffsetsForRegularStaticData(bmtInternal->pType->GetTypeDefToken(),
|
||||
bmtProp->fDynamicStatics,
|
||||
GetNumHandleRegularStatics(), dwCumulativeStaticFieldPos,
|
||||
&dwGCOffset, &dwNonGCOffset);
|
||||
uint32_t dwNonGCOffset, dwGCOffset;
|
||||
MethodTable::GetStaticsOffsets(StaticsOffsetType::Normal, bmtProp->fGenericsStatics, &dwGCOffset, &dwNonGCOffset);
|
||||
|
||||
// Allocate boxed statics first ("x << LOG2_PTRSIZE" is equivalent to "x * sizeof(void *)")
|
||||
dwCumulativeStaticGCFieldPos = bmtFP->NumRegularStaticGCBoxedFields<<LOG2_PTRSIZE;
|
||||
|
@ -7962,17 +7939,9 @@ VOID MethodTableBuilder::PlaceRegularStaticFields()
|
|||
LOG((LF_CLASSLOADER, LL_INFO1000000, "Offset of %s: %i\n", pCurField->m_debugName, pCurField->GetOffset()));
|
||||
}
|
||||
|
||||
if (bmtProp->fDynamicStatics)
|
||||
{
|
||||
_ASSERTE(dwNonGCOffset == 0 || // no statics at all
|
||||
dwNonGCOffset == OFFSETOF__DomainLocalModule__NormalDynamicEntry__m_pDataBlob); // We need space to point to the GC statics
|
||||
_ASSERTE(dwNonGCOffset == 0 || (dwNonGCOffset == sizeof(TADDR) * 2));
|
||||
bmtProp->dwNonGCRegularStaticFieldBytes = dwCumulativeStaticFieldPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
bmtProp->dwNonGCRegularStaticFieldBytes = 0; // Non dynamics shouldnt be using this
|
||||
}
|
||||
LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Static field bytes needed (0 is normal for non dynamic case)%i\n", bmtProp->dwNonGCRegularStaticFieldBytes));
|
||||
LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Static field bytes needed %i\n", bmtProp->dwNonGCRegularStaticFieldBytes));
|
||||
}
|
||||
|
||||
|
||||
|
@ -8024,12 +7993,9 @@ VOID MethodTableBuilder::PlaceThreadStaticFields()
|
|||
|
||||
// Tell the module to give us the offsets we'll be using and commit space for us
|
||||
// if necessary
|
||||
DWORD dwNonGCOffset, dwGCOffset;
|
||||
uint32_t dwNonGCOffset, dwGCOffset;
|
||||
|
||||
GetModule()->GetOffsetsForThreadStaticData(bmtInternal->pType->GetTypeDefToken(),
|
||||
bmtProp->fDynamicStatics,
|
||||
GetNumHandleThreadStatics(), dwCumulativeStaticFieldPos,
|
||||
&dwGCOffset, &dwNonGCOffset);
|
||||
MethodTable::GetStaticsOffsets(StaticsOffsetType::ThreadLocal, bmtProp->fGenericsStatics, &dwGCOffset, &dwNonGCOffset);
|
||||
|
||||
// Allocate boxed statics first ("x << LOG2_PTRSIZE" is equivalent to "x * sizeof(void *)")
|
||||
dwCumulativeStaticGCFieldPos = bmtFP->NumThreadStaticGCBoxedFields<<LOG2_PTRSIZE;
|
||||
|
@ -8077,15 +8043,14 @@ VOID MethodTableBuilder::PlaceThreadStaticFields()
|
|||
LOG((LF_CLASSLOADER, LL_INFO1000000, "Offset of %s: %i\n", pCurField->m_debugName, pCurField->GetOffset()));
|
||||
}
|
||||
|
||||
if (bmtProp->fDynamicStatics)
|
||||
if (dwCumulativeStaticFieldPos != 0)
|
||||
{
|
||||
_ASSERTE(dwNonGCOffset == 0 || // no thread statics at all
|
||||
dwNonGCOffset == OFFSETOF__ThreadLocalModule__DynamicEntry__m_pDataBlob); // We need space to point to the GC statics
|
||||
_ASSERTE(bmtProp->fDynamicStatics);
|
||||
bmtProp->dwNonGCThreadStaticFieldBytes = dwCumulativeStaticFieldPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
bmtProp->dwNonGCThreadStaticFieldBytes = 0; // Non dynamics shouldnt be using this
|
||||
bmtProp->dwNonGCThreadStaticFieldBytes = 0;
|
||||
}
|
||||
LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: ThreadStatic field bytes needed (0 is normal for non dynamic case)%i\n", bmtProp->dwNonGCThreadStaticFieldBytes));
|
||||
}
|
||||
|
@ -10272,6 +10237,7 @@ MethodTable * MethodTableBuilder::AllocateNewMT(
|
|||
BOOL isInterface,
|
||||
BOOL fDynamicStatics,
|
||||
BOOL fHasGenericsStaticsInfo,
|
||||
bool fHasThreadStatics,
|
||||
BOOL fHasVirtualStaticMethods
|
||||
#ifdef FEATURE_COMINTEROP
|
||||
, BOOL fHasDynamicInterfaceMap
|
||||
|
@ -10374,7 +10340,20 @@ MethodTable * MethodTableBuilder::AllocateNewMT(
|
|||
pMT->SetFlag(MethodTable::enum_flag_HasPerInstInfo);
|
||||
}
|
||||
|
||||
pMT->AllocateAuxiliaryData(pAllocator, pLoaderModule, pamTracker, fHasGenericsStaticsInfo, static_cast<WORD>(dwNonVirtualSlots), S_SIZE_T(dispatchMapAllocationSize));
|
||||
MethodTableStaticsFlags staticsFlags = MethodTableStaticsFlags::None;
|
||||
if (fDynamicStatics)
|
||||
staticsFlags |= MethodTableStaticsFlags::Present;
|
||||
|
||||
if (fHasGenericsStaticsInfo)
|
||||
{
|
||||
_ASSERTE(fDynamicStatics);
|
||||
staticsFlags |= MethodTableStaticsFlags::Generic;
|
||||
}
|
||||
|
||||
if (fHasThreadStatics)
|
||||
staticsFlags |= MethodTableStaticsFlags::Thread;
|
||||
|
||||
pMT->AllocateAuxiliaryData(pAllocator, pLoaderModule, pamTracker, staticsFlags, static_cast<WORD>(dwNonVirtualSlots), S_SIZE_T(dispatchMapAllocationSize));
|
||||
|
||||
pMT->GetAuxiliaryDataForWrite()->SetIsNotFullyLoadedForBuildMethodTable();
|
||||
|
||||
|
@ -10470,7 +10449,7 @@ MethodTable * MethodTableBuilder::AllocateNewMT(
|
|||
|
||||
if (fDynamicStatics)
|
||||
{
|
||||
pMT->SetDynamicStatics(fHasGenericsStaticsInfo);
|
||||
pMT->SetDynamicStatics();
|
||||
}
|
||||
|
||||
// the dictionary pointers follow the interface map
|
||||
|
@ -10574,6 +10553,7 @@ MethodTableBuilder::SetupMethodTable2(
|
|||
IsInterface(),
|
||||
bmtProp->fDynamicStatics,
|
||||
bmtProp->fGenericsStatics,
|
||||
bmtEnumFields->dwNumThreadStaticFields != 0,
|
||||
bmtProp->fHasVirtualStaticMethods,
|
||||
#ifdef FEATURE_COMINTEROP
|
||||
fHasDynamicInterfaceMap,
|
||||
|
@ -10663,6 +10643,7 @@ MethodTableBuilder::SetupMethodTable2(
|
|||
pMT->SetHasClassConstructor();
|
||||
CONSISTENCY_CHECK(pMT->GetClassConstructorSlot() == bmtVT->pCCtor->GetSlotIndex());
|
||||
}
|
||||
|
||||
if (bmtVT->pDefaultCtor != NULL)
|
||||
{
|
||||
pMT->SetHasDefaultConstructor();
|
||||
|
|
|
@ -206,7 +206,6 @@ private:
|
|||
void SetUnsafeValueClass() { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetUnsafeValueClass(); }
|
||||
void SetHasFieldsWhichMustBeInited() { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetHasFieldsWhichMustBeInited(); }
|
||||
void SetHasNonPublicFields() { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetHasNonPublicFields(); }
|
||||
void SetModuleDynamicID(DWORD x) { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetModuleDynamicID(x); }
|
||||
void SetNumHandleRegularStatics(WORD x) { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetNumHandleRegularStatics(x); }
|
||||
void SetNumHandleThreadStatics(WORD x) { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetNumHandleThreadStatics(x); }
|
||||
void SetAlign8Candidate() { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetAlign8Candidate(); }
|
||||
|
@ -2952,6 +2951,7 @@ private:
|
|||
BOOL isIFace,
|
||||
BOOL fDynamicStatics,
|
||||
BOOL fHasGenericsStaticsInfo,
|
||||
bool fHasThreadStatics,
|
||||
BOOL fHasVirtualStaticMethods
|
||||
#ifdef FEATURE_COMINTEROP
|
||||
, BOOL bHasDynamicInterfaceMap
|
||||
|
|
|
@ -3497,21 +3497,6 @@ static PCODE getHelperForSharedStatic(Module * pModule, CORCOMPILE_FIXUP_BLOB_KI
|
|||
|
||||
CorInfoHelpFunc helpFunc = CEEInfo::getSharedStaticsHelper(pFD, pMT);
|
||||
|
||||
TADDR moduleID = pMT->GetModuleForStatics()->GetModuleID();
|
||||
|
||||
TADDR classID = 0;
|
||||
if (helpFunc != CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR && helpFunc != CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR)
|
||||
{
|
||||
if (pMT->IsDynamicStatics())
|
||||
{
|
||||
classID = pMT->GetModuleDynamicEntryID();
|
||||
}
|
||||
else
|
||||
{
|
||||
classID = pMT->GetClassIndex();
|
||||
}
|
||||
}
|
||||
|
||||
bool fUnbox = (pFD->GetFieldType() == ELEMENT_TYPE_VALUETYPE);
|
||||
|
||||
AllocMemTracker amTracker;
|
||||
|
@ -3521,8 +3506,31 @@ static PCODE getHelperForSharedStatic(Module * pModule, CORCOMPILE_FIXUP_BLOB_KI
|
|||
AllocMem(S_SIZE_T(sizeof(StaticFieldAddressArgs))));
|
||||
|
||||
pArgs->staticBaseHelper = (FnStaticBaseHelper)CEEJitInfo::getHelperFtnStatic((CorInfoHelpFunc)helpFunc);
|
||||
pArgs->arg0 = moduleID;
|
||||
pArgs->arg1 = classID;
|
||||
|
||||
switch(helpFunc)
|
||||
{
|
||||
case CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETDYNAMIC_GCTHREADSTATIC_BASE:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCTHREADSTATIC_BASE:
|
||||
pArgs->arg0 = (TADDR)pMT->GetThreadStaticsInfo();
|
||||
break;
|
||||
|
||||
case CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETPINNED_GCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETDYNAMIC_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETPINNED_GCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE_NOCTOR:
|
||||
case CORINFO_HELP_GETDYNAMIC_NONGCSTATIC_BASE:
|
||||
case CORINFO_HELP_GETPINNED_NONGCSTATIC_BASE:
|
||||
pArgs->arg0 = (TADDR)pMT->GetDynamicStaticsInfo();
|
||||
break;
|
||||
default:
|
||||
_ASSERTE(!"Unexpected shared statics helper CORINFO_HELP_FUNC");
|
||||
pArgs->arg0 = 0;
|
||||
break;
|
||||
}
|
||||
pArgs->offset = pFD->GetOffset();
|
||||
|
||||
PCODE pHelper = DynamicHelpers::CreateHelper(pModule->GetLoaderAllocator(), (TADDR)pArgs,
|
||||
|
@ -3537,52 +3545,50 @@ static PCODE getHelperForStaticBase(Module * pModule, CORCOMPILE_FIXUP_BLOB_KIND
|
|||
{
|
||||
STANDARD_VM_CONTRACT;
|
||||
|
||||
int helpFunc = CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE;
|
||||
pMT->AttemptToPreinit();
|
||||
bool GCStatic = (kind == ENCODE_STATIC_BASE_GC_HELPER || kind == ENCODE_THREAD_STATIC_BASE_GC_HELPER);
|
||||
bool noCtor = pMT->IsClassInited();
|
||||
bool threadStatic = (kind == ENCODE_THREAD_STATIC_BASE_NONGC_HELPER || kind == ENCODE_THREAD_STATIC_BASE_GC_HELPER);
|
||||
|
||||
if (kind == ENCODE_STATIC_BASE_GC_HELPER || kind == ENCODE_THREAD_STATIC_BASE_GC_HELPER)
|
||||
{
|
||||
helpFunc = CORINFO_HELP_GETSHARED_GCSTATIC_BASE;
|
||||
}
|
||||
CorInfoHelpFunc helper;
|
||||
|
||||
if (pMT->IsDynamicStatics())
|
||||
if (threadStatic)
|
||||
{
|
||||
const int delta = CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS - CORINFO_HELP_GETSHARED_GCSTATIC_BASE;
|
||||
helpFunc += delta;
|
||||
if (GCStatic)
|
||||
{
|
||||
if (noCtor)
|
||||
helper = CORINFO_HELP_GET_GCTHREADSTATIC_BASE_NOCTOR;
|
||||
else
|
||||
helper = CORINFO_HELP_GET_GCTHREADSTATIC_BASE;
|
||||
}
|
||||
else
|
||||
if (!pMT->HasClassConstructor() && !pMT->HasBoxedRegularStatics())
|
||||
{
|
||||
const int delta = CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR - CORINFO_HELP_GETSHARED_GCSTATIC_BASE;
|
||||
helpFunc += delta;
|
||||
if (noCtor)
|
||||
helper = CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE_NOCTOR;
|
||||
else
|
||||
helper = CORINFO_HELP_GET_NONGCTHREADSTATIC_BASE;
|
||||
}
|
||||
|
||||
if (kind == ENCODE_THREAD_STATIC_BASE_NONGC_HELPER || kind == ENCODE_THREAD_STATIC_BASE_GC_HELPER)
|
||||
}
|
||||
else
|
||||
{
|
||||
const int delta = CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE - CORINFO_HELP_GETSHARED_GCSTATIC_BASE;
|
||||
helpFunc += delta;
|
||||
if (GCStatic)
|
||||
{
|
||||
if (noCtor)
|
||||
helper = CORINFO_HELP_GET_GCSTATIC_BASE_NOCTOR;
|
||||
else
|
||||
helper = CORINFO_HELP_GET_GCSTATIC_BASE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (noCtor)
|
||||
helper = CORINFO_HELP_GET_NONGCSTATIC_BASE_NOCTOR;
|
||||
else
|
||||
helper = CORINFO_HELP_GET_NONGCSTATIC_BASE;
|
||||
}
|
||||
}
|
||||
|
||||
PCODE pHelper;
|
||||
if (helpFunc == CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR || helpFunc == CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR)
|
||||
{
|
||||
pHelper = DynamicHelpers::CreateHelper(pModule->GetLoaderAllocator(), pMT->GetModule()->GetModuleID(), CEEJitInfo::getHelperFtnStatic((CorInfoHelpFunc)helpFunc));
|
||||
}
|
||||
else
|
||||
{
|
||||
TADDR moduleID = pMT->GetModuleForStatics()->GetModuleID();
|
||||
|
||||
TADDR classID;
|
||||
if (pMT->IsDynamicStatics())
|
||||
{
|
||||
classID = pMT->GetModuleDynamicEntryID();
|
||||
}
|
||||
else
|
||||
{
|
||||
classID = pMT->GetClassIndex();
|
||||
}
|
||||
|
||||
pHelper = DynamicHelpers::CreateHelper(pModule->GetLoaderAllocator(), moduleID, classID, CEEJitInfo::getHelperFtnStatic((CorInfoHelpFunc)helpFunc));
|
||||
}
|
||||
pHelper = DynamicHelpers::CreateHelper(pModule->GetLoaderAllocator(), (TADDR)pMT, CEEJitInfo::getHelperFtnStatic(helper));
|
||||
|
||||
return pHelper;
|
||||
}
|
||||
|
@ -3800,6 +3806,11 @@ PCODE DynamicHelperFixup(TransitionBlock * pTransitionBlock, TADDR * pCell, DWOR
|
|||
Statics:
|
||||
th.AsMethodTable()->EnsureInstanceActive();
|
||||
th.AsMethodTable()->CheckRunClassInitThrowing();
|
||||
if (kind == ENCODE_THREAD_STATIC_BASE_NONGC_HELPER || kind == ENCODE_THREAD_STATIC_BASE_GC_HELPER ||
|
||||
(kind == ENCODE_FIELD_ADDRESS && pFD->IsThreadStatic()))
|
||||
{
|
||||
th.AsMethodTable()->EnsureTlsIndexAllocated();
|
||||
}
|
||||
fReliable = true;
|
||||
break;
|
||||
|
||||
|
@ -4139,11 +4150,9 @@ extern "C" SIZE_T STDCALL DynamicHelperWorker(TransitionBlock * pTransitionBlock
|
|||
result = (SIZE_T)th.AsMethodTable()->GetGCStaticsBasePointer();
|
||||
break;
|
||||
case ENCODE_THREAD_STATIC_BASE_NONGC_HELPER:
|
||||
ThreadStatics::GetTLM(th.AsMethodTable())->EnsureClassAllocated(th.AsMethodTable());
|
||||
result = (SIZE_T)th.AsMethodTable()->GetNonGCThreadStaticsBasePointer();
|
||||
break;
|
||||
case ENCODE_THREAD_STATIC_BASE_GC_HELPER:
|
||||
ThreadStatics::GetTLM(th.AsMethodTable())->EnsureClassAllocated(th.AsMethodTable());
|
||||
result = (SIZE_T)th.AsMethodTable()->GetGCThreadStaticsBasePointer();
|
||||
break;
|
||||
case ENCODE_CCTOR_TRIGGER:
|
||||
|
|
|
@ -143,9 +143,7 @@ inline BOOL IsClassOfMethodTableInited(MethodTable * pMethodTable)
|
|||
{
|
||||
LIMITED_METHOD_CONTRACT;
|
||||
|
||||
return ((pMethodTable->GetModuleForStatics() != NULL) &&
|
||||
(pMethodTable->GetDomainLocalModule() != NULL) &&
|
||||
pMethodTable->IsClassInited());
|
||||
return pMethodTable->IsClassInited();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -201,12 +201,6 @@ ASMCONSTANTS_C_ASSERT(MethodDesc_ALIGNMENT_SHIFT == MethodDesc::ALIGNMENT_SHIFT)
|
|||
ASMCONSTANTS_C_ASSERT(ResolveCacheElem__target == offsetof(ResolveCacheElem, target));
|
||||
ASMCONSTANTS_C_ASSERT(ResolveCacheElem__pNext == offsetof(ResolveCacheElem, pNext));
|
||||
|
||||
#define DomainLocalModule__m_pDataBlob 0x30
|
||||
#define DomainLocalModule__m_pGCStatics 0x20
|
||||
ASMCONSTANTS_C_ASSERT(DomainLocalModule__m_pDataBlob == offsetof(DomainLocalModule, m_pDataBlob));
|
||||
ASMCONSTANTS_C_ASSERT(DomainLocalModule__m_pGCStatics == offsetof(DomainLocalModule, m_pGCStatics));
|
||||
|
||||
|
||||
// For JIT_PInvokeBegin and JIT_PInvokeEnd helpers
|
||||
#define Frame__m_Next 0x08
|
||||
ASMCONSTANTS_C_ASSERT(Frame__m_Next == offsetof(Frame, m_Next))
|
||||
|
|
|
@ -520,25 +520,6 @@ NESTED_ENTRY TheUMEntryPrestub, _TEXT, UnhandledExceptionHandlerUnix
|
|||
EPILOG_BRANCH_REG t4
|
||||
NESTED_END TheUMEntryPrestub, _TEXT
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// void* JIT_GetSharedGCStaticBase(SIZE_T moduleDomainID, DWORD dwClassDomainID)
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedGCStaticBase_SingleAppDomain, _TEXT
|
||||
// If class is not initialized, bail to C++ helper
|
||||
addi a2, a0, DomainLocalModule__m_pDataBlob
|
||||
add a2, a2, a1
|
||||
lb a2, 0(a2)
|
||||
andi t5, a2, 1
|
||||
beq t5, zero, LOCAL_LABEL(JIT_GetSharedGCStaticBase_SingleAppDomain_CallHelper)
|
||||
|
||||
ld a0, DomainLocalModule__m_pGCStatics(a0)
|
||||
ret
|
||||
|
||||
LOCAL_LABEL(JIT_GetSharedGCStaticBase_SingleAppDomain_CallHelper):
|
||||
// Tail call JIT_GetSharedGCStaticBase_Helper
|
||||
call JIT_GetSharedGCStaticBase_Helper
|
||||
LEAF_END JIT_GetSharedGCStaticBase_SingleAppDomain, _TEXT
|
||||
|
||||
// Make sure the `FaultingExceptionFrame_StackAlloc` is 16-byte aligned.
|
||||
#define FaultingExceptionFrame_StackAlloc (SIZEOF__GSCookie + SIZEOF__FaultingExceptionFrame + 0x8)
|
||||
#define FaultingExceptionFrame_FrameOffset SIZEOF__GSCookie
|
||||
|
@ -667,22 +648,6 @@ NESTED_ENTRY ResolveWorkerAsmStub, _TEXT, NoHandler
|
|||
EPILOG_BRANCH_REG t4
|
||||
NESTED_END ResolveWorkerAsmStub, _TEXT
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// void* JIT_GetSharedNonGCStaticBaseNoCtor(SIZE_T moduleDomainID, DWORD dwClassDomainID)
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
ret
|
||||
LEAF_END JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// void* JIT_GetSharedGCStaticBaseNoCtor(SIZE_T moduleDomainID, DWORD dwClassDomainID)
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
ld a0, (DomainLocalModule__m_pGCStatics)(a0)
|
||||
ret
|
||||
LEAF_END JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
|
||||
|
||||
|
||||
#ifdef FEATURE_HIJACK
|
||||
// ------------------------------------------------------------------
|
||||
// Hijack function for functions which return a scalar type or a struct (value type)
|
||||
|
@ -848,30 +813,6 @@ LEAF_END setFPReturn, _TEXT
|
|||
|
||||
#endif // FEATURE_COMINTEROP
|
||||
|
||||
//
|
||||
// JIT Static access helpers when coreclr host specifies single appdomain flag
|
||||
//
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// void* JIT_GetSharedNonGCStaticBase(SIZE_T moduleDomainID, DWORD dwClassDomainID)
|
||||
|
||||
LEAF_ENTRY JIT_GetSharedNonGCStaticBase_SingleAppDomain, _TEXT
|
||||
// If class is not initialized, bail to C++ helper
|
||||
// dext a1, a1, 0, 32
|
||||
addi a2, a0, DomainLocalModule__m_pDataBlob
|
||||
|
||||
add a2, a2, a1
|
||||
lb a2, 0(a2)
|
||||
andi t4, a2, 1
|
||||
beq t4, zero, LOCAL_LABEL(JIT_GetSharedNonGCStaticBase_SingleAppDomain_CallHelper)
|
||||
|
||||
ret
|
||||
|
||||
LOCAL_LABEL(JIT_GetSharedNonGCStaticBase_SingleAppDomain_CallHelper):
|
||||
// Tail call JIT_GetSharedNonGCStaticBase_Helper
|
||||
tail JIT_GetSharedNonGCStaticBase_Helper
|
||||
LEAF_END JIT_GetSharedNonGCStaticBase_SingleAppDomain, _TEXT
|
||||
|
||||
#ifdef FEATURE_READYTORUN
|
||||
|
||||
NESTED_ENTRY DelayLoad_MethodCall_FakeProlog, _TEXT, NoHandler
|
||||
|
|
|
@ -104,10 +104,6 @@ inline unsigned StackElemSize(unsigned parmSize, bool isValueType, bool isFloatH
|
|||
//
|
||||
// Create alias for optimized implementations of helpers provided on this platform
|
||||
//
|
||||
#define JIT_GetSharedGCStaticBase JIT_GetSharedGCStaticBase_SingleAppDomain
|
||||
#define JIT_GetSharedNonGCStaticBase JIT_GetSharedNonGCStaticBase_SingleAppDomain
|
||||
#define JIT_GetSharedGCStaticBaseNoCtor JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain
|
||||
#define JIT_GetSharedNonGCStaticBaseNoCtor JIT_GetSharedNonGCStaticBaseNoCtor_SingleAppDomain
|
||||
|
||||
//**********************************************************************
|
||||
// Frames
|
||||
|
|
|
@ -85,6 +85,7 @@ void SpinLock::Init(LOCK_TYPE type, bool RequireCoopGC)
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
#ifdef _DEBUG
|
||||
BOOL SpinLock::OwnedByCurrentThread()
|
||||
{
|
||||
|
@ -398,5 +399,6 @@ void SpinLockProfiler::DumpStatics()
|
|||
}
|
||||
|
||||
#endif // _DEBUG
|
||||
#endif // !DACCESS_COMPILE
|
||||
|
||||
// End of file: spinlock.cpp
|
||||
|
|
|
@ -134,7 +134,8 @@ enum LOCK_TYPE
|
|||
#endif
|
||||
LOCK_REFLECTCACHE = 5,
|
||||
LOCK_CORMAP = 7,
|
||||
LOCK_TYPE_DEFAULT = 8
|
||||
LOCK_TLSDATA = 8,
|
||||
LOCK_TYPE_DEFAULT = 9
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -204,6 +205,7 @@ public:
|
|||
static void AcquireLock(SpinLock *s);
|
||||
static void ReleaseLock(SpinLock *s);
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
class Holder
|
||||
{
|
||||
SpinLock * m_pSpinLock;
|
||||
|
@ -224,9 +226,10 @@ public:
|
|||
m_pSpinLock->FreeLock();
|
||||
}
|
||||
};
|
||||
#endif // !DACCESS_COMPILE
|
||||
};
|
||||
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
typedef SpinLock::Holder SpinLockHolder;
|
||||
#define TAKE_SPINLOCK_AND_DONOT_TRIGGER_GC(lock) \
|
||||
SpinLockHolder __spinLockHolder(lock);\
|
||||
|
@ -244,6 +247,8 @@ typedef SpinLock::Holder SpinLockHolder;
|
|||
SpinLock::ReleaseLock(lock); \
|
||||
} \
|
||||
|
||||
#endif // !DACCESS_COMPILE
|
||||
|
||||
__inline BOOL IsOwnerOfSpinLock (LPVOID lock)
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
|
|
|
@ -82,26 +82,26 @@ DebugBlockingItemHolder::DebugBlockingItemHolder(Thread *pThread, DebugBlockingI
|
|||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
// Try to get the address of the thread-local slot for the managed ThreadBlockingInfo.t_first
|
||||
m_ppFirstBlockingInfo = (ThreadBlockingInfo**)&t_ThreadStatics.ThreadBlockingInfo_First;
|
||||
#ifdef _DEBUG
|
||||
// Try to verify the address of the thread-local slot for the managed ThreadBlockingInfo.t_first matches the address of the native thread static
|
||||
EX_TRY
|
||||
{
|
||||
FieldDesc *pFD = CoreLibBinder::GetField(FIELD__THREAD_BLOCKING_INFO__FIRST);
|
||||
m_ppFirstBlockingInfo = (ThreadBlockingInfo **)Thread::GetStaticFieldAddress(pFD);
|
||||
_ASSERTE(m_ppFirstBlockingInfo == (ThreadBlockingInfo **)Thread::GetStaticFieldAddress(pFD));
|
||||
}
|
||||
EX_CATCH
|
||||
{
|
||||
}
|
||||
EX_END_CATCH(RethrowTerminalExceptions);
|
||||
#endif
|
||||
|
||||
if (m_ppFirstBlockingInfo != nullptr)
|
||||
{
|
||||
// Push info for the managed ThreadBlockingInfo
|
||||
m_blockingInfo.objectPtr = pItem->pMonitor;
|
||||
m_blockingInfo.objectKind = (ThreadBlockingInfo::ObjectKind)pItem->type;
|
||||
m_blockingInfo.timeoutMs = (INT32)pItem->dwTimeout;
|
||||
m_blockingInfo.next = *m_ppFirstBlockingInfo;
|
||||
*m_ppFirstBlockingInfo = &m_blockingInfo;
|
||||
}
|
||||
|
||||
pThread->DebugBlockingInfo.PushBlockingItem(pItem);
|
||||
}
|
||||
|
@ -115,14 +115,8 @@ DebugBlockingItemHolder::~DebugBlockingItemHolder()
|
|||
|
||||
m_pThread->DebugBlockingInfo.PopBlockingItem();
|
||||
|
||||
if (m_ppFirstBlockingInfo != nullptr)
|
||||
{
|
||||
// Pop info for the managed ThreadBlockingInfo
|
||||
_ASSERTE(
|
||||
m_ppFirstBlockingInfo ==
|
||||
(void *)m_pThread->GetStaticFieldAddrNoCreate(CoreLibBinder::GetField(FIELD__THREAD_BLOCKING_INFO__FIRST)));
|
||||
_ASSERTE(*m_ppFirstBlockingInfo == &m_blockingInfo);
|
||||
*m_ppFirstBlockingInfo = m_blockingInfo.next;
|
||||
}
|
||||
}
|
||||
#endif //DACCESS_COMPILE
|
||||
|
|
|
@ -111,24 +111,6 @@ BYTE* ThreadStore::s_pOSContextBuffer = NULL;
|
|||
|
||||
CLREvent *ThreadStore::s_pWaitForStackCrawlEvent;
|
||||
|
||||
PTR_ThreadLocalModule ThreadLocalBlock::GetTLMIfExists(ModuleIndex index)
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
SUPPORTS_DAC;
|
||||
|
||||
if (index.m_dwIndex >= m_TLMTableSize)
|
||||
return NULL;
|
||||
|
||||
return m_pTLMTable[index.m_dwIndex].pTLM;
|
||||
}
|
||||
|
||||
PTR_ThreadLocalModule ThreadLocalBlock::GetTLMIfExists(MethodTable* pMT)
|
||||
{
|
||||
WRAPPER_NO_CONTRACT;
|
||||
ModuleIndex index = pMT->GetModuleForStatics()->GetModuleIndex();
|
||||
return GetTLMIfExists(index);
|
||||
}
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
|
||||
BOOL Thread::s_fCleanFinalizedThread = FALSE;
|
||||
|
@ -370,6 +352,7 @@ void SetThread(Thread* t)
|
|||
gCurrentThreadInfo.m_pThread = t;
|
||||
if (t != NULL)
|
||||
{
|
||||
InitializeCurrentThreadsStaticData(t);
|
||||
EnsureTlsDestructionMonitor();
|
||||
}
|
||||
|
||||
|
@ -1613,6 +1596,8 @@ Thread::Thread()
|
|||
m_isInForbidSuspendForDebuggerRegion = false;
|
||||
m_hasPendingActivation = false;
|
||||
|
||||
m_ThreadLocalDataPtr = NULL;
|
||||
|
||||
#ifdef _DEBUG
|
||||
memset(dangerousObjRefs, 0, sizeof(dangerousObjRefs));
|
||||
#endif // _DEBUG
|
||||
|
@ -7482,10 +7467,6 @@ LPVOID Thread::GetStaticFieldAddress(FieldDesc *pFD)
|
|||
// for static field the MethodTable is exact even for generic classes
|
||||
MethodTable *pMT = pFD->GetEnclosingMethodTable();
|
||||
|
||||
// We need to make sure that the class has been allocated, however
|
||||
// we should not call the class constructor
|
||||
ThreadStatics::GetTLM(pMT)->EnsureClassAllocated(pMT);
|
||||
|
||||
PTR_BYTE base = NULL;
|
||||
|
||||
if (pFD->GetFieldType() == ELEMENT_TYPE_CLASS ||
|
||||
|
@ -7643,25 +7624,15 @@ void Thread::DeleteThreadStaticData()
|
|||
CONTRACTL {
|
||||
NOTHROW;
|
||||
GC_NOTRIGGER;
|
||||
MODE_COOPERATIVE;
|
||||
}
|
||||
CONTRACTL_END;
|
||||
|
||||
m_ThreadLocalBlock.FreeTable();
|
||||
}
|
||||
|
||||
//+----------------------------------------------------------------------------
|
||||
//
|
||||
// Method: Thread::DeleteThreadStaticData public
|
||||
//
|
||||
// Synopsis: Delete the static data for the given module. This is called
|
||||
// when the AssemblyLoadContext unloads.
|
||||
//
|
||||
//
|
||||
//+----------------------------------------------------------------------------
|
||||
|
||||
void Thread::DeleteThreadStaticData(ModuleIndex index)
|
||||
FreeLoaderAllocatorHandlesForTLSData(this);
|
||||
if (!IsAtProcessExit() && !g_fEEShutDown)
|
||||
{
|
||||
m_ThreadLocalBlock.FreeTLM(index.m_dwIndex, FALSE /* isThreadShuttingDown */);
|
||||
FreeThreadStaticData(m_ThreadLocalDataPtr, this);
|
||||
}
|
||||
}
|
||||
|
||||
OBJECTREF Thread::GetCulture(BOOL bUICulture)
|
||||
|
@ -8214,7 +8185,8 @@ Thread::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
|
|||
|
||||
m_ExceptionState.EnumChainMemoryRegions(flags);
|
||||
|
||||
m_ThreadLocalBlock.EnumMemoryRegions(flags);
|
||||
if (GetThreadLocalDataPtr() != NULL)
|
||||
EnumThreadMemoryRegions(GetThreadLocalDataPtr(), flags);
|
||||
|
||||
if (flags != CLRDATA_ENUM_MEM_MINI && flags != CLRDATA_ENUM_MEM_TRIAGE)
|
||||
{
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue