aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/beam_bif_load.c
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2011-08-23 05:41:28 +0200
committerBjörn Gustavsson <[email protected]>2011-11-17 10:09:51 +0100
commit379064981ecccc8c099623cdb93894d02a6bcdc1 (patch)
tree4e93169a9e15729084e71a3983acf962df7679f5 /erts/emulator/beam/beam_bif_load.c
parent6107d4123f23a48d77b1852df88cb0fee3a23539 (diff)
downloadotp-379064981ecccc8c099623cdb93894d02a6bcdc1.tar.gz
otp-379064981ecccc8c099623cdb93894d02a6bcdc1.tar.bz2
otp-379064981ecccc8c099623cdb93894d02a6bcdc1.zip
Allow refc binaries in literal pools
To simplify the implementation of literal pools (constant pools) for the R12 release, a shortcut was taken regarding binaries -- all binaries would be stored as heap binaries regardless of size. To allow a module containing literals to be unloaded, literal terms are copied when sent to another process. That means that huge literal binaries will also be copied if they are sent to another process, which could be surprising. Another problem is that the arity field in the header for the heap object may not be wide enough to handle big binaries. Therefore, bite the bullet and allow refc binaries to be stored in literal pools. In short, the following need to be changed: * Each loaded module needs a MSO list, linking all refc binaries in the literal pool. * When check_process_code/2 copies literals to a process heap, it must link each referenced binary into the MSO list for the process and increment the reference counter for the binary. * purge_module/1 must decrement the reference counter for each refc binary in the literal pool.
Diffstat (limited to 'erts/emulator/beam/beam_bif_load.c')
-rw-r--r--erts/emulator/beam/beam_bif_load.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index efb72cd3e7..bc8c001454 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -40,6 +40,7 @@ static Eterm check_process_code(Process* rp, Module* modp);
static void delete_code(Process *c_p, ErtsProcLocks c_p_locks, Module* modp);
static void delete_export_references(Eterm module);
static int purge_module(int module);
+static void decrement_refc(BeamInstr* code);
static int is_native(BeamInstr* code);
static int any_heap_ref_ptrs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size);
static int any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size);
@@ -553,6 +554,7 @@ check_process_code(Process* rp, Module* modp)
} else {
Eterm* literals;
Uint lit_size;
+ struct erl_off_heap_header* oh;
/*
* Try to get rid of constants by by garbage collecting.
@@ -566,7 +568,9 @@ check_process_code(Process* rp, Module* modp)
(void) erts_garbage_collect(rp, 0, rp->arg_reg, rp->arity);
literals = (Eterm *) modp->old_code[MI_LITERALS_START];
lit_size = (Eterm *) modp->old_code[MI_LITERALS_END] - literals;
- erts_garbage_collect_literals(rp, literals, lit_size);
+ oh = (struct erl_off_heap_header *)
+ modp->old_code[MI_LITERALS_OFF_HEAP];
+ erts_garbage_collect_literals(rp, literals, lit_size, oh);
}
}
return am_false;
@@ -664,6 +668,7 @@ purge_module(int module)
end = (BeamInstr *)((char *)code + modp->old_code_length);
erts_cleanup_funs_on_purge(code, end);
beam_catches_delmod(modp->old_catches, code, modp->old_code_length);
+ decrement_refc(code);
erts_free(ERTS_ALC_T_CODE, (void *) code);
modp->old_code = NULL;
modp->old_code_length = 0;
@@ -673,6 +678,23 @@ purge_module(int module)
}
static void
+decrement_refc(BeamInstr* code)
+{
+ struct erl_off_heap_header* oh =
+ (struct erl_off_heap_header *) code[MI_LITERALS_OFF_HEAP];
+
+ while (oh) {
+ Binary* bptr;
+ ASSERT(thing_subtag(oh->thing_word) == REFC_BINARY_SUBTAG);
+ bptr = ((ProcBin*)oh)->val;
+ if (erts_refc_dectest(&bptr->refc, 0) == 0) {
+ erts_bin_free(bptr);
+ }
+ oh = oh->next;
+ }
+}
+
+static void
remove_from_address_table(BeamInstr* code)
{
int i;