diff options
author | Björn Gustavsson <[email protected]> | 2019-06-26 15:49:48 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2019-08-22 13:37:41 +0200 |
commit | 25fe3fb23c594d735cb6ebae120910e44f0cdae4 (patch) | |
tree | 746907d20fb667858ec419cf49138f851317e055 /erts/emulator/hipe | |
parent | e51727f129d6b5667f81e86865d17cf564712054 (diff) | |
download | otp-25fe3fb23c594d735cb6ebae120910e44f0cdae4.tar.gz otp-25fe3fb23c594d735cb6ebae120910e44f0cdae4.tar.bz2 otp-25fe3fb23c594d735cb6ebae120910e44f0cdae4.zip |
Optimize continuation pointer management
The BEAM instructions for calling a function don't save the
continuation pointer (return address) on the stack, but to a special
BEAM register called CP. It is the responsibility of the called
function to save CP to the stack frame before calling other functions.
In the earlier implementations of BEAM on Sparc, CP was located in a
CPU register. That meant that the continuation pointer was never
written to memory when calling simple functions that didn't call
other functions at all or ended in a tail-call to another function.
The modern BEAM no longer keeps CP in CPU register. Instead, it is
kept in the `process` struct (in `p->cp`). That means the continuation
pointer must be written to the memory on every call, and if the called
function will call other functions, it will must read the continuation
pointer from `p->cp` and store it on the stack.
This commit eliminates the concept of the CP register and modifies
the call instructions to directly store the continuation pointer on
the stack. That makes allocation and trimming of stack frames slightly
faster. A more important benefit is simplification of code that handles
continuation pointers. Because all continuation pointers are now stored
on the stack, the special case of handling `p->cp` disappears.
Co-authored-by: John Högberg <[email protected]>
Diffstat (limited to 'erts/emulator/hipe')
-rw-r--r-- | erts/emulator/hipe/hipe_debug.c | 1 | ||||
-rw-r--r-- | erts/emulator/hipe/hipe_instrs.tab | 4 | ||||
-rw-r--r-- | erts/emulator/hipe/hipe_mode_switch.c | 8 |
3 files changed, 4 insertions, 9 deletions
diff --git a/erts/emulator/hipe/hipe_debug.c b/erts/emulator/hipe/hipe_debug.c index 138e4f7da3..2e34cfac59 100644 --- a/erts/emulator/hipe/hipe_debug.c +++ b/erts/emulator/hipe/hipe_debug.c @@ -232,7 +232,6 @@ void hipe_print_pcb(Process *p) U("intial.fun ", u.initial.function); U("intial.ari ", u.initial.arity); U("current ", current); - P("cp ", cp); P("i ", i); U("catches ", catches); U("arity ", arity); diff --git a/erts/emulator/hipe/hipe_instrs.tab b/erts/emulator/hipe/hipe_instrs.tab index a01baebddf..62162fcb9c 100644 --- a/erts/emulator/hipe/hipe_instrs.tab +++ b/erts/emulator/hipe/hipe_instrs.tab @@ -86,8 +86,7 @@ hipe_trap.post() { switch( c_p->def_arg_reg[3] ) { case HIPE_MODE_SWITCH_RES_RETURN: ASSERT(is_value(reg[0])); - SET_I(c_p->cp); - c_p->cp = 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()]; @@ -111,7 +110,6 @@ hipe_trap.post() { goto find_func_info; } case HIPE_MODE_SWITCH_RES_THROW: - c_p->cp = NULL; I = handle_error(c_p, I, reg, NULL); goto post_error_handling; default: diff --git a/erts/emulator/hipe/hipe_mode_switch.c b/erts/emulator/hipe/hipe_mode_switch.c index 052cf9c263..863c5e6d44 100644 --- a/erts/emulator/hipe/hipe_mode_switch.c +++ b/erts/emulator/hipe/hipe_mode_switch.c @@ -202,15 +202,13 @@ hipe_push_beam_trap_frame(Process *p, Eterm reg[], unsigned arity) p->stop -= 2; p->stop[1] = hipe_beam_catch_throw; } - p->stop[0] = make_cp(p->cp); + p->stop[0] = (BeamInstr) hipe_beam_pc_return; ++p->catches; - p->cp = hipe_beam_pc_return; } static __inline__ void hipe_pop_beam_trap_frame(Process *p) { ASSERT(p->stop[1] == hipe_beam_catch_throw); - p->cp = cp_val(p->stop[0]); --p->catches; p->stop += 2; } @@ -263,7 +261,7 @@ Process *hipe_mode_switch(Process *p, unsigned cmd, Eterm reg[]) unsigned arity = cmd >> 8; /* p->hipe.u.ncallee set in beam_emu */ - if (p->cp == hipe_beam_pc_return) { + if (cp_val(p->stop[0]) == hipe_beam_pc_return) { /* Native called BEAM, which now tailcalls native. */ hipe_pop_beam_trap_frame(p); result = hipe_tailcall_to_native(p, arity, reg); @@ -292,7 +290,7 @@ Process *hipe_mode_switch(Process *p, unsigned cmd, Eterm reg[]) /* just like a normal call from now on */ /* p->hipe.u.ncallee set in beam_emu */ - if (p->cp == hipe_beam_pc_return) { + if (cp_val(p->stop[0]) == hipe_beam_pc_return) { /* Native called BEAM, which now tailcalls native. */ hipe_pop_beam_trap_frame(p); result = hipe_tailcall_to_native(p, arity, reg); |