summaryrefslogtreecommitdiff
path: root/vm_args.c
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-07-28 11:02:30 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-07-28 11:02:30 +0000
commit9f60791a0412cae804f13ed3e746a634c7a0731b (patch)
tree49b3f9ff4924a622e13fbdfc9478d34717d19378 /vm_args.c
parent683eafd973e4db60756f6ee12e1b066e316f026f (diff)
* vm_core.h: revisit the structure of frame, block and env.
[Bug #12628] This patch introduce many changes. * Introduce concept of "Block Handler (BH)" to represent passed blocks. * move rb_control_frame_t::flag to ep[0] (as a special local variable). This flags represents not only frame type, but also env flags such as escaped. * rename `rb_block_t` to `struct rb_block`. * Make Proc, Binding and RubyVM::Env objects wb-protected. Check [Bug #12628] for more details. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55766 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm_args.c')
-rw-r--r--vm_args.c103
1 files changed, 45 insertions, 58 deletions
diff --git a/vm_args.c b/vm_args.c
index 1e310eb25c..89e25ca49b 100644
--- a/vm_args.c
+++ b/vm_args.c
@@ -466,22 +466,22 @@ args_setup_kw_rest_parameter(VALUE keyword_hash, VALUE *locals)
static inline void
args_setup_block_parameter(rb_thread_t *th, struct rb_calling_info *calling, VALUE *locals)
{
+ VALUE block_handler = calling->block_handler;
VALUE blockval = Qnil;
- const rb_block_t *blockptr = calling->blockptr;
- if (blockptr) {
- /* make Proc object */
- if (blockptr->proc == 0) {
- rb_proc_t *proc;
- blockval = rb_vm_make_proc(th, blockptr, rb_cProc);
- GetProcPtr(blockval, proc);
- calling->blockptr = &proc->block;
- }
- else if (SYMBOL_P(blockptr->proc)) {
- blockval = rb_sym_to_proc(blockptr->proc);
- }
- else {
- blockval = blockptr->proc;
+ if (block_handler != VM_BLOCK_HANDLER_NONE) {
+
+ switch (vm_block_handler_type(block_handler)) {
+ case block_handler_type_iseq:
+ case block_handler_type_ifunc:
+ blockval = rb_vm_make_proc(th, VM_BH_TO_CAPT_BLOCK(block_handler), rb_cProc);
+ break;
+ case block_handler_type_symbol:
+ blockval = rb_sym_to_proc(VM_BH_TO_SYMBOL(block_handler));
+ break;
+ case block_handler_type_proc:
+ blockval = VM_BH_TO_PROC(block_handler);
+ break;
}
}
*locals = blockval;
@@ -698,9 +698,9 @@ raise_argument_error(rb_thread_t *th, const rb_iseq_t *iseq, const VALUE exc)
VALUE at;
if (iseq) {
- vm_push_frame(th, iseq, VM_FRAME_MAGIC_DUMMY, Qnil /* self */,
- VM_ENVVAL_BLOCK_PTR(0) /* specval*/, Qfalse /* me or cref */,
- iseq->body->iseq_encoded, th->cfp->sp, 1 /* local_size (cref/me) */, 0 /* stack_max */);
+ vm_push_frame(th, iseq, VM_FRAME_MAGIC_DUMMY | VM_ENV_FLAG_LOCAL, Qnil /* self */,
+ VM_BLOCK_HANDLER_NONE /* specval*/, Qfalse /* me or cref */,
+ iseq->body->iseq_encoded, th->cfp->sp, 0, 0 /* stack_max */);
at = rb_vm_backtrace_object();
rb_vm_pop_frame(th);
}
@@ -766,16 +766,23 @@ vm_caller_setup_arg_kw(rb_control_frame_t *cfp, struct rb_calling_info *calling,
calling->argc -= kw_len - 1;
}
-static inline void
-vm_caller_setup_proc_as_block(rb_control_frame_t *reg_cfp,
- struct rb_calling_info *calling,
- VALUE proc)
+static VALUE
+vm_to_proc(VALUE proc)
{
- rb_proc_t *po;
+ if (UNLIKELY(!rb_obj_is_proc(proc))) {
+ VALUE b;
+ b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
- GetProcPtr(proc, po);
- calling->blockptr = &po->block;
- RUBY_VM_GET_BLOCK_PTR_IN_CFP(reg_cfp)->proc = proc;
+ if (NIL_P(b) || !rb_obj_is_proc(b)) {
+ rb_raise(rb_eTypeError,
+ "wrong argument type %s (expected Proc)",
+ rb_obj_classname(proc));
+ }
+ return b;
+ }
+ else {
+ return proc;
+ }
}
static void
@@ -783,51 +790,31 @@ vm_caller_setup_arg_block(const rb_thread_t *th, rb_control_frame_t *reg_cfp,
struct rb_calling_info *calling, const struct rb_call_info *ci, rb_iseq_t *blockiseq, const int is_super)
{
if (ci->flag & VM_CALL_ARGS_BLOCKARG) {
- VALUE proc;
+ VALUE block_code = *(--reg_cfp->sp);
- proc = *(--reg_cfp->sp);
-
- if (NIL_P(proc)) {
- calling->blockptr = NULL;
+ if (NIL_P(block_code)) {
+ calling->block_handler = VM_BLOCK_HANDLER_NONE;
}
- else if (SYMBOL_P(proc) &&
- rb_method_basic_definition_p(rb_cSymbol, idTo_proc)) {
- if (LIKELY(!(ci->flag & VM_CALL_TAILCALL))) {
- calling->blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(reg_cfp);
- calling->blockptr->iseq = (rb_iseq_t *)proc;
- calling->blockptr->proc = proc;
+ else {
+ if (SYMBOL_P(block_code) && rb_method_basic_definition_p(rb_cSymbol, idTo_proc)) {
+ calling->block_handler = block_code;
}
else {
- proc = rb_sym_to_proc(proc);
- vm_caller_setup_proc_as_block(reg_cfp, calling, proc);
- }
- }
- else {
- if (!rb_obj_is_proc(proc)) {
- VALUE b;
- b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
-
- if (NIL_P(b) || !rb_obj_is_proc(b)) {
- rb_raise(rb_eTypeError,
- "wrong argument type %s (expected Proc)",
- rb_obj_classname(proc));
- }
- proc = b;
+ calling->block_handler = vm_to_proc(block_code);
}
- vm_caller_setup_proc_as_block(reg_cfp, calling, proc);
}
}
- else if (blockiseq != 0) { /* likely */
- rb_block_t *blockptr = calling->blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(reg_cfp);
- blockptr->iseq = blockiseq;
- blockptr->proc = 0;
+ else if (blockiseq != NULL) { /* likely */
+ struct rb_captured_block *captured = VM_CFP_TO_CAPTURED_BLOCK(reg_cfp);
+ captured->code.iseq = blockiseq;
+ calling->block_handler = VM_BH_FROM_ISEQ_BLOCK(captured);
}
else {
if (is_super) {
- calling->blockptr = GET_BLOCK_PTR();
+ calling->block_handler = GET_BLOCK_HANDLER();
}
else {
- calling->blockptr = NULL;
+ calling->block_handler = VM_BLOCK_HANDLER_NONE;
}
}
}