aboutsummaryrefslogblamecommitdiffstats
path: root/erts/emulator/hipe/hipe_instrs.tab
blob: 62162fcb9ca97883f1e5c68ce13b42f7aeea6757 (plain) (tree)














































                                                                           
                                               






                                                                        
                                               































                                                                                
                  






















                                                                         



















                                                                                         
                                               





                                     
// -*- c -*-
//
// %CopyrightBegin%
//
// Copyright Ericsson AB 2017. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// %CopyrightEnd%
//


HIPE_MODE_SWITCH(Cmd) {
    SWAPOUT;
    ERTS_DBG_CHK_REDS(c_p, FCALLS);
    c_p->fcalls = FCALLS;
    c_p->def_arg_reg[4] = -neg_o_reds;
    c_p = hipe_mode_switch(c_p, $Cmd, reg);
}

hipe_trap_call := hipe_trap.call.post;
hipe_trap_call_closure := hipe_trap.call_closure.post;
hipe_trap_return := hipe_trap.return.post;
hipe_trap_throw := hipe_trap.throw.post;
hipe_trap_resume := hipe_trap.resume.post;

hipe_trap.call() {
    /*
     * I[-5]: &&lb_i_func_info_IaaI
     * I[-4]: Native code callee (inserted by HiPE)
     * I[-3]: Module (tagged atom)
     * I[-2]: Function (tagged atom)
     * I[-1]: Arity (untagged integer)
     * I[ 0]: &&lb_hipe_trap_call
     * ... remainder of original BEAM code
     */
    ErtsCodeInfo *ci = erts_code_to_codeinfo(I);
    ASSERT(IsOpCode(ci->op, i_func_info_IaaI));
    c_p->hipe.u.ncallee = ci->u.ncallee;
    ++hipe_trap_count;
    $HIPE_MODE_SWITCH(HIPE_MODE_SWITCH_CMD_CALL | (ci->mfa.arity << 8));
}

hipe_trap.call_closure() {
    ErtsCodeInfo *ci = erts_code_to_codeinfo(I);
    ASSERT(IsOpCode(ci->op, i_func_info_IaaI));
    c_p->hipe.u.ncallee = ci->u.ncallee;
    ++hipe_trap_count;
    $HIPE_MODE_SWITCH(HIPE_MODE_SWITCH_CMD_CALL_CLOSURE | (ci->mfa.arity << 8));
}

hipe_trap.return() {
    $HIPE_MODE_SWITCH(HIPE_MODE_SWITCH_CMD_RETURN);
}

hipe_trap.throw() {
    $HIPE_MODE_SWITCH(HIPE_MODE_SWITCH_CMD_THROW);
}

hipe_trap.resume() {
    $HIPE_MODE_SWITCH(HIPE_MODE_SWITCH_CMD_RESUME);
}

hipe_trap.post() {
#ifdef DEBUG
    pid = c_p->common.id; /* may have switched process... */
#endif
    reg = erts_proc_sched_data(c_p)->x_reg_array;
    freg = erts_proc_sched_data(c_p)->f_reg_array;
    ERL_BITS_RELOAD_STATEP(c_p);
    /* XXX: this abuse of def_arg_reg[] is horrid! */
    neg_o_reds = -c_p->def_arg_reg[4];
    FCALLS = c_p->fcalls;
    SWAPIN;
    ERTS_DBG_CHK_REDS(c_p, FCALLS);
    switch( c_p->def_arg_reg[3] ) {
    case HIPE_MODE_SWITCH_RES_RETURN:
        ASSERT(is_value(reg[0]));
        $RETURN();
        Goto(*I);
    case HIPE_MODE_SWITCH_RES_CALL_EXPORTED:
        c_p->i = c_p->hipe.u.callee_exp->addressv[erts_active_code_ix()];
        /*fall through*/
    case HIPE_MODE_SWITCH_RES_CALL_BEAM:
        SET_I(c_p->i);
        Dispatch();
    case HIPE_MODE_SWITCH_RES_CALL_CLOSURE:
        /* This can be used to call any function value, but currently
           it's only used to call closures referring to unloaded
           modules. */
        {
            BeamInstr *next;

            next = call_fun(c_p, c_p->arity - 1, reg, THE_NON_VALUE);
            HEAVY_SWAPIN;
            if (next != NULL) {
                SET_I(next);
                Dispatchfun();
            }
            goto find_func_info;
        }
    case HIPE_MODE_SWITCH_RES_THROW:
        I = handle_error(c_p, I, reg, NULL);
        goto post_error_handling;
    default:
        erts_exit(ERTS_ERROR_EXIT, "hipe_mode_switch: result %u\n", c_p->def_arg_reg[3]);
    }
    //| -no_next;
}

hipe_call_count() {
    /*
     * I[-5]: &&lb_i_func_info_IaaI
     * I[-4]: pointer to struct hipe_call_count (inserted by HiPE)
     * I[-3]: Module (tagged atom)
     * I[-2]: Function (tagged atom)
     * I[-1]: Arity (untagged integer)
     * I[ 0]: &&lb_hipe_call_count
     * ... remainder of original BEAM code
     */
    ErtsCodeInfo *ci = erts_code_to_codeinfo(I);
    struct hipe_call_count *hcc = ci->u.hcc;
    ASSERT(IsOpCode(ci->op, i_func_info_IaaI));
    ASSERT(hcc != NULL);
    ASSERT(VALID_INSTR(hcc->opcode));
    ++(hcc->count);
    Goto(hcc->opcode);
    //| -no_next;
}