Previously, Method#super_method looked at the called_id to
determine the method id to use, but that isn't correct for
aliased methods, because the super target depends on the
original method id, not the called_id.
Additionally, aliases can reference methods defined in other
classes and modules, and super lookup needs to start in the
super of the defined class in such cases.
This adds tests for Method#super_method for both types of
aliases, one that uses VM_METHOD_TYPE_ALIAS and another that
does not. Both check that the results for calling super
methods return the expected values.
To find the defined class for alias methods, add an rb_ prefix
to find_defined_class_by_owner in vm_insnhelper.c and make it
non-static, so that it can be called from method_super_method
in proc.c.
This bug was original discovered while researching [Bug #11189].
Fixes [Bug #17130]
Without this, if a refinement defines a method that calls super and
includes a module with a module that calls super and has a activated
refinement at the point super is called, the module method super call
will end up calling back into the refinement method, creating a loop.
Fixes [Bug #17007]
Struct assignment using a compound literal is more readable than before,
to me at least. It seems compilers reorder assignments anyways.
Neither speedup nor slowdown is observed on my machine.
Use ID instead of GENTRY for gvars.
Global variables are compiled into GENTRY (a pointer to struct
rb_global_entry). This patch replace this GENTRY to ID and
make the code simple.
We need to search GENTRY from ID every time (st_lookup), so
additional overhead will be introduced.
However, the performance of accessing global variables is not
important now a day and this simplicity helps Ractor development.
for opt_* insns.
opt_eq handles rb_obj_equal inside opt_eq, and all other cfunc is
handled by opt_send_without_block. Therefore we can't decide which insn
should be generated by checking whether it's cfunc cc or not.
```
$ benchmark-driver -v --rbenv 'before --jit;after --jit' benchmark/mjit_opt_cc_insns.yml --repeat-count=4
before --jit: ruby 2.8.0dev (2020-06-26T05:21:43Z master 9dbc2294a6) +JIT [x86_64-linux]
after --jit: ruby 2.8.0dev (2020-06-26T06:30:18Z master 75cece1b0b) +JIT [x86_64-linux]
last_commit=Decide JIT-ed insn based on cached cfunc
Calculating -------------------------------------
before --jit after --jit
mjit_nil?(1) 73.878M 74.021M i/s - 40.000M times in 0.541432s 0.540391s
mjit_not(1) 72.635M 74.601M i/s - 40.000M times in 0.550702s 0.536187s
mjit_eq(1, nil) 7.331M 7.445M i/s - 8.000M times in 1.091211s 1.074596s
mjit_eq(nil, 1) 49.450M 64.711M i/s - 8.000M times in 0.161781s 0.123627s
Comparison:
mjit_nil?(1)
after --jit: 74020528.4 i/s
before --jit: 73878185.9 i/s - 1.00x slower
mjit_not(1)
after --jit: 74600882.0 i/s
before --jit: 72634507.6 i/s - 1.03x slower
mjit_eq(1, nil)
after --jit: 7444657.4 i/s
before --jit: 7331304.3 i/s - 1.02x slower
mjit_eq(nil, 1)
after --jit: 64710790.6 i/s
before --jit: 49449507.4 i/s - 1.31x slower
```
This callcache is on stack, must not be GCed. However its contents are
copied from other materials, which can be an ordinal object. Should
set a flag to make sure it is properly skipped by the GC.
This changeset reduces the generated binary of
vm_call_method_missing_body from 604 bytes to 532 bytes on my machine.
Should reduce GC pressure as well.
VM stack could overflow here. The condition is when a symbol is passed
to a block-taking method via &variable, and that symbol has never been
used for actual method names (thus yielding that results in calling
method_missing), and the VM stack is full (no single word left). This
is a once-in-a-blue-moon event. Yet there is a very tiny room of stack
overflow. We need to check that.
This commit changes the number of calls of MEMCPY from...
| send | &:sym
-------------------------|-------|-------
Symbol already interned | once | twice
Symbol not pinned yet | none | once
to:
| send | &:sym
-------------------------|-------|-------
Symbol already interned | once | none
Symbol not pinned yet | twice | once
So it sacrifices exceptional situation for normal path.
Symbol#to_proc and Object#send are closely related each other. Why not
share their implementations. By doing so we can skip recursive call of
vm_exec(), which could benefit for speed.
This changeset slightly speeds up on my machine.
Calculating -------------------------------------
before after
Optcarrot Lan_Master.nes 38.33488426546287 40.89825082589147 fps
40.91288557922081 41.48687465359386
40.96591995270991 41.98499064664184
41.20461943032173 43.67314690779162
42.38344888176518 44.02777536251875
43.43563728880915 44.88695892714136
43.88082889062643 45.11226186242523
This makes it possible for vm_invoke_block to pass its passed arguments
verbatimly to calling functions. Because they are tail-called the
function calls can be strength-recuced into indirect jumps, which is a
huge win.