diff options
Diffstat (limited to 'erts/emulator/beam/utils.c')
-rw-r--r-- | erts/emulator/beam/utils.c | 104 |
1 files changed, 60 insertions, 44 deletions
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c index 092a5320ba..457cada745 100644 --- a/erts/emulator/beam/utils.c +++ b/erts/emulator/beam/utils.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1996-2016. All Rights Reserved. + * Copyright Ericsson AB 1996-2017. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -1578,16 +1578,13 @@ do { /* Lightweight mixing of constant (type info) */ \ } while (0) Uint32 -make_internal_hash(Eterm term) +make_internal_hash(Eterm term, Uint32 salt) { Uint32 hash; - Uint32 hash_xor_pairs; - - ERTS_UNDEF(hash_xor_pairs, 0); /* Optimization. Simple cases before declaration of estack. */ if (primary_tag(term) == TAG_PRIMARY_IMMED1) { - hash = 0; + hash = salt; #if ERTS_SIZEOF_ETERM == 8 UINT32_HASH_2((Uint32)term, (Uint32)(term >> 32), HCONST); #elif ERTS_SIZEOF_ETERM == 4 @@ -1601,7 +1598,7 @@ make_internal_hash(Eterm term) Eterm tmp; DECLARE_ESTACK(s); - hash = 0; + hash = salt; for (;;) { switch (primary_tag(term)) { case TAG_PRIMARY_LIST: @@ -1664,6 +1661,11 @@ make_internal_hash(Eterm term) Eterm* ptr = boxed_val(term) + 1; Uint size; int i; + + /* + * We rely on key-value iteration order being constant + * for identical maps (in this VM instance). + */ switch (hdr & _HEADER_MAP_SUBTAG_MASK) { case HAMT_SUBTAG_HEAD_FLATMAP: { @@ -1675,26 +1677,10 @@ make_internal_hash(Eterm term) if (size == 0) goto pop_next; - /* We want a hash function that is *independent* of - * the order in which keys and values are encountered. - * We therefore calculate context independent hashes for all . - * key-value pairs and then xor them together. - * - * We *do* need to use an initial seed for each pair, i.e. the - * hash value, so the hash value is reset for each pair with 'hash'. - * If we don't, no additional entropy is given to the system and the - * hash collision resolution in maps:from_list/1 would fail. - */ - ESTACK_PUSH(s, hash_xor_pairs); - ESTACK_PUSH(s, hash); - ESTACK_PUSH(s, HASH_MAP_TAIL); for (i = size - 1; i >= 0; i--) { - ESTACK_PUSH(s, hash); /* initial seed for all pairs */ - ESTACK_PUSH(s, HASH_MAP_PAIR); ESTACK_PUSH(s, vs[i]); ESTACK_PUSH(s, ks[i]); } - hash_xor_pairs = 0; goto pop_next; } case HAMT_SUBTAG_HEAD_ARRAY: @@ -1703,10 +1689,6 @@ make_internal_hash(Eterm term) UINT32_HASH(size, HCONST_16); if (size == 0) goto pop_next; - ESTACK_PUSH(s, hash_xor_pairs); - ESTACK_PUSH(s, hash); - ESTACK_PUSH(s, HASH_MAP_TAIL); - hash_xor_pairs = 0; } switch (hdr & _HEADER_MAP_SUBTAG_MASK) { case HAMT_SUBTAG_HEAD_ARRAY: @@ -1722,8 +1704,6 @@ make_internal_hash(Eterm term) while (i) { if (is_list(*ptr)) { Eterm* cons = list_val(*ptr); - ESTACK_PUSH(s, hash); /* initial seed for all pairs */ - ESTACK_PUSH(s, HASH_MAP_PAIR); ESTACK_PUSH(s, CDR(cons)); ESTACK_PUSH(s, CAR(cons)); } @@ -1739,7 +1719,7 @@ make_internal_hash(Eterm term) case EXPORT_SUBTAG: { Export* ep = *((Export **) (export_val(term) + 1)); - /* Assumes Export entries never moves */ + /* Assumes Export entries never move */ POINTER_HASH(ep, HCONST_14); goto pop_next; } @@ -1894,7 +1874,7 @@ make_internal_hash(Eterm term) goto pop_next; } default: - erts_exit(ERTS_ERROR_EXIT, "Invalid tag in make_hash2(0x%X)\n", term); + erts_exit(ERTS_ERROR_EXIT, "Invalid tag in make_internal_hash(0x%X, %lu)\n", term, salt); } } break; @@ -1907,7 +1887,7 @@ make_internal_hash(Eterm term) goto pop_next; default: - erts_exit(ERTS_ERROR_EXIT, "Invalid tag in make_hash2(0x%X)\n", term); + erts_exit(ERTS_ERROR_EXIT, "Invalid tag in make_internal_hash(0x%X, %lu)\n", term, salt); pop_next: if (ESTACK_ISEMPTY(s)) { @@ -1919,17 +1899,6 @@ make_internal_hash(Eterm term) term = ESTACK_POP(s); switch (term) { - case HASH_MAP_TAIL: { - hash = (Uint32) ESTACK_POP(s); - UINT32_HASH(hash_xor_pairs, HCONST_19); - hash_xor_pairs = (Uint32) ESTACK_POP(s); - goto pop_next; - } - case HASH_MAP_PAIR: - hash_xor_pairs ^= hash; - hash = (Uint32) ESTACK_POP(s); /* initial seed for all pairs */ - goto pop_next; - case HASH_CDR: CONST_HASH(HCONST_18); /* Hash CDR i cons cell */ goto pop_next; @@ -3594,7 +3563,7 @@ store_external_or_ref_(Uint **hpp, ErlOffHeap* oh, Eterm ns) ErtsMRefThing *mreft = (ErtsMRefThing *) from_hp; ErtsMagicBinary *mb = mreft->mb; ASSERT(is_magic_ref_thing(from_hp)); - erts_refc_inc(&mb->refc, 2); + erts_refc_inc(&mb->intern.refc, 2); OH_OVERHEAD(oh, mb->orig_size / sizeof(Eterm)); } @@ -4835,6 +4804,53 @@ Uint64 erts_timestamp_millis(void) #endif } +void * +erts_calc_stacklimit(char *prev_c, UWord stacksize) +{ + /* + * We *don't* want this function inlined, i.e., it is + * risky to call this function from another function + * in utils.c + */ + + UWord pagesize = erts_sys_get_page_size(); + char c; + char *start; + if (&c > prev_c) { + start = (char *) ((((UWord) prev_c) / pagesize) * pagesize); + return (void *) (start + stacksize); + } + else { + start = (char *) (((((UWord) prev_c) - 1) / pagesize + 1) * pagesize); + return (void *) (start - stacksize); + } +} + +/* + * erts_check_below_limit() and + * erts_check_above_limit() are put + * in utils.c in order to prevent + * inlining. + */ + +int +erts_check_below_limit(char *ptr, char *limit) +{ + return ptr < limit; +} + +int +erts_check_above_limit(char *ptr, char *limit) +{ + return ptr > limit; +} + +void * +erts_ptr_id(void *ptr) +{ + return ptr; +} + #ifdef DEBUG /* * Handy functions when using a debugger - don't use in the code! |