为什么类型参数中的基本接口导致产生的单态函数使用Runtime.asserti2i()?
多态函数(完整代码请参见在此处):
type Intf interface{
Do()
}
type Intf2 interface {
Intf
Do2()
}
func CallIntf[T Intf](intf T) {
intf.Do()
}
手动单体词:
func CallIntf_mono(intf Intf) {
intf.Do()
}
实例:实例:
var intf2 Intf2
intf2 = &impl{}
CallIntf[Intf](intf2)
实例: Code> Runtime.Asserti2i()):
LEAQ type."".impl(SB), AX
CALL runtime.newobject(SB)
MOVQ AX, ""..autotmp_13+24(SP)
LEAQ go.itab.*"".impl,"".Intf2(SB), BX
LEAQ type."".Intf(SB), AX
CALL runtime.convI2I(SB)
MOVQ AX, BX
MOVQ ""..autotmp_13+24(SP), CX
LEAQ ""..dict.CallIntf["".Intf](SB), AX
CALL "".CallIntf[go.shape.interface { Do() }_0](SB)
生成的单态函数ASM(包含调用Runtime Time.asserti2i()
):
TEXT "".CallIntf[go.shape.interface { Do() }_0](SB), DUPOK|ABIInternal, $32-24
MOVQ CX, "".intf+56(SP)
LEAQ type."".Intf(SB), AX
CALL runtime.assertI2I(SB)
MOVQ 24(AX), CX
MOVQ "".intf+56(SP), AX
CALL CX
MOVQ 24(SP), BP
ADDQ $32, SP
RET
手动单型ASM(不调用runtime.asserti.asserti.asserti2i(( )
):
TEXT "".CallIntf_mono(SB), ABIInternal, $16-16
MOVQ AX, "".intf+24(FP)
MOVQ BX, "".intf+32(FP)
MOVQ 24(AX), CX
MOVQ BX, AX
CALL CX
MOVQ 8(SP), BP
ADDQ $16, SP
RET
问题:为什么生成的单态函数的组装使用runtime.asserti2i()
,而手动单态函数之一则没有?在这种情况下,呼叫者将使用需要断言的类型?
Polymorphic function (full code see here):
type Intf interface{
Do()
}
type Intf2 interface {
Intf
Do2()
}
func CallIntf[T Intf](intf T) {
intf.Do()
}
Manual monomorph:
func CallIntf_mono(intf Intf) {
intf.Do()
}
Instantiation:
var intf2 Intf2
intf2 = &impl{}
CallIntf[Intf](intf2)
Instantiation asm (contains a call to runtime.assertI2I()
):
LEAQ type."".impl(SB), AX
CALL runtime.newobject(SB)
MOVQ AX, ""..autotmp_13+24(SP)
LEAQ go.itab.*"".impl,"".Intf2(SB), BX
LEAQ type."".Intf(SB), AX
CALL runtime.convI2I(SB)
MOVQ AX, BX
MOVQ ""..autotmp_13+24(SP), CX
LEAQ ""..dict.CallIntf["".Intf](SB), AX
CALL "".CallIntf[go.shape.interface { Do() }_0](SB)
Generated monomorphic function asm (contains a call to runtime.assertI2I()
):
TEXT "".CallIntf[go.shape.interface { Do() }_0](SB), DUPOK|ABIInternal, $32-24
MOVQ CX, "".intf+56(SP)
LEAQ type."".Intf(SB), AX
CALL runtime.assertI2I(SB)
MOVQ 24(AX), CX
MOVQ "".intf+56(SP), AX
CALL CX
MOVQ 24(SP), BP
ADDQ $32, SP
RET
Manual monomorph asm (does not call runtime.assertI2I()
):
TEXT "".CallIntf_mono(SB), ABIInternal, $16-16
MOVQ AX, "".intf+24(FP)
MOVQ BX, "".intf+32(FP)
MOVQ 24(AX), CX
MOVQ BX, AX
CALL CX
MOVQ 8(SP), BP
ADDQ $16, SP
RET
Question: Why does the assembly of the generated monomorphic function use runtime.assertI2I()
, while the one of the manual monomorphic function does not? In which case caller would use a type which needs to be asserted?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我无法在其他地方得到确认,所以我只是要在这里发布直觉。
您可能看到的可能是由于当前的GO Generics实施,该实施基于 gc固定。 GC代表垃圾收集器。
执行摘要是:
GCSHAPE是一组与垃圾收集器“看起来相同”的类型。更正式地,具有相同类型或指针的类型。
标识符
go.shape.interface {do()} _0
在您的ASM中看到的是intf
接口的gcshape,用作类型参数约束,其中> GO.Shape
是一个内置软件包,接口{do()}
是intf
的基础类型。基于我的理解,以上意味着通用函数并不是实例化后真正单体化。因此,pseudo-register
sb
最终具有接口的GCSHAPE,而不是接口本身。因此,runtime.asserti2i(sb)
用于确保两个接口兼容。无论如何,这都是所有实施详细信息。 ASM可能会随着未来的GO发布,甚至可以发行。在撰写本文时,该断言仍然存在于GO 1.18.3编译的代码中。
I couldn't get confirmation elsewhere, so I'm just going to post my intuition here.
What you see is likely due to the current implementation of Go generics, which is based on GC Stenciling. GC stands for Garbage Collector.
The executive summary is:
A gcshape is a group of types that "look the same" to the garbage collector. More formally, types that have the same underlying type, or pointers.
The identifier
go.shape.interface { Do() }_0
seen in your ASM is the gcshape of theIntf
interface, used as a type parameter constraint, wherego.shape
is a builtin package andinterface { Do() }
is the underlying type ofIntf
.Based on my understanding, the above implies that generic functions aren't truly monomorphized upon instantiation. So the pseudo-register
SB
ends up having the gcshape of the interface, not the interface itself. For this reason,runtime.assertI2I(SB)
is used to ensure that the two interfaces are compatible.Anyway this is all implementation details. The ASM may change with future Go releases, and even point releases. At the time of writing, the assertion is still present in Go 1.18.3 compiled code.