diff --git a/ChangeLog b/ChangeLog index ac2c7c021a..bf8c371997 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +Wed Jun 17 06:19:06 2009 Koichi Sasada + + * include/ruby/ruby.h: New structure RTypedData, added. + This structure incldues more explicit type information for + T_DATA objects. If RData(obj)->dfree is immediate value `1' on + T_DATA object obj, obj is needed to be accessed with RTYPEDDATA(obj) + instead of RDATA(obj). A RTypedData structure points the structure + rb_typed_data_t. rb_typed_data_t includes information such as the + type name of this data, mark and free function what RData includes, + and memsize function show how data consuming the memory size. + Note that you do not need any change existing T_DATA objects. + If you use RDataType instead of RData on T_DATA object, + you can specify explicit type information. + + * gc.c (rb_data_typed_object_alloc, rb_objspace_data_type_memsize, + rb_objspace_data_type_name): added. + Wed Jun 17 06:14:23 2009 Koichi Sasada * gc.c: fix indent. diff --git a/gc.c b/gc.c index 76b4053806..bb19fa38da 100644 --- a/gc.c +++ b/gc.c @@ -264,6 +264,7 @@ typedef struct RVALUE { struct RRegexp regexp; struct RHash hash; struct RData data; + struct RTypedData typeddata; struct RStruct rstruct; struct RBignum bignum; struct RFile file; @@ -1177,6 +1178,44 @@ rb_data_object_alloc(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_F return (VALUE)data; } +VALUE +rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *type) +{ + NEWOBJ(data, struct RTypedData); + + if (klass) Check_Type(klass, T_CLASS); + + OBJSETUP(data, klass, T_DATA); + + data->data = datap; + data->typed_flag = 1; + data->type = type; + + return (VALUE)data; +} + +size_t +rb_objspace_data_type_memsize(VALUE obj) +{ + if (RTYPEDDATA_P(obj)) { + return RTYPEDDATA_TYPE(obj)->dsize(RTYPEDDATA_DATA(obj)); + } + else { + return 0; + } +} + +const char * +rb_objspace_data_type_name(VALUE obj) +{ + if (RTYPEDDATA_P(obj)) { + return RTYPEDDATA_TYPE(obj)->name; + } + else { + return 0; + } +} + #ifdef __ia64 #define SET_STACK_END (SET_MACHINE_STACK_END(&th->machine_stack_end), th->machine_register_stack_end = rb_ia64_bsp()) #else @@ -1695,7 +1734,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) break; case T_DATA: + if (RTYPEDDATA_P(obj)) { + if (obj->as.typeddata.type->dmark) (*obj->as.typeddata.type->dmark)(DATA_PTR(obj)); + } + else { if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj)); + } break; case T_OBJECT: @@ -2058,6 +2102,9 @@ obj_free(rb_objspace_t *objspace, VALUE obj) break; case T_DATA: if (DATA_PTR(obj)) { + if (RTYPEDDATA_P(obj)) { + RDATA(obj)->dfree = RANY(obj)->as.typeddata.type->dfree; + } if ((long)RANY(obj)->as.data.dfree == -1) { xfree(DATA_PTR(obj)); } @@ -2652,12 +2699,19 @@ run_final(rb_objspace_t *objspace, VALUE obj) long i; int status; VALUE args[3], table, objid; + RUBY_DATA_FUNC free_func = 0; objid = rb_obj_id(obj); /* make obj into id */ RBASIC(obj)->klass = 0; - if (RDATA(obj)->dfree) { - (*RDATA(obj)->dfree)(DATA_PTR(obj)); + if (RTYPEDDATA_P(obj)) { + free_func = RTYPEDDATA_TYPE(obj)->dfree; + } + else { + free_func = RDATA(obj)->dfree; + } + if (free_func) { + (*free_func)(DATA_PTR(obj)); } if (finalizer_table && diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h index 7da0b9e908..9da3f5b9fd 100644 --- a/include/ruby/ruby.h +++ b/include/ruby/ruby.h @@ -735,14 +735,34 @@ struct RData { void *data; }; +typedef struct rb_data_type_struct { + const char *name; + void (*dmark)(void*); + void (*dfree)(void*); + size_t (*dsize)(void *); + void *ary[4]; /* for extension */ +} rb_data_type_t; + +struct RTypedData { + struct RBasic basic; + const rb_data_type_t *type; + VALUE typed_flag; /* 1 or not */ + void *data; +}; + #define DATA_PTR(dta) (RDATA(dta)->data) +#define RTYPEDDATA_P(v) (RTYPEDDATA(v)->typed_flag == 1) +#define RTYPEDDATA_TYPE(v) (RTYPEDDATA(v)->type) +#define RTYPEDDATA_DATA(v) (RTYPEDDATA(v)->data) + /* #define RUBY_DATA_FUNC(func) ((void (*)(void*))func) */ typedef void (*RUBY_DATA_FUNC)(void*); VALUE rb_data_object_alloc(VALUE,void*,RUBY_DATA_FUNC,RUBY_DATA_FUNC); +VALUE rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *); #define Data_Wrap_Struct(klass,mark,free,sval)\ rb_data_object_alloc(klass,sval,(RUBY_DATA_FUNC)mark,(RUBY_DATA_FUNC)free) @@ -753,6 +773,15 @@ VALUE rb_data_object_alloc(VALUE,void*,RUBY_DATA_FUNC,RUBY_DATA_FUNC); Data_Wrap_Struct(klass,mark,free,sval)\ ) +#define Data_Wrap_TypedStruct(klass,data_type,sval)\ + rb_data_typed_object_alloc(klass,sval,data_type) + +#define Data_Make_TypedStruct(klass, type, data_type, sval) (\ + sval = ALLOC(type),\ + memset(sval, 0, sizeof(type)),\ + Data_Wrap_TypedStruct(klass,data_type,sval)\ +) + #define Data_Get_Struct(obj,type,sval) do {\ Check_Type(obj, T_DATA); \ sval = (type*)DATA_PTR(obj);\ @@ -826,6 +855,7 @@ struct RBignum { #define RARRAY(obj) (R_CAST(RArray)(obj)) #define RHASH(obj) (R_CAST(RHash)(obj)) #define RDATA(obj) (R_CAST(RData)(obj)) +#define RTYPEDDATA(obj) (R_CAST(RTypedData)(obj)) #define RSTRUCT(obj) (R_CAST(RStruct)(obj)) #define RBIGNUM(obj) (R_CAST(RBignum)(obj)) #define RFILE(obj) (R_CAST(RFile)(obj))