aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/emulator/beam/beam_bif_load.c47
-rw-r--r--erts/emulator/beam/beam_bp.h2
-rw-r--r--erts/emulator/beam/beam_emu.c22
-rw-r--r--erts/emulator/beam/bif.c4
-rw-r--r--erts/emulator/beam/binary.c18
-rw-r--r--erts/emulator/beam/break.c32
-rw-r--r--erts/emulator/beam/copy.c98
-rw-r--r--erts/emulator/beam/dist.c26
-rw-r--r--erts/emulator/beam/erl_bif_binary.c4
-rw-r--r--erts/emulator/beam/erl_bif_info.c52
-rw-r--r--erts/emulator/beam/erl_bif_trace.c2
-rw-r--r--erts/emulator/beam/erl_bits.c8
-rw-r--r--erts/emulator/beam/erl_db_hash.c6
-rw-r--r--erts/emulator/beam/erl_db_tree.c19
-rw-r--r--erts/emulator/beam/erl_db_util.c13
-rw-r--r--erts/emulator/beam/erl_fun.c14
-rw-r--r--erts/emulator/beam/erl_fun.h4
-rw-r--r--erts/emulator/beam/erl_gc.c454
-rw-r--r--erts/emulator/beam/erl_message.c149
-rw-r--r--erts/emulator/beam/erl_message.h21
-rw-r--r--erts/emulator/beam/erl_nif.c10
-rw-r--r--erts/emulator/beam/erl_node_tables.c70
-rw-r--r--erts/emulator/beam/erl_process.c28
-rw-r--r--erts/emulator/beam/erl_process.h2
-rw-r--r--erts/emulator/beam/erl_term.h15
-rw-r--r--erts/emulator/beam/external.c95
-rw-r--r--erts/emulator/beam/global.h26
-rw-r--r--erts/emulator/beam/io.c20
-rw-r--r--erts/emulator/beam/utils.c28
-rw-r--r--erts/emulator/hipe/hipe_mkliterals.c4
-rw-r--r--lib/edoc/src/edoc_lib.erl4
-rw-r--r--lib/erl_interface/src/misc/ei_decode_term.c1
-rw-r--r--lib/erl_interface/src/prog/erl_call.c3
-rw-r--r--lib/hipe/rtl/hipe_rtl_primops.erl22
-rw-r--r--lib/hipe/rtl/hipe_tagscheme.erl4
-rw-r--r--lib/inviso/src/inviso.erl78
-rw-r--r--lib/inviso/src/inviso_c.erl50
-rw-r--r--lib/inviso/src/inviso_lfm.erl14
-rw-r--r--lib/inviso/src/inviso_lfm_tpfreader.erl12
-rw-r--r--lib/inviso/src/inviso_tool.erl72
-rw-r--r--lib/inviso/src/inviso_tool_lib.erl18
-rw-r--r--lib/kernel/internal_doc/distribution_handshake.txt40
-rw-r--r--lib/kernel/src/code.erl18
-rw-r--r--lib/kernel/test/code_SUITE.erl32
-rw-r--r--lib/stdlib/test/ets_SUITE.erl21
45 files changed, 693 insertions, 989 deletions
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index 596ad9a010..4fc271d41c 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -402,7 +402,7 @@ check_process_code(Process* rp, Module* modp)
BeamInstr* end;
Eterm* sp;
#ifndef HYBRID /* FIND ME! */
- ErlFunThing* funp;
+ struct erl_off_heap_header* oh;
int done_gc = 0;
#endif
@@ -470,27 +470,30 @@ check_process_code(Process* rp, Module* modp)
#ifndef HYBRID /* FIND ME! */
rescan:
- for (funp = MSO(rp).funs; funp; funp = funp->next) {
- BeamInstr* fun_code;
-
- fun_code = funp->fe->address;
-
- if (INSIDE((BeamInstr *) funp->fe->address)) {
- if (done_gc) {
- return am_true;
- } else {
- /*
- * Try to get rid of this fun by garbage collecting.
- * Clear both fvalue and ftrace to make sure they
- * don't hold any funs.
- */
- rp->freason = EXC_NULL;
- rp->fvalue = NIL;
- rp->ftrace = NIL;
- done_gc = 1;
- FLAGS(rp) |= F_NEED_FULLSWEEP;
- (void) erts_garbage_collect(rp, 0, rp->arg_reg, rp->arity);
- goto rescan;
+ for (oh = MSO(rp).first; oh; oh = oh->next) {
+ if (thing_subtag(oh->thing_word) == FUN_SUBTAG) {
+ ErlFunThing* funp = (ErlFunThing*) oh;
+ BeamInstr* fun_code;
+
+ fun_code = funp->fe->address;
+
+ if (INSIDE((BeamInstr *) funp->fe->address)) {
+ if (done_gc) {
+ return am_true;
+ } else {
+ /*
+ * Try to get rid of this fun by garbage collecting.
+ * Clear both fvalue and ftrace to make sure they
+ * don't hold any funs.
+ */
+ rp->freason = EXC_NULL;
+ rp->fvalue = NIL;
+ rp->ftrace = NIL;
+ done_gc = 1;
+ FLAGS(rp) |= F_NEED_FULLSWEEP;
+ (void) erts_garbage_collect(rp, 0, rp->arg_reg, rp->arity);
+ goto rescan;
+ }
}
}
}
diff --git a/erts/emulator/beam/beam_bp.h b/erts/emulator/beam/beam_bp.h
index b5d5b3c203..ebc171078d 100644
--- a/erts/emulator/beam/beam_bp.h
+++ b/erts/emulator/beam/beam_bp.h
@@ -123,7 +123,7 @@ typedef struct {
Uint ms;
Uint s;
Uint us;
- Uint *pc;
+ BeamInstr *pc;
} process_breakpoint_time_t; /* used within psd */
extern erts_smp_spinlock_t erts_bp_lock;
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index c0680086aa..260f349563 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -3385,8 +3385,8 @@ apply_bif_or_nif_epilogue:
HTOP += PROC_BIN_SIZE;
pb->thing_word = HEADER_PROC_BIN;
pb->size = num_bytes;
- pb->next = MSO(c_p).mso;
- MSO(c_p).mso = pb;
+ pb->next = MSO(c_p).first;
+ MSO(c_p).first = (struct erl_off_heap_header*) pb;
pb->val = bptr;
pb->bytes = (byte*) bptr->orig_bytes;
pb->flags = 0;
@@ -3486,8 +3486,8 @@ apply_bif_or_nif_epilogue:
HTOP += PROC_BIN_SIZE;
pb->thing_word = HEADER_PROC_BIN;
pb->size = tmp_arg1;
- pb->next = MSO(c_p).mso;
- MSO(c_p).mso = pb;
+ pb->next = MSO(c_p).first;
+ MSO(c_p).first = (struct erl_off_heap_header*) pb;
pb->val = bptr;
pb->bytes = (byte*) bptr->orig_bytes;
pb->flags = 0;
@@ -4463,7 +4463,7 @@ apply_bif_or_nif_epilogue:
E -= 2;
E[0] = make_cp(I);
E[1] = make_cp(c_p->cp); /* original return address */
- c_p->cp = (BeamInstr *) make_cp(beam_return_time_trace);
+ c_p->cp = beam_return_time_trace;
}
}
@@ -4493,20 +4493,20 @@ apply_bif_or_nif_epilogue:
BeamInstr real_I;
Uint32 flags;
Eterm tracer_pid;
- BeamInstr *cpp;
+ Uint* cpp;
int return_to_trace = 0, need = 0;
flags = 0;
SWAPOUT;
reg[0] = r(0);
if (*(c_p->cp) == (BeamInstr) OpCode(return_trace)) {
- cpp = (BeamInstr*)&E[2];
+ cpp = &E[2];
} else if (*(c_p->cp) == (BeamInstr) OpCode(i_return_to_trace)) {
return_to_trace = !0;
- cpp = (BeamInstr*)&E[0];
+ cpp = &E[0];
} else if (*(c_p->cp) == (BeamInstr) OpCode(i_return_time_trace)) {
return_to_trace = !0;
- cpp = (BeamInstr*)&E[0];
+ cpp = &E[0];
} else {
cpp = NULL;
}
@@ -6323,8 +6323,8 @@ new_fun(Process* p, Eterm* reg, ErlFunEntry* fe, int num_free)
erts_refc_inc(&fe->refc, 2);
funp->thing_word = HEADER_FUN;
#ifndef HYBRID /* FIND ME! */
- funp->next = MSO(p).funs;
- MSO(p).funs = funp;
+ funp->next = MSO(p).first;
+ MSO(p).first = (struct erl_off_heap_header*) funp;
#endif
funp->fe = fe;
funp->num_free = num_free;
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 506bf383ca..6e9755ad48 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -3611,11 +3611,11 @@ BIF_RETTYPE list_to_pid_1(BIF_ALIST_1)
etp = (ExternalThing *) HAlloc(BIF_P, EXTERNAL_THING_HEAD_SIZE + 1);
etp->header = make_external_pid_header(1);
- etp->next = MSO(BIF_P).externals;
+ etp->next = MSO(BIF_P).first;
etp->node = enp;
etp->data.ui[0] = make_pid_data(c, b);
- MSO(BIF_P).externals = etp;
+ MSO(BIF_P).first = (struct erl_off_heap_header*) etp;
erts_deref_dist_entry(dep);
BIF_RET(make_external_pid(etp));
}
diff --git a/erts/emulator/beam/binary.c b/erts/emulator/beam/binary.c
index c68392fad4..3fd714f9c2 100644
--- a/erts/emulator/beam/binary.c
+++ b/erts/emulator/beam/binary.c
@@ -88,8 +88,8 @@ new_binary(Process *p, byte *buf, int len)
pb = (ProcBin *) HAlloc(p, PROC_BIN_SIZE);
pb->thing_word = HEADER_PROC_BIN;
pb->size = len;
- pb->next = MSO(p).mso;
- MSO(p).mso = pb;
+ pb->next = MSO(p).first;
+ MSO(p).first = (struct erl_off_heap_header*)pb;
pb->val = bptr;
pb->bytes = (byte*) bptr->orig_bytes;
pb->flags = 0;
@@ -127,8 +127,8 @@ Eterm erts_new_mso_binary(Process *p, byte *buf, int len)
pb = (ProcBin *) HAlloc(p, PROC_BIN_SIZE);
pb->thing_word = HEADER_PROC_BIN;
pb->size = len;
- pb->next = MSO(p).mso;
- MSO(p).mso = pb;
+ pb->next = MSO(p).first;
+ MSO(p).first = (struct erl_off_heap_header*)pb;
pb->val = bptr;
pb->bytes = (byte*) bptr->orig_bytes;
pb->flags = 0;
@@ -487,16 +487,6 @@ BIF_RETTYPE split_binary_2(BIF_ALIST_2)
BIF_ERROR(BIF_P, BADARG);
}
-void
-erts_cleanup_mso(ProcBin* pb)
-{
- while (pb != NULL) {
- ProcBin* next = pb->next;
- if (erts_refc_dectest(&pb->val->refc, 0) == 0)
- erts_bin_free(pb->val);
- pb = next;
- }
-}
/*
* Local functions.
diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c
index 857cb177c8..f339e19761 100644
--- a/erts/emulator/beam/break.c
+++ b/erts/emulator/beam/break.c
@@ -611,29 +611,29 @@ static void
bin_check(void)
{
Process *rp;
- ProcBin *bp;
- int i, printed;
+ struct erl_off_heap_header* hdr;
+ int i, printed = 0;
for (i=0; i < erts_max_processes; i++) {
if ((rp = process_tab[i]) == NULL)
continue;
- if (!(bp = rp->off_heap.mso))
- continue;
- printed = 0;
- while (bp) {
- if (printed == 0) {
- erts_printf("Process %T holding binary data \n", rp->id);
- printed = 1;
+ for (hdr = rp->off_heap.first; hdr; hdr = hdr->next) {
+ if (hdr->thing_word == HEADER_PROC_BIN) {
+ ProcBin *bp = (ProcBin*) hdr;
+ if (!printed) {
+ erts_printf("Process %T holding binary data \n", rp->id);
+ printed = 1;
+ }
+ erts_printf("0x%08lx orig_size: %ld, norefs = %ld\n",
+ (unsigned long)bp->val,
+ (long)bp->val->orig_size,
+ erts_smp_atomic_read(&bp->val->refc));
}
- erts_printf("0x%08lx orig_size: %ld, norefs = %ld\n",
- (unsigned long)bp->val,
- (long)bp->val->orig_size,
- erts_smp_atomic_read(&bp->val->refc));
-
- bp = bp->next;
}
- if (printed == 1)
+ if (printed) {
erts_printf("--------------------------------------\n");
+ printed = 0;
+ }
}
/* db_bin_check() has to be rewritten for the AVL trees... */
/*db_bin_check();*/
diff --git a/erts/emulator/beam/copy.c b/erts/emulator/beam/copy.c
index 521a1b1788..57be0169ba 100644
--- a/erts/emulator/beam/copy.c
+++ b/erts/emulator/beam/copy.c
@@ -314,9 +314,9 @@ copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
*argp = make_binary(hbot);
pb = (ProcBin*) hbot;
erts_refc_inc(&pb->val->refc, 2);
- pb->next = off_heap->mso;
+ pb->next = off_heap->first;
pb->flags = 0;
- off_heap->mso = pb;
+ off_heap->first = (struct erl_off_heap_header*) pb;
off_heap->overhead += pb->size / sizeof(Eterm);
}
break;
@@ -363,9 +363,9 @@ copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
to->val = from->val;
erts_refc_inc(&to->val->refc, 2);
to->bytes = from->bytes + offset;
- to->next = off_heap->mso;
+ to->next = off_heap->first;
to->flags = 0;
- off_heap->mso = to;
+ off_heap->first = (struct erl_off_heap_header*) to;
off_heap->overhead += to->size / sizeof(Eterm);
}
*argp = make_binary(hbot);
@@ -396,8 +396,8 @@ copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
}
#ifndef HYBRID /* FIND ME! */
funp = (ErlFunThing *) tp;
- funp->next = off_heap->funs;
- off_heap->funs = funp;
+ funp->next = off_heap->first;
+ off_heap->first = (struct erl_off_heap_header*) funp;
erts_refc_inc(&funp->fe->refc, 2);
#endif
*argp = make_fun(tp);
@@ -416,8 +416,8 @@ copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
*htop++ = *objp++;
}
- etp->next = off_heap->externals;
- off_heap->externals = etp;
+ etp->next = off_heap->first;
+ off_heap->first = (struct erl_off_heap_header*)etp;
erts_refc_inc(&etp->node->refc, 2);
*argp = make_external(tp);
@@ -650,8 +650,8 @@ Eterm copy_struct_lazy(Process *from, Eterm orig, Uint offs)
*hp++ = *objp++;
}
erts_refc_inc(&pb->val->refc, 2);
- pb->next = erts_global_offheap.mso;
- erts_global_offheap.mso = pb;
+ pb->next = erts_global_offheap.first;
+ erts_global_offheap.first = pb;
erts_global_offheap.overhead += pb->size / sizeof(Eterm);
continue;
}
@@ -672,9 +672,9 @@ Eterm copy_struct_lazy(Process *from, Eterm orig, Uint offs)
while (i--) {
*hp++ = *objp++;
}
-#ifndef HYBRID // FIND ME!
- funp->next = erts_global_offheap.funs;
- erts_global_offheap.funs = funp;
+#ifndef HYBRID /* FIND ME! */
+ funp->next = erts_global_offheap.first;
+ erts_global_offheap.first = funp;
erts_refc_inc(&funp->fe->refc, 2);
#endif
for (i = k; i < j; i++) {
@@ -718,8 +718,8 @@ Eterm copy_struct_lazy(Process *from, Eterm orig, Uint offs)
*hp++ = *objp++;
}
- etp->next = erts_global_offheap.externals;
- erts_global_offheap.externals = etp;
+ etp->next = erts_global_offheap.first;
+ erts_global_offheap.first = etp;
erts_refc_inc(&etp->node->refc, 2);
continue;
}
@@ -775,8 +775,8 @@ Eterm copy_struct_lazy(Process *from, Eterm orig, Uint offs)
to_bin->size = real_size;
to_bin->val = from_bin->val;
to_bin->bytes = from_bin->bytes + sub_offset;
- to_bin->next = erts_global_offheap.mso;
- erts_global_offheap.mso = to_bin;
+ to_bin->next = erts_global_offheap.first;
+ erts_global_offheap.first = to_bin;
erts_global_offheap.overhead += to_bin->size / sizeof(Eterm);
res_binary=make_binary(to_bin);
hp += PROC_BIN_SIZE;
@@ -910,57 +910,43 @@ copy_shallow(Eterm* ptr, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
break;
case REFC_BINARY_SUBTAG:
{
- ProcBin* pb = (ProcBin *) (hp-1);
- int tari = thing_arityval(val);
-
- sz -= tari;
- while (tari--) {
- *hp++ = *tp++;
- }
+ ProcBin* pb = (ProcBin *) (tp-1);
erts_refc_inc(&pb->val->refc, 2);
- pb->next = off_heap->mso;
- off_heap->mso = pb;
off_heap->overhead += pb->size / sizeof(Eterm);
}
- break;
+ goto off_heap_common;
+
case FUN_SUBTAG:
{
-#ifndef HYBRID /* FIND ME! */
- ErlFunThing* funp = (ErlFunThing *) (hp-1);
-#endif
- int tari = thing_arityval(val);
-
- sz -= tari;
- while (tari--) {
- *hp++ = *tp++;
- }
-#ifndef HYBRID /* FIND ME! */
- funp->next = off_heap->funs;
- off_heap->funs = funp;
+ ErlFunThing* funp = (ErlFunThing *) (tp-1);
erts_refc_inc(&funp->fe->refc, 2);
-#endif
}
- break;
+ goto off_heap_common;
+
case EXTERNAL_PID_SUBTAG:
case EXTERNAL_PORT_SUBTAG:
case EXTERNAL_REF_SUBTAG:
{
- ExternalThing* etp = (ExternalThing *) (hp-1);
+ ExternalThing* etp = (ExternalThing *) (tp-1);
+ erts_refc_inc(&etp->node->refc, 2);
+ }
+ off_heap_common:
+ {
+ struct erl_off_heap_header* ohh = (struct erl_off_heap_header*)(hp-1);
int tari = thing_arityval(val);
-
+
sz -= tari;
while (tari--) {
*hp++ = *tp++;
}
- etp->next = off_heap->externals;
- off_heap->externals = etp;
- erts_refc_inc(&etp->node->refc, 2);
+ ohh->next = off_heap->first;
+ off_heap->first = ohh;
}
break;
default:
{
int tari = header_arity(val);
-
+
sz -= tari;
while (tari--) {
*hp++ = *tp++;
@@ -1029,12 +1015,6 @@ void move_multi_frags(Eterm** hpp, ErlOffHeap* off_heap, ErlHeapFragment* first,
static void
move_one_frag(Eterm** hpp, Eterm* src, Uint src_sz, ErlOffHeap* off_heap)
{
- union {
- Uint *up;
- ProcBin *pbp;
- ErlFunThing *efp;
- ExternalThing *etp;
- } ohe;
Eterm* ptr = src;
Eterm* end = ptr + src_sz;
Eterm dummy_ref;
@@ -1046,23 +1026,17 @@ move_one_frag(Eterm** hpp, Eterm* src, Uint src_sz, ErlOffHeap* off_heap)
val = *ptr;
ASSERT(val != ERTS_HOLE_MARKER);
if (is_header(val)) {
+ struct erl_off_heap_header* hdr = (struct erl_off_heap_header*)hp;
ASSERT(ptr + header_arity(val) < end);
- ohe.up = hp;
MOVE_BOXED(ptr, val, hp, &dummy_ref);
switch (val & _HEADER_SUBTAG_MASK) {
case REFC_BINARY_SUBTAG:
- ohe.pbp->next = off_heap->mso;
- off_heap->mso = ohe.pbp;
- break;
case FUN_SUBTAG:
- ohe.efp->next = off_heap->funs;
- off_heap->funs = ohe.efp;
- break;
case EXTERNAL_PID_SUBTAG:
case EXTERNAL_PORT_SUBTAG:
case EXTERNAL_REF_SUBTAG:
- ohe.etp->next = off_heap->externals;
- off_heap->externals = ohe.etp;
+ hdr->next = off_heap->first;
+ off_heap->first = hdr;
break;
}
}
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index d465017949..16b6aeac3f 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -922,12 +922,8 @@ int erts_net_message(Port *prt,
UseTmpHeapNoproc(DIST_CTL_DEFAULT_SIZE);
/* Thanks to Luke Gorrie */
- off_heap.mso = NULL;
-#ifndef HYBRID /* FIND ME! */
- off_heap.funs = NULL;
-#endif
+ off_heap.first = NULL;
off_heap.overhead = 0;
- off_heap.externals = NULL;
ERTS_SMP_CHK_NO_PROC_LOCKS;
@@ -1434,16 +1430,8 @@ int erts_net_message(Port *prt,
}
}
- if (off_heap.mso) {
- erts_cleanup_mso(off_heap.mso);
- }
- if (off_heap.externals) {
- erts_cleanup_externals(off_heap.externals);
- }
+ erts_cleanup_offheap(&off_heap);
#ifndef HYBRID /* FIND ME! */
- if (off_heap.funs) {
- erts_cleanup_funs(off_heap.funs);
- }
if (ctl != ctl_default) {
erts_free(ERTS_ALC_T_DCTRL_BUF, (void *) ctl);
}
@@ -1453,16 +1441,8 @@ int erts_net_message(Port *prt,
return 0;
data_error:
- if (off_heap.mso) {
- erts_cleanup_mso(off_heap.mso);
- }
- if (off_heap.externals) {
- erts_cleanup_externals(off_heap.externals);
- }
+ erts_cleanup_offheap(&off_heap);
#ifndef HYBRID /* FIND ME! */
- if (off_heap.funs) {
- erts_cleanup_funs(off_heap.funs);
- }
if (ctl != ctl_default) {
erts_free(ERTS_ALC_T_DCTRL_BUF, (void *) ctl);
}
diff --git a/erts/emulator/beam/erl_bif_binary.c b/erts/emulator/beam/erl_bif_binary.c
index 82f1e06e8e..1d8fd11b7b 100644
--- a/erts/emulator/beam/erl_bif_binary.c
+++ b/erts/emulator/beam/erl_bif_binary.c
@@ -2511,8 +2511,8 @@ BIF_RETTYPE binary_copy_trap(BIF_ALIST_2)
pb = (ProcBin *) HAlloc(BIF_P, PROC_BIN_SIZE);
pb->thing_word = HEADER_PROC_BIN;
pb->size = target_size;
- pb->next = MSO(BIF_P).mso;
- MSO(BIF_P).mso = pb;
+ pb->next = MSO(BIF_P).first;
+ MSO(BIF_P).first = (struct erl_off_heap_header*) pb;
pb->val = save;
pb->bytes = t;
pb->flags = 0;
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 48cda52612..ca1ab44012 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -122,22 +122,26 @@ static char erts_system_version[] = ("Erlang " ERLANG_OTP_RELEASE
#endif
static Eterm
-bld_bin_list(Uint **hpp, Uint *szp, ProcBin* pb)
+bld_bin_list(Uint **hpp, Uint *szp, ErlOffHeap* oh)
{
+ struct erl_off_heap_header* ohh;
Eterm res = NIL;
Eterm tuple;
- for (; pb; pb = pb->next) {
- Eterm val = erts_bld_uword(hpp, szp, (UWord) pb->val);
- Eterm orig_size = erts_bld_uint(hpp, szp, pb->val->orig_size);
-
- if (szp)
- *szp += 4+2;
- if (hpp) {
- Uint refc = (Uint) erts_smp_atomic_read(&pb->val->refc);
- tuple = TUPLE3(*hpp, val, orig_size, make_small(refc));
- res = CONS(*hpp + 4, tuple, res);
- *hpp += 4+2;
+ for (ohh = oh->first; ohh; ohh = ohh->next) {
+ if (ohh->thing_word == HEADER_PROC_BIN) {
+ ProcBin* pb = (ProcBin*) ohh;
+ Eterm val = erts_bld_uword(hpp, szp, (UWord) pb->val);
+ Eterm orig_size = erts_bld_uint(hpp, szp, pb->val->orig_size);
+
+ if (szp)
+ *szp += 4+2;
+ if (hpp) {
+ Uint refc = (Uint) erts_smp_atomic_read(&pb->val->refc);
+ tuple = TUPLE3(*hpp, val, orig_size, make_small(refc));
+ res = CONS(*hpp + 4, tuple, res);
+ *hpp += 4+2;
+ }
}
}
return res;
@@ -176,10 +180,10 @@ static void do_make_one_mon_element(ErtsMonitor *mon, void * vpmlc)
Eterm tup;
Eterm r = (IS_CONST(mon->ref)
? mon->ref
- : STORE_NC(&(pmlc->hp), &MSO(pmlc->p).externals, mon->ref));
+ : STORE_NC(&(pmlc->hp), &MSO(pmlc->p), mon->ref));
Eterm p = (IS_CONST(mon->pid)
? mon->pid
- : STORE_NC(&(pmlc->hp), &MSO(pmlc->p).externals, mon->pid));
+ : STORE_NC(&(pmlc->hp), &MSO(pmlc->p), mon->pid));
tup = TUPLE5(pmlc->hp, pmlc->tag, make_small(mon->type), r, p, mon->name);
pmlc->hp += 6;
pmlc->res = CONS(pmlc->hp, tup, pmlc->res);
@@ -240,7 +244,7 @@ static void do_make_one_lnk_element(ErtsLink *lnk, void * vpllc)
Eterm old_res, targets = NIL;
Eterm p = (IS_CONST(lnk->pid)
? lnk->pid
- : STORE_NC(&(pllc->hp), &MSO(pllc->p).externals, lnk->pid));
+ : STORE_NC(&(pllc->hp), &MSO(pllc->p), lnk->pid));
if (lnk->type == LINK_NODE) {
targets = make_small(ERTS_LINK_REFC(lnk));
} else if (ERTS_LINK_ROOT(lnk) != NULL) {
@@ -1225,7 +1229,7 @@ process_info_aux(Process *BIF_P,
hp = HAlloc(BIF_P, 3 + mic.sz);
res = NIL;
for (i = 0; i < mic.mi_i; i++) {
- item = STORE_NC(&hp, &MSO(BIF_P).externals, mic.mi[i].entity);
+ item = STORE_NC(&hp, &MSO(BIF_P), mic.mi[i].entity);
res = CONS(hp, item, res);
hp += 2;
}
@@ -1258,9 +1262,7 @@ process_info_aux(Process *BIF_P,
else {
/* Monitor by pid. Build {process, Pid} and cons it. */
Eterm t;
- Eterm pid = STORE_NC(&hp,
- &MSO(BIF_P).externals,
- mic.mi[i].entity);
+ Eterm pid = STORE_NC(&hp, &MSO(BIF_P), mic.mi[i].entity);
t = TUPLE2(hp, am_process, pid);
hp += 3;
res = CONS(hp, t, res);
@@ -1282,7 +1284,7 @@ process_info_aux(Process *BIF_P,
res = NIL;
for (i = 0; i < mic.mi_i; ++i) {
- item = STORE_NC(&hp, &MSO(BIF_P).externals, mic.mi[i].entity);
+ item = STORE_NC(&hp, &MSO(BIF_P), mic.mi[i].entity);
res = CONS(hp, item, res);
hp += 2;
}
@@ -1491,7 +1493,7 @@ process_info_aux(Process *BIF_P,
case am_group_leader: {
int sz = NC_HEAP_SIZE(rp->group_leader);
hp = HAlloc(BIF_P, 3 + sz);
- res = STORE_NC(&hp, &MSO(BIF_P).externals, rp->group_leader);
+ res = STORE_NC(&hp, &MSO(BIF_P), rp->group_leader);
break;
}
@@ -1516,9 +1518,9 @@ process_info_aux(Process *BIF_P,
case am_binary: {
Uint sz = 3;
- (void) bld_bin_list(NULL, &sz, MSO(rp).mso);
+ (void) bld_bin_list(NULL, &sz, &MSO(rp));
hp = HAlloc(BIF_P, sz);
- res = bld_bin_list(&hp, NULL, MSO(rp).mso);
+ res = bld_bin_list(&hp, NULL, &MSO(rp));
break;
}
@@ -2678,7 +2680,7 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
hp = HAlloc(BIF_P, 3 + mic.sz);
res = NIL;
for (i = 0; i < mic.mi_i; i++) {
- item = STORE_NC(&hp, &MSO(BIF_P).externals, mic.mi[i].entity);
+ item = STORE_NC(&hp, &MSO(BIF_P), mic.mi[i].entity);
res = CONS(hp, item, res);
hp += 2;
}
@@ -2698,7 +2700,7 @@ BIF_RETTYPE port_info_2(BIF_ALIST_2)
res = NIL;
for (i = 0; i < mic.mi_i; i++) {
Eterm t;
- item = STORE_NC(&hp, &MSO(BIF_P).externals, mic.mi[i].entity);
+ item = STORE_NC(&hp, &MSO(BIF_P), mic.mi[i].entity);
t = TUPLE2(hp, am_process, item);
hp += 3;
res = CONS(hp, t, res);
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index 443cac9033..0509e51a6f 100644
--- a/erts/emulator/beam/erl_bif_trace.c
+++ b/erts/emulator/beam/erl_bif_trace.c
@@ -2161,7 +2161,7 @@ trace_delivered_1(BIF_ALIST_1)
#ifdef ERTS_SMP
bp = new_message_buffer(REF_THING_SIZE + 4);
hp = &bp->mem[0];
- msg_ref = STORE_NC(&hp, &bp->off_heap.externals, ref);
+ msg_ref = STORE_NC(&hp, &bp->off_heap, ref);
#else
hp = HAlloc(BIF_P, 4);
msg_ref = ref;
diff --git a/erts/emulator/beam/erl_bits.c b/erts/emulator/beam/erl_bits.c
index defe18c92b..96faa673f6 100644
--- a/erts/emulator/beam/erl_bits.c
+++ b/erts/emulator/beam/erl_bits.c
@@ -1335,8 +1335,8 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term,
hp += PROC_BIN_SIZE;
pb->thing_word = HEADER_PROC_BIN;
pb->size = used_size_in_bytes;
- pb->next = MSO(c_p).mso;
- MSO(c_p).mso = pb;
+ pb->next = MSO(c_p).first;
+ MSO(c_p).first = (struct erl_off_heap_header*)pb;
pb->val = bptr;
pb->bytes = (byte*) bptr->orig_bytes;
pb->flags = PB_IS_WRITABLE | PB_ACTIVE_WRITER;
@@ -1506,8 +1506,8 @@ erts_bs_init_writable(Process* p, Eterm sz)
hp += PROC_BIN_SIZE;
pb->thing_word = HEADER_PROC_BIN;
pb->size = 0;
- pb->next = MSO(p).mso;
- MSO(p).mso = pb;
+ pb->next = MSO(p).first;
+ MSO(p).first = (struct erl_off_heap_header*) pb;
pb->val = bptr;
pb->bytes = (byte*) bptr->orig_bytes;
pb->flags = PB_IS_WRITABLE | PB_ACTIVE_WRITER;
diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c
index 124129a371..96008ccef0 100644
--- a/erts/emulator/beam/erl_db_hash.c
+++ b/erts/emulator/beam/erl_db_hash.c
@@ -2751,11 +2751,7 @@ static void db_finalize_dbterm_hash(DbUpdateHandle* handle)
newDbTerm = &newp->dbterm;
newDbTerm->size = handle->new_size;
- newDbTerm->off_heap.mso = NULL;
- newDbTerm->off_heap.externals = NULL;
- #ifndef HYBRID /* FIND ME! */
- newDbTerm->off_heap.funs = NULL;
- #endif
+ newDbTerm->off_heap.first = NULL;
newDbTerm->off_heap.overhead = 0;
/* make a flat copy */
diff --git a/erts/emulator/beam/erl_db_tree.c b/erts/emulator/beam/erl_db_tree.c
index b6b3cabafe..da2696163a 100644
--- a/erts/emulator/beam/erl_db_tree.c
+++ b/erts/emulator/beam/erl_db_tree.c
@@ -1081,11 +1081,12 @@ static int db_select_continue_tree(Process *p,
static int db_select_tree(Process *p, DbTable *tbl,
Eterm pattern, int reverse, Eterm *ret)
{
+ /* Strategy: Traverse backwards to build resulting list from tail to head */
DbTableTree *tb = &tbl->tree;
DbTreeStack* stack;
struct select_context sc;
struct mp_info mpi;
- Eterm lastkey = NIL;
+ Eterm lastkey = THE_NON_VALUE;
Eterm key;
Eterm continuation;
unsigned sz;
@@ -1293,7 +1294,7 @@ static int db_select_count_tree(Process *p, DbTable *tbl,
DbTreeStack* stack;
struct select_count_context sc;
struct mp_info mpi;
- Eterm lastkey = NIL;
+ Eterm lastkey = THE_NON_VALUE;
Eterm key;
Eterm continuation;
unsigned sz;
@@ -1395,7 +1396,7 @@ static int db_select_chunk_tree(Process *p, DbTable *tbl,
DbTreeStack* stack;
struct select_context sc;
struct mp_info mpi;
- Eterm lastkey = NIL;
+ Eterm lastkey = THE_NON_VALUE;
Eterm key;
Eterm continuation;
unsigned sz;
@@ -1636,7 +1637,7 @@ static int db_select_delete_tree(Process *p, DbTable *tbl,
DbTableTree *tb = &tbl->tree;
struct select_delete_context sc;
struct mp_info mpi;
- Eterm lastkey = NIL;
+ Eterm lastkey = THE_NON_VALUE;
Eterm key;
Eterm continuation;
unsigned sz;
@@ -2588,11 +2589,7 @@ static void db_finalize_dbterm_tree(DbUpdateHandle* handle)
newDbTerm = &newp->dbterm;
newDbTerm->size = handle->new_size;
- newDbTerm->off_heap.mso = NULL;
- newDbTerm->off_heap.externals = NULL;
- #ifndef HYBRID /* FIND ME! */
- newDbTerm->off_heap.funs = NULL;
- #endif
+ newDbTerm->off_heap.first = NULL;
newDbTerm->off_heap.overhead = 0;
/* make a flat copy */
@@ -2628,7 +2625,7 @@ static void traverse_backwards(DbTableTree *tb,
{
TreeDbTerm *this, *next;
- if (lastkey == NIL) {
+ if (lastkey == THE_NON_VALUE) {
stack->pos = stack->slot = 0;
if (( this = tb->root ) == NULL) {
return;
@@ -2666,7 +2663,7 @@ static void traverse_forward(DbTableTree *tb,
{
TreeDbTerm *this, *next;
- if (lastkey == NIL) {
+ if (lastkey == THE_NON_VALUE) {
stack->pos = stack->slot = 0;
if (( this = tb->root ) == NULL) {
return;
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index 93a47eb76f..48e0080525 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -363,12 +363,7 @@ static ErtsMatchPseudoProcess *match_pseudo_process;
static ERTS_INLINE void
cleanup_match_pseudo_process(ErtsMatchPseudoProcess *mpsp, int keep_heap)
{
- if (mpsp->process.mbuf
- || mpsp->process.off_heap.mso
-#ifndef HYBRID /* FIND ME! */
- || mpsp->process.off_heap.funs
-#endif
- || mpsp->process.off_heap.externals) {
+ if (mpsp->process.mbuf || mpsp->process.off_heap.first) {
erts_cleanup_empty_process(&mpsp->process);
}
#ifdef DEBUG
@@ -2495,11 +2490,7 @@ void* db_get_term(DbTableCommon *tb, DbTerm* old, Uint offset, Eterm obj)
p = (DbTerm*) ((void *)(((char *) structp) + offset));
}
p->size = size;
- p->off_heap.mso = NULL;
- p->off_heap.externals = NULL;
-#ifndef HYBRID /* FIND ME! */
- p->off_heap.funs = NULL;
-#endif
+ p->off_heap.first = NULL;
p->off_heap.overhead = 0;
top = DBTERM_BUF(p);
diff --git a/erts/emulator/beam/erl_fun.c b/erts/emulator/beam/erl_fun.c
index 15d9538301..1f74393a96 100644
--- a/erts/emulator/beam/erl_fun.c
+++ b/erts/emulator/beam/erl_fun.c
@@ -192,20 +192,6 @@ erts_erase_fun_entry(ErlFunEntry* fe)
erts_fun_write_unlock();
}
-#ifndef HYBRID /* FIND ME! */
-void
-erts_cleanup_funs(ErlFunThing* funp)
-{
- while (funp) {
- ErlFunEntry* fe = funp->fe;
- if (erts_refc_dectest(&fe->refc, 0) == 0) {
- erts_erase_fun_entry(fe);
- }
- funp = funp->next;
- }
-}
-#endif
-
void
erts_cleanup_funs_on_purge(BeamInstr* start, BeamInstr* end)
{
diff --git a/erts/emulator/beam/erl_fun.h b/erts/emulator/beam/erl_fun.h
index 944d4b3df5..2f165afa06 100644
--- a/erts/emulator/beam/erl_fun.h
+++ b/erts/emulator/beam/erl_fun.h
@@ -53,10 +53,10 @@ typedef struct erl_fun_entry {
typedef struct erl_fun_thing {
Eterm thing_word; /* Subtag FUN_SUBTAG. */
+ ErlFunEntry* fe; /* Pointer to fun entry. */
#ifndef HYBRID /* FIND ME! */
- struct erl_fun_thing* next; /* Next fun in mso list. */
+ struct erl_off_heap_header* next;
#endif
- ErlFunEntry* fe; /* Pointer to fun entry. */
#ifdef HIPE
UWord* native_address; /* Native code for the fun. */
#endif
diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c
index a19e090f1e..adc50675bf 100644
--- a/erts/emulator/beam/erl_gc.c
+++ b/erts/emulator/beam/erl_gc.c
@@ -110,9 +110,7 @@ static Uint adjust_after_fullsweep(Process *p, int size_before,
int need, Eterm *objv, int nobj);
static void shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj);
static void grow_new_heap(Process *p, Uint new_sz, Eterm* objv, int nobj);
-static void sweep_proc_bins(Process *p, int fullsweep);
-static void sweep_proc_funs(Process *p, int fullsweep);
-static void sweep_proc_externals(Process *p, int fullsweep);
+static void sweep_off_heap(Process *p, int fullsweep);
static void offset_heap(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size);
static void offset_heap_ptr(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size);
static void offset_rootset(Process *p, Sint offs, char* area, Uint area_size,
@@ -145,6 +143,16 @@ erts_init_gc(void)
{
int i = 0;
+ ASSERT(offsetof(ProcBin,thing_word) == offsetof(struct erl_off_heap_header,thing_word));
+ ASSERT(offsetof(ProcBin,thing_word) == offsetof(ErlFunThing,thing_word));
+ ASSERT(offsetof(ProcBin,thing_word) == offsetof(ExternalThing,header));
+ ASSERT(offsetof(ProcBin,size) == offsetof(struct erl_off_heap_header,size));
+ ASSERT(offsetof(ProcBin,size) == offsetof(ErlSubBin,size));
+ ASSERT(offsetof(ProcBin,size) == offsetof(ErlHeapBin,size));
+ ASSERT(offsetof(ProcBin,next) == offsetof(struct erl_off_heap_header,next));
+ ASSERT(offsetof(ProcBin,next) == offsetof(ErlFunThing,next));
+ ASSERT(offsetof(ProcBin,next) == offsetof(ExternalThing,next));
+
erts_smp_spinlock_init(&info_lck, "gc_info");
garbage_cols = 0;
reclaimed = 0;
@@ -286,25 +294,14 @@ erts_offset_heap_ptr(Eterm* hp, Uint sz, Sint offs,
offset_heap_ptr(hp, sz, offs, (char *) low, ((char *)high)-((char *)low));
}
+
#define ptr_within(ptr, low, high) ((ptr) < (high) && (ptr) >= (low))
void
erts_offset_off_heap(ErlOffHeap *ohp, Sint offs, Eterm* low, Eterm* high)
{
- if (ohp->mso && ptr_within((Eterm *)ohp->mso, low, high)) {
- Eterm** uptr = (Eterm**) (void *) &ohp->mso;
- *uptr += offs;
- }
-
-#ifndef HYBRID /* FIND ME! */
- if (ohp->funs && ptr_within((Eterm *)ohp->funs, low, high)) {
- Eterm** uptr = (Eterm**) (void *) &ohp->funs;
- *uptr += offs;
- }
-#endif
-
- if (ohp->externals && ptr_within((Eterm *)ohp->externals, low, high)) {
- Eterm** uptr = (Eterm**) (void *) &ohp->externals;
+ if (ohp->first && ptr_within((Eterm *)ohp->first, low, high)) {
+ Eterm** uptr = (Eterm**) (void *) &ohp->first;
*uptr += offs;
}
}
@@ -504,14 +501,8 @@ erts_garbage_collect_hibernate(Process* p)
cleanup_rootset(&rootset);
- if (MSO(p).mso) {
- sweep_proc_bins(p, 1);
- }
- if (MSO(p).funs) {
- sweep_proc_funs(p, 1);
- }
- if (MSO(p).externals) {
- sweep_proc_externals(p, 1);
+ if (MSO(p).first) {
+ sweep_off_heap(p, 1);
}
/*
@@ -1041,15 +1032,8 @@ do_minor(Process *p, int new_sz, Eterm* objv, int nobj)
OLD_HTOP(p) = old_htop;
HIGH_WATER(p) = (HEAP_START(p) != HIGH_WATER(p)) ? n_heap : n_htop;
- if (MSO(p).mso) {
- sweep_proc_bins(p, 0);
- }
-
- if (MSO(p).funs) {
- sweep_proc_funs(p, 0);
- }
- if (MSO(p).externals) {
- sweep_proc_externals(p, 0);
+ if (MSO(p).first) {
+ sweep_off_heap(p, 0);
}
#ifdef HARDDEBUG
@@ -1271,17 +1255,11 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
}
}
- if (MSO(p).mso) {
- sweep_proc_bins(p, 1);
- }
- if (MSO(p).funs) {
- sweep_proc_funs(p, 1);
- }
- if (MSO(p).externals) {
- sweep_proc_externals(p, 1);
+ if (MSO(p).first) {
+ sweep_off_heap(p, 1);
}
- if (OLD_HEAP(p) != NULL) {
+ if (OLD_HEAP(p) != NULL) {
ERTS_HEAP_FREE(ERTS_ALC_T_OLD_HEAP,
OLD_HEAP(p),
(OLD_HEND(p) - OLD_HEAP(p)) * sizeof(Eterm));
@@ -1305,6 +1283,7 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
HIGH_WATER(p) = HEAP_TOP(p);
ErtsGcQuickSanityCheck(p);
+
/*
* Copy newly received message onto the end of the new heap.
*/
@@ -2044,108 +2023,24 @@ next_vheap_size(Process* p, Uint vheap, Uint vheap_sz) {
return vheap_sz < p->min_vheap_size ? p->min_vheap_size : vheap_sz;
}
-static void
-sweep_proc_externals(Process *p, int fullsweep)
-{
- ExternalThing** prev;
- ExternalThing* ptr;
- char* oh = 0;
- Uint oh_size = 0;
-
- if (fullsweep == 0) {
- oh = (char *) OLD_HEAP(p);
- oh_size = (char *) OLD_HEND(p) - oh;
- }
-
- prev = &MSO(p).externals;
- ptr = MSO(p).externals;
-
- while (ptr) {
- Eterm* ppt = (Eterm *) ptr;
-
- if (IS_MOVED_BOXED(*ppt)) { /* Object is alive */
- ExternalThing* ro = external_thing_ptr(*ppt);
-
- *prev = ro; /* Patch to moved pos */
- prev = &ro->next;
- ptr = ro->next;
- } else if (in_area(ppt, oh, oh_size)) {
- /*
- * Object resides on old heap, and we just did a
- * generational collection - keep object in list.
- */
- prev = &ptr->next;
- ptr = ptr->next;
- } else { /* Object has not been moved - deref it */
- erts_deref_node_entry(ptr->node);
- *prev = ptr = ptr->next;
- }
- }
- ASSERT(*prev == NULL);
-}
-
-static void
-sweep_proc_funs(Process *p, int fullsweep)
-{
- ErlFunThing** prev;
- ErlFunThing* ptr;
- char* oh = 0;
- Uint oh_size = 0;
-
- if (fullsweep == 0) {
- oh = (char *) OLD_HEAP(p);
- oh_size = (char *) OLD_HEND(p) - oh;
- }
-
- prev = &MSO(p).funs;
- ptr = MSO(p).funs;
-
- while (ptr) {
- Eterm* ppt = (Eterm *) ptr;
-
- if (IS_MOVED_BOXED(*ppt)) { /* Object is alive */
- ErlFunThing* ro = (ErlFunThing *) fun_val(*ppt);
-
- *prev = ro; /* Patch to moved pos */
- prev = &ro->next;
- ptr = ro->next;
- } else if (in_area(ppt, oh, oh_size)) {
- /*
- * Object resides on old heap, and we just did a
- * generational collection - keep object in list.
- */
- prev = &ptr->next;
- ptr = ptr->next;
- } else { /* Object has not been moved - deref it */
- ErlFunEntry* fe = ptr->fe;
-
- *prev = ptr = ptr->next;
- if (erts_refc_dectest(&fe->refc, 0) == 0) {
- erts_erase_fun_entry(fe);
- }
- }
- }
- ASSERT(*prev == NULL);
-}
-
struct shrink_cand_data {
- ProcBin* new_candidates;
- ProcBin* new_candidates_end;
- ProcBin* old_candidates;
+ struct erl_off_heap_header* new_candidates;
+ struct erl_off_heap_header* new_candidates_end;
+ struct erl_off_heap_header* old_candidates;
Uint no_of_candidates;
Uint no_of_active;
};
static ERTS_INLINE void
link_live_proc_bin(struct shrink_cand_data *shrink,
- ProcBin ***prevppp,
- ProcBin **pbpp,
+ struct erl_off_heap_header*** prevppp,
+ struct erl_off_heap_header** currpp,
int new_heap)
{
- ProcBin *pbp = *pbpp;
-
- *pbpp = pbp->next;
+ ProcBin *pbp = (ProcBin*) *currpp;
+ ASSERT(**prevppp == *currpp);
+ *currpp = pbp->next;
if (pbp->flags & (PB_ACTIVE_WRITER|PB_IS_WRITABLE)) {
ASSERT(((pbp->flags & (PB_ACTIVE_WRITER|PB_IS_WRITABLE))
== (PB_ACTIVE_WRITER|PB_IS_WRITABLE))
@@ -2162,15 +2057,16 @@ link_live_proc_bin(struct shrink_cand_data *shrink,
/* Our allocators are 8 byte aligned, i.e., shrinking with
less than 8 bytes will have no real effect */
if (unused >= 8) { /* A shrink candidate; save in candidate list */
+ **prevppp = pbp->next;
if (new_heap) {
if (!shrink->new_candidates)
- shrink->new_candidates_end = pbp;
+ shrink->new_candidates_end = (struct erl_off_heap_header*)pbp;
pbp->next = shrink->new_candidates;
- shrink->new_candidates = pbp;
+ shrink->new_candidates = (struct erl_off_heap_header*)pbp;
}
else {
pbp->next = shrink->old_candidates;
- shrink->old_candidates = pbp;
+ shrink->old_candidates = (struct erl_off_heap_header*)pbp;
}
shrink->no_of_candidates++;
return;
@@ -2178,67 +2074,101 @@ link_live_proc_bin(struct shrink_cand_data *shrink,
}
}
- /* Not a shrink candidate; keep in original mso list */
- **prevppp = pbp;
+ /* Not a shrink candidate; keep in original mso list */
*prevppp = &pbp->next;
-
}
static void
-sweep_proc_bins(Process *p, int fullsweep)
+sweep_off_heap(Process *p, int fullsweep)
{
struct shrink_cand_data shrink = {0};
- ProcBin** prev;
- ProcBin* ptr;
- Binary* bptr;
- char* oh = NULL;
- Uint oh_size = 0;
+ struct erl_off_heap_header* ptr;
+ struct erl_off_heap_header** prev;
+ char* oheap = NULL;
+ Uint oheap_sz = 0;
Uint bin_vheap = 0;
+#ifdef DEBUG
+ int seen_mature = 0;
+#endif
if (fullsweep == 0) {
- oh = (char *) OLD_HEAP(p);
- oh_size = (char *) OLD_HEND(p) - oh;
+ oheap = (char *) OLD_HEAP(p);
+ oheap_sz = (char *) OLD_HEND(p) - oheap;
}
BIN_OLD_VHEAP(p) = 0;
- prev = &MSO(p).mso;
- ptr = MSO(p).mso;
+ prev = &MSO(p).first;
+ ptr = MSO(p).first;
- /*
- * Note: In R7 we no longer force a fullsweep when we find binaries
- * on the old heap. The reason is that with the introduction of the
- * bit syntax we can expect binaries to be used a lot more. Note that
- * in earlier releases a brand new binary (or any other term) could
- * be put on the old heap during a gen-gc fullsweep, but this is
- * no longer the case in R7.
+ /* Firts part of the list will reside on the (old) new-heap.
+ * Keep if moved, otherwise deref.
*/
while (ptr) {
- Eterm* ppt = (Eterm *) ptr;
-
- if (IS_MOVED_BOXED(*ppt)) { /* Object is alive */
- bin_vheap += ptr->size / sizeof(Eterm);
- ptr = (ProcBin*) binary_val(*ppt);
- link_live_proc_bin(&shrink,
- &prev,
- &ptr,
- !in_area(ptr, oh, oh_size));
- } else if (in_area(ppt, oh, oh_size)) {
- /*
- * Object resides on old heap, and we just did a
- * generational collection - keep object in list.
- */
- BIN_OLD_VHEAP(p) += ptr->size / sizeof(Eterm); /* for binary gc (words)*/
- link_live_proc_bin(&shrink, &prev, &ptr, 0);
- } else { /* Object has not been moved - deref it */
-
- *prev = ptr->next;
- bptr = ptr->val;
- if (erts_refc_dectest(&bptr->refc, 0) == 0)
- erts_bin_free(bptr);
- ptr = *prev;
- }
+ if (IS_MOVED_BOXED(ptr->thing_word)) {
+ ASSERT(!in_area(ptr, oheap, oheap_sz));
+ *prev = ptr = (struct erl_off_heap_header*) boxed_val(ptr->thing_word);
+ ASSERT(!IS_MOVED_BOXED(ptr->thing_word));
+ if (ptr->thing_word == HEADER_PROC_BIN) {
+ int to_new_heap = !in_area(ptr, oheap, oheap_sz);
+ ASSERT(to_new_heap == !seen_mature || (!to_new_heap && (seen_mature=1)));
+ if (to_new_heap) {
+ bin_vheap += ptr->size / sizeof(Eterm);
+ } else {
+ BIN_OLD_VHEAP(p) += ptr->size / sizeof(Eterm); /* for binary gc (words)*/
+ }
+ link_live_proc_bin(&shrink, &prev, &ptr, to_new_heap);
+ }
+ else {
+ prev = &ptr->next;
+ ptr = ptr->next;
+ }
+ }
+ else if (!in_area(ptr, oheap, oheap_sz)) {
+ /* garbage */
+ switch (thing_subtag(ptr->thing_word)) {
+ case REFC_BINARY_SUBTAG:
+ {
+ Binary* bptr = ((ProcBin*)ptr)->val;
+ if (erts_refc_dectest(&bptr->refc, 0) == 0) {
+ erts_bin_free(bptr);
+ }
+ break;
+ }
+ case FUN_SUBTAG:
+ {
+ ErlFunEntry* fe = ((ErlFunThing*)ptr)->fe;
+ if (erts_refc_dectest(&fe->refc, 0) == 0) {
+ erts_erase_fun_entry(fe);
+ }
+ break;
+ }
+ default:
+ ASSERT(is_external_header(ptr->thing_word));
+ erts_deref_node_entry(((ExternalThing*)ptr)->node);
+ }
+ *prev = ptr = ptr->next;
+ }
+ else break; /* and let old-heap loop continue */
+ }
+
+ /* The rest of the list resides on old-heap, and we just did a
+ * generational collection - keep objects in list.
+ */
+ while (ptr) {
+ ASSERT(in_area(ptr, oheap, oheap_sz));
+ ASSERT(!IS_MOVED_BOXED(ptr->thing_word));
+ if (ptr->thing_word == HEADER_PROC_BIN) {
+ BIN_OLD_VHEAP(p) += ptr->size / sizeof(Eterm); /* for binary gc (words)*/
+ link_live_proc_bin(&shrink, &prev, &ptr, 0);
+ }
+ else {
+ ASSERT(is_fun_header(ptr->thing_word) ||
+ is_external_header(ptr->thing_word));
+ prev = &ptr->next;
+ ptr = ptr->next;
+ }
}
if (BIN_OLD_VHEAP(p) >= BIN_OLD_VHEAP_SZ(p)) {
@@ -2254,7 +2184,8 @@ sweep_proc_bins(Process *p, int fullsweep)
*/
if (shrink.no_of_candidates) {
- ProcBin *candlist[] = {shrink.new_candidates, shrink.old_candidates};
+ ProcBin *candlist[] = { (ProcBin*)shrink.new_candidates,
+ (ProcBin*)shrink.old_candidates };
Uint leave_unused = 0;
int i;
@@ -2266,21 +2197,21 @@ sweep_proc_bins(Process *p, int fullsweep)
}
for (i = 0; i < sizeof(candlist)/sizeof(candlist[0]); i++) {
-
- for (ptr = candlist[i]; ptr; ptr = ptr->next) {
- Uint new_size = ptr->size;
+ ProcBin* pb;
+ for (pb = candlist[i]; pb; pb = (ProcBin*)pb->next) {
+ Uint new_size = pb->size;
if (leave_unused) {
new_size += (new_size * 100) / leave_unused;
/* Our allocators are 8 byte aligned, i.e., shrinking with
less than 8 bytes will have no real effect */
- if (new_size + 8 >= ptr->val->orig_size)
+ if (new_size + 8 >= pb->val->orig_size)
continue;
}
- ptr->val = erts_bin_realloc(ptr->val, new_size);
- ptr->val->orig_size = new_size;
- ptr->bytes = (byte *) ptr->val->orig_bytes;
+ pb->val = erts_bin_realloc(pb->val, new_size);
+ pb->val->orig_size = new_size;
+ pb->bytes = (byte *) pb->val->orig_bytes;
}
}
@@ -2289,21 +2220,20 @@ sweep_proc_bins(Process *p, int fullsweep)
* We now potentially have the mso list divided into three lists:
* - shrink candidates on new heap (inactive writable with unused data)
* - shrink candidates on old heap (inactive writable with unused data)
- * - other binaries (read only + active writable ...)
+ * - other binaries (read only + active writable ...) + funs and externals
*
* Put them back together: new candidates -> other -> old candidates
* This order will ensure that the list only refers from new
* generation to old and never from old to new *which is important*.
*/
if (shrink.new_candidates) {
- if (prev == &MSO(p).mso) /* empty other binaries list */
+ if (prev == &MSO(p).first) /* empty other binaries list */
prev = &shrink.new_candidates_end->next;
else
- shrink.new_candidates_end->next = MSO(p).mso;
- MSO(p).mso = shrink.new_candidates;
+ shrink.new_candidates_end->next = MSO(p).first;
+ MSO(p).first = shrink.new_candidates;
}
}
-
*prev = shrink.old_candidates;
}
@@ -2334,15 +2264,17 @@ offset_heap(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size)
tari = thing_arityval(val);
switch (thing_subtag(val)) {
case REFC_BINARY_SUBTAG:
+ case FUN_SUBTAG:
+ case EXTERNAL_PID_SUBTAG:
+ case EXTERNAL_PORT_SUBTAG:
+ case EXTERNAL_REF_SUBTAG:
{
- ProcBin* pb = (ProcBin*) hp;
- Eterm** uptr = (Eterm **) (void *) &pb->next;
+ struct erl_off_heap_header* oh = (struct erl_off_heap_header*) hp;
- if (*uptr && in_area((Eterm *)pb->next, area, area_size)) {
+ if (in_area(oh->next, area, area_size)) {
+ Eterm** uptr = (Eterm **) (void *) &oh->next;
*uptr += offs; /* Patch the mso chain */
}
- sz -= tari;
- hp += tari + 1;
}
break;
case BIN_MATCHSTATE_SUBTAG:
@@ -2353,40 +2285,11 @@ offset_heap(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size)
mb->orig = offset_ptr(mb->orig, offs);
mb->base = binary_bytes(mb->orig);
}
- sz -= tari;
- hp += tari + 1;
}
break;
- case FUN_SUBTAG:
- {
- ErlFunThing* funp = (ErlFunThing *) hp;
- Eterm** uptr = (Eterm **) (void *) &funp->next;
-
- if (*uptr && in_area((Eterm *)funp->next, area, area_size)) {
- *uptr += offs;
- }
- sz -= tari;
- hp += tari + 1;
- }
- break;
- case EXTERNAL_PID_SUBTAG:
- case EXTERNAL_PORT_SUBTAG:
- case EXTERNAL_REF_SUBTAG:
- {
- ExternalThing* etp = (ExternalThing *) hp;
- Eterm** uptr = (Eterm **) (void *) &etp->next;
-
- if (*uptr && in_area((Eterm *)etp->next, area, area_size)) {
- *uptr += offs;
- }
- sz -= tari;
- hp += tari + 1;
- }
- break;
- default:
- sz -= tari;
- hp += tari + 1;
}
+ sz -= tari;
+ hp += tari + 1;
break;
}
default:
@@ -2423,18 +2326,8 @@ offset_heap_ptr(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size)
static void
offset_off_heap(Process* p, Sint offs, char* area, Uint area_size)
{
- if (MSO(p).mso && in_area((Eterm *)MSO(p).mso, area, area_size)) {
- Eterm** uptr = (Eterm**) (void *) &MSO(p).mso;
- *uptr += offs;
- }
-
- if (MSO(p).funs && in_area((Eterm *)MSO(p).funs, area, area_size)) {
- Eterm** uptr = (Eterm**) (void *) &MSO(p).funs;
- *uptr += offs;
- }
-
- if (MSO(p).externals && in_area((Eterm *)MSO(p).externals, area, area_size)) {
- Eterm** uptr = (Eterm**) (void *) &MSO(p).externals;
+ if (MSO(p).first && in_area((Eterm *)MSO(p).first, area, area_size)) {
+ Eterm** uptr = (Eterm**) (void *) &MSO(p).first;
*uptr += offs;
}
}
@@ -2555,8 +2448,8 @@ do { \
__FILE__, __LINE__, #EXP); \
} while (0)
-#ifdef ERTS_OFFHEAP_DEBUG_CHK_CIRCULAR_EXTERNAL_LIST
-# define ERTS_EXTERNAL_VISITED_BIT ((Eterm) 1 << 31)
+#ifdef ERTS_OFFHEAP_DEBUG_CHK_CIRCULAR_LIST
+# define ERTS_OFFHEAP_VISITED_BIT ((Eterm) 1 << 31)
#endif
@@ -2566,62 +2459,45 @@ erts_check_off_heap2(Process *p, Eterm *htop)
Eterm *oheap = (Eterm *) OLD_HEAP(p);
Eterm *ohtop = (Eterm *) OLD_HTOP(p);
int old;
- ProcBin *pb;
- ErlFunThing *eft;
- ExternalThing *et;
+ union erl_off_heap_ptr u;
old = 0;
- for (pb = MSO(p).mso; pb; pb = pb->next) {
- Eterm *ptr = (Eterm *) pb;
- long refc = erts_refc_read(&pb->val->refc, 1);
+ for (u.hdr = MSO(p).first; u.hdr; u.hdr = u.hdr->next) {
+ long refc;
+ switch (thing_subtag(u.hdr->thing_word)) {
+ case REFC_BINARY_SUBTAG:
+ refc = erts_refc_read(&u.pb->val->refc, 1);
+ break;
+ case FUN_SUBTAG:
+ refc = erts_refc_read(&u.fun->fe->refc, 1);
+ break;
+ case EXTERNAL_PID_SUBTAG:
+ case EXTERNAL_PORT_SUBTAG:
+ case EXTERNAL_REF_SUBTAG:
+ refc = erts_refc_read(&u.ext->node->refc, 1);
+ break;
+ default:
+ ASSERT(!!"erts_check_off_heap2: Invalid thing_word");
+ }
ERTS_CHK_OFFHEAP_ASSERT(refc >= 1);
+#ifdef ERTS_OFFHEAP_DEBUG_CHK_CIRCULAR_LIST
+ ERTS_CHK_OFFHEAP_ASSERT(!(u.hdr->thing_word & ERTS_EXTERNAL_VISITED_BIT));
+ u.hdr->thing_word |= ERTS_OFFHEAP_VISITED_BIT;
+#endif
if (old) {
- ERTS_CHK_OFFHEAP_ASSERT(oheap <= ptr && ptr < ohtop);
+ ERTS_CHK_OFFHEAP_ASSERT(oheap <= u.ep && u.ep < ohtop);
}
- else if (oheap <= ptr && ptr < ohtop)
+ else if (oheap <= u.ep && u.ep < ohtop)
old = 1;
else {
- ERTS_CHK_OFFHEAP_ASSERT(within2(ptr, p, htop));
+ ERTS_CHK_OFFHEAP_ASSERT(within2(u.ep, p, htop));
}
}
- old = 0;
- for (eft = MSO(p).funs; eft; eft = eft->next) {
- Eterm *ptr = (Eterm *) eft;
- long refc = erts_refc_read(&eft->fe->refc, 1);
- ERTS_CHK_OFFHEAP_ASSERT(refc >= 1);
- if (old)
- ERTS_CHK_OFFHEAP_ASSERT(oheap <= ptr && ptr < ohtop);
- else if (oheap <= ptr && ptr < ohtop)
- old = 1;
- else
- ERTS_CHK_OFFHEAP_ASSERT(within2(ptr, p, htop));
- }
-
- old = 0;
- for (et = MSO(p).externals; et; et = et->next) {
- Eterm *ptr = (Eterm *) et;
- long refc = erts_refc_read(&et->node->refc, 1);
- ERTS_CHK_OFFHEAP_ASSERT(refc >= 1);
-#ifdef ERTS_OFFHEAP_DEBUG_CHK_CIRCULAR_EXTERNAL_LIST
- ERTS_CHK_OFFHEAP_ASSERT(!(et->header & ERTS_EXTERNAL_VISITED_BIT));
-#endif
- if (old)
- ERTS_CHK_OFFHEAP_ASSERT(oheap <= ptr && ptr < ohtop);
- else if (oheap <= ptr && ptr < ohtop)
- old = 1;
- else
- ERTS_CHK_OFFHEAP_ASSERT(within2(ptr, p, htop));
-#ifdef ERTS_OFFHEAP_DEBUG_CHK_CIRCULAR_EXTERNAL_LIST
- et->header |= ERTS_EXTERNAL_VISITED_BIT;
-#endif
- }
-
#ifdef ERTS_OFFHEAP_DEBUG_CHK_CIRCULAR_EXTERNAL_LIST
- for (et = MSO(p).externals; et; et = et->next)
- et->header &= ~ERTS_EXTERNAL_VISITED_BIT;
+ for (u.hdr = MSO(p).first; u.hdr; u.hdr = u.hdr->next)
+ u.hdr->thing_word &= ~ERTS_OFFHEAP_VISITED_BIT;
#endif
-
}
void
diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c
index b63f3df7df..1f61dca230 100644
--- a/erts/emulator/beam/erl_message.c
+++ b/erts/emulator/beam/erl_message.c
@@ -30,6 +30,7 @@
#include "erl_message.h"
#include "erl_process.h"
#include "erl_nmgc.h"
+#include "erl_binary.h"
ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(message,
ErlMessage,
@@ -164,16 +165,25 @@ erts_resize_message_buffer(ErlHeapFragment *bp, Uint size,
void
erts_cleanup_offheap(ErlOffHeap *offheap)
{
- if (offheap->mso) {
- erts_cleanup_mso(offheap->mso);
- }
-#ifndef HYBRID /* FIND ME! */
- if (offheap->funs) {
- erts_cleanup_funs(offheap->funs);
- }
-#endif
- if (offheap->externals) {
- erts_cleanup_externals(offheap->externals);
+ union erl_off_heap_ptr u;
+
+ for (u.hdr = offheap->first; u.hdr; u.hdr = u.hdr->next) {
+ switch (thing_subtag(u.hdr->thing_word)) {
+ case REFC_BINARY_SUBTAG:
+ if (erts_refc_dectest(&u.pb->val->refc, 0) == 0) {
+ erts_bin_free(u.pb->val);
+ }
+ break;
+ case FUN_SUBTAG:
+ if (erts_refc_dectest(&u.fun->fe->refc, 0) == 0) {
+ erts_erase_fun_entry(u.fun->fe);
+ }
+ break;
+ default:
+ ASSERT(is_external_header(u.hdr->thing_word));
+ erts_deref_node_entry(u.ext->node);
+ break;
+ }
}
}
@@ -201,41 +211,17 @@ link_mbuf_to_proc(Process *proc, ErlHeapFragment *bp)
MBUF_SIZE(proc) += bp->used_size;
FLAGS(proc) |= F_FORCE_GC;
- /* Move any binaries into the process */
- if (bp->off_heap.mso != NULL) {
- ProcBin** next_p = &bp->off_heap.mso;
+ /* Move any off_heap's into the process */
+ if (bp->off_heap.first != NULL) {
+ struct erl_off_heap_header** next_p = &bp->off_heap.first;
while (*next_p != NULL) {
next_p = &((*next_p)->next);
}
- *next_p = MSO(proc).mso;
- MSO(proc).mso = bp->off_heap.mso;
- bp->off_heap.mso = NULL;
+ *next_p = MSO(proc).first;
+ MSO(proc).first = bp->off_heap.first;
+ bp->off_heap.first = NULL;
MSO(proc).overhead += bp->off_heap.overhead;
}
-
- /* Move any funs into the process */
-#ifndef HYBRID
- if (bp->off_heap.funs != NULL) {
- ErlFunThing** next_p = &bp->off_heap.funs;
- while (*next_p != NULL) {
- next_p = &((*next_p)->next);
- }
- *next_p = MSO(proc).funs;
- MSO(proc).funs = bp->off_heap.funs;
- bp->off_heap.funs = NULL;
- }
-#endif
-
- /* Move any external things into the process */
- if (bp->off_heap.externals != NULL) {
- ExternalThing** next_p = &bp->off_heap.externals;
- while (*next_p != NULL) {
- next_p = &((*next_p)->next);
- }
- *next_p = MSO(proc).externals;
- MSO(proc).externals = bp->off_heap.externals;
- bp->off_heap.externals = NULL;
- }
}
}
@@ -506,19 +492,7 @@ erts_link_mbuf_to_proc(struct process *proc, ErlHeapFragment *bp)
void
erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg)
{
- /* Unions for typecasts avoids warnings about type-punned pointers and aliasing */
- union {
- Uint** upp;
- ProcBin **pbpp;
- ErlFunThing **efpp;
- ExternalThing **etpp;
- } oh_list_pp, oh_el_next_pp;
- union {
- Uint *up;
- ProcBin *pbp;
- ErlFunThing *efp;
- ExternalThing *etp;
- } oh_el_p;
+ struct erl_off_heap_header* oh;
Eterm term, token, *fhp, *hp;
Sint offs;
Uint sz;
@@ -571,9 +545,7 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg)
hp = *hpp;
offs = hp - fhp;
- oh_list_pp.upp = NULL;
- oh_el_next_pp.upp = NULL; /* Shut up compiler warning */
- oh_el_p.up = NULL; /* Shut up compiler warning */
+ oh = NULL;
while (sz--) {
Uint cpy_sz;
Eterm val = *fhp++;
@@ -593,25 +565,11 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg)
case ARITYVAL_SUBTAG:
break;
case REFC_BINARY_SUBTAG:
- oh_list_pp.pbpp = &off_heap->mso;
- oh_el_p.up = (hp-1);
- oh_el_next_pp.pbpp = &(oh_el_p.pbp)->next;
- cpy_sz = thing_arityval(val);
- goto cpy_words;
case FUN_SUBTAG:
-#ifndef HYBRID
- oh_list_pp.efpp = &off_heap->funs;
- oh_el_p.up = (hp-1);
- oh_el_next_pp.efpp = &(oh_el_p.efp)->next;
-#endif
- cpy_sz = thing_arityval(val);
- goto cpy_words;
case EXTERNAL_PID_SUBTAG:
case EXTERNAL_PORT_SUBTAG:
case EXTERNAL_REF_SUBTAG:
- oh_list_pp.etpp = &off_heap->externals;
- oh_el_p.up = (hp-1);
- oh_el_next_pp.etpp = &(oh_el_p.etp)->next;
+ oh = (struct erl_off_heap_header*) (hp-1);
cpy_sz = thing_arityval(val);
goto cpy_words;
default:
@@ -641,44 +599,13 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg)
case 1: *hp++ = *fhp++;
default: break;
}
- if (oh_list_pp.upp) {
-#ifdef HARD_DEBUG
- Uint *dbg_old_oh_list_p = *oh_list_pp.upp;
-#endif
+ if (oh) {
/* Add to offheap list */
- *oh_el_next_pp.upp = *oh_list_pp.upp;
- *oh_list_pp.upp = oh_el_p.up;
- ASSERT(*hpp <= oh_el_p.up);
- ASSERT(hp > oh_el_p.up);
-#ifdef HARD_DEBUG
- switch (val & _HEADER_SUBTAG_MASK) {
- case REFC_BINARY_SUBTAG:
- ASSERT(off_heap->mso == *oh_list_pp.pbpp);
- ASSERT(off_heap->mso->next
- == (ProcBin *) dbg_old_oh_list_p);
- break;
-#ifndef HYBRID
- case FUN_SUBTAG:
- ASSERT(off_heap->funs == *oh_list_pp.efpp);
- ASSERT(off_heap->funs->next
- == (ErlFunThing *) dbg_old_oh_list_p);
- break;
-#endif
- case EXTERNAL_PID_SUBTAG:
- case EXTERNAL_PORT_SUBTAG:
- case EXTERNAL_REF_SUBTAG:
- ASSERT(off_heap->externals
- == *oh_list_pp.etpp);
- ASSERT(off_heap->externals->next
- == (ExternalThing *) dbg_old_oh_list_p);
- break;
- default:
- ASSERT(0);
- }
-#endif
- oh_list_pp.upp = NULL;
-
-
+ oh->next = off_heap->first;
+ off_heap->first = oh;
+ ASSERT(*hpp <= (Eterm*)oh);
+ ASSERT(hp > (Eterm*)oh);
+ oh = NULL;
}
break;
}
@@ -765,11 +692,7 @@ copy_done:
#endif
- bp->off_heap.mso = NULL;
-#ifndef HYBRID
- bp->off_heap.funs = NULL;
-#endif
- bp->off_heap.externals = NULL;
+ bp->off_heap.first = NULL;
free_message_buffer(bp);
msg->data.heap_frag = NULL;
diff --git a/erts/emulator/beam/erl_message.h b/erts/emulator/beam/erl_message.h
index f478572ac2..55ea92860a 100644
--- a/erts/emulator/beam/erl_message.h
+++ b/erts/emulator/beam/erl_message.h
@@ -28,13 +28,18 @@ struct external_thing_;
* but is stored outside of any heap.
*/
-typedef struct erl_off_heap {
- struct proc_bin* mso; /* List of associated binaries. */
-#ifndef HYBRID /* FIND ME! */
- struct erl_fun_thing* funs; /* List of funs. */
+struct erl_off_heap_header {
+ Eterm thing_word;
+ Uint size;
+#if HALFWORD_HEAP
+ void* dummy_ptr_padding__;
#endif
- struct external_thing_* externals; /* List of external things. */
- int overhead; /* Administrative overhead (used to force GC). */
+ struct erl_off_heap_header* next;
+};
+
+typedef struct erl_off_heap {
+ struct erl_off_heap_header* first;
+ int overhead; /* Administrative overhead (used to force GC). */
} ErlOffHeap;
#include "external.h"
@@ -201,9 +206,7 @@ do { \
(HEAP_FRAG_P)->next = NULL; \
(HEAP_FRAG_P)->alloc_size = (DATA_WORDS); \
(HEAP_FRAG_P)->used_size = (DATA_WORDS); \
- (HEAP_FRAG_P)->off_heap.mso = NULL; \
- (HEAP_FRAG_P)->off_heap.funs = NULL; \
- (HEAP_FRAG_P)->off_heap.externals = NULL; \
+ (HEAP_FRAG_P)->off_heap.first = NULL; \
(HEAP_FRAG_P)->off_heap.overhead = 0; \
} while (0)
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index 3d63fa1caf..e95d9c4f75 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -258,9 +258,7 @@ void enif_free_env(ErlNifEnv* env)
static ERTS_INLINE void clear_offheap(ErlOffHeap* oh)
{
- oh->mso = NULL;
- oh->externals = NULL;
- oh->funs = NULL;
+ oh->first = NULL;
oh->overhead = 0;
}
@@ -364,7 +362,7 @@ ERL_NIF_TERM enif_make_copy(ErlNifEnv* dst_env, ERL_NIF_TERM src_term)
#ifdef DEBUG
static int is_offheap(const ErlOffHeap* oh)
{
- return oh->mso != NULL || oh->funs != NULL || oh->externals != NULL;
+ return oh->first != NULL;
}
#endif
@@ -627,8 +625,8 @@ Eterm enif_make_binary(ErlNifEnv* env, ErlNifBinary* bin)
pb = (ProcBin *) alloc_heap(env, PROC_BIN_SIZE);
pb->thing_word = HEADER_PROC_BIN;
pb->size = bptr->orig_size;
- pb->next = MSO(env->proc).mso;
- MSO(env->proc).mso = pb;
+ pb->next = MSO(env->proc).first;
+ MSO(env->proc).first = (struct erl_off_heap_header*) pb;
pb->val = bptr;
pb->bytes = (byte*) bptr->orig_bytes;
pb->flags = 0;
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index 5865d33138..7482da251e 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -1087,30 +1087,24 @@ insert_offheap2(ErlOffHeap *oh, void *arg)
static void
insert_offheap(ErlOffHeap *oh, int type, Eterm id)
{
- if(oh->externals) {
- ExternalThing *etp = oh->externals;
- while (etp) {
- insert_node(etp->node, type, id);
- etp = etp->next;
- }
- }
+ union erl_off_heap_ptr u;
+ struct insert_offheap2_arg a;
+ a.type = BIN_REF;
- if(oh->mso) {
- ProcBin *pb;
- struct insert_offheap2_arg a;
- a.type = BIN_REF;
- for(pb = oh->mso; pb; pb = pb->next) {
- if(IsMatchProgBinary(pb->val)) {
+ for (u.hdr = oh->first; u.hdr; u.hdr = u.hdr->next) {
+ switch (thing_subtag(u.hdr->thing_word)) {
+ case REFC_BINARY_SUBTAG:
+ if(IsMatchProgBinary(u.pb->val)) {
InsertedBin *ib;
int insert_bin = 1;
for (ib = inserted_bins; ib; ib = ib->next)
- if(ib->bin_val == pb->val) {
+ if(ib->bin_val == u.pb->val) {
insert_bin = 0;
break;
}
if (insert_bin) {
#if HALFWORD_HEAP
- UWord val = (UWord) pb->val;
+ UWord val = (UWord) u.pb->val;
DeclareTmpHeapNoproc(id_heap,BIG_UINT_HEAP_SIZE*2); /* extra place allocated */
#else
DeclareTmpHeapNoproc(id_heap,BIG_UINT_HEAP_SIZE);
@@ -1124,13 +1118,13 @@ insert_offheap(ErlOffHeap *oh, int type, Eterm id)
a.id = erts_bld_uword(&hp, NULL, (UWord) val);
#else
UseTmpHeapNoproc(BIG_UINT_HEAP_SIZE);
- a.id = erts_bld_uint(&hp, NULL, (Uint) pb->val);
+ a.id = erts_bld_uint(&hp, NULL, (Uint) u.pb->val);
#endif
- erts_match_prog_foreach_offheap(pb->val,
+ erts_match_prog_foreach_offheap(u.pb->val,
insert_offheap2,
(void *) &a);
nib = erts_alloc(ERTS_ALC_T_NC_TMP, sizeof(InsertedBin));
- nib->bin_val = pb->val;
+ nib->bin_val = u.pb->val;
nib->next = inserted_bins;
inserted_bins = nib;
#if HALFWORD_HEAP
@@ -1139,15 +1133,16 @@ insert_offheap(ErlOffHeap *oh, int type, Eterm id)
UnUseTmpHeapNoproc(BIG_UINT_HEAP_SIZE);
#endif
}
- }
+ }
+ break;
+ case FUN_SUBTAG:
+ break; /* No need to */
+ default:
+ ASSERT(is_external_header(u.hdr->thing_word));
+ insert_node(u.ext->node, type, id);
+ break;
}
}
-
-#if 0
- if(oh->funs) {
- /* No need to */
- }
-#endif
}
static void doit_insert_monitor(ErtsMonitor *monitor, void *p)
@@ -1289,6 +1284,7 @@ setup_reference_table(void)
for (i = 0; i < erts_max_processes; i++)
if (process_tab[i]) {
ErlMessage *msg;
+
/* Insert Heap */
insert_offheap(&(process_tab[i]->off_heap),
HEAP_REF,
@@ -1375,21 +1371,22 @@ setup_reference_table(void)
{ /* Add binaries stored elsewhere ... */
ErlOffHeap oh;
- ProcBin pb[2] = {{0},{0}};
- ProcBin *mso = NULL;
+ ProcBin pb[2];
int i = 0;
Binary *default_match_spec;
Binary *default_meta_match_spec;
- /* Only the ProcBin members val and next will be inspected
+ oh.first = NULL;
+ /* Only the ProcBin members thing_word, val and next will be inspected
(by insert_offheap()) */
#undef ADD_BINARY
-#define ADD_BINARY(Bin) \
- if ((Bin)) { \
- pb[i].val = (Bin); \
- pb[i].next = mso; \
- mso = &pb[i]; \
- i++; \
+#define ADD_BINARY(Bin) \
+ if ((Bin)) { \
+ pb[i].thing_word = REFC_BINARY_SUBTAG; \
+ pb[i].val = (Bin); \
+ pb[i].next = oh.first; \
+ oh.first = (struct erl_off_heap_header*) &pb[i]; \
+ i++; \
}
erts_get_default_trace_pattern(NULL,
@@ -1401,11 +1398,6 @@ setup_reference_table(void)
ADD_BINARY(default_match_spec);
ADD_BINARY(default_meta_match_spec);
- oh.mso = mso;
- oh.externals = NULL;
-#ifndef HYBRID /* FIND ME! */
- oh.funs = NULL;
-#endif
insert_offheap(&oh, BIN_REF, AM_match_spec);
#undef ADD_BINARY
}
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 41031f5468..8c88353593 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -6761,11 +6761,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
/*
* Must initialize binary lists here before copying binaries to process.
*/
- p->off_heap.mso = NULL;
-#ifndef HYBRID /* FIND ME! */
- p->off_heap.funs = NULL;
-#endif
- p->off_heap.externals = NULL;
+ p->off_heap.first = NULL;
p->off_heap.overhead = 0;
heap_need +=
@@ -6855,7 +6851,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->group_leader =
IS_CONST(parent->group_leader)
? parent->group_leader
- : STORE_NC(&p->htop, &p->off_heap.externals, parent->group_leader);
+ : STORE_NC(&p->htop, &p->off_heap, parent->group_leader);
}
erts_get_default_tracing(&p->trace_flags, &p->tracer_proc);
@@ -7056,11 +7052,7 @@ void erts_init_empty_process(Process *p)
memset(&(p->u.tm), 0, sizeof(ErlTimer));
#endif
p->next = NULL;
- p->off_heap.mso = NULL;
-#ifndef HYBRID /* FIND ME! */
- p->off_heap.funs = NULL;
-#endif
- p->off_heap.externals = NULL;
+ p->off_heap.first = NULL;
p->off_heap.overhead = 0;
p->reg = NULL;
p->heap_sz = 0;
@@ -7207,11 +7199,7 @@ erts_debug_verify_clean_empty_process(Process* p)
/* Thing that erts_cleanup_empty_process() cleans up */
- ASSERT(p->off_heap.mso == NULL);
-#ifndef HYBRID /* FIND ME! */
- ASSERT(p->off_heap.funs == NULL);
-#endif
- ASSERT(p->off_heap.externals == NULL);
+ ASSERT(p->off_heap.first == NULL);
ASSERT(p->off_heap.overhead == 0);
ASSERT(p->mbuf == NULL);
@@ -7225,11 +7213,7 @@ erts_cleanup_empty_process(Process* p)
/* We only check fields that are known to be used... */
erts_cleanup_offheap(&p->off_heap);
- p->off_heap.mso = NULL;
-#ifndef HYBRID /* FIND ME! */
- p->off_heap.funs = NULL;
-#endif
- p->off_heap.externals = NULL;
+ p->off_heap.first = NULL;
p->off_heap.overhead = 0;
if (p->mbuf != NULL) {
@@ -7266,7 +7250,7 @@ delete_process(Process* p)
* The mso list should not be used anymore, but if it is, make sure that
* we'll notice.
*/
- p->off_heap.mso = (void *) 0x8DEFFACD;
+ p->off_heap.first = (void *) 0x8DEFFACD;
if (p->arg_reg != p->def_arg_reg) {
erts_free(ERTS_ALC_T_ARG_REG, p->arg_reg);
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index 8f9f7f004e..6ce74a917f 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -828,7 +828,7 @@ extern struct erts_system_profile_flags_t erts_system_profile_flags;
#define F_INSLPQUEUE (1 << 1) /* Set if in timer queue */
#define F_TIMO (1 << 2) /* Set if timeout */
#define F_HEAP_GROW (1 << 3)
-#define F_NEED_FULLSWEEP (1 << 4) /* If process has old binaries & funs. */
+#define F_NEED_FULLSWEEP (1 << 4)
#define F_USING_DB (1 << 5) /* If have created tables */
#define F_DISTRIBUTION (1 << 6) /* Process used in distribution */
#define F_USING_DDLL (1 << 7) /* Process has used the DDLL interface */
diff --git a/erts/emulator/beam/erl_term.h b/erts/emulator/beam/erl_term.h
index 3a8c30fe6a..b8e4473141 100644
--- a/erts/emulator/beam/erl_term.h
+++ b/erts/emulator/beam/erl_term.h
@@ -821,10 +821,10 @@ _ET_DECLARE_CHECKED(struct erl_node_*,internal_ref_node,Eterm)
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |A A A A A A A A A A A A A A A A A A A A A A A A A A|t t t t|0 0| Thing
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N| Next
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E| ErlNode
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N| Next
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X| Data 0
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* . . .
@@ -835,7 +835,7 @@ _ET_DECLARE_CHECKED(struct erl_node_*,internal_ref_node,Eterm)
* t : External pid thing tag (1100)
* t : External port thing tag (1101)
* t : External ref thing tag (1110)
- * N : Next (external thing) pointer
+ * N : Next (off_heap) pointer
* E : ErlNode pointer
* X : Type specific data
*
@@ -852,13 +852,16 @@ _ET_DECLARE_CHECKED(struct erl_node_*,internal_ref_node,Eterm)
/* XXX:PaN - this structure is not perfect for halfword heap, it takes
a lot of memory due to padding, and the array will not begin at the end of the
structure, as otherwise expected. Be sure to access data.ui32 array and not try
- to do pointer manipulation on an Eterm * to reach the actual data... */
+ to do pointer manipulation on an Eterm * to reach the actual data...
+ XXX:Sverk - Problem made worse by "one off-heap list" when 'next' pointer
+ must align with 'next' in ProcBin, erl_fun_thing and erl_off_heap_header.
+*/
typedef struct external_thing_ {
/* ----+ */
Eterm header; /* | */
- struct external_thing_ *next; /* > External thing head */
- struct erl_node_ *node; /* | */
+ struct erl_node_* node; /* > External thing head */
+ struct erl_off_heap_header* next; /* | */
/* ----+ */
union {
Uint32 ui32[1];
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index 466165f26f..310a83200b 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -1468,11 +1468,11 @@ dec_pid(ErtsDistExternal *edep, Eterm** hpp, byte* ep, ErlOffHeap* off_heap, Ete
*hpp += EXTERNAL_THING_HEAD_SIZE + 1;
etp->header = make_external_pid_header(1);
- etp->next = off_heap->externals;
+ etp->next = off_heap->first;
etp->node = node;
etp->data.ui[0] = data;
- off_heap->externals = etp;
+ off_heap->first = (struct erl_off_heap_header*) etp;
*objp = make_external_pid(etp);
}
return ep;
@@ -1910,69 +1910,30 @@ is_external_string(Eterm list, int* p_is_string)
return len;
}
-/* Assumes that the ones to undo are preluding the lists. */
+/* Assumes that the ones to undo are preluding the list. */
static void
undo_offheap_in_area(ErlOffHeap* off_heap, Eterm* start, Eterm* end)
{
const Uint area_sz = (end - start) * sizeof(Eterm);
- struct proc_bin* mso;
- struct proc_bin** mso_nextp = NULL;
-#ifndef HYBRID /* FIND ME! */
- struct erl_fun_thing* funs;
- struct erl_fun_thing** funs_nextp = NULL;
-#endif
- struct external_thing_* ext;
- struct external_thing_** ext_nextp = NULL;
-
- for (mso = off_heap->mso; ; mso=mso->next) {
- if (!in_area(mso, start, area_sz)) {
- if (mso_nextp != NULL) {
- *mso_nextp = NULL;
- erts_cleanup_mso(off_heap->mso);
- off_heap->mso = mso;
+ struct erl_off_heap_header* hdr;
+ struct erl_off_heap_header** hdr_nextp = NULL;
+
+ for (hdr = off_heap->first; ; hdr=hdr->next) {
+ if (!in_area(hdr, start, area_sz)) {
+ if (hdr_nextp != NULL) {
+ *hdr_nextp = NULL;
+ erts_cleanup_offheap(off_heap);
+ off_heap->first = hdr;
}
break;
}
- mso_nextp = &mso->next;
+ hdr_nextp = &hdr->next;
}
-#ifndef HYBRID /* FIND ME! */
- for (funs = off_heap->funs; ; funs=funs->next) {
- if (!in_area(funs, start, area_sz)) {
- if (funs_nextp != NULL) {
- *funs_nextp = NULL;
- erts_cleanup_funs(off_heap->funs);
- off_heap->funs = funs;
- }
- break;
- }
- funs_nextp = &funs->next;
- }
-#endif
- for (ext = off_heap->externals; ; ext=ext->next) {
- if (!in_area(ext, start, area_sz)) {
- if (ext_nextp != NULL) {
- *ext_nextp = NULL;
- erts_cleanup_externals(off_heap->externals);
- off_heap->externals = ext;
- }
- break;
- }
- ext_nextp = &ext->next;
- }
-
- /* Assert that the ones to undo were indeed preluding the lists. */
+ /* Assert that the ones to undo were indeed preluding the list. */
#ifdef DEBUG
- for (mso = off_heap->mso; mso != NULL; mso=mso->next) {
- ASSERT(!in_area(mso, start, area_sz));
- }
-# ifndef HYBRID /* FIND ME! */
- for (funs = off_heap->funs; funs != NULL; funs=funs->next) {
- ASSERT(!in_area(funs, start, area_sz));
- }
-# endif
- for (ext = off_heap->externals; ext != NULL; ext=ext->next) {
- ASSERT(!in_area(ext, start, area_sz));
+ for (hdr = off_heap->first; hdr != NULL; hdr = hdr->next) {
+ ASSERT(!in_area(hdr, start, area_sz));
}
#endif /* DEBUG */
}
@@ -2216,11 +2177,11 @@ dec_term_atom_common:
hp += EXTERNAL_THING_HEAD_SIZE + 1;
etp->header = make_external_port_header(1);
- etp->next = off_heap->externals;
+ etp->next = off_heap->first;
etp->node = node;
etp->data.ui[0] = num;
- off_heap->externals = etp;
+ off_heap->first = (struct erl_off_heap_header*)etp;
*objp = make_external_port(etp);
}
@@ -2298,10 +2259,10 @@ dec_term_atom_common:
#else
etp->header = make_external_ref_header(ref_words);
#endif
- etp->next = off_heap->externals;
+ etp->next = off_heap->first;
etp->node = node;
- off_heap->externals = etp;
+ off_heap->first = (struct erl_off_heap_header*)etp;
*objp = make_external_ref(etp);
ref_num = &(etp->data.ui32[0]);
}
@@ -2344,8 +2305,8 @@ dec_term_atom_common:
hp += PROC_BIN_SIZE;
pb->thing_word = HEADER_PROC_BIN;
pb->size = n;
- pb->next = off_heap->mso;
- off_heap->mso = pb;
+ pb->next = off_heap->first;
+ off_heap->first = (struct erl_off_heap_header*)pb;
pb->val = dbin;
pb->bytes = (byte*) dbin->orig_bytes;
pb->flags = 0;
@@ -2381,8 +2342,8 @@ dec_term_atom_common:
pb = (ProcBin *) hp;
pb->thing_word = HEADER_PROC_BIN;
pb->size = n;
- pb->next = off_heap->mso;
- off_heap->mso = pb;
+ pb->next = off_heap->first;
+ off_heap->first = (struct erl_off_heap_header*)pb;
pb->val = dbin;
pb->bytes = (byte*) dbin->orig_bytes;
pb->flags = 0;
@@ -2502,8 +2463,8 @@ dec_term_atom_common:
* It is safe to link the fun into the fun list only when
* no more validity tests can fail.
*/
- funp->next = off_heap->funs;
- off_heap->funs = funp;
+ funp->next = off_heap->first;
+ off_heap->first = (struct erl_off_heap_header*)funp;
#endif
funp->fe = erts_put_fun_entry2(module, old_uniq, old_index,
@@ -2580,8 +2541,8 @@ dec_term_atom_common:
* It is safe to link the fun into the fun list only when
* no more validity tests can fail.
*/
- funp->next = off_heap->funs;
- off_heap->funs = funp;
+ funp->next = off_heap->first;
+ off_heap->first = (struct erl_off_heap_header*)funp;
#endif
old_uniq = unsigned_val(temp);
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index b4a7a22082..064dc69da8 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -464,7 +464,10 @@ typedef union {
typedef struct proc_bin {
Eterm thing_word; /* Subtag REFC_BINARY_SUBTAG. */
Uint size; /* Binary size in bytes. */
- struct proc_bin *next; /* Pointer to next ProcBin. */
+#if HALFWORD_HEAP
+ void* dummy_ptr_padding__;
+#endif
+ struct erl_off_heap_header *next;
Binary *val; /* Pointer to Binary structure. */
byte *bytes; /* Pointer to the actual data bytes. */
Uint flags; /* Flag word. */
@@ -494,8 +497,8 @@ erts_mk_magic_binary_term(Eterm **hpp, ErlOffHeap *ohp, Binary *mbp)
pb->thing_word = HEADER_PROC_BIN;
pb->size = 0;
- pb->next = ohp->mso;
- ohp->mso = pb;
+ pb->next = ohp->first;
+ ohp->first = (struct erl_off_heap_header*) pb;
pb->val = mbp;
pb->bytes = (byte *) mbp->orig_bytes;
pb->flags = 0;
@@ -512,6 +515,15 @@ erts_mk_magic_binary_term(Eterm **hpp, ErlOffHeap *ohp, Binary *mbp)
&& (thing_subtag(*binary_val((T))) == REFC_BINARY_SUBTAG) \
&& (((ProcBin *) binary_val((T)))->val->flags & BIN_FLAG_MAGIC))
+
+union erl_off_heap_ptr {
+ struct erl_off_heap_header* hdr;
+ ProcBin *pb;
+ struct erl_fun_thing* fun;
+ struct external_thing_* ext;
+ Eterm* ep;
+};
+
/* arrays that get malloced at startup */
extern Port* erts_port;
extern erts_smp_atomic_t erts_ports_alive;
@@ -823,7 +835,6 @@ Eterm erts_new_heap_binary(Process *p, byte *buf, int len, byte** datap);
Eterm erts_new_mso_binary(Process*, byte*, int);
Eterm new_binary(Process*, byte*, int);
Eterm erts_realloc_binary(Eterm bin, size_t size);
-void erts_cleanup_mso(ProcBin* pb);
/* erl_bif_info.c */
@@ -1499,7 +1510,6 @@ void p_slpq(_VOID_);
void erts_silence_warn_unused_result(long unused);
void erts_cleanup_offheap(ErlOffHeap *offheap);
-void erts_cleanup_externals(ExternalThing *);
Uint erts_fit_in_bits(Uint);
int list_length(Eterm);
@@ -1532,7 +1542,7 @@ erts_bld_atom_2uint_3tup_list(Uint **hpp, Uint *szp, Sint length,
Eterm atoms[], Uint uints1[], Uint uints2[]);
Eterm store_external_or_ref_in_proc_(Process *, Eterm);
-Eterm store_external_or_ref_(Uint **, ExternalThing **, Eterm);
+Eterm store_external_or_ref_(Uint **, ErlOffHeap*, Eterm);
#define NC_HEAP_SIZE(NC) \
(ASSERT_EXPR(is_node_container((NC))), \
@@ -1957,5 +1967,5 @@ erts_alloc_message_heap(Uint size,
# define UnUseTmpHeap(Size,Proc) /* Nothing */
# define UseTmpHeapNoproc(Size) /* Nothing */
# define UnUseTmpHeapNoproc(Size) /* Nothing */
-#endif
-#endif
+#endif /* HEAP_ON_C_STACK */
+#endif /* !__GLOBAL_H__ */
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index 68625801cf..b840f65cdd 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -1575,8 +1575,8 @@ static void deliver_read_message(Port* prt, Eterm to,
pb = (ProcBin *) hp;
pb->thing_word = HEADER_PROC_BIN;
pb->size = len;
- pb->next = ohp->mso;
- ohp->mso = pb;
+ pb->next = ohp->first;
+ ohp->first = (struct erl_off_heap_header*)pb;
pb->val = bptr;
pb->bytes = (byte*) bptr->orig_bytes;
pb->flags = 0;
@@ -1725,8 +1725,8 @@ deliver_vec_message(Port* prt, /* Port */
}
pb->thing_word = HEADER_PROC_BIN;
pb->size = iov->iov_len;
- pb->next = ohp->mso;
- ohp->mso = pb;
+ pb->next = ohp->first;
+ ohp->first = (struct erl_off_heap_header*)pb;
pb->val = ErlDrvBinary2Binary(b);
pb->bytes = base;
pb->flags = 0;
@@ -2259,8 +2259,8 @@ erts_port_control(Process* p, Port* prt, Uint command, Eterm iolist)
ProcBin* pb = (ProcBin *) HAlloc(p, PROC_BIN_SIZE);
pb->thing_word = HEADER_PROC_BIN;
pb->size = dbin->orig_size;
- pb->next = MSO(p).mso;
- MSO(p).mso = pb;
+ pb->next = MSO(p).first;
+ MSO(p).first = (struct erl_off_heap_header*)pb;
pb->val = ErlDrvBinary2Binary(dbin);
pb->bytes = (byte*) dbin->orig_bytes;
pb->flags = 0;
@@ -3033,8 +3033,8 @@ driver_deliver_term(ErlDrvPort port,
driver_binary_inc_refc(b); /* caller will free binary */
pb->thing_word = HEADER_PROC_BIN;
pb->size = size;
- pb->next = ohp->mso;
- ohp->mso = pb;
+ pb->next = ohp->first;
+ ohp->first = (struct erl_off_heap_header*)pb;
pb->val = ErlDrvBinary2Binary(b);
pb->bytes = ((byte*) b->orig_bytes) + offset;
pb->flags = 0;
@@ -3072,8 +3072,8 @@ driver_deliver_term(ErlDrvPort port,
hp += PROC_BIN_SIZE;
pbp->thing_word = HEADER_PROC_BIN;
pbp->size = size;
- pbp->next = ohp->mso;
- ohp->mso = pbp;
+ pbp->next = ohp->first;
+ ohp->first = (struct erl_off_heap_header*)pbp;
pbp->val = bp;
pbp->bytes = (byte*) bp->orig_bytes;
pbp->flags = 0;
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index b8d407f5e5..25472ef47a 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -162,13 +162,8 @@ erts_heap_alloc(Process* p, Uint need)
bp->alloc_size = n;
bp->used_size = n;
MBUF_SIZE(p) += n;
- bp->off_heap.mso = NULL;
-#ifndef HYBRID /* FIND ME! */
- bp->off_heap.funs = NULL;
-#endif
- bp->off_heap.externals = NULL;
+ bp->off_heap.first = NULL;
bp->off_heap.overhead = 0;
-
return bp->mem;
}
@@ -2729,21 +2724,8 @@ not_equal:
}
-void
-erts_cleanup_externals(ExternalThing *etp)
-{
- ExternalThing *tetp;
-
- tetp = etp;
-
- while(tetp) {
- erts_deref_node_entry(tetp->node);
- tetp = tetp->next;
- }
-}
-
Eterm
-store_external_or_ref_(Uint **hpp, ExternalThing **etpp, Eterm ns)
+store_external_or_ref_(Uint **hpp, ErlOffHeap* oh, Eterm ns)
{
Uint i;
Uint size;
@@ -2762,8 +2744,8 @@ store_external_or_ref_(Uint **hpp, ExternalThing **etpp, Eterm ns)
erts_refc_inc(&((ExternalThing *) to_hp)->node->refc, 2);
- ((ExternalThing *) to_hp)->next = *etpp;
- *etpp = (ExternalThing *) to_hp;
+ ((struct erl_off_heap_header*) to_hp)->next = oh->first;
+ oh->first = (struct erl_off_heap_header*) to_hp;
return make_external(to_hp);
}
@@ -2792,7 +2774,7 @@ store_external_or_ref_in_proc_(Process *proc, Eterm ns)
sz = NC_HEAP_SIZE(ns);
ASSERT(sz > 0);
hp = HAlloc(proc, sz);
- return store_external_or_ref_(&hp, &MSO(proc).externals, ns);
+ return store_external_or_ref_(&hp, &MSO(proc), ns);
}
void bin_write(int to, void *to_arg, byte* buf, int sz)
diff --git a/erts/emulator/hipe/hipe_mkliterals.c b/erts/emulator/hipe/hipe_mkliterals.c
index a77aec7919..900dfc5a8a 100644
--- a/erts/emulator/hipe/hipe_mkliterals.c
+++ b/erts/emulator/hipe/hipe_mkliterals.c
@@ -261,7 +261,7 @@ static const struct literal {
/* Field offsets in a process struct */
{ "P_HP", offsetof(struct process, htop) },
{ "P_HP_LIMIT", offsetof(struct process, stop) },
- { "P_OFF_HEAP_MSO", offsetof(struct process, off_heap.mso) },
+ { "P_OFF_HEAP_FIRST", offsetof(struct process, off_heap.first) },
{ "P_MBUF", offsetof(struct process, mbuf) },
{ "P_ID", offsetof(struct process, id) },
{ "P_FLAGS", offsetof(struct process, flags) },
@@ -456,7 +456,7 @@ static const struct rts_param {
} rts_params[] = {
{ 1, "P_OFF_HEAP_FUNS",
#if !defined(HYBRID)
- 1, offsetof(struct process, off_heap.funs)
+ 1, offsetof(struct process, off_heap.first)
#endif
},
diff --git a/lib/edoc/src/edoc_lib.erl b/lib/edoc/src/edoc_lib.erl
index 47e61f7932..5b7fb1e0d2 100644
--- a/lib/edoc/src/edoc_lib.erl
+++ b/lib/edoc/src/edoc_lib.erl
@@ -472,7 +472,7 @@ uri_get_file(File0) ->
uri_get_http(URI) ->
%% Try using option full_result=false
- case catch {ok, http:request(get, {URI,[]}, [],
+ case catch {ok, httpc:request(get, {URI,[]}, [],
[{full_result, false}])} of
{'EXIT', _} ->
uri_get_http_r10(URI);
@@ -482,7 +482,7 @@ uri_get_http(URI) ->
uri_get_http_r10(URI) ->
%% Try most general form of request
- Result = (catch {ok, http:request(get, {URI,[]}, [], [])}),
+ Result = (catch {ok, httpc:request(get, {URI,[]}, [], [])}),
uri_get_http_1(Result, URI).
uri_get_http_1(Result, URI) ->
diff --git a/lib/erl_interface/src/misc/ei_decode_term.c b/lib/erl_interface/src/misc/ei_decode_term.c
index ddcbfa5a9a..75c5dc9460 100644
--- a/lib/erl_interface/src/misc/ei_decode_term.c
+++ b/lib/erl_interface/src/misc/ei_decode_term.c
@@ -34,7 +34,6 @@ int ei_decode_ei_term(const char* buf, int* index, ei_term* term)
const char* s = buf + *index, * s0 = s;
int len, i, n, sign;
char c;
- double f;
if (term == NULL) return -1;
c = term->ei_type = get8(s);
diff --git a/lib/erl_interface/src/prog/erl_call.c b/lib/erl_interface/src/prog/erl_call.c
index f0d638324d..93b84cbb36 100644
--- a/lib/erl_interface/src/prog/erl_call.c
+++ b/lib/erl_interface/src/prog/erl_call.c
@@ -812,7 +812,8 @@ static int get_module(char **mbuf, char **mname)
*mname = (char *) calloc(i+1, sizeof(char));
memcpy(*mname, start, i);
}
- free(mbuf); /* Allocated in read_stdin() */
+ if (*mbuf)
+ free(*mbuf); /* Allocated in read_stdin() */
return len;
diff --git a/lib/hipe/rtl/hipe_rtl_primops.erl b/lib/hipe/rtl/hipe_rtl_primops.erl
index 560e0259f8..0361053676 100644
--- a/lib/hipe/rtl/hipe_rtl_primops.erl
+++ b/lib/hipe/rtl/hipe_rtl_primops.erl
@@ -701,9 +701,9 @@ gen_cons(Dst, [Arg1, Arg2]) ->
%% Increase refcount
%% fe->refc++;
%%
-%% Link to the process off_heap.funs list
-%% funp->next = p->off_heap.funs;
-%% p->off_heap.funs = funp;
+%% Link to the process off_heap list
+%% funp->next = p->off_heap.first;
+%% p->off_heap.first = funp;
%%
%% Tag the thing
%% return make_fun(funp);
@@ -729,9 +729,9 @@ gen_mkfun([Dst], {_Mod, _FunId, _Arity} = MFidA, MagicNr, Index, FreeVars) ->
%% fe->refc++;
SkeletonCode = gen_fun_thing_skeleton(HP, MFidA, NumFree, MagicNr, Index),
- %% Link to the process off_heap.funs list
- %% funp->next = p->off_heap.funs;
- %% p->off_heap.funs = funp;
+ %% Link to the process off_heap list
+ %% funp->next = p->off_heap.first;
+ %% p->off_heap.first = funp;
LinkCode = gen_link_closure(HP),
%% Tag the thing and increase the heap_pointer.
@@ -797,14 +797,14 @@ gen_link_closure(FUNP) ->
end.
gen_link_closure_private(FUNP) ->
- %% Link to the process off_heap.funs list
- %% funp->next = p->off_heap.funs;
- %% p->off_heap.funs = funp;
+ %% Link fun to the process off_heap list
+ %% funp->next = p->off_heap.first;
+ %% p->off_heap.first = funp;
FunsVar = hipe_rtl:mk_new_reg(),
- [load_p_field(FunsVar,?P_OFF_HEAP_FUNS),
+ [load_p_field(FunsVar,?P_OFF_HEAP_FIRST),
hipe_rtl:mk_store(FUNP, hipe_rtl:mk_imm(?EFT_NEXT), FunsVar),
- store_p_field(FUNP,?P_OFF_HEAP_FUNS)].
+ store_p_field(FUNP,?P_OFF_HEAP_FIRST)].
gen_link_closure_non_private(_FUNP) -> [].
diff --git a/lib/hipe/rtl/hipe_tagscheme.erl b/lib/hipe/rtl/hipe_tagscheme.erl
index dc44b803a1..c0b6dfad8a 100644
--- a/lib/hipe/rtl/hipe_tagscheme.erl
+++ b/lib/hipe/rtl/hipe_tagscheme.erl
@@ -849,9 +849,9 @@ create_refc_binary(Base, Size, Flags, Dst) ->
heap_arch_spec(HP) ->
Tmp1 = hipe_rtl:mk_new_reg(), % MSO state
- [hipe_rtl_arch:pcb_load(Tmp1, ?P_OFF_HEAP_MSO),
+ [hipe_rtl_arch:pcb_load(Tmp1, ?P_OFF_HEAP_FIRST),
set_field_from_pointer({proc_bin, next}, HP, Tmp1),
- hipe_rtl_arch:pcb_store(?P_OFF_HEAP_MSO, HP)].
+ hipe_rtl_arch:pcb_store(?P_OFF_HEAP_FIRST, HP)].
test_heap_binary(Binary, TrueLblName, FalseLblName) ->
Tmp1 = hipe_rtl:mk_new_reg_gcsafe(),
diff --git a/lib/inviso/src/inviso.erl b/lib/inviso/src/inviso.erl
index de42926ffe..0eda06a5c2 100644
--- a/lib/inviso/src/inviso.erl
+++ b/lib/inviso/src/inviso.erl
@@ -129,7 +129,7 @@ start(Options) ->
add_node(Reference) ->
gen_server:call(?CONTROLLER,{add_nodes,[node()],[],Reference,any_ref},?CALL_TIMEOUT).
-add_node(Reference,Options) when list(Options) ->
+add_node(Reference,Options) when is_list(Options) ->
gen_server:call(?CONTROLLER,{add_nodes,[node()],Options,Reference,any_ref},?CALL_TIMEOUT).
%% -----------------------------------------------------------------------------
@@ -142,7 +142,7 @@ add_node(Reference,Options) when list(Options) ->
add_node_if_ref(Reference) ->
gen_server:call(?CONTROLLER,{add_nodes,[node()],[],Reference,if_ref},?CALL_TIMEOUT).
-add_node_if_ref(Reference,Options) when list(Options) ->
+add_node_if_ref(Reference,Options) when is_list(Options) ->
gen_server:call(?CONTROLLER,{add_nodes,[node()],Options,Reference,if_ref},?CALL_TIMEOUT).
%% -----------------------------------------------------------------------------
@@ -156,10 +156,10 @@ add_node_if_ref(Reference,Options) when list(Options) ->
%% system. By speicifying node() as the node where the runtime component shall
%% be started. The return value will then follow the rules of non distributed
%% returnvalues and not have a node indicator.
-add_nodes(Nodes,Reference) when list(Nodes) ->
+add_nodes(Nodes,Reference) when is_list(Nodes) ->
gen_server:call(?CONTROLLER,{add_nodes,Nodes,[],Reference,any_ref},?CALL_TIMEOUT).
-add_nodes(Nodes,Reference,Options) when list(Nodes),list(Options) ->
+add_nodes(Nodes,Reference,Options) when is_list(Nodes),is_list(Options) ->
gen_server:call(?CONTROLLER,{add_nodes,Nodes,Options,Reference,any_ref},?CALL_TIMEOUT).
%% -----------------------------------------------------------------------------
@@ -168,10 +168,10 @@ add_nodes(Nodes,Reference,Options) when list(Nodes),list(Options) ->
%%
%% As add_nodes/2,/3 but will only connect to an already existing runtime component
%% if its reference is the same as the one given as argument.
-add_nodes_if_ref(Nodes,Reference) when list(Nodes) ->
+add_nodes_if_ref(Nodes,Reference) when is_list(Nodes) ->
gen_server:call(?CONTROLLER,{add_nodes,Nodes,[],Reference,if_ref},?CALL_TIMEOUT).
-add_nodes_if_ref(Nodes,Reference,Options) when list(Nodes),list(Options) ->
+add_nodes_if_ref(Nodes,Reference,Options) when is_list(Nodes),is_list(Options) ->
gen_server:call(?CONTROLLER,{add_nodes,Nodes,Options,Reference,if_ref},?CALL_TIMEOUT).
%% -----------------------------------------------------------------------------
@@ -182,9 +182,9 @@ add_nodes_if_ref(Nodes,Reference,Options) when list(Nodes),list(Options) ->
%%
%% Change options on all or specified Nodes. This may result in for instance
%% reinitialization of overloadcheck.
-change_options(Options) when list(Options) ->
+change_options(Options) when is_list(Options) ->
gen_server:call(?CONTROLLER,{change_options,all,Options},?CALL_TIMEOUT).
-change_options(Nodes,Options) when list(Nodes),list(Options) ->
+change_options(Nodes,Options) when is_list(Nodes),is_list(Options) ->
gen_server:call(?CONTROLLER,{change_options,Nodes,Options},?CALL_TIMEOUT).
%% -----------------------------------------------------------------------------
@@ -234,7 +234,7 @@ change_options(Nodes,Options) when list(Nodes),list(Options) ->
init_tracing(TracerDataList) ->
gen_server:call(?CONTROLLER,{init_tracing,TracerDataList},?CALL_TIMEOUT).
-init_tracing(Nodes,TracerData) when list(Nodes) ->
+init_tracing(Nodes,TracerData) when is_list(Nodes) ->
gen_server:call(?CONTROLLER,{init_tracing,Nodes,TracerData},?CALL_TIMEOUT).
%% -----------------------------------------------------------------------------
@@ -270,10 +270,10 @@ stop_tracing(Nodes) when is_list(Nodes) ->
clear() ->
gen_server:call(?CONTROLLER,{clear,all,[]},?CALL_TIMEOUT).
-clear(Nodes) when list(Nodes) ->
+clear(Nodes) when is_list(Nodes) ->
gen_server:call(?CONTROLLER,{clear,Nodes,[]},?CALL_TIMEOUT).
-clear(Nodes,Options) when list(Nodes),list(Options) ->
+clear(Nodes,Options) when is_list(Nodes),is_list(Options) ->
gen_server:call(?CONTROLLER,{clear,Nodes,Options},?CALL_TIMEOUT).
%% -----------------------------------------------------------------------------
@@ -355,9 +355,9 @@ stop_all() ->
tp(Nodes,Module,Function,Arity,MatchSpec,Opts) ->
trace_pattern(Nodes,[{Module,Function,Arity,MatchSpec,Opts}],[global]).
-tp(Nodes,Module,Function,Arity,MatchSpec) when list(Nodes) ->
+tp(Nodes,Module,Function,Arity,MatchSpec) when is_list(Nodes) ->
trace_pattern(Nodes,[{Module,Function,Arity,MatchSpec,[]}],[global]);
-tp(Module,Function,Arity,MatchSpec,Opts) when atom(Module) ->
+tp(Module,Function,Arity,MatchSpec,Opts) when is_atom(Module) ->
trace_pattern(all,[{Module,Function,Arity,MatchSpec,Opts}],[global]).
tp(Module,Function,Arity,MatchSpec) ->
@@ -384,9 +384,9 @@ tp(PatternList) ->
tpl(Nodes,Module,Function,Arity,MatchSpec,Opts) ->
trace_pattern(Nodes,[{Module,Function,Arity,MatchSpec,Opts}],[local]).
-tpl(Nodes,Module,Function,Arity,MatchSpec) when list(Nodes) ->
+tpl(Nodes,Module,Function,Arity,MatchSpec) when is_list(Nodes) ->
trace_pattern(Nodes,[{Module,Function,Arity,MatchSpec,[]}],[local]);
-tpl(Module,Function,Arity,MatchSpec,Opts) when atom(Module) ->
+tpl(Module,Function,Arity,MatchSpec,Opts) when is_atom(Module) ->
trace_pattern(all,[{Module,Function,Arity,MatchSpec,Opts}],[local]).
tpl(Module,Function,Arity,MatchSpec) ->
@@ -417,12 +417,12 @@ ctp(Nodes,Module,Function,Arity) ->
ctp(Module,Function,Arity) ->
trace_pattern(all,[{Module,Function,Arity,false,[only_loaded]}],[global]).
-ctp(Nodes,PatternList) when list(PatternList) ->
+ctp(Nodes,PatternList) when is_list(PatternList) ->
trace_pattern(Nodes,
lists:map(fun({M,F,A})->{M,F,A,false,[only_loaded]} end,PatternList),
[global]).
-ctp(PatternList) when list(PatternList) ->
+ctp(PatternList) when is_list(PatternList) ->
trace_pattern(all,
lists:map(fun({M,F,A})->{M,F,A,false,[only_loaded]} end,PatternList),
[global]).
@@ -445,12 +445,12 @@ ctpl(Nodes,Module,Function,Arity) ->
ctpl(Module,Function,Arity) ->
trace_pattern(all,[{Module,Function,Arity,false,[only_loaded]}],[local]).
-ctpl(Nodes,PatternList) when list(PatternList) ->
+ctpl(Nodes,PatternList) when is_list(PatternList) ->
trace_pattern(Nodes,
lists:map(fun({M,F,A})->{M,F,A,false,[only_loaded]} end,PatternList),
[local]).
-ctpl(PatternList) when list(PatternList) ->
+ctpl(PatternList) when is_list(PatternList) ->
trace_pattern(all,
lists:map(fun({M,F,A})->{M,F,A,false,[only_loaded]} end,PatternList),
[local]).
@@ -485,19 +485,19 @@ trace_pattern(Nodes,Patterns,FlagList) ->
%% specifying a certain pid at all nodes. Or an empty TraceConfList for all
%% nodes.
%% When calling several nodes, the nodes are called in parallel.
-tf(Nodes,PidSpec,FlagList) when list(Nodes),list(FlagList) ->
+tf(Nodes,PidSpec,FlagList) when is_list(Nodes),is_list(FlagList) ->
trace_flags(Nodes,[{PidSpec, FlagList}],true).
-tf(Nodes,TraceConfList) when list(Nodes),list(TraceConfList) ->
+tf(Nodes,TraceConfList) when is_list(Nodes),is_list(TraceConfList) ->
trace_flags(Nodes,TraceConfList,true);
-tf(PidSpec,FlagList) when list(FlagList) ->
+tf(PidSpec,FlagList) when is_list(FlagList) ->
trace_flags(all,[{PidSpec,FlagList}],true).
-tf(ArgList) when list(ArgList) -> % This one has triple functionality!
+tf(ArgList) when is_list(ArgList) -> % This one has triple functionality!
case ArgList of
- [{_Process,Flags}|_] when list(Flags),atom(hd(Flags))-> % A call to all nodes.
+ [{_Process,Flags}|_] when is_list(Flags),is_atom(hd(Flags))-> % A call to all nodes.
trace_flags(all,ArgList,true);
- [{_Node,TraceConfList}|_] when list(TraceConfList),tuple(hd(TraceConfList)) ->
+ [{_Node,TraceConfList}|_] when is_list(TraceConfList),is_tuple(hd(TraceConfList)) ->
trace_flags(ArgList,true);
[{_Node,_TraceConfList,_How}|_] ->
trace_flags(ArgList);
@@ -517,15 +517,15 @@ tf(ArgList) when list(ArgList) -> % This one has triple functionality
%% The functions without a Nodes argument means all nodes, in a non-distributed
%% environment it means the local node.
%% When calling several nodes, the nodes are called in parallel.
-ctf(Nodes,PidSpec,FlagList) when list(Nodes),list(FlagList) ->
+ctf(Nodes,PidSpec,FlagList) when is_list(Nodes),is_list(FlagList) ->
trace_flags(Nodes,[{PidSpec,FlagList}],false).
-ctf(Nodes,TraceConfList) when list(Nodes),list(TraceConfList) ->
+ctf(Nodes,TraceConfList) when is_list(Nodes),is_list(TraceConfList) ->
trace_flags(Nodes,TraceConfList,false);
-ctf(PidSpec,FlagList) when list(FlagList) ->
+ctf(PidSpec,FlagList) when is_list(FlagList) ->
trace_flags(all,[{PidSpec,FlagList}],false).
-ctf(TraceConfList) when list(TraceConfList) ->
+ctf(TraceConfList) when is_list(TraceConfList) ->
trace_flags(all,TraceConfList,false).
%% -----------------------------------------------------------------------------
@@ -668,10 +668,10 @@ init_tpm(Nodes,Mod,Func,Arity,InitFunc,CallFunc,ReturnFunc,RemoveFunc) ->
tpm(Mod,Func,Arity,MS) ->
tpm(all,Mod,Func,Arity,MS).
-tpm(Nodes,Mod,Func,Arity,MS) when integer(Arity) ->
+tpm(Nodes,Mod,Func,Arity,MS) when is_integer(Arity) ->
gen_server:call(?CONTROLLER,
{meta_pattern,Nodes,{tpm,[Mod,Func,Arity,MS]}});
-tpm(Mod,Func,Arity,MS,CallFunc) when integer(Arity) ->
+tpm(Mod,Func,Arity,MS,CallFunc) when is_integer(Arity) ->
tpm(all,Mod,Func,Arity,MS,CallFunc).
tpm(Nodes,Mod,Func,Arity,MS,CallFunc) ->
@@ -695,11 +695,11 @@ tpm(Nodes,Mod,Func,Arity,MS,InitFunc,CallFunc,ReturnFunc,RemoveFunc) ->
tpm_tracer(Mod,Func,Arity,MS) ->
tpm_tracer(all,Mod,Func,Arity,MS).
-tpm_tracer(Nodes,Mod,Func,Arity,MS) when integer(Arity) ->
+tpm_tracer(Nodes,Mod,Func,Arity,MS) when is_integer(Arity) ->
gen_server:call(?CONTROLLER,
{meta_pattern,Nodes,{tpm_tracer,[Mod,Func,Arity,MS]}},
?CALL_TIMEOUT);
-tpm_tracer(Mod,Func,Arity,MS,CallFunc) when integer(Arity) ->
+tpm_tracer(Mod,Func,Arity,MS,CallFunc) when is_integer(Arity) ->
tpm_tracer(all,Mod,Func,Arity,MS,CallFunc).
tpm_tracer(Nodes,Mod,Func,Arity,MS,CallFunc) ->
@@ -878,7 +878,7 @@ cancel_suspension() ->
%% Status=running|{suspended,SReason}
%%
%% Get Status form all or specified runtime components.
-get_status(Nodes) when list(Nodes) ->
+get_status(Nodes) when is_list(Nodes) ->
gen_server:call(?CONTROLLER,{get_status,Nodes},?CALL_TIMEOUT).
get_status() ->
@@ -918,7 +918,7 @@ get_tracerdata(Nodes) when is_list(Nodes) ->
list_logs() ->
gen_server:call(?CONTROLLER,list_logs,?CALL_TIMEOUT).
-list_logs(TracerDataOrNodesList) when list(TracerDataOrNodesList) ->
+list_logs(TracerDataOrNodesList) when is_list(TracerDataOrNodesList) ->
gen_server:call(?CONTROLLER,{list_logs,TracerDataOrNodesList},?CALL_TIMEOUT).
%% ------------------------------------------------------------------------------
@@ -960,17 +960,17 @@ list_logs(TracerDataOrNodesList) when list(TracerDataOrNodesList) ->
%% Note that the client process using this function will wait until all files
%% are moved. The job can be cancelled, causing any already copied files to be
%% removed, by simply terminating the waiting client process.
-fetch_log(DestDir,Prefix) when list(DestDir),list(Prefix) ->
+fetch_log(DestDir,Prefix) when is_list(DestDir),is_list(Prefix) ->
gen_server:call(?CONTROLLER,{fetch_log,node(),all,DestDir,Prefix},infinity).
-fetch_log(ToNode,DestDir,Prefix) when atom(ToNode),list(DestDir),list(Prefix) ->
+fetch_log(ToNode,DestDir,Prefix) when is_atom(ToNode),is_list(DestDir),is_list(Prefix) ->
gen_server:call(?CONTROLLER,{fetch_log,ToNode,all,DestDir,Prefix},infinity);
-fetch_log(LogSpecList,DestDir,Prefix) when list(LogSpecList),list(DestDir),list(Prefix) ->
+fetch_log(LogSpecList,DestDir,Prefix) when is_list(LogSpecList),is_list(DestDir),is_list(Prefix) ->
gen_server:call(?CONTROLLER,{fetch_log,node(),LogSpecList,DestDir,Prefix},infinity).
fetch_log(ToNode,LogSpecList,DestDir,Prefix)
- when atom(ToNode),list(LogSpecList),list(DestDir),list(Prefix) ->
+ when is_atom(ToNode),is_list(LogSpecList),is_list(DestDir),is_list(Prefix) ->
gen_server:call(?CONTROLLER,{fetch_log,ToNode,LogSpecList,DestDir,Prefix},infinity).
%% ------------------------------------------------------------------------------
diff --git a/lib/inviso/src/inviso_c.erl b/lib/inviso/src/inviso_c.erl
index ecbd5b0778..b1597a7f35 100644
--- a/lib/inviso/src/inviso_c.erl
+++ b/lib/inviso/src/inviso_c.erl
@@ -100,7 +100,7 @@ init({_Parent,Options}) ->
end.
%% ------------------------------------------------------------------------------
-handle_call({subscribe,Pid},_From,LD) when pid(Pid) ->
+handle_call({subscribe,Pid},_From,LD) when is_pid(Pid) ->
MRef=erlang:monitor(process,Pid),
{reply,ok,LD#state{subscribers=[{Pid,MRef}|LD#state.subscribers]}};
handle_call({subscribe,Faulty},_From,LD) ->
@@ -131,7 +131,7 @@ handle_call({change_options,Nodes,Opts},_From,LD) ->
end;
handle_call({init_tracing,TracerDataList},_From,LD) ->
{reply,adapt_reply(LD,do_init_tracing(TracerDataList,LD)),LD};
-handle_call({init_tracing,Nodes,TracerData},_From,LD) when list(Nodes) ->
+handle_call({init_tracing,Nodes,TracerData},_From,LD) when is_list(Nodes) ->
TracerDataList=
lists:map(fun(N)->{N,TracerData} end,started_trace_nodes(Nodes,LD)),
{reply,adapt_reply(LD,do_init_tracing(TracerDataList,LD)),LD};
@@ -173,7 +173,7 @@ handle_call({fetch_log,ToNode,Spec,Dest,Prefix},From,LD) ->
end;
handle_call({delete_log,NodesOrNodeSpecs},_From,LD) ->
{reply,adapt_reply(LD,do_delete_log(NodesOrNodeSpecs,LD)),LD};
-handle_call({delete_log,Nodes,Specs},_From,LD) when list(Nodes) ->
+handle_call({delete_log,Nodes,Specs},_From,LD) when is_list(Nodes) ->
Reply=do_delete_log(lists:map(fun(N)->{N,Specs} end,Nodes),LD),
{reply,adapt_reply(LD,Reply),LD};
handle_call({delete_log,FaultyNodes,_Specs},_From,LD) ->
@@ -283,7 +283,7 @@ do_change_option(Nodes,Options,LD) ->
do_change_option_2([Node|Tail],Options,LD,Replies) ->
case get_node_rec(Node,LD) of
- Rec when record(Rec,node) ->
+ Rec when is_record(Rec,node) ->
Answer=?RUNTIME:change_options(Rec#node.pid,Options),
do_change_option_2(Tail,Options,LD,[{Node,Answer}|Replies]);
Error ->
@@ -333,7 +333,7 @@ do_init_tracing_2(What,_LD,_) ->
%% Returns {ok,Reply} or {error,Reason}.
distribute_tp(all,Patterns,FlagList,LD) ->
distribute_tp(started_trace_nodes(all,LD),Patterns,FlagList,LD);
-distribute_tp(Nodes,Patterns,FlagList,LD) when list(Nodes) ->
+distribute_tp(Nodes,Patterns,FlagList,LD) when is_list(Nodes) ->
RTpids=lists:map(fun(N)->case get_node_rec(N,LD) of
#node{pid=Pid} ->
{Pid,N};
@@ -354,7 +354,7 @@ distribute_tp(Faulty,_,_,_) ->
%% Returns {ok,Reply} or {error,Reason}.
distribute_tf(all,Args,How,LD) ->
distribute_tf(started_trace_nodes(all,LD),Args,How,LD);
-distribute_tf(Nodes,Args,How,LD) when list(Nodes) ->
+distribute_tf(Nodes,Args,How,LD) when is_list(Nodes) ->
RTpids=lists:map(fun(Node)->
case get_node_rec(Node,LD) of
#node{pid=Pid} ->
@@ -369,7 +369,7 @@ distribute_tf(Faulty,_,_,_) ->
{error,{badarg,Faulty}}.
%% As above but specific args for each node.
-distribute_tf(NodeArgs,How,LD) when list(NodeArgs) ->
+distribute_tf(NodeArgs,How,LD) when is_list(NodeArgs) ->
RTpidArgs=lists:map(fun({Node,Args})->
case get_node_rec(Node,LD) of
#node{pid=Pid} ->
@@ -384,7 +384,7 @@ distribute_tf(Faulty,_,_) ->
{error,{badarg,Faulty}}.
%% As above but both specific args for each node and How (set or remove flag).
-distribute_tf(NodeArgHows,LD) when list(NodeArgHows) ->
+distribute_tf(NodeArgHows,LD) when is_list(NodeArgHows) ->
RTpidArgHows=
lists:map(fun({Node,Args,How}) ->
case get_node_rec(Node,LD) of
@@ -405,7 +405,7 @@ distribute_tf(Faulty,_) ->
%% Returns {ok,Reply} or {error,Reason}.
distribute_metapattern(all,Args,LD) ->
distribute_metapattern(started_trace_nodes(all,LD),Args,LD);
-distribute_metapattern(Nodes,Args,LD) when list(Nodes) ->
+distribute_metapattern(Nodes,Args,LD) when is_list(Nodes) ->
RTpids=lists:map(fun(N)->case get_node_rec(N,LD) of
#node{pid=Pid} ->
{Pid,N};
@@ -480,7 +480,7 @@ do_cancel_suspension_2(Faulty,_,_) ->
%% Return {ok,Reply} or {error,Reason}.
do_stop_tracing(all,LD) ->
do_stop_tracing(started_trace_nodes(all,LD),LD);
-do_stop_tracing(Nodes,LD) when list(Nodes) ->
+do_stop_tracing(Nodes,LD) when is_list(Nodes) ->
RTpids=lists:map(fun(N)->case get_node_rec(N,LD) of
#node{pid=Pid} ->
{Pid,N};
@@ -580,7 +580,7 @@ do_list_logs_2(Other,_LD,_Replies) ->
%% proper strings.
do_fetch_log(ToNode,all,Dest,Prefix,From,LD) ->
do_fetch_log(ToNode,started_trace_nodes(all,LD),Dest,Prefix,From,LD);
-do_fetch_log(ToNode,Specs,Dest,Prefix,From,LD) when list(Dest),list(Prefix) ->
+do_fetch_log(ToNode,Specs,Dest,Prefix,From,LD) when is_list(Dest),is_list(Prefix) ->
CollectPid=spawn_link(ToNode,?MODULE,log_rec_init,[self(),Dest,Prefix,From]),
do_fetch_log_2(Specs,LD,CollectPid,[],[]);
do_fetch_log(_ToNode,_Specs,Dest,Prefix,From,_LD) ->
@@ -639,7 +639,7 @@ do_delete_log(NodeSpecs,LD) ->
LD,[]);
false ->
if
- list(NodeSpecs),list(hd(NodeSpecs)) -> % A list of files.
+ is_list(NodeSpecs),is_list(hd(NodeSpecs)) -> % A list of files.
do_delete_log_2(lists:map(fun(N)->{N,NodeSpecs} end,
started_trace_nodes(all,LD)),
LD,[]);
@@ -785,9 +785,9 @@ check_options(Options, Context) ->
check_options_2([],_Context,Result) ->
{ok,Result};
-check_options_2([{subscribe,Pid}|OptionsTail],start,Result) when pid(Pid) ->
+check_options_2([{subscribe,Pid}|OptionsTail],start,Result) when is_pid(Pid) ->
check_options_2(OptionsTail,start,[{subscribe,Pid}|Result]);
-check_options_2([{unsubscribe,Pid}|OptionsTail],start,Result) when pid(Pid) ->
+check_options_2([{unsubscribe,Pid}|OptionsTail],start,Result) when is_pid(Pid) ->
check_options_2(OptionsTail,start,[{unsubscribe,Pid}|Result]);
check_options_2([{dependency,How}|OptionsTail],Context,Result) ->
check_options_2(OptionsTail,Context,[{dependency,How}|Result]);
@@ -819,12 +819,12 @@ initiate_state(Options) ->
LD1#state{distributed=true}
end.
-initiate_state_2([{subscribe,Proc}|Tail],LD) when pid(Proc);atom(Proc)->
+initiate_state_2([{subscribe,Proc}|Tail],LD) when is_pid(Proc);is_atom(Proc)->
MRef=erlang:monitor(process,Proc),
initiate_state_2(Tail,LD#state{subscribers=[{Proc,MRef}|LD#state.subscribers]});
-initiate_state_2([Opt|Tail],LD) when tuple(Opt),size(Opt)>=1 ->
+initiate_state_2([Opt|Tail],LD) when is_tuple(Opt),size(Opt)>=1 ->
initiate_state_2(Tail,initiate_state_3(element(1,Opt),Opt,LD));
-initiate_state_2([Opt|Tail],LD) when atom(Opt) ->
+initiate_state_2([Opt|Tail],LD) when is_atom(Opt) ->
initiate_state_2(Tail,initiate_state_3(Opt,Opt,LD));
initiate_state_2([_|Tail],LD) ->
initiate_state_2(Tail,LD);
@@ -853,9 +853,9 @@ initiate_state_is_rt_option(_) -> false.
%% or more values associated with the Parameter, or just an atom.
merge_options([], Options) ->
Options;
-merge_options([T|DefaultTail],Options) when tuple(T),size(T)>=1 ->
+merge_options([T|DefaultTail],Options) when is_tuple(T),size(T)>=1 ->
merge_options(DefaultTail,merge_options_2(element(1,T),T,Options));
-merge_options([Param|DefaultTail],Options) when atom(Param) ->
+merge_options([Param|DefaultTail],Options) when is_atom(Param) ->
merge_options(DefaultTail,merge_options_2(Param,Param,Options));
merge_options([_|DefaultTail],Options) -> % Strange, bad default option!
merge_options(DefaultTail,Options).
@@ -868,7 +868,7 @@ merge_options_2(Param,Opt,Options) ->
[Opt|Options]
end.
-merge_options_find(Param,[T|_]) when tuple(T),element(1,T)==Param ->
+merge_options_find(Param,[T|_]) when is_tuple(T),element(1,T)==Param ->
true;
merge_options_find(Param,[Param|_]) ->
true;
@@ -883,7 +883,7 @@ merge_options_find(_,[]) ->
%% It also checks the formatting of the tracerdata since runtime components
%% does not accept too badly formatted tracerdata.
%% Returns {ok,NewTraceData} or {error,Reason}.
-check_modify_tracerdata(TracerData,LoopData) when list(TracerData) ->
+check_modify_tracerdata(TracerData,LoopData) when is_list(TracerData) ->
case lists:keysearch(trace,1,TracerData) of
{value,{_,TraceTD}} -> % Examine the trace part.
case check_modify_tracerdata(TraceTD,LoopData) of
@@ -908,7 +908,7 @@ check_modify_tracerdata({relayer,Collector},LoopData) when is_atom(Collector) ->
end;
check_modify_tracerdata({Type,Data},_LoopData) when Type==ip;Type==file ->
{ok,{Type,Data}};
-check_modify_tracerdata({Handler,Data},_LoopData) when function(Handler) ->
+check_modify_tracerdata({Handler,Data},_LoopData) when is_function(Handler) ->
{ok,{Handler,Data}};
check_modify_tracerdata(Data,_LoopData) ->
{error,{bad_tracerdata,Data}}.
@@ -999,7 +999,7 @@ set_node_rec_2(Rec,[NodeRec|Tail]) ->
%% Help function finding a node record for Node in a list of #node or in loopdata.
%% Returns the #node in question or {error,not_an_added_node}.
-get_node_rec(Node,NodeList) when list(NodeList) ->
+get_node_rec(Node,NodeList) when is_list(NodeList) ->
get_node_rec_2(Node,NodeList);
get_node_rec(Node,#state{nodes=NodeList}) ->
get_node_rec_2(Node,NodeList).
@@ -1016,7 +1016,7 @@ get_node_rec_2(Node,[_NodeRec|Tail]) ->
%% structure. Returns a new list of #node or a new loopdata structure.
delete_node_rec(Node,LD=#state{nodes=NodeList}) ->
LD#state{nodes=delete_node_rec_2(Node,NodeList)};
-delete_node_rec(Node,NodeList) when list(NodeList) ->
+delete_node_rec(Node,NodeList) when is_list(NodeList) ->
delete_node_rec_2(Node,NodeList).
delete_node_rec_2(_,[]) ->
@@ -1059,7 +1059,7 @@ log_rec_init(Parent,Dest,Prefix,From={ClientPid,_}) ->
Fetchers),
CMRef=erlang:monitor(process,ClientPid), % Monitor the client.
case log_rec_loop(Dest,Prefix,RTs,InitialReplies,CMRef) of
- Reply when list(Reply) -> % It is an ok value.
+ Reply when is_list(Reply) -> % It is an ok value.
gen_server:reply(From,{ok,Reply});
{error,Reason} ->
gen_server:reply(From,{error,Reason});
diff --git a/lib/inviso/src/inviso_lfm.erl b/lib/inviso/src/inviso_lfm.erl
index 362176c776..085048518c 100644
--- a/lib/inviso/src/inviso_lfm.erl
+++ b/lib/inviso/src/inviso_lfm.erl
@@ -87,13 +87,13 @@
%% close the outfile.
%%
%% Using merge/2 assumes you want to use default handlers writing to a file.
-merge(Files,OutputFile) when list(OutputFile) ->
+merge(Files,OutputFile) when is_list(OutputFile) ->
merge(Files,fun outfile_opener/1,fun outfile_writer/4,fun outfile_closer/1,OutputFile,off).
-merge(Files,WorkHandlerFun,HandlerData) when function(WorkHandlerFun) ->
+merge(Files,WorkHandlerFun,HandlerData) when is_function(WorkHandlerFun) ->
merge(Files,void,WorkHandlerFun,void,HandlerData,off);
-merge(Files,OutputFile,Dbg) when list(OutputFile) ->
+merge(Files,OutputFile,Dbg) when is_list(OutputFile) ->
merge(Files,fun outfile_opener/1,fun outfile_writer/4,fun outfile_closer/1,OutputFile,Dbg).
-merge(Files,WorkHandlerFun,HandlerData,Dbg) when function(WorkHandlerFun) ->
+merge(Files,WorkHandlerFun,HandlerData,Dbg) when is_function(WorkHandlerFun) ->
merge(Files,void,WorkHandlerFun,void,HandlerData,Dbg).
merge(Files,BeginHandlerFun,WorkHandlerFun,EndHandlerFun,HandlerData) ->
merge(Files,BeginHandlerFun,WorkHandlerFun,EndHandlerFun,HandlerData,off).
@@ -123,7 +123,7 @@ init_receiver(From,Files,BeginHandlerFun,WorkHandlerFun,EndHandlerFun,HandlerDat
{ok,Readers} ->
process_flag(trap_exit,true),
if
- function(BeginHandlerFun) ->
+ is_function(BeginHandlerFun) ->
case catch BeginHandlerFun(HandlerData) of
{ok,NewHandlerData} ->
init_receiver_2(From,WorkHandlerFun,EndHandlerFun,
@@ -145,7 +145,7 @@ init_receiver_2(From,WorkHandlerFun,EndHandlerFun,HandlerData,Dbg,Readers) ->
{Reply,NewHandlerData}=
loop(From,WorkHandlerFun,HandlerData,NewReaders,EntryStruct,Dbg,0),
if
- function(EndHandlerFun) ->
+ is_function(EndHandlerFun) ->
case EndHandlerFun(NewHandlerData) of
ok ->
From ! {reply,self(),Reply};
@@ -207,7 +207,7 @@ find_oldest_entry(EntryStruct) ->
case list_all_entries(EntryStruct) of
[] -> % The we are done!
done;
- EntryList when list(EntryList) -> % Find smallest timestamp in here then.
+ EntryList when is_list(EntryList) -> % Find smallest timestamp in here then.
{Pid,Node,PidMappings,_TS,Term}=
lists:foldl(fun({P,N,PMap,TS1,T},{_P,_N,_PMap,TS0,_T}) when TS1<TS0 ->
{P,N,PMap,TS1,T};
diff --git a/lib/inviso/src/inviso_lfm_tpfreader.erl b/lib/inviso/src/inviso_lfm_tpfreader.erl
index d0db4b6d02..6de4d11fe0 100644
--- a/lib/inviso/src/inviso_lfm_tpfreader.erl
+++ b/lib/inviso/src/inviso_lfm_tpfreader.erl
@@ -60,9 +60,9 @@
%% File=string()
%% Spawn on this function to start a reader process for trace-port generated
%% logfiles, possibly with inviso-generated ti-files.
-init(RecPid,LogFiles=[Tuple|_]) when tuple(Tuple) -> % Only one LogFiles.
+init(RecPid,LogFiles=[Tuple|_]) when is_tuple(Tuple) -> % Only one LogFiles.
init(RecPid,[LogFiles]);
-init(RecPid,FileStruct) when list(FileStruct) ->
+init(RecPid,FileStruct) when is_list(FileStruct) ->
logfiles_loop(RecPid,FileStruct).
%% -----------------------------------------------------------------------------
@@ -135,7 +135,7 @@ read_traceport_file(FileName,FD) ->
case file:read(FD,5) of % Trace-port file entries start with 5 bytes.
{ok,<<0,Size:32>>} -> % Each entry in a traceport file begins.
case file:read(FD,Size) of
- {ok,Bin} when binary(Bin),size(Bin)=:=Size ->
+ {ok,Bin} when is_binary(Bin),size(Bin)=:=Size ->
try binary_to_term(Bin) of
Term -> % Bin was a properly formatted term!
{ok,Term}
@@ -244,7 +244,7 @@ find_timestamp_in_term(_) -> % Don't know if there is a timestamp
%% (1) plain straight raw binary files.
handle_ti_file(FileStruct) ->
case lists:keysearch(ti_log,1,FileStruct) of
- {value,{_,[FileName]}} when list(FileName) -> % There is one ti-file in this set.
+ {value,{_,[FileName]}} when is_list(FileName) -> % There is one ti-file in this set.
case file:open(FileName,[read,raw,binary]) of
{ok,FD} ->
TIdAlias=ets:new(list_to_atom("inviso_ti_atab_"++pid_to_list(self())),
@@ -308,9 +308,9 @@ handle_ti_file_2(FD,TIdAlias,TIdUnalias) ->
handle_logfiles(FileStruct) ->
handle_logfiles_2(lists:keysearch(trace_log,1,FileStruct)).
-handle_logfiles_2({value,{_,[FileName]}}) when list(FileName)-> % One single plain file.
+handle_logfiles_2({value,{_,[FileName]}}) when is_list(FileName)-> % One single plain file.
[FileName];
-handle_logfiles_2({value,{_,Files}}) when list(Files) -> % A wrap-set.
+handle_logfiles_2({value,{_,Files}}) when is_list(Files) -> % A wrap-set.
handle_logfile_sort_wrapset(Files);
handle_logfiles_2(_) ->
[]. % Pretend there were no files otherwise.
diff --git a/lib/inviso/src/inviso_tool.erl b/lib/inviso/src/inviso_tool.erl
index 7126ba4387..05158f58fe 100644
--- a/lib/inviso/src/inviso_tool.erl
+++ b/lib/inviso/src/inviso_tool.erl
@@ -267,9 +267,9 @@ stop(UntouchedNodes) ->
%% tracing.
reconnect_nodes() ->
gen_server:call(?MODULE,{reconnect_nodes,local_runtime},?CALL_TIMEOUT).
-reconnect_nodes(Node) when atom(Node) ->
+reconnect_nodes(Node) when is_atom(Node) ->
reconnect_nodes([Node]);
-reconnect_nodes(Nodes) when list(Nodes) ->
+reconnect_nodes(Nodes) when is_list(Nodes) ->
gen_server:call(?MODULE,{reconnect_nodes,Nodes},?CALL_TIMEOUT).
%% -----------------------------------------------------------------------------
@@ -572,7 +572,7 @@ reactivator_reply(TPid,Counter) ->
init(Config) ->
case fetch_configuration(Config) of % From conf-file and Config.
- {ok,LD} when record(LD,ld) ->
+ {ok,LD} when is_record(LD,ld) ->
case start_inviso_at_c_node(LD) of
{ok,CPid} ->
LD2=start_runtime_components(LD),
@@ -650,7 +650,7 @@ start_runtime_components_2([],_,LD) ->
start_runtime_components_mk_opts(Node,{M,F,Args}) ->
case catch apply(M,F,[Node|Args]) of
- {ok,Opts} when list(Opts) ->
+ {ok,Opts} when is_list(Opts) ->
start_runtime_component_mk_opts_add_dependency(Opts);
_ ->
[?DEFAULT_DEPENDENCY]
@@ -698,7 +698,7 @@ handle_call({reconnect_nodes,Nodes},_From,LD) ->
{reply,
build_reconnect_nodes_reply(Nodes,Nodes2,NodesErr,NewLD#ld.nodes),
NewLD};
- list(Nodes) ->
+ is_list(Nodes) ->
{reply,
{ok,build_reconnect_nodes_reply(Nodes,Nodes2,NodesErr,NewLD#ld.nodes)},
NewLD}
@@ -711,7 +711,7 @@ handle_call({start_session,MoreTDGargs},_From,LD=#ld{session_state=SState}) ->
case is_tracing(SState) of
false -> % No session running.
if
- list(MoreTDGargs) ->
+ is_list(MoreTDGargs) ->
DateTime=calendar:universal_time(),
{M,F,Args}=LD#ld.tdg,
TDGargs=inviso_tool_lib:mk_tdg_args(DateTime,MoreTDGargs++Args),
@@ -757,15 +757,15 @@ handle_call({reinitiate_session,Nodes},_From,LD=#ld{session_state=SState}) ->
end;
handle_call({restore_session,{FileName,MoreTDGargs}},_From,LD=#ld{chl=OldCHL})
- when list(MoreTDGargs) ->
+ when is_list(MoreTDGargs) ->
case is_tracing(LD#ld.session_state) of
false ->
case catch make_absolute_path(FileName,LD#ld.dir) of
- AbsFileName when list(AbsFileName) ->
+ AbsFileName when is_list(AbsFileName) ->
case file:read_file(AbsFileName) of
{ok,Bin} ->
if
- list(MoreTDGargs) ->
+ is_list(MoreTDGargs) ->
case catch replace_history_chl(OldCHL,
binary_to_term(Bin)) of
{ok,CHL} -> % The file was well formatted.
@@ -803,7 +803,7 @@ handle_call({restore_session,MoreTDGargs},_From,LD=#ld{chl=CHL}) ->
case history_exists_chl(CHL) of
true -> % There is a history to redo.
if
- list(MoreTDGargs) ->
+ is_list(MoreTDGargs) ->
case h_restore_session(MoreTDGargs,LD) of
{ok,{SessionNr,ReturnVal,NewLD}} ->
{reply,
@@ -879,7 +879,7 @@ handle_call({sync_atc,{TC,Id,Vars,TimeOut}},_From,LD=#ld{session_state=SState})
case is_tracing(SState) of
true ->
if
- integer(TimeOut);TimeOut==infinity ->
+ is_integer(TimeOut);TimeOut==infinity ->
case h_sync_atc(TC,Id,Vars,TimeOut,LD) of
{ok,NewLD,Result} ->
{reply,Result,NewLD};
@@ -897,7 +897,7 @@ handle_call({sync_rtc,{TC,Vars,TimeOut}},_From,LD=#ld{session_state=SState}) ->
case is_tracing(SState) of
true ->
if
- integer(TimeOut);TimeOut==infinity ->
+ is_integer(TimeOut);TimeOut==infinity ->
case h_sync_rtc(TC,Vars,TimeOut,LD) of
{ok,NewLD,Result} ->
{reply,Result,NewLD};
@@ -929,7 +929,7 @@ handle_call({sync_dtc,{TC,Id,TimeOut}},_From,LD=#ld{session_state=SState}) ->
case is_tracing(SState) of % Check that we are tracing now.
true ->
if
- integer(TimeOut);TimeOut==infinity ->
+ is_integer(TimeOut);TimeOut==infinity ->
case h_sync_dtc(TC,Id,TimeOut,LD) of
{ok,NewLD,Result} ->
{reply,Result,NewLD};
@@ -947,7 +947,7 @@ handle_call({inviso,{Cmd,Args}},_From,LD=#ld{session_state=SState}) ->
case is_tracing(SState) of
true ->
if
- list(Args) ->
+ is_list(Args) ->
case h_inviso(Cmd,Args,LD) of
{ok,{Reply,NewLD}} ->
{reply,Reply,NewLD};
@@ -1156,7 +1156,7 @@ h_reconnect_nodes(local_runtime,LD=#ld{nodes=NodesD}) -> % Non-distributed.
_ -> % Allready connected!
{ok,{[],{error,already_connected},LD}}
end;
-h_reconnect_nodes(Nodes,LD=#ld{nodes=NodesD}) when list(Nodes) ->
+h_reconnect_nodes(Nodes,LD=#ld{nodes=NodesD}) when is_list(Nodes) ->
{Nodes2,NodesErr}=
lists:foldl(fun(N,{Nodes2,NodesErr})->
case get_state_nodes(N,NodesD) of
@@ -1246,7 +1246,7 @@ h_start_session_ctp_all_2([],Errors,Nodes) ->
%% Help function doing the actual init_tracing.
h_start_session_2(undefined,TracerData,_Errors) -> % Non distributed case.
case inviso:init_tracing(TracerData) of
- {ok,LogResult} when list(LogResult) ->
+ {ok,LogResult} when is_list(LogResult) ->
{ok,{ok,LogResult}};
{error,already_initated} -> % Perhaps adopted!?
{ok,{error,already_initiated}}; % Not necessarily wrong.
@@ -1360,7 +1360,7 @@ h_reinitiate_session_2(local_runtime,NodesD,undefined) -> % Non distributed case
_ ->
{ok,{[],{error,already_in_session}}}
end;
-h_reinitiate_session_2(Nodes,NodesD,CNode) when list(Nodes) ->
+h_reinitiate_session_2(Nodes,NodesD,CNode) when is_list(Nodes) ->
{ok,lists:foldl(fun(N,{Nodes2,NodesErr})->
case get_state_nodes(N,NodesD) of
{inactive,running} -> % Only ok case.
@@ -1515,7 +1515,7 @@ h_atc(TC,Id,Vars,LD=#ld{c_node=CNode,tc_dict=TCdict,chl=CHL},Nodes) ->
case check_bindings(Vars,TraceCase) of
{ok,Bindings} -> % Necessary vars exists in Vars.
if
- list(Nodes) -> % Nodes predefined.
+ is_list(Nodes) -> % Nodes predefined.
h_atc_2(TC,Id,CNode,CHL,LD,TraceCase,Bindings,Nodes);
true -> % Use all tracing and running nodes.
Nodes1=get_nodenames_running_nodes(LD#ld.nodes),
@@ -1769,13 +1769,13 @@ h_reactivate(Node,CNode) ->
h_save_history(HDir,Dir,FileName,SortedLog) ->
Dir0=
if
- list(HDir) -> % There is a history dir specified.
+ is_list(HDir) -> % There is a history dir specified.
HDir; % Use it then.
true ->
Dir % Else use the tool dir.
end,
case catch make_absolute_path(FileName,Dir0) of
- AbsFileName when list(AbsFileName) ->
+ AbsFileName when is_list(AbsFileName) ->
Log2=build_saved_history_data(SortedLog), % Remove stopped tracecases.
case file:write_file(AbsFileName,term_to_binary(Log2)) of
ok ->
@@ -1801,7 +1801,7 @@ h_get_autostart_data(local_runtime,_,Dependency,ASD,M,F,TDGargs,OptsG) ->
Opts=[Dependency|lists:keydelete(dependency,1,Opts0)],
{ok,{ASD,{ok,{Opts,{tdg,{M,F,CompleteTDGargs}}}}}};
-h_get_autostart_data(Nodes,CNode,Dependency,ASD,M,F,TDGargs,OptsG) when list(Nodes) ->
+h_get_autostart_data(Nodes,CNode,Dependency,ASD,M,F,TDGargs,OptsG) when is_list(Nodes) ->
{ok,{ASD,h_get_autostart_data_2(Nodes,CNode,Dependency,M,F,TDGargs,OptsG)}};
h_get_autostart_data(Nodes,_CNode,_Dependency,_ASD,_M,_F,_TDGargs,_OptsG) ->
{error,{badarg,Nodes}}.
@@ -2144,14 +2144,14 @@ expand_module_regexps(Args,_RegExpNode,_Nodes,false) ->
{ok,Args};
expand_module_regexps([PatternList],RegExpNode,Nodes,{tp,1,1}) ->
case catch expand_module_regexps_tp(PatternList,RegExpNode,Nodes) of
- NewPatternList when list(NewPatternList) ->
+ NewPatternList when is_list(NewPatternList) ->
{ok,[NewPatternList]};
{error,Reason} ->
{error,Reason}
end;
expand_module_regexps([PatternList],RegExpNode,Nodes,{ctp,1,1}) ->
case catch expand_module_regexps_ctp(PatternList,RegExpNode,Nodes) of
- NewPatternList when list(NewPatternList) ->
+ NewPatternList when is_list(NewPatternList) ->
{ok,[NewPatternList]};
{error,Reason} ->
{error,Reason}
@@ -2164,9 +2164,9 @@ expand_module_regexps([M,F,Arity],RegExpNode,Nodes,{ctp,3,1}) ->
expand_module_regexps([[{M,F,Arity}]],RegExpNode,Nodes,{ctp,1,1}).
-expand_module_regexps_tp([E={M,_,_,_,_}|Rest],RegExpNode,Nodes) when atom(M) ->
+expand_module_regexps_tp([E={M,_,_,_,_}|Rest],RegExpNode,Nodes) when is_atom(M) ->
[E|expand_module_regexps_tp(Rest,RegExpNode,Nodes)];
-expand_module_regexps_tp([{M,F,Arity,MS,Opts}|Rest],RegExpNode,Nodes) when list(M);tuple(M) ->
+expand_module_regexps_tp([{M,F,Arity,MS,Opts}|Rest],RegExpNode,Nodes) when is_list(M);is_tuple(M) ->
case inviso_tool_lib:expand_module_names([RegExpNode],
M,
[{expand_only_at,RegExpNode}]) of
@@ -2193,9 +2193,9 @@ expand_module_regexps_tp_2([M|MRest],F,Arity,MS,Opts,Rest,RegExpNode,Nodes) ->
expand_module_regexps_tp_2([],_,_,_,_,Rest,RegExpNode,Nodes) ->
expand_module_regexps_tp(Rest,RegExpNode,Nodes).
-expand_module_regexps_ctp([E={M,_,_}|Rest],RegExpNode,Nodes) when atom(M) ->
+expand_module_regexps_ctp([E={M,_,_}|Rest],RegExpNode,Nodes) when is_atom(M) ->
[E|expand_module_regexps_ctp(Rest,RegExpNode,Nodes)];
-expand_module_regexps_ctp([{M,F,Arity}|Rest],RegExpNode,Nodes) when list(M);tuple(M) ->
+expand_module_regexps_ctp([{M,F,Arity}|Rest],RegExpNode,Nodes) when is_list(M);is_tuple(M) ->
case inviso_tool_lib:expand_module_names([RegExpNode],
M,
[{expand_only_at,RegExpNode}]) of
@@ -2450,7 +2450,7 @@ fetch_configuration(Config) ->
%% Returns {ok,FileName} or 'false'. The latter if no name could be determined.
fetch_config_filename(Config) ->
case catch lists:keysearch(config_file,1,Config) of
- {value,{_,FName}} when list(FName) ->
+ {value,{_,FName}} when is_list(FName) ->
{ok,FName};
_ -> % No filename in the start argument.
fetch_config_filename_2()
@@ -2458,7 +2458,7 @@ fetch_config_filename(Config) ->
fetch_config_filename_2() ->
case application:get_env(inviso_tool_config_file) of
- {ok,FName} when list(FName) ->
+ {ok,FName} when is_list(FName) ->
{ok,FName};
_ -> % Application parameter not specified.
false % Means no config file will be used.
@@ -2499,14 +2499,14 @@ read_config_list_2(LD,Terms,Tag) ->
%% Function updating a named field in a record. Returns a new record. Note that
%% this function must be maintained due the fact that field names are removed
%% at compile time.
-update_ld_record(LD,nodes,Value) when record(LD,ld) ->
+update_ld_record(LD,nodes,Value) when is_record(LD,ld) ->
case mk_nodes(Value) of
{ok,NodesD} ->
LD#ld{nodes=NodesD};
error ->
LD
end;
-update_ld_record(LD,Tag,Value) when record(LD,ld) ->
+update_ld_record(LD,Tag,Value) when is_record(LD,ld) ->
Index=
case Tag of
c_node -> % atom()
@@ -2546,7 +2546,7 @@ update_ld_record(LD,Tag,Value) when record(LD,ld) ->
%% ActivationFileName=DeactivationFileName=string()
read_trace_case_definitions(LD) ->
case LD#ld.tc_def_file of
- TCfileName when list(TCfileName) ->
+ TCfileName when is_list(TCfileName) ->
case catch file:consult(TCfileName) of
{ok,Terms} ->
Dir=LD#ld.dir, % The working directory of the tool.
@@ -2636,8 +2636,8 @@ get_status(CNode,Nodes) ->
%% We can end up here if a session is stopped with this node suspended.
%% Returns a nodes database structure filled with the nodes Nodes.
-mk_nodes(Nodes) when list(Nodes) ->
- {ok,lists:map(fun(N) when atom(N)->{N,down} end,Nodes)};
+mk_nodes(Nodes) when is_list(Nodes) ->
+ {ok,lists:map(fun(N) when is_atom(N)->{N,down} end,Nodes)};
mk_nodes(local_runtime) -> % The non-distributed case.
down;
mk_nodes(_Nodes) ->
@@ -2783,7 +2783,7 @@ set_suspended_nodes(_,{up,{State,_}}) ->
%% This function is called when reactivation is completed. Hence it moves the
%% node to no longer suspended. Note this can mean that the node is either
%% tracing or inactive. Reactivation is not allowed for a node have trace_failure.
-set_running_nodes(Node,NodesD) when list(NodesD) ->
+set_running_nodes(Node,NodesD) when is_list(NodesD) ->
case lists:keysearch(Node,1,NodesD) of
{value,{_,AvailableStatus}} ->
lists:keyreplace(Node,1,NodesD,{Node,set_running_nodes_2(AvailableStatus)});
@@ -2902,7 +2902,7 @@ get_available_nodes([]) ->
%% suspended or not.
%% Returns {State,Status} | reactivating | down
%% where
-get_state_nodes(Node,NodesD) when list(NodesD) ->
+get_state_nodes(Node,NodesD) when is_list(NodesD) ->
case lists:keysearch(Node,1,NodesD) of
{value,{_,AvailableStatus}} ->
get_state_nodes_2(AvailableStatus);
diff --git a/lib/inviso/src/inviso_tool_lib.erl b/lib/inviso/src/inviso_tool_lib.erl
index 20a8b509ae..7953acedd6 100644
--- a/lib/inviso/src/inviso_tool_lib.erl
+++ b/lib/inviso/src/inviso_tool_lib.erl
@@ -83,7 +83,7 @@ inviso_cmd(NodeName,Func,Args) ->
%% In the non-distributed case the singlenode_expansion will be returned.
expand_module_names(_Nodes,Mod={_,'_'},_) ->
{error,{faulty_regexp_combination,Mod}};
-expand_module_names(Nodes,{DirStr,ModStr},Opts) when list(DirStr), list(ModStr) ->
+expand_module_names(Nodes,{DirStr,ModStr},Opts) when is_list(DirStr), is_list(ModStr) ->
case expand_module_names_special_regexp(DirStr) of
{ok,NewDirStr} ->
case expand_module_names_special_regexp(ModStr) of
@@ -97,11 +97,11 @@ expand_module_names(Nodes,{DirStr,ModStr},Opts) when list(DirStr), list(ModStr)
end;
expand_module_names(_,'_',_Opts) -> % If we want to trace all modules
wildcard; % we shall not expand it.
-expand_module_names(_Nodes,Mod,_Opts) when atom(Mod) ->
+expand_module_names(_Nodes,Mod,_Opts) when is_atom(Mod) ->
module; % If it is an atom, no expansion.
expand_module_names(Nodes,"*",Opts) -> % Treat this as a reg.exp.
expand_module_names(Nodes,".*",Opts);
-expand_module_names(Nodes,ModStr,Opts) when list(ModStr) ->
+expand_module_names(Nodes,ModStr,Opts) when is_list(ModStr) ->
case expand_module_names_special_regexp(ModStr) of
{ok,NewModStr} ->
expand_module_names_2(Nodes,NewModStr,Opts);
@@ -115,7 +115,7 @@ expand_module_names_2(Nodes,ModStr,Opts) ->
case get_expand_regexp_at_opts(Opts) of
{ok,Node} -> % Expansion only at this node.
case inviso_rt_lib:expand_regexp([Node],ModStr,Opts) of
- [{Node,Modules}] when list(Modules) ->
+ [{Node,Modules}] when is_list(Modules) ->
{singlenode_expansion,Modules};
[{Node,_}] -> % Most likely badrpc.
{error,{faulty_node,Node}}
@@ -130,7 +130,7 @@ expand_module_names_2(Nodes,DirStr,ModStr,Opts) ->
case get_expand_regexp_at_opts(Opts) of
{ok,Node} -> % Expansion only at this node.
case inviso_rt_lib:expand_regexp([Node],DirStr,ModStr,Opts) of
- [{Node,Modules}] when list(Modules) ->
+ [{Node,Modules}] when is_list(Modules) ->
{singlenode_expansion,Modules};
[{Node,_}] -> % Most likely badrpc.
{error,{faulty_node,Node}}
@@ -186,12 +186,12 @@ make_patterns(Catches,Opts,Dbg,NodeModsOrMods,F,A,MS) ->
make_patterns_2(Catches,OwnArg,Dbg,NodeModsOrMods,F,A,MS)
end.
-make_patterns_2(Catches,OwnArg,Dbg,[{Node,Mods}|Rest],F,A,MS) when list(Mods) ->
+make_patterns_2(Catches,OwnArg,Dbg,[{Node,Mods}|Rest],F,A,MS) when is_list(Mods) ->
TPs=make_patterns_3(Catches,OwnArg,Dbg,Mods,F,A,MS,[]),
[{Node,join_patterns(TPs)}|make_patterns_2(Catches,OwnArg,Dbg,Rest,F,A,MS)];
make_patterns_2(Catches,OwnArg,Dbg,[{_Node,_}|Rest],F,A,MS) -> % badrpc!?
make_patterns_2(Catches,OwnArg,Dbg,Rest,F,A,MS);
-make_patterns_2(Catches,OwnArg,Dbg,Modules,F,A,MS) when list(Modules) ->
+make_patterns_2(Catches,OwnArg,Dbg,Modules,F,A,MS) when is_list(Modules) ->
TPs=make_patterns_3(Catches,OwnArg,Dbg,Modules,F,A,MS,[]),
join_patterns(TPs);
make_patterns_2(_,_,_,[],_,_,_) ->
@@ -330,7 +330,7 @@ get_datetime_from_tdg_args([DateTime|_]) ->
%% Returns a list.
get_ownarg_opts(Opts) ->
case lists:keysearch(arg,1,Opts) of
- {value,{_,OwnArg}} when list(OwnArg) ->
+ {value,{_,OwnArg}} when is_list(OwnArg) ->
OwnArg;
{value,{_,OwnArg}} ->
[OwnArg];
@@ -350,7 +350,7 @@ get_disable_safety_opts(Opts) ->
get_expand_regexp_at_opts(Opts) ->
case lists:keysearch(expand_only_at,1,Opts) of
- {value,{_,Node}} when atom(Node) ->
+ {value,{_,Node}} when is_atom(Node) ->
{ok,Node};
_ ->
false
diff --git a/lib/kernel/internal_doc/distribution_handshake.txt b/lib/kernel/internal_doc/distribution_handshake.txt
index f64ebe0302..6a3ee22ed3 100644
--- a/lib/kernel/internal_doc/distribution_handshake.txt
+++ b/lib/kernel/internal_doc/distribution_handshake.txt
@@ -11,7 +11,7 @@ The TCP/IP distribution uses a handshake which expects a
connection based protocol, i.e. the protocol does not include
any authentication after the handshake procedure.
-This is not entirelly safe, as it is vulnerable against takeover
+This is not entirely safe, as it is vulnerable against takeover
attacks, but it is a tradeoff between fair safety and performance.
The cookies are never sent in cleartext and the handshake procedure
@@ -23,7 +23,7 @@ random numbers.
DEFINITIONS
-----------
-A challenge is a 32 bit integer number in big endian. Below the function
+A challenge is a 32 bit integer number in big endian order. Below the function
gen_challenge() returns a random 32 bit integer used as a challenge.
A digest is a (16 bytes) MD5 hash of [the Challenge (as text) concatenated
@@ -46,19 +46,19 @@ The cookies are text strings that can be viewed as passwords.
Every message in the handshake starts with a 16 bit big endian integer
which contains the length of the message (not counting the two initial bytes).
In erlang this corresponds to the gen_tcp option {packet, 2}. Note that after
-the handshake, the distribution switches to 4 byte backet headers.
+the handshake, the distribution switches to 4 byte packet headers.
THE HANDSHAKE IN DETAIL
-----------------------
-Imagine two nodes, node A, which initiates the handshake and node B, whitch
+Imagine two nodes, node A, which initiates the handshake and node B, which
accepts the connection.
1) connect/accept: A connects to B via TCP/IP and B accepts the connection.
2) send_name/receive_name: A sends an initial identification to B.
B receives the message. The message looks
-like this (every "square" beeing one byte and the packet header removed):
+like this (every "square" being one byte and the packet header removed):
+---+--------+--------+-----+-----+-----+-----+-----+-----+-...-+-----+
|'n'|Version0|Version1|Flag0|Flag1|Flag2|Flag3|Name0|Name1| ... |NameN|
@@ -67,7 +67,7 @@ like this (every "square" beeing one byte and the packet header removed):
The 'n' is just a message tag,
Version0 & Version1 is the distribution version selected by node A,
based on information from EPMD. (16 bit big endian)
-Flag0 ... Flag3 is capability flags, the capabilities defined in dist.hrl.
+Flag0 ... Flag3 are capability flags, the capabilities defined in dist.hrl.
(32 bit big endian)
Name0 ... NameN is the full nodename of A, as a string of bytes (the
packet length denotes how long it is).
@@ -91,9 +91,9 @@ alive: A connection to the node is already active, which either means
This is the format of the status message:
-+---+-------+-------+ ... +-------+
++---+-------+-------+-...-+-------+
|'s'|Status0|Status1| ... |StatusN|
-+---+-------+-------+ ... +-------+
++---+-------+-------+-...-+-------+
's' is the message tag
Status0 ... StatusN is the status as a string (not terminated)
@@ -111,35 +111,35 @@ initially sent from A to B, with the addition of a 32 bit challenge:
+---+--------+--------+-----+-----+-----+-----+-----+-----+-----+-----+---
|'n'|Version0|Version1|Flag0|Flag1|Flag2|Flag3|Chal0|Chal1|Chal2|Chal3|
-+---+--------+--------+-----+-----+-----+-----+-----+-----+---- +-----+---
++---+--------+--------+-----+-----+-----+-----+-----+-----+-----+-----+---
------+-----+-...-+-----+
Name0|Name1| ... |NameN|
------+-----+-... +-----+
-Where Chal0 ... Chal3 is the challenge as a 32 bit biog endian integer
+Where Chal0 ... Chal3 is the challenge as a 32 bit big endian integer
and the other fields are B's version, flags and full nodename.
5) send_challenge_reply/recv_challenge_reply: Now A has generated
-a digest and it's own challenge. Those are sent together in a package
+a digest and its own challenge. Those are sent together in a package
to B:
-+---+-----+-----+-----+-----+-----+-----+-----+-----+
-|'r'|Chal0|Chal1|Chal2|Chal3|Dige0|Dige1|Dige2|Dige3|
-+---+-----+-----+-----+-----+-----+-----+---- +-----+
++---+-----+-----+-----+-----+-----+-----+-----+-----+-...-+------+
+|'r'|Chal0|Chal1|Chal2|Chal3|Dige0|Dige1|Dige2|Dige3| ... |Dige15|
++---+-----+-----+-----+-----+-----+-----+-----+-----+-...-+------+
Where 'r' is the tag, Chal0 ... Chal3 is A's challenge for B to handle and
-Dige0 ... Dige3 is the digest that A constructed from the challenge B sent
+Dige0 ... Dige15 is the digest that A constructed from the challenge B sent
in the previous step.
6) recv_challenge_ack/send_challenge_ack: B checks that the digest received
from A is correct and generates a digest from the challenge received from
A. The digest is then sent to A. The message looks like this:
-+---+-----+-----+-----+-----+
-|'a'|Dige0|Dige1|Dige2|Dige3|
-+---+-----+-----+---- +-----+
++---+-----+-----+-----+-----+-...-+------+
+|'a'|Dige0|Dige1|Dige2|Dige3| ... |Dige15|
++---+-----+-----+-----+-----+-...-+------+
-Where 'a' is the tag and Dige0 ... Dige3 is the digest calculated by B
+Where 'a' is the tag and Dige0 ... Dige15 is the digest calculated by B
for A's challenge.
7) A checks the digest from B and the connection is up.
@@ -206,7 +206,7 @@ Currently the following capability flags are defined:
%% The node implements distributed process monitoring.
-define(DFLAG_DIST_MONITOR,8).
-%% The node uses separate tag for fun's (labmdas) in the distribution protocol.
+%% The node uses separate tag for fun's (lambdas) in the distribution protocol.
-define(DFLAG_FUN_TAGS,16).
An R6 erlang node implements all of the above, while a C or Java node only
diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl
index 42d4818f08..ec256d5806 100644
--- a/lib/kernel/src/code.erl
+++ b/lib/kernel/src/code.erl
@@ -304,6 +304,8 @@ do_start(Flags) ->
true ->
ok
end,
+ % Quietly load the native code for all modules loaded so far.
+ catch load_native_code_for_all_loaded(),
Ok2;
Other ->
Other
@@ -496,3 +498,19 @@ has_ext(Ext, Extlen,File) ->
to_path(X) ->
filename:join(packages:split(X)).
+
+-spec load_native_code_for_all_loaded() -> ok.
+load_native_code_for_all_loaded() ->
+ Architecture = erlang:system_info(hipe_architecture),
+ ChunkName = hipe_unified_loader:chunk_name(Architecture),
+ lists:foreach(fun({Module, BeamFilename}) ->
+ case code:is_module_native(Module) of
+ false ->
+ case beam_lib:chunks(BeamFilename, [ChunkName]) of
+ {ok,{_,[{_,Bin}]}} when is_binary(Bin) ->
+ load_native_partial(Module, Bin);
+ {error, beam_lib, _} -> ok
+ end;
+ true -> ok
+ end
+ end, all_loaded()).
diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl
index 08b6477c9d..c9437df258 100644
--- a/lib/kernel/test/code_SUITE.erl
+++ b/lib/kernel/test/code_SUITE.erl
@@ -31,7 +31,7 @@
where_is_file_cached/1, where_is_file_no_cache/1,
purge_stacktrace/1, mult_lib_roots/1, bad_erl_libs/1,
code_archive/1, code_archive2/1, on_load/1,
- on_load_embedded/1, on_load_errors/1]).
+ on_load_embedded/1, on_load_errors/1, native_early_modules/1]).
-export([init_per_testcase/2, fin_per_testcase/2,
init_per_suite/1, end_per_suite/1,
@@ -53,7 +53,7 @@ all(suite) ->
where_is_file_no_cache, where_is_file_cached,
purge_stacktrace, mult_lib_roots, bad_erl_libs,
code_archive, code_archive2, on_load, on_load_embedded,
- on_load_errors].
+ on_load_errors, native_early_modules].
init_per_suite(Config) ->
%% The compiler will no longer create a Beam file if
@@ -1333,6 +1333,34 @@ do_on_load_error(ReturnValue) ->
?line {undef,[{on_load_error,main,[]}|_]} = Exit
end.
+native_early_modules(suite) -> [];
+native_early_modules(doc) -> ["Test that the native code of early loaded modules is loaded"];
+native_early_modules(Config) when is_list(Config) ->
+ case erlang:system_info(hipe_architecture) of
+ undefined ->
+ {skip,"Native code support is not enabled"};
+ Architecture ->
+ native_early_modules_1(Architecture)
+ end.
+
+native_early_modules_1(Architecture) ->
+ ?line {lists, ListsBinary, _ListsFilename} = code:get_object_code(lists),
+ ?line ChunkName = hipe_unified_loader:chunk_name(Architecture),
+ ?line NativeChunk = beam_lib:chunks(ListsBinary, [ChunkName]),
+ ?line IsHipeCompiled = case NativeChunk of
+ {ok,{_,[{_,Bin}]}} when is_binary(Bin) -> true;
+ {error, beam_lib, _} -> false
+ end,
+ case IsHipeCompiled of
+ false ->
+ {skip,"OTP apparently not configured with --enable-native-libs"};
+ true ->
+ ?line true = lists:all(fun code:is_module_native/1,
+ [ets,file,filename,gb_sets,gb_trees,
+ hipe_unified_loader,lists,os,packages]),
+ ok
+ end.
+
%%-----------------------------------------------------------------
%% error_logger handler.
%% (Copied from stdlib/test/proc_lib_SUITE.erl.)
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index 13c87ca005..5f26b7d431 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -63,7 +63,8 @@
meta_lookup_unnamed_read/1, meta_lookup_unnamed_write/1,
meta_lookup_named_read/1, meta_lookup_named_write/1,
meta_newdel_unnamed/1, meta_newdel_named/1]).
--export([smp_insert/1, smp_fixed_delete/1, smp_unfix_fix/1, smp_select_delete/1, otp_8166/1]).
+-export([smp_insert/1, smp_fixed_delete/1, smp_unfix_fix/1, smp_select_delete/1,
+ otp_8166/1, otp_8732/1]).
-export([exit_large_table_owner/1,
exit_many_large_table_owner/1,
exit_many_tables_owner/1,
@@ -129,7 +130,7 @@ all(suite) ->
t_select_delete, t_ets_dets, memory,
t_bucket_disappears,
select_fail,t_insert_new, t_repair_continuation, otp_5340, otp_6338,
- otp_6842_select_1000, otp_7665,
+ otp_6842_select_1000, otp_7665, otp_8732,
meta_wb,
grow_shrink, grow_pseudo_deleted, shrink_pseudo_deleted,
meta_smp,
@@ -391,7 +392,7 @@ memory(Config) when is_list(Config) ->
?line erts_debug:set_internal_state(available_internal_state, true),
?line ok = chk_normal_tab_struct_size(),
?line L = [T1,T2,T3,T4] = fill_sets_int(1000),
- ?line XRes1 = adjust_xmem(L, {16862,16072,16072,16078}),
+ ?line XRes1 = adjust_xmem(L, {14862,14072,14072,14078}),
?line Res1 = {?S(T1),?S(T2),?S(T3),?S(T4)},
?line lists:foreach(fun(T) ->
Before = ets:info(T,size),
@@ -402,7 +403,7 @@ memory(Config) when is_list(Config) ->
[Key, ets:info(T,type), Before, ets:info(T,size), Objs])
end,
L),
- ?line XRes2 = adjust_xmem(L, {16849,16060,16048,16054}),
+ ?line XRes2 = adjust_xmem(L, {14851,14062,14052,14058}),
?line Res2 = {?S(T1),?S(T2),?S(T3),?S(T4)},
?line lists:foreach(fun(T) ->
Before = ets:info(T,size),
@@ -413,7 +414,7 @@ memory(Config) when is_list(Config) ->
[Key, ets:info(T,type), Before, ets:info(T,size), Objs])
end,
L),
- ?line XRes3 = adjust_xmem(L, {16836,16048,16024,16030}),
+ ?line XRes3 = adjust_xmem(L, {14840,14052,14032,14038}),
?line Res3 = {?S(T1),?S(T2),?S(T3),?S(T4)},
?line lists:foreach(fun(T) ->
?line ets:delete_all_objects(T)
@@ -5010,8 +5011,14 @@ verify_table_load(T) ->
end.
-
-
+otp_8732(doc) -> ["ets:select on a tree with NIL key object"];
+otp_8732(Config) when is_list(Config) ->
+ Tab = ets:new(noname,[ordered_set]),
+ filltabstr(Tab,999),
+ ets:insert(Tab,{[],"nasty NIL object"}),
+ ?line [] = ets:match(Tab,{'_',nomatch}), %% Will hang if bug not fixed
+ ok.
+
smp_select_delete(suite) -> [];
smp_select_delete(doc) ->