aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/beam_emu.c11
-rw-r--r--erts/emulator/beam/bif.c6
-rw-r--r--erts/emulator/beam/erl_bif_info.c20
-rw-r--r--erts/emulator/beam/erl_db_hash.c8
-rw-r--r--erts/emulator/beam/erl_map.c48
-rw-r--r--erts/emulator/beam/utils.c6
6 files changed, 68 insertions, 31 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 8fcdc72895..fdb84aae42 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -6573,6 +6573,7 @@ new_map(Process* p, Eterm* reg, BeamInstr* I)
ptr = &Arg(4);
if (n > 2*MAP_SMALL_MAP_LIMIT) {
+ Eterm res;
if (HeapWordsLeft(p) < n) {
erts_garbage_collect(p, n, reg, Arg(2));
}
@@ -6589,7 +6590,15 @@ new_map(Process* p, Eterm* reg, BeamInstr* I)
p->htop = mhp;
factory.p = p;
- return erts_hashmap_from_array(&factory, thp, n/2, 0);
+ res = erts_hashmap_from_array(&factory, thp, n/2, 0);
+ if (p->mbuf) {
+ Uint live = Arg(2);
+ reg[live] = res;
+ erts_garbage_collect(p, 0, reg, live+1);
+ res = reg[live];
+ E = p->stop;
+ }
+ return res;
}
if (HeapWordsLeft(p) < need) {
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index cc20ec7440..022150da55 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -2930,7 +2930,7 @@ static int do_list_to_integer(Process *p, Eterm orig_list,
Uint ui = 0;
int skip = 0;
int neg = 0;
- int n = 0;
+ Sint n = 0;
int m;
int lg2;
Eterm res;
@@ -3010,7 +3010,9 @@ static int do_list_to_integer(Process *p, Eterm orig_list,
else i = (Sint)ui;
res = make_small(i);
} else {
- lg2 = (n+1)*230/69+1;
+ /* Convert from log10 to log2 by multiplying with 1/log10(2)=3.3219
+ which we round up to (3 + 1/3) */
+ lg2 = (n+1)*3 + (n+1)/3 + 1;
m = (lg2+D_EXP-1)/D_EXP; /* number of digits */
m = BIG_NEED_SIZE(m); /* number of words + thing */
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index b2658a1fd6..fa7de23f00 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -3747,6 +3747,20 @@ BIF_RETTYPE erts_internal_is_system_process_1(BIF_ALIST_1)
static erts_smp_atomic_t hipe_test_reschedule_flag;
+#if defined(VALGRIND) && defined(__GNUC__)
+/* Force noinline for valgrind suppression */
+static void broken_halt_test(Eterm bif_arg_2) __attribute__((noinline));
+#endif
+
+static void broken_halt_test(Eterm bif_arg_2)
+{
+ /* Ugly ugly code used by bif_SUITE:erlang_halt/1 */
+#if defined(ERTS_HAVE_TRY_CATCH)
+ erts_get_scheduler_data()->run_queue = NULL;
+#endif
+ erl_exit(ERTS_DUMP_EXIT, "%T", bif_arg_2);
+}
+
BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
{
@@ -4040,11 +4054,7 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
}
}
else if (ERTS_IS_ATOM_STR("broken_halt", BIF_ARG_1)) {
- /* Ugly ugly code used by bif_SUITE:erlang_halt/1 */
-#if defined(ERTS_HAVE_TRY_CATCH)
- erts_get_scheduler_data()->run_queue = NULL;
-#endif
- erl_exit(ERTS_DUMP_EXIT, "%T", BIF_ARG_2);
+ broken_halt_test(BIF_ARG_2);
}
else if (ERTS_IS_ATOM_STR("unique_monotonic_integer_state", BIF_ARG_1)) {
int res = erts_debug_set_unique_monotonic_integer_state(BIF_ARG_2);
diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c
index 045c8ae135..383ee7c430 100644
--- a/erts/emulator/beam/erl_db_hash.c
+++ b/erts/emulator/beam/erl_db_hash.c
@@ -2471,10 +2471,10 @@ static int alloc_seg(DbTableHash *tb)
*/
static int free_seg(DbTableHash *tb, int free_records)
{
- int seg_ix = (tb->nslots >> SEGSZ_EXP) - 1;
+ const int seg_ix = (tb->nslots >> SEGSZ_EXP) - 1;
+ struct segment** const segtab = SEGTAB(tb);
+ struct ext_segment* const top = (struct ext_segment*) segtab[seg_ix];
int bytes;
- struct segment** segtab = SEGTAB(tb);
- struct ext_segment* top = (struct ext_segment*) segtab[seg_ix];
int nrecords = 0;
ASSERT(top != NULL);
@@ -2537,7 +2537,7 @@ static int free_seg(DbTableHash *tb, int free_records)
(void*)top, bytes);
#ifdef DEBUG
if (seg_ix > 0) {
- if (seg_ix < tb->nsegs) SEGTAB(tb)[seg_ix] = NULL;
+ segtab[seg_ix] = NULL;
} else {
SET_SEGTAB(tb, NULL);
}
diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c
index 5a70407e42..cca287c753 100644
--- a/erts/emulator/beam/erl_map.c
+++ b/erts/emulator/beam/erl_map.c
@@ -89,7 +89,7 @@ static Eterm flatmap_from_validated_list(Process *p, Eterm list, Uint size);
static Eterm hashmap_from_validated_list(Process *p, Eterm list, Uint size);
static Eterm hashmap_from_unsorted_array(ErtsHeapFactory*, hxnode_t *hxns, Uint n, int reject_dupkeys);
static Eterm hashmap_from_sorted_unique_array(ErtsHeapFactory*, hxnode_t *hxns, Uint n, int is_root);
-static Eterm hashmap_from_chunked_array(ErtsHeapFactory*, hxnode_t *hxns, Uint n, int is_root);
+static Eterm hashmap_from_chunked_array(ErtsHeapFactory*, hxnode_t *hxns, Uint n, Uint size, 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);
@@ -392,12 +392,11 @@ static Eterm hashmap_from_validated_list(Process *p, Eterm list, Uint size) {
Eterm item = list;
Eterm *hp;
Eterm *kv, res;
- Eterm tmp[2];
Uint32 sw, hx;
Uint ix = 0;
hxnode_t *hxns;
ErtsHeapFactory factory;
-
+ DeclareTmpHeap(tmp,2,p);
ASSERT(size > 0);
hp = HAlloc(p, (2 * size));
@@ -405,6 +404,7 @@ static Eterm hashmap_from_validated_list(Process *p, Eterm list, Uint size) {
/* create tmp hx values and leaf ptrs */
hxns = (hxnode_t *)erts_alloc(ERTS_ALC_T_TMP, size * sizeof(hxnode_t));
+ UseTmpHeap(2,p);
while(is_list(item)) {
res = CAR(list_val(item));
kv = tuple_val(res);
@@ -417,6 +417,7 @@ static Eterm hashmap_from_validated_list(Process *p, Eterm list, Uint size) {
ix++;
item = CDR(list_val(item));
}
+ UnUseTmpHeap(2,p);
factory.p = p;
res = hashmap_from_unsorted_array(&factory, hxns, size, 0);
@@ -625,9 +626,9 @@ static Eterm hashmap_from_sorted_unique_array(ErtsHeapFactory* factory,
Uint i,ix,jx,elems;
Uint32 sw, hx;
Eterm val;
- Eterm th[2];
hxnode_t *tmp;
-
+ DeclareTmpHeapNoproc(th,2);
+ UseTmpHeapNoproc(2);
ASSERT(lvl < 32);
ix = 0;
elems = 1;
@@ -661,16 +662,17 @@ static Eterm hashmap_from_sorted_unique_array(ErtsHeapFactory* factory,
ix++;
}
- res = hashmap_from_chunked_array(factory, hxns, elems, !lvl);
+ res = hashmap_from_chunked_array(factory, hxns, elems, n, !lvl);
ERTS_FACTORY_HOLE_CHECK(factory);
+ UnUseTmpHeapNoproc(2);
return res;
}
#define HALLOC_EXTRA 200
-static Eterm hashmap_from_chunked_array(ErtsHeapFactory *factory,
- hxnode_t *hxns, Uint n, int is_root) {
+static Eterm hashmap_from_chunked_array(ErtsHeapFactory *factory, hxnode_t *hxns, Uint n,
+ Uint size, int is_root) {
Uint ix, d, dn, dc, slot, elems;
Uint32 v, vp, vn, hdr;
Uint bp, sz;
@@ -840,7 +842,7 @@ static Eterm hashmap_from_chunked_array(ErtsHeapFactory *factory,
if (is_root) {
*hp++ = (hdr == 0xffff) ? MAP_HEADER_HAMT_HEAD_ARRAY : MAP_HEADER_HAMT_HEAD_BITMAP(hdr);
- *hp++ = n;
+ *hp++ = size;
} else {
*hp++ = MAP_HEADER_HAMT_NODE_BITMAP(hdr);
}
@@ -1099,12 +1101,13 @@ static Eterm hashmap_merge(Process *p, Eterm nodeA, Eterm nodeB) {
struct HashmapMergePStackType* sp = PSTACK_PUSH(s);
Eterm *hp, *nhp;
Eterm hdrA, hdrB;
- Eterm th[2];
Uint32 ahx, bhx;
Uint size; /* total key-value counter */
int keepA = 0;
- unsigned lvl = 0;
+ unsigned int lvl = 0;
+ DeclareTmpHeap(th,2,p);
Eterm res = THE_NON_VALUE;
+ UseTmpHeap(2,p);
/*
* Strategy: Do depth-first traversal of both trees (at the same time)
@@ -1297,6 +1300,7 @@ recurse:
res = make_boxed(nhp);
}
PSTACK_DESTROY(s);
+ UnUseTmpHeap(2,p);
return res;
}
@@ -1315,8 +1319,9 @@ static int hash_cmp(Uint32 ha, Uint32 hb)
int hashmap_key_hash_cmp(Eterm* ap, Eterm* bp)
{
- Eterm th[2];
- unsigned lvl = 0;
+ unsigned int lvl = 0;
+ DeclareTmpHeapNoproc(th,2);
+ UseTmpHeapNoproc(2);
if (ap && bp) {
ASSERT(CMP_TERM(CAR(ap), CAR(bp)) != 0);
@@ -1324,11 +1329,14 @@ int hashmap_key_hash_cmp(Eterm* ap, Eterm* bp)
Uint32 ha = hashmap_restore_hash(th, lvl, CAR(ap));
Uint32 hb = hashmap_restore_hash(th, lvl, CAR(bp));
int cmp = hash_cmp(ha, hb);
- if (cmp)
+ if (cmp) {
+ UnUseTmpHeapNoproc(2);
return cmp;
+ }
lvl += 8;
}
}
+ UnUseTmpHeapNoproc(2);
return ap ? -1 : 1;
}
@@ -1901,13 +1909,14 @@ int erts_hashmap_insert_down(Uint32 hx, Eterm key, Eterm node, Uint *sz,
Uint *update_size, ErtsEStack *sp, int is_update) {
Eterm *ptr;
Eterm hdr, ckey;
- Eterm th[2];
Uint32 ix, cix, bp, hval, chx;
Uint slot, lvl = 0, clvl;
Uint size = 0, n = 0;
+ DeclareTmpHeapNoproc(th,2);
*update_size = 1;
+ UseTmpHeapNoproc(2);
for (;;) {
switch(primary_tag(node)) {
case TAG_PRIMARY_LIST: /* LEAF NODE [K|V] */
@@ -1918,6 +1927,7 @@ int erts_hashmap_insert_down(Uint32 hx, Eterm key, Eterm node, Uint *sz,
goto unroll;
}
if (is_update) {
+ UnUseTmpHeapNoproc(2);
return 0;
}
goto insert_subnodes;
@@ -1950,6 +1960,7 @@ int erts_hashmap_insert_down(Uint32 hx, Eterm key, Eterm node, Uint *sz,
if (!(bp & hval)) { /* not occupied */
if (is_update) {
+ UnUseTmpHeapNoproc(2);
return 0;
}
size += HAMT_NODE_BITMAP_SZ(n+1);
@@ -1981,6 +1992,7 @@ int erts_hashmap_insert_down(Uint32 hx, Eterm key, Eterm node, Uint *sz,
}
/* not occupied */
if (is_update) {
+ UnUseTmpHeapNoproc(2);
return 0;
}
size += HAMT_HEAD_BITMAP_SZ(n+1);
@@ -2014,6 +2026,7 @@ insert_subnodes:
unroll:
*sz = size + /* res cons */ 2;
+ UnUseTmpHeapNoproc(2);
return 1;
}
@@ -2156,13 +2169,14 @@ static Eterm hashmap_values(Process* p, Eterm node) {
static Eterm hashmap_delete(Process *p, Uint32 hx, Eterm key, Eterm map) {
Eterm *hp = NULL, *nhp = NULL, *hp_end = NULL;
- Eterm th[2];
Eterm *ptr;
Eterm hdr, res = map, node = map;
Uint32 ix, bp, hval;
Uint slot, lvl = 0;
Uint size = 0, n = 0;
DECLARE_ESTACK(stack);
+ DeclareTmpHeapNoproc(th,2);
+ UseTmpHeapNoproc(2);
for (;;) {
switch(primary_tag(node)) {
@@ -2277,6 +2291,7 @@ unroll:
erts_validate_and_sort_flatmap(mp);
DESTROY_WSTACK(wstack);
+ UnUseTmpHeapNoproc(2);
return make_flatmap(mp);
}
@@ -2417,6 +2432,7 @@ not_found:
DESTROY_ESTACK(stack);
ERTS_VERIFY_UNUSED_TEMP_ALLOC(p);
ERTS_HOLE_CHECK(p);
+ UnUseTmpHeapNoproc(2);
return res;
}
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index 889c217b0b..bf6d9fff50 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -1614,7 +1614,6 @@ make_internal_hash(Eterm term)
Eterm tmp;
DECLARE_ESTACK(s);
- UseTmpHeapNoproc(2);
hash = 0;
for (;;) {
switch (primary_tag(term)) {
@@ -1894,10 +1893,12 @@ make_internal_hash(Eterm term)
{
FloatDef ff;
GET_DOUBLE(term, ff);
+ if (ff.fd == 0.0) {
+ ff.fd = 0.0; /* ensure pos. 0.0 */
+ }
UINT32_HASH_2(ff.fw[0], ff.fw[1], HCONST_12);
goto pop_next;
}
-
default:
erl_exit(1, "Invalid tag in make_hash2(0x%X)\n", term);
}
@@ -1917,7 +1918,6 @@ make_internal_hash(Eterm term)
pop_next:
if (ESTACK_ISEMPTY(s)) {
DESTROY_ESTACK(s);
- UnUseTmpHeapNoproc(2);
return hash;
}