diff options
Diffstat (limited to 'erts/emulator/beam/erl_map.c')
| -rw-r--r-- | erts/emulator/beam/erl_map.c | 74 | 
1 files changed, 35 insertions, 39 deletions
| diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c index cba17d3e6a..93816542cd 100644 --- a/erts/emulator/beam/erl_map.c +++ b/erts/emulator/beam/erl_map.c @@ -125,15 +125,20 @@ BIF_RETTYPE map_size_1(BIF_ALIST_1) {  	flatmap_t *mp = (flatmap_t*)flatmap_val(BIF_ARG_1);  	BIF_RET(make_small(flatmap_get_size(mp)));      } else if (is_hashmap(BIF_ARG_1)) { -	Eterm *head, *hp, res; -	Uint size, hsz=0; +	Eterm *head; +	Uint size;  	head = hashmap_val(BIF_ARG_1);  	size = head[1]; -	(void) erts_bld_uint(NULL, &hsz, size); -	hp = HAlloc(BIF_P, hsz); -	res = erts_bld_uint(&hp, NULL, size); -	BIF_RET(res); + +        /* +         * As long as a small has 28 bits (on a 32-bit machine) for +         * the integer itself, it is impossible to build a map whose +         * size would not fit in a small. Add an assertion in case we +         * ever decreases the number of bits in a small. +         */ +        ASSERT(IS_USMALL(0, size)); +        BIF_RET(make_small(size));      }      BIF_P->fvalue = BIF_ARG_1; @@ -1505,25 +1510,6 @@ int hashmap_key_hash_cmp(Eterm* ap, Eterm* bp)      return ap ? -1 : 1;  } -/* maps:new/0 */ - -BIF_RETTYPE maps_new_0(BIF_ALIST_0) { -    Eterm* hp; -    Eterm tup; -    flatmap_t *mp; - -    hp    = HAlloc(BIF_P, (MAP_HEADER_FLATMAP_SZ + 1)); -    tup   = make_tuple(hp); -    *hp++ = make_arityval(0); - -    mp    = (flatmap_t*)hp; -    mp->thing_word = MAP_HEADER_FLATMAP; -    mp->size = 0; -    mp->keys = tup; - -    BIF_RET(make_flatmap(mp)); -} -  /* maps:put/3 */  BIF_RETTYPE maps_put_3(BIF_ALIST_3) { @@ -1707,11 +1693,16 @@ int erts_maps_update(Process *p, Eterm key, Eterm value, Eterm map, Eterm *res)  	return 0;  found_key: -	*hp++ = value; -	vs++; -	if (++i < n) -	    sys_memcpy(hp, vs, (n - i)*sizeof(Eterm)); -	*res = make_flatmap(shp); +        if(*vs == value) { +            HRelease(p, shp + MAP_HEADER_FLATMAP_SZ + n, shp); +            *res = map; +        } else { +	    *hp++ = value; +	    vs++; +	    if (++i < n) +	       sys_memcpy(hp, vs, (n - i)*sizeof(Eterm)); +	    *res = make_flatmap(shp); +        }  	return 1;      } @@ -1767,9 +1758,7 @@ Eterm erts_maps_put(Process *p, Eterm key, Eterm value, Eterm map) {  	if (is_immed(key)) {  	    for( i = 0; i < n; i ++) {  		if (ks[i] == key) { -		    *hp++ = value; -		    vs++; -		    c = 1; +                    goto found_key;  		} else {  		    *hp++ = *vs++;  		} @@ -1777,18 +1766,13 @@ Eterm erts_maps_put(Process *p, Eterm key, Eterm value, Eterm map) {  	} else {  	    for( i = 0; i < n; i ++) {  		if (EQ(ks[i], key)) { -		    *hp++ = value; -		    vs++; -		    c = 1; +		    goto found_key;  		} else {  		    *hp++ = *vs++;  		}  	    }  	} -	if (c) -	    return res; -  	/* the map will grow */  	if (n >= MAP_SMALL_MAP_LIMIT) { @@ -1843,6 +1827,18 @@ Eterm erts_maps_put(Process *p, Eterm key, Eterm value, Eterm map) {  	 */  	*shp = make_pos_bignum_header(0);  	return res; + +found_key: +        if(*vs == value) { +            HRelease(p, shp + MAP_HEADER_FLATMAP_SZ + n, shp); +            return map; +        } else { +            *hp++ = value; +            vs++; +            if (++i < n) +               sys_memcpy(hp, vs, (n - i)*sizeof(Eterm)); +            return res; +        }      }      ASSERT(is_hashmap(map)); | 
