beam_bif_load:load_module_2

在beam_bif_load.c中
Eterm
load_module_2(BIF_ALIST_2)
{
    Eterm   reason;
    Eterm*  hp;
    int      i;
    int      sz;
    byte*    code;
    int trace_pattern_is_on;
    Binary *match_spec;
    Binary *meta_match_spec;
    struct trace_pattern_flags trace_pattern_flags;
    Eterm meta_tracer_pid;
    Eterm res;
    byte* temp_alloc = NULL;

    if (is_not_atom(BIF_ARG_1)) {
    error:
erts_free_aligned_binary_bytes(temp_alloc);
BIF_ERROR(BIF_P, BADARG);
    }
    if ((code = erts_get_aligned_binary_bytes(BIF_ARG_2, &temp_alloc)) == NULL) {
goto error;
    }
    erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
    erts_smp_block_system(0);

    erts_export_consolidate();

    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;
default: reason = am_badfile; break;
}
res = TUPLE2(hp, am_error, reason);
goto done;
    }

    erts_get_default_trace_pattern(&trace_pattern_is_on,
   &match_spec,
   &meta_match_spec,
   &trace_pattern_flags,
   &meta_tracer_pid);
    if (trace_pattern_is_on) {
Eterm mfa[1];
mfa[0] = BIF_ARG_1;
(void) erts_set_trace_pattern(mfa, 1,
      match_spec,
      meta_match_spec,
      1, trace_pattern_flags,
      meta_tracer_pid);
    }

    res = TUPLE2(hp, am_module, BIF_ARG_1);

done:
    erts_free_aligned_binary_bytes(temp_alloc);
    erts_smp_release_system();
    erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);

    BIF_RET(res);
}

看点:1、binary.c中的erts_get_aligned_binary_bytes和erts_free_aligned_binary_bytes
2、export.c中的erts_export_consolidate
3、beam_load.c中的erts_load_module(本bif实质上还是调用的beam_load)
4、erl_bif_trace.c中的erts_set_trace_pattern和get
5、erl_term.c中的TUPLE2


2. beam_load:erts_load_module
int
erts_load_module(Process *c_p,
ErtsProcLocks c_p_locks,
Eterm group_leader, /* Group leader or NIL if none. */
Eterm* modp, /*
* Module name as an atom (NIL to not check).
* On return, contains the actual module name.
*/
byte* code, /* Points to the code to load */
int size) /* Size of code to load. */
{
    ErlDrvBinary* bin;
    int result;

    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 -1;
}
result = bin_load (c_p, c_p_locks, group_leader, modp,
  (byte*)bin->orig_bytes, bin->orig_size);
driver_free_binary(bin);
    }
    return result;
}

代码块开始是“FOR1”,

3. beam_load:bin_load
static int
bin_load(Process *c_p, ErtsProcLocks c_p_locks,
Eterm group_leader, Eterm* modp, byte* bytes, int unloaded_size)
{
    LoaderState state;
    int rval = -1;

    init_state(&state);
    state.module = *modp;
    state.group_leader = group_leader;

    /*
     * Scan the IFF file.
     */

    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)) {
goto load_error;
    }

    /*
     * Read the header for the code chunk.
     */

    define_file(&state, "code chunk header", CODE_CHUNK);
    if (!read_code_header(&state)) {
goto load_error;
    }

    /*
     * Read the atom table.
     */

    define_file(&state, "atom table", ATOM_CHUNK);
    if (!load_atom_table(&state)) {
goto load_error;
    }

    /*
     * Read the import table.
     */

    define_file(&state, "import table", IMP_CHUNK);
    if (!load_import_table(&state)) {
goto load_error;
    }

    /*
     * Read the lambda (fun) table.
     */

    if (state.chunks[LAMBDA_CHUNK].size > 0) {
define_file(&state, "lambda (fun) table", LAMBDA_CHUNK);
if (!read_lambda_table(&state)) {
    goto load_error;
}
    }

    /*
     * Read the literal table.
     */

    if (state.chunks[LITERAL_CHUNK].size > 0) {
define_file(&state, "literals table (constant pool)", LITERAL_CHUNK);
if (!read_literal_table(&state)) {
    goto load_error;
}
    }

    /*
     * Load the code chunk.
     */

    state.file_name = "code chunk";
    state.file_p = state.code_start;
    state.file_left = state.code_size;
    if (!load_code(&state) || !freeze_code(&state)) {
goto load_error;
    }

    /*
     * Read and validate the export table.  (This must be done after
     * loading the code, because it contains labels.)
     */
   
    define_file(&state, "export table", EXP_CHUNK);
    if (!read_export_table(&state)) {
goto load_error;
    }

    /*
     * Ready for the final touch: fixing the export table entries for
     * exported and imported functions.  This can't fail.
     */
   
    rval = insert_new_code (c_p, c_p_locks, state.group_leader, state.module,
   state.code, state.loaded_size, state.catches);
    if (rval < 0) {
goto load_error;
    }
    final_touch(&state);

    /*
     * Loading succeded.
     */
    rval = 0;
    state.code = NULL; /* Prevent code from being freed. */
    *modp = state.module;

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;
    }

    return rval;
}

Insert_new_code是把Code放到module_table中,同时更新加载的模块数等全局变量;
final_touch是更新export。

4. beam_load: insert_new_code
static int
insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
Eterm group_leader, Eterm module, Eterm* code, Uint size, Uint catches)
{
    Module* modp;
    int rval;
    int i;

    if ((rval = 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;
    }

    /*
     * Update module table.
     */

    erts_total_code_size += size;
    modp = erts_put_module(module);
    modp->code = code;
    modp->code_length = size;
    modp->catches = catches;

    /*
     * Update address table (used for finding a function from a PC value).
     */

    if (num_loaded_modules == allocated_modules) {
allocated_modules *= 2;
modules = (Range *) erts_realloc(ERTS_ALC_T_MODULE_REFS,
(void *) modules,
allocated_modules * sizeof(Range));
    }
    for (i = num_loaded_modules; i > 0; i--) {
if (code > modules[i-1].start) {
    break;
}
modules[i] = modules[i-1];
    }
    modules[i].start = code;
    modules[i].end = (Eterm *) (((byte *)code) + size);
    num_loaded_modules++;
    mid_module = &modules[num_loaded_modules/2];

    return 0;
}

如果modules满了,则再分配同样多的;
modules(全局变量)的结构,Range*。只是一个附加变量,主要内容在modp = erts_put_module(module);中,需要看全局变量module_table(index)

typedef struct {
    Eterm* start; /* Pointer to start of module. */
    Eterm* end; /* Points one word beyond last function in module. */
} Range;


5. beam_load:final_touch
static void
final_touch(LoaderState* stp)
{
    int i;

    /*
     * Export functions.
     */

    for (i = 0; i < stp->num_exps; i++) {
Export* ep = erts_export_put (stp->module, stp->export[i].function,
     stp->export[i].arity);
ep->address = stp->export[i].address;
    }

    /*
     * Import functions and patch all callers.
     */

    for (i = 0; i < stp->num_imports; i++) {
Eterm mod;
Eterm func;
Uint arity;
Uint import;
Uint current;
Uint next;

mod = stp->import[i].module;
func = stp->import[i].function;
arity = stp->import[i].arity;
import = (Uint) erts_export_put(mod, func, arity);
current = stp->import[i].patches;
while (current != 0) {
    ASSERT(current < stp->ci);
    next = stp->code[current];
    stp->code[current] = import;
    current = next;
}
    }

    /*
     * Fix all funs.
     */

    if (stp->num_lambdas > 0) {
for (i = 0; i < stp->num_lambdas; i++) {
    unsigned entry_label = stp->lambdas[i].label;
    ErlFunEntry* fe = stp->lambdas[i].fe;
    Eterm* code_ptr = (Eterm *) (stp->code + stp->labels[entry_label].value);

    if (fe->address[0] != 0) {
/*
* We are hiding a pointer into older code.
*/
erts_refc_dec(&fe->refc, 1);
    }
    fe->address = code_ptr;
#ifdef HIPE
    hipe_set_closure_stub(fe, stp->lambdas[i].num_free);
#endif
}
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值