diff options
author | Björn Gustavsson <[email protected]> | 2019-06-04 12:51:54 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2019-06-14 12:58:22 +0200 |
commit | 5943ff2cfb38f7ad572bb76abf425dd128dab72d (patch) | |
tree | e1757860cca984cf8e2f93992e88a36efaeedb73 /erts/emulator/beam/erl_fun.c | |
parent | 0ddddac7691521f76d984140ec5d82db5ab1e3ea (diff) | |
download | otp-5943ff2cfb38f7ad572bb76abf425dd128dab72d.tar.gz otp-5943ff2cfb38f7ad572bb76abf425dd128dab72d.tar.bz2 otp-5943ff2cfb38f7ad572bb76abf425dd128dab72d.zip |
Support sharing of fun entries in the runtime system
Before OTP 23, there had to be a one-to-one correspodence between
`make_fun2` instructions and fun entries.
In the OTP 23 runtime system, start keying the fun entries with the
explicit ("new") index included in the fun entry. That will allow
multiple `make_fun2` instructions to refer to the same entry in
the fun table.
This change is safe for code compiled by OTP R15B or later, because
the old and new indices are identical. The loader will refuse to
load code where the old and new indices are not equal unless the
code is known to be compiled with an OTP 23 compiler.
Diffstat (limited to 'erts/emulator/beam/erl_fun.c')
-rw-r--r-- | erts/emulator/beam/erl_fun.c | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/erts/emulator/beam/erl_fun.c b/erts/emulator/beam/erl_fun.c index ca1e6bf5e7..257f9bf5b3 100644 --- a/erts/emulator/beam/erl_fun.c +++ b/erts/emulator/beam/erl_fun.c @@ -109,12 +109,12 @@ erts_put_fun_entry2(Eterm mod, int old_uniq, int old_index, ASSERT(is_atom(mod)); template.old_uniq = old_uniq; - template.old_index = old_index; + template.index = index; template.module = mod; erts_fun_write_lock(); fe = (ErlFunEntry *) hash_put(&erts_fun_table, (void*) &template); sys_memcpy(fe->uniq, uniq, sizeof(fe->uniq)); - fe->index = index; + fe->old_index = old_index; fe->arity = arity; refc = erts_refc_inctest(&fe->refc, 0); if (refc < 2) /* New or pending delete */ @@ -131,7 +131,7 @@ erts_get_fun_entry(Eterm mod, int uniq, int index) ASSERT(is_atom(mod)); template.old_uniq = uniq; - template.old_index = index; + template.index = index; template.module = mod; erts_fun_read_lock(); ret = (ErlFunEntry *) hash_get(&erts_fun_table, (void*) &template); @@ -287,15 +287,27 @@ erts_dump_fun_entries(fmtfn_t to, void *to_arg) static HashValue fun_hash(ErlFunEntry* obj) { - return (HashValue) (obj->old_uniq ^ obj->old_index ^ atom_val(obj->module)); + return (HashValue) (obj->old_uniq ^ obj->index ^ atom_val(obj->module)); } static int fun_cmp(ErlFunEntry* obj1, ErlFunEntry* obj2) { - return !(obj1->module == obj2->module && + /* + * OTP 23: Use 'index' (instead of 'old_index') when comparing fun + * entries. In OTP 23, multiple make_fun2 instructions may refer to the + * the same 'index' (for the wrapper function generated for the + * 'fun F/A' syntax). + * + * This is safe when loading code compiled with OTP R15 and later, + * because since R15 (2011), the 'index' has been reliably equal + * to 'old_index'. The loader refuses to load modules compiled before + * OTP R15. + */ + + return !(obj1->module == obj2->module && obj1->old_uniq == obj2->old_uniq && - obj1->old_index == obj2->old_index); + obj1->index == obj2->index); } static ErlFunEntry* @@ -305,7 +317,7 @@ fun_alloc(ErlFunEntry* template) sizeof(ErlFunEntry)); obj->old_uniq = template->old_uniq; - obj->old_index = template->old_index; + obj->index = template->index; obj->module = template->module; erts_refc_init(&obj->refc, -1); obj->address = unloaded_fun; |