summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog44
-rw-r--r--array.c34
-rw-r--r--class.c49
-rw-r--r--compile.c2
-rw-r--r--encoding.c2
-rw-r--r--enum.c6
-rw-r--r--error.c2
-rw-r--r--eval.c9
-rw-r--r--ext/coverage/coverage.c2
-rw-r--r--ext/readline/readline.c4
-rw-r--r--ext/socket/ancdata.c2
-rw-r--r--ext/socket/init.c4
-rw-r--r--ext/zlib/zlib.c16
-rw-r--r--file.c8
-rw-r--r--gc.c6
-rw-r--r--hash.c4
-rw-r--r--include/ruby/ruby.h7
-rw-r--r--internal.h25
-rw-r--r--io.c6
-rw-r--r--iseq.c2
-rw-r--r--marshal.c2
-rw-r--r--object.c21
-rw-r--r--parse.y8
-rw-r--r--proc.c2
-rw-r--r--process.c2
-rw-r--r--random.c2
-rw-r--r--ruby.c6
-rw-r--r--sprintf.c8
-rw-r--r--string.c6
-rw-r--r--thread.c2
-rw-r--r--transcode.c2
-rw-r--r--vm.c2
-rw-r--r--vm_eval.c2
-rw-r--r--win32/file.c3
34 files changed, 190 insertions, 112 deletions
diff --git a/ChangeLog b/ChangeLog
index b8bf4f0..351565b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,47 @@
+Mon May 13 19:29:54 2013 Koichi Sasada <ko1@atdot.net>
+
+ * include/ruby/ruby.h: constify RBasic::klass and add
+ RBASIC_CLASS(obj) macro which returns a class of `obj'.
+ This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
+
+ * object.c: add new function rb_obj_reveal().
+ This function reveal interal (hidden) object by rb_obj_hide().
+ Note that do not change class before and after hiding.
+ Only permitted example is:
+ klass = RBASIC_CLASS(obj);
+ rb_obj_hide(obj);
+ ....
+ rb_obj_reveal(obj, klass);
+
+ TODO: API design. rb_obj_reveal() should be replaced with others.
+
+ TODO: modify constified variables using cast may be harmful for
+ compiler's analysis and optimizaton.
+ Any idea to prohibt inserting RBasic::klass directly?
+ If rename RBasic::klass and force to use RBASIC_CLASS(obj),
+ then all codes such as `RBASIC(obj)->klass' will be
+ compilation error. Is it acceptable? (We have similar
+ experience at Ruby 1.9,
+ for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
+
+ * internal.h: add some macros.
+ * RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
+ object.
+ * RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
+ * RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
+ without write barrier (planned).
+ * RCLASS_SET_SUPER(a, b) set super class of a.
+
+ * array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
+ file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
+ parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
+ string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
+ Use above macros and functions to access RBasic::klass.
+
+ * ext/coverage/coverage.c, ext/readline/readline.c,
+ ext/socket/ancdata.c, ext/socket/init.c,
+ * ext/zlib/zlib.c: ditto.
+
Mon May 13 18:44:14 2013 Koichi Sasada <ko1@atdot.net>
* *.c, parse.y, insns.def: use RARRAY_AREF/ASET macro
diff --git a/array.c b/array.c
index 47ff7ac..f605af2 100644
--- a/array.c
+++ b/array.c
@@ -2297,7 +2297,7 @@ rb_ary_sort_bang(VALUE ary)
struct ary_sort_data data;
long len = RARRAY_LEN(ary);
- RBASIC(tmp)->klass = 0;
+ RBASIC_CLEAR_CLASS(tmp);
data.ary = tmp;
data.opt_methods = 0;
data.opt_inited = 0;
@@ -2343,7 +2343,7 @@ rb_ary_sort_bang(VALUE ary)
FL_SET(tmp, FL_FREEZE);
}
/* tmp will be GC'ed. */
- RBASIC(tmp)->klass = rb_cArray;
+ RBASIC_SET_CLASS_RAW(tmp, rb_cArray); /* rb_cArray must be marked */
}
return ary;
}
@@ -2896,7 +2896,7 @@ rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
}
if (len == 0) return rb_ary_new2(0);
arg2 = rb_ary_new4(len, RARRAY_PTR(ary)+pos);
- RBASIC(arg2)->klass = rb_obj_class(ary);
+ RBASIC_SET_CLASS(arg2, rb_obj_class(ary));
rb_ary_splice(ary, pos, len, Qundef);
return arg2;
}
@@ -3755,7 +3755,7 @@ ary_tmp_hash_new(void)
{
VALUE hash = rb_hash_new();
- RBASIC(hash)->klass = 0;
+ RBASIC_CLEAR_CLASS(hash);
return hash;
}
@@ -4192,7 +4192,7 @@ flatten(VALUE ary, int level, int *modified)
st_free_table(memo);
- RBASIC(result)->klass = rb_class_of(ary);
+ RBASIC_SET_CLASS(result, rb_class_of(ary));
return result;
}
@@ -4461,7 +4461,7 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary)
else {
VALUE *ptr_result;
result = rb_ary_new4(len, ptr);
- RBASIC(result)->klass = 0;
+ RBASIC_CLEAR_CLASS(result);
ptr_result = RARRAY_PTR(result);
RB_GC_GUARD(ary);
for (i=0; i<n; i++) {
@@ -4470,7 +4470,7 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary)
ptr_result[j] = ptr_result[i];
ptr_result[i] = nv;
}
- RBASIC(result)->klass = rb_cArray;
+ RBASIC_SET_CLASS_RAW(result, rb_cArray);
}
ARY_SET_LEN(result, n);
@@ -4538,9 +4538,9 @@ rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
}
#define tmpbuf(n, size) rb_str_tmp_new((n)*(size))
-#define tmpbuf_discard(s) (rb_str_resize((s), 0L), RBASIC(s)->klass = rb_cString)
+#define tmpbuf_discard(s) (rb_str_resize((s), 0L), RBASIC_SET_CLASS_RAW(s, rb_cString))
#define tmpary(n) rb_ary_tmp_new(n)
-#define tmpary_discard(a) (ary_discard(a), RBASIC(a)->klass = rb_cArray)
+#define tmpary_discard(a) (ary_discard(a), RBASIC_SET_CLASS_RAW(a, rb_cArray))
/*
* Recursively compute permutations of +r+ elements of the set
@@ -4679,14 +4679,14 @@ rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
volatile VALUE t1 = tmpbuf(n,sizeof(char));
char *used = (char*)RSTRING_PTR(t1);
VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
- RBASIC(ary0)->klass = 0;
+ RBASIC_CLEAR_CLASS(ary0);
MEMZERO(used, char, n); /* initialize array */
permute0(n, r, p, 0, used, ary0); /* compute and yield permutations */
tmpbuf_discard(t0);
tmpbuf_discard(t1);
- RBASIC(ary0)->klass = rb_cArray;
+ RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
}
return ary;
}
@@ -4874,11 +4874,11 @@ rb_ary_repeated_permutation(VALUE ary, VALUE num)
volatile VALUE t0 = tmpbuf(r, sizeof(long));
long *p = (long*)RSTRING_PTR(t0);
VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
- RBASIC(ary0)->klass = 0;
+ RBASIC_CLEAR_CLASS(ary0);
rpermute0(n, r, p, 0, ary0); /* compute and yield repeated permutations */
tmpbuf_discard(t0);
- RBASIC(ary0)->klass = rb_cArray;
+ RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
}
return ary;
}
@@ -4971,11 +4971,11 @@ rb_ary_repeated_combination(VALUE ary, VALUE num)
volatile VALUE t0 = tmpbuf(n, sizeof(long));
long *p = (long*)RSTRING_PTR(t0);
VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
- RBASIC(ary0)->klass = 0;
+ RBASIC_CLEAR_CLASS(ary0);
rcombinate0(len, n, p, 0, n, ary0); /* compute and yield repeated combinations */
tmpbuf_discard(t0);
- RBASIC(ary0)->klass = rb_cArray;
+ RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
}
return ary;
}
@@ -5013,8 +5013,8 @@ rb_ary_product(int argc, VALUE *argv, VALUE ary)
long i,j;
long resultlen = 1;
- RBASIC(t0)->klass = 0;
- RBASIC(t1)->klass = 0;
+ RBASIC_CLEAR_CLASS(t0);
+ RBASIC_CLEAR_CLASS(t1);
/* initialize the arrays of arrays */
ARY_SET_LEN(t0, n);
diff --git a/class.c b/class.c
index a37a153..eeca410 100644
--- a/class.c
+++ b/class.c
@@ -54,7 +54,7 @@ class_alloc(VALUE flags, VALUE klass)
RCLASS_IV_TBL(obj) = 0;
RCLASS_CONST_TBL(obj) = 0;
RCLASS_M_TBL(obj) = 0;
- RCLASS_SUPER(obj) = 0;
+ RCLASS_SET_SUPER((VALUE)obj, 0);
RCLASS_ORIGIN(obj) = (VALUE)obj;
RCLASS_IV_INDEX_TBL(obj) = 0;
RCLASS_REFINED_CLASS(obj) = Qnil;
@@ -77,7 +77,7 @@ rb_class_boot(VALUE super)
{
VALUE klass = class_alloc(T_CLASS, rb_cClass);
- RCLASS_SUPER(klass) = super;
+ RCLASS_SET_SUPER(klass, super);
RCLASS_M_TBL(klass) = st_init_numtable();
OBJ_INFECT(klass, super);
@@ -200,10 +200,10 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
}
rb_obj_init_copy(clone, orig);
if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
- RBASIC(clone)->klass = rb_singleton_class_clone(orig);
+ RBASIC_SET_CLASS(clone, rb_singleton_class_clone(orig));
rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
}
- RCLASS_SUPER(clone) = RCLASS_SUPER(orig);
+ RCLASS_SET_SUPER(clone, RCLASS_SUPER(orig));
RCLASS_EXT(clone)->allocator = RCLASS_EXT(orig)->allocator;
if (RCLASS_IV_TBL(orig)) {
st_data_t id;
@@ -255,13 +255,13 @@ rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach)
VALUE clone = class_alloc(RBASIC(klass)->flags, 0);
if (BUILTIN_TYPE(obj) == T_CLASS) {
- RBASIC(clone)->klass = clone;
+ RBASIC_SET_CLASS(clone, clone);
}
else {
- RBASIC(clone)->klass = rb_singleton_class_clone(klass);
+ RBASIC_SET_CLASS(clone, rb_singleton_class_clone(klass));
}
- RCLASS_SUPER(clone) = RCLASS_SUPER(klass);
+ RCLASS_SET_SUPER(clone, RCLASS_SUPER(klass));
RCLASS_EXT(clone)->allocator = RCLASS_EXT(klass)->allocator;
if (RCLASS_IV_TBL(klass)) {
RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(klass));
@@ -299,6 +299,7 @@ rb_singleton_class_attached(VALUE klass, VALUE obj)
#define METACLASS_OF(k) RBASIC(k)->klass
+#define SET_METACLASS_OF(k, cls) RBASIC_SET_CLASS(k, cls)
/*!
* whether k is a meta^(n)-class of Class class
@@ -346,17 +347,18 @@ make_metaclass(VALUE klass)
rb_singleton_class_attached(metaclass, klass);
if (META_CLASS_OF_CLASS_CLASS_P(klass)) {
- METACLASS_OF(klass) = METACLASS_OF(metaclass) = metaclass;
+ SET_METACLASS_OF(klass, metaclass);
+ SET_METACLASS_OF(metaclass, metaclass);
}
else {
VALUE tmp = METACLASS_OF(klass); /* for a meta^(n)-class klass, tmp is meta^(n)-class of Class class */
- METACLASS_OF(klass) = metaclass;
- METACLASS_OF(metaclass) = ENSURE_EIGENCLASS(tmp);
+ SET_METACLASS_OF(klass, metaclass);
+ SET_METACLASS_OF(metaclass, ENSURE_EIGENCLASS(tmp));
}
super = RCLASS_SUPER(klass);
while (RB_TYPE_P(super, T_ICLASS)) super = RCLASS_SUPER(super);
- RCLASS_SUPER(metaclass) = super ? ENSURE_EIGENCLASS(super) : rb_cClass;
+ RCLASS_SET_SUPER(metaclass, super ? ENSURE_EIGENCLASS(super) : rb_cClass);
OBJ_INFECT(metaclass, RCLASS_SUPER(metaclass));
@@ -376,10 +378,10 @@ make_singleton_class(VALUE obj)
VALUE klass = rb_class_boot(orig_class);
FL_SET(klass, FL_SINGLETON);
- RBASIC(obj)->klass = klass;
+ RBASIC_SET_CLASS(obj, klass);
rb_singleton_class_attached(klass, obj);
- METACLASS_OF(klass) = METACLASS_OF(rb_class_real(orig_class));
+ SET_METACLASS_OF(klass, METACLASS_OF(rb_class_real(orig_class)));
return klass;
}
@@ -406,11 +408,10 @@ Init_class_hierarchy(void)
rb_cClass = boot_defclass("Class", rb_cModule);
rb_const_set(rb_cObject, rb_intern("BasicObject"), rb_cBasicObject);
- RBASIC(rb_cClass)->klass
- = RBASIC(rb_cModule)->klass
- = RBASIC(rb_cObject)->klass
- = RBASIC(rb_cBasicObject)->klass
- = rb_cClass;
+ RBASIC_SET_CLASS(rb_cClass, rb_cClass);
+ RBASIC_SET_CLASS(rb_cModule, rb_cClass);
+ RBASIC_SET_CLASS(rb_cObject, rb_cClass);
+ RBASIC_SET_CLASS(rb_cBasicObject, rb_cClass);
}
@@ -674,12 +675,12 @@ rb_include_class_new(VALUE module, VALUE super)
RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module);
RCLASS_M_TBL(klass) = RCLASS_M_TBL(RCLASS_ORIGIN(module));
- RCLASS_SUPER(klass) = super;
+ RCLASS_SET_SUPER(klass, super);
if (RB_TYPE_P(module, T_ICLASS)) {
- RBASIC(klass)->klass = RBASIC(module)->klass;
+ RBASIC_SET_CLASS(klass, RBASIC(module)->klass);
}
else {
- RBASIC(klass)->klass = module;
+ RBASIC_SET_CLASS(klass, module);
}
OBJ_INFECT(klass, module);
OBJ_INFECT(klass, super);
@@ -748,7 +749,7 @@ include_modules_at(const VALUE klass, VALUE c, VALUE module)
break;
}
}
- c = RCLASS_SUPER(c) = rb_include_class_new(module, RCLASS_SUPER(c));
+ c = RCLASS_SET_SUPER(c, rb_include_class_new(module, RCLASS_SUPER(c)));
if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) {
VALUE refined_class =
rb_refinement_module_get_refined_class(klass);
@@ -812,8 +813,8 @@ rb_prepend_module(VALUE klass, VALUE module)
origin = RCLASS_ORIGIN(klass);
if (origin == klass) {
origin = class_alloc(T_ICLASS, klass);
- RCLASS_SUPER(origin) = RCLASS_SUPER(klass);
- RCLASS_SUPER(klass) = origin;
+ RCLASS_SET_SUPER(origin, RCLASS_SUPER(klass));
+ RCLASS_SET_SUPER(klass, origin);
RCLASS_ORIGIN(klass) = origin;
RCLASS_M_TBL(origin) = RCLASS_M_TBL(klass);
RCLASS_M_TBL(klass) = st_init_numtable();
diff --git a/compile.c b/compile.c
index 1a911f1..c079c03 100644
--- a/compile.c
+++ b/compile.c
@@ -299,7 +299,7 @@ r_value(VALUE value)
#define INIT_ANCHOR(name) \
(name##_body__.last = &name##_body__.anchor, name = &name##_body__)
-#define hide_obj(obj) do {OBJ_FREEZE(obj); RBASIC(obj)->klass = 0;} while (0)
+#define hide_obj(obj) do {OBJ_FREEZE(obj); RBASIC_CLEAR_CLASS(obj);} while (0)
#include "optinsn.inc"
#if OPT_INSTRUCTIONS_UNIFICATION
diff --git a/encoding.c b/encoding.c
index 3d89d52..a9a2244 100644
--- a/encoding.c
+++ b/encoding.c
@@ -1866,7 +1866,7 @@ Init_Encoding(void)
rb_define_singleton_method(rb_cEncoding, "locale_charmap", rb_locale_charmap, 0);
list = rb_ary_new2(enc_table.count);
- RBASIC(list)->klass = 0;
+ RBASIC_CLEAR_CLASS(list);
rb_encoding_list = list;
rb_gc_register_mark_object(list);
diff --git a/enum.c b/enum.c
index cd03f41..1a30897 100644
--- a/enum.c
+++ b/enum.c
@@ -931,7 +931,7 @@ enum_sort_by(VALUE obj)
else {
ary = rb_ary_new();
}
- RBASIC(ary)->klass = 0;
+ RBASIC_CLEAR_CLASS(ary);
buf = rb_ary_tmp_new(SORT_BY_BUFSIZE*2);
rb_ary_store(buf, SORT_BY_BUFSIZE*2-1, Qnil);
memo = NEW_MEMO(0, 0, 0);
@@ -958,7 +958,7 @@ enum_sort_by(VALUE obj)
RARRAY_ASET(ary, i/2, RARRAY_AREF(ary, i));
}
rb_ary_resize(ary, RARRAY_LEN(ary)/2);
- RBASIC(ary)->klass = rb_cArray;
+ RBASIC_SET_CLASS_RAW(ary, rb_cArray);
OBJ_INFECT(ary, memo);
return ary;
@@ -2309,7 +2309,7 @@ enum_cycle(int argc, VALUE *argv, VALUE obj)
if (n <= 0) return Qnil;
}
ary = rb_ary_new();
- RBASIC(ary)->klass = 0;
+ RBASIC_CLEAR_CLASS(ary);
rb_block_call(obj, id_each, 0, 0, cycle_i, ary);
len = RARRAY_LEN(ary);
if (len == 0) return Qnil;
diff --git a/error.c b/error.c
index 2dbcd81..ea8c3cf 100644
--- a/error.c
+++ b/error.c
@@ -1261,7 +1261,7 @@ syserr_initialize(int argc, VALUE *argv, VALUE self)
if (!RB_TYPE_P(self, T_OBJECT)) { /* insurance to avoid type crash */
rb_raise(rb_eTypeError, "invalid instance type");
}
- RBASIC(self)->klass = klass;
+ RBASIC_SET_CLASS(self, klass);
}
}
else {
diff --git a/eval.c b/eval.c
index 3880a0e..53d6d14 100644
--- a/eval.c
+++ b/eval.c
@@ -1060,7 +1060,7 @@ hidden_identity_hash_new()
VALUE hash = rb_hash_new();
rb_funcall(hash, rb_intern("compare_by_identity"), 0);
- RBASIC(hash)->klass = 0; /* hide from ObjectSpace */
+ RBASIC_CLEAR_CLASS(hash); /* hide from ObjectSpace */
return hash;
}
@@ -1097,7 +1097,7 @@ rb_using_refinement(NODE *cref, VALUE klass, VALUE module)
module = RCLASS_SUPER(module);
while (module && module != klass) {
FL_SET(module, RMODULE_IS_OVERLAID);
- c = RCLASS_SUPER(c) = rb_include_class_new(module, RCLASS_SUPER(c));
+ c = RCLASS_SET_SUPER(c, rb_include_class_new(module, RCLASS_SUPER(c)));
RCLASS_REFINED_CLASS(c) = klass;
module = RCLASS_SUPER(module);
}
@@ -1156,8 +1156,7 @@ add_activated_refinement(VALUE activated_refinements,
refinement = RCLASS_SUPER(refinement);
while (refinement) {
FL_SET(refinement, RMODULE_IS_OVERLAID);
- c = RCLASS_SUPER(c) =
- rb_include_class_new(refinement, RCLASS_SUPER(c));
+ c = RCLASS_SET_SUPER(c, rb_include_class_new(refinement, RCLASS_SUPER(c)));
RCLASS_REFINED_CLASS(c) = klass;
refinement = RCLASS_SUPER(refinement);
}
@@ -1210,7 +1209,7 @@ rb_mod_refine(VALUE module, VALUE klass)
refinement = rb_hash_lookup(refinements, klass);
if (NIL_P(refinement)) {
refinement = rb_module_new();
- RCLASS_SUPER(refinement) = klass;
+ RCLASS_SET_SUPER(refinement, klass);
FL_SET(refinement, RMODULE_IS_REFINEMENT);
CONST_ID(id_refined_class, "__refined_class__");
rb_ivar_set(refinement, id_refined_class, klass);
diff --git a/ext/coverage/coverage.c b/ext/coverage/coverage.c
index d2cdb35..93cb2a5 100644
--- a/ext/coverage/coverage.c
+++ b/ext/coverage/coverage.c
@@ -25,7 +25,7 @@ rb_coverage_start(VALUE klass)
if (!RTEST(rb_get_coverages())) {
if (rb_coverages == Qundef) {
rb_coverages = rb_hash_new();
- RBASIC(rb_coverages)->klass = 0;
+ rb_obj_hide(rb_coverages);
}
rb_set_coverages(rb_coverages);
}
diff --git a/ext/readline/readline.c b/ext/readline/readline.c
index fe5c723..a4c51c6 100644
--- a/ext/readline/readline.c
+++ b/ext/readline/readline.c
@@ -1217,7 +1217,7 @@ readline_s_set_special_prefixes(VALUE self, VALUE str)
if (!NIL_P(str)) {
OutputStringValue(str);
str = rb_str_dup_frozen(str);
- RBASIC(str)->klass = 0;
+ rb_obj_hide(str);
}
rb_ivar_set(mReadline, id_special_prefixes, str);
if (NIL_P(str)) {
@@ -1252,7 +1252,7 @@ readline_s_get_special_prefixes(VALUE self)
str = rb_ivar_get(mReadline, id_special_prefixes);
if (!NIL_P(str)) {
str = rb_str_dup_frozen(str);
- RBASIC(str)->klass = rb_cString;
+ rb_obj_reveal(str, rb_cString);
}
return str;
}
diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c
index 3e6431e..7fe9659 100644
--- a/ext/socket/ancdata.c
+++ b/ext/socket/ancdata.c
@@ -1677,7 +1677,7 @@ bsock_recvmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock)
else {
rb_str_resize(dat_str, ss);
OBJ_TAINT(dat_str);
- RBASIC(dat_str)->klass = rb_cString;
+ rb_obj_reveal(dat_str, rb_cString);
}
ret = rb_ary_new3(3, dat_str,
diff --git a/ext/socket/init.c b/ext/socket/init.c
index a5ffe7b..6d98a66 100644
--- a/ext/socket/init.c
+++ b/ext/socket/init.c
@@ -132,7 +132,7 @@ rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
arg.str = str = rb_tainted_str_new(0, buflen);
klass = RBASIC(str)->klass;
- RBASIC(str)->klass = 0;
+ rb_obj_hide(str);
while (rb_io_check_closed(fptr),
rb_thread_wait_fd(arg.fd),
@@ -145,7 +145,7 @@ rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
}
}
- RBASIC(str)->klass = klass;
+ rb_obj_reveal(str, klass);
if (slen < RSTRING_LEN(str)) {
rb_str_set_len(str, slen);
}
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index 64a3e69..db153e3 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -633,7 +633,7 @@ zstream_expand_buffer(struct zstream *z)
VALUE self = (VALUE)z->stream.opaque;
rb_str_resize(z->buf, z->buf_filled);
- RBASIC(z->buf)->klass = rb_cString;
+ rb_obj_reveal(z->buf, rb_cString);
OBJ_INFECT(z->buf, self);
rb_protect(rb_yield, z->buf, &state);
@@ -678,7 +678,7 @@ zstream_expand_buffer_into(struct zstream *z, unsigned long size)
z->buf_filled = 0;
z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf);
z->stream.avail_out = MAX_UINT(size);
- RBASIC(z->buf)->klass = 0;
+ rb_obj_hide(z->buf);
}
else if (z->stream.avail_out != size) {
rb_str_resize(z->buf, z->buf_filled + size);
@@ -740,7 +740,7 @@ zstream_append_buffer(struct zstream *z, const Bytef *src, long len)
z->buf_filled = len;
z->stream.next_out = (Bytef*)RSTRING_PTR(z->buf);
z->stream.avail_out = 0;
- RBASIC(z->buf)->klass = 0;
+ rb_obj_hide(z->buf);
return;
}
@@ -782,7 +782,7 @@ zstream_detach_buffer(struct zstream *z)
else {
dst = z->buf;
rb_str_resize(dst, z->buf_filled);
- RBASIC(dst)->klass = rb_cString;
+ rb_obj_reveal(dst, rb_cString);
}
OBJ_INFECT(dst, self);
@@ -811,7 +811,7 @@ zstream_shift_buffer(struct zstream *z, long len)
}
dst = rb_str_subseq(z->buf, 0, len);
- RBASIC(dst)->klass = rb_cString;
+ rb_obj_reveal(dst, rb_cString);
z->buf_filled -= len;
memmove(RSTRING_PTR(z->buf), RSTRING_PTR(z->buf) + len,
z->buf_filled);
@@ -866,7 +866,7 @@ zstream_append_input(struct zstream *z, const Bytef *src, long len)
if (NIL_P(z->input)) {
z->input = rb_str_buf_new(len);
rb_str_buf_cat(z->input, (const char*)src, len);
- RBASIC(z->input)->klass = 0;
+ rb_obj_hide(z->input);
}
else {
rb_str_buf_cat(z->input, (const char*)src, len);
@@ -915,10 +915,10 @@ zstream_detach_input(struct zstream *z)
}
else {
dst = z->input;
- RBASIC(dst)->klass = rb_cString;
+ rb_obj_reveal(dst, rb_cString);
}
z->input = Qnil;
- RBASIC(dst)->klass = rb_cString;
+ rb_obj_reveal(dst, rb_cString);
return dst;
}
diff --git a/file.c b/file.c
index 55d4792..2628cb5 100644
--- a/file.c
+++ b/file.c
@@ -4013,7 +4013,7 @@ rb_file_join(VALUE ary, VALUE sep)
len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
}
result = rb_str_buf_new(len);
- RBASIC(result)->klass = 0;
+ RBASIC_CLEAR_CLASS(result);
OBJ_INFECT(result, ary);
for (i=0; i<RARRAY_LEN(ary); i++) {
tmp = RARRAY_AREF(ary, i);
@@ -4057,7 +4057,7 @@ rb_file_join(VALUE ary, VALUE sep)
rb_str_buf_append(result, tmp);
rb_enc_associate(result, enc);
}
- RBASIC(result)->klass = rb_cString;
+ RBASIC_SET_CLASS_RAW(result, rb_cString);
return result;
}
@@ -5304,7 +5304,7 @@ is_explicit_relative(const char *path)
static VALUE
copy_path_class(VALUE path, VALUE orig)
{
- RBASIC(path)->klass = rb_obj_class(orig);
+ RBASIC_SET_CLASS(path, rb_obj_class(orig));
OBJ_FREEZE(path);
return path;
}
@@ -5360,7 +5360,7 @@ rb_find_file_ext_safe(VALUE *filep, const char *const *ext, int safe_level)
if (!load_path) return 0;
fname = rb_str_dup(*filep);
- RBASIC(fname)->klass = 0;
+ RBASIC_CLEAR_CLASS(fname);
fnlen = RSTRING_LEN(fname);
tmp = rb_str_tmp_new(MAXPATHLEN + 2);
rb_enc_associate_index(tmp, rb_usascii_encindex());
diff --git a/gc.c b/gc.c
index 8283e58..679a727 100644
--- a/gc.c
+++ b/gc.c
@@ -1330,7 +1330,7 @@ define_final0(VALUE obj, VALUE block)
}
else {
table = rb_ary_new3(1, block);
- RBASIC(table)->klass = 0;
+ RBASIC_CLEAR_CLASS(table);
st_add_direct(finalizer_table, obj, table);
}
return block;
@@ -1405,7 +1405,7 @@ run_final(rb_objspace_t *objspace, VALUE obj)
objspace->heap.final_num--;
- RBASIC(obj)->klass = 0;
+ RBASIC_CLEAR_CLASS(obj);
if (RTYPEDDATA_P(obj)) {
free_func = RTYPEDDATA_TYPE(obj)->function.dfree;
@@ -2796,7 +2796,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr)
if (!RCLASS_EXT(obj)) break;
mark_tbl(objspace, RCLASS_IV_TBL(obj));
mark_const_tbl(objspace, RCLASS_CONST_TBL(obj));
- ptr = RCLASS_SUPER(obj);
+ ptr = RCLASS_SUPER((VALUE)obj);
goto again;
case T_ARRAY:
diff --git a/hash.c b/hash.c
index e990f53..f51da37 100644
--- a/hash.c
+++ b/hash.c
@@ -2708,7 +2708,7 @@ env_reject_bang(VALUE ehash)
RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
keys = env_keys(); /* rb_secure(4); */
- RBASIC(keys)->klass = 0;
+ RBASIC_CLEAR_CLASS(keys);
for (i=0; i<RARRAY_LEN(keys); i++) {
VALUE val = rb_f_getenv(Qnil, RARRAY_AREF(keys, i));
if (!NIL_P(val)) {
@@ -2812,7 +2812,7 @@ env_select_bang(VALUE ehash)
RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
keys = env_keys(); /* rb_secure(4); */
- RBASIC(keys)->klass = 0;
+ RBASIC_CLEAR_CLASS(keys);
for (i=0; i<RARRAY_LEN(keys); i++) {
VALUE val = rb_f_getenv(Qnil, RARRAY_AREF(keys, i));
if (!NIL_P(val)) {
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index e860336..562e7b0 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -683,13 +683,18 @@ VALUE rb_obj_setup(VALUE obj, VALUE klass, VALUE type);
struct RBasic {
VALUE flags;
- VALUE klass;
+ const VALUE klass;
}
#ifdef __GNUC__
__attribute__((aligned(sizeof(VALUE))))
#endif
;
+VALUE rb_obj_hide(VALUE obj);
+VALUE rb_obj_reveal(VALUE obj, VALUE klass); /* do not use this API to change klass information */
+
+#define RBASIC_CLASS(obj) (RBASIC(obj)->klass)
+
#define ROBJECT_EMBED_LEN_MAX 3
struct RObject {
struct RBasic basic;
diff --git a/internal.h b/internal.h
index 89a0e3e..6f2091c 100644
--- a/internal.h
+++ b/internal.h
@@ -64,9 +64,7 @@ struct rb_classext_struct {
rb_alloc_func_t allocator;
};
-#undef RCLASS_SUPER
#define RCLASS_EXT(c) (RCLASS(c)->ptr)
-#define RCLASS_SUPER(c) (RCLASS_EXT(c)->super)
#define RCLASS_IV_TBL(c) (RCLASS_EXT(c)->iv_tbl)
#define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl)
#define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
@@ -74,6 +72,19 @@ struct rb_classext_struct {
#define RCLASS_ORIGIN(c) (RCLASS_EXT(c)->origin)
#define RCLASS_REFINED_CLASS(c) (RCLASS_EXT(c)->refined_class)
+#undef RCLASS_SUPER
+static inline VALUE
+RCLASS_SUPER(VALUE c)
+{
+ return RCLASS_EXT(c)->super;
+}
+
+static inline VALUE
+RCLASS_SET_SUPER(VALUE a, VALUE b) {
+ RCLASS_EXT(a)->super = b;
+ return b;
+}
+
struct vtm; /* defined by timev.h */
/* array.c */
@@ -220,7 +231,15 @@ VALUE rb_int_pred(VALUE num);
/* object.c */
VALUE rb_obj_equal(VALUE obj1, VALUE obj2);
-VALUE rb_obj_hide(VALUE obj);
+
+struct RBasicRaw {
+ VALUE flags;
+ VALUE klass;
+};
+
+#define RBASIC_CLEAR_CLASS(obj) (((struct RBasicRaw *)((VALUE)(obj)))->klass = 0)
+#define RBASIC_SET_CLASS_RAW(obj, cls) (((struct RBasicRaw *)((VALUE)(obj)))->klass = (cls))
+#define RBASIC_SET_CLASS(obj, cls) do {((struct RBasicRaw *)(obj))->klass = cls; } while (0)
/* parse.y */
VALUE rb_parser_get_yydebug(VALUE);
diff --git a/io.c b/io.c
index 1aa043e..b5aa6c6 100644
--- a/io.c
+++ b/io.c
@@ -6061,7 +6061,7 @@ rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
}
#endif
tmp = rb_ary_dup(tmp);
- RBASIC(tmp)->klass = 0;
+ RBASIC_CLEAR_CLASS(tmp);
execarg_obj = rb_execarg_new((int)len, RARRAY_PTR(tmp), FALSE);
rb_ary_clear(tmp);
}
@@ -6091,7 +6091,7 @@ rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
}
return Qnil;
}
- RBASIC(port)->klass = klass;
+ RBASIC_SET_CLASS(port, klass);
if (rb_block_given_p()) {
return rb_ensure(rb_yield, port, io_close, port);
}
@@ -6487,7 +6487,7 @@ io_reopen(VALUE io, VALUE nfile)
rb_io_binmode(io);
}
- RBASIC(io)->klass = rb_obj_class(nfile);
+ RBASIC_SET_CLASS(io, rb_obj_class(nfile));
return io;
}
diff --git a/iseq.c b/iseq.c
index 1e32bc3..a7f5097 100644
--- a/iseq.c
+++ b/iseq.c
@@ -246,7 +246,7 @@ rb_iseq_add_mark_object(rb_iseq_t *iseq, VALUE obj)
if (!RTEST(iseq->mark_ary)) {
iseq->mark_ary = rb_ary_tmp_new(3);
OBJ_UNTRUST(iseq->mark_ary);
- RBASIC(iseq->mark_ary)->klass = 0;
+ RBASIC_CLEAR_CLASS(iseq->mark_ary);
}
rb_ary_push(iseq->mark_ary, obj);
}
diff --git a/marshal.c b/marshal.c
index 79fd948..c948a1d 100644
--- a/marshal.c
+++ b/marshal.c
@@ -1554,7 +1554,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
if (TYPE(v) != TYPE(tmp)) goto format_error;
}
- RBASIC(v)->klass = c;
+ RBASIC_SET_CLASS(v, c);
}
break;
diff --git a/object.c b/object.c
index d999c8c..e15d89f 100644
--- a/object.c
+++ b/object.c
@@ -53,7 +53,16 @@ VALUE
rb_obj_hide(VALUE obj)
{
if (!SPECIAL_CONST_P(obj)) {
- RBASIC(obj)->klass = 0;
+ RBASIC_CLEAR_CLASS(obj);
+ }
+ return obj;
+}
+
+VALUE
+rb_obj_reveal(VALUE obj, VALUE klass)
+{
+ if (!SPECIAL_CONST_P(obj)) {
+ RBASIC_SET_CLASS(obj, klass);
}
return obj;
}
@@ -62,7 +71,7 @@ VALUE
rb_obj_setup(VALUE obj, VALUE klass, VALUE type)
{
RBASIC(obj)->flags = type;
- RBASIC(obj)->klass = klass;
+ RBASIC_SET_CLASS(obj, klass);
if (rb_safe_level() >= 3) FL_SET((obj), FL_TAINT | FL_UNTRUSTED);
return obj;
}
@@ -327,7 +336,7 @@ rb_obj_clone(VALUE obj)
}
clone = rb_obj_alloc(rb_obj_class(obj));
singleton = rb_singleton_class_clone_and_attach(obj, clone);
- RBASIC(clone)->klass = singleton;
+ RBASIC_SET_CLASS(clone, singleton);
if (FL_TEST(singleton, FL_SINGLETON)) {
rb_singleton_class_attached(singleton, clone);
}
@@ -1630,7 +1639,7 @@ rb_module_s_alloc(VALUE klass)
{
VALUE mod = rb_module_new();
- RBASIC(mod)->klass = klass;
+ RBASIC_SET_CLASS(mod, klass);
return mod;
}
@@ -1723,7 +1732,7 @@ rb_class_initialize(int argc, VALUE *argv, VALUE klass)
rb_raise(rb_eTypeError, "can't inherit uninitialized class");
}
}
- RCLASS_SUPER(klass) = super;
+ RCLASS_SET_SUPER(klass, super);
rb_make_metaclass(klass, RBASIC(super)->klass);
rb_class_inherited(super, klass);
rb_mod_initialize(klass);
@@ -1858,7 +1867,7 @@ rb_class_superclass(VALUE klass)
VALUE
rb_class_get_superclass(VALUE klass)
{
- return RCLASS_SUPER(klass);
+ return RCLASS_EXT(klass)->super;
}
#define id_for_setter(name, type, message) \
diff --git a/parse.y b/parse.y
index c866497..b02de5c 100644
--- a/parse.y
+++ b/parse.y
@@ -5298,7 +5298,7 @@ coverage(const char *f, int n)
VALUE fname = rb_external_str_new_with_enc(f, strlen(f), rb_filesystem_encoding());
VALUE lines = rb_ary_new2(n);
int i;
- RBASIC(lines)->klass = 0;
+ RBASIC_CLEAR_CLASS(lines);
for (i = 0; i < n; i++) RARRAY_ASET(lines, i, Qnil);
RARRAY(lines)->as.heap.len = n;
rb_hash_aset(coverages, fname, lines);
@@ -10238,7 +10238,7 @@ static VALUE
setup_fake_str(struct RString *fake_str, const char *name, long len)
{
fake_str->basic.flags = T_STRING|RSTRING_NOEMBED;
- fake_str->basic.klass = rb_cString;
+ RBASIC_SET_CLASS((VALUE)fake_str, rb_cString);
fake_str->as.heap.len = len;
fake_str->as.heap.ptr = (char *)name;
fake_str->as.heap.aux.capa = len;
@@ -10426,7 +10426,7 @@ rb_id2str(ID id)
if (st_lookup(global_symbols.id_str, id, &data)) {
VALUE str = (VALUE)data;
if (RBASIC(str)->klass == 0)
- RBASIC(str)->klass = rb_cString;
+ RBASIC_SET_CLASS_RAW(str, rb_cString);
return str;
}
@@ -10444,7 +10444,7 @@ rb_id2str(ID id)
if (st_lookup(global_symbols.id_str, id, &data)) {
VALUE str = (VALUE)data;
if (RBASIC(str)->klass == 0)
- RBASIC(str)->klass = rb_cString;
+ RBASIC_SET_CLASS_RAW(str, rb_cString);
return str;
}
}
diff --git a/proc.c b/proc.c
index f4ce838..32b7ef8 100644
--- a/proc.c
+++ b/proc.c
@@ -427,7 +427,7 @@ proc_new(VALUE klass, int is_lambda)
}
else {
VALUE newprocval = proc_dup(procval);
- RBASIC(newprocval)->klass = klass;
+ RBASIC_SET_CLASS(newprocval, klass);
return newprocval;
}
}
diff --git a/process.c b/process.c
index f741d28..afb2885 100644
--- a/process.c
+++ b/process.c
@@ -1435,7 +1435,7 @@ proc_spawn_sh(char *str)
static VALUE
hide_obj(VALUE obj)
{
- RBASIC(obj)->klass = 0;
+ RBASIC_CLEAR_CLASS(obj);
return obj;
}
diff --git a/random.c b/random.c
index 8f8a7f3..cb5fd57 100644
--- a/random.c
+++ b/random.c
@@ -1435,7 +1435,7 @@ Init_RandomSeed2(void)
VALUE seed = default_rand.seed;
if (RB_TYPE_P(seed, T_BIGNUM)) {
- RBASIC(seed)->klass = rb_cBignum;
+ rb_obj_reveal(seed, rb_cBignum);
}
}
diff --git a/ruby.c b/ruby.c
index fc29887..669e802 100644
--- a/ruby.c
+++ b/ruby.c
@@ -542,10 +542,10 @@ add_modules(VALUE *req_list, const char *mod)
if (!list) {
*req_list = list = rb_ary_new();
- RBASIC(list)->klass = 0;
+ RBASIC_CLEAR_CLASS(list);
}
feature = rb_str_new2(mod);
- RBASIC(feature)->klass = 0;
+ RBASIC_CLEAR_CLASS(feature);
rb_ary_push(list, feature);
}
@@ -565,7 +565,7 @@ require_libraries(VALUE *req_list)
while (list && RARRAY_LEN(list) > 0) {
VALUE feature = rb_ary_shift(list);
rb_enc_associate(feature, extenc);
- RBASIC(feature)->klass = rb_cString;
+ RBASIC_SET_CLASS_RAW(feature, rb_cString);
OBJ_FREEZE(feature);
rb_funcall2(self, require, 1, &feature);
}
diff --git a/sprintf.c b/sprintf.c
index 77fd7bc..c818eb5 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -1239,12 +1239,12 @@ rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
}
f._bf._base = (unsigned char *)result;
f._p = (unsigned char *)RSTRING_PTR(result);
- RBASIC(result)->klass = 0;
+ RBASIC_CLEAR_CLASS(result);
f.vwrite = ruby__sfvwrite;
f.vextra = ruby__sfvextra;
buffer.value = 0;
BSD_vfprintf(&f, fmt, ap);
- RBASIC(result)->klass = rb_cString;
+ RBASIC_SET_CLASS_RAW(result, rb_cString);
rb_str_resize(result, (char *)f._p - RSTRING_PTR(result));
#undef f
@@ -1298,12 +1298,12 @@ rb_str_vcatf(VALUE str, const char *fmt, va_list ap)
f._bf._base = (unsigned char *)str;
f._p = (unsigned char *)RSTRING_END(str);
klass = RBASIC(str)->klass;
- RBASIC(str)->klass = 0;
+ RBASIC_CLEAR_CLASS(str);
f.vwrite = ruby__sfvwrite;
f.vextra = ruby__sfvextra;
buffer.value = 0;
BSD_vfprintf(&f, fmt, ap);
- RBASIC(str)->klass = klass;
+ RBASIC_SET_CLASS_RAW(str, klass);
rb_str_resize(str, (char *)f._p - RSTRING_PTR(str));
#undef f
diff --git a/string.c b/string.c
index 11e974e..b6adfef 100644
--- a/string.c
+++ b/string.c
@@ -519,7 +519,7 @@ rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags,
olen = len;
econv_wrapper = rb_obj_alloc(rb_cEncodingConverter);
- RBASIC(econv_wrapper)->klass = 0;
+ RBASIC_CLEAR_CLASS(econv_wrapper);
ec = rb_econv_open_opts(from->name, to->name, ecflags, ecopts);
if (!ec) return str;
DATA_PTR(econv_wrapper) = ec;
@@ -1446,7 +1446,7 @@ rb_str_associate(VALUE str, VALUE add)
RESIZE_CAPA(str, RSTRING_LEN(str));
}
FL_SET(str, STR_ASSOC);
- RBASIC(add)->klass = 0;
+ RBASIC_CLEAR_CLASS(add);
RSTRING(str)->as.heap.aux.shared = add;
}
}
@@ -3931,7 +3931,7 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang)
rb_str_shared_replace(str, dest);
}
else {
- RBASIC(dest)->klass = rb_obj_class(str);
+ RBASIC_SET_CLASS(dest, rb_obj_class(str));
OBJ_INFECT(dest, str);
str = dest;
}
diff --git a/thread.c b/thread.c
index f1f3e30..c2edb7e 100644
--- a/thread.c
+++ b/thread.c
@@ -622,7 +622,7 @@ thread_create_core(VALUE thval, VALUE args, VALUE (*fn)(ANYARGS))
th->pending_interrupt_queue = rb_ary_tmp_new(0);
th->pending_interrupt_queue_checked = 0;
th->pending_interrupt_mask_stack = rb_ary_dup(current_th->pending_interrupt_mask_stack);
- RBASIC(th->pending_interrupt_mask_stack)->klass = 0;
+ RBASIC_CLEAR_CLASS(th->pending_interrupt_mask_stack);
th->interrupt_mask = 0;
diff --git a/transcode.c b/transcode.c
index 58a4265..badb846 100644
--- a/transcode.c
+++ b/transcode.c
@@ -2892,7 +2892,7 @@ encoded_dup(VALUE newstr, VALUE str, int encidx)
return newstr;
}
else {
- RBASIC(newstr)->klass = rb_obj_class(str);
+ RBASIC_SET_CLASS(newstr, rb_obj_class(str));
}
return str_encode_associate(newstr, encidx);
}
diff --git a/vm.c b/vm.c
index bd38d2d..c8124a3 100644
--- a/vm.c
+++ b/vm.c
@@ -1730,7 +1730,7 @@ vm_init2(rb_vm_t *vm)
MEMZERO(vm, rb_vm_t, 1);
vm->src_encoding_index = -1;
vm->at_exit.basic.flags = (T_ARRAY | RARRAY_EMBED_FLAG) & ~RARRAY_EMBED_LEN_MASK; /* len set 0 */
- vm->at_exit.basic.klass = 0;
+ rb_obj_hide((VALUE)&vm->at_exit);
vm_default_params_setup(vm);
}
diff --git a/vm_eval.c b/vm_eval.c
index 7b8aafe..783bbfe 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -750,7 +750,7 @@ rb_apply(VALUE recv, ID mid, VALUE args)
argc = RARRAY_LENINT(args);
if (argc >= 0x100) {
args = rb_ary_subseq(args, 0, argc);
- RBASIC(args)->klass = 0;
+ RBASIC_CLEAR_CLASS(args);
OBJ_FREEZE(args);
ret = rb_call(recv, mid, argc, RARRAY_PTR(args), CALL_FCALL);
RB_GC_GUARD(args);
diff --git a/win32/file.c b/win32/file.c
index 96fe61b..78e7331 100644
--- a/win32/file.c
+++ b/win32/file.c
@@ -1,5 +1,6 @@
#include "ruby/ruby.h"
#include "ruby/encoding.h"
+#include "internal.h"
#include <winbase.h>
#include <wchar.h>
#include <shlwapi.h>
@@ -193,7 +194,7 @@ code_page(rb_encoding *enc)
enc_name = (char *)rb_enc_name(enc);
fake_str.basic.flags = T_STRING|RSTRING_NOEMBED;
- fake_str.basic.klass = rb_cString;
+ RBASIC_SET_CLASS_RAW((VALUE)&fake_str, rb_cString);
fake_str.as.heap.len = strlen(enc_name);
fake_str.as.heap.ptr = enc_name;
fake_str.as.heap.aux.capa = fake_str.as.heap.len;