You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
To map an FCall entrypoint back to a MethodDesc, we read the global `FCallMethods` hash table. This is a array of pointers to `ECHash` objects. The length of this array is defined by the global `FCallHashSize` and it uses a simple hash function: `<hash> = codePointer % FCallHashSize`. To find the correct `ECHash` chain, simply take the `<hash>` offset into the `FCallMethods` array.
35
+
36
+
Once we find the `ECHash` chain, we iterate the chain until we find an `ECHash` where the `Implementation` field matches the `codePointer`. If found, return the `MethodDesc` field.
37
+
38
+
If no `ECHash` matches return `TargetPointer.Null` to indicate a MethodDesc was not found.
### DacEnumerableHash (EETypeHashTable and InstMethodHashTable)
465
+
466
+
Both `EETypeHashTable` and `InstMethodHashTable` are based on the templated `DacEnumerableHash`. Because the base class is templated on the derived type, offsets may be different in derived types.
467
+
468
+
The base implementation of `DacEnumerableHash` uses four datadescriptors:
469
+
| Datadescriptor | Purpose |
470
+
| --- | --- |
471
+
|`Buckets`| Pointer to the bucket array |
472
+
|`Count`| Number of elements in the hash table |
473
+
|`VolatileEntryValue`| The data held by an entry, defined by the derived class |
474
+
|`VolatileEntryNextEntry`| The next pointer on an hash table entry |
475
+
476
+
The hash table is laid out as an array of `VolatileEntry` pointers's (buckets), each possibly forming a chain for values that hash into that bucket. The first three buckets are special and reserved for special metadata. Instead of containing a `VolatileEntry`, these pointers are read as values with the following meanings.
477
+
478
+
| Reserved Bucket offset | Purpose |
479
+
| --- | --- |
480
+
|`0`| Length of the Bucket array, this value does not include the first 3 slots which are special |
481
+
|`1`| Pointer to the next bucket array, not currently used in the cDAC |
482
+
|`2`| End sentinel for the current bucket array, not currently used in the cDAC |
483
+
484
+
To read all entries in the hash table:
485
+
1. Read the length bucket to find the number of chains `n`.
486
+
2. Initialize a list of elements `entries = []`.
487
+
3. For each chain, (buckets with offsets `3..n + 3`):
488
+
1. Read the pointer in the bucket as `volatileEntryPtr`.
489
+
2. If `volatileEntryPtr & 0x1 == 0x1`, this is the end sentinel and we stop reading this chain.
490
+
3. Otherwise, add `volatileEntryPtr + /* VolatileEntryValue offset */` to entries. This points to the derived class defined data type.
491
+
4. Set `volatileEntryPtr` to the value of the pointer located at `volatileEntryPtr + /* VolatileEntryNextEntry offset */` and go to step 3.2.
492
+
4. Return `entries` to be further parsed by derived classes.
493
+
494
+
For both EETypeHashTable and InstMethodHashTable, the data type stored on the `VolatileEntry` are simply pointers with a couple of bits used as flags.
495
+
496
+
EETypeHashTable uses the LSB to indicate if the TypeHandle is a hot entry. Therefore this bit is stripped before values are returned.
497
+
498
+
InstMethodHashTable uses the 2 most LSBs as flags for the MethodDesc. These must be taken into account before reading values from them.
// The component size is only available for strings and arrays. It is the size of the element type of the array, or the size of an ECMA 335 character (2 bytes)
0 commit comments