4. map
map变量只有8个字节,指向map对象自己。
var var_map map[int64]int64 = map[int64]int64{0x1234:0x1234};
1878 "".var_map SBSS size=8
var var2_map map[int64]int64 = map[int64]int64{0x1234:0x1234};
1、调用运行时runtime.makemap_small()创建一个hmap
结构体。
// makehmap_small implements Go map creation for make(map[k]v) and
// make(map[k]v, hint) when hint is known to be at most bucketCnt
// at compile time and the map needs to be allocated on the heap.
func makemap_small() *hmap {
h := new(hmap)
h.hash0 = fastrand()
return h
}
// A header for a Go map.
type hmap struct {
// Note: the format of the hmap is also encoded in cmd/compile/internal/gc/reflect.go.
// Make sure this stays in sync with the compiler's definition.
count int // # live cells == size of map. Must be first (used by len() builtin)
flags uint8
B uint8 // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details
hash0 uint32 // hash seed
buckets unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
nevacuate uintptr // progress counter for evacuation (buckets less than this have been evacuated)
extra *mapextra // optional fields
}
2、mapassign_fast64获取key对应值位置
func mapassign_fast64(t *maptype, h *hmap, key uint64) unsafe.Pointer {
src\runtime\type.go
type _type struct {
size uintptr //8 字节
ptrdata uintptr //8 字节 size of memory prefix holding all pointers
hash uint32 //4 字节
tflag tflag //1 字节
align uint8 //1 字节 0x08 8字节对象
fieldalign uint8 //1 字节 0x08 8字节对象
kind uint8 //1 字节 0x14=20=RUNTIME_TYPE_KIND_INTERFACE
alg *typeAlg //8 字节
// gcdata stores the GC type data for the garbage collector.
// If the KindGCProg bit is set in kind, gcdata is a GC program.
// Otherwise it is a ptrmask bitmap. See mbitmap.go for details.
gcdata *byte //8
str nameOff //4
ptrToThis typeOff //4
}
type maptype struct { //80字节
typ _type //48字节
key *_type //8字节
elem *_type //8字节
bucket *_type // 8字节 internal type representing a hash bucket
keysize uint8 // 1字节 size of key slot
valuesize uint8 // 1字节 size of value slot
bucketsize uint16 // 2字节 size of bucket
flags uint32 // 4字节
}
map底层类型信息 maptype
可以看出有80个字节
type.map[int64]int64 SRODATA dupok size=80
2247 type..namedata.*map[int64]int64- SRODATA dupok size=19
2248 0x0000 00 00 10 2a 6d 61 70 5b 69 6e 74 36 34 5d 69 6e ...*map[int64]in
2249 0x0010 74 36 34 t64
2250 type.*map[int64]int64 SRODATA dupok size=56
2251 0x0000 08 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 ................
2252 0x0010 d1 14 ff d7 00 08 08 36 00 00 00 00 00 00 00 00 .......6........
2253 0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
2254 0x0030 00 00 00 00 00 00 00 00 ........
2255 rel 24+8 t=1 runtime.algarray+80
2256 rel 32+8 t=1 runtime.gcbits.01+0
2257 rel 40+4 t=5 type..namedata.*map[int64]int64-+0
2258 rel 48+8 t=1 type.map[int64]int64+0
2259 type.map[int64]int64 SRODATA dupok size=80
2260 0x0000 08 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 ................
2261 0x0010 9c 10 d3 02 02 08 08 35 00 00 00 00 00 00 00 00 .......5........
2262 0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
2263 0x0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
2264 0x0040 00 00 00 00 00 00 00 00 08 08 90 00 04 00 00 00 ................
2265 rel 24+8 t=1 runtime.algarray+0
2266 rel 32+8 t=1 runtime.gcbits.01+0
2267 rel 40+4 t=5 type..namedata.*map[int64]int64-+0
2268 rel 44+4 t=6 type.*map[int64]int64+0
2269 rel 48+8 t=1 type.int64+0
2270 rel 56+8 t=1 type.int64+0
2271 rel 64+8 t=1 type.noalg.map.bucket[int64]int64+0
3、赋值
39 0x0040 00064 (type.go:41) CALL runtime.makemap_small(SB) //创建hmap对象
40 0x0045 00069 (type.go:41) PCDATA $2, $1
41 0x0045 00069 (type.go:41) MOVQ (SP), AX //将hmap对象地址赋值给AX
42 0x0049 00073 (type.go:41) PCDATA $2, $0
43 0x0049 00073 (type.go:41) PCDATA $0, $1
44 0x0049 00073 (type.go:41) MOVQ AX, "".var2_map+136(SP) //将hmap对象地址赋值给var2_map
45 0x0051 00081 (type.go:41) MOVQ $4660, ""..autotmp_27+104(SP) //临时变量赋值为0x1234
46 0x005a 00090 (type.go:41) MOVQ $4660, ""..autotmp_28+96(SP) //临时变量赋值为0x1234
47 0x0063 00099 (type.go:41) PCDATA $2, $1
48 0x0063 00099 (type.go:41) LEAQ type.map[int64]int64(SB), AX //将map[int64]int64类型地址赋值给AX
49 0x006a 00106 (type.go:41) PCDATA $2, $0
50 0x006a 00106 (type.go:41) MOVQ AX, (SP) //将map类型信息压入栈
51 0x006e 00110 (type.go:41) PCDATA $2, $1
52 0x006e 00110 (type.go:41) MOVQ "".var2_map+136(SP), AX
53 0x0076 00118 (type.go:41) PCDATA $2, $0
54 0x0076 00118 (type.go:41) MOVQ AX, 8(SP) //将map变量地址压入栈
55 0x007b 00123 (type.go:41) MOVQ ""..autotmp_27+104(SP), AX
56 0x0080 00128 (type.go:41) MOVQ AX, 16(SP) //将临时变量压入栈
57 0x0085 00133 (type.go:41) CALL runtime.mapassign_fast64(SB) //获取key对应的值地址
58 0x008a 00138 (type.go:41) PCDATA $2, $1
59 0x008a 00138 (type.go:41) MOVQ 24(SP), AX
60 0x008f 00143 (type.go:41) MOVQ AX, ""..autotmp_29+184(SP) //返回值赋值给临时变量
61 0x0097 00151 (type.go:41) TESTB AL, (AX)
62 0x0099 00153 (type.go:41) MOVQ ""..autotmp_28+96(SP), CX //将0x1234放到寄存器CX
63 0x009e 00158 (type.go:41) PCDATA $2, $0
64 0x009e 00158 (type.go:41) MOVQ CX, (AX) //将值0x1234赋值给key对应的val指向地址