虚方法的CLR实现调用接口成员 [英] CLR implementation of virtual method calls to interface members

查看:161
本文介绍了虚方法的CLR实现调用接口成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出于好奇:?如何在CLR分派虚方法调用接口成员正确实施

我了解的虚函数表在CLR维护每个类型具有每个方法方法时隙,并且每个接口具有指向相关联的接口方法的实施方式的时隙的附加列表中的事实。但我不明白以下内容:?如何在CLR有效地确定从类型的VTable挑哪个接口方法槽列表

I know about the VTable that the CLR maintains for each type with method slots for each method, and the fact that for each interface it has an additional list of method slots that point to the associated interface method implementations. But I don't understand the following: how does the CLR efficiently determine which interface method slot list to pick from the type's VTable?

这篇文章的钻入.NET框架内幕,看看如何CLR创建运行时从有关接口ID索引进程级映射表IVMap的MSDN杂志会谈2005年5月发行对象。 ?这是否意味着,在同一进程的所有类型具有相同的指向同一IVMap

The article Drill Into .NET Framework Internals to See How the CLR Creates Runtime Objects from the May 2005 issue of the MSDN Magazine talks about a process-level mapping table IVMap indexed by interface ID. Does this mean that all types in the same process have the same pointer to the same IVMap?

该法还规定:

如果 MyInterface1 由两个类实现,将有在IVMap表中的两个
项。该条目将指向回嵌入 MyClass的方法表中的子表的开始

If MyInterface1 is implemented by two classes, there will be two entries in the IVMap table. The entry will point back to the beginning of the sub-table embedded within the MyClass method table.

如何在CLR知道挑哪一个条目?它做线性搜索发现,目前的类型相匹配的条目?或二进制搜索?或某种直接的索引,并有可能很多空条目的地图中呢?

How does the CLR know which entry to pick? Does it do a linear search to find the entry that matches the current type? Or a binary search? Or some kind of direct indexing and have a map with possibly many empty entries in it?

我也看到了在CLR通过C#第三版上的接口的一章,但它不谈论这个。因此,答案此另一个问题不回答我的问题。

I've also read the chapter on Interfaces in CLR via C# 3rd edition but it does not talk about this. Therefore, the answers to this other question do not answer my question.

推荐答案

如果你看看图,它是链接网站上,它可能更容易理解。

If you take a look at diagram that was on the linked site, it may make it easier to understand.

这是否意味着,在同一进程的所有类型具有相同的指向同一IVMap?

Does this mean that all types in the same process have the same pointer to the same IVMap?

是的,因为它是在域级别,这意味着一切都在AppDomain中具有相同的IVMap。

Yes, since it is at the domain level, it means everything in that AppDomain has the same IVMap.

如何在CLR知道挑哪一个条目?它做线性搜索发现,目前的类型相匹配的条目?或二进制搜索?或某种直接的索引,并与它可能许多空条目的地图吗?

How does the CLR know which entry to pick? Does it do a linear search to find the entry that matches the current type? Or a binary search? Or some kind of direct indexing and have a map with possibly many empty entries in it?

中的类与偏移摆出来,所以一切都在那里将是一个相对设置的区域。这在寻找方法时,使事情变得更容易。它将查询的IVMap表并找到从接口方法。从那里,这是不言而喻的MethodSlotTable并使用该类的接口的实现。该inteface地图类持有的元数据,然而,实施被视为就像任何其他的方法。

The classes are laid out with offsets, so everything has a relatively set area on where it would be. That makes things easier when looking for methods. It would search the IVMap table and find that method from the interface. From there, it goes to the MethodSlotTable and uses that class' implementation of the interface. The inteface map for the class holds the metadata, however, the implementation is treated just like any other method.

每个接口的实现将有:

再从你链接的网站条目IVMap。如果MyInterface1由两个类实现,会有在IVMap表两个条目。该条目将指向回嵌入MyClass的方法表

Each interface implementation will have an entry in IVMap. If MyInterface1 is implemented by two classes, there will be two entries in the IVMap table. The entry will point back to the beginning of the sub-table embedded within the MyClass method table

这意味着每次一个接口是实现它在IVMap唯一的记录,它指向MethodSlotTable反过来指向执行。因此它知道挑基于呼吁它作为IVMap记录指向MethodSlotTable类中的调用方法的类实现。所以我想这仅仅是通过IVMap线性搜索,找到正确的实例,然后他们关闭和运行。

This means that each time an interface is implemented it has a unique record in the IVMap which points to the MethodSlotTable which in turn points to the implementation. So it knows which implementation to pick based on the class that is calling it as that IVMap record points to the MethodSlotTable in the class calling the method. So I imagine it is just a linear search through the IVMap to find the correct instance and then they are off and running.

编辑:提供有关IVMap更多信息

To provide more info on the IVMap.

再次从OP链接:

到MyInterface1的类型句柄的前4个字节的第一InterfaceInfo入口点(见图9和图10)。下一个字(2字节)是采取了由旗(其中0是由父母继承的,1是当前类实现)。旗之后的词是开始插槽,它使用的类加载器进行布局接口实现的子表。

The first 4 bytes of the first InterfaceInfo entry points to the TypeHandle of MyInterface1 (see Figure 9 and Figure 10). The next WORD (2 bytes) is taken up by Flags (where 0 is inherited from parent, and 1 is implemented in the current class). The WORD right after Flags is Start Slot, which is used by the class loader to lay out the interface implementation sub-table.

所以在这里我们有一个表,其中数字是字节偏移。这是IVMap只是一条记录:

So here we have a table where the number is the offset of bytes. This is just one record in the IVMap:

+----------------------------------+
| 0 - InterfaceInfo                |
+----------------------------------+
| 4 - Parent                       |
+----------------------------------+
| 5 - Current Class                |
+----------------------------------+
| 6 - Start Slot (2 Bytes)         |
+----------------------------------+

假设有这个AppDomain中100接口的记录,我们需要找到每个人的执行情况。我们只是比较第5个字节,看它是否我们目前的类相匹配,如果确实如此,我们跳转到代码中的第6个字节。因为,每一个记录是8个字节长,我们需要做这样的事情:(伪码)

Suppose there are 100 interface records in this AppDomain and we need to find the implementation for each one. We just compare the 5th byte to see if it matches our current class and if it does, we jump to the code in the 6th byte. Since, each record is 8 bytes long, we would need to do something like this: (Psuedocode)

findclass :
   if (!position == class) 
      findclass adjust offset by 8 and try again

虽然它仍然是一个线性搜索,在现实中,它是不会采取这种只要数据的大小被迭代并不大。我希望帮助

While it is still a linear search, in reality, it isn't going to take that long as the size of data being iterated isn't huge. I hope that helps.

EDIT2:

所以经过看着图,不知道为什么会出现在IVMap为图中的类没有插槽1我重新阅读部分,并发现这一点:

So after looking at the diagram and wondering why there is no Slot 1 in the IVMap for the class in the diagram I re-read the section and found this:

IVMap基于嵌入式方法表中的接口映射信息创建的。接口地图是基于类的在方法表布局过程中的元数据创建的。一旦typeloading完成后,只有IVMap在方法调度使用。

IVMap is created based on the Interface Map information embedded within the method table. Interface Map is created based on the metadata of the class during the MethodTable layout process. Once typeloading is complete, only IVMap is used in method dispatching.

因此​​,对于一类IVMap只装有接口的具体的类继承。它看起来像从域IVMap它复制,但只保留那些指向的接口。这带来了另一个问题,怎么样?没准它是C ++如何做虚函数表,其中每个条目都有一个偏移量和接口Map提供的偏移量的列表中IVMap包括相当。

So the IVMap for a class is only loaded with the interfaces that the specific class inherits. It looks like it copies from the Domain IVMap but only keeps the interfaces that are pointed to. This brings up another question, how? Chances are it is the equivalent of how C++ does vtables where each entry has an offset and the Interface Map provides a list of the offsets to include in the IVMap.

如果我们看一下IVMap这可能是这整个域:

If we look at the IVMap that could be for this entire domain:

+-------------------------+
| Slot 1 - YourInterface  |
+-------------------------+
| Slot 2 - MyInterface    |
+-------------------------+
| Slot 3 - MyInterface2   |
+-------------------------+
| Slot 4 - YourInterface2 |
+-------------------------+

假设有在这一领域只有4个接口映射的实现。每个时隙将一个偏移(类似于IVMap记录我先前公布)和IVMap此类会使用这些偏移来访问IVMap记录

Assume there are only 4 implementations of Interface Map in this domain. Each slot would have an offset (similar to the IVMap record I posted earlier) and the IVMap for this class would use those offsets to access the record in the IVMap.

假设每个插槽是8个字节插槽1从0开始,所以如果我们想获得插槽2和3,我们会做这样的事情:

Assume each slot is 8 bytes with slot 1 starting at 0 so if we wanted to get slot 2 and 3 we would do something like this:

mov ecx,edi
mov eax, dword ptr [ecx]
mov eax, dword ptr [ecx+08h] ; slot 2
; do stuff with slot 2
mov eax, dword ptr [ecx+10h] ; slot 3
; do stuff with slot 3

请原谅我的x86架构我没那么熟悉,但我试过复制他们有什么被链接到文章。

Please excuse my x86 as I'm not that familiar with it but I tried to copy what they have in the article that was linked to.

这篇关于虚方法的CLR实现调用接口成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆