From 39c3252cd175074581855e5f9681cc723c15ff72 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Tue, 3 Sep 2019 11:32:02 -0700 Subject: Merge pull request #2422 from jeremyevans/rb_keyword_given_p Add rb_keyword_given_p to the C-API --- eval.c | 8 ++++++++ include/ruby/ruby.h | 1 + vm.c | 6 ++++++ vm_core.h | 11 +++++++++-- vm_insnhelper.c | 6 +++++- vm_insnhelper.h | 1 + 6 files changed, 30 insertions(+), 3 deletions(-) diff --git a/eval.c b/eval.c index 30d4ea57c3..eb34c35f01 100644 --- a/eval.c +++ b/eval.c @@ -899,6 +899,14 @@ rb_block_given_p(void) } } +int rb_vm_cframe_keyword_p(const rb_control_frame_t *cfp); + +int +rb_keyword_given_p(void) +{ + return rb_vm_cframe_keyword_p(GET_EC()->cfp); +} + VALUE rb_eThreadError; /*! Declares that the current method needs a block. diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h index 0d7880b349..53d4eabc0a 100644 --- a/include/ruby/ruby.h +++ b/include/ruby/ruby.h @@ -1960,6 +1960,7 @@ VALUE rb_yield_values(int n, ...); VALUE rb_yield_values2(int n, const VALUE *argv); VALUE rb_yield_splat(VALUE); VALUE rb_yield_block(VALUE, VALUE, int, const VALUE *, VALUE); /* rb_block_call_func */ +int rb_keyword_given_p(void); int rb_block_given_p(void); void rb_need_block(void); VALUE rb_iterate(VALUE(*)(VALUE),VALUE,rb_block_call_func_t,VALUE); diff --git a/vm.c b/vm.c index cbd7b31f3e..88b76c47ab 100644 --- a/vm.c +++ b/vm.c @@ -96,6 +96,12 @@ VM_CF_BLOCK_HANDLER(const rb_control_frame_t * const cfp) return VM_ENV_BLOCK_HANDLER(ep); } +int +rb_vm_cframe_keyword_p(const rb_control_frame_t *cfp) +{ + return VM_FRAME_CFRAME_KW_P(cfp); +} + VALUE rb_vm_frame_block_handler(const rb_control_frame_t *cfp) { diff --git a/vm_core.h b/vm_core.h index 1ebcea7a2d..eec80e41ef 100644 --- a/vm_core.h +++ b/vm_core.h @@ -1166,11 +1166,11 @@ typedef rb_control_frame_t * enum { /* Frame/Environment flag bits: - * MMMM MMMM MMMM MMMM ____ __FF FFFF EEEX (LSB) + * MMMM MMMM MMMM MMMM ____ _FFF FFFF EEEX (LSB) * * X : tag for GC marking (It seems as Fixnum) * EEE : 3 bits Env flags - * FF..: 6 bits Frame flags + * FF..: 7 bits Frame flags * MM..: 15 bits frame magic (to check frame corruption) */ @@ -1194,6 +1194,7 @@ enum { VM_FRAME_FLAG_CFRAME = 0x0080, VM_FRAME_FLAG_LAMBDA = 0x0100, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM = 0x0200, + VM_FRAME_FLAG_CFRAME_KW = 0x0400, /* env flag */ VM_ENV_FLAG_LOCAL = 0x0002, @@ -1248,6 +1249,12 @@ VM_FRAME_LAMBDA_P(const rb_control_frame_t *cfp) return VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_LAMBDA) != 0; } +static inline int +VM_FRAME_CFRAME_KW_P(const rb_control_frame_t *cfp) +{ + return VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_CFRAME_KW) != 0; +} + static inline int VM_FRAME_FINISHED_P(const rb_control_frame_t *cfp) { diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 1c74b121e8..b1a13d078e 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -2185,6 +2185,7 @@ vm_call_cfunc_with_frame(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp VALUE recv = calling->recv; VALUE block_handler = calling->block_handler; + VALUE frame_type = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL; int argc = calling->argc; int orig_argc = argc; @@ -2193,11 +2194,14 @@ vm_call_cfunc_with_frame(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp argc--; } } + if (UNLIKELY(IS_ARGS_KW_OR_KW_SPLAT(ci))) { + frame_type |= VM_FRAME_FLAG_CFRAME_KW; + } RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, me->owner, me->def->original_id); EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, recv, me->def->original_id, ci->mid, me->owner, Qundef); - vm_push_frame(ec, NULL, VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL, recv, + vm_push_frame(ec, NULL, frame_type, recv, block_handler, (VALUE)me, 0, ec->cfp->sp, 0, 0); diff --git a/vm_insnhelper.h b/vm_insnhelper.h index 7709840930..9f09d4ab5e 100644 --- a/vm_insnhelper.h +++ b/vm_insnhelper.h @@ -241,6 +241,7 @@ THROW_DATA_CONSUMED_SET(struct vm_throw_data *obj) #define IS_ARGS_SPLAT(ci) ((ci)->flag & VM_CALL_ARGS_SPLAT) #define IS_ARGS_KEYWORD(ci) ((ci)->flag & VM_CALL_KWARG) #define IS_ARGS_KW_SPLAT(ci) ((ci)->flag & VM_CALL_KW_SPLAT) +#define IS_ARGS_KW_OR_KW_SPLAT(ci) ((ci)->flag & (VM_CALL_KWARG | VM_CALL_KW_SPLAT)) /* If this returns true, an optimized function returned by `vm_call_iseq_setup_func` can be used as a fastpath. */ -- cgit v1.2.3