[macruby-changes] [216] MacRuby/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Sat May 24 00:55:27 PDT 2008
Revision: 216
http://trac.macosforge.org/projects/ruby/changeset/216
Author: lsansonetti at apple.com
Date: 2008-05-24 00:55:26 -0700 (Sat, 24 May 2008)
Log Message:
-----------
fixing memory leaks after bs parsing and when setting generic ivars (#23)
Modified Paths:
--------------
MacRuby/trunk/bs.c
MacRuby/trunk/gc.c
MacRuby/trunk/hash.c
MacRuby/trunk/include/ruby/intern.h
MacRuby/trunk/objc.m
MacRuby/trunk/variable.c
Modified: MacRuby/trunk/bs.c
===================================================================
--- MacRuby/trunk/bs.c 2008-05-24 04:54:44 UTC (rev 215)
+++ MacRuby/trunk/bs.c 2008-05-24 07:55:26 UTC (rev 216)
@@ -694,6 +694,8 @@
case BS_XML_INFORMAL_PROTOCOL:
{
+ if (protocol_name != NULL)
+ free(protocol_name);
protocol_name = get_attribute(reader, "name");
CHECK_ATTRIBUTE(protocol_name, "name");
break;
@@ -825,6 +827,9 @@
func_ptr = bs_arg->function_pointer;
func_ptr_arg_depth = xmlTextReaderDepth(reader);
}
+ else {
+ bs_arg->function_pointer = NULL;
+ }
}
else {
BAIL("argument defined outside of a " \
@@ -897,6 +902,9 @@
func_ptr = bs_retval->function_pointer;
func_ptr_arg_depth = xmlTextReaderDepth(reader);
}
+ else {
+ bs_retval->function_pointer = NULL;
+ }
}
else {
BAIL("return value defined outside a function/method");
@@ -926,7 +934,7 @@
bs_informal_method->class_method =
get_boolean_attribute(reader, "class_method", false);
bs_informal_method->type = method_type;
- bs_informal_method->protocol_name = protocol_name;
+ bs_informal_method->protocol_name = strdup(protocol_name);
bs_element = bs_informal_method;
bs_element_type = BS_ELEMENT_INFORMAL_PROTOCOL_METHOD;
@@ -942,6 +950,7 @@
ASSERT_ALLOC(method);
method->name = sel_registerName(selector);
+ free(selector);
method->class_method =
get_boolean_attribute(reader, "class_method", false);
method->variadic =
@@ -1083,6 +1092,9 @@
success = true;
bails:
+ if (protocol_name != NULL)
+ free(protocol_name);
+
xmlFreeTextReader(reader);
return success;
@@ -1108,10 +1120,165 @@
return status;
}
+#define SAFE_FREE(x) do { if ((x) != NULL) free(x); } while (0)
+
+static void bs_free_retval(bs_element_retval_t *bs_retval);
+static void bs_free_arg(bs_element_arg_t *bs_arg);
+
+static void
+bs_free_function_pointer(bs_element_function_pointer_t *bs_func_ptr)
+{
+ if (bs_func_ptr != NULL) {
+ unsigned i;
+ for (i = 0; i < bs_func_ptr->args_count; i++)
+ bs_free_arg(&bs_func_ptr->args[i]);
+ SAFE_FREE(bs_func_ptr->args);
+ bs_free_retval(bs_func_ptr->retval);
+ SAFE_FREE(bs_func_ptr);
+ }
+}
+
+static void
+bs_free_retval(bs_element_retval_t *bs_retval)
+{
+ if (bs_retval == NULL)
+ return;
+ SAFE_FREE(bs_retval->type);
+ bs_free_function_pointer(bs_retval->function_pointer);
+}
+
+static void
+bs_free_arg(bs_element_arg_t *bs_arg)
+{
+ SAFE_FREE(bs_arg->type);
+ SAFE_FREE(bs_arg->sel_of_type);
+ bs_free_function_pointer(bs_arg->function_pointer);
+}
+
+static void
+bs_free_method(bs_element_method_t *bs_method)
+{
+ unsigned i;
+ for (i = 0; i < bs_method->args_count; i++)
+ bs_free_arg(&bs_method->args[i]);
+ SAFE_FREE(bs_method->args);
+ bs_free_retval(bs_method->retval);
+ SAFE_FREE(bs_method->suggestion);
+}
+
void
bs_element_free(bs_element_type_t type, void *value)
{
- /* TODO */
+ assert(value != NULL);
+
+ switch (type) {
+ case BS_ELEMENT_STRUCT:
+ {
+ bs_element_struct_t *bs_struct = (bs_element_struct_t *)value;
+ unsigned i;
+ SAFE_FREE(bs_struct->name);
+ SAFE_FREE(bs_struct->type);
+ for (i = 0; i < bs_struct->fields_count; i++) {
+ SAFE_FREE(bs_struct->fields[i].name);
+ SAFE_FREE(bs_struct->fields[i].type);
+ }
+ SAFE_FREE(bs_struct->fields);
+ break;
+ }
+
+ case BS_ELEMENT_CFTYPE:
+ {
+ bs_element_cftype_t *bs_cftype = (bs_element_cftype_t *)value;
+ SAFE_FREE(bs_cftype->name);
+ SAFE_FREE(bs_cftype->type);
+ SAFE_FREE(bs_cftype->tollfree);
+ break;
+ }
+
+ case BS_ELEMENT_OPAQUE:
+ {
+ bs_element_opaque_t *bs_opaque = (bs_element_opaque_t *)value;
+ SAFE_FREE(bs_opaque->name);
+ SAFE_FREE(bs_opaque->type);
+ break;
+ }
+
+ case BS_ELEMENT_CONSTANT:
+ {
+ bs_element_constant_t *bs_const = (bs_element_constant_t *)value;
+ SAFE_FREE(bs_const->name);
+ SAFE_FREE(bs_const->type);
+ SAFE_FREE(bs_const->suggestion);
+ break;
+ }
+
+ case BS_ELEMENT_STRING_CONSTANT:
+ {
+ bs_element_string_constant_t *bs_str_const =
+ (bs_element_string_constant_t *)value;
+ SAFE_FREE(bs_str_const->name);
+ SAFE_FREE(bs_str_const->value);
+ break;
+ }
+
+ case BS_ELEMENT_ENUM:
+ {
+ bs_element_enum_t *bs_enum = (bs_element_enum_t *)value;
+ SAFE_FREE(bs_enum->name);
+ SAFE_FREE(bs_enum->value);
+ SAFE_FREE(bs_enum->suggestion);
+ break;
+ }
+
+ case BS_ELEMENT_FUNCTION:
+ {
+ unsigned i;
+ bs_element_function_t *bs_func = (bs_element_function_t *)value;
+ free(bs_func->name);
+ for (i = 0; i < bs_func->args_count; i++)
+ bs_free_arg(&bs_func->args[i]);
+ SAFE_FREE(bs_func->args);
+ bs_free_retval(bs_func->retval);
+ break;
+ }
+
+ case BS_ELEMENT_FUNCTION_ALIAS:
+ {
+ bs_element_function_alias_t *bs_func_alias =
+ (bs_element_function_alias_t *)value;
+ SAFE_FREE(bs_func_alias->name);
+ SAFE_FREE(bs_func_alias->original);
+ break;
+ }
+
+ case BS_ELEMENT_CLASS:
+ {
+ bs_element_class_t *bs_class = (bs_element_class_t *)value;
+ unsigned i;
+ free(bs_class->name);
+ for (i = 0; i < bs_class->class_methods_count; i++)
+ bs_free_method(&bs_class->class_methods[i]);
+ SAFE_FREE(bs_class->class_methods);
+ for (i = 0; i < bs_class->instance_methods_count; i++)
+ bs_free_method(&bs_class->instance_methods[i]);
+ SAFE_FREE(bs_class->instance_methods);
+ break;
+ }
+
+ case BS_ELEMENT_INFORMAL_PROTOCOL_METHOD:
+ {
+ bs_element_informal_protocol_method_t *bs_iprotm =
+ (bs_element_informal_protocol_method_t *)value;
+ SAFE_FREE(bs_iprotm->protocol_name);
+ SAFE_FREE(bs_iprotm->type);
+ break;
+ }
+
+ default:
+ fprintf(stderr, "unknown value %p of type %d passed to bs_free()",
+ value, type);
+ }
+ free(value);
}
#if 0
Modified: MacRuby/trunk/gc.c
===================================================================
--- MacRuby/trunk/gc.c 2008-05-24 04:54:44 UTC (rev 215)
+++ MacRuby/trunk/gc.c 2008-05-24 07:55:26 UTC (rev 216)
@@ -2923,12 +2923,14 @@
if (rb_objc_is_non_native((VALUE)obj)) {
static SEL sel = NULL;
rb_objc_remove_keys(obj);
+ rb_free_generic_ivar((VALUE)obj, true);
if (sel == NULL)
sel = sel_registerName("finalize");
objc_msgSend(obj, sel);
}
else {
- /* TODO: call ObjectSpace finalizers, if any */
+ if (FL_TEST(obj, FL_EXIVAR))
+ rb_free_generic_ivar((VALUE)obj, false);
}
}
Modified: MacRuby/trunk/hash.c
===================================================================
--- MacRuby/trunk/hash.c 2008-05-24 04:54:44 UTC (rev 215)
+++ MacRuby/trunk/hash.c 2008-05-24 07:55:26 UTC (rev 216)
@@ -263,14 +263,14 @@
return (CFHashCode)rb_any_hash((VALUE)v);
}
-static const void *
+const void *
rb_cfdictionary_retain_cb(CFAllocatorRef allocator, const void *v)
{
rb_objc_retain(v);
return v;
}
-static void
+void
rb_cfdictionary_release_cb(CFAllocatorRef allocator, const void *v)
{
rb_objc_release(v);
Modified: MacRuby/trunk/include/ruby/intern.h
===================================================================
--- MacRuby/trunk/include/ruby/intern.h 2008-05-24 04:54:44 UTC (rev 215)
+++ MacRuby/trunk/include/ruby/intern.h 2008-05-24 07:55:26 UTC (rev 216)
@@ -656,7 +656,7 @@
void rb_copy_generic_ivar(VALUE,VALUE);
void rb_mark_generic_ivar(VALUE);
void rb_mark_generic_ivar_tbl(void);
-void rb_free_generic_ivar(VALUE);
+void rb_free_generic_ivar(VALUE,bool);
VALUE rb_ivar_get(VALUE, ID);
VALUE rb_ivar_set(VALUE, ID, VALUE);
VALUE rb_ivar_defined(VALUE, ID);
Modified: MacRuby/trunk/objc.m
===================================================================
--- MacRuby/trunk/objc.m 2008-05-24 04:54:44 UTC (rev 215)
+++ MacRuby/trunk/objc.m 2008-05-24 07:55:26 UTC (rev 216)
@@ -2109,6 +2109,7 @@
case BS_ELEMENT_STRUCT:
{
setup_bs_boxed_type(type, value);
+ do_not_free = true;
break;
}
@@ -2121,7 +2122,7 @@
bs_class_new = (bs_element_indexed_class_t *)
malloc(sizeof(bs_element_indexed_class_t));
- bs_class_new->name = strdup(bs_class->name);
+ bs_class_new->name = bs_class->name;
#define INDEX_METHODS(table, ary, len) \
do { \
@@ -2150,6 +2151,8 @@
st_insert(bs_classes, (st_data_t)bs_class_new->name,
(st_data_t)bs_class_new);
+ free(bs_class);
+ do_not_free = true;
break;
}
@@ -2164,6 +2167,9 @@
st_insert(t, (st_data_t)bs_inf_prot_method->name,
(st_data_t)bs_inf_prot_method->type);
+ free(bs_inf_prot_method->protocol_name);
+ free(bs_inf_prot_method);
+ do_not_free = true;
break;
}
@@ -2172,6 +2178,7 @@
bs_element_cftype_t *bs_cftype = (bs_element_cftype_t *)value;
st_insert(bs_cftypes, (st_data_t)bs_cftype->type,
(st_data_t)bs_cftype);
+ do_not_free = true;
break;
}
}
Modified: MacRuby/trunk/variable.c
===================================================================
--- MacRuby/trunk/variable.c 2008-05-24 04:54:44 UTC (rev 215)
+++ MacRuby/trunk/variable.c 2008-05-24 07:55:26 UTC (rev 216)
@@ -784,23 +784,48 @@
entry1->var = entry2->var;
}
+#if WITH_OBJC
+static CFMutableDictionaryRef generic_iv_dict = NULL;
+const void * rb_cfdictionary_retain_cb(CFAllocatorRef, const void *);
+void rb_cfdictionary_release_cb(CFAllocatorRef, const void *);
+#else
static int special_generic_ivar = 0;
static st_table *generic_iv_tbl;
+#endif
st_table*
rb_generic_ivar_table(VALUE obj)
{
+#if WITH_OBJC
+ return NULL;
+#else
st_data_t tbl;
if (!FL_TEST(obj, FL_EXIVAR)) return 0;
if (!generic_iv_tbl) return 0;
if (!st_lookup(generic_iv_tbl, obj, &tbl)) return 0;
return (st_table *)tbl;
+#endif
}
static VALUE
generic_ivar_get(VALUE obj, ID id, int warn)
{
+#if WITH_OBJC
+ if (generic_iv_dict != NULL) {
+ CFDictionaryRef obj_dict;
+
+ if (CFDictionaryGetValueIfPresent(generic_iv_dict,
+ (const void *)obj, (const void **)&obj_dict)
+ && obj_dict != NULL) {
+ VALUE val;
+
+ if (CFDictionaryGetValueIfPresent(obj_dict, (const void *)id,
+ (const void **)&val))
+ return val;
+ }
+ }
+#else
st_data_t tbl;
VALUE val;
@@ -811,6 +836,7 @@
}
}
}
+#endif
if (warn) {
rb_warning("instance variable %s not initialized", rb_id2name(id));
}
@@ -818,8 +844,45 @@
}
static void
-generic_ivar_set(VALUE obj, ID id, VALUE val)
+generic_ivar_set(VALUE obj, ID id, VALUE val, int pure)
{
+#if WITH_OBJC
+ CFMutableDictionaryRef obj_dict;
+
+ if (rb_special_const_p(obj)) {
+ if (rb_obj_frozen_p(obj))
+ rb_error_frozen("object");
+ }
+ if (generic_iv_dict == NULL) {
+ CFDictionaryValueCallBacks values_cb;
+
+ memset(&values_cb, 0, sizeof(values_cb));
+ values_cb.retain = rb_cfdictionary_retain_cb;
+ values_cb.release = rb_cfdictionary_release_cb;
+
+ generic_iv_dict = CFDictionaryCreateMutable(NULL, 0, NULL, &values_cb);
+ obj_dict = NULL;
+ }
+ else {
+ obj_dict = (CFMutableDictionaryRef)CFDictionaryGetValue(
+ (CFDictionaryRef)generic_iv_dict, (const void *)obj);
+ }
+ if (obj_dict == NULL) {
+ CFDictionaryValueCallBacks values_cb;
+
+ memset(&values_cb, 0, sizeof(values_cb));
+ values_cb.retain = rb_cfdictionary_retain_cb;
+ values_cb.release = rb_cfdictionary_release_cb;
+
+ obj_dict = CFDictionaryCreateMutable(NULL, 0, NULL, &values_cb);
+ CFDictionarySetValue(generic_iv_dict, (const void *)obj,
+ (const void *)obj_dict);
+ CFMakeCollectable(obj_dict);
+ }
+ if (!pure)
+ FL_SET(obj, FL_EXIVAR);
+ CFDictionarySetValue(obj_dict, (const void *)id, (const void *)val);
+#else
st_table *tbl;
st_data_t data;
@@ -839,11 +902,24 @@
return;
}
st_insert((st_table *)data, id, val);
+#endif
}
static VALUE
generic_ivar_defined(VALUE obj, ID id)
{
+#if WITH_OBJC
+ CFMutableDictionaryRef obj_dict;
+
+ if (generic_iv_dict != NULL
+ && CFDictionaryGetValueIfPresent((CFDictionaryRef)generic_iv_dict,
+ (const void *)obj, (const void **)&obj_dict) && obj_dict != NULL) {
+ if (CFDictionaryGetValueIfPresent(obj_dict, (const void *)id, NULL))
+ return Qtrue;
+ }
+ return Qfalse;
+
+#else
st_table *tbl;
st_data_t data;
VALUE val;
@@ -855,11 +931,33 @@
return Qtrue;
}
return Qfalse;
+#endif
}
static int
generic_ivar_remove(VALUE obj, ID id, VALUE *valp)
{
+#if WITH_OBJC
+ CFMutableDictionaryRef obj_dict;
+ VALUE val;
+
+ if (generic_iv_dict == NULL)
+ return 0;
+
+ obj_dict = (CFMutableDictionaryRef)CFDictionaryGetValue(
+ (CFDictionaryRef)generic_iv_dict, (const void *)obj);
+ if (obj_dict == NULL)
+ return 0;
+
+ if (CFDictionaryGetValueIfPresent(obj_dict, (const void *)id,
+ (const void **)&val)) {
+ *valp = val;
+ CFDictionaryRemoveValue(obj_dict, (const void *)id);
+ return 1;
+ }
+
+ return 0;
+#else
st_table *tbl;
st_data_t data;
int status;
@@ -873,8 +971,10 @@
st_free_table((st_table *)data);
}
return status;
+#endif
}
+#if !WITH_OBJC
void
rb_mark_generic_ivar(VALUE obj)
{
@@ -909,20 +1009,59 @@
if (special_generic_ivar == 0) return;
st_foreach_safe(generic_iv_tbl, givar_i, 0);
}
+#endif
void
-rb_free_generic_ivar(VALUE obj)
+rb_free_generic_ivar(VALUE obj, bool lookup)
{
+#if WITH_OBJC
+ if (generic_iv_dict != NULL) {
+ if (lookup) {
+ if (CFDictionaryGetValueIfPresent(generic_iv_dict,
+ (const void *)obj, NULL)) {
+ CFDictionaryReplaceValue(generic_iv_dict, (const void *)obj,
+ NULL);
+ }
+ }
+ else {
+ CFDictionaryRemoveValue(generic_iv_dict, (const void *)obj);
+ }
+ }
+#else
st_data_t tbl;
if (!generic_iv_tbl) return;
if (st_delete(generic_iv_tbl, &obj, &tbl))
st_free_table((st_table *)tbl);
+#endif
}
void
rb_copy_generic_ivar(VALUE clone, VALUE obj)
{
+#if WITH_OBJC
+ CFMutableDictionaryRef obj_dict;
+ CFMutableDictionaryRef clone_dict;
+ VALUE val;
+
+ if (generic_iv_dict == NULL)
+ return;
+
+ obj_dict = (CFMutableDictionaryRef)CFDictionaryGetValue(
+ (CFDictionaryRef)generic_iv_dict, (const void *)obj);
+ if (obj_dict == NULL)
+ return;
+
+ if (CFDictionaryGetValueIfPresent((CFDictionaryRef)generic_iv_dict,
+ (const void *)clone, (const void **)&clone_dict)
+ && clone_dict != NULL)
+ CFDictionaryRemoveValue(generic_iv_dict, (const void *)clone);
+
+ clone_dict = CFDictionaryCreateMutableCopy(NULL, 0, obj_dict);
+ CFDictionarySetValue(generic_iv_dict, (const void *)clone,
+ (const void *)clone_dict);
+ CFMakeCollectable(clone_dict);
+#else
st_data_t data;
if (!generic_iv_tbl) return;
@@ -949,6 +1088,7 @@
FL_SET(clone, FL_EXIVAR);
}
}
+#endif
}
static VALUE
@@ -1012,16 +1152,15 @@
long i, len;
int ivar_extended;
+ if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
+ rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
+ if (OBJ_FROZEN(obj)) rb_error_frozen("object");
#if WITH_OBJC
if (rb_objc_is_non_native(obj)) {
- generic_ivar_set(obj, id, val);
+ generic_ivar_set(obj, id, val, 1);
return val;
}
#endif
-
- if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
- rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
- if (OBJ_FROZEN(obj)) rb_error_frozen("object");
switch (TYPE(obj)) {
case T_OBJECT:
iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
@@ -1082,7 +1221,7 @@
st_insert(RCLASS_IV_TBL(obj), id, val);
break;
default:
- generic_ivar_set(obj, id, val);
+ generic_ivar_set(obj, id, val, 0);
break;
}
return val;
@@ -1094,6 +1233,9 @@
VALUE val;
struct st_table *iv_index_tbl;
st_data_t index;
+ if (rb_objc_is_non_native(obj)) {
+ return generic_ivar_defined(obj, id);
+ }
switch (TYPE(obj)) {
case T_OBJECT:
iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
@@ -1155,29 +1297,39 @@
void rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg)
{
#if WITH_OBJC
- if (!rb_objc_is_non_native(obj))
+ if (rb_objc_is_non_native(obj))
+ goto generic;
#endif
switch (TYPE(obj)) {
case T_OBJECT:
obj_ivar_each(obj, func, arg);
- break;
+ return;
case T_CLASS:
case T_MODULE:
if (RCLASS_IV_TBL(obj)) {
st_foreach_safe(RCLASS_IV_TBL(obj), func, arg);
}
- break;
- default:
- if (!generic_iv_tbl) break;
- if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
- st_data_t tbl;
+ return;
+ }
+generic:
+#if WITH_OBJC
+ if (generic_iv_dict != NULL) {
+ CFDictionaryRef obj_dict;
- if (st_lookup(generic_iv_tbl, obj, &tbl)) {
- st_foreach_safe((st_table *)tbl, func, arg);
- }
+ obj_dict = (CFDictionaryRef)CFDictionaryGetValue((CFDictionaryRef)generic_iv_dict, (const void *)obj);
+ if (obj_dict != NULL)
+ CFDictionaryApplyFunction(obj_dict, (CFDictionaryApplierFunction)func, (void *)arg);
+ }
+#else
+ if (!generic_iv_tbl) break;
+ if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
+ st_data_t tbl;
+
+ if (st_lookup(generic_iv_tbl, obj, &tbl)) {
+ st_foreach_safe((st_table *)tbl, func, arg);
}
- break;
}
+#endif
}
static int
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macruby-changes/attachments/20080524/a7cb16cd/attachment-0001.htm
More information about the macruby-changes
mailing list