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

ruby-changes:6394

From: nobu <ko1@a...>
Date: Mon, 7 Jul 2008 00:01:02 +0900 (JST)
Subject: [ruby-changes:6394] Ruby:r17909 (mvm): * include/ruby/public_object.h: moved global variables to VM specific data.

nobu	2008-07-07 00:00:24 +0900 (Mon, 07 Jul 2008)

  New Revision: 17909

  Modified files:
    branches/mvm/ChangeLog
    branches/mvm/array.c
    branches/mvm/bignum.c
    branches/mvm/class.c
    branches/mvm/common.mk
    branches/mvm/compar.c
    branches/mvm/complex.c
    branches/mvm/configure.in
    branches/mvm/cont.c
    branches/mvm/debug.c
    branches/mvm/dir.c
    branches/mvm/dln.c
    branches/mvm/encoding.c
    branches/mvm/enum.c
    branches/mvm/enumerator.c
    branches/mvm/error.c
    branches/mvm/eval.c
    branches/mvm/eval_jump.c
    branches/mvm/file.c
    branches/mvm/gc.c
    branches/mvm/hash.c
    branches/mvm/include/ruby/encoding.h
    branches/mvm/include/ruby/intern.h
    branches/mvm/include/ruby/mvm.h
    branches/mvm/include/ruby/ruby.h
    branches/mvm/io.c
    branches/mvm/iseq.c
    branches/mvm/marshal.c
    branches/mvm/math.c
    branches/mvm/numeric.c
    branches/mvm/object.c
    branches/mvm/prec.c
    branches/mvm/proc.c
    branches/mvm/process.c
    branches/mvm/range.c
    branches/mvm/rational.c
    branches/mvm/re.c
    branches/mvm/ruby.c
    branches/mvm/string.c
    branches/mvm/struct.c
    branches/mvm/thread.c
    branches/mvm/thread_pthread.c
    branches/mvm/thread_pthread.h
    branches/mvm/thread_win32.c
    branches/mvm/thread_win32.h
    branches/mvm/time.c
    branches/mvm/variable.c
    branches/mvm/vm.c
    branches/mvm/vm.h
    branches/mvm/vm_core.h
    branches/mvm/win32/Makefile.sub

  Log:
    * include/ruby/public_object.h: moved global variables to VM specific data.


  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=17909

Index: mvm/complex.c
===================================================================
--- mvm/complex.c	(revision 17908)
+++ mvm/complex.c	(revision 17909)
@@ -19,8 +19,6 @@
 #define ONE INT2FIX(1)
 #define TWO INT2FIX(2)
 
-VALUE rb_cComplex;
-
 static ID id_Unify, id_abs, id_abs2, id_arg, id_atan2_bang, id_cmp,
   id_conjugate, id_convert, id_cos, id_denominator, id_divmod,
   id_equal_p, id_exact_p, id_exp_bang, id_expt, id_floor, id_format,
Index: mvm/array.c
===================================================================
--- mvm/array.c	(revision 17908)
+++ mvm/array.c	(revision 17909)
@@ -15,8 +15,6 @@
 #include "ruby/util.h"
 #include "ruby/st.h"
 
-VALUE rb_cArray;
-
 static ID id_cmp;
 
 #define ARY_DEFAULT_SIZE 16
Index: mvm/debug.c
===================================================================
--- mvm/debug.c	(revision 17908)
+++ mvm/debug.c	(revision 17909)
@@ -22,6 +22,8 @@
     enum ruby_value_type        value_type;
     enum ruby_tag_type          tag_type;
     enum node_type              node_type;
+    enum ruby_public_object_vmkey public_vmkey;
+    enum ruby_private_object_vmkey private_vmkey;
     enum {
         RUBY_ENCODING_INLINE_MAX = ENCODING_INLINE_MAX,
         RUBY_ENCODING_SHIFT = ENCODING_SHIFT,
@@ -65,7 +67,7 @@
         RUBY_NODE_LMASK     = NODE_LMASK,
         RUBY_NODE_FL_NEWLINE   = NODE_FL_NEWLINE
     } various;
-} dummy_gdb_enums;
+} dummy_gdb_enums = {0};
 
 const VALUE RUBY_FL_USER20    = FL_USER20;
 
Index: mvm/encoding.c
===================================================================
--- mvm/encoding.c	(revision 17908)
+++ mvm/encoding.c	(revision 17909)
@@ -12,14 +12,13 @@
 #include "ruby/ruby.h"
 #include "ruby/encoding.h"
 #include "regenc.h"
+#include "private_object.h"
 #include <ctype.h>
 #ifdef HAVE_LANGINFO_H
 #include <langinfo.h>
 #endif
 
 static ID id_encoding, id_base_encoding;
-VALUE rb_cEncoding;
-static VALUE rb_encoding_list;
 
 struct rb_encoding_entry {
     const char *name;
@@ -1196,7 +1195,6 @@
     rb_define_singleton_method(rb_cEncoding, "default_external", get_default_external, 0);
     rb_define_singleton_method(rb_cEncoding, "locale_charmap", rb_locale_charmap, 0);
 
-    rb_gc_register_address(&rb_encoding_list);
     list = rb_ary_new2(enc_table.count);
     RBASIC(list)->klass = 0;
     rb_encoding_list = list;
Index: mvm/thread_win32.c
===================================================================
--- mvm/thread_win32.c	(revision 17908)
+++ mvm/thread_win32.c	(revision 17909)
@@ -32,13 +32,13 @@
 static void native_cond_initialize(rb_thread_cond_t *cond);
 static void native_cond_destroy(rb_thread_cond_t *cond);
 
-static rb_thread_t *
+rb_thread_t *
 ruby_thread_from_native(void)
 {
     return TlsGetValue(ruby_native_thread_key);
 }
 
-static int
+int
 ruby_thread_set_native(rb_thread_t *th)
 {
     return TlsSetValue(ruby_native_thread_key, th);
@@ -290,6 +290,12 @@
 #endif
 }
 
+int
+ruby_native_thread_lock(rb_thread_lock_t *lock)
+{
+    return native_mutex_lock(lock);
+}
+
 static int
 native_mutex_unlock(rb_thread_lock_t *lock)
 {
@@ -302,6 +308,12 @@
 #endif
 }
 
+int
+ruby_native_thread_unlock(rb_thread_lock_t *lock)
+{
+    return native_mutex_unlock(lock);
+}
+
 static int
 native_mutex_trylock(rb_thread_lock_t *lock)
 {
Index: mvm/math.c
===================================================================
--- mvm/math.c	(revision 17908)
+++ mvm/math.c	(revision 17909)
@@ -13,8 +13,6 @@
 #include <math.h>
 #include <errno.h>
 
-VALUE rb_mMath;
-
 static VALUE
 to_flo(VALUE x)
 {
Index: mvm/time.c
===================================================================
--- mvm/time.c	(revision 17908)
+++ mvm/time.c	(revision 17909)
@@ -21,7 +21,6 @@
 
 #include <math.h>
 
-VALUE rb_cTime;
 static VALUE time_utc_offset _((VALUE));
 
 static ID id_divmod, id_mul, id_submicro;
Index: mvm/thread_win32.h
===================================================================
--- mvm/thread_win32.h	(revision 17908)
+++ mvm/thread_win32.h	(revision 17909)
@@ -24,10 +24,14 @@
 typedef HANDLE rb_thread_id_t;
 typedef CRITICAL_SECTION rb_thread_lock_t;
 typedef struct rb_thread_cond_struct rb_thread_cond_t;
+#define RB_THREAD_LOCK_INITIALIZER {}
 
 typedef struct native_thread_data_struct {
     HANDLE interrupt_event;
 } native_thread_data_t;
 
+int ruby_native_thread_lock(rb_thread_lock_t*);
+int ruby_native_thread_unlock(rb_thread_lock_t*);
+
 #endif /* RUBY_THREAD_WIN32_H */
 
Index: mvm/include/ruby/intern.h
===================================================================
--- mvm/include/ruby/intern.h	(revision 17908)
+++ mvm/include/ruby/intern.h	(revision 17909)
@@ -282,8 +282,6 @@
 int rb_obj_method_arity(VALUE, ID);
 VALUE rb_protect(VALUE (*)(VALUE), VALUE, int*);
 void rb_set_end_proc(void (*)(VALUE), VALUE);
-void rb_mark_end_proc(void);
-void rb_exec_end_proc(void);
 void Init_jump(void);
 void ruby_finalize(void);
 NORETURN(void ruby_stop(int));
@@ -640,7 +638,6 @@
 void rb_autoload(VALUE, ID, const char*);
 VALUE rb_autoload_load(VALUE, ID);
 VALUE rb_autoload_p(VALUE, ID);
-void rb_gc_mark_global_tbl(void);
 VALUE rb_f_trace_var(int, VALUE*);
 VALUE rb_f_untrace_var(int, VALUE*);
 VALUE rb_f_global_variables(void);
Index: mvm/include/ruby/mvm.h
===================================================================
--- mvm/include/ruby/mvm.h	(revision 17908)
+++ mvm/include/ruby/mvm.h	(revision 17909)
@@ -12,6 +12,8 @@
 #ifndef RUBY_MVM_H
 #define RUBY_MVM_H 1
 
+#define HAVE_MVM 1
+
 typedef struct rb_vm_struct rb_vm_t;
 typedef struct rb_thread_struct rb_thread_t;
 
@@ -32,4 +34,9 @@
 rb_vm_t *ruby_vm_new(void);
 int ruby_vm_run(rb_vm_t *, VALUE);
 
+int rb_vm_key_count(void);
+int rb_vm_key_create(void);
+VALUE *ruby_vm_specific_ptr(rb_vm_t *, int);
+VALUE *rb_vm_specific_ptr(int);
+
 #endif /* RUBY_MVM_H */
Index: mvm/include/ruby/ruby.h
===================================================================
--- mvm/include/ruby/ruby.h	(revision 17908)
+++ mvm/include/ruby/ruby.h	(revision 17909)
@@ -742,6 +742,7 @@
 void rb_define_variable(const char*,VALUE*);
 void rb_define_virtual_variable(const char*,VALUE(*)(ANYARGS),void(*)(ANYARGS));
 void rb_define_hooked_variable(const char*,VALUE*,VALUE(*)(ANYARGS),void(*)(ANYARGS));
+void rb_define_vm_specific_variable(const char*,int,VALUE(*)(ANYARGS),void(*)(ANYARGS));
 void rb_define_readonly_variable(const char*,VALUE*);
 void rb_define_const(VALUE,const char*,VALUE);
 void rb_define_global_const(const char*,VALUE);
@@ -861,87 +862,8 @@
 void *ruby_options(int, char**);
 int ruby_run_node(void *);
 
-RUBY_EXTERN VALUE rb_mKernel;
-RUBY_EXTERN VALUE rb_mComparable;
-RUBY_EXTERN VALUE rb_mEnumerable;
-RUBY_EXTERN VALUE rb_mPrecision;
-RUBY_EXTERN VALUE rb_mErrno;
-RUBY_EXTERN VALUE rb_mFileTest;
-RUBY_EXTERN VALUE rb_mGC;
-RUBY_EXTERN VALUE rb_mMath;
-RUBY_EXTERN VALUE rb_mProcess;
+#include "ruby/public_object.h"
 
-RUBY_EXTERN VALUE rb_cBasicObject;
-RUBY_EXTERN VALUE rb_cObject;
-RUBY_EXTERN VALUE rb_cArray;
-RUBY_EXTERN VALUE rb_cBignum;
-RUBY_EXTERN VALUE rb_cBinding;
-RUBY_EXTERN VALUE rb_cClass;
-RUBY_EXTERN VALUE rb_cCont;
-RUBY_EXTERN VALUE rb_cDir;
-RUBY_EXTERN VALUE rb_cData;
-RUBY_EXTERN VALUE rb_cFalseClass;
-RUBY_EXTERN VALUE rb_cEnumerator;
-RUBY_EXTERN VALUE rb_cFile;
-RUBY_EXTERN VALUE rb_cFixnum;
-RUBY_EXTERN VALUE rb_cFloat;
-RUBY_EXTERN VALUE rb_cHash;
-RUBY_EXTERN VALUE rb_cInteger;
-RUBY_EXTERN VALUE rb_cIO;
-RUBY_EXTERN VALUE rb_cMatch;
-RUBY_EXTERN VALUE rb_cMethod;
-RUBY_EXTERN VALUE rb_cModule;
-RUBY_EXTERN VALUE rb_cNameErrorMesg;
-RUBY_EXTERN VALUE rb_cNilClass;
-RUBY_EXTERN VALUE rb_cNumeric;
-RUBY_EXTERN VALUE rb_cProc;
-RUBY_EXTERN VALUE rb_cRange;
-RUBY_EXTERN VALUE rb_cRational;
-RUBY_EXTERN VALUE rb_cComplex;
-RUBY_EXTERN VALUE rb_cRegexp;
-RUBY_EXTERN VALUE rb_cStat;
-RUBY_EXTERN VALUE rb_cString;
-RUBY_EXTERN VALUE rb_cStruct;
-RUBY_EXTERN VALUE rb_cSymbol;
-RUBY_EXTERN VALUE rb_cThread;
-RUBY_EXTERN VALUE rb_cTime;
-RUBY_EXTERN VALUE rb_cTrueClass;
-RUBY_EXTERN VALUE rb_cUnboundMethod;
-
-RUBY_EXTERN VALUE rb_eException;
-RUBY_EXTERN VALUE rb_eStandardError;
-RUBY_EXTERN VALUE rb_eSystemExit;
-RUBY_EXTERN VALUE rb_eInterrupt;
-RUBY_EXTERN VALUE rb_eSignal;
-RUBY_EXTERN VALUE rb_eFatal;
-RUBY_EXTERN VALUE rb_eArgError;
-RUBY_EXTERN VALUE rb_eEOFError;
-RUBY_EXTERN VALUE rb_eIndexError;
-RUBY_EXTERN VALUE rb_eStopIteration;
-RUBY_EXTERN VALUE rb_eKeyError;
-RUBY_EXTERN VALUE rb_eRangeError;
-RUBY_EXTERN VALUE rb_eIOError;
-RUBY_EXTERN VALUE rb_eRuntimeError;
-RUBY_EXTERN VALUE rb_eSecurityError;
-RUBY_EXTERN VALUE rb_eSystemCallError;
-RUBY_EXTERN VALUE rb_eThreadError;
-RUBY_EXTERN VALUE rb_eTypeError;
-RUBY_EXTERN VALUE rb_eZeroDivError;
-RUBY_EXTERN VALUE rb_eNotImpError;
-RUBY_EXTERN VALUE rb_eNoMemError;
-RUBY_EXTERN VALUE rb_eNoMethodError;
-RUBY_EXTERN VALUE rb_eFloatDomainError;
-RUBY_EXTERN VALUE rb_eLocalJumpError;
-RUBY_EXTERN VALUE rb_eSysStackError;
-RUBY_EXTERN VALUE rb_eRegexpError;
-
-RUBY_EXTERN VALUE rb_eScriptError;
-RUBY_EXTERN VALUE rb_eNameError;
-RUBY_EXTERN VALUE rb_eSyntaxError;
-RUBY_EXTERN VALUE rb_eLoadError;
-
-RUBY_EXTERN VALUE rb_stdin, rb_stdout, rb_stderr;
-
 static inline VALUE
 rb_class_of(VALUE obj)
 {
Index: mvm/include/ruby/encoding.h
===================================================================
--- mvm/include/ruby/encoding.h	(revision 17908)
+++ mvm/include/ruby/encoding.h	(revision 17909)
@@ -175,7 +175,6 @@
 VALUE rb_locale_charmap(VALUE klass);
 long rb_memsearch(const void*,long,const void*,long,rb_encoding*);
 
-RUBY_EXTERN VALUE rb_cEncoding;
 #define enc_initialized_p(enc) ((enc)->ruby_encoding_index != ENC_UNINITIALIZED)
 #define ENC_DUMMY_FLAG (1<<24)
 #define ENC_INDEX_MASK (~(~0U<<24))
Index: mvm/configure.in
===================================================================
--- mvm/configure.in	(revision 17908)
+++ mvm/configure.in	(revision 17909)
@@ -1130,6 +1130,18 @@
 	AC_CHECK_FUNCS(getcontext setcontext)
     fi
 fi
+AC_CACHE_CHECK([for thread specific data], rb_cv_thread_specific,
+[rb_cv_thread_specific=no
+for th in "__declspec(thread)" __thread; do
+    AC_TRY_COMPILE(AC_INCLUDES_DEFAULT[
+@%:@ifdef HAVE_PTHREAD_H
+@%:@include <pthread.h>
+@%:@endif
+extern $th int foo_th_extern; static $th int foo_th_static;],
+	[if (foo_th_extern) return foo_th_static;],
+	[rb_cv_thread_specific="$th"; break])
+done])
+test "$rb_cv_thread_specific" = "" || AC_DEFINE_UNQUOTED(THREAD_SPECIFIC, $rb_cv_thread_specific)
 
 if test "$ac_cv_func_fork" = "yes" -a "$rb_with_pthread" = "yes"; then
     AC_CACHE_CHECK([if fork works with pthread], rb_cv_fork_with_pthread,
Index: mvm/re.c
===================================================================
--- mvm/re.c	(revision 17908)
+++ mvm/re.c	(revision 17909)
@@ -16,8 +16,6 @@
 #include "regint.h"
 #include <ctype.h>
 
-VALUE rb_eRegexpError;
-
 typedef char onig_errmsg_buffer[ONIG_MAX_ERROR_MESSAGE_LEN];
 
 #define BEG(no) regs->beg[no]
@@ -767,8 +765,6 @@
  *
  */
 
-VALUE rb_cMatch;
-
 static VALUE
 match_alloc(VALUE klass)
 {
@@ -1823,8 +1819,6 @@
     return str;
 }
 
-VALUE rb_cRegexp;
-
 static int
 read_escaped_byte(const char **pp, const char *end, onig_errmsg_buffer err)
 {
Index: mvm/ChangeLog
===================================================================
--- mvm/ChangeLog	(revision 17908)
+++ mvm/ChangeLog	(revision 17909)
@@ -1,3 +1,7 @@
+Mon Jul  7 00:00:21 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* include/ruby/public_object.h: moved global variables to VM specific data.
+
 Sun Jul  6 23:48:06 2008  Nobuyoshi Nakada  <nobu@r...>
 
 	* ext/socket/socket.c (bsock_send, s_recvfrom, ruby_connect, s_accept),
Index: mvm/thread_pthread.c
===================================================================
--- mvm/thread_pthread.c	(revision 17908)
+++ mvm/thread_pthread.c	(revision 17909)
@@ -135,7 +135,7 @@
 #endif
 static void remove_signal_thread_list(rb_thread_t *th);
 
-static rb_thread_lock_t signal_thread_list_lock;
+static rb_thread_lock_t signal_thread_list_lock = RB_THREAD_LOCK_INITIALIZER;;
 
 static pthread_key_t ruby_native_thread_key;
 
@@ -145,29 +145,44 @@
     /* null */
 }
 
-static rb_thread_t *
+rb_thread_t *
 ruby_thread_from_native(void)
 {
+#ifdef THREAD_SPECIFIC
+    return ruby_current_thread;
+#else
     return pthread_getspecific(ruby_native_thread_key);
+#endif
 }
 
-static int
+int
 ruby_thread_set_native(rb_thread_t *th)
 {
+#ifdef THREAD_SPECIFIC
+    ruby_current_thread = th;
+    return 1;
+#else
     return pthread_setspecific(ruby_native_thread_key, th) == 0;
+#endif
 }
 
 static void
+init_once_native_thread(void)
+{
+    pthread_key_create(&ruby_native_thread_key, NULL);
+    posix_signal(SIGVTALRM, null_func);
+}
+
+static void
 Init_native_thread(void)
 {
     rb_thread_t *th = GET_THREAD();
+    static pthread_once_t init_for_all_thread = PTHREAD_ONCE_INIT;
 
-    pthread_key_create(&ruby_native_thread_key, NULL);
+    pthread_once(&init_for_all_thread, init_once_native_thread);
     th->thread_id = pthread_self();
     native_cond_initialize(&th->native_thread_data.sleep_cond);
     ruby_thread_set_native(th);
-    native_mutex_initialize(&signal_thread_list_lock);
-    posix_signal(SIGVTALRM, null_func);
 }
 
 static void
Index: mvm/enumerator.c
===================================================================
--- mvm/enumerator.c	(revision 17908)
+++ mvm/enumerator.c	(revision 17909)
@@ -21,11 +21,8 @@
  * A class which provides a method `each' to be used as an Enumerable
  * object.
  */
-VALUE rb_cEnumerator;
 static VALUE sym_each;
 
-VALUE rb_eStopIteration;
-
 struct enumerator {
     VALUE obj;
     ID    meth;
Index: mvm/thread_pthread.h
===================================================================
--- mvm/thread_pthread.h	(revision 17908)
+++ mvm/thread_pthread.h	(revision 17909)
@@ -15,10 +15,14 @@
 typedef pthread_t rb_thread_id_t;
 typedef pthread_mutex_t rb_thread_lock_t;
 typedef pthread_cond_t rb_thread_cond_t;
+#define RB_THREAD_LOCK_INITIALIZER PTHREAD_MUTEX_INITIALIZER
 
 typedef struct native_thread_data_struct {
     void *signal_thread_list;
     pthread_cond_t sleep_cond;
 } native_thread_data_t;
 
+#define ruby_native_thread_lock(lock) pthread_mutex_lock(lock)
+#define ruby_native_thread_unlock(lock) pthread_mutex_unlock(lock)
+
 #endif /* RUBY_THREAD_PTHREAD_H */
Index: mvm/variable.c
===================================================================
--- mvm/variable.c	(revision 17908)
+++ mvm/variable.c	(revision 17909)
@@ -15,20 +15,22 @@
 #include "ruby/node.h"
 #include "ruby/st.h"
 #include "ruby/util.h"
+#include "vm_core.h"
 
 void rb_vm_change_state(void);
-st_table *rb_global_tbl;
-st_table *rb_class_tbl;
-static ID autoload, classpath, tmp_classpath;
+#define rb_global_tbl GET_VM()->global_tbl
+static ID autoload, classpath, tmp_classpath, id_const_missing;
 
 void
 Init_var_tables(void)
 {
-    rb_global_tbl = st_init_numtable();
-    rb_class_tbl = st_init_numtable();
+    rb_vm_t *vm = GET_VM();
+    vm->mark_object_ary = rb_ary_new();
+    vm->global_tbl = st_init_numtable();
     CONST_ID(autoload, "__autoload__");
     CONST_ID(classpath, "__classpath__");
     CONST_ID(tmp_classpath, "__tmp_classpath__");
+    CONST_ID(id_const_missing, "const_missing");
 }
 
 struct fc_result {
@@ -120,9 +122,6 @@
     if (RCLASS_IV_TBL(rb_cObject)) {
 	st_foreach_safe(RCLASS_IV_TBL(rb_cObject), fc_i, (st_data_t)&arg);
     }
-    if (arg.path == 0) {
-	st_foreach_safe(rb_class_tbl, fc_i, (st_data_t)&arg);
-    }
     if (arg.path) {
 	if (!RCLASS_IV_TBL(klass)) {
 	    RCLASS_IV_TBL(klass) = st_init_numtable();
@@ -291,8 +290,13 @@
     struct trace_var *next;
 };
 
+enum gvar_flags {
+    gv_vm_specific_storage = 1
+};
+
 struct global_variable {
     int   counter;
+    int flags;
     void *data;
     VALUE (*getter)();
     void  (*setter)();
@@ -301,11 +305,6 @@
     struct trace_var *trace;
 };
 
-struct global_entry {
-    struct global_variable *var;
-    ID id;
-};
-
 static VALUE undef_getter(ID id);
 static void  undef_setter(VALUE val, ID id, void *data, struct global_variable *var);
 static void  undef_marker(void);
@@ -331,6 +330,7 @@
 	entry->id = id;
 	entry->var = var;
 	var->counter = 1;
+	var->flags = 0;
 	var->data = 0;
 	var->getter = undef_getter;
 	var->setter = undef_setter;
@@ -407,6 +407,12 @@
 }
 
 static void
+vm_marker(void *var)
+{
+    rb_gc_mark(*rb_vm_specific_ptr((int)var));
+}
+
+static void
 readonly_setter(VALUE val, ID id, void *var)
 {
     rb_name_error(id, "%s is a read-only variable", rb_id2name(id));
@@ -428,10 +434,10 @@
 }
 
 void
-rb_gc_mark_global_tbl(void)
+rb_vm_mark_global_tbl(st_table *global_tbl)
 {
-    if (rb_global_tbl)
-        st_foreach_safe(rb_global_tbl, mark_global_entry, 0);
+    if (global_tbl)
+        st_foreach_safe(global_tbl, mark_global_entry, 0);
 }
 
 static ID
@@ -459,16 +465,34 @@
     struct global_variable *gvar;
     ID id;
     VALUE tmp;
-    
-    if (var)
-        tmp = *var;
+    int vmkey = -1;
 
+    if (var) {
+	rb_vm_t *vm = GET_VM();
+	if (vm->specific_storage.ptr &&
+	    vm->specific_storage.ptr <= var &&
+	    var < vm->specific_storage.ptr + vm->specific_storage.len &&
+	    ((char *)var - (char *)vm->specific_storage.ptr) % sizeof(VALUE) == 0) {
+	    vmkey = var - vm->specific_storage.ptr;
+	}
+	else {
+	    tmp = *var;
+	}
+    }
+
     id = global_id(name);
     gvar = rb_global_entry(id)->var;
-    gvar->data = (void*)var;
+    if (vmkey != -1) {
+	gvar->flags |= gv_vm_specific_storage;
+	gvar->data = (void*)vmkey;
+	gvar->marker = vm_marker;
+    }
+    else {
+	gvar->data = (void*)var;
+	gvar->marker = var_marker;
+    }
     gvar->getter = getter?getter:var_getter;
     gvar->setter = setter?setter:var_setter;
-    gvar->marker = var_marker;
 
     RB_GC_GUARD(tmp);
 }
@@ -496,6 +520,30 @@
     rb_define_hooked_variable(name, 0, getter, setter);
 }
 
+
+void
+rb_define_vm_specific_variable(
+    const char *name,
+    int vmkey,
+    VALUE (*getter)(ANYARGS),
+    void  (*setter)(ANYARGS))
+{
+    struct global_variable *gvar;
+    ID id;
+
+    if (!getter) getter = var_getter;
+    if (!setter) setter = var_setter;
+    else if (setter == (void (*)(ANYARGS))-1) setter = readonly_setter;
+
+    id = global_id(name);
+    gvar = rb_global_entry(id)->var;
+    gvar->flags |= gv_vm_specific_storage;
+    gvar->data = (void*)vmkey;
+    gvar->getter = getter;
+    gvar->setter = setter;
+    gvar->marker = vm_marker;
+}
+
 static void
 rb_trace_eval(VALUE cmd, VALUE val)
 {
@@ -632,7 +680,11 @@
 rb_gvar_get(struct global_entry *entry)
 {
     struct global_variable *var = entry->var;
-    return (*var->getter)(entry->id, var->data, var);
+    void *data = var->data;
+    if (var->flags & gv_vm_specific_storage) {
+	data = (void *)rb_vm_specific_ptr((int)data);
+    }
+    return (*var->getter)(entry->id, data, var);
 }
 
 struct trace_data {
@@ -665,10 +717,14 @@
 {
     struct trace_data trace;
     struct global_variable *var = entry->var;
+    void *data = var->data;
 
     if (rb_safe_level() >= 4)
 	rb_raise(rb_eSecurityError, "Insecure: can't change global variable value");
-    (*var->setter)(val, entry->id, var->data, var);
+    if (var->flags & gv_vm_specific_storage) {
+	data = (void *)rb_vm_specific_ptr((int)data);
+    }
+    (*var->setter)(val, entry->id, data, var);
 
     if (var->trace && !var->block_trace) {
 	var->block_trace = 1;
@@ -773,16 +829,43 @@
     entry1->var = entry2->var;
 }
 
-static int special_generic_ivar = 0;
-static st_table *generic_iv_tbl;
+#define generic_iv_tbl ((st_table *)DATA_PTR(generic_iv))
 
+static int
+generic_iv_mark_entry(st_data_t key, st_data_t val, st_data_t arg)
+{
+    rb_mark_tbl((st_table *)val);
+    return ST_CONTINUE;
+}
+
+static void
+generic_iv_mark(void *ptr)
+{
+    st_foreach(ptr, generic_iv_mark_entry, 0);
+}
+
+static int
+generic_iv_mark_free(st_data_t key, st_data_t val, st_data_t arg)
+{
+    st_free_table((st_table *)val);
+    return ST_DELETE;
+}
+
+static void
+generic_iv_free(void *ptr)
+{
+    st_foreach(ptr, generic_iv_mark_free, 0);
+    st_free_table(ptr);
+}
+
 st_table*
 rb_generic_ivar_table(VALUE obj)
 {
     st_data_t tbl;
+    VALUE generic_iv;
 
     if (!FL_TEST(obj, FL_EXIVAR)) return 0;
-    if (!generic_iv_tbl) return 0;
+    if (!(generic_iv = rb_generic_iv_tbl)) return 0;
     if (!st_lookup(generic_iv_tbl, obj, &tbl)) return 0;
     return (st_table *)tbl;
 }
@@ -792,8 +875,9 @@
 {
     st_data_t tbl;
     VALUE val;
+    VALUE generic_iv = rb_generic_iv_tbl;
 
-    if (generic_iv_tbl) {
+    if (generic_iv) {
 	if (st_lookup(generic_iv_tbl, obj, &tbl)) {
 	    if (st_lookup((st_table *)tbl, id, &val)) {
 		return val;
@@ -811,13 +895,14 @@
 {
     st_table *tbl;
     st_data_t data;
+    VALUE generic_iv;
 
     if (rb_special_const_p(obj)) {
 	if (rb_obj_frozen_p(obj)) rb_error_frozen("object");
-	special_generic_ivar = 1;
     }
-    if (!generic_iv_tbl) {
-	generic_iv_tbl = st_init_numtable();
+    if (!(generic_iv = rb_generic_iv_tbl)) {
+	generic_iv = Data_Wrap_Struct(0, generic_iv_mark, generic_iv_free, st_init_numtable());
+	rb_generic_iv_tbl = generic_iv;
     }
     if (!st_lookup(generic_iv_tbl, obj, &data)) {
 	FL_SET(obj, FL_EXIVAR);
@@ -835,8 +920,9 @@
     st_table *tbl;
     st_data_t data;
     VALUE val;
+    VALUE generic_iv = rb_generic_iv_tbl;
 
-    if (!generic_iv_tbl) return Qfalse;
+    if (!generic_iv) return Qfalse;
     if (!st_lookup(generic_iv_tbl, obj, &data)) return Qfalse;
     tbl = (st_table *)data;
     if (st_lookup(tbl, id, &val)) {
@@ -851,8 +937,9 @@
     st_table *tbl;
     st_data_t data;
     int status;
+    VALUE generic_iv = rb_generic_iv_tbl;
 
-    if (!generic_iv_tbl) return 0;
+    if (!generic_iv) return 0;
     if (!st_lookup(generic_iv_tbl, obj, &data)) return 0;
     tbl = (st_table *)data;
     status = st_delete(tbl, &id, valp);
@@ -867,8 +954,9 @@
 rb_mark_generic_ivar(VALUE obj)
 {
     st_data_t tbl;
+    VALUE generic_iv = rb_generic_iv_tbl;
 
-    if (!generic_iv_tbl) return;
+    if (!generic_iv) return;
     if (st_lookup(generic_iv_tbl, obj, &tbl)) {
 	rb_mark_tbl((st_table *)tbl);
     }
@@ -893,8 +981,10 @@
 void
 rb_mark_generic_ivar_tbl(void)
 {
-    if (!generic_iv_tbl) return;
-    if (special_generic_ivar == 0) return;
+    VALUE generic_iv = rb_generic_iv_tbl;
+
+    if (!generic_iv) return;
+    if (generic_iv_tbl->num_entries == 0) return;
     st_foreach_safe(generic_iv_tbl, givar_i, 0);
 }
 
@@ -902,8 +992,9 @@
 rb_free_generic_ivar(VALUE obj)
 {
     st_data_t tbl;
+    VALUE generic_iv = rb_generic_iv_tbl;
 
-    if (!generic_iv_tbl) return;
+    if (!generic_iv) return;
     if (st_delete(generic_iv_tbl, &obj, &tbl))
 	st_free_table((st_table *)tbl);
 }
@@ -912,8 +1003,9 @@
 rb_copy_generic_ivar(VALUE clone, VALUE obj)
 {
     st_data_t data;
+    VALUE generic_iv = rb_generic_iv_tbl;
 
-    if (!generic_iv_tbl) return;
+    if (!generic_iv) return;
     if (!FL_TEST(obj, FL_EXIVAR)) {
 clear:
         if (FL_TEST(clone, FL_EXIVAR)) {
@@ -1127,6 +1219,8 @@
 
 void rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg)
 {
+    VALUE generic_iv = rb_generic_iv_tbl;
+
     switch (TYPE(obj)) {
       case T_OBJECT:
         obj_ivar_each(obj, func, arg);
@@ -1138,7 +1232,7 @@
 	}
 	break;
       default:
-	if (!generic_iv_tbl) break;
+	if (!generic_iv) break;
 	if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
 	    st_data_t tbl;
 
@@ -1269,7 +1363,7 @@
 static VALUE
 const_missing(VALUE klass, ID id)
 {
-    return rb_funcall(klass, rb_intern("const_missing"), 1, ID2SYM(id));
+    return rb_funcall(klass, id_const_missing, 1, ID2SYM(id));
 }
 
 
Index: mvm/vm_core.h
===================================================================
--- mvm/vm_core.h	(revision 17908)
+++ mvm/vm_core.h	(revision 17909)
@@ -21,6 +21,7 @@
 #include "ruby/signal.h"
 #include "ruby/st.h"
 #include "ruby/node.h"
+#include "private_object.h"
 
 #include "debug.h"
 #include "vm_opts.h"
@@ -282,15 +283,15 @@
     struct iseq_compile_data *compile_data;
 };
 
-enum ruby_special_exceptions {
-    ruby_error_reenter,
-    ruby_error_nomemory,
-    ruby_error_sysstack,
-    ruby_special_error_count
+typedef struct rb_iseq_struct rb_iseq_t;
+
+enum end_proc_type {
+    end_proc_ordinary,
+    end_proc_ephemeral,
+    end_proc_temporary,
+    end_proc_count
 };
 
-typedef struct rb_iseq_struct rb_iseq_t;
-
 #define GetVMPtr(obj, ptr) \
   GetCoreDataFromValue(obj, rb_vm_t, ptr)
 
@@ -302,6 +303,10 @@
 
     rb_thread_lock_t global_vm_lock;
 
+    VALUE global_state_version;
+    VALUE redefined_flag;
+    st_table *opt_method_table;
+
     struct rb_thread_struct *main_thread;
     struct rb_thread_struct *running_thread;
 
@@ -314,17 +319,17 @@
     unsigned long trace_flag;
     volatile int sleeper;
 
-    VALUE argf;
-
     /* object management */
     VALUE mark_object_ary;
 
+    st_table *global_tbl;
+
     struct {
 	VALUE *ptr;
 	long len;
     } specific_storage;
 
-    VALUE special_exceptions[ruby_special_error_count];
+    struct end_proc_data *end_procs[end_proc_count];
 
     /* load */
     VALUE top_self;
@@ -341,9 +346,6 @@
 
     int src_encoding_index;
 
-    VALUE verbose, debug, progname;
-    VALUE coverages;
-
 #ifdef RUBY_DEBUG_ENV
     int enable_coredump;
 #endif
@@ -518,11 +520,6 @@
 VALUE ruby_iseq_disasm_insn(VALUE str, VALUE *iseqval, int pos, rb_iseq_t *iseq, VALUE child);
 const char *ruby_node_name(int node);
 
-RUBY_EXTERN VALUE rb_cISeq;
-RUBY_EXTERN VALUE rb_cRubyVM;
-RUBY_EXTERN VALUE rb_cEnv;
-RUBY_EXTERN VALUE rb_mRubyVMFrozenCore;
-
 /* each thread has this size stack : 128KB */
 #define RUBY_VM_THREAD_STACK_SIZE (128 * 1024)
 
@@ -608,6 +605,7 @@
 typedef NODE *IC;
 
 void rb_vm_change_state(void);
+void rb_vm_mark_global_tbl(st_table *);
 
 typedef VALUE CDHASH;
 
@@ -681,17 +679,27 @@
 
 NOINLINE(void rb_gc_save_machine_context(rb_thread_t *));
 
-#define sysstack_error GET_VM()->special_exceptions[ruby_error_sysstack]
+void rb_mark_end_proc(struct end_proc_data **);
+void rb_exec_end_proc(struct end_proc_data **);
 
+#define sysstack_error rb_errSysStack
+
 /* for thread */
 
 #if RUBY_VM_THREAD_MODEL == 2
-RUBY_EXTERN rb_thread_t *ruby_current_thread;
-extern rb_vm_t *ruby_current_vm;
+#ifdef THREAD_SPECIFIC
+extern THREAD_SPECIFIC rb_thread_t *ruby_current_thread;
+#define rb_thread_set_current_raw(th) (void)(ruby_current_thread = (th))
+#else
+#define ruby_current_thread ruby_thread_from_native()
+#define rb_thread_set_current_raw(th) (void)ruby_thread_from_native(th)
+#endif
 
-#define GET_VM() ruby_current_vm
+rb_thread_t * ruby_thread_from_native(void);
+int ruby_thread_set_native(rb_thread_t *th);
+
+#define GET_VM() (GET_THREAD()->vm)
 #define GET_THREAD() ruby_current_thread
-#define rb_thread_set_current_raw(th) (ruby_current_thread = th)
 #define rb_thread_set_current(th) do { \
     rb_thread_set_current_raw(th); \
     th->vm->running_thread = th; \
Index: mvm/iseq.c
===================================================================
--- mvm/iseq.c	(revision 17908)
+++ mvm/iseq.c	(revision 17909)
@@ -23,8 +23,6 @@
 void iseq_compile(VALUE self, NODE *node);
 int iseq_translate_threaded_code(rb_iseq_t *iseq);
 
-VALUE rb_cISeq;
-
 static void
 compile_data_free(struct iseq_compile_data *compile_data)
 {
Index: mvm/enum.c
===================================================================
--- mvm/enum.c	(revision 17908)
+++ mvm/enum.c	(revision 17909)
@@ -13,7 +13,6 @@
 #include "ruby/node.h"
 #include "ruby/util.h"
 
-VALUE rb_mEnumerable;
 static ID id_each, id_eqq, id_cmp, id_next, id_size;
 
 static VALUE
Index: mvm/string.c
===================================================================
--- mvm/string.c	(revision 17908)
+++ mvm/string.c	(revision 17909)
@@ -29,9 +29,6 @@
 #undef rb_tainted_str_new2
 #undef rb_usascii_str_new2
 
-VALUE rb_cString;
-VALUE rb_cSymbol;
-
 #define STR_TMPLOCK FL_USER7
 #define STR_NOEMBED FL_USER1
 #define STR_SHARED  FL_USER2 /* = ELTS_SHARED */
Index: mvm/object.c
===================================================================
--- mvm/object.c	(revision 17908)
+++ mvm/object.c	(revision 17909)
@@ -14,6 +14,7 @@
 #include "ruby/ruby.h"
 #include "ruby/st.h"
 #include "ruby/util.h"
+#include "private_object.h"
 #include "debug.h"
 #include <stdio.h>
 #include <errno.h>
@@ -21,17 +22,6 @@
 #include <math.h>
 #include <float.h>
 
-VALUE rb_cBasicObject;
-VALUE rb_mKernel;
-VALUE rb_cObject;
-VALUE rb_cModule;
-VALUE rb_cClass;
-VALUE rb_cData;
-
-VALUE rb_cNilClass;
-VALUE rb_cTrueClass;
-VALUE rb_cFalseClass;
-
 static ID id_eq, id_eql, id_match, id_inspect, id_init_copy;
 
 /*
@@ -698,8 +688,6 @@
     OBJ_INFECT(obj1, obj2);
 }
 
-static st_table *immediate_frozen_tbl = 0;
-
 /*
  *  call-seq:
  *     obj.freeze    => obj
@@ -728,8 +716,15 @@
 	}
 	OBJ_FREEZE(obj);
 	if (SPECIAL_CONST_P(obj)) {
-	    if (!immediate_frozen_tbl) {
+	    VALUE *wrapper = &rb_immediate_frozen_tbl;
+	    st_table *immediate_frozen_tbl;
+
+	    if (*wrapper) {
+		immediate_frozen_tbl = DATA_PTR(*wrapper);
+	    }
+	    else {
 		immediate_frozen_tbl = st_init_numtable();
+		*wrapper = rb_wrap_st_table(immediate_frozen_tbl);
 	    }
 	    st_insert(immediate_frozen_tbl, obj, (st_data_t)Qtrue);
 	}
@@ -753,8 +748,9 @@
 {
     if (OBJ_FROZEN(obj)) return Qtrue;
     if (SPECIAL_CONST_P(obj)) {
-	if (!immediate_frozen_tbl) return Qfalse;
-	if (st_lookup(immediate_frozen_tbl, obj, 0)) return Qtrue;
+	VALUE tbl = rb_immediate_frozen_tbl;
+	if (!tbl) return Qfalse;
+	if (st_lookup(DATA_PTR(tbl), obj, 0)) return Qtrue;
     }
     return Qfalse;
 }
@@ -2279,12 +2275,10 @@
 static VALUE
 boot_defclass(const char *name, VALUE super)
 {
-    extern st_table *rb_class_tbl;
     VALUE obj = rb_class_boot(super);
     ID id = rb_intern(name);
 
     rb_name_class(obj, id);
-    st_add_direct(rb_class_tbl, id, obj);
     rb_const_set((rb_cObject ? rb_cObject : obj), id, obj);
     return obj;
 }
Index: mvm/io.c
===================================================================
--- mvm/io.c	(revision 17908)
+++ mvm/io.c	(revision 17909)
@@ -111,11 +111,6 @@
 # endif
 #endif
 
-VALUE rb_cIO;
-VALUE rb_eEOFError;
-VALUE rb_eIOError;
-
-VALUE rb_stdin, rb_stdout, rb_stderr;
 VALUE rb_deferr;		/* rescue VIM plugin */
 static VALUE orig_stdout, orig_stderr;
 
@@ -141,13 +136,16 @@
 };
 
 static int max_file_descriptor = NOFILE;
+static rb_thread_lock_t max_file_descriptor_lock;
 #define UPDATE_MAXFD(fd) \
     do { \
+	ruby_native_thread_lock(&max_file_descriptor_lock); \
         if (max_file_descriptor < (fd)) max_file_descriptor = (fd); \
+	ruby_native_thread_unlock(&max_file_descriptor_lock); \
     } while (0)
 
 #define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
-#define ruby_vm_argf(vm) ((vm)->argf)
+#define ruby_vm_argf(vm) (*ruby_vm_specific_ptr(vm, rb_vmkey_argf))
 #define ARGF argf_of(ruby_vm_argf(GET_VM()))
 
 #ifdef _STDIO_USES_IOSTREAM  /* GNU libc */
@@ -3649,8 +3647,9 @@
         }
     }
     if (ret == 0) {
-        UPDATE_MAXFD(pipes[0]);
-        UPDATE_MAXFD(pipes[1]);
+	int larger_file_descriptor =
+	    pipes[0] > pipes[1] ? pipes[0] : pipes[1];
+        UPDATE_MAXFD(larger_file_descriptor);
     }
     return ret;
 }
@@ -7465,15 +7464,15 @@
 const char *
 ruby_vm_get_inplace_mode(rb_vm_t *vm)
 {
-    return argf_of(vm->argf).inplace;
+    return argf_of(ruby_vm_argf(vm)).inplace;
 }
 
 void
 ruby_vm_set_inplace_mode(rb_vm_t *vm, const char *suffix)
 {
-    if (argf_of(vm->argf).inplace) free(argf_of(vm->argf).inplace);
-    argf_of(vm->argf).inplace = 0;
-    if (suffix) argf_of(vm->argf).inplace = strdup(suffix);
+    if (argf_of(ruby_vm_argf(vm)).inplace) free(argf_of(ruby_vm_argf(vm)).inplace);
+    argf_of(ruby_vm_argf(vm)).inplace = 0;
+    if (suffix) argf_of(ruby_vm_argf(vm)).inplace = strdup(suffix);
 }
 
 static VALUE
@@ -7491,7 +7490,7 @@
 VALUE
 ruby_vm_get_argv(rb_vm_t *vm)
 {
-    return argf_of(vm->argf).argv;
+    return argf_of(ruby_vm_argf(vm)).argv;
 }
 
 VALUE
@@ -7582,7 +7581,7 @@
 #undef rb_intern
 
     VALUE rb_cARGF;
-    VALUE *argfp = &GET_VM()->argf;
+    VALUE *argfp = &ruby_vm_argf(GET_VM());
 #ifdef __CYGWIN__
 #include <sys/cygwin.h>
     static struct __cygwin_perfile pf[] =
Index: mvm/range.c
===================================================================
--- mvm/range.c	(revision 17908)
+++ mvm/range.c	(revision 17909)
@@ -12,7 +12,6 @@
 #include "ruby/ruby.h"
 #include "ruby/encoding.h"
 
-VALUE rb_cRange;
 static ID id_cmp, id_succ, id_beg, id_end, id_excl;
 
 #define RANGE_BEG(r) (RSTRUCT(r)->as.ary[0])
Index: mvm/proc.c
===================================================================
--- mvm/proc.c	(revision 17908)
+++ mvm/proc.c	(revision 17909)
@@ -20,11 +20,6 @@
     NODE *body;
 };
 
-VALUE rb_cUnboundMethod;
-VALUE rb_cMethod;
-VALUE rb_cBinding;
-VALUE rb_cProc;
-
 static VALUE bmcall(VALUE, VALUE);
 static int method_arity(VALUE);
 static VALUE rb_obj_is_method(VALUE m);
Index: mvm/thread.c
===================================================================
--- mvm/thread.c	(revision 17908)
+++ mvm/thread.c	(revision 17909)
@@ -52,9 +52,6 @@
 #define THREAD_DEBUG 0
 #endif
 
-VALUE rb_cMutex;
-VALUE rb_cBarrier;
-
 static void sleep_timeval(rb_thread_t *th, struct timeval time);
 static void sleep_wait_for_interrupt(rb_thread_t *th, double sleepsec);
 static void sleep_forever(rb_thread_t *th, int nodeadlock);
@@ -297,7 +294,7 @@
 	}
 	POP_TAG();
     }
-    system_working = 0;
+    --system_working;
 }
 
 static void
@@ -2092,8 +2089,7 @@
 void
 rb_thread_stop_timer_thread(void)
 {
-    if (timer_thread_id) {
-	system_working = 0;
+    if (timer_thread_id && --system_working == 0) {
 	native_thread_join(timer_thread_id);
 	timer_thread_id = 0;
     }
@@ -2410,8 +2406,6 @@
     VALUE next_mutex;
 } mutex_t;
 
-static VALUE rb_eMutex_OrphanLock;
-
 #define GetMutexPtr(obj, tobj) \
   Data_Get_Struct(obj, mutex_t, tobj)
 
@@ -3563,9 +3557,18 @@
 static struct {
     rb_thread_lock_t lock;
     int last;
-} specific_key;
+} specific_key = {
+    RB_THREAD_LOCK_INITIALIZER,
+    ruby_builtin_object_count + 8,
+};
 
 int
+rb_vm_key_count(void)
+{
+    return specific_key.last;
+}
+
+int
 rb_vm_key_create(void)
 {
     int key;
@@ -3580,14 +3583,13 @@
 {
     VALUE *ptr;
 
-    native_mutex_lock(&vm->global_vm_lock);
     ptr = vm->specific_storage.ptr;
     if (!ptr || vm->specific_storage.len <= key) {
 	ptr = realloc(vm->specific_storage.ptr, sizeof(VALUE) * (key + 1));
 	vm->specific_storage.ptr = ptr;
+	MEMZERO(ptr, VALUE, key + 1 - vm->specific_storage.len);
 	vm->specific_storage.len = key + 1;
     }
-    native_mutex_unlock(&vm->global_vm_lock);
     return &ptr[key];
 }
 
@@ -3617,11 +3619,12 @@
 void
 rb_enable_coverages(void)
 {
+    VALUE *coverages = rb_vm_specific_ptr(rb_vmkey_coverages);
     VALUE rb_mCoverage;
 
-    if (!RTEST(GET_VM()->coverages)) {
+    if (!RTEST(*coverages)) {
 	extern VALUE rb_vm_get_coverages(void);
-	GET_VM()->coverages = rb_hash_new();
+	*coverages = rb_hash_new();
 	rb_add_event_hook(update_coverage, RUBY_EVENT_COVERAGE, Qnil);
 	rb_mCoverage = rb_define_module("Coverage");
 	rb_define_module_function(rb_mCoverage, "result", rb_vm_get_coverages, 0);
Index: mvm/common.mk
===================================================================
--- mvm/common.mk	(revision 17908)
+++ mvm/common.mk	(revision 17909)
@@ -430,8 +430,11 @@
 ###
 
 RUBY_H_INCLUDES = {$(VPATH)}ruby.h {$(VPATH)}config.h {$(VPATH)}defines.h \
-		  {$(VPATH)}intern.h {$(VPATH)}missing.h
+		  {$(VPATH)}intern.h {$(VPATH)}missing.h \
+		  {$(VPATH)}public_object.h
 
+VM_CORE_H_INCLUDES = {$(VPATH)}vm_core.h {$(VPATH)}private_object.h
+
 array.$(OBJEXT): {$(VPATH)}array.c $(RUBY_H_INCLUDES) \
   {$(VPATH)}st.h {$(VPATH)}util.h
 bignum.$(OBJEXT): {$(VPATH)}bignum.c $(RUBY_H_INCLUDES) \
@@ -450,35 +453,36 @@
 dmyext.$(OBJEXT): {$(VPATH)}dmyext.c
 dmyencoding.$(OBJEXT): {$(VPATH)}dmyencoding.c \
   {$(VPATH)}encoding.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
-  {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h {$(VPATH)}regenc.h
+  {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h {$(VPATH)}regenc.h \
+  {$(VPATH)}private_object.h
 encoding.$(OBJEXT): dmyencoding.$(OBJEXT)
 enum.$(OBJEXT): {$(VPATH)}enum.c $(RUBY_H_INCLUDES) \
   {$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}util.h
 enumerator.$(OBJEXT): {$(VPATH)}enumerator.c $(RUBY_H_INCLUDES) \
   {$(VPATH)}st.h {$(VPATH)}debug.h {$(VPATH)}node.h
 error.$(OBJEXT): {$(VPATH)}error.c $(RUBY_H_INCLUDES) \
-  {$(VPATH)}st.h {$(VPATH)}vm_core.h {$(VPATH)}signal.h {$(VPATH)}node.h \
+  {$(VPATH)}st.h $(VM_CORE_H_INCLUDES) {$(VPATH)}signal.h {$(VPATH)}node.h \
   {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h
 eval.$(OBJEXT): {$(VPATH)}eval.c {$(VPATH)}eval_intern.h \
   $(RUBY_H_INCLUDES) {$(VPATH)}st.h {$(VPATH)}node.h \
-  {$(VPATH)}util.h {$(VPATH)}signal.h {$(VPATH)}vm_core.h \
+  {$(VPATH)}util.h {$(VPATH)}signal.h $(VM_CORE_H_INCLUDES) \
   {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}dln.h \
   {$(VPATH)}eval_error.c {$(VPATH)}eval_safe.c \
   {$(VPATH)}eval_jump.c
 load.$(OBJEXT): {$(VPATH)}load.c {$(VPATH)}eval_intern.h \
   $(RUBY_H_INCLUDES) {$(VPATH)}st.h {$(VPATH)}node.h \
-  {$(VPATH)}util.h {$(VPATH)}signal.h {$(VPATH)}vm_core.h \
+  {$(VPATH)}util.h {$(VPATH)}signal.h $(VM_CORE_H_INCLUDES) \
   {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}dln.h
 file.$(OBJEXT): {$(VPATH)}file.c $(RUBY_H_INCLUDES) \
   {$(VPATH)}st.h {$(VPATH)}io.h {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h \
-  {$(VPATH)}signal.h {$(VPATH)}util.h {$(VPATH)}dln.h
+  {$(VPATH)}signal.h {$(VPATH)}util.h {$(VPATH)}dln.h {$(VPATH)}private_object.h
 gc.$(OBJEXT): {$(VPATH)}gc.c $(RUBY_H_INCLUDES) \
   {$(VPATH)}st.h {$(VPATH)}signal.h {$(VPATH)}node.h {$(VPATH)}re.h \
   {$(VPATH)}regex.h {$(VPATH)}oniguruma.h {$(VPATH)}io.h \
-  {$(VPATH)}encoding.h {$(VPATH)}vm_core.h {$(VPATH)}debug.h \
+  {$(VPATH)}encoding.h $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h \
   {$(VPATH)}vm_opts.h {$(VPATH)}id.h {$(VPATH)}thread_$(THREAD_MODEL).h \
   {$(VPATH)}gc.h {$(VPATH)}eval_intern.h
 hash.$(OBJEXT): {$(VPATH)}hash.c $(RUBY_H_INCLUDES) \
@@ -492,12 +496,13 @@
   {$(VPATH)}st.h
 marshal.$(OBJEXT): {$(VPATH)}marshal.c $(RUBY_H_INCLUDES) \
   {$(VPATH)}st.h {$(VPATH)}io.h {$(VPATH)}encoding.h \
-  {$(VPATH)}oniguruma.h {$(VPATH)}util.h
+  {$(VPATH)}oniguruma.h {$(VPATH)}util.h {$(VPATH)}private_object.h
 math.$(OBJEXT): {$(VPATH)}math.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h
 numeric.$(OBJEXT): {$(VPATH)}numeric.c $(RUBY_H_INCLUDES) \
   {$(VPATH)}st.h {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h
 object.$(OBJEXT): {$(VPATH)}object.c $(RUBY_H_INCLUDES) \
-  {$(VPATH)}st.h {$(VPATH)}util.h {$(VPATH)}debug.h {$(VPATH)}node.h
+  {$(VPATH)}st.h {$(VPATH)}util.h {$(VPATH)}debug.h {$(VPATH)}node.h \
+  {$(VPATH)}private_object.h
 pack.$(OBJEXT): {$(VPATH)}pack.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h
 parse.$(OBJEXT): {$(VPATH)}parse.c {$(VPATH)}parse.y $(RUBY_H_INCLUDES) \
   {$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}encoding.h \
@@ -507,11 +512,11 @@
 prec.$(OBJEXT): {$(VPATH)}prec.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h
 proc.$(OBJEXT): {$(VPATH)}proc.c {$(VPATH)}eval_intern.h \
   $(RUBY_H_INCLUDES) {$(VPATH)}st.h {$(VPATH)}node.h \
-  {$(VPATH)}util.h {$(VPATH)}signal.h {$(VPATH)}vm_core.h \
+  {$(VPATH)}util.h {$(VPATH)}signal.h $(VM_CORE_H_INCLUDES) \
   {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}dln.h {$(VPATH)}gc.h
 process.$(OBJEXT): {$(VPATH)}process.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
-  {$(VPATH)}signal.h {$(VPATH)}vm_core.h \
+  {$(VPATH)}signal.h $(VM_CORE_H_INCLUDES) \
   {$(VPATH)}node.h {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h
 random.$(OBJEXT): {$(VPATH)}random.c $(RUBY_H_INCLUDES) \
@@ -545,11 +550,11 @@
 ruby.$(OBJEXT): {$(VPATH)}ruby.c $(RUBY_H_INCLUDES) \
   {$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}encoding.h \
   {$(VPATH)}oniguruma.h {$(VPATH)}eval_intern.h {$(VPATH)}util.h \
-  {$(VPATH)}signal.h {$(VPATH)}vm_core.h {$(VPATH)}debug.h \
+  {$(VPATH)}signal.h $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h \
   {$(VPATH)}vm_opts.h {$(VPATH)}id.h {$(VPATH)}thread_$(THREAD_MODEL).h \
   {$(VPATH)}dln.h
 signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \
-  {$(VPATH)}st.h {$(VPATH)}signal.h {$(VPATH)}node.h {$(VPATH)}vm_core.h \
+  {$(VPATH)}st.h {$(VPATH)}signal.h {$(VPATH)}node.h $(VM_CORE_H_INCLUDES) \
   {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h
 sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
@@ -564,14 +569,14 @@
   {$(VPATH)}st.h
 thread.$(OBJEXT): {$(VPATH)}thread.c {$(VPATH)}eval_intern.h \
   $(RUBY_H_INCLUDES) {$(VPATH)}st.h {$(VPATH)}node.h \
-  {$(VPATH)}util.h {$(VPATH)}signal.h {$(VPATH)}vm_core.h \
+  {$(VPATH)}util.h {$(VPATH)}signal.h $(VM_CORE_H_INCLUDES) \
   {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}dln.h {$(VPATH)}vm.h \
   {$(VPATH)}gc.h {$(VPATH)}thread_$(THREAD_MODEL).c
 transcode.$(OBJEXT): {$(VPATH)}transcode.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
   {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h {$(VPATH)}transcode_data.h
 cont.$(OBJEXT): {$(VPATH)}cont.c $(RUBY_H_INCLUDES) \
-  {$(VPATH)}st.h {$(VPATH)}vm_core.h {$(VPATH)}signal.h {$(VPATH)}node.h \
+  {$(VPATH)}st.h $(VM_CORE_H_INCLUDES) {$(VPATH)}signal.h {$(VPATH)}node.h \
   {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}gc.h \
   {$(VPATH)}eval_intern.h {$(VPATH)}util.h {$(VPATH)}dln.h
@@ -580,17 +585,17 @@
 util.$(OBJEXT): {$(VPATH)}util.c $(RUBY_H_INCLUDES) \
   {$(VPATH)}st.h {$(VPATH)}util.h
 variable.$(OBJEXT): {$(VPATH)}variable.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
-  {$(VPATH)}node.h {$(VPATH)}util.h
+  {$(VPATH)}node.h {$(VPATH)}util.h $(VM_CORE_H_INCLUDES)
 version.$(OBJEXT): {$(VPATH)}version.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
   {$(VPATH)}version.h $(srcdir)/revision.h
 
 compile.$(OBJEXT): {$(VPATH)}compile.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
-  {$(VPATH)}node.h {$(VPATH)}vm_core.h \
+  {$(VPATH)}node.h $(VM_CORE_H_INCLUDES) \
   {$(VPATH)}signal.h {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}compile.h \
   {$(VPATH)}insns.inc {$(VPATH)}insns_info.inc {$(VPATH)}optinsn.inc
 iseq.$(OBJEXT): {$(VPATH)}iseq.c $(RUBY_H_INCLUDES) \
-  {$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}gc.h {$(VPATH)}vm_core.h \
+  {$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}gc.h $(VM_CORE_H_INCLUDES) \
   {$(VPATH)}signal.h {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}insns.inc \
   {$(VPATH)}insns_info.inc {$(VPATH)}node_name.inc
@@ -598,36 +603,36 @@
   {$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}encoding.h \
   {$(VPATH)}oniguruma.h {$(VPATH)}gc.h {$(VPATH)}insnhelper.h \
   {$(VPATH)}eval_intern.h {$(VPATH)}util.h {$(VPATH)}signal.h \
-  {$(VPATH)}vm_core.h {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
+  $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}dln.h {$(VPATH)}vm.h \
   {$(VPATH)}vm_insnhelper.c {$(VPATH)}insns.inc {$(VPATH)}vm_evalbody.c \
   {$(VPATH)}vmtc.inc {$(VPATH)}vm.inc {$(VPATH)}insns.def \
   {$(VPATH)}vm_method.c {$(VPATH)}vm_eval.c
 vm_dump.$(OBJEXT): {$(VPATH)}vm_dump.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
-  {$(VPATH)}node.h {$(VPATH)}vm_core.h \
+  {$(VPATH)}node.h $(VM_CORE_H_INCLUDES) \
   {$(VPATH)}signal.h {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}vm.h
 debug.$(OBJEXT): {$(VPATH)}debug.c $(RUBY_H_INCLUDES) \
   {$(VPATH)}st.h {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h \
-  {$(VPATH)}debug.h {$(VPATH)}node.h {$(VPATH)}vm_core.h \
+  {$(VPATH)}debug.h {$(VPATH)}node.h $(VM_CORE_H_INCLUDES) \
   {$(VPATH)}signal.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h
 blockinlining.$(OBJEXT): {$(VPATH)}blockinlining.c $(RUBY_H_INCLUDES) \
-  {$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}vm_core.h \
+  {$(VPATH)}st.h {$(VPATH)}node.h $(VM_CORE_H_INCLUDES) \
   {$(VPATH)}signal.h {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h
 id.$(OBJEXT): {$(VPATH)}id.c $(RUBY_H_INCLUDES) \
   {$(VPATH)}st.h {$(VPATH)}id.h
 miniprelude.$(OBJEXT): {$(VPATH)}miniprelude.c $(RUBY_H_INCLUDES) \
-  {$(VPATH)}st.h {$(VPATH)}vm_core.h {$(VPATH)}signal.h \
+  {$(VPATH)}st.h $(VM_CORE_H_INCLUDES) {$(VPATH)}signal.h \
   {$(VPATH)}node.h {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h
 prelude.$(OBJEXT): {$(VPATH)}prelude.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
-  {$(VPATH)}vm_core.h {$(VPATH)}signal.h \
+  $(VM_CORE_H_INCLUDES) {$(VPATH)}signal.h \
   {$(VPATH)}node.h {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h
 golf_prelude.$(OBJEXT): {$(VPATH)}golf_prelude.c $(RUBY_H_INCLUDES) \
-  {$(VPATH)}st.h {$(VPATH)}vm_core.h {$(VPATH)}signal.h \
+  {$(VPATH)}st.h $(VM_CORE_H_INCLUDES) {$(VPATH)}signal.h \
   {$(VPATH)}node.h {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h
 goruby.$(OBJEXT): {$(VPATH)}goruby.c {$(VPATH)}main.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h
Index: mvm/dir.c
===================================================================
--- mvm/dir.c	(revision 17908)
+++ mvm/dir.c	(revision 17909)
@@ -338,8 +338,6 @@
 	return fnmatch_helper(&p, &s, flags);
 }
 
-VALUE rb_cDir;
-
 struct dir_data {
     DIR *dir;
     char *path;
Index: mvm/win32/Makefile.sub
===================================================================
--- mvm/win32/Makefile.sub	(revision 17908)
+++ mvm/win32/Makefile.sub	(revision 17909)
@@ -451,6 +451,7 @@
 !if "$(PROCESSOR_ARCHITECTURE)" == "x86" || "$(ARCH)" == "x64" || "$(ARCH)" == "ia64"
 #define STACK_GROW_DIRECTION -1
 !endif
+#define THREAD_SPECIFIC __declspec(thread)
 #define DEFAULT_KCODE KCODE_NONE
 #define DLEXT ".so"
 #define RUBY_LIB "/lib/ruby/$(MAJOR).$(MINOR).$(TEENY)"
Index: mvm/eval_jump.c
===================================================================
--- mvm/eval_jump.c	(revision 17908)
+++ mvm/eval_jump.c	(revision 17909)
@@ -54,8 +54,6 @@
     struct end_proc_data *next;
 };
 
-static struct end_proc_data *end_procs, *ephemeral_end_procs, *tmp_end_procs;
-
 void
 rb_set_end_proc(void (*func)(VALUE), VALUE data)
 {
@@ -64,10 +62,10 @@
     rb_thread_t *th = GET_THREAD();
 
     if (th->top_wrapper) {
-	list = &ephemeral_end_procs;
+	list = th->vm->end_procs + end_proc_ephemeral;
     }
     else {
-	list = &end_procs;
+	list = th->vm->end_procs + end_proc_ordinary;
     }
     link->next = *list;
     link->func = func;
@@ -77,70 +75,48 @@
 }
 
 void
-rb_mark_end_proc(void)
+rb_mark_end_proc(struct end_proc_data **endp)
 {
     struct end_proc_data *link;
+    int i;
 
-    link = end_procs;
-    while (link) {
-	rb_gc_mark(link->data);
-	link = link->next;
+    for (i = 0; i < end_proc_count; ++i) {
+	link = endp[i];
+	while (link) {
+	    rb_gc_mark(link->data);
+	    link = link->next;
+	}
     }
-    link = ephemeral_end_procs;
-    while (link) {
-	rb_gc_mark(link->data);
-	link = link->next;
-    }
-    link = tmp_end_procs;
-    while (link) {
-	rb_gc_mark(link->data);
-	link = link->next;
-    }
 }
 
 void
-rb_exec_end_proc(void)
+rb_exec_end_proc(struct end_proc_data **end_procs)
 {
     struct end_proc_data *link, *tmp;
-    int status;
+    int status, i;
     volatile int safe = rb_safe_level();
 
-    while (ephemeral_end_procs) {
-	tmp_end_procs = link = ephemeral_end_procs;
-	ephemeral_end_procs = 0;
-	while (link) {
-	    PUSH_TAG();
-	    if ((status = EXEC_TAG()) == 0) {
-		rb_set_safe_level_force(link->safe);
-		(*link->func) (link->data);
+    i = end_proc_ephemeral;
+    do {
+	while ((link = end_procs[i]) != 0) {
+	    end_procs[i] = 0;
+	    end_procs[end_proc_temporary] = link;
+	    while (link) {
+		PUSH_TAG();
+		if ((status = EXEC_TAG()) == 0) {
+		    rb_set_safe_level_force(link->safe);
+		    (*link->func) (link->data);
+		}
+		POP_TAG();
+		if (status) {
+		    error_handle(status);
+		}
+		tmp = link;
+		end_procs[end_proc_temporary] = link = link->next;
+		xfree(tmp);
 	    }
-	    POP_TAG();
-	    if (status) {
-		error_handle(status);
-	    }
-	    tmp = link;
-	    tmp_end_procs = link = link->next;
-	    xfree(tmp);
 	}
-    }
-    while (end_procs) {
-	tmp_end_procs = link = end_procs;
-	end_procs = 0;
-	while (link) {
-	    PUSH_TAG();
-	    if ((status = EXEC_TAG()) == 0) {
-		rb_set_safe_level_force(link->safe);
-		(*link->func) (link->data);
-	    }
-	    POP_TAG();
-	    if (status) {
-		error_handle(status);
-	    }
-	    tmp = link;
-	    tmp_end_procs = link = link->next;
-	    xfree(tmp);
-	}
-    }
+    } while (i-- > end_proc_ordinary);
     rb_set_safe_level_force(safe);
 }
 
Index: mvm/struct.c
===================================================================
--- mvm/struct.c	(revision 17908)
+++ mvm/struct.c	(revision 17909)
@@ -11,8 +11,6 @@
 
 #include "ruby/ruby.h"
 
-VALUE rb_cStruct;
-
 static VALUE struct_alloc(VALUE);
 
 VALUE
Index: mvm/eval.c
===================================================================
--- mvm/eval.c	(revision 17908)
+++ mvm/eval.c	(revision 17909)
@@ -18,10 +18,8 @@
 NORETURN(void rb_raise_jump(VALUE));
 
 ID rb_frame_callee(void);
-VALUE rb_eLocalJumpError;
-VALUE rb_eSysStackError;
 
-#define exception_error GET_VM()->special_exceptions[ruby_error_reenter]
+#define exception_error rb_errReenterError
 
 #include "eval_error.c"
 #include "eval_safe.c"
@@ -123,7 +121,7 @@
 	rb_trap_exit();
     }
     POP_TAG();
-    rb_exec_end_proc();
+    rb_exec_end_proc(vm->end_procs);
     rb_clear_trace_func();
 }
 
@@ -621,8 +619,6 @@
     }
 }
 
-VALUE rb_eThreadError;
-
 void
 rb_need_block()
 {
@@ -1177,9 +1173,6 @@
 void
 Init_eval(void)
 {
-    /* TODO: fix position */
-    GET_THREAD()->vm->mark_object_ary = rb_ary_new();
-
     rb_define_virtual_variable("$@", errat_getter, errat_setter);
     rb_define_virtual_variable("$!", errinfo_getter, 0);
 
Index: mvm/gc.c
===================================================================
--- mvm/gc.c	(revision 17908)
+++ mvm/gc.c	(revision 17909)
@@ -84,7 +84,7 @@
 #endif
 #endif
 
-#define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory]
+#define nomem_error rb_errNoMemError
 
 #define MARK_STACK_MAX 1024
 
@@ -243,8 +243,6 @@
 
 #define HEAP_OBJ_LIMIT (HEAP_SIZE / sizeof(struct RVALUE))
 
-extern st_table *rb_class_tbl;
-
 int ruby_disable_gc_stress = 0;
 
 static void run_final(rb_objspace_t *objspace, VALUE obj);
@@ -494,8 +492,6 @@
     return old;
 }
 
-VALUE rb_mGC;
-
 void
 rb_register_mark_object(VALUE obj)
 {
@@ -1715,10 +1711,7 @@
     for (list = global_List; list; list = list->next) {
 	rb_gc_mark_maybe(*list->varptr);
     }
-    rb_mark_end_proc();
-    rb_gc_mark_global_tbl();
 
-    mark_tbl(objspace, rb_class_tbl, 0);
     rb_gc_mark_trap_list();
 
     /* mark generic instance variables for special constants */
Index: mvm/class.c
===================================================================
--- mvm/class.c	(revision 17908)
+++ mvm/class.c	(revision 17909)
@@ -15,8 +15,6 @@
 #include "ruby/st.h"
 #include <ctype.h>
 
-extern st_table *rb_class_tbl;
-
 static VALUE
 class_alloc(VALUE flags, VALUE klass)
 {
@@ -243,7 +241,7 @@
 	rb_warn("no super class for `%s', Object assumed", name);
     }
     klass = rb_define_class_id(id, super);
-    st_add_direct(rb_class_tbl, id, klass);
+    rb_register_mark_object(klass);
     rb_name_class(klass, id);
     rb_const_set(rb_cObject, id, klass);
     rb_class_inherited(super, klass);
@@ -315,7 +313,7 @@
 	rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module));
     }
     module = rb_define_module_id(id);
-    st_add_direct(rb_class_tbl, id, module);
+    rb_register_mark_object(module);
     rb_const_set(rb_cObject, id, module);
 
     return module;
Index: mvm/dln.c
===================================================================
--- mvm/dln.c	(revision 17908)
+++ mvm/dln.c	(revision 17909)
@@ -1601,6 +1601,7 @@
 #endif
 }
 
+#ifndef HAVE_MVM
 static char fbuf[MAXPATHLEN];
 
 char *
@@ -1614,6 +1615,7 @@
 {
     return dln_find_file_r(fname, path, fbuf, sizeof(fbuf));
 }
+#endif
 
 static char *
 dln_find_1(const char *fname, const char *path, char *fbuf, int size,
Index: mvm/process.c
===================================================================
--- mvm/process.c	(revision 17908)
+++ mvm/process.c	(revision 17909)
@@ -73,10 +73,6 @@
 #include <grp.h>
 #endif
 
-#if defined(HAVE_TIMES) || defined(_WIN32)
-static VALUE rb_cProcessTms;
-#endif
-
 #ifndef WIFEXITED
 #define WIFEXITED(w)    (((w) & 0xff) == 0)
 #endif
@@ -213,8 +209,6 @@
  *  _stat_, we're referring to this 16 bit value.
  */
 
-static VALUE rb_cProcessStatus;
-
 VALUE
 rb_last_status_get(void)
 {
@@ -5060,12 +5054,7 @@
 #endif
 }
 
-VALUE rb_mProcess;
-VALUE rb_mProcUID;
-VALUE rb_mProcGID;
-VALUE rb_mProcID_Syscall;
 
-
 /*
  *  The <code>Process</code> module is a collection of methods used to
  *  manipulate processes.
@@ -5074,6 +5063,10 @@
 void
 Init_process(void)
 {
+    VALUE rb_mProcUID;
+    VALUE rb_mProcGID;
+    VALUE rb_mProcID_Syscall;
+
     rb_define_virtual_variable("$?", rb_last_status_get, 0);
     rb_define_virtual_variable("$$", get_pid, 0);
     rb_define_global_function("exec", rb_f_exec, -1);
Index: mvm/hash.c
===================================================================
--- mvm/hash.c	(revision 17908)
+++ mvm/hash.c	(revision 17909)
@@ -31,8 +31,6 @@
     return rb_obj_freeze(hash);
 }
 
-VALUE rb_cHash;
-
 static VALUE envtbl;
 static ID id_hash, id_yield, id_default;
 
Index: mvm/prec.c
===================================================================
--- mvm/prec.c	(revision 17908)
+++ mvm/prec.c	(revision 17909)
@@ -11,8 +11,6 @@
 
 #include "ruby/ruby.h"
 
-VALUE rb_mPrecision;
-
 static ID prc_pr, prc_if;
 
 
Index: mvm/error.c
===================================================================
--- mvm/error.c	(revision 17908)
+++ mvm/error.c	(revision 17909)
@@ -310,33 +310,6 @@
 /* exception classes */
 #include <errno.h>
 
-VALUE rb_eException;
-VALUE rb_eSystemExit;
-VALUE rb_eInterrupt;
-VALUE rb_eSignal;
-VALUE rb_eFatal;
-VALUE rb_eStandardError;
-VALUE rb_eRuntimeError;
-VALUE rb_eTypeError;
-VALUE rb_eArgError;
-VALUE rb_eIndexError;
-VALUE rb_eKeyError;
-VALUE rb_eRangeError;
-VALUE rb_eNameError;
-VALUE rb_eNoMethodError;
-VALUE rb_eSecurityError;
-VALUE rb_eNotImpError;
-VALUE rb_eNoMemError;
-VALUE rb_cNameErrorMesg;
-
-VALUE rb_eScriptError;
-VALUE rb_eSyntaxError;
-VALUE rb_eLoadError;
-
-VALUE rb_eSystemCallError;
-VALUE rb_mErrno;
-static VALUE rb_eNOERROR;
-
 VALUE
 rb_exc_new(VALUE etype, const char *ptr, long len)
 {
@@ -852,12 +825,11 @@
  *     Errno.constants   #=> :E2BIG, :EACCES, :EADDRINUSE, :EADDRNOTAVAIL, ...
  */
 
-static st_table *syserr_tbl;
-
 static VALUE
 set_syserr(int n, const char *name)
 {
     VALUE error;
+    st_table *syserr_tbl = DATA_PTR(rb_syserr_tbl);
 
     if (!st_lookup(syserr_tbl, n, &error)) {
 	error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError);
@@ -874,6 +846,7 @@
 get_syserr(int n)
 {
     VALUE error;
+    st_table *syserr_tbl = DATA_PTR(rb_syserr_tbl);
 
     if (!st_lookup(syserr_tbl, n, &error)) {
 	char name[8];	/* some Windows' errno have 5 digits. */
@@ -906,6 +879,7 @@
     VALUE klass = rb_obj_class(self);
 
     if (klass == rb_eSystemCallError) {
+	st_table *syserr_tbl = DATA_PTR(rb_syserr_tbl);
 	rb_scan_args(argc, argv, "11", &mesg, &error);
 	if (argc == 1 && FIXNUM_P(mesg)) {
 	    error = mesg; mesg = Qnil;
@@ -1058,7 +1032,7 @@
     rb_eSecurityError = rb_define_class("SecurityError", rb_eException);
     rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException);
 
-    syserr_tbl = st_init_numtable();
+    rb_syserr_tbl = rb_wrap_st_table(st_init_numtable());
     rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError);
     rb_define_method(rb_eSystemCallError, "initialize", syserr_initialize, -1);
     rb_define_method(rb_eSystemCallError, "errno", syserr_errno, 0);
Index: mvm/numeric.c
===================================================================
--- mvm/numeric.c	(revision 17908)
+++ mvm/numeric.c	(revision 17909)
@@ -82,14 +82,6 @@
 
 static ID id_coerce, id_to_i, id_eq;
 
-VALUE rb_cNumeric;
-VALUE rb_cFloat;
-VALUE rb_cInteger;
-VALUE rb_cFixnum;
-
-VALUE rb_eZeroDivError;
-VALUE rb_eFloatDomainError;
-
 void
 rb_num_zerodiv(void)
 {
Index: mvm/cont.c
===================================================================
--- mvm/cont.c	(revision 17908)
+++ mvm/cont.c	(revision 17909)
@@ -39,10 +39,6 @@
     enum context_type type;
 } rb_context_t;
 
-static VALUE rb_cContinuation;
-static VALUE rb_cFiber;
-static VALUE rb_eFiberError;
-
 #define GetContPtr(obj, ptr)  \
   Data_Get_Struct(obj, rb_context_t, ptr)
 
Index: mvm/compar.c
===================================================================
--- mvm/compar.c	(revision 17908)
+++ mvm/compar.c	(revision 17909)
@@ -11,8 +11,6 @@
 
 #include "ruby/ruby.h"
 
-VALUE rb_mComparable;
-
 static ID cmp;
 
 void
Index: mvm/vm.c
===================================================================
--- mvm/vm.c	(revision 17908)
+++ mvm/vm.c	(revision 17909)
@@ -21,15 +21,10 @@
 #define BUFSIZE 0x100
 #define PROCDEBUG 0
 
-VALUE rb_cRubyVM;
-VALUE rb_cThread;
-VALUE rb_cEnv;
-VALUE rb_mRubyVMFrozenCore;
+#ifdef THREAD_SPECIFIC
+THREAD_SPECIFIC rb_thread_t *ruby_current_thread = 0;
+#endif
 
-VALUE ruby_vm_global_state_version = 1;
-rb_thread_t *ruby_current_thread = 0;
-rb_vm_t *ruby_current_vm = 0;
-
 void vm_analysis_operand(int insn, int n, VALUE op);
 void vm_analysis_register(int reg, int isset);
 void vm_analysis_insn(int insn);
@@ -784,7 +779,6 @@
 static VALUE
 make_localjump_error(const char *mesg, VALUE value, int reason)
 {
-    extern VALUE rb_eLocalJumpError;
     VALUE exc = rb_exc_new2(rb_eLocalJumpError, mesg);
     ID id;
 
@@ -883,8 +877,7 @@
 
 /* optimization: redefine management */
 
-VALUE ruby_vm_redefined_flag = 0;
-static st_table *vm_opt_method_table = 0;
+#define vm_opt_method_table GET_VM()->opt_method_table
 
 static void
 rb_vm_check_redefinition_opt_method(const NODE *node)
@@ -910,12 +903,12 @@
 }
 
 static void
-vm_init_redefined_flag(void)
+vm_init_redefined_flag(rb_vm_t *vm)
 {
     ID mid;
     VALUE bop;
 
-    vm_opt_method_table = st_init_numtable();
+    vm->opt_method_table = st_init_numtable();
 
 #define OP(mid_, bop_) (mid = id##mid_, bop = BOP_##bop_)
 #define C(k) add_opt_method(rb_c##k, mid, bop)
@@ -1395,13 +1388,15 @@
 	RUBY_MARK_UNLESS_NULL(vm->load_path);
 	RUBY_MARK_UNLESS_NULL(vm->loaded_features);
 	RUBY_MARK_UNLESS_NULL(vm->top_self);
-	RUBY_MARK_UNLESS_NULL(vm->coverages);
-	rb_gc_mark_locations(vm->special_exceptions, vm->special_exceptions + ruby_special_error_count - 1);
+	rb_gc_mark_locations(vm->specific_storage.ptr, vm->specific_storage.ptr + vm->specific_storage.len - 1);
 
 	if (vm->loading_table) {
 	    rb_mark_tbl(vm->loading_table);
 	}
 
+	rb_vm_mark_global_tbl(vm->global_tbl);
+	rb_mark_end_proc(vm->end_procs);
+
 	mark_event_hooks(vm->event_hooks);
     }
 
@@ -1413,6 +1408,9 @@
 {
     MEMZERO(vm, rb_vm_t, 1);
     vm->src_encoding_index = -1;
+    vm->global_state_version = 1;
+    vm->specific_storage.len = rb_vm_key_count();
+    vm->specific_storage.ptr = calloc(vm->specific_storage.len, sizeof(VALUE));
 }
 
 /* Thread */
@@ -1693,11 +1691,6 @@
 }
 
 VALUE insns_name_array(void);
-extern VALUE *rb_gc_stack_start;
-extern size_t rb_gc_stack_maxsize;
-#ifdef __ia64
-extern VALUE *rb_gc_register_stack_start;
-#endif
 
 /* debug functions */
 
@@ -1736,20 +1729,21 @@
 Init_VM(void)
 {
     VALUE opts;
+    VALUE core;
 
     /* ::VM */
     rb_cRubyVM = rb_define_class("RubyVM", rb_cObject);
     rb_undef_alloc_func(rb_cRubyVM);
 
     /* ::VM::FrozenCore */
-    rb_mRubyVMFrozenCore = rb_define_module_under(rb_cRubyVM, "FrozenCore");
-    rb_define_singleton_method(rb_mRubyVMFrozenCore, "core_set_method_alias", m_core_set_method_alias, 3);
-    rb_define_singleton_method(rb_mRubyVMFrozenCore, "core_set_variable_alias", m_core_set_variable_alias, 2);
-    rb_define_singleton_method(rb_mRubyVMFrozenCore, "core_undef_method", m_core_undef_method, 2);
-    rb_define_singleton_method(rb_mRubyVMFrozenCore, "core_define_method", m_core_define_method, 3);
-    rb_define_singleton_method(rb_mRubyVMFrozenCore, "core_define_singleton_method", m_core_define_singleton_method, 3);
-    rb_define_singleton_method(rb_mRubyVMFrozenCore, "core_set_postexe", m_core_set_postexe, 1);
-    rb_obj_freeze(rb_mRubyVMFrozenCore);
+    rb_mRubyVMFrozenCore = core = rb_define_module_under(rb_cRubyVM, "FrozenCore");
+    rb_define_singleton_method(core, "core_set_method_alias", m_core_set_method_alias, 3);
+    rb_define_singleton_method(core, "core_set_variable_alias", m_core_set_variable_alias, 2);
+    rb_define_singleton_method(core, "core_undef_method", m_core_undef_method, 2);
+    rb_define_singleton_method(core, "core_define_method", m_core_define_method, 3);
+    rb_define_singleton_method(core, "core_define_singleton_method", m_core_define_singleton_method, 3);
+    rb_define_singleton_method(core, "core_set_postexe", m_core_set_postexe, 1);
+    rb_obj_freeze(core);
 
     /* ::VM::Env */
     rb_cEnv = rb_define_class_under(rb_cRubyVM, "Env", rb_cObject);
@@ -1807,8 +1801,8 @@
 
     /* VM bootstrap: phase 2 */
     {
-	rb_vm_t *vm = ruby_current_vm;
 	rb_thread_t *th = GET_THREAD();
+	rb_vm_t *vm = th->vm;
 	VALUE filename = rb_str_new2("<dummy toplevel>");
 	volatile VALUE iseqval = rb_iseq_new(0, filename, filename, 0, ISEQ_TYPE_TOP);
         volatile VALUE th_self;
@@ -1833,8 +1827,8 @@
 	GetISeqPtr(iseqval, iseq);
 	th->cfp->iseq = iseq;
 	th->cfp->pc = iseq->iseq_encoded;
+	vm_init_redefined_flag(vm);
     }
-    vm_init_redefined_flag();
 }
 
 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
@@ -1856,10 +1850,9 @@
 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
     vm->objspace = rb_objspace_alloc();
 #endif
-    ruby_current_vm = vm;
 
-    th_init2(th, 0);
     th->vm = vm;
+    th_init2(th, 0);
     ruby_thread_init_stack(th);
 }
 
@@ -1896,13 +1889,13 @@
 VALUE *
 ruby_vm_verbose_ptr(rb_vm_t *vm)
 {
-    return &vm->verbose;
+    return ruby_vm_specific_ptr(vm, rb_vmkey_verbose);
 }
 
 VALUE *
 ruby_vm_debug_ptr(rb_vm_t *vm)
 {
-    return &vm->debug;
+    return ruby_vm_specific_ptr(vm, rb_vmkey_debug);
 }
 
 VALUE *
@@ -1920,5 +1913,5 @@
 VALUE
 rb_vm_get_coverages(void)
 {
-    return GET_VM()->coverages;
+    return *rb_vm_specific_ptr(rb_vmkey_coverages);
 }
Index: mvm/vm.h
===================================================================
--- mvm/vm.h	(revision 17908)
+++ mvm/vm.h	(revision 17909)
@@ -18,9 +18,8 @@
 typedef rb_num_t GENTRY;
 typedef rb_iseq_t *ISEQ;
 
-extern VALUE rb_cEnv;
-extern VALUE ruby_vm_global_state_version;
-extern VALUE ruby_vm_redefined_flag;
+#define ruby_vm_global_state_version (GET_VM()->global_state_version)
+#define ruby_vm_redefined_flag (GET_VM()->redefined_flag)
 
 
 /**
Index: mvm/ruby.c
===================================================================
--- mvm/ruby.c	(revision 17908)
+++ mvm/ruby.c	(revision 17909)
@@ -629,8 +629,8 @@
 	    goto reswitch;
 
 	  case 'd':
-	    vm->debug = Qtrue;
-	    vm->verbose = Qtrue;
+	    *ruby_vm_specific_ptr(vm, rb_vmkey_debug) = Qtrue;
+	    *ruby_vm_specific_ptr(vm, rb_vmkey_verbose) = Qtrue;
 	    s++;
 	    goto reswitch;
 
@@ -647,7 +647,7 @@
 	    ruby_show_version();
 	    opt->verbose = 1;
 	  case 'w':
-	    vm->verbose = Qtrue;
+	    *ruby_vm_specific_ptr(vm, rb_vmkey_verbose) = Qtrue;
 	    s++;
 	    goto reswitch;
 
@@ -664,13 +664,13 @@
 		}
 		switch (v) {
 		  case 0:
-		    vm->verbose = Qnil;
+		    *ruby_vm_specific_ptr(vm, rb_vmkey_verbose) = Qnil;
 		    break;
 		  case 1:
-		    vm->verbose = Qfalse;
+		    *ruby_vm_specific_ptr(vm, rb_vmkey_verbose) = Qfalse;
 		    break;
 		  default:
-		    vm->verbose = Qtrue;
+		    *ruby_vm_specific_ptr(vm, rb_vmkey_verbose) = Qtrue;
 		    break;
 		}
 	    }
@@ -850,8 +850,8 @@
 	    if (strcmp("copyright", s) == 0)
 		opt->copyright = 1;
 	    else if (strcmp("debug", s) == 0) {
-		vm->debug = Qtrue;
-		vm->verbose = Qtrue;
+		*ruby_vm_specific_ptr(vm, rb_vmkey_debug) = Qtrue;
+		*ruby_vm_specific_ptr(vm, rb_vmkey_verbose) = Qtrue;
             }
 	    else if (strncmp("enable", s, n = 6) == 0 &&
 		     (!s[n] || s[n] == '-' || s[n] == '=')) {
@@ -882,7 +882,7 @@
 		opt->version = 1;
 	    else if (strcmp("verbose", s) == 0) {
 		opt->verbose = 1;
-		vm->verbose = Qtrue;
+		*ruby_vm_specific_ptr(vm, rb_vmkey_verbose) = Qtrue;
 	    }
 	    else if (strcmp("yydebug", s) == 0)
 		opt->yydebug = 1;
@@ -952,7 +952,7 @@
     return i;
 }
 
-#define rb_progname (vm->progname)
+#define rb_progname (*ruby_vm_specific_ptr(vm, rb_vmkey_progname))
 VALUE rb_argv0;
 
 static VALUE
@@ -1064,9 +1064,9 @@
 
     ruby_script(opt->script);
 #if defined DOSISH || defined __CYGWIN__
-    translate_char(RSTRING_PTR(vm->progname), '\\', '/');
+    translate_char(RSTRING_PTR(*ruby_vm_specific_ptr(vm, rb_vmkey_progname)), '\\', '/');
 #endif
-    opt->script_name = rb_str_new4(vm->progname);
+    opt->script_name = rb_str_new4(*ruby_vm_specific_ptr(vm, rb_vmkey_progname));
     opt->script = RSTRING_PTR(opt->script_name);
     ruby_vm_set_argv(vm, argc, argv);
     process_sflag(vm, opt);
@@ -1153,7 +1153,6 @@
 static NODE *
 load_file(rb_vm_t *vm, VALUE parser, const char *fname, int script, struct cmdline_options *opt)
 {
-    extern VALUE rb_stdin;
     VALUE f;
     int line_start = 1;
     NODE *tree = 0;
@@ -1396,7 +1395,7 @@
 	}
     }
 #endif
-    *var = rb_obj_freeze(rb_tainted_str_new(s, i));
+    *rb_vm_specific_ptr((int)var) = rb_obj_freeze(rb_tainted_str_new(s, i));
 }
 
 DEPRECATED(void ruby_script(const char *name));
@@ -1404,7 +1403,7 @@
 ruby_script(const char *name)
 {
     if (name) {
-	GET_VM()->progname = rb_obj_freeze(rb_tainted_str_new2(name));
+	*rb_vm_specific_ptr(rb_vmkey_progname) = rb_obj_freeze(rb_tainted_str_new2(name));
     }
 }
 
@@ -1464,15 +1463,15 @@
 void
 ruby_vm_prog_init(rb_vm_t *vm)
 {
-    rb_define_hooked_variable("$VERBOSE", &vm->verbose, 0, verbose_setter);
-    rb_define_hooked_variable("$-v", &vm->verbose, 0, verbose_setter);
-    rb_define_hooked_variable("$-w", &vm->verbose, 0, verbose_setter);
-    rb_define_hooked_variable("$-W", &vm->verbose, opt_W_getter, 0);
-    rb_define_variable("$DEBUG", &vm->debug);
-    rb_define_variable("$-d", &vm->debug);
+    rb_define_vm_specific_variable("$VERBOSE", rb_vmkey_verbose, 0, verbose_setter);
+    rb_define_vm_specific_variable("$-v", rb_vmkey_verbose, 0, verbose_setter);
+    rb_define_vm_specific_variable("$-w", rb_vmkey_verbose, 0, verbose_setter);
+    rb_define_vm_specific_variable("$-W", rb_vmkey_verbose, opt_W_getter, 0);
+    rb_define_vm_specific_variable("$DEBUG", rb_vmkey_debug, 0, 0);
+    rb_define_vm_specific_variable("$-d", rb_vmkey_debug, 0, 0);
 
-    rb_define_hooked_variable("$0", &vm->progname, 0, set_arg0);
-    rb_define_hooked_variable("$PROGRAM_NAME", &vm->progname, 0, set_arg0);
+    rb_define_vm_specific_variable("$0", rb_vmkey_progname, 0, set_arg0);
+    rb_define_vm_specific_variable("$PROGRAM_NAME", rb_vmkey_progname, 0, set_arg0);
 
     rb_define_global_const("ARGV", rb_argv);
 }
@@ -1542,7 +1541,7 @@
     NODE *tree;
 
     if (argv[0]) {		/* for the time being */
-	vm->progname = rb_tainted_str_new2(argv[0]);
+	*ruby_vm_specific_ptr(vm, rb_vmkey_progname) = rb_tainted_str_new2(argv[0]);
     }
     args.vm = vm;
     args.argc = argc;
@@ -1551,7 +1550,7 @@
     opt.ext.enc.index = -1;
     tree = (NODE *)rb_vm_call_cfunc(vm->top_self,
 				    process_options, (VALUE)&args,
-				    0, vm->progname);
+				    0, *ruby_vm_specific_ptr(vm, rb_vmkey_progname));
 
     rb_define_readonly_boolean("$-p", opt.do_print);
     rb_define_readonly_boolean("$-l", opt.do_line);
@@ -1564,7 +1563,7 @@
 {
     rb_vm_t *vm = GET_VM();
     VALUE result = ruby_vm_process_options(vm, argc, argv);
-    rb_argv0 = rb_str_new4(vm->progname);
+    rb_argv0 = rb_str_new4(*ruby_vm_specific_ptr(vm, rb_vmkey_progname));
     return (void *)result;
 }
 
Index: mvm/bignum.c
===================================================================
--- mvm/bignum.c	(revision 17908)
+++ mvm/bignum.c	(revision 17909)
@@ -18,8 +18,6 @@
 #include <ieeefp.h>
 #endif
 
-VALUE rb_cBignum;
-
 #if defined __MINGW32__
 #define USHORT _USHORT
 #endif
Index: mvm/marshal.c
===================================================================
--- mvm/marshal.c	(revision 17908)
+++ mvm/marshal.c	(revision 17909)
@@ -14,6 +14,7 @@
 #include "ruby/st.h"
 #include "ruby/util.h"
 #include "ruby/encoding.h"
+#include "private_object.h"
 
 #include <math.h>
 #ifdef HAVE_FLOAT_H
@@ -91,9 +92,6 @@
     VALUE (*loader)(VALUE, VALUE);
 } marshal_compat_t;
 
-static st_table *compat_allocator_tbl;
-static VALUE compat_allocator_tbl_wrapper;
-
 static int
 mark_marshal_compat_i(st_data_t key, st_data_t value)
 {
@@ -115,6 +113,7 @@
 {
     marshal_compat_t *compat;
     rb_alloc_func_t allocator = rb_get_alloc_func(newclass);
+    st_table *compat_allocator_tbl = DATA_PTR(rb_compat_allocator_tbl);
 
     if (!allocator) {
         rb_raise(rb_eTypeError, "no allocator");
@@ -140,6 +139,7 @@
     st_table *compat_tbl;
     VALUE wrapper;
     st_table *encodings;
+    st_table *compat_allocator_tbl;
 };
 
 struct dump_call_arg {
@@ -624,7 +624,7 @@
         {
             st_data_t compat_data;
             rb_alloc_func_t allocator = rb_get_alloc_func(RBASIC(obj)->klass);
-            if (st_lookup(compat_allocator_tbl,
+            if (st_lookup(arg->compat_allocator_tbl,
                           (st_data_t)allocator,
                           &compat_data)) {
                 marshal_compat_t *compat = (marshal_compat_t*)compat_data;
@@ -880,6 +880,7 @@
     arg.compat_tbl = st_init_numtable();
     arg.wrapper = Data_Wrap_Struct(rb_cData, mark_dump_arg, 0, &arg);
     arg.encodings = 0;
+    arg.compat_allocator_tbl = DATA_PTR(rb_compat_allocator_tbl);
     c_arg.obj   = obj;
     c_arg.arg   = &arg;
     c_arg.limit = limit;
@@ -899,6 +900,7 @@
     VALUE data;
     VALUE proc;
     int taint;
+    st_table *compat_allocator_tbl;
     st_table *compat_tbl;
     VALUE compat_tbl_wrapper;
 };
@@ -1094,7 +1096,7 @@
         VALUE real_obj = (VALUE)data;
         rb_alloc_func_t allocator = rb_get_alloc_func(CLASS_OF(real_obj));
         st_data_t key = v;
-        if (st_lookup(compat_allocator_tbl, (st_data_t)allocator, &data)) {
+        if (st_lookup(arg->compat_allocator_tbl, (st_data_t)allocator, &data)) {
             marshal_compat_t *compat = (marshal_compat_t*)data;
             compat->loader(real_obj, v);
         }
@@ -1161,7 +1163,7 @@
     klass = path2class(path);
 
     allocator = rb_get_alloc_func(klass);
-    if (st_lookup(compat_allocator_tbl, (st_data_t)allocator, &data)) {
+    if (st_lookup(arg->compat_allocator_tbl, (st_data_t)allocator, &data)) {
         marshal_compat_t *compat = (marshal_compat_t*)data;
         VALUE real_obj = rb_obj_alloc(klass);
         VALUE obj = rb_obj_alloc(compat->oldclass);
@@ -1612,6 +1614,7 @@
     arg.offset = 0;
     arg.compat_tbl = st_init_numtable();
     arg.compat_tbl_wrapper = Data_Wrap_Struct(rb_cData, rb_mark_tbl, 0, arg.compat_tbl);
+    arg.compat_allocator_tbl = DATA_PTR(rb_compat_allocator_tbl);
 
     major = r_byte(&arg);
     minor = r_byte(&arg);
@@ -1695,10 +1698,8 @@
     rb_define_const(rb_mMarshal, "MAJOR_VERSION", INT2FIX(MARSHAL_MAJOR));
     rb_define_const(rb_mMarshal, "MINOR_VERSION", INT2FIX(MARSHAL_MINOR));
 
-    compat_allocator_tbl = st_init_numtable();
-    rb_gc_register_address(&compat_allocator_tbl_wrapper);
-    compat_allocator_tbl_wrapper =
-	Data_Wrap_Struct(rb_cData, mark_marshal_compat_t, 0, compat_allocator_tbl);
+    rb_compat_allocator_tbl =
+	Data_Wrap_Struct(rb_cData, mark_marshal_compat_t, 0, st_init_numtable());
 }
 
 VALUE
Index: mvm/rational.c
===================================================================
--- mvm/rational.c	(revision 17908)
+++ mvm/rational.c	(revision 17909)
@@ -24,8 +24,6 @@
 #define ONE INT2FIX(1)
 #define TWO INT2FIX(2)
 
-VALUE rb_cRational;
-
 static ID id_Unify, id_abs, id_cmp, id_convert, id_equal_p,
   id_expt, id_floor, id_format, id_idiv, id_inspect, id_negate, id_new,
   id_new_bang, id_to_f, id_to_i, id_to_s, id_truncate;
Index: mvm/file.c
===================================================================
--- mvm/file.c	(revision 17908)
+++ mvm/file.c	(revision 17909)
@@ -24,6 +24,7 @@
 #include "ruby/signal.h"
 #include "ruby/util.h"
 #include "dln.h"
+#include "private_object.h"
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
@@ -94,10 +95,6 @@
 #define fchown be_fchown
 #endif /* __BEOS__ */
 
-VALUE rb_cFile;
-VALUE rb_mFileTest;
-VALUE rb_cStat;
-
 static VALUE
 rb_get_path_check(VALUE obj, int check)
 {
@@ -4328,8 +4325,6 @@
     return Qfalse;
 }
 
-VALUE rb_mFConst;
-
 void
 rb_file_const(const char *name, VALUE value)
 {

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

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