@@ -567,7 +567,8 @@ gen_putself(jitstate_t* jit, ctx_t* ctx)
567567}
568568
569569// 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 )
571572{
572573 // Convoluted rules from local_var_name() in iseq.c
573574 int32_t local_table_size = iseq -> body -> local_table_size ;
@@ -633,10 +634,10 @@ gen_setlocal_wc0(jitstate_t* jit, ctx_t* ctx)
633634 {
634635 VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
635636 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);
637638 }
638639 else {
639- vm_env_write_slowpath(ep, index, v);
640+ vm_env_write_slowpath(ep, index, v);
640641 }
641642 }
642643 */
@@ -1772,8 +1773,6 @@ gen_oswb_cfunc(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const
17721773 return YJIT_END_BLOCK ;
17731774}
17741775
1775- bool rb_simple_iseq_p (const rb_iseq_t * iseq );
1776-
17771776static void
17781777gen_return_branch (codeblock_t * cb , uint8_t * target0 , uint8_t * target1 , uint8_t shape )
17791778{
@@ -1791,31 +1790,67 @@ gen_return_branch(codeblock_t* cb, uint8_t* target0, uint8_t* target1, uint8_t s
17911790 }
17921791}
17931792
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+
17941797static 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 )
17961799{
17971800 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 ;
18011801
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 );
18041805 return YJIT_CANT_COMPILE ;
18051806 }
18061807
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+ }
18121816 }
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+ }
18131833
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 );
18171840 return YJIT_CANT_COMPILE ;
18181841 }
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 ;
18191854
18201855 // Create a size-exit to fall back to the interpreter
18211856 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
19341969 gen_direct_jump (
19351970 jit -> block ,
19361971 & callee_ctx ,
1937- (blockid_t ){ iseq , 0 }
1972+ (blockid_t ){ iseq , start_pc_offset }
19381973 );
19391974
19401975 return true;
0 commit comments