diff options
-rw-r--r-- | erts/emulator/beam/bif.tab | 2 | ||||
-rw-r--r-- | erts/emulator/beam/erl_hashmap.c | 135 | ||||
-rw-r--r-- | erts/emulator/beam/erl_map.c | 133 |
3 files changed, 134 insertions, 136 deletions
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab index e9c5e83203..f9127ef955 100644 --- a/erts/emulator/beam/bif.tab +++ b/erts/emulator/beam/bif.tab @@ -613,9 +613,9 @@ bif erlang:fun_info_mfa/1 # bif erlang:get_keys/0 +bif erts_debug:map_info/1 # Hash Array Mappped Trie -bif hashmap:info/1 bif hashmap:merge/2 # diff --git a/erts/emulator/beam/erl_hashmap.c b/erts/emulator/beam/erl_hashmap.c index 29a14a9f20..fecdc2ef31 100644 --- a/erts/emulator/beam/erl_hashmap.c +++ b/erts/emulator/beam/erl_hashmap.c @@ -45,10 +45,6 @@ #include "erl_map.h" #include "erl_hashmap.h" -#ifndef DECL_AM -#define DECL_AM(S) Eterm AM_ ## S = am_atom_put(#S, sizeof(#S) - 1) -#endif - #if 0 static char *format_binary(Uint64 x, char *b) { int z; @@ -62,7 +58,6 @@ static char *format_binary(Uint64 x, char *b) { static Eterm hashmap_merge(Process *p, Eterm nodeA, Eterm nodeB); -static Eterm hashmap_bld_tuple_uint(Uint **hpp, Uint *szp, Uint n, Uint nums[]); /* hashmap:new/0 */ @@ -100,10 +95,6 @@ BIF_RETTYPE hashmap_merge_2(BIF_ALIST_2) { /* impl. */ -/* n must be > 1 - * hash values in hxns has to be unique - */ - #define HALLOC_EXTRA 200 static Eterm hashmap_merge(Process *p, Eterm nodeA, Eterm nodeB) { @@ -354,129 +345,3 @@ int hashmap_key_hash_cmp(Eterm* ap, Eterm* bp) } /* hashmap:info/0 */ - -static Eterm hashmap_info(Process *p, Eterm node) { - Eterm *hp; - Eterm res = NIL, info = NIL; - Eterm *ptr, tup, hdr; - Uint sz; - DECL_AM(depth); - DECL_AM(leafs); - DECL_AM(bitmaps); - DECL_AM(arrays); - Uint nleaf=0, nbitmap=0, narray=0; - Uint bitmap_usage[16], leaf_usage[16]; - Uint lvl = 0, clvl; - DECLARE_ESTACK(stack); - - for (sz = 0; sz < 16; sz++) { - bitmap_usage[sz] = 0; - leaf_usage[sz] = 0; - } - - ptr = boxed_val(node); - ESTACK_PUSH(stack, 0); - ESTACK_PUSH(stack, node); - do { - node = ESTACK_POP(stack); - clvl = ESTACK_POP(stack); - lvl = MAX(lvl,clvl); - switch(primary_tag(node)) { - case TAG_PRIMARY_LIST: - nleaf++; - leaf_usage[clvl] += 1; - break; - case TAG_PRIMARY_BOXED: - ptr = boxed_val(node); - hdr = *ptr; - ASSERT(is_header(hdr)); - switch(hdr & _HEADER_MAP_SUBTAG_MASK) { - case HAMT_SUBTAG_NODE_ARRAY: - narray++; - sz = 16; - while(sz--) { - ESTACK_PUSH(stack, clvl + 1); - ESTACK_PUSH(stack, ptr[sz+1]); - } - break; - case HAMT_SUBTAG_NODE_BITMAP: - nbitmap++; - sz = hashmap_bitcount(MAP_HEADER_VAL(hdr)); - ASSERT(sz < 17); - bitmap_usage[sz-1] += 1; - while(sz--) { - ESTACK_PUSH(stack, clvl + 1); - ESTACK_PUSH(stack, ptr[sz+1]); - } - break; - case HAMT_SUBTAG_HEAD_BITMAP: - nbitmap++; - sz = hashmap_bitcount(MAP_HEADER_VAL(hdr)); - bitmap_usage[sz-1] += 1; - while(sz--) { - ESTACK_PUSH(stack, clvl + 1); - ESTACK_PUSH(stack, ptr[sz+2]); - } - break; - case HAMT_SUBTAG_HEAD_ARRAY: - narray++; - sz = 16; - while(sz--) { - ESTACK_PUSH(stack, clvl + 1); - ESTACK_PUSH(stack, ptr[sz+2]); - } - break; - default: - erl_exit(1, "bad header\r\n"); - break; - } - } - } while(!ESTACK_ISEMPTY(stack)); - - - /* size */ - sz = 0; - hashmap_bld_tuple_uint(NULL,&sz,16,leaf_usage); - hashmap_bld_tuple_uint(NULL,&sz,16,bitmap_usage); - - /* alloc */ - hp = HAlloc(p, 2+3 + 3*(2+4) + sz); - - info = hashmap_bld_tuple_uint(&hp,NULL,16,leaf_usage); - tup = TUPLE3(hp, AM_leafs, make_small(nleaf),info); hp += 4; - res = CONS(hp, tup, res); hp += 2; - - info = hashmap_bld_tuple_uint(&hp,NULL,16,bitmap_usage); - tup = TUPLE3(hp, AM_bitmaps, make_small(nbitmap), info); hp += 4; - res = CONS(hp, tup, res); hp += 2; - - tup = TUPLE3(hp, AM_arrays, make_small(narray),NIL); hp += 4; - res = CONS(hp, tup, res); hp += 2; - - tup = TUPLE2(hp, AM_depth, make_small(lvl)); hp += 3; - res = CONS(hp, tup, res); hp += 2; - - DESTROY_ESTACK(stack); - ERTS_HOLE_CHECK(p); - return res; -} - -static Eterm hashmap_bld_tuple_uint(Uint **hpp, Uint *szp, Uint n, Uint nums[]) { - Eterm res = THE_NON_VALUE; - Eterm *ts = (Eterm *)erts_alloc(ERTS_ALC_T_TMP, n * sizeof(Eterm)); - Uint i; - - for (i = 0; i < n; i++) { - ts[i] = erts_bld_uint(hpp, szp, nums[i]); - } - res = erts_bld_tuplev(hpp, szp, n, ts); - erts_free(ERTS_ALC_T_TMP, (void *) ts); - return res; -} - -BIF_RETTYPE hashmap_info_1(BIF_ALIST_1) { - if (is_hashmap(BIF_ARG_1)) { - BIF_RET(hashmap_info(BIF_P,BIF_ARG_1)); - } - BIF_ERROR(BIF_P, BADARG); -} diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c index 7281353af5..14f16e9050 100644 --- a/erts/emulator/beam/erl_map.c +++ b/erts/emulator/beam/erl_map.c @@ -63,6 +63,10 @@ * - erts_internal:map_to_tuple_keys/1 */ +#ifndef DECL_AM +#define DECL_AM(S) Eterm AM_ ## S = am_atom_put(#S, sizeof(#S) - 1) +#endif + /* for hashmap_from_list/1 */ typedef struct { Uint32 hx; @@ -82,6 +86,8 @@ static Eterm hashmap_from_validated_list(Process *p, Eterm list, Uint size); static Eterm hashmap_from_unsorted_array(Process *p, hxnode_t *hxns, Uint n); static Eterm hashmap_from_sorted_unique_array(Process *p, hxnode_t *hxns, Uint n, int is_root); static Eterm hashmap_from_chunked_array(Process *p, hxnode_t *hxns, Uint n, int is_root); +static Eterm hashmap_info(Process *p, Eterm node); +static Eterm hashmap_bld_tuple_uint(Uint **hpp, Uint *szp, Uint n, Uint nums[]); static int hxnodecmp(hxnode_t* a, hxnode_t* b); static int hxnodecmpkey(hxnode_t* a, hxnode_t* b); @@ -1993,6 +1999,13 @@ int erts_validate_and_sort_map(map_t* mp) return 1; } +BIF_RETTYPE erts_debug_map_info_1(BIF_ALIST_1) { + if (is_hashmap(BIF_ARG_1)) { + BIF_RET(hashmap_info(BIF_P,BIF_ARG_1)); + } + BIF_ERROR(BIF_P, BADARG); +} + /* * erts_internal:map_to_tuple_keys/1 * @@ -2007,6 +2020,126 @@ BIF_RETTYPE erts_internal_map_to_tuple_keys_1(BIF_ALIST_1) { BIF_ERROR(BIF_P, BADARG); } +static Eterm hashmap_info(Process *p, Eterm node) { + Eterm *hp; + Eterm res = NIL, info = NIL; + Eterm *ptr, tup, hdr; + Uint sz; + DECL_AM(depth); + DECL_AM(leafs); + DECL_AM(bitmaps); + DECL_AM(arrays); + Uint nleaf=0, nbitmap=0, narray=0; + Uint bitmap_usage[16], leaf_usage[16]; + Uint lvl = 0, clvl; + DECLARE_ESTACK(stack); + + for (sz = 0; sz < 16; sz++) { + bitmap_usage[sz] = 0; + leaf_usage[sz] = 0; + } + + ptr = boxed_val(node); + ESTACK_PUSH(stack, 0); + ESTACK_PUSH(stack, node); + do { + node = ESTACK_POP(stack); + clvl = ESTACK_POP(stack); + lvl = MAX(lvl,clvl); + switch(primary_tag(node)) { + case TAG_PRIMARY_LIST: + nleaf++; + leaf_usage[clvl] += 1; + break; + case TAG_PRIMARY_BOXED: + ptr = boxed_val(node); + hdr = *ptr; + ASSERT(is_header(hdr)); + switch(hdr & _HEADER_MAP_SUBTAG_MASK) { + case HAMT_SUBTAG_NODE_ARRAY: + narray++; + sz = 16; + while(sz--) { + ESTACK_PUSH(stack, clvl + 1); + ESTACK_PUSH(stack, ptr[sz+1]); + } + break; + case HAMT_SUBTAG_NODE_BITMAP: + nbitmap++; + sz = hashmap_bitcount(MAP_HEADER_VAL(hdr)); + ASSERT(sz < 17); + bitmap_usage[sz-1] += 1; + while(sz--) { + ESTACK_PUSH(stack, clvl + 1); + ESTACK_PUSH(stack, ptr[sz+1]); + } + break; + case HAMT_SUBTAG_HEAD_BITMAP: + nbitmap++; + sz = hashmap_bitcount(MAP_HEADER_VAL(hdr)); + bitmap_usage[sz-1] += 1; + while(sz--) { + ESTACK_PUSH(stack, clvl + 1); + ESTACK_PUSH(stack, ptr[sz+2]); + } + break; + case HAMT_SUBTAG_HEAD_ARRAY: + narray++; + sz = 16; + while(sz--) { + ESTACK_PUSH(stack, clvl + 1); + ESTACK_PUSH(stack, ptr[sz+2]); + } + break; + default: + erl_exit(1, "bad header\r\n"); + break; + } + } + } while(!ESTACK_ISEMPTY(stack)); + + + /* size */ + sz = 0; + hashmap_bld_tuple_uint(NULL,&sz,16,leaf_usage); + hashmap_bld_tuple_uint(NULL,&sz,16,bitmap_usage); + + /* alloc */ + hp = HAlloc(p, 2+3 + 3*(2+4) + sz); + + info = hashmap_bld_tuple_uint(&hp,NULL,16,leaf_usage); + tup = TUPLE3(hp, AM_leafs, make_small(nleaf),info); hp += 4; + res = CONS(hp, tup, res); hp += 2; + + info = hashmap_bld_tuple_uint(&hp,NULL,16,bitmap_usage); + tup = TUPLE3(hp, AM_bitmaps, make_small(nbitmap), info); hp += 4; + res = CONS(hp, tup, res); hp += 2; + + tup = TUPLE3(hp, AM_arrays, make_small(narray),NIL); hp += 4; + res = CONS(hp, tup, res); hp += 2; + + tup = TUPLE2(hp, AM_depth, make_small(lvl)); hp += 3; + res = CONS(hp, tup, res); hp += 2; + + DESTROY_ESTACK(stack); + ERTS_HOLE_CHECK(p); + return res; +} + +static Eterm hashmap_bld_tuple_uint(Uint **hpp, Uint *szp, Uint n, Uint nums[]) { + Eterm res = THE_NON_VALUE; + Eterm *ts = (Eterm *)erts_alloc(ERTS_ALC_T_TMP, n * sizeof(Eterm)); + Uint i; + + for (i = 0; i < n; i++) { + ts[i] = erts_bld_uint(hpp, szp, nums[i]); + } + res = erts_bld_tuplev(hpp, szp, n, ts); + erts_free(ERTS_ALC_T_TMP, (void *) ts); + return res; +} + + /* implementation of builtin emulations */ #if !defined(__GNUC__) |