3-数据类型内存结构-map

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指向地址
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • map 的底层如何实现 首先声明我用的 Go 版本:go version go1.9.2 darwin/amd64...
    CCCCCCMake阅读 4,308评论 0 1
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 13,805评论 1 32
  • pyspark.sql模块 模块上下文 Spark SQL和DataFrames的重要类: pyspark.sql...
    mpro阅读 13,150评论 0 13
  • 几乎每天早上醒来的第一件事就是搜索你的消息。我也不知道什么时候才到头。
    往前走啊不回头阅读 2,578评论 0 0
  • 给我们讲保险的老师,是一个中等身材的女老师。也负责考研指导。她讲话很快,一节课都在讲,几乎不停顿。但是讲的很简单。...
    温柔的小仙女阅读 2,854评论 0 0