maptype questions

101 views
Skip to first unread message

Bill Morgan

unread,
Jun 29, 2020, 8:31:52 PM6/29/20
to golang-nuts
for this code:

m := make(map[int]int, 9)

I think the compiler creates a maptype that is stored at type.*+60480(SB) that it uses for the call to runtime.makemap:

m := make(map[int]int, 9)
  0x10d0b81 488d05f8ec0000 LEAQ type.*+60480(SB), AX
  0x10d0b88 48890424 MOVQ AX, 0(SP)
  0x10d0b8c 48c744240809000000 MOVQ $0x9, 0x8(SP)
  0x10d0b95 48c744241000000000 MOVQ $0x0, 0x10(SP)
  0x10d0b9e 6690 NOPW
  0x10d0ba0 e8fbdff3ff CALL runtime.makemap(SB)

Where is the code in the compiler that creates the maptype? I'm wondering how the bucket size is computed and how the rest of the maptype structure is filled out.

Is there a way to print out the type info stored in the binary?

Ian Lance Taylor

unread,
Jun 29, 2020, 9:16:14 PM6/29/20
to Bill Morgan, golang-nuts
https://golang.org/src/cmd/compile/internal/gc/reflect.go#L189

> Is there a way to print out the type info stored in the binary?

I'm not sure if this is what you want, but you can use reflect.TypeOf:
https://play.golang.org/p/FEUIoqc6SMU .

Ian

arthurwil...@gmail.com

unread,
Jun 29, 2020, 9:33:19 PM6/29/20
to golang-nuts
Thanks Ian, that is pretty cool. I think that is printing out the map[int]int type though instead of the *maptype that is generated by the compiler and passed to runtime.makemap. 

I think this is loading a pointer to a maptype into AX to pass as the first arg to runtime.makemap. The maptype seems to be stored at type.*+60480(SB). 

LEAQ type.*+60480(SB), AX 

here's the type I'm asking about: where is this guy created in the compiler? 

type maptype struct {
typ _type
key *_type
elem *_type
bucket *_type // internal type representing a hash bucket
// function for hashing keys (ptr to key, seed) -> hash
hasher func(unsafe.Pointer, uintptr) uintptr
keysize uint8 // size of key slot
elemsize uint8 // size of elem slot
bucketsize uint16 // size of bucket
flags uint32
}

Here are the runtime.makemap comments and signature

// makemap implements Go map creation for make(map[k]v, hint).
// If the compiler has determined that the map or the first bucket
// can be created on the stack, h and/or bucket may be non-nil.
// If h != nil, the map can be created directly in h.
// If h.buckets != nil, bucket pointed to can be used as the first bucket.
func makemap(t *maptype, hint int, h *hmap) *hmap {

Ian Lance Taylor

unread,
Jun 29, 2020, 11:41:15 PM6/29/20
to arthurwil...@gmail.com, golang-nuts

arthurwil...@gmail.com

unread,
Jul 2, 2020, 8:33:48 PM7/2/20
to golang-nuts
Where is the maptype.bucket.size computed? 

It is used here in makemap (t.bucket.size):


I'm assuming the bucket is created here in bmap but I couldn't figure out how the bucket.size is computed and set:


 

Ian Lance Taylor

unread,
Jul 2, 2020, 9:07:08 PM7/2/20
to arthurwil...@gmail.com, golang-nuts
On Thu, Jul 2, 2020 at 5:34 PM arthurwil...@gmail.com
The bucket type is an ordinary struct, and the runtime code is looking
at the size field of the bucket struct's type descriptor. That is the
value returned by bmap in cmd/compile/internal/gc/reflect.go. The
size field is set by the call to dowidth(bucket), which the size as is
done for any struct type.

Ian
Reply all
Reply to author
Forward
0 new messages