[前][次][番号順一覧][スレッド一覧]

ruby-changes:43694

From: ko1 <ko1@a...>
Date: Thu, 28 Jul 2016 20:02:38 +0900 (JST)
Subject: [ruby-changes:43694] ko1:r55766 (trunk): * vm_core.h: revisit the structure of frame, block and env.

ko1	2016-07-28 20:02:30 +0900 (Thu, 28 Jul 2016)

  New Revision: 55766

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=55766

  Log:
    * 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.

  Modified files:
    trunk/ChangeLog
    trunk/compile.c
    trunk/cont.c
    trunk/eval.c
    trunk/eval_intern.h
    trunk/gc.c
    trunk/insns.def
    trunk/internal.h
    trunk/iseq.c
    trunk/load.c
    trunk/parse.y
    trunk/proc.c
    trunk/process.c
    trunk/ruby.c
    trunk/string.c
    trunk/thread.c
    trunk/tool/mk_call_iseq_optimized.rb
    trunk/vm.c
    trunk/vm_args.c
    trunk/vm_core.h
    trunk/vm_dump.c
    trunk/vm_eval.c
    trunk/vm_insnhelper.c
    trunk/vm_insnhelper.h
    trunk/vm_method.c
Index: string.c
===================================================================
--- string.c	(revision 55765)
+++ string.c	(revision 55766)
@@ -9459,7 +9459,7 @@ sym_to_sym(VALUE sym) https://github.com/ruby/ruby/blob/trunk/string.c#L9459
 }
 
 VALUE
-rb_sym_proc_call(VALUE args, VALUE sym, int argc, const VALUE *argv, VALUE passed_proc)
+rb_sym_proc_call(ID mid, int argc, const VALUE *argv, VALUE passed_proc)
 {
     VALUE obj;
 
@@ -9467,7 +9467,7 @@ rb_sym_proc_call(VALUE args, VALUE sym, https://github.com/ruby/ruby/blob/trunk/string.c#L9467
 	rb_raise(rb_eArgError, "no receiver given");
     }
     obj = argv[0];
-    return rb_funcall_with_block(obj, (ID)sym, argc - 1, argv + 1, passed_proc);
+    return rb_funcall_with_block(obj, mid, argc - 1, argv + 1, passed_proc);
 }
 
 #if 0
Index: eval_intern.h
===================================================================
--- eval_intern.h	(revision 55765)
+++ eval_intern.h	(revision 55766)
@@ -5,13 +5,23 @@ https://github.com/ruby/ruby/blob/trunk/eval_intern.h#L5
 #include "vm_core.h"
 
 static inline void
-pass_passed_block(rb_thread_t *th)
+vm_passed_block_handler_set(rb_thread_t *th, VALUE block_handler)
 {
-    th->passed_block = rb_vm_control_frame_block_ptr(th->cfp);
-    th->cfp->flag |= VM_FRAME_FLAG_PASSED;
+    VM_ASSERT(vm_block_handler_verify(block_handler));
+    th->passed_block_handler = block_handler;
 }
-#define PASS_PASSED_BLOCK_TH(th) pass_passed_block(th)
-#define PASS_PASSED_BLOCK() pass_passed_block(GET_THREAD())
+
+static inline void
+pass_passed_block_handler(rb_thread_t *th)
+{
+    VALUE block_handler = rb_vm_frame_block_handler(th->cfp);
+    VM_ASSERT(vm_block_handler_verify(block_handler));
+    vm_passed_block_handler_set(th, block_handler);
+    VM_ENV_FLAGS_SET(th->cfp->ep, VM_FRAME_FLAG_PASSED);
+}
+
+#define PASS_PASSED_BLOCK_HANDLER_TH(th) pass_passed_block_handler(th)
+#define PASS_PASSED_BLOCK_HANDLER() pass_passed_block_handler(GET_THREAD())
 
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
@@ -277,7 +287,7 @@ NORETURN(void rb_raise_method_missing(rb https://github.com/ruby/ruby/blob/trunk/eval_intern.h#L287
 VALUE rb_vm_make_jump_tag_but_local_jump(int state, VALUE val);
 rb_cref_t *rb_vm_cref(void);
 rb_cref_t *rb_vm_cref_replace_with_duplicated_cref(void);
-VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, const rb_block_t *blockptr, VALUE filename);
+VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, VALUE block_handler, VALUE filename);
 void rb_vm_set_progname(VALUE filename);
 void rb_thread_terminate_all(void);
 VALUE rb_vm_cbase(void);
Index: ruby.c
===================================================================
--- ruby.c	(revision 55765)
+++ ruby.c	(revision 55766)
@@ -639,13 +639,10 @@ require_libraries(VALUE *req_list) https://github.com/ruby/ruby/blob/trunk/ruby.c#L639
     *req_list = 0;
 }
 
-static rb_block_t*
+static const struct rb_block*
 toplevel_context(rb_binding_t *bind)
 {
-    rb_env_t *env;
-
-    GetEnvPtr(bind->env, env);
-    return &env->block;
+    return &bind->block;
 }
 
 static void
@@ -1447,7 +1444,7 @@ process_options(int argc, char **argv, s https://github.com/ruby/ruby/blob/trunk/ruby.c#L1444
     char fbuf[MAXPATHLEN];
     int i = (int)proc_options(argc, argv, opt, 0);
     rb_binding_t *toplevel_binding;
-    rb_block_t *base_block;
+    const struct rb_block *base_block;
 
     argc -= i;
     argv += i;
@@ -1700,7 +1697,7 @@ process_options(int argc, char **argv, s https://github.com/ruby/ruby/blob/trunk/ruby.c#L1697
 	    path = rb_realpath_internal(Qnil, opt->script_name, 1);
 	}
 	base_block = toplevel_context(toplevel_binding);
-	iseq = rb_iseq_new_main(tree, opt->script_name, path, base_block->iseq);
+	iseq = rb_iseq_new_main(tree, opt->script_name, path, vm_block_iseq(base_block));
     }
 
     if (opt->dump & DUMP_BIT(insns)) {
Index: insns.def
===================================================================
--- insns.def	(revision 55765)
+++ insns.def	(revision 55766)
@@ -58,7 +58,7 @@ getlocal https://github.com/ruby/ruby/blob/trunk/insns.def#L58
 (VALUE val)
 {
     int i, lev = (int)level;
-    VALUE *ep = GET_EP();
+    const VALUE *ep = GET_EP();
 
     /* optimized insns generated for level == (0|1) in defs/opt_operand.def */
     for (i = 0; i < lev; i++) {
@@ -81,13 +81,13 @@ setlocal https://github.com/ruby/ruby/blob/trunk/insns.def#L81
 ()
 {
     int i, lev = (int)level;
-    VALUE *ep = GET_EP();
+    const VALUE *ep = GET_EP();
 
     /* optimized insns generated for level == (0|1) in defs/opt_operand.def */
     for (i = 0; i < lev; i++) {
 	ep = GET_PREV_EP(ep);
     }
-    *(ep - idx) = val;
+    vm_env_write(ep, -(int)idx, val);
 }
 
 /**
@@ -790,7 +790,7 @@ checkkeyword https://github.com/ruby/ruby/blob/trunk/insns.def#L790
 	ret = (bits & (0x01 << keyword_index)) ? Qfalse : Qtrue;
     }
     else {
-	assert(RB_TYPE_P(kw_bits, T_HASH));
+	VM_ASSERT(RB_TYPE_P(kw_bits, T_HASH));
 	ret = rb_hash_has_key(kw_bits, INT2FIX(keyword_index)) ? Qfalse : Qtrue;
     }
 }
@@ -932,11 +932,11 @@ defineclass https://github.com/ruby/ruby/blob/trunk/insns.def#L932
     rb_iseq_check(class_iseq);
 
     /* enter scope */
-    vm_push_frame(th, class_iseq, VM_FRAME_MAGIC_CLASS, klass,
-		  VM_ENVVAL_BLOCK_PTR(GET_BLOCK_PTR()),
+    vm_push_frame(th, class_iseq, VM_FRAME_MAGIC_CLASS | VM_ENV_FLAG_LOCAL, klass,
+		  GET_BLOCK_HANDLER(),
 		  (VALUE)vm_cref_push(th, klass, NULL, FALSE),
 		  class_iseq->body->iseq_encoded, GET_SP(),
-		  class_iseq->body->local_size,
+		  class_iseq->body->local_table_size,
 		  class_iseq->body->stack_max);
     RESTORE_REGS();
     NEXT_INSN();
@@ -1059,7 +1059,7 @@ opt_send_without_block https://github.com/ruby/ruby/blob/trunk/insns.def#L1059
 (VALUE val) // inc += -ci->orig_argc;
 {
     struct rb_calling_info calling;
-    calling.blockptr = NULL;
+    calling.block_handler = VM_BLOCK_HANDLER_NONE;
     vm_search_method(ci, cc, calling.recv = TOPN(calling.argc = ci->orig_argc));
     CALL_METHOD(&calling, ci, cc);
 }
@@ -1097,7 +1097,7 @@ invokeblock https://github.com/ruby/ruby/blob/trunk/insns.def#L1097
 {
     struct rb_calling_info calling;
     calling.argc = ci->orig_argc;
-    calling.blockptr = NULL;
+    calling.block_handler = VM_BLOCK_HANDLER_NONE;
     calling.recv = GET_SELF();
 
     val = vm_invoke_block(th, GET_CFP(), &calling, ci);
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 55765)
+++ ChangeLog	(revision 55766)
@@ -1,3 +1,23 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Thu Jul 28 19:53:21 2016  Koichi Sasada  <ko1@a...>
+
+	* 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.
+
 Thu Jul 28 15:05:12 2016  Nobuyoshi Nakada  <nobu@r...>
 
 	* include/ruby/ruby.h (ruby_fl_type): use __extension__ to get rid
Index: thread.c
===================================================================
--- thread.c	(revision 55765)
+++ thread.c	(revision 55766)
@@ -587,10 +587,12 @@ thread_start_func_2(rb_thread_t *th, VAL https://github.com/ruby/ruby/blob/trunk/thread.c#L587
 		if (!th->first_func) {
 		    GetProcPtr(th->first_proc, proc);
 		    th->errinfo = Qnil;
-		    th->root_lep = rb_vm_ep_local_ep(proc->block.ep);
+		    th->root_lep = rb_vm_ep_local_ep(vm_proc_ep(th->first_proc));
 		    th->root_svar = Qfalse;
 		    EXEC_EVENT_HOOK(th, RUBY_EVENT_THREAD_BEGIN, th->self, 0, 0, Qundef);
-		    th->value = rb_vm_invoke_proc(th, proc, (int)RARRAY_LEN(args), RARRAY_CONST_PTR(args), 0);
+		    th->value = rb_vm_invoke_proc(th, proc,
+						  (int)RARRAY_LEN(args), RARRAY_CONST_PTR(args),
+						  VM_BLOCK_HANDLER_NONE);
 		    EXEC_EVENT_HOOK(th, RUBY_EVENT_THREAD_END, th->self, 0, 0, Qundef);
 		}
 		else {
Index: gc.c
===================================================================
--- gc.c	(revision 55765)
+++ gc.c	(revision 55766)
@@ -9158,19 +9158,6 @@ rb_raw_iseq_info(char *buff, const int b https://github.com/ruby/ruby/blob/trunk/gc.c#L9158
     }
 }
 
-static const rb_iseq_t *
-vm_proc_iseq(VALUE procval)
-{
-    rb_proc_t *proc = RTYPEDDATA_DATA(procval);
-
-    if (RUBY_VM_NORMAL_ISEQ_P(proc->block.iseq)) {
-	return proc->block.iseq;
-    }
-    else {
-	return NULL;
-    }
-}
-
 const char *
 rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
 {
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 55765)
+++ vm_core.h	(revision 55766)
@@ -47,8 +47,12 @@ https://github.com/ruby/ruby/blob/trunk/vm_core.h#L47
 #if VM_CHECK_MODE > 0
 #define VM_ASSERT(expr) ( \
 	RUBY_ASSERT_WHEN(VM_CHECK_MODE > 0, expr))
+
+#define VM_UNREACHABLE(func) rb_bug(#func ": unreachable")
+
 #else
 #define VM_ASSERT(expr) ((void)0)
+#define VM_UNREACHABLE(func) ((void)0)
 #endif
 
 #define RUBY_VM_THREAD_MODEL 2
@@ -225,7 +229,7 @@ struct rb_call_info_with_kwarg { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L229
 };
 
 struct rb_calling_info {
-    struct rb_block_struct *blockptr;
+    VALUE block_handler;
     VALUE recv;
     int argc;
 };
@@ -278,10 +282,6 @@ struct rb_iseq_constant_body { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L282
 	ISEQ_TYPE_DEFINED_GUARD
     } type;              /* instruction sequence type */
 
-    unsigned int stack_max; /* for stack overflow check */
-    /* sizeof(vars) + 1 */
-    unsigned int local_size;
-
     unsigned int iseq_size;
     const VALUE *iseq_encoded; /* encoded iseq (insn addr and operands) */
 
@@ -384,6 +384,7 @@ struct rb_iseq_constant_body { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L384
     unsigned int ci_size;
     unsigned int ci_kw_size;
     unsigned int line_info_size;
+    unsigned int stack_max; /* for stack overflow check */
 };
 
 /* T_IMEMO/iseq */
@@ -593,28 +594,52 @@ typedef struct rb_vm_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L594
 #define VM_DEBUG_VERIFY_METHOD_CACHE (VM_DEBUG_MODE != 0)
 #endif
 
+struct rb_captured_block {
+    VALUE self;
+    const VALUE *ep;
+    union {
+	const rb_iseq_t *iseq;
+	const struct vm_ifunc *ifunc;
+	VALUE val;
+    } code;
+};
+
+enum rb_block_handler_type {
+    block_handler_type_iseq,
+    block_handler_type_ifunc,
+    block_handler_type_symbol,
+    block_handler_type_proc
+};
+
+enum rb_block_type {
+    block_type_iseq,
+    block_type_ifunc,
+    block_type_symbol,
+    block_type_proc
+};
+
+struct rb_block {
+    union {
+	struct rb_captured_block captured;
+	VALUE symbol;
+	VALUE proc;
+    } as;
+    enum rb_block_type type;
+};
+
 typedef struct rb_control_frame_struct {
     const VALUE *pc;		/* cfp[0] */
     VALUE *sp;			/* cfp[1] */
     const rb_iseq_t *iseq;	/* cfp[2] */
-    VALUE flag;			/* cfp[3] */
-    VALUE self;			/* cfp[4] / block[0] */
-    VALUE *ep;			/* cfp[5] / block[1] */
-    const rb_iseq_t *block_iseq;/* cfp[6] / block[2] */
-    VALUE proc;			/* cfp[7] / block[3] */
+    VALUE self;			/* cfp[3] / block[0] */
+    const VALUE *ep;		/* cfp[4] / block[1] */
+    const void *block_code;     /* cfp[5] / block[2] */ /* iseq or ifunc */
 
 #if VM_DEBUG_BP_CHECK
-    VALUE *bp_check;		/* cfp[8] */
+    VALUE *bp_check;		/* cfp[6] */
 #endif
 } rb_control_frame_t;
 
-typedef struct rb_block_struct {
-    VALUE self;			/* share with method frame if it's only block */
-    VALUE *ep;			/* share with method frame if it's only block */
-    const rb_iseq_t *iseq;
-    VALUE proc;
-} rb_block_t;
-
 extern const rb_data_type_t ruby_threadptr_data_type;
 
 #define GetThreadPtr(obj, ptr) \
@@ -690,7 +715,7 @@ typedef struct rb_thread_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L715
     int waiting_fd;
 
     /* for rb_iterate */
-    const rb_block_t *passed_block;
+    VALUE passed_block_handler;
 
     /* for bmethod */
     const rb_callable_method_entry_t *passed_bmethod_me;
@@ -703,7 +728,7 @@ typedef struct rb_thread_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L728
     VALUE top_wrapper;
 
     /* eval env */
-    VALUE *root_lep;
+    const VALUE *root_lep;
     VALUE root_svar;
 
     /* thread control */
@@ -822,8 +847,8 @@ rb_iseq_t *rb_iseq_new_with_opt(NODE*, V https://github.com/ruby/ruby/blob/trunk/vm_core.h#L847
 
 /* src -> iseq */
 rb_iseq_t *rb_iseq_compile(VALUE src, VALUE file, VALUE line);
-rb_iseq_t *rb_iseq_compile_on_base(VALUE src, VALUE file, VALUE line, rb_block_t *base_block);
-rb_iseq_t *rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE absolute_path, VALUE line, rb_block_t *base_block, VALUE opt);
+rb_iseq_t *rb_iseq_compile_on_base(VALUE src, VALUE file, VALUE line, const struct rb_block *base_block);
+rb_iseq_t *rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE absolute_path, VALUE line, const struct rb_block *base_block, VALUE opt);
 
 VALUE rb_iseq_disasm(const rb_iseq_t *iseq);
 int rb_iseq_disasm_insn(VALUE str, const VALUE *iseqval, size_t pos, const rb_iseq_t *iseq, VALUE child);
@@ -841,7 +866,7 @@ RUBY_SYMBOL_EXPORT_END https://github.com/ruby/ruby/blob/trunk/vm_core.h#L866
   GetCoreDataFromValue((obj), rb_proc_t, (ptr))
 
 typedef struct {
-    rb_block_t block;
+    const struct rb_block block;
     int8_t safe_level;		/* 0..1 */
     int8_t is_from_method;	/* bool */
     int8_t is_lambda;		/* bool */
@@ -852,8 +877,9 @@ typedef struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L877
 
 typedef struct {
     int env_size;
-    rb_block_t block;
-    VALUE env[1];               /* flexible array */
+    const VALUE *ep;
+    const rb_iseq_t *iseq;
+    const VALUE env[1];               /* flexible array */
 } rb_env_t;
 
 extern const rb_data_type_t ruby_binding_data_type;
@@ -862,7 +888,7 @@ extern const rb_data_type_t ruby_binding https://github.com/ruby/ruby/blob/trunk/vm_core.h#L888
   GetCoreDataFromValue((obj), rb_binding_t, (ptr))
 
 typedef struct {
-    VALUE env;
+    struct rb_block block;
     VALUE path;
     unsigned short first_lineno;
 } rb_binding_t;
@@ -903,32 +929,6 @@ enum vm_svar_index { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L929
     VM_SVAR_FLIPFLOP_START = 2 /* flipflop */
 };
 
-#define VM_FRAME_MAGIC_METHOD 0x11
-#define VM_FRAME_MAGIC_BLOCK  0x21
-#define VM_FRAME_MAGIC_CLASS  0x31
-#define VM_FRAME_MAGIC_TOP    0x41
-#define VM_FRAME_MAGIC_CFUNC  0x61
-#define VM_FRAME_MAGIC_PROC   0x71
-#define VM_FRAME_MAGIC_IFUNC  0x81
-#define VM_FRAME_MAGIC_EVAL   0x91
-#define VM_FRAME_MAGIC_LAMBDA 0xa1
-#define VM_FRAME_MAGIC_RESCUE 0xb1
-#define VM_FRAME_MAGIC_DUMMY  0xc1
-#define VM_FRAME_MAGIC_MASK_BITS 8
-#define VM_FRAME_MAGIC_MASK   (~(~(VALUE)0<<VM_FRAME_MAGIC_MASK_BITS))
-
-#define VM_FRAME_TYPE(cfp) ((cfp)->flag & VM_FRAME_MAGIC_MASK)
-
-/* other frame flag */
-#define VM_FRAME_FLAG_PASSED  0x0100
-#define VM_FRAME_FLAG_FINISH  0x0200
-#define VM_FRAME_FLAG_BMETHOD 0x0400
-#define VM_FRAME_TYPE_FINISH_P(cfp)  (((cfp)->flag & VM_FRAME_FLAG_FINISH) != 0)
-#define VM_FRAME_TYPE_BMETHOD_P(cfp) (((cfp)->flag & VM_FRAME_FLAG_BMETHOD) != 0)
-
-#define RUBYVM_CFUNC_FRAME_P(cfp) \
-  (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CFUNC)
-
 /* inline cache */
 typedef struct iseq_inline_cache_entry *IC;
 typedef struct rb_call_info *CALL_INFO;
@@ -945,31 +945,180 @@ typedef VALUE CDHASH; https://github.com/ruby/ruby/blob/trunk/vm_core.h#L945
 typedef rb_control_frame_t *
   (FUNC_FASTCALL(*rb_insn_func_t))(rb_thread_t *, rb_control_frame_t *);
 
-#define GC_GUARDED_PTR(p)     ((VALUE)((VALUE)(p) | 0x01))
-#define GC_GUARDED_PTR_REF(p) ((void *)(((VALUE)(p)) & ~0x03))
+#define VM_TAGGED_PTR_SET(p, tag)  ((VALUE)(p) | (tag))
+#define VM_TAGGED_PTR_REF(v, mask) ((void *)((v) & ~mask))
+
+#define GC_GUARDED_PTR(p)     VM_TAGGED_PTR_SET((p), 0x01)
+#define GC_GUARDED_PTR_REF(p) VM_TAGGED_PTR_REF((p), 0x03)
 #define GC_GUARDED_PTR_P(p)   (((VALUE)(p)) & 0x01)
 
-/*
- * block frame:
- *  ep[ 0]: prev frame
- *  ep[-1]: CREF (for *_eval)
- *
- * method frame:
- *  ep[ 0]: block pointer (ptr | VM_ENVVAL_BLOCK_PTR_FLAG)
- */
+enum {
+    /* Frame/Environment flag bits:
+     *   MMMM MMMM MMMM MMMM ____ ____ FFFF EEEX (LSB)
+     *
+     * X   : tag for GC marking (It seems as Fixnum)
+     * EEE : 3 bits Env flags
+     * FFFF: 4 bits Frame flags
+     * MMMM: 16 bits frame magic (to check frame corruption)
+     */
+
+    /* frame types */
+    VM_FRAME_MAGIC_METHOD = 0x11110001,
+    VM_FRAME_MAGIC_BLOCK  = 0x22220001,
+    VM_FRAME_MAGIC_CLASS  = 0x33330001,
+    VM_FRAME_MAGIC_TOP    = 0x44440001,
+    VM_FRAME_MAGIC_CFUNC  = 0x55550001,
+    VM_FRAME_MAGIC_PROC   = 0x66660001,
+    VM_FRAME_MAGIC_IFUNC  = 0x77770001,
+    VM_FRAME_MAGIC_EVAL   = 0x88880001,
+    VM_FRAME_MAGIC_LAMBDA = 0x99990001,
+    VM_FRAME_MAGIC_RESCUE = 0xaaaa0001,
+    VM_FRAME_MAGIC_DUMMY  = 0xbbbb0001,
+
+    VM_FRAME_MAGIC_MASK   = 0xffff0001,
+
+    /* frame flag */
+    VM_FRAME_FLAG_PASSED    = 0x0010,
+    VM_FRAME_FLAG_FINISH    = 0x0020,
+    VM_FRAME_FLAG_BMETHOD   = 0x0040,
+
+    /* env flag */
+    VM_ENV_FLAG_LOCAL       = 0x0002,
+    VM_ENV_FLAG_ESCAPED     = 0x0004,
+    VM_ENV_FLAG_WB_REQUIRED = 0x0008
+};
+
+static inline void VM_FORCE_WRITE_SPECIAL_CONST(const VALUE *ptr, VALUE special_const_value);
+
+#define VM_FRAME_TYPE_FINISH_P(cfp)  (VM_ENV_FLAGS((cfp)->ep, VM_FRAME_FLAG_FINISH ) != 0)
+#define VM_FRAME_TYPE_BMETHOD_P(cfp) (VM_ENV_FLAGS((cfp)->ep, VM_FRAME_FLAG_BMETHOD) != 0)
+
+#define VM_ENV_DATA_SIZE             ( 3)
+
+#define VM_ENV_DATA_INDEX_ME_CREF    (-2) /* ep[-2] */
+#define VM_ENV_DATA_INDEX_SPECVAL    (-1) /* ep[-1] */
+#define VM_ENV_DATA_INDEX_FLAGS      ( 0) /* ep[ 0] */
+#define VM_ENV_DATA_INDEX_ENV        ( 1) /* ep[ 1] */
+#define VM_ENV_DATA_INDEX_ENV_PROC   ( 2) /* ep[ 2] */
+
+#define VM_ENV_INDEX_LAST_LVAR              (-VM_ENV_DATA_SIZE)
+
+static inline void
+VM_ENV_FLAGS_SET(const VALUE *ep, VALUE flag)
+{
+    VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
+    VM_ASSERT(FIXNUM_P(flags));
+    VM_FORCE_WRITE_SPECIAL_CONST(&ep[VM_ENV_DATA_INDEX_FLAGS], flags | flag);
+}
+
+static inline void
+VM_ENV_FLAGS_UNSET(const VALUE *ep, VALUE flag)
+{
+    VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
+    VM_ASSERT(FIXNUM_P(flags));
+    VM_FORCE_WRITE_SPECIAL_CONST(&ep[VM_ENV_DATA_INDEX_FLAGS], flags & ~flag);
+}
+
+static inline long
+VM_ENV_FLAGS(const VALUE *ep, long flag)
+{
+    VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
+    VM_ASSERT(FIXNUM_P(flags));
+    return flags & flag;
+}
+
+static inline long
+VM_FRAME_TYPE(const rb_control_frame_t *cfp)
+{
+    return VM_ENV_FLAGS(cfp->ep, VM_FRAME_MAGIC_MASK);
+}
+
+#define RUBYVM_CFUNC_FRAME_P(cfp) \
+  (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CFUNC)
 
-#define VM_ENVVAL_BLOCK_PTR_FLAG 0x02
-#define VM_ENVVAL_BLOCK_PTR(v)     (GC_GUARDED_PTR(v) | VM_ENVVAL_BLOCK_PTR_FLAG)
-#define VM_ENVVAL_BLOCK_PTR_P(v)   ((v) & VM_ENVVAL_BLOCK_PTR_FLAG)
-#define VM_ENVVAL_PREV_EP_PTR(v)   ((VALUE)GC_GUARDED_PTR(v))
-#define VM_ENVVAL_PREV_EP_PTR_P(v) (!(VM_ENVVAL_BLOCK_PTR_P(v)))
-
-#define VM_EP_PREV_EP(ep)   ((VALUE *)GC_GUARDED_PTR_REF((ep)[0]))
-#define VM_EP_BLOCK_PTR(ep) ((rb_block_t *)GC_GUARDED_PTR_REF((ep)[0]))
-#define VM_EP_LEP_P(ep)     VM_ENVVAL_BLOCK_PTR_P((ep)[0])
+#define VM_GUARDED_PREV_EP(ep)         GC_GUARDED_PTR(ep)
+#define VM_BLOCK_HANDLER_NONE 0
 
-VALUE *rb_vm_ep_local_ep(VALUE *ep);
-rb_block_t *rb_vm_control_frame_block_ptr(const rb_control_frame_t *cfp);
+static inline int
+VM_ENV_LOCAL_P(const VALUE *ep)
+{
+    return VM_ENV_FLAGS(ep, VM_ENV_FLAG_LOCAL) ? 1 : 0;
+}
+
+static inline const VALUE *
+VM_ENV_PREV_EP(const VALUE *e (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]