Skip to content

Commit

Permalink
Merge branch 'main' into morecodecleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
stephentoub committed Jul 21, 2024
2 parents b409cb4 + 18b2ef1 commit ee0a277
Show file tree
Hide file tree
Showing 111 changed files with 2,570 additions and 954 deletions.
62 changes: 60 additions & 2 deletions docs/design/datacontracts/RuntimeTypeSystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ This contract is for exploring the properties of the runtime types of values on

## APIs of contract

### TypeHandle

A `TypeHandle` is the runtime representation of the type information about a value which is represented as a TypeHandle.
Given a `TargetPointer` address, the `RuntimeTypeSystem` contract provides a `TypeHandle` for querying the details of the `TypeHandle`.


``` csharp
struct TypeHandle
{
Expand All @@ -28,6 +29,8 @@ internal enum CorElementType
A `TypeHandle` is the runtime representation of the type information about a value. This can be constructed from the address of a `TypeHandle` or a `MethodTable`.

``` csharp
partial interface IRuntimeTypeSystem : IContract
{
#region TypeHandle inspection APIs
public virtual TypeHandle GetTypeHandle(TargetPointer targetPointer);

Expand Down Expand Up @@ -73,10 +76,35 @@ A `TypeHandle` is the runtime representation of the type information about a val
public virtual bool IsFunctionPointer(TypeHandle typeHandle, out ReadOnlySpan<TypeHandle> retAndArgTypes, out byte callConv);

#endregion TypeHandle inspection APIs
}
```

### MethodDesc

A `MethodDesc` is the runtime representation of a managed method (either from IL, from reflection emit, or generated by the runtime).

```csharp
struct MethodDescHandle
{
// no public properties or constructors
internal TargetPointer Address { get; }
}
```

```csharp
partial interface IRuntimeTypeSystem : IContract
{
public virtual MethodDescHandle GetMethodDescHandle(TargetPointer methodDescPointer);

public virtual TargetPointer GetMethodTable(MethodDescHandle methodDesc);
}
```

## Version 1

### TypeHandle

The `MethodTable` inspection APIs are implemented in terms of the following flags on the runtime `MethodTable` structure:

``` csharp
Expand Down Expand Up @@ -233,7 +261,11 @@ static class RuntimeTypeSystem_1_Helpers
}
```

The contract depends on the global pointer value `FreeObjectMethodTablePointer`.
The contract depends on the following globals

| Global name | Meaning |
| --- | --- |
| `FreeObjectMethodTablePointer` | A pointer to the address of a `MethodTable` used by the GC to indicate reclaimed memory

The contract additionally depends on these data descriptors

Expand All @@ -251,6 +283,7 @@ The contract additionally depends on these data descriptors
| `EEClass` | `InternalCorElementType` | An InternalCorElementType uses the enum values of a CorElementType to indicate some of the information about the type of the type which uses the EEClass In particular, all reference types are CorElementType.Class, Enums are the element type of their underlying type and ValueTypes which can exactly be represented as an element type are represented as such, all other values types are represented as CorElementType.ValueType. |
| `EEClass` | `MethodTable` | Pointer to the canonical MethodTable of this type |
| `EEClass` | `NumMethods` | Count of methods attached to the EEClass |
| `EEClass` | `NumNonVirtualSlots` | Count of non-virtual slots for the EEClass |
| `EEClass` | `CorTypeAttr` | Various flags |
| `ArrayClass` | `Rank` | Rank of the associated array MethodTable |
| `TypeDesc` | `TypeAndFlags` | The lower 8 bits are the CorElementType of the `TypeDesc`, the upper 24 bits are reserved for flags |
Expand Down Expand Up @@ -523,3 +556,28 @@ The contract additionally depends on these data descriptors
return true;
}
```

### MethodDesc

The version 1 `MethodDesc` APIs depend on the `MethodDescAlignment` global and the `MethodDesc` and `MethodDescChunk` data descriptors.

| Global name | Meaning |
| --- | --- |
| `MethodDescAlignment` | `MethodDescChunk` trailing data is allocated in multiples of this constant. The size (in bytes) of each `MethodDesc` (or subclass) instance is a multiple of this constant.


In the runtime a `MethodDesc` implicitly belongs to a single `MethodDescChunk` and some common data is shared between method descriptors that belong to the same chunk. A single method table
will typically have multiple chunks. There are subkinds of MethodDescs at runtime of varying sizes (but the sizes must be mutliples of `MethodDescAlignment`) and each chunk contains method descriptors of the same size.

We depend on the following data descriptors:
| Data Descriptor Name | Field | Meaning |
| --- | --- | --- |
| `MethodDesc` | `ChunkIndex` | Offset of this `MethodDesc` relative to the end of its containing `MethodDescChunk` - in multiples of `MethodDescAlignment`
| `MethodDesc` | `Slot` | The method's slot
| `MethodDesc` | `Flags` | The method's flags
| `MethodDescChunk` | `MethodTable` | The method table set of methods belongs to
| `MethodDescChunk` | `Next` | The next chunk of methods
| `MethodDescChunk` | `Size` | The size of this `MethodDescChunk` following this `MethodDescChunk` header, minus 1. In multiples of `MethodDescAlignment`
| `MethodDescChunk` | `Count` | The number of `MethodDesc` entries in this chunk, minus 1.

**TODO(cdac)**
4 changes: 2 additions & 2 deletions docs/design/specs/Memory-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ void ThreadFunc1()
}

// thread #2
void ThreadFunc1()
void ThreadFunc2()
{
while (true)
{
Expand All @@ -197,7 +197,7 @@ void ThreadFunc1()
}

// thread #3
void ThreadFunc2()
void ThreadFunc3()
{
MyClass localObj = obj;
if (localObj != null)
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/debug/daccess/dacimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1243,6 +1243,7 @@ class ClrDataAccess
HRESULT GetObjectExceptionDataImpl(CLRDATA_ADDRESS objAddr, struct DacpExceptionObjectData *data);
HRESULT GetObjectStringDataImpl(CLRDATA_ADDRESS obj, unsigned int count, _Inout_updates_z_(count) WCHAR *stringData, unsigned int *pNeeded);
HRESULT GetUsefulGlobalsImpl(struct DacpUsefulGlobalsData *globalsData);
HRESULT GetMethodDescDataImpl(CLRDATA_ADDRESS methodDesc, CLRDATA_ADDRESS ip, struct DacpMethodDescData *data, ULONG cRevertedRejitVersions, DacpReJitData * rgRevertedRejitData, ULONG * pcNeededRevertedRejitData);

BOOL IsExceptionFromManagedCode(EXCEPTION_RECORD * pExceptionRecord);
#ifndef TARGET_UNIX
Expand Down
65 changes: 64 additions & 1 deletion src/coreclr/debug/daccess/request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1041,6 +1041,70 @@ HRESULT ClrDataAccess::GetMethodDescData(
}

SOSDacEnter();
if (m_cdacSos != NULL)
{
// Try the cDAC first - it will return E_NOTIMPL if it doesn't support this method yet. Fall back to the DAC.
hr = m_cdacSos->GetMethodDescData(methodDesc, ip, methodDescData, cRevertedRejitVersions, rgRevertedRejitData, pcNeededRevertedRejitData);
if (FAILED(hr))
{
hr = GetMethodDescDataImpl(methodDesc, ip, methodDescData, cRevertedRejitVersions, rgRevertedRejitData, pcNeededRevertedRejitData);
}
#ifdef _DEBUG
else
{
// Assert that the data is the same as what we get from the DAC.
DacpMethodDescData mdDataLocal;
NewArrayHolder<DacpReJitData> rgRevertedRejitDataLocal{};
if (rgRevertedRejitData != nullptr)
{
rgRevertedRejitDataLocal = new DacpReJitData[cRevertedRejitVersions];
}
ULONG cNeededRevertedRejitDataLocal = 0;
ULONG *pcNeededRevertedRejitDataLocal = NULL;
if (pcNeededRevertedRejitData != NULL)
{
pcNeededRevertedRejitDataLocal = &cNeededRevertedRejitDataLocal;
}
HRESULT hrLocal = GetMethodDescDataImpl(methodDesc, ip,&mdDataLocal, cRevertedRejitVersions, rgRevertedRejitDataLocal, pcNeededRevertedRejitDataLocal);
_ASSERTE(hr == hrLocal);
_ASSERTE(methodDescData->bHasNativeCode == mdDataLocal.bHasNativeCode);
_ASSERTE(methodDescData->bIsDynamic == mdDataLocal.bIsDynamic);
_ASSERTE(methodDescData->wSlotNumber == mdDataLocal.wSlotNumber);
_ASSERTE(methodDescData->NativeCodeAddr == mdDataLocal.NativeCodeAddr);
_ASSERTE(methodDescData->AddressOfNativeCodeSlot == mdDataLocal.AddressOfNativeCodeSlot);
//TODO[cdac]: assert the rest of mdDataLocal contains the same info as methodDescData
if (rgRevertedRejitData != NULL)
{
_ASSERTE (cNeededRevertedRejitDataLocal == *pcNeededRevertedRejitData);
for (ULONG i = 0; i < cNeededRevertedRejitDataLocal; i++)
{
_ASSERTE(rgRevertedRejitData[i].rejitID == rgRevertedRejitDataLocal[i].rejitID);
_ASSERTE(rgRevertedRejitData[i].NativeCodeAddr == rgRevertedRejitDataLocal[i].NativeCodeAddr);
_ASSERTE(rgRevertedRejitData[i].flags == rgRevertedRejitDataLocal[i].flags);
}
}
}
#endif
}
else
{
hr = GetMethodDescDataImpl(methodDesc, ip, methodDescData, cRevertedRejitVersions, rgRevertedRejitData, pcNeededRevertedRejitData);
}

SOSDacLeave();
return hr;
}

HRESULT ClrDataAccess::GetMethodDescDataImpl(
CLRDATA_ADDRESS methodDesc,
CLRDATA_ADDRESS ip,
struct DacpMethodDescData *methodDescData,
ULONG cRevertedRejitVersions,
DacpReJitData * rgRevertedRejitData,
ULONG * pcNeededRevertedRejitData)
{

HRESULT hr = S_OK;

PTR_MethodDesc pMD = PTR_MethodDesc(TO_TADDR(methodDesc));

Expand Down Expand Up @@ -1236,7 +1300,6 @@ HRESULT ClrDataAccess::GetMethodDescData(
}
}

SOSDacLeave();
return hr;
}

Expand Down
19 changes: 18 additions & 1 deletion src/coreclr/debug/runtimeinfo/datadescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ CDAC_TYPE_FIELD(Module, /*pointer*/, TypeDefToMethodTableMap, cdac_offsets<Modul
CDAC_TYPE_FIELD(Module, /*pointer*/, TypeRefToMethodTableMap, cdac_offsets<Module>::TypeRefToMethodTableMap)
CDAC_TYPE_END(Module)

// Metadata
// RuntimeTypeSystem

CDAC_TYPE_BEGIN(MethodTable)
CDAC_TYPE_INDETERMINATE(MethodTable)
Expand All @@ -223,6 +223,7 @@ CDAC_TYPE_FIELD(EEClass, /*pointer*/, MethodTable, cdac_offsets<EEClass>::Method
CDAC_TYPE_FIELD(EEClass, /*uint16*/, NumMethods, cdac_offsets<EEClass>::NumMethods)
CDAC_TYPE_FIELD(EEClass, /*uint32*/, CorTypeAttr, cdac_offsets<EEClass>::CorTypeAttr)
CDAC_TYPE_FIELD(EEClass, /*uint8*/, InternalCorElementType, cdac_offsets<EEClass>::InternalCorElementType)
CDAC_TYPE_FIELD(EEClass, /*uint16*/, NumNonVirtualSlots, cdac_offsets<EEClass>::NumNonVirtualSlots)
CDAC_TYPE_END(EEClass)

CDAC_TYPE_BEGIN(ArrayClass)
Expand Down Expand Up @@ -263,6 +264,21 @@ CDAC_TYPE_FIELD(DynamicMetadata, /*uint32*/, Size, cdac_offsets<DynamicMetadata>
CDAC_TYPE_FIELD(DynamicMetadata, /*inline byte array*/, Data, cdac_offsets<DynamicMetadata>::Data)
CDAC_TYPE_END(DynamicMetadata)

CDAC_TYPE_BEGIN(MethodDesc)
CDAC_TYPE_INDETERMINATE(MethodDesc)
CDAC_TYPE_FIELD(MethodDesc, /*uint8*/, ChunkIndex, cdac_offsets<MethodDesc>::ChunkIndex)
CDAC_TYPE_FIELD(MethodDesc, /*uint16*/, Slot, cdac_offsets<MethodDesc>::Slot)
CDAC_TYPE_FIELD(MethodDesc, /*uint16*/, Flags, cdac_offsets<MethodDesc>::Flags)
CDAC_TYPE_END(MethodDesc)

CDAC_TYPE_BEGIN(MethodDescChunk)
CDAC_TYPE_SIZE(sizeof(MethodDescChunk))
CDAC_TYPE_FIELD(MethodDescChunk, /*pointer*/, MethodTable, cdac_offsets<MethodDescChunk>::MethodTable)
CDAC_TYPE_FIELD(MethodDescChunk, /*pointer*/, Next, cdac_offsets<MethodDescChunk>::Next)
CDAC_TYPE_FIELD(MethodDescChunk, /*uint8*/, Size, cdac_offsets<MethodDescChunk>::Size)
CDAC_TYPE_FIELD(MethodDescChunk, /*uint8*/, Count, cdac_offsets<MethodDescChunk>::Count)
CDAC_TYPE_END(MethodDescChunk)

CDAC_TYPES_END()

CDAC_GLOBALS_BEGIN()
Expand All @@ -282,6 +298,7 @@ CDAC_GLOBAL(ObjectToMethodTableUnmask, uint8, 1 | 1 << 1 | 1 << 2)
CDAC_GLOBAL(ObjectToMethodTableUnmask, uint8, 1 | 1 << 1)
#endif //TARGET_64BIT
CDAC_GLOBAL(SOSBreakingChangeVersion, uint8, SOS_BREAKING_CHANGE_VERSION)
CDAC_GLOBAL(MethodDescAlignment, uint64, MethodDesc::ALIGNMENT)
CDAC_GLOBAL_POINTER(ExceptionMethodTable, &::g_pExceptionClass)
CDAC_GLOBAL_POINTER(FreeObjectMethodTable, &::g_pFreeObjectMethodTable)
CDAC_GLOBAL_POINTER(ObjectMethodTable, &::g_pObjectClass)
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
#define GUID_DEFINED
#endif // !GUID_DEFINED

constexpr GUID JITEEVersionIdentifier = { /* 273ba350-32bf-4714-beb0-7fa46c11364d */
0x273ba350,
0x32bf,
0x4714,
{0xbe, 0xb0, 0x7f, 0xa4, 0x6c, 0x11, 0x36, 0x4d}
constexpr GUID JITEEVersionIdentifier = { /* 488a17ce-26c9-4ad0-a7b7-79bf320ea4d1 */
0x488a17ce,
0x26c9,
0x4ad0,
{0xa7, 0xb7, 0x79, 0xbf, 0x32, 0x0e, 0xa4, 0xd1}
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
20 changes: 13 additions & 7 deletions src/coreclr/jit/codegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2236,18 +2236,12 @@ void CodeGen::instGen_Set_Reg_To_Imm(emitAttr size,
// reg cannot be a FP register
assert(!genIsValidFloatReg(reg));

emitAttr origAttr = size;
if (!compiler->opts.compReloc)
{
size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs
}

if (compiler->IsTargetAbi(CORINFO_NATIVEAOT_ABI) && EA_IS_CNS_SEC_RELOC(origAttr))
{
// This emits pair of `add` instructions for TLS reloc
GetEmitter()->emitIns_Add_Add_Tls_Reloc(size, reg, imm DEBUGARG(gtFlags));
}
else if (EA_IS_RELOC(size))
if (EA_IS_RELOC(size))
{
// This emits a pair of adrp/add (two instructions) with fix-ups.
GetEmitter()->emitIns_R_AI(INS_adrp, size, reg, imm DEBUGARG(targetHandle) DEBUGARG(gtFlags));
Expand Down Expand Up @@ -2764,6 +2758,18 @@ void CodeGen::genCodeForBinary(GenTreeOp* tree)
genProduceReg(tree);
return;
}
else if (compiler->IsTargetAbi(CORINFO_NATIVEAOT_ABI) && TargetOS::IsWindows &&
op2->IsIconHandle(GTF_ICON_SECREL_OFFSET))
{
// This emits pair of `add` instructions for TLS reloc on windows/arm64/nativeaot
assert(op2->AsIntCon()->ImmedValNeedsReloc(compiler));

emitAttr attr = emitActualTypeSize(targetType);
attr = EA_SET_FLG(attr, EA_CNS_RELOC_FLG | EA_CNS_SEC_RELOC);

emit->emitIns_Add_Add_Tls_Reloc(attr, targetReg, op1->GetRegNum(), op2->AsIntCon()->IconValue());
return;
}

instruction ins = genGetInsForOper(tree->OperGet(), targetType);

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/copyprop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ bool Compiler::optCopyProp(
JITDUMP(" Updating COMMA parent VN [%06u]\n", dspTreeID(parent));
ValueNumPair op1Xvnp = vnStore->VNPExceptionSet(parent->AsOp()->gtOp1->gtVNPair);
parent->SetVNs(vnStore->VNPWithExc(parent->AsOp()->gtOp2->gtVNPair, op1Xvnp));
parent = tree->gtGetParent(nullptr);
parent = parent->gtGetParent(nullptr);
}
}
gtUpdateSideEffects(stmt, tree);
Expand Down
Loading

0 comments on commit ee0a277

Please sign in to comment.