go cmd/compile:在接口的切片字面量中重用装箱基本类型 ```markdown cmd/compile: 在接口的切片字面量中重用装箱基本类型 ```

ubby3x7f  于 5个月前  发布在  Go
关注(0)|答案(5)|浏览(49)

使用 go1.12
考虑以下代码片段:

func main() {
	lit := []interface{}{
		0, 0, 0, 0, 0,
	}
	type ifaceHeader struct{ Type, Data unsafe.Pointer }
	for i := range lit {
		fmt.Printf("%+v\n", *(*ifaceHeader)(unsafe.Pointer(&lit[i])))
	}
}

这将输出:

{Type:0x4962e0 Data:0x4c95c0}
{Type:0x4962e0 Data:0x4c95c8}
{Type:0x4962e0 Data:0x4c95d0}
{Type:0x4962e0 Data:0x4c95d8}
{Type:0x4962e0 Data:0x4c95e0}

这表明每个带框的整数都有自己的堆分配元素(因为每个元素的数据指针都不同)。似乎编译器应该能够重用相同值的带框元素。
此外,我希望这种方法适用于具有相同底层类型的不同类型。因此,我还希望:

type EnumC int32
type EnumB int32
type EnumC int32
lit := []interface{EnumA(0), EnumB(0), EnumC(0)}

共享相同的带框元素,因为这三个类型都是 int32 类型。
\cc @randall77

7gyucuyw

7gyucuyw1#

每个接口数据项的后备存储目前是其自身的静态临时变量。由于我们不写入这些静态临时变量,所以共享它们是可以的。为了实现这一点,我们需要使用它们的内容来命名它们,以便链接器可以将它们合并。这应该不难;我认为我们已经为字符串的后备存储这样做了。

顺便说一下,对于这个特定情况,我们可以使用零值(runtime.zeroVal)来代替。

sqougxex

sqougxex2#

这表明每个整数都在自己的堆分配元素中。顺便说一下,这些不是堆分配的元素,而是静态分配的元素(在数据段中)。

ix0qys7i

ix0qys7i3#

另一个观察。这里是一段汇编代码:

0x004e 00078 (x.go:10)	LEAQ	type.int(SB), AX
	0x0055 00085 (x.go:10)	MOVQ	AX, ""..autotmp_12+104(SP)
	0x005a 00090 (x.go:10)	PCDATA	$2, $3
	0x005a 00090 (x.go:10)	LEAQ	"".statictmp_0(SB), CX
	0x0061 00097 (x.go:10)	PCDATA	$2, $2
	0x0061 00097 (x.go:10)	MOVQ	CX, ""..autotmp_12+112(SP)
	0x0066 00102 (x.go:10)	MOVQ	AX, ""..autotmp_12+120(SP)
	0x006b 00107 (x.go:10)	PCDATA	$2, $3
	0x006b 00107 (x.go:10)	LEAQ	"".statictmp_1(SB), CX
	0x0072 00114 (x.go:10)	PCDATA	$2, $2
	0x0072 00114 (x.go:10)	MOVQ	CX, ""..autotmp_12+128(SP)
	0x007a 00122 (x.go:10)	MOVQ	AX, ""..autotmp_12+136(SP)
	0x0082 00130 (x.go:10)	PCDATA	$2, $3
	0x0082 00130 (x.go:10)	LEAQ	"".statictmp_2(SB), CX

我们正在耐心地填写 lit ,一次填写一个字。
对于某些大小和类型的 lit ,我们可以改为布局整个数据结构(多次复制类型字),然后执行 DUFFCOPY 或类似操作将其复制到堆栈中。它编译速度更快,执行速度可能更快,二进制文件大小也许更小。

nnvyjq4y

nnvyjq4y4#

Ah,@randall77 在 #29573 (评论)中提出了同样的建议。
相关链接:#21561 , #19818
由于我们不写入这些静态临时变量,所以共享它们是可以的。
顺便说一下,我在 https://go-review.googlesource.com/c/go/+/42170/ 中尝试了这个方法,但遇到了问题。所以如果有人想解决这个问题,这是一个起点。

bkhjykvo

bkhjykvo5#

作为附注,我们可以在这个特定的情况下使用零值(runtime.zeroVal)。这是 #23948 。我们不断发现这一整套问题和可能的解决方案。我们只是没有解决它们。:P

相关问题