|
|
От: |
Serginio1
|
https://habrahabr.ru/users/serginio1/topics/ |
| Дата: | 14.09.21 12:32 | ||
| Оценка: | |||
V>class Object {
V> private RuntimeType _type;
V> public Type GetType() => _type;
V> public virtual void ToString() = _type.ToString();
V> ...
V>}
V>unsafe class RuntimeType {
V> ...
V> // по смещению 0x40 в AMDx64 ссылка на VMT (или TypeDesc)
V> private IntPtr* _vmt;
V> ...
V>}
V>V>IntPtr * funcAddr = obj->_type->_vmt[4];
V>V>IntPtr * funcAddr = obj->_vmt[4];
V>// A TypeHandle is the FUNDAMENTAL concept of type identity in the CLR.
// That is two types are equal if and only if their type handles
// are equal. A TypeHandle, is a pointer sized struture that encodes
// everything you need to know to figure out what kind of type you are
// actually dealing with.
// At the present time a TypeHandle can point at two possible things
//
// 1) A MethodTable (Intrinsics, Classes, Value Types and their instantiations)
// 2) A TypeDesc (all other cases: arrays, byrefs, pointer types, function pointers, generic type variables)
//
// or with IL stubs, a third thing:
//
// 3) A MethodTable for a native value type.
//
// MTs that satisfy IsSharedByReferenceArrayTypes are not
// valid TypeHandles: for example no allocated object will
// ever return such a type handle from Object::GetTypeHandle(), and
// these type handles should not be passed across the JIT Interface
// as CORINFO_CLASS_HANDLEs. However some code in the EE does create
// temporary TypeHandles out of these MTs, so we can't yet assert
// !IsSharedByReferenceArrayTypes() in the TypeHandle constructor.
Ага, значит TypeHandle может быть как указателем на MethodTable, так и указателем на TypeDesc, в зависимости от типа объекта. Для массивов он указывает на TypeDesc. Тип object[][] — это массив, элементами которого являются object[], для которых TypeHandle=TypeDesc. Эта информация объясняет наш пример, но всё ещё остаются некоторые вопросы. Например: а как же отличить, на что именно указывает TypeHandle? Поможет нам в этом дальнейшее изучение исходников CLI:
Всё зависит от второго бита в адресе: нулевое значение определяет MethodTable, а единичное — TypeDesc. Если мы работаем с шестнадцатеричными адресами, то можно легко определить вид TypeHandle по последней цифре: