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