From 600e82d4808a013296c6ade531e6a29afee5ae6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 14 Nov 2011 09:14:58 +0100 Subject: beam_load.c: Remove the unused struct LoadedCode --- erts/emulator/beam/beam_load.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'erts/emulator/beam') diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index 3836f1ae96..2d75990c3f 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -351,11 +351,6 @@ typedef struct { int loc_size; /* Size of location info in bytes (2/4) */ } LoaderState; -typedef struct { - unsigned num_functions; /* Number of functions. */ - Eterm* func_tab[1]; /* Pointers to each function. */ -} LoadedCode; - /* * Layout of the line table. */ -- cgit v1.2.3 From db8f3882288990dfc007765decad01233c455cbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 14 Nov 2011 13:59:47 +0100 Subject: beam_load.c: Simplify handling of the bs_put_string_II instruction Remove the special-case handling of the bs_put_string_II instruction; simply use the string patch mechanism that is already used for the i_bs_match_string_* instructions. --- erts/emulator/beam/beam_load.c | 43 +----------------------------------------- 1 file changed, 1 insertion(+), 42 deletions(-) (limited to 'erts/emulator/beam') diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index 2d75990c3f..e98210d39c 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -287,7 +287,6 @@ typedef struct { BeamInstr* code; /* Loaded code. */ int ci; /* Current index into loaded code. */ Label* labels; - BeamInstr new_bs_put_strings; /* Linked list of i_new_bs_put_string instructions. */ StringPatch* string_patches; /* Linked list of position into string table to patch. */ BeamInstr catches; /* Linked list of catch_yf instructions. */ unsigned loaded_size; /* Final size of code when loaded. */ @@ -1602,7 +1601,6 @@ read_code_header(LoaderState* stp) #endif } - stp->new_bs_put_strings = 0; stp->catches = 0; return 1; @@ -2314,32 +2312,6 @@ load_code(LoaderState* stp) stp->on_load = ci; break; case op_bs_put_string_II: - { - /* - * At entry: - * - * code[ci-3] &&lb_i_new_bs_put_string_II - * code[ci-2] length of string - * code[ci-1] offset into string table - * - * Since we don't know the address of the string table yet, - * just check the offset and length for validity, and use - * the instruction field as a link field to link all put_string - * instructions into a single linked list. At exit: - * - * code[ci-3] pointer to next i_new_bs_put_string instruction (or 0 - * if this is the last) - */ - Uint offset = code[ci-1]; - Uint len = code[ci-2]; - unsigned strtab_size = stp->chunks[STR_CHUNK].size; - if (offset > strtab_size || offset + len > strtab_size) { - LoadError2(stp, "invalid string reference %d, size %d", offset, len); - } - code[ci-3] = stp->new_bs_put_strings; - stp->new_bs_put_strings = ci - 3; - } - break; case op_i_bs_match_string_rfII: case op_i_bs_match_string_xfII: new_string_patch(stp, ci-1); @@ -3876,7 +3848,6 @@ freeze_code(LoaderState* stp) { BeamInstr* code = stp->code; Uint *literal_end = NULL; - Uint index; int i; byte* str_table; unsigned strtab_size = stp->chunks[STR_CHUNK].size; @@ -4096,20 +4067,8 @@ freeze_code(LoaderState* stp) ((byte *) code) + size); /* - * Go through all i_new_bs_put_strings instructions, restore the pointer to - * the instruction and convert string offsets to pointers (to the - * FIRST character). + * Patch all instructions that refer to the string table. */ - - index = stp->new_bs_put_strings; - while (index != 0) { - Uint next = code[index]; - code[index] = BeamOpCode(op_bs_put_string_II); - code[index+2] = (BeamInstr) (str_table + code[index+2]); - index = next; - } - CHKBLK(ERTS_ALC_T_CODE,code); - { StringPatch* sp = stp->string_patches; -- cgit v1.2.3 From 757a4720645366af1aace7469a6f5e7b9be7ab45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 10 Nov 2011 06:19:56 +0100 Subject: Remove the useless -l option The -l option used to print information about modules being loaded, but now it prints very little information. --- erts/emulator/beam/beam_bif_load.c | 6 ------ erts/emulator/beam/erl_init.c | 7 ------- erts/emulator/beam/global.h | 1 - 3 files changed, 14 deletions(-) (limited to 'erts/emulator/beam') diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c index 294b1578be..9ee4bb6878 100644 --- a/erts/emulator/beam/beam_bif_load.c +++ b/erts/emulator/beam/beam_bif_load.c @@ -654,9 +654,6 @@ purge_module(int module) * Any code to purge? */ if (modp->old_code == 0) { - if (display_loads) { - erts_printf("No code to purge for %T\n", make_atom(module)); - } return -1; } @@ -785,9 +782,6 @@ beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks, Eterm module) if (modp->code != NULL && modp->old_code != NULL) { return -3; } else if (modp->old_code == NULL) { /* Make the current version old. */ - if (display_loads) { - erts_printf("saving old code\n"); - } delete_code(c_p, c_p_locks, modp); delete_export_references(module); } diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c index 7c047891d9..fd15df731a 100644 --- a/erts/emulator/beam/erl_init.c +++ b/erts/emulator/beam/erl_init.c @@ -92,7 +92,6 @@ int erts_use_sender_punish; */ Uint display_items; /* no of items to display in traces etc */ -Uint display_loads; /* print info about loaded modules */ int H_MIN_SIZE; /* The minimum heap grain */ int BIN_VH_MIN_SIZE; /* The minimum binary virtual*/ @@ -499,8 +498,6 @@ void erts_usage(void) erts_fprintf(stderr, "-K boolean enable or disable kernel poll\n"); - erts_fprintf(stderr, "-l turn on auto load tracing\n"); - erts_fprintf(stderr, "-M memory allocator switches,\n"); erts_fprintf(stderr, " see the erts_alloc(3) documentation for more info.\n"); @@ -616,7 +613,6 @@ early_init(int *argc, char **argv) /* erts_printf_eterm_func = erts_printf_term; erts_disable_tolerant_timeofday = 0; display_items = 200; - display_loads = 0; erts_backtrace_depth = DEFAULT_BACKTRACE_SIZE; erts_async_max_threads = 0; erts_async_thread_suggested_stack_size = ERTS_ASYNC_THREAD_MIN_STACK_SIZE; @@ -981,9 +977,6 @@ erl_start(int argc, char **argv) erts_fprintf(stderr, "%s unknown flag %s\n", argv[0], argv[i]); erts_usage(); } - case 'l': - display_loads++; - break; case 'L': erts_no_line_info = 1; break; diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 4a4973baab..e4e9386dd7 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -555,7 +555,6 @@ extern Eterm node_cookie; extern erts_smp_atomic_t erts_bytes_out; /* no bytes written out */ extern erts_smp_atomic_t erts_bytes_in; /* no bytes sent into the system */ extern Uint display_items; /* no of items to display in traces etc */ -extern Uint display_loads; /* print info about loaded modules */ extern int erts_backtrace_depth; extern erts_smp_atomic32_t erts_max_gen_gcs; -- cgit v1.2.3 From b67d3e5447f4b2bca3ed92f3db84adb3f79f9b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 9 Nov 2011 17:27:52 +0100 Subject: BEAM loader: Clean up handling of error reasons There is no reason to have erts_load_module() return integer values, only to have the caller convert the values to atoms. Return the appropriate atom directly from the place where the error is generated instead. Return NIL if the module was successfully loaded. --- erts/emulator/beam/beam_bif_load.c | 42 ++++++++------------------------------ erts/emulator/beam/beam_load.c | 40 ++++++++++++++++++------------------ erts/emulator/beam/beam_load.h | 3 ++- erts/emulator/beam/erl_init.c | 7 ++++--- erts/emulator/beam/global.h | 2 +- 5 files changed, 36 insertions(+), 58 deletions(-) (limited to 'erts/emulator/beam') diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c index 9ee4bb6878..e57becbe9f 100644 --- a/erts/emulator/beam/beam_bif_load.c +++ b/erts/emulator/beam/beam_bif_load.c @@ -50,7 +50,6 @@ load_module_2(BIF_ALIST_2) { Eterm reason; Eterm* hp; - int i; int sz; byte* code; Eterm res; @@ -69,38 +68,15 @@ load_module_2(BIF_ALIST_2) hp = HAlloc(BIF_P, 3); sz = binary_size(BIF_ARG_2); - if ((i = erts_load_module(BIF_P, 0, - BIF_P->group_leader, &BIF_ARG_1, code, sz)) < 0) { - switch (i) { - case -1: reason = am_badfile; break; - case -2: reason = am_nofile; break; - case -3: reason = am_not_purged; break; - case -4: - reason = am_atom_put("native_code", sizeof("native_code")-1); - break; - case -5: - { - /* - * The module contains an on_load function. The loader - * has loaded the module as usual, except that the - * export entries does not point into the module, so it - * is not possible to call any code in the module. - */ - - ERTS_DECL_AM(on_load); - reason = AM_on_load; - break; - } - default: reason = am_badfile; break; - } + reason = erts_load_module(BIF_P, 0, BIF_P->group_leader, + &BIF_ARG_1, code, sz); + if (reason != NIL) { res = TUPLE2(hp, am_error, reason); - goto done; + } else { + set_default_trace_pattern(BIF_ARG_1); + res = TUPLE2(hp, am_module, BIF_ARG_1); } - set_default_trace_pattern(BIF_ARG_1); - res = TUPLE2(hp, am_module, BIF_ARG_1); - - done: erts_free_aligned_binary_bytes(temp_alloc); erts_smp_thr_progress_unblock(); erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); @@ -769,7 +745,7 @@ delete_export_references(Eterm module) } -int +Eterm beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks, Eterm module) { Module* modp = erts_put_module(module); @@ -780,12 +756,12 @@ beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks, Eterm module) */ if (modp->code != NULL && modp->old_code != NULL) { - return -3; + return am_not_purged; } else if (modp->old_code == NULL) { /* Make the current version old. */ delete_code(c_p, c_p_locks, modp); delete_export_references(module); } - return 0; + return NIL; } static int diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index e98210d39c..883689f9d3 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -494,10 +494,10 @@ typedef struct { } while (0) -static int bin_load(Process *c_p, ErtsProcLocks c_p_locks, +static Eterm bin_load(Process *c_p, ErtsProcLocks c_p_locks, Eterm group_leader, Eterm* modp, byte* bytes, int unloaded_size); static void init_state(LoaderState* stp); -static int insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, +static Eterm insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, Eterm group_leader, Eterm module, BeamInstr* code, Uint size, BeamInstr catches); static int scan_iff_file(LoaderState* stp, Uint* chunk_types, @@ -592,7 +592,7 @@ define_file(LoaderState* stp, char* name, int idx) stp->file_left = stp->chunks[idx].size; } -int +Eterm erts_load_module(Process *c_p, ErtsProcLocks c_p_locks, Eterm group_leader, /* Group leader or NIL if none. */ @@ -604,7 +604,7 @@ erts_load_module(Process *c_p, int size) /* Size of code to load. */ { ErlDrvBinary* bin; - int result; + Eterm result; if (size >= 4 && code[0] == 'F' && code[1] == 'O' && code[2] == 'R' && code[3] == '1') { @@ -617,7 +617,7 @@ erts_load_module(Process *c_p, * The BEAM module is compressed (or possibly invalid/corrupted). */ if ((bin = (ErlDrvBinary *) erts_gzinflate_buffer((char*)code, size)) == NULL) { - return -1; + return am_badfile; } result = bin_load(c_p, c_p_locks, group_leader, modp, (byte*)bin->orig_bytes, bin->orig_size); @@ -638,12 +638,12 @@ extern void check_allocated_block(Uint type, void *blk); #define CHKBLK(TYPE,BLK) /* nothing */ #endif -static int +static Eterm bin_load(Process *c_p, ErtsProcLocks c_p_locks, Eterm group_leader, Eterm* modp, byte* bytes, int unloaded_size) { LoaderState state; - int rval = -1; + Eterm retval = am_badfile; init_state(&state); state.module = *modp; @@ -793,9 +793,9 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, */ CHKBLK(ERTS_ALC_T_CODE,state.code); - rval = insert_new_code(c_p, c_p_locks, state.group_leader, state.module, - state.code, state.loaded_size, state.catches); - if (rval < 0) { + retval = insert_new_code(c_p, c_p_locks, state.group_leader, state.module, + state.code, state.loaded_size, state.catches); + if (retval != NIL) { goto load_error; } CHKBLK(ERTS_ALC_T_CODE,state.code); @@ -811,7 +811,6 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, debug_dump_code(state.code,state.ci); #endif #endif - rval = 0; state.code = NULL; /* Prevent code from being freed. */ *modp = state.module; @@ -820,7 +819,7 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, * indicate that the on_load function must be run. */ if (state.on_load) { - rval = -5; + retval = am_on_load; } load_error: @@ -883,7 +882,7 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, erts_free(ERTS_ALC_T_LOADER_TMP, state.fname); } - return rval; + return retval; } @@ -919,21 +918,22 @@ init_state(LoaderState* stp) stp->fname = 0; } -static int +static Eterm insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, - Eterm group_leader, Eterm module, BeamInstr* code, Uint size, BeamInstr catches) + Eterm group_leader, Eterm module, BeamInstr* code, + Uint size, BeamInstr catches) { Module* modp; - int rval; + Eterm retval; int i; - if ((rval = beam_make_current_old(c_p, c_p_locks, module)) < 0) { + if ((retval = beam_make_current_old(c_p, c_p_locks, module)) < 0) { erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf(); erts_dsprintf(dsbufp, "Module %T must be purged before loading\n", module); erts_send_error_to_logger(group_leader, dsbufp); - return rval; + return retval; } /* @@ -966,7 +966,7 @@ insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, modules[i].end = (BeamInstr *) (((byte *)code) + size); num_loaded_modules++; mid_module = &modules[num_loaded_modules/2]; - return 0; + return NIL; } static int @@ -5889,7 +5889,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) rval = insert_new_code(p, 0, p->group_leader, Mod, code, code_size, BEAM_CATCHES_NIL); - if (rval < 0) { + if (rval != NIL) { goto error; } diff --git a/erts/emulator/beam/beam_load.h b/erts/emulator/beam/beam_load.h index 9d4a60fed1..2956bd0add 100644 --- a/erts/emulator/beam/beam_load.h +++ b/erts/emulator/beam/beam_load.h @@ -23,7 +23,8 @@ #include "beam_opcodes.h" #include "erl_process.h" -int beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks, Eterm module); +Eterm beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks, + Eterm module); typedef struct gen_op_entry { char* name; diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c index fd15df731a..7ae9f990ad 100644 --- a/erts/emulator/beam/erl_init.c +++ b/erts/emulator/beam/erl_init.c @@ -436,7 +436,7 @@ static void load_preloaded(void) { int i; - int res; + Eterm res; Preload* preload_p; Eterm module_name; byte* code; @@ -455,8 +455,9 @@ load_preloaded(void) name); res = erts_load_module(NULL, 0, NIL, &module_name, code, length); sys_preload_end(&preload_p[i]); - if (res < 0) - erl_exit(1,"Failed loading preloaded module %s\n", name); + if (res != NIL) + erl_exit(1,"Failed loading preloaded module %s (%T)\n", + name, res); i++; } } diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index e4e9386dd7..6c75c3876b 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -866,7 +866,7 @@ typedef struct { Eterm* fname_ptr; /* Pointer to fname table */ } FunctionInfo; -int erts_load_module(Process *c_p, ErtsProcLocks c_p_locks, +Eterm erts_load_module(Process *c_p, ErtsProcLocks c_p_locks, Eterm group_leader, Eterm* mod, byte* code, int size); void init_load(void); BeamInstr* find_function_from_pc(BeamInstr* pc); -- cgit v1.2.3 From 4de78fc7542905a519ec52b91769df63f8939952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 10 Nov 2011 08:40:48 +0100 Subject: beam_load.c: Factor out cleaning up of the loader state into free_state() --- erts/emulator/beam/beam_load.c | 154 ++++++++++++++++++----------------------- 1 file changed, 68 insertions(+), 86 deletions(-) (limited to 'erts/emulator/beam') diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index 883689f9d3..cf4c04a135 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -497,6 +497,7 @@ typedef struct { static Eterm bin_load(Process *c_p, ErtsProcLocks c_p_locks, Eterm group_leader, Eterm* modp, byte* bytes, int unloaded_size); static void init_state(LoaderState* stp); +static void free_state(LoaderState* stp); static Eterm insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, Eterm group_leader, Eterm module, BeamInstr* code, Uint size, BeamInstr catches); @@ -823,65 +824,7 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, } load_error: - if (state.code != 0) { - erts_free(ERTS_ALC_T_CODE, state.code); - } - if (state.labels != NULL) { - erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.labels); - } - if (state.atom != NULL) { - erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.atom); - } - if (state.import != NULL) { - erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.import); - } - if (state.export != NULL) { - erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.export); - } - if (state.lambdas != state.def_lambdas) { - erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.lambdas); - } - if (state.literals != NULL) { - int i; - for (i = 0; i < state.num_literals; i++) { - if (state.literals[i].heap != NULL) { - erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.literals[i].heap); - } - } - erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.literals); - } - while (state.literal_patches != NULL) { - LiteralPatch* next = state.literal_patches->next; - erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.literal_patches); - state.literal_patches = next; - } - while (state.string_patches != NULL) { - StringPatch* next = state.string_patches->next; - erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.string_patches); - state.string_patches = next; - } - while (state.genop_blocks) { - GenOpBlock* next = state.genop_blocks->next; - erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.genop_blocks); - state.genop_blocks = next; - } - - if (state.line_item != 0) { - erts_free(ERTS_ALC_T_LOADER_TMP, state.line_item); - } - - if (state.line_instr != 0) { - erts_free(ERTS_ALC_T_LOADER_TMP, state.line_instr); - } - - if (state.func_line != 0) { - erts_free(ERTS_ALC_T_LOADER_TMP, state.func_line); - } - - if (state.fname != 0) { - erts_free(ERTS_ALC_T_LOADER_TMP, state.fname); - } - + free_state(&state); return retval; } @@ -918,6 +861,70 @@ init_state(LoaderState* stp) stp->fname = 0; } +static void +free_state(LoaderState* stp) +{ + if (stp->code != 0) { + erts_free(ERTS_ALC_T_CODE, stp->code); + } + if (stp->labels != NULL) { + erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->labels); + } + if (stp->atom != NULL) { + erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->atom); + } + if (stp->import != NULL) { + erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->import); + } + if (stp->export != NULL) { + erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->export); + } + if (stp->lambdas != stp->def_lambdas) { + erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->lambdas); + } + if (stp->literals != NULL) { + int i; + for (i = 0; i < stp->num_literals; i++) { + if (stp->literals[i].heap != NULL) { + erts_free(ERTS_ALC_T_LOADER_TMP, + (void *) stp->literals[i].heap); + } + } + erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->literals); + } + while (stp->literal_patches != NULL) { + LiteralPatch* next = stp->literal_patches->next; + erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->literal_patches); + stp->literal_patches = next; + } + while (stp->string_patches != NULL) { + StringPatch* next = stp->string_patches->next; + erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->string_patches); + stp->string_patches = next; + } + while (stp->genop_blocks) { + GenOpBlock* next = stp->genop_blocks->next; + erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->genop_blocks); + stp->genop_blocks = next; + } + + if (stp->line_item != 0) { + erts_free(ERTS_ALC_T_LOADER_TMP, stp->line_item); + } + + if (stp->line_instr != 0) { + erts_free(ERTS_ALC_T_LOADER_TMP, stp->line_instr); + } + + if (stp->func_line != 0) { + erts_free(ERTS_ALC_T_LOADER_TMP, stp->func_line); + } + + if (stp->fname != 0) { + erts_free(ERTS_ALC_T_LOADER_TMP, stp->fname); + } +} + static Eterm insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, Eterm group_leader, Eterm module, BeamInstr* code, @@ -5905,12 +5912,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) if (patch_funentries(Patchlist)) { erts_free_aligned_binary_bytes(temp_alloc); - if (state.lambdas != state.def_lambdas) { - erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.lambdas); - } - erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.labels); - erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.atom); - erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.export); + free_state(&state); if (bin != NULL) { driver_free_binary(bin); } @@ -5918,27 +5920,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) } error: - erts_free_aligned_binary_bytes(temp_alloc); - if (code != NULL) { - erts_free(ERTS_ALC_T_CODE, code); - } - if (state.labels != NULL) { - erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.labels); - } - if (state.lambdas != state.def_lambdas) { - erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.lambdas); - } - if (state.atom != NULL) { - erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.atom); - } - if (state.export != NULL) { - erts_free(ERTS_ALC_T_LOADER_TMP, (void *) state.export); - } - if (bin != NULL) { - driver_free_binary(bin); - } - - + free_state(&state); BIF_ERROR(p, BADARG); } -- cgit v1.2.3 From 0b27c0ce578db5266dbaaa50a6d116836a03aa94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 10 Nov 2011 14:42:47 +0100 Subject: BEAM loader: Refactor code loading into separate functions Break apart code loading into the three functions: erts_alloc_loader_state() erts_prepare_loading() erts_finish_loading() The erts_alloc_loader_state() and erts_prepare_loading() can be executed with all schedulers running. Only erts_finish_loading() needs to be run in a single-scheduling system. --- erts/emulator/beam/beam_load.c | 340 +++++++++++++++++++++++------------------ erts/emulator/beam/beam_load.h | 1 + erts/emulator/beam/global.h | 8 +- 3 files changed, 196 insertions(+), 153 deletions(-) (limited to 'erts/emulator/beam') diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index cf4c04a135..10ed46417b 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -245,7 +245,7 @@ typedef struct { * This structure contains all information about the module being loaded. */ -typedef struct { +typedef struct LoaderState { /* * The current logical file within the binary. */ @@ -494,13 +494,10 @@ typedef struct { } while (0) -static Eterm bin_load(Process *c_p, ErtsProcLocks c_p_locks, - Eterm group_leader, Eterm* modp, byte* bytes, int unloaded_size); -static void init_state(LoaderState* stp); static void free_state(LoaderState* stp); static Eterm insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, - Eterm group_leader, Eterm module, - BeamInstr* code, Uint size, BeamInstr catches); + Eterm group_leader, Eterm module, + BeamInstr* code, Uint size); static int scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types, Uint num_mandatory); static int load_atom_table(LoaderState* stp); @@ -602,29 +599,17 @@ erts_load_module(Process *c_p, * On return, contains the actual module name. */ byte* code, /* Points to the code to load */ - int size) /* Size of code to load. */ + Uint size) /* Size of code to load. */ { - ErlDrvBinary* bin; - Eterm result; + LoaderState* stp = erts_alloc_loader_state(); + Eterm retval; - if (size >= 4 && code[0] == 'F' && code[1] == 'O' && - code[2] == 'R' && code[3] == '1') { - /* - * The BEAM module is not compressed. - */ - result = bin_load(c_p, c_p_locks, group_leader, modp, code, size); - } else { - /* - * The BEAM module is compressed (or possibly invalid/corrupted). - */ - if ((bin = (ErlDrvBinary *) erts_gzinflate_buffer((char*)code, size)) == NULL) { - return am_badfile; - } - result = bin_load(c_p, c_p_locks, group_leader, modp, - (byte*)bin->orig_bytes, bin->orig_size); - driver_free_binary(bin); + retval = erts_prepare_loading(stp, c_p, group_leader, modp, + code, size); + if (retval != NIL) { + return retval; } - return result; + return erts_finish_loading(stp, c_p, c_p_locks, modp); } /* #define LOAD_MEMORY_HARD_DEBUG 1*/ @@ -639,16 +624,30 @@ extern void check_allocated_block(Uint type, void *blk); #define CHKBLK(TYPE,BLK) /* nothing */ #endif -static Eterm -bin_load(Process *c_p, ErtsProcLocks c_p_locks, - Eterm group_leader, Eterm* modp, byte* bytes, int unloaded_size) +Eterm +erts_prepare_loading(LoaderState* stp, Process *c_p, Eterm group_leader, + Eterm* modp, byte* code, Uint unloaded_size) { - LoaderState state; Eterm retval = am_badfile; + ErlDrvBinary* bin = NULL; - init_state(&state); - state.module = *modp; - state.group_leader = group_leader; + stp->module = *modp; + stp->group_leader = group_leader; + + /* + * Check if the module is compressed (or possibly invalid/corrupted). + */ + if ( !(unloaded_size >= 4 && + code[0] == 'F' && code[1] == 'O' && + code[2] == 'R' && code[3] == '1') ) { + bin = (ErlDrvBinary *) + erts_gzinflate_buffer((char*)code, unloaded_size); + if (bin == NULL) { + goto load_error; + } + code = (byte*)bin->orig_bytes; + unloaded_size = bin->orig_size; + } /* * Scan the IFF file. @@ -659,11 +658,11 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, #endif CHKALLOC(); - CHKBLK(ERTS_ALC_T_CODE,state.code); - state.file_name = "IFF header for Beam file"; - state.file_p = bytes; - state.file_left = unloaded_size; - if (!scan_iff_file(&state, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) { + CHKBLK(ERTS_ALC_T_CODE,stp->code); + stp->file_name = "IFF header for Beam file"; + stp->file_p = code; + stp->file_left = unloaded_size; + if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) { goto load_error; } @@ -671,38 +670,38 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, * Read the header for the code chunk. */ - CHKBLK(ERTS_ALC_T_CODE,state.code); - define_file(&state, "code chunk header", CODE_CHUNK); - if (!read_code_header(&state)) { + CHKBLK(ERTS_ALC_T_CODE,stp->code); + define_file(stp, "code chunk header", CODE_CHUNK); + if (!read_code_header(stp)) { goto load_error; } /* * Initialize code area. */ - state.code_buffer_size = erts_next_heap_size(2048 + state.num_functions, 0); - state.code = (BeamInstr *) erts_alloc(ERTS_ALC_T_CODE, - sizeof(BeamInstr) * state.code_buffer_size); + stp->code_buffer_size = erts_next_heap_size(2048 + stp->num_functions, 0); + stp->code = (BeamInstr *) erts_alloc(ERTS_ALC_T_CODE, + sizeof(BeamInstr) * stp->code_buffer_size); - state.code[MI_NUM_FUNCTIONS] = state.num_functions; - state.ci = MI_FUNCTIONS + state.num_functions + 1; + stp->code[MI_NUM_FUNCTIONS] = stp->num_functions; + stp->ci = MI_FUNCTIONS + stp->num_functions + 1; - state.code[MI_ATTR_PTR] = 0; - state.code[MI_ATTR_SIZE] = 0; - state.code[MI_ATTR_SIZE_ON_HEAP] = 0; - state.code[MI_COMPILE_PTR] = 0; - state.code[MI_COMPILE_SIZE] = 0; - state.code[MI_COMPILE_SIZE_ON_HEAP] = 0; - state.code[MI_NUM_BREAKPOINTS] = 0; + stp->code[MI_ATTR_PTR] = 0; + stp->code[MI_ATTR_SIZE] = 0; + stp->code[MI_ATTR_SIZE_ON_HEAP] = 0; + stp->code[MI_COMPILE_PTR] = 0; + stp->code[MI_COMPILE_SIZE] = 0; + stp->code[MI_COMPILE_SIZE_ON_HEAP] = 0; + stp->code[MI_NUM_BREAKPOINTS] = 0; /* * Read the atom table. */ - CHKBLK(ERTS_ALC_T_CODE,state.code); - define_file(&state, "atom table", ATOM_CHUNK); - if (!load_atom_table(&state)) { + CHKBLK(ERTS_ALC_T_CODE,stp->code); + define_file(stp, "atom table", ATOM_CHUNK); + if (!load_atom_table(stp)) { goto load_error; } @@ -710,9 +709,9 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, * Read the import table. */ - CHKBLK(ERTS_ALC_T_CODE,state.code); - define_file(&state, "import table", IMP_CHUNK); - if (!load_import_table(&state)) { + CHKBLK(ERTS_ALC_T_CODE,stp->code); + define_file(stp, "import table", IMP_CHUNK); + if (!load_import_table(stp)) { goto load_error; } @@ -720,10 +719,10 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, * Read the lambda (fun) table. */ - CHKBLK(ERTS_ALC_T_CODE,state.code); - if (state.chunks[LAMBDA_CHUNK].size > 0) { - define_file(&state, "lambda (fun) table", LAMBDA_CHUNK); - if (!read_lambda_table(&state)) { + CHKBLK(ERTS_ALC_T_CODE,stp->code); + if (stp->chunks[LAMBDA_CHUNK].size > 0) { + define_file(stp, "lambda (fun) table", LAMBDA_CHUNK); + if (!read_lambda_table(stp)) { goto load_error; } } @@ -732,10 +731,10 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, * Read the literal table. */ - CHKBLK(ERTS_ALC_T_CODE,state.code); - if (state.chunks[LITERAL_CHUNK].size > 0) { - define_file(&state, "literals table (constant pool)", LITERAL_CHUNK); - if (!read_literal_table(&state)) { + CHKBLK(ERTS_ALC_T_CODE,stp->code); + if (stp->chunks[LITERAL_CHUNK].size > 0) { + define_file(stp, "literals table (constant pool)", LITERAL_CHUNK); + if (!read_literal_table(stp)) { goto load_error; } } @@ -744,35 +743,27 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, * Read the line table (if present). */ - CHKBLK(ERTS_ALC_T_CODE,state.code); - if (state.chunks[LINE_CHUNK].size > 0) { - define_file(&state, "line table", LINE_CHUNK); - if (!read_line_table(&state)) { + CHKBLK(ERTS_ALC_T_CODE,stp->code); + if (stp->chunks[LINE_CHUNK].size > 0) { + define_file(stp, "line table", LINE_CHUNK); + if (!read_line_table(stp)) { goto load_error; } } - /* - * Since the literal table *may* have contained external - * funs (containing references to export entries), now is - * the time to consolidate the export tables. - */ - - erts_export_consolidate(); - /* * Load the code chunk. */ - CHKBLK(ERTS_ALC_T_CODE,state.code); - state.file_name = "code chunk"; - state.file_p = state.code_start; - state.file_left = state.code_size; - if (!load_code(&state)) { + CHKBLK(ERTS_ALC_T_CODE,stp->code); + stp->file_name = "code chunk"; + stp->file_p = stp->code_start; + stp->file_left = stp->code_size; + if (!load_code(stp)) { goto load_error; } - CHKBLK(ERTS_ALC_T_CODE,state.code); - if (!freeze_code(&state)) { + CHKBLK(ERTS_ALC_T_CODE,stp->code); + if (!freeze_code(stp)) { goto load_error; } @@ -782,56 +773,96 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks, * loading the code, because it contains labels.) */ - CHKBLK(ERTS_ALC_T_CODE,state.code); - define_file(&state, "export table", EXP_CHUNK); - if (!read_export_table(&state)) { + CHKBLK(ERTS_ALC_T_CODE,stp->code); + define_file(stp, "export table", EXP_CHUNK); + if (!read_export_table(stp)) { goto load_error; } /* - * Ready for the final touch: fixing the export table entries for - * exported and imported functions. This can't fail. + * Good so far. */ - - CHKBLK(ERTS_ALC_T_CODE,state.code); - retval = insert_new_code(c_p, c_p_locks, state.group_leader, state.module, - state.code, state.loaded_size, state.catches); + + retval = NIL; + + load_error: + if (bin) { + driver_free_binary(bin); + } + if (retval != NIL) { + free_state(stp); + } + return retval; +} + +Eterm +erts_finish_loading(LoaderState* stp, Process* c_p, + ErtsProcLocks c_p_locks, Eterm* modp) +{ + Eterm retval; + + /* + * No other process may run since we will update the export + * table which is not protected by any locks. + */ + + ERTS_SMP_LC_ASSERT(erts_initialized == 0 || + erts_smp_thr_progress_is_blocking()); + + /* + * Make current code for the module old and insert the new code + * as current. This will fail if there already exists old code + * for the module. + */ + + CHKBLK(ERTS_ALC_T_CODE,stp->code); + retval = insert_new_code(c_p, c_p_locks, stp->group_leader, stp->module, + stp->code, stp->loaded_size); if (retval != NIL) { goto load_error; } - CHKBLK(ERTS_ALC_T_CODE,state.code); - final_touch(&state); + + /* + * Ready for the final touch: fixing the export table entries for + * exported and imported functions. This can't fail. + */ + + erts_export_consolidate(); + CHKBLK(ERTS_ALC_T_CODE,stp->code); + final_touch(stp); /* * Loading succeded. */ - CHKBLK(ERTS_ALC_T_CODE,state.code); + CHKBLK(ERTS_ALC_T_CODE,stp->code); #if defined(LOAD_MEMORY_HARD_DEBUG) && defined(DEBUG) erts_fprintf(stderr,"Loaded %T\n",*modp); #if 0 - debug_dump_code(state.code,state.ci); + debug_dump_code(stp->code,stp->ci); #endif #endif - state.code = NULL; /* Prevent code from being freed. */ - *modp = state.module; + stp->code = NULL; /* Prevent code from being freed. */ + *modp = stp->module; /* * If there is an on_load function, signal an error to * indicate that the on_load function must be run. */ - if (state.on_load) { + if (stp->on_load) { retval = am_on_load; } load_error: - free_state(&state); + free_state(stp); return retval; } - -static void -init_state(LoaderState* stp) +LoaderState* +erts_alloc_loader_state(void) { + LoaderState* stp; + + stp = erts_alloc(ERTS_ALC_T_LOADER_TMP, sizeof(LoaderState)); stp->function = THE_NON_VALUE; /* Function not known yet */ stp->arity = 0; stp->specific_op = -1; @@ -859,6 +890,7 @@ init_state(LoaderState* stp) stp->line_instr = 0; stp->func_line = 0; stp->fname = 0; + return stp; } static void @@ -923,12 +955,13 @@ free_state(LoaderState* stp) if (stp->fname != 0) { erts_free(ERTS_ALC_T_LOADER_TMP, stp->fname); } + erts_free(ERTS_ALC_T_LOADER_TMP, stp); } static Eterm insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, Eterm group_leader, Eterm module, BeamInstr* code, - Uint size, BeamInstr catches) + Uint size) { Module* modp; Eterm retval; @@ -951,7 +984,7 @@ insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, modp = erts_put_module(module); modp->code = code; modp->code_length = size; - modp->catches = catches; + modp->catches = BEAM_CATCHES_NIL; /* Will be filled in later. */ /* * Update address table (used for finding a function from a PC value). @@ -3861,7 +3894,6 @@ freeze_code(LoaderState* stp) unsigned attr_size = stp->chunks[ATTR_CHUNK].size; unsigned compile_size = stp->chunks[COMPILE_CHUNK].size; Uint size; - unsigned catches; Sint decoded_size; Uint line_size; @@ -4115,21 +4147,6 @@ freeze_code(LoaderState* stp) } CHKBLK(ERTS_ALC_T_CODE,code); - /* - * Fix all catch_yf instructions. - */ - index = stp->catches; - catches = BEAM_CATCHES_NIL; - while (index != 0) { - BeamInstr next = code[index]; - code[index] = BeamOpCode(op_catch_yf); - catches = beam_catches_cons((BeamInstr *)code[index+2], catches); - code[index+2] = make_catch(catches); - index = next; - } - stp->catches = catches; - CHKBLK(ERTS_ALC_T_CODE,code); - /* * Save the updated code pointer and code size. */ @@ -4155,6 +4172,26 @@ final_touch(LoaderState* stp) { int i; int on_load = stp->on_load; + unsigned catches; + Uint index; + BeamInstr* code = stp->code; + Module* modp; + + /* + * Allocate catch indices and fix up all catch_yf instructions. + */ + + index = stp->catches; + catches = BEAM_CATCHES_NIL; + while (index != 0) { + BeamInstr next = code[index]; + code[index] = BeamOpCode(op_catch_yf); + catches = beam_catches_cons((BeamInstr *)code[index+2], catches); + code[index+2] = make_catch(catches); + index = next; + } + modp = erts_put_module(stp->module); + modp->catches = catches; /* * Export functions. @@ -5692,7 +5729,7 @@ patch_funentries(Eterm Patchlist) Eterm erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) { - LoaderState state; + LoaderState* stp; BeamInstr Funcs; BeamInstr Patchlist; Eterm* tp; @@ -5711,10 +5748,10 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) Uint size; /* - * Must initialize state.lambdas here because the error handling code + * Must initialize stp->lambdas here because the error handling code * at label 'error' uses it. */ - init_state(&state); + stp = erts_alloc_loader_state(); if (is_not_atom(Mod)) { goto error; @@ -5754,31 +5791,31 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) * Scan the Beam binary and read the interesting sections. */ - state.file_name = "IFF header for Beam file"; - state.file_p = bytes; - state.file_left = size; - state.module = Mod; - state.group_leader = p->group_leader; - state.num_functions = n; - if (!scan_iff_file(&state, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) { + stp->file_name = "IFF header for Beam file"; + stp->file_p = bytes; + stp->file_left = size; + stp->module = Mod; + stp->group_leader = p->group_leader; + stp->num_functions = n; + if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES, NUM_MANDATORY)) { goto error; } - define_file(&state, "code chunk header", CODE_CHUNK); - if (!read_code_header(&state)) { + define_file(stp, "code chunk header", CODE_CHUNK); + if (!read_code_header(stp)) { goto error; } - define_file(&state, "atom table", ATOM_CHUNK); - if (!load_atom_table(&state)) { + define_file(stp, "atom table", ATOM_CHUNK); + if (!load_atom_table(stp)) { goto error; } - define_file(&state, "export table", EXP_CHUNK); - if (!stub_read_export_table(&state)) { + define_file(stp, "export table", EXP_CHUNK); + if (!stub_read_export_table(stp)) { goto error; } - if (state.chunks[LAMBDA_CHUNK].size > 0) { - define_file(&state, "lambda (fun) table", LAMBDA_CHUNK); - if (!read_lambda_table(&state)) { + if (stp->chunks[LAMBDA_CHUNK].size > 0) { + define_file(stp, "lambda (fun) table", LAMBDA_CHUNK); + if (!read_lambda_table(stp)) { goto error; } } @@ -5788,8 +5825,8 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) */ code_size = ((WORDS_PER_FUNCTION+1)*n + MI_FUNCTIONS + 2) * sizeof(BeamInstr); - code_size += state.chunks[ATTR_CHUNK].size; - code_size += state.chunks[COMPILE_CHUNK].size; + code_size += stp->chunks[ATTR_CHUNK].size; + code_size += stp->chunks[COMPILE_CHUNK].size; code = erts_alloc_fnf(ERTS_ALC_T_CODE, code_size); if (!code) { goto error; @@ -5879,12 +5916,12 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) */ info = (byte *) fp; - info = stub_copy_info(&state, ATTR_CHUNK, info, + info = stub_copy_info(stp, ATTR_CHUNK, info, code+MI_ATTR_PTR, code+MI_ATTR_SIZE_ON_HEAP); if (info == NULL) { goto error; } - info = stub_copy_info(&state, COMPILE_CHUNK, info, + info = stub_copy_info(stp, COMPILE_CHUNK, info, code+MI_COMPILE_PTR, code+MI_COMPILE_SIZE_ON_HEAP); if (info == NULL) { goto error; @@ -5894,8 +5931,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) * Insert the module in the module table. */ - rval = insert_new_code(p, 0, p->group_leader, Mod, code, code_size, - BEAM_CATCHES_NIL); + rval = insert_new_code(p, 0, p->group_leader, Mod, code, code_size); if (rval != NIL) { goto error; } @@ -5906,13 +5942,13 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) fp = code + ci; for (i = 0; i < n; i++) { - stub_final_touch(&state, fp); + stub_final_touch(stp, fp); fp += WORDS_PER_FUNCTION; } if (patch_funentries(Patchlist)) { erts_free_aligned_binary_bytes(temp_alloc); - free_state(&state); + free_state(stp); if (bin != NULL) { driver_free_binary(bin); } @@ -5920,7 +5956,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info) } error: - free_state(&state); + free_state(stp); BIF_ERROR(p, BADARG); } diff --git a/erts/emulator/beam/beam_load.h b/erts/emulator/beam/beam_load.h index 2956bd0add..126d9a3935 100644 --- a/erts/emulator/beam/beam_load.h +++ b/erts/emulator/beam/beam_load.h @@ -26,6 +26,7 @@ Eterm beam_make_current_old(Process *c_p, ErtsProcLocks c_p_locks, Eterm module); + typedef struct gen_op_entry { char* name; int arity; diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 6c75c3876b..9f19172e08 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -866,8 +866,14 @@ typedef struct { Eterm* fname_ptr; /* Pointer to fname table */ } FunctionInfo; +struct LoaderState* erts_alloc_loader_state(void); +Eterm erts_prepare_loading(struct LoaderState*, Process *c_p, + Eterm group_leader, Eterm* modp, + byte* code, Uint size); +Eterm erts_finish_loading(struct LoaderState* stp, Process* c_p, + ErtsProcLocks c_p_locks, Eterm* modp); Eterm erts_load_module(Process *c_p, ErtsProcLocks c_p_locks, - Eterm group_leader, Eterm* mod, byte* code, int size); + Eterm group_leader, Eterm* mod, byte* code, Uint size); void init_load(void); BeamInstr* find_function_from_pc(BeamInstr* pc); Eterm* erts_build_mfa_item(FunctionInfo* fi, Eterm* hp, -- cgit v1.2.3 From bee543c25be70380be225021864a079c01b56255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 10 Nov 2011 10:42:42 +0100 Subject: BEAM loader: Don't stop other schedulers until truly needed The erlang:module_load/2 BIF will stop all other schedulers before it starts to process the BEAM file. That is not a problem when starting the Erlang/OTP system, since the start-up is mostly sequential. It is a problem, however, when big BEAM files are loaded in an already running system. After the refactoring in the previous commits, we can now do most of the processing of the BEAM file before we stop the other schedulers, so that we can minimize the time when only one scheduler will be running. Suggested-by: Bob Ippolito --- erts/emulator/beam/beam_bif_load.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'erts/emulator/beam') diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c index e57becbe9f..efb72cd3e7 100644 --- a/erts/emulator/beam/beam_bif_load.c +++ b/erts/emulator/beam/beam_bif_load.c @@ -54,6 +54,7 @@ load_module_2(BIF_ALIST_2) byte* code; Eterm res; byte* temp_alloc = NULL; + struct LoaderState* stp; if (is_not_atom(BIF_ARG_1)) { error: @@ -63,13 +64,28 @@ load_module_2(BIF_ALIST_2) if ((code = erts_get_aligned_binary_bytes(BIF_ARG_2, &temp_alloc)) == NULL) { goto error; } + hp = HAlloc(BIF_P, 3); + + /* + * Read the BEAM file and prepare the module for loading. + */ + stp = erts_alloc_loader_state(); + sz = binary_size(BIF_ARG_2); + reason = erts_prepare_loading(stp, BIF_P, BIF_P->group_leader, + &BIF_ARG_1, code, sz); + erts_free_aligned_binary_bytes(temp_alloc); + if (reason != NIL) { + res = TUPLE2(hp, am_error, reason); + BIF_RET(res); + } + + /* + * Stop all other processes and finish the loading of the module. + */ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); erts_smp_thr_progress_block(); - hp = HAlloc(BIF_P, 3); - sz = binary_size(BIF_ARG_2); - reason = erts_load_module(BIF_P, 0, BIF_P->group_leader, - &BIF_ARG_1, code, sz); + reason = erts_finish_loading(stp, BIF_P, 0, &BIF_ARG_1); if (reason != NIL) { res = TUPLE2(hp, am_error, reason); } else { @@ -77,10 +93,8 @@ load_module_2(BIF_ALIST_2) res = TUPLE2(hp, am_module, BIF_ARG_1); } - erts_free_aligned_binary_bytes(temp_alloc); erts_smp_thr_progress_unblock(); erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); - BIF_RET(res); } -- cgit v1.2.3