mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Replace the implementation of method tables in classes/modules.
They are basically the copy of instance variable tables. On my Linux box, memory consumption of `mrbtest` measured by `valgrind` is: - old: 17,683,830 bytes - new: 14,283,749 bytes
This commit is contained in:
+1
-190
@@ -218,191 +218,6 @@ mrb_obj_class_m(mrb_state *mrb, mrb_value self)
|
||||
return mrb_obj_value(mrb_obj_class(mrb, self));
|
||||
}
|
||||
|
||||
static struct RClass*
|
||||
mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj)
|
||||
{
|
||||
struct RClass *klass = mrb_basic_ptr(obj)->c;
|
||||
|
||||
if (klass->tt != MRB_TT_SCLASS)
|
||||
return klass;
|
||||
else {
|
||||
/* copy singleton(unnamed) class */
|
||||
struct RClass *clone = (struct RClass*)mrb_obj_alloc(mrb, klass->tt, mrb->class_class);
|
||||
|
||||
switch (mrb_type(obj)) {
|
||||
case MRB_TT_CLASS:
|
||||
case MRB_TT_SCLASS:
|
||||
break;
|
||||
default:
|
||||
clone->c = mrb_singleton_class_clone(mrb, mrb_obj_value(klass));
|
||||
break;
|
||||
}
|
||||
clone->super = klass->super;
|
||||
if (klass->iv) {
|
||||
mrb_iv_copy(mrb, mrb_obj_value(clone), mrb_obj_value(klass));
|
||||
mrb_obj_iv_set(mrb, (struct RObject*)clone, MRB_SYM(__attached__), obj);
|
||||
}
|
||||
if (klass->mt) {
|
||||
clone->mt = kh_copy(mt, mrb, klass->mt);
|
||||
}
|
||||
else {
|
||||
clone->mt = kh_init(mt, mrb);
|
||||
}
|
||||
clone->tt = MRB_TT_SCLASS;
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
copy_class(mrb_state *mrb, mrb_value dst, mrb_value src)
|
||||
{
|
||||
struct RClass *dc = mrb_class_ptr(dst);
|
||||
struct RClass *sc = mrb_class_ptr(src);
|
||||
/* if the origin is not the same as the class, then the origin and
|
||||
the current class need to be copied */
|
||||
if (sc->flags & MRB_FL_CLASS_IS_PREPENDED) {
|
||||
struct RClass *c0 = sc->super;
|
||||
struct RClass *c1 = dc;
|
||||
|
||||
/* copy prepended iclasses */
|
||||
while (!(c0->flags & MRB_FL_CLASS_IS_ORIGIN)) {
|
||||
c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0)));
|
||||
c1 = c1->super;
|
||||
c0 = c0->super;
|
||||
}
|
||||
c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0)));
|
||||
c1->super->flags |= MRB_FL_CLASS_IS_ORIGIN;
|
||||
}
|
||||
if (sc->mt) {
|
||||
dc->mt = kh_copy(mt, mrb, sc->mt);
|
||||
}
|
||||
else {
|
||||
dc->mt = kh_init(mt, mrb);
|
||||
}
|
||||
dc->super = sc->super;
|
||||
MRB_SET_INSTANCE_TT(dc, MRB_INSTANCE_TT(sc));
|
||||
}
|
||||
|
||||
static mrb_value mrb_obj_init_copy(mrb_state *mrb, mrb_value self);
|
||||
|
||||
static void
|
||||
init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj)
|
||||
{
|
||||
switch (mrb_type(obj)) {
|
||||
case MRB_TT_ICLASS:
|
||||
copy_class(mrb, dest, obj);
|
||||
return;
|
||||
case MRB_TT_CLASS:
|
||||
case MRB_TT_MODULE:
|
||||
copy_class(mrb, dest, obj);
|
||||
mrb_iv_copy(mrb, dest, obj);
|
||||
mrb_iv_remove(mrb, dest, MRB_SYM(__classname__));
|
||||
break;
|
||||
case MRB_TT_OBJECT:
|
||||
case MRB_TT_SCLASS:
|
||||
case MRB_TT_HASH:
|
||||
case MRB_TT_DATA:
|
||||
case MRB_TT_EXCEPTION:
|
||||
mrb_iv_copy(mrb, dest, obj);
|
||||
break;
|
||||
case MRB_TT_ISTRUCT:
|
||||
mrb_istruct_copy(dest, obj);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!mrb_func_basic_p(mrb, dest, MRB_SYM(initialize_copy), mrb_obj_init_copy)) {
|
||||
mrb_funcall_id(mrb, dest, MRB_SYM(initialize_copy), 1, obj);
|
||||
}
|
||||
}
|
||||
|
||||
/* 15.3.1.3.8 */
|
||||
/*
|
||||
* call-seq:
|
||||
* obj.clone -> an_object
|
||||
*
|
||||
* Produces a shallow copy of <i>obj</i>---the instance variables of
|
||||
* <i>obj</i> are copied, but not the objects they reference. Copies
|
||||
* the frozen state of <i>obj</i>. See also the discussion
|
||||
* under <code>Object#dup</code>.
|
||||
*
|
||||
* class Klass
|
||||
* attr_accessor :str
|
||||
* end
|
||||
* s1 = Klass.new #=> #<Klass:0x401b3a38>
|
||||
* s1.str = "Hello" #=> "Hello"
|
||||
* s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello">
|
||||
* s2.str[1,4] = "i" #=> "i"
|
||||
* s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">"
|
||||
* s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">"
|
||||
*
|
||||
* This method may have class-specific behavior. If so, that
|
||||
* behavior will be documented under the #+initialize_copy+ method of
|
||||
* the class.
|
||||
*
|
||||
* Some Class(True False Nil Symbol Integer Float) Object cannot clone.
|
||||
*/
|
||||
MRB_API mrb_value
|
||||
mrb_obj_clone(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct RObject *p;
|
||||
mrb_value clone;
|
||||
|
||||
if (mrb_immediate_p(self)) {
|
||||
return self;
|
||||
}
|
||||
if (mrb_sclass_p(self)) {
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "can't clone singleton class");
|
||||
}
|
||||
p = (struct RObject*)mrb_obj_alloc(mrb, mrb_type(self), mrb_obj_class(mrb, self));
|
||||
p->c = mrb_singleton_class_clone(mrb, self);
|
||||
mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)p->c);
|
||||
clone = mrb_obj_value(p);
|
||||
init_copy(mrb, clone, self);
|
||||
p->flags |= mrb_obj_ptr(self)->flags & MRB_FL_OBJ_IS_FROZEN;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/* 15.3.1.3.9 */
|
||||
/*
|
||||
* call-seq:
|
||||
* obj.dup -> an_object
|
||||
*
|
||||
* Produces a shallow copy of <i>obj</i>---the instance variables of
|
||||
* <i>obj</i> are copied, but not the objects they reference.
|
||||
* <code>dup</code> copies the frozen state of <i>obj</i>. See also
|
||||
* the discussion under <code>Object#clone</code>. In general,
|
||||
* <code>clone</code> and <code>dup</code> may have different semantics
|
||||
* in descendant classes. While <code>clone</code> is used to duplicate
|
||||
* an object, including its internal state, <code>dup</code> typically
|
||||
* uses the class of the descendant object to create the new instance.
|
||||
*
|
||||
* This method may have class-specific behavior. If so, that
|
||||
* behavior will be documented under the #+initialize_copy+ method of
|
||||
* the class.
|
||||
*/
|
||||
|
||||
MRB_API mrb_value
|
||||
mrb_obj_dup(mrb_state *mrb, mrb_value obj)
|
||||
{
|
||||
struct RBasic *p;
|
||||
mrb_value dup;
|
||||
|
||||
if (mrb_immediate_p(obj)) {
|
||||
return obj;
|
||||
}
|
||||
if (mrb_sclass_p(obj)) {
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "can't dup singleton class");
|
||||
}
|
||||
p = mrb_obj_alloc(mrb, mrb_type(obj), mrb_obj_class(mrb, obj));
|
||||
dup = mrb_obj_value(p);
|
||||
init_copy(mrb, dup, obj);
|
||||
|
||||
return dup;
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_obj_extend(mrb_state *mrb, mrb_int argc, mrb_value *argv, mrb_value obj)
|
||||
{
|
||||
@@ -493,7 +308,7 @@ mrb_obj_hash(mrb_state *mrb, mrb_value self)
|
||||
}
|
||||
|
||||
/* 15.3.1.3.16 */
|
||||
static mrb_value
|
||||
mrb_value
|
||||
mrb_obj_init_copy(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value orig = mrb_get_arg1(mrb);
|
||||
@@ -505,7 +320,6 @@ mrb_obj_init_copy(mrb_state *mrb, mrb_value self)
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
MRB_API mrb_bool
|
||||
mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c)
|
||||
{
|
||||
@@ -568,9 +382,6 @@ mrb_obj_is_kind_of_m(mrb_state *mrb, mrb_value self)
|
||||
return mrb_bool_value(mrb_obj_is_kind_of(mrb, self, c));
|
||||
}
|
||||
|
||||
KHASH_DECLARE(st, mrb_sym, char, FALSE)
|
||||
KHASH_DEFINE(st, mrb_sym, char, FALSE, kh_int_hash_func, kh_int_hash_equal)
|
||||
|
||||
/* 15.3.1.3.32 */
|
||||
/*
|
||||
* call_seq:
|
||||
|
||||
Reference in New Issue
Block a user