mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
Remove __bp__ and speed-up bmethod calls (#8060)
Remove rb_control_frame_t::__bp__ and optimize bmethod calls
This commit removes the __bp__ field from rb_control_frame_t. It was
introduced to help MJIT, but since MJIT was replaced by RJIT, we can use
vm_base_ptr() to compute it from the SP of the previous control frame
instead. Removing the field avoids needing to set it up when pushing new
frames.
Simply removing __bp__ would cause crashes since RJIT and YJIT used a
slightly different stack layout for bmethod calls than the interpreter.
At the moment of the call, the two layouts looked as follows:
┌────────────┐ ┌────────────┐
│ frame_base │ │ frame_base │
├────────────┤ ├────────────┤
│ ... │ │ ... │
├────────────┤ ├────────────┤
│ args │ │ args │
├────────────┤ └────────────┘<─prev_frame_sp
│ receiver │
prev_frame_sp─>└────────────┘
RJIT & YJIT interpreter
Essentially, vm_base_ptr() needs to compute the address to frame_base
given prev_frame_sp in the diagrams. The presence of the receiver
created an off-by-one situation.
Make the interpreter use the layout the JITs use for iseq-to-iseq
bmethod calls. Doing so removes unnecessary argument shifting and
vm_exec_core() re-entry from the interpreter, yielding a speed
improvement visible through `benchmark/vm_defined_method.yml`:
patched: 7578743.1 i/s
master: 4796596.3 i/s - 1.58x slower
C-to-iseq bmethod calls now store one more VALUE than before, but that
should have negligible impact on overall performance.
Note that re-entering vm_exec_core() used to be necessary for firing
TracePoint events, but that's no longer the case since
9121e57a5f
.
Closes ruby/ruby#6428
This commit is contained in:
parent
105bdba899
commit
f302e725e1
8 changed files with 38 additions and 36 deletions
|
@ -281,14 +281,14 @@ rb_vmdebug_stack_dump_th(VALUE thval)
|
|||
|
||||
#if VMDEBUG > 2
|
||||
|
||||
/* copy from vm.c */
|
||||
/* copy from vm_insnhelper.c */
|
||||
static const VALUE *
|
||||
vm_base_ptr(const rb_control_frame_t *cfp)
|
||||
{
|
||||
const rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
||||
const VALUE *bp = prev_cfp->sp + ISEQ_BODY(cfp->iseq)->local_table_size + VM_ENV_DATA_SIZE;
|
||||
|
||||
if (ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_METHOD) {
|
||||
if (ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_METHOD || VM_FRAME_BMETHOD_P(cfp)) {
|
||||
bp += 1;
|
||||
}
|
||||
return bp;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue