diff options
Diffstat (limited to 'erts/emulator/beam/beam_bif_load.c')
-rw-r--r-- | erts/emulator/beam/beam_bif_load.c | 65 |
1 files changed, 44 insertions, 21 deletions
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c index 27d6823d3c..8fc8613c66 100644 --- a/erts/emulator/beam/beam_bif_load.c +++ b/erts/emulator/beam/beam_bif_load.c @@ -242,7 +242,7 @@ struct m { Binary* code; Eterm module; Module* modp; - Uint exception; + Eterm exception; }; static Eterm staging_epilogue(Process* c_p, int, Eterm res, int, struct m*, int); @@ -263,7 +263,7 @@ exception_list(Process* p, Eterm tag, struct m* mp, Sint exceptions) Eterm res = NIL; while (exceptions > 0) { - if (mp->exception) { + if (is_value(mp->exception)) { res = CONS(hp, mp->module, res); hp += 2; exceptions--; @@ -366,9 +366,9 @@ finish_loading_1(BIF_ALIST_1) exceptions = 0; for (i = 0; i < n; i++) { - p[i].exception = 0; + p[i].exception = THE_NON_VALUE; if (p[i].modp->seen) { - p[i].exception = 1; + p[i].exception = am_duplicated; exceptions++; } p[i].modp->seen = 1; @@ -401,9 +401,9 @@ finish_loading_1(BIF_ALIST_1) exceptions = 0; for (i = 0; i < n; i++) { - p[i].exception = 0; + p[i].exception = THE_NON_VALUE; if (p[i].modp->curr.code_hdr && p[i].modp->old.code_hdr) { - p[i].exception = 1; + p[i].exception = am_not_purged; exceptions++; } } @@ -424,7 +424,7 @@ finish_loading_1(BIF_ALIST_1) retval = erts_finish_loading(p[i].code, BIF_P, 0, &mod); ASSERT(retval == NIL || retval == am_on_load); if (retval == am_on_load) { - p[i].exception = 1; + p[i].exception = am_on_load; exceptions++; } } @@ -456,8 +456,9 @@ staging_epilogue(Process* c_p, int commit, Eterm res, int is_blocking, erts_commit_staging_code_ix(); if (loaded) { int i; - for (i=0; i < nloaded; i++) { - set_default_trace_pattern(loaded[i].module); + for (i=0; i < nloaded; i++) { + if (loaded[i].exception != am_on_load) + set_default_trace_pattern(loaded[i].module); } } } @@ -1051,23 +1052,32 @@ erts_proc_copy_literal_area(Process *c_p, int *redsp, int fcalls, int gc_allowed return am_ok; -literal_gc: +literal_gc: { + int hibernated = !!(c_p->flags & F_HIBERNATED); + int gc_cost; - if (!gc_allowed) - return am_need_gc; + if (!gc_allowed) + return am_need_gc; - if (c_p->flags & F_DISABLE_GC) - return THE_NON_VALUE; + if (c_p->flags & F_DISABLE_GC) + return THE_NON_VALUE; - FLAGS(c_p) |= F_NEED_FULLSWEEP; + FLAGS(c_p) |= F_NEED_FULLSWEEP; - *redsp += erts_garbage_collect_nobump(c_p, 0, c_p->arg_reg, c_p->arity, fcalls); + gc_cost = erts_garbage_collect_nobump(c_p, 0, c_p->arg_reg, c_p->arity, fcalls); + *redsp += gc_cost; - erts_garbage_collect_literals(c_p, (Eterm *) literals, lit_bsize, oh); + erts_garbage_collect_literals(c_p, (Eterm *) literals, lit_bsize, oh); - *redsp += lit_bsize / 64; /* Need, better value... */ + *redsp += lit_bsize / 64; /* Need, better value... */ - return am_ok; + if (hibernated) { + erts_garbage_collect_hibernate(c_p); + *redsp += gc_cost; + } + + return am_ok; + } } static Eterm @@ -1154,6 +1164,8 @@ check_process_code(Process* rp, Module* modp, Uint flags, int *redsp, int fcalls Eterm* sp; int done_gc = 0; int need_gc = 0; + int hibernated = !!(rp->flags & F_HIBERNATED); + int gc_cost = 0; ErtsMessage *msgp; ErlHeapFragment *hfrag; @@ -1288,8 +1300,13 @@ check_process_code(Process* rp, Module* modp, Uint flags, int *redsp, int fcalls while (1) { /* Check heap, stack etc... */ - if (check_mod_funs(rp, &rp->off_heap, mod_start, mod_size)) + if (check_mod_funs(rp, &rp->off_heap, mod_start, mod_size)) { + if (hibernated) { + /* GC wont help; everything on heap is live... */ + return am_true; + } goto try_gc; + } if (any_heap_ref_ptrs(&rp->fvalue, &rp->fvalue+1, literals, lit_bsize)) { rp->freason = EXC_NULL; rp->fvalue = NIL; @@ -1379,7 +1396,9 @@ check_process_code(Process* rp, Module* modp, Uint flags, int *redsp, int fcalls if (need_gc & ERTS_ORDINARY_GC__) { FLAGS(rp) |= F_NEED_FULLSWEEP; - *redsp += erts_garbage_collect_nobump(rp, 0, rp->arg_reg, rp->arity, fcalls); + gc_cost = erts_garbage_collect_nobump(rp, 0, rp->arg_reg, rp->arity, fcalls); + ASSERT(!hibernated || (need_gc & ERTS_LITERAL_GC__)); + *redsp += gc_cost; done_gc |= ERTS_ORDINARY_GC__; } if (need_gc & ERTS_LITERAL_GC__) { @@ -1388,6 +1407,10 @@ check_process_code(Process* rp, Module* modp, Uint flags, int *redsp, int fcalls *redsp += lit_bsize / 64; /* Need, better value... */ erts_garbage_collect_literals(rp, (Eterm*)literals, lit_bsize, oh); done_gc |= ERTS_LITERAL_GC__; + if (hibernated) { + erts_garbage_collect_hibernate(rp); + *redsp += gc_cost; + } } need_gc = 0; } |