`

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

 

分享到:
评论

相关推荐

    THK_BIF28055RRG0560LC0H2K354KH21000.zip

    2. BIF2805-5RRG0+560LC0-H2K_354KH21000_front.dwg:同样为AutoCAD文件,"front"表示此文件代表产品的正视图,揭示了产品前面的布局和设计。 3. BIF2805-5RRG0+560LC0-H2K_354KH21000_right.dwg:这可能是产品的侧...

    Core_python_programming_素材

    Chapter 2 5. Loops and numbers a) i = 0 while i &lt; 11: i += 1 b) for i in range(11): pass 6. Conditionals n = int(raw_input('enter a number: ')) if n &lt; 0: print 'negative' elif n &gt; 0: print 'positive' ...

    SAP SNC 技术文档

    2. SNC 用户界面改进: - ASN_DOWNLOAD:ASN下载相关处理。 - SHIPMENT_BOL:货物装运单据处理。 - SNC_USABILITY_PO_EXT:采购订单的可用性增强。 - UIMDL_APPCUST:UI框架的变更,可以影响Web视图中的列、行、...

    FO_Lyap_李雅普诺夫_matlab_

    2. **分数阶系统**:传统上,李雅普诺夫指数是针对整数阶微分方程定义的。分数阶系统引入了非整数阶导数,使得模型能更好地描述现实世界中的复杂现象,如粘滞性、记忆效应等。 3. **MATLAB编程**:在MATLAB中,计算...

    TX1参考手册(上)

    - **BIF 位**:同活动监控器中的 BIF 位一样,此处的 BIF 位也已被标记为保留。 ##### 4. 音频处理引擎 (Audio Processing Engine) - **APE 中断控制器 (AGIC)**:新增的文字提供了有关 AGIC 的更多信息,有助于...

    bif_artery_heart_cadmodel_artery.cad_

    标题 "bif_artery_heart_cadmodel_artery.cad_" 提供的信息表明,这是一个与心血管系统相关的计算机辅助设计(CAD)模型,特别是关于动脉分叉或分支的细节。"Bifurcating artery" 指的是动脉在某个点分成两个或更多...

    光盘引导.bif光盘引导.bif光盘引导.bif光盘引导.bif光盘引导.bif43g

    光盘引导.bif光盘引导.bif光盘引导.bif光盘引导.bif

    Windows98光盘引导文件win98.bif

    《深入解析Windows 98光盘引导文件win98.bif》 在计算机操作系统的历史长河中,Windows 98以其独特的魅力和广泛的应用,占据了举足轻重的地位。其中,win98.bif文件是Windows 98光盘引导过程中的关键组件,它的存在...

    C++ BROWSEINFO

    2. **pidlRoot**:这是一个指向`ITEMIDLIST`结构的指针,表示浏览器对话框初始显示的根目录。如果设置为`NULL`,则默认显示当前用户的个人文件夹。 3. **pszDisplayName**:这是一个指向字符缓冲区的指针,用来存储...

    Python基本语法(适合小白).docx

    文档由Ryan3610于2020年4月3日编写,覆盖了Python语言的基础知识点,包括但不限于模块、序列、魔法方法、爬虫基础、正则表达式、内置函数(BIF)、文件处理、集合等。 #### 二、Python基础语法概述 ##### 1. print ...

    文件夹浏览对话框

    文件夹(路径)浏览... 2文件夹和exe文件 BrwsPath(_T("选择文件夹"),_T("C:\\Windows"),_T("C:\\"),UINT uFlags = BIF_RETURNONLYFSDIRS | BIF_BROWSEINCLUDEFILES,_T("*.exe")); &lt;br&gt; &lt;br&gt; &lt;br&gt;

    chashi-bif-1_maphem_ode_分岔_bifurcation_分叉_

    "chashi-bif-1_maphem_ode_分岔_bifurcation_分叉_"这个标题暗示了我们正在探讨的是用MATLAB进行分岔分析的实践应用,特别是针对常微分方程(ODE)的解。MATLAB是一个强大的数值计算和可视化环境,非常适合此类复杂...

    bif.zip_bifurcation_chaos_easily6x3_分岔_分岔 极大值

    标题中的“bif.zip_bifurcation_chaos_easily6x3_分岔_分岔 极大值”揭示了这个压缩包的内容与非线性动力系统的分岔和混沌现象密切相关,而且可能包含了一个名为“easily6x3”的简化模型或算法。 首先,我们来理解...

    Bif.rar_边缘平滑 matlab

    2. **bif.m**:这是MATLAB的脚本或函数文件,很可能实现了双边滤波器(Bilateral Filter)算法。双边滤波器是一种非线性的滤波器,它结合了空间一致性和色彩相似性,能够在保留图像边缘的同时平滑图像。其工作原理是...

    AM33X_SK_BSP.zip

    2. cebasecesysgen.bat:这可能是Windows CE系统生成工具的启动脚本,用于自定义和生成适应AM335x平台的Windows CE映像。 3. AM33X_SK_OS.bif:Boot Image File(BIF)文件,用于指定系统启动时加载的组件和设置,它...

    mfc选择文件夹路径代码

    //bi.ulFlags = BIF_EDITBOX | BIF_RETURNONLYFSDIRS; // 打开对话框, 有点像DoModal LPITEMIDLIST targetLocation = SHBrowseForFolder(&bi); ``` **2.1 解析** - **`BROWSEINFO`**: 结构体,用于定义浏览文件夹...

    信号灯:使用ETS的快速信号灯

    ETS提供了多种操作,如`new/2`创建表,`insert/2`插入数据,`lookup/2`查询数据,`delete/2`删除数据,以及`match_object/2`等高级查询。为了实现信号量,我们可以创建一个ETS表,其中每个键对应一个信号量,值表示...

    bif.rar_bifurcation_bifurcation diagram_matlab分岔图_分岔_分岔图

    2. **数值求解器**:MATLAB提供了多种内置的数值求解器,如`ode45`,可以用来求解这些微分方程,得到系统的演化轨迹。 3. **参数扫描**:为了绘制分岔图,需要对一个或多个参数进行扫描,改变其值并记录相应的系统...

    test-libbfd.rar_V2

    1. `bif_dma_defs.c`:这是一个C语言源代码文件,很可能包含了定义DMA(直接内存访问)相关接口的函数和结构体。DMA是一种让外部设备直接与内存交换数据的技术,无需CPU的介入,提高了系统效率,尤其在处理大量数据...

Global site tag (gtag.js) - Google Analytics