@@ -565,7 +565,8 @@ gen_putself(jitstate_t* jit, ctx_t* ctx)
565
565
}
566
566
567
567
// Compute the index of a local variable from its slot index
568
- uint32_t slot_to_local_idx (const rb_iseq_t * iseq , int32_t slot_idx )
568
+ static uint32_t
569
+ slot_to_local_idx (const rb_iseq_t * iseq , int32_t slot_idx )
569
570
{
570
571
// Convoluted rules from local_var_name() in iseq.c
571
572
int32_t local_table_size = iseq -> body -> local_table_size ;
@@ -631,10 +632,10 @@ gen_setlocal_wc0(jitstate_t* jit, ctx_t* ctx)
631
632
{
632
633
VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
633
634
if (LIKELY((flags & VM_ENV_FLAG_WB_REQUIRED) == 0)) {
634
- VM_STACK_ENV_WRITE(ep, index, v);
635
+ VM_STACK_ENV_WRITE(ep, index, v);
635
636
}
636
637
else {
637
- vm_env_write_slowpath(ep, index, v);
638
+ vm_env_write_slowpath(ep, index, v);
638
639
}
639
640
}
640
641
*/
@@ -1771,8 +1772,6 @@ gen_oswb_cfunc(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const
1771
1772
return YJIT_END_BLOCK ;
1772
1773
}
1773
1774
1774
- bool rb_simple_iseq_p (const rb_iseq_t * iseq );
1775
-
1776
1775
static void
1777
1776
gen_return_branch (codeblock_t * cb , uint8_t * target0 , uint8_t * target1 , uint8_t shape )
1778
1777
{
@@ -1790,31 +1789,67 @@ gen_return_branch(codeblock_t* cb, uint8_t* target0, uint8_t* target1, uint8_t s
1790
1789
}
1791
1790
}
1792
1791
1792
+ bool rb_simple_iseq_p (const rb_iseq_t * iseq );
1793
+ bool rb_iseq_only_optparam_p (const rb_iseq_t * iseq );
1794
+ bool rb_iseq_only_kwparam_p (const rb_iseq_t * iseq );
1795
+
1793
1796
static codegen_status_t
1794
- gen_oswb_iseq (jitstate_t * jit , ctx_t * ctx , const struct rb_callinfo * ci , const rb_callable_method_entry_t * cme , int32_t argc )
1797
+ gen_oswb_iseq (jitstate_t * jit , ctx_t * ctx , const struct rb_callinfo * ci , const rb_callable_method_entry_t * cme , const int32_t argc )
1795
1798
{
1796
1799
const rb_iseq_t * iseq = def_iseq_ptr (cme -> def );
1797
- const VALUE * start_pc = iseq -> body -> iseq_encoded ;
1798
- int num_params = iseq -> body -> param.size ;
1799
- int num_locals = iseq -> body -> local_table_size - num_params ;
1800
1800
1801
- if (num_params != argc ) {
1802
- GEN_COUNTER_INC (cb , oswb_iseq_argc_mismatch );
1801
+ if (vm_ci_flag (ci ) & VM_CALL_TAILCALL ) {
1802
+ // We can't handle tailcalls
1803
+ GEN_COUNTER_INC (cb , oswb_iseq_tailcall );
1803
1804
return YJIT_CANT_COMPILE ;
1804
1805
}
1805
1806
1806
- if (!rb_simple_iseq_p (iseq )) {
1807
- // Only handle iseqs that have simple parameters.
1808
- // See vm_callee_setup_arg().
1809
- GEN_COUNTER_INC (cb , oswb_iseq_not_simple );
1810
- return YJIT_CANT_COMPILE ;
1807
+ // Arity handling and optional parameter setup
1808
+ int num_params = iseq -> body -> param .size ;
1809
+ uint32_t start_pc_offset = 0 ;
1810
+ if (rb_simple_iseq_p (iseq )) {
1811
+ if (num_params != argc ) {
1812
+ GEN_COUNTER_INC (cb , oswb_iseq_arity_error );
1813
+ return YJIT_CANT_COMPILE ;
1814
+ }
1811
1815
}
1816
+ else if (rb_iseq_only_optparam_p (iseq )) {
1817
+ // These are iseqs with 0 or more required parameters followed by 1
1818
+ // or more optional parameters.
1819
+ // We follow the logic of vm_call_iseq_setup_normal_opt_start()
1820
+ // and these are the preconditions required for using that fast path.
1821
+ RUBY_ASSERT (vm_ci_markable (ci ) && ((vm_ci_flag (ci ) &
1822
+ (VM_CALL_KW_SPLAT | VM_CALL_KWARG | VM_CALL_ARGS_SPLAT )) == 0 ));
1823
+
1824
+ const int required_num = iseq -> body -> param .lead_num ;
1825
+ const int opts_filled = argc - required_num ;
1826
+ const int opt_num = iseq -> body -> param .opt_num ;
1827
+
1828
+ if (opts_filled < 0 || opts_filled > opt_num ) {
1829
+ GEN_COUNTER_INC (cb , oswb_iseq_arity_error );
1830
+ return YJIT_CANT_COMPILE ;
1831
+ }
1812
1832
1813
- if (vm_ci_flag (ci ) & VM_CALL_TAILCALL ) {
1814
- // We can't handle tailcalls
1815
- GEN_COUNTER_INC (cb , oswb_iseq_tailcall );
1833
+ num_params -= opt_num - opts_filled ;
1834
+ start_pc_offset = (uint32_t )iseq -> body -> param .opt_table [opts_filled ];
1835
+ }
1836
+ else if (rb_iseq_only_kwparam_p (iseq )) {
1837
+ // vm_callee_setup_arg() has a fast path for this.
1838
+ GEN_COUNTER_INC (cb , oswb_iseq_only_keywords );
1816
1839
return YJIT_CANT_COMPILE ;
1817
1840
}
1841
+ else {
1842
+ // Only handle iseqs that have simple parameter setup.
1843
+ // See vm_callee_setup_arg().
1844
+ GEN_COUNTER_INC (cb , oswb_iseq_complex_callee );
1845
+ return YJIT_CANT_COMPILE ;
1846
+ }
1847
+
1848
+ // The starting pc of the callee frame
1849
+ const VALUE * start_pc = & iseq -> body -> iseq_encoded [start_pc_offset ];
1850
+
1851
+ // Number of locals that are not parameters
1852
+ const int num_locals = iseq -> body -> local_table_size - num_params ;
1818
1853
1819
1854
// Create a size-exit to fall back to the interpreter
1820
1855
uint8_t * side_exit = yjit_side_exit (jit , ctx );
@@ -1933,7 +1968,7 @@ gen_oswb_iseq(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const r
1933
1968
gen_direct_jump (
1934
1969
jit -> block ,
1935
1970
& callee_ctx ,
1936
- (blockid_t ){ iseq , 0 }
1971
+ (blockid_t ){ iseq , start_pc_offset }
1937
1972
);
1938
1973
1939
1974
return YJIT_END_BLOCK ;
0 commit comments