diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2002-08-29 09:08:18 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2002-08-29 09:08:18 +0000 |
commit | 40bc4f5ae4ffe325c36a49e0d3280dbee2a39cee (patch) | |
tree | 834cc2146161802fb97d89f0a747ae794048169b | |
parent | 3bf972993f689965c857540ec1ccc729477e8e66 (diff) | |
download | ruby-40bc4f5ae4ffe325c36a49e0d3280dbee2a39cee.tar.gz |
* array.c (rb_ary_become): should not free ptr if it's shared.
* eval.c (rb_alias): prohibit making an alias named "allocate" if
klass is a metaclass.
* string.c (rb_string_value_ptr): StringValuePtr() should never
return NULL pointer.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2764 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | ToDo | 5 | ||||
-rw-r--r-- | array.c | 3 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | eval.c | 12 | ||||
-rw-r--r-- | file.c | 8 | ||||
-rw-r--r-- | gc.c | 2 | ||||
-rw-r--r-- | hash.c | 6 | ||||
-rw-r--r-- | lib/finalize.rb | 253 | ||||
-rw-r--r-- | marshal.c | 25 | ||||
-rw-r--r-- | re.c | 2 | ||||
-rw-r--r-- | ruby.h | 3 | ||||
-rw-r--r-- | string.c | 28 | ||||
-rw-r--r-- | struct.c | 4 |
14 files changed, 203 insertions, 164 deletions
@@ -7,6 +7,13 @@ Thu Aug 29 00:55:55 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net> * marshal.c (r_object): yield loaded objects, not intermediates. (ruby-bugs-ja:PR#296) +Thu Aug 29 00:06:54 2002 Yukihiro Matsumoto <matz@ruby-lang.org> + + * array.c (rb_ary_become): should not free ptr if it's shared. + + * eval.c (rb_alias): prohibit making an alias named "allocate" if + klass is a metaclass. + Wed Aug 28 23:59:15 2002 Michal Rokos <michal@ruby-lang.org> * signal.c: remove #ifdef SIGINT for struct signals. @@ -17,6 +24,11 @@ Wed Aug 28 23:34:32 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net> * io.c (appendline): data was lost when raw mode. +Wed Aug 28 22:57:34 2002 Yukihiro Matsumoto <matz@ruby-lang.org> + + * string.c (rb_string_value_ptr): StringValuePtr() should never + return NULL pointer. + Wed Aug 28 19:12:46 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net> * ext/stringio/stringio.c (strio_initialize): RSTRING(mode)->ptr @@ -34,7 +46,7 @@ Wed Aug 28 17:45:03 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net> Wed Aug 28 16:36:40 2002 WATANABE Hirofumi <eban@ruby-lang.org> - * configure.in (ar): don't check twice for ar. + * configure.in (ar): don't check ar twice. Wed Aug 28 15:00:29 2002 Yukihiro Matsumoto <matz@ruby-lang.org> @@ -32,10 +32,11 @@ Language Spec. * .. or something like defadvice in Emacs. * property - for methods, or for objects in general. * "in" modifier, to annotate, or to encourage assertion. -* selector namespace - something like generic-flet in CLOS, to help RubyBehevior +* selector namespace - something like generic-flet in CLOS, to help RubyBehavior * private instance variable (as in Python?) @_foo in class Foo => @_Foo_foo * warn/error "bare word" method, like "foo", you should type "foo()" * clarify evaluation order of operator argument (=~, .., ...) +* :symbol => value hash in the form of {symbol: value, ...} ?? Hacking Interpreter @@ -115,7 +116,7 @@ Extension Libraries Ruby Libraries -* add uri.rb +- add uri.rb * urllib.rb, nttplib.rb, etc. * format like perl's @@ -801,7 +801,8 @@ rb_ary_become(copy, orig) { orig = to_ary(orig); ary_make_shared(orig); - if (RARRAY(copy)->ptr) free(RARRAY(copy)->ptr); + if (RARRAY(copy)->ptr && !FL_TEST(copy, ELTS_SHARED)) + free(RARRAY(copy)->ptr); RARRAY(copy)->ptr = RARRAY(orig)->ptr; RARRAY(copy)->len = RARRAY(orig)->len; RARRAY(copy)->aux.shared = RARRAY(orig)->aux.shared; diff --git a/configure.in b/configure.in index 4553aaa9ef..357eb74314 100644 --- a/configure.in +++ b/configure.in @@ -1018,7 +1018,7 @@ case "$target_os" in CFLAGS="$CFLAGS -pipe -no-precomp" ;; darwin*) - CFLAGS="$CFLAGS -pipe -no-precomp" + CFLAGS="$CFLAGS -pipe" ;; os2_emx) CFLAGS="$CFLAGS -DOS2" @@ -1700,6 +1700,7 @@ rb_alias(klass, name, def) { VALUE origin; NODE *orig, *body; + VALUE singleton = 0; rb_frozen_class_p(klass); if (name == def) return; @@ -1715,6 +1716,12 @@ rb_alias(klass, name, def) if (!orig || !orig->nd_body) { print_undef(klass, def); } + if (FL_TEST(klass, FL_SINGLETON)) { + singleton = rb_iv_get(klass, "__attached__"); + if (name == alloc && TYPE(singleton) == T_CLASS) { + rb_raise(rb_eNameError, "cannot make alias named `allocate'"); + } + } body = orig->nd_body; orig->nd_cnt++; if (nd_type(body) == NODE_FBODY) { /* was alias */ @@ -1726,9 +1733,8 @@ rb_alias(klass, name, def) rb_clear_cache_by_id(name); st_insert(RCLASS(klass)->m_tbl, name, NEW_METHOD(NEW_FBODY(body, def, origin), orig->nd_noex)); - if (FL_TEST(klass, FL_SINGLETON)) { - rb_funcall(rb_iv_get(klass, "__attached__"), - singleton_added, 1, ID2SYM(name)); + if (singleton) { + rb_funcall(singleton, singleton_added, 1, ID2SYM(name)); } else { rb_funcall(klass, added, 1, ID2SYM(name)); @@ -2027,8 +2027,12 @@ rb_stat_become(obj, orig) struct stat *nst; /* need better argument type check */ - if (!rb_obj_is_kind_of(orig, rb_obj_class(obj))) { - rb_raise(rb_eTypeError, "wrong argument type"); + if (!rb_obj_is_instance_of(orig, rb_obj_class(obj))) { + rb_raise(rb_eTypeError, "wrong argument class"); + } + if (DATA_PTR(obj)) { + free(DATA_PTR(obj)); + DATA_PTR(obj) = 0; } if (DATA_PTR(orig)) { nst = ALLOC(struct stat); @@ -1356,7 +1356,7 @@ static VALUE call_final(os, obj) VALUE os, obj; { - rb_warn("ObjectSpace::call_final is deprecated; use define_finalizer"); + rb_warn("ObjectSpace::call_finalizer is deprecated; use define_finalizer"); need_call_final = 1; FL_SET(obj, FL_FINALIZE); return obj; @@ -265,9 +265,15 @@ rb_hash_become(copy, orig) if (FL_TEST(orig, HASH_PROC_DEFAULT)) { FL_SET(copy, HASH_PROC_DEFAULT); } + else { + FL_UNSET(copy, HASH_PROC_DEFAULT); + } if (FL_TEST(orig, HASH_DELETED)) { FL_SET(copy, HASH_DELETED); } + else { + FL_UNSET(copy, HASH_DELETED); + } return copy; } diff --git a/lib/finalize.rb b/lib/finalize.rb index 598569f52e..7d86d94212 100644 --- a/lib/finalize.rb +++ b/lib/finalize.rb @@ -43,159 +43,144 @@ module Finalizer RCS_ID='-$Id: finalize.rb,v 1.4 1998/02/27 05:34:33 keiju Exp keiju $-' - - # @dependency: {id => [[dependant, method, *opt], ...], ...} - - # add dependency R_method(obj, dependant) - def add_dependency(obj, dependant, method = :finalize, *opt) - ObjectSpace.call_finalizer(obj) - method = method.intern unless method.kind_of?(Integer) - assoc = [dependant, method].concat(opt) - if dep = @dependency[obj.id] - dep.push assoc - else - @dependency[obj.id] = [assoc] + + class <<self + # @dependency: {id => [[dependant, method, *opt], ...], ...} + + # add dependency R_method(obj, dependant) + def add_dependency(obj, dependant, method = :finalize, *opt) + ObjectSpace.call_finalizer(obj) + method = method.intern unless method.kind_of?(Integer) + assoc = [dependant, method].concat(opt) + if dep = @dependency[obj.id] + dep.push assoc + else + @dependency[obj.id] = [assoc] + end end - end - alias add add_dependency - - # delete dependency R_method(obj, dependant) - def delete_dependency(id, dependant, method = :finalize) - id = id.id unless id.kind_of?(Integer) - method = method.intern unless method.kind_of?(Integer) - for assoc in @dependency[id] - assoc.delete_if do - |d, m, *o| - d == dependant && m == method + alias add add_dependency + + # delete dependency R_method(obj, dependant) + def delete_dependency(id, dependant, method = :finalize) + id = id.id unless id.kind_of?(Integer) + method = method.intern unless method.kind_of?(Integer) + for assoc in @dependency[id] + assoc.delete_if do + |d, m, *o| + d == dependant && m == method + end + @dependency.delete(id) if assoc.empty? end - @dependency.delete(id) if assoc.empty? end - end - alias delete delete_dependency - - # delete dependency R_*(obj, dependant) - def delete_all_dependency(id, dependant) - id = id.id unless id.kind_of?(Integer) - method = method.intern unless method.kind_of?(Integer) - for assoc in @dependency[id] - assoc.delete_if do - |d, m, *o| - d == dependant + alias delete delete_dependency + + # delete dependency R_*(obj, dependant) + def delete_all_dependency(id, dependant) + id = id.id unless id.kind_of?(Integer) + method = method.intern unless method.kind_of?(Integer) + for assoc in @dependency[id] + assoc.delete_if do + |d, m, *o| + d == dependant + end + @dependency.delete(id) if assoc.empty? end - @dependency.delete(id) if assoc.empty? end - end - - # delete dependency R_method(*, dependant) - def delete_by_dependant(dependant, method = :finalize) - method = method.intern unless method.kind_of?(Integer) - for id in @dependency.keys - delete(id, dependant, method) + + # delete dependency R_method(*, dependant) + def delete_by_dependant(dependant, method = :finalize) + method = method.intern unless method.kind_of?(Integer) + for id in @dependency.keys + delete(id, dependant, method) + end end - end - - # delete dependency R_*(*, dependant) - def delete_all_by_dependant(dependant) - for id in @dependency.keys - delete_all_dependency(id, dependant) + + # delete dependency R_*(*, dependant) + def delete_all_by_dependant(dependant) + for id in @dependency.keys + delete_all_dependency(id, dependant) + end end - end - - # finalize the depandant connected by dependency R_method(obj, dependtant) - def finalize_dependency(id, dependant, method = :finalize) - id = id.id unless id.kind_of?(Integer) - method = method.intern unless method.kind_of?(Integer) - for assocs in @dependency[id] - assocs.delete_if do - |d, m, *o| - d.send(m, id, *o) if ret = d == dependant && m == method - ret + + # finalize the depandant connected by dependency R_method(obj, dependtant) + def finalize_dependency(id, dependant, method = :finalize) + id = id.id unless id.kind_of?(Integer) + method = method.intern unless method.kind_of?(Integer) + for assocs in @dependency[id] + assocs.delete_if do + |d, m, *o| + d.send(m, id, *o) if ret = d == dependant && m == method + ret + end + @dependency.delete(id) if assoc.empty? end - @dependency.delete(id) if assoc.empty? end - end - alias finalize finalize_dependency - - # finalize all dependants connected by dependency R_*(obj, dependtant) - def finalize_all_dependency(id, dependant) - id = id.id unless id.kind_of?(Integer) - method = method.intern unless method.kind_of?(Integer) - for assoc in @dependency[id] - assoc.delete_if do - |d, m, *o| - d.send(m, id, *o) if ret = d == dependant + alias finalize finalize_dependency + + # finalize all dependants connected by dependency R_*(obj, dependtant) + def finalize_all_dependency(id, dependant) + id = id.id unless id.kind_of?(Integer) + method = method.intern unless method.kind_of?(Integer) + for assoc in @dependency[id] + assoc.delete_if do + |d, m, *o| + d.send(m, id, *o) if ret = d == dependant + end + @dependency.delete(id) if assoc.empty? end - @dependency.delete(id) if assoc.empty? end - end - - # finalize the dependant connected by dependency R_method(*, dependtant) - def finalize_by_dependant(dependant, method = :finalize) - method = method.intern unless method.kind_of?(Integer) - for id in @dependency.keys - finalize(id, dependant, method) + + # finalize the dependant connected by dependency R_method(*, dependtant) + def finalize_by_dependant(dependant, method = :finalize) + method = method.intern unless method.kind_of?(Integer) + for id in @dependency.keys + finalize(id, dependant, method) + end end - end - - # finalize all dependants connected by dependency R_*(*, dependtant) - def finalize_all_by_dependant(dependant) - for id in @dependency.keys - finalize_all_dependency(id, dependant) + + # finalize all dependants connected by dependency R_*(*, dependtant) + def finalize_all_by_dependant(dependant) + for id in @dependency.keys + finalize_all_dependency(id, dependant) + end end - end - - # finalize all dependants registered to the Finalizer. - def finalize_all - for id, assocs in @dependency - for dependant, method, *opt in assocs - dependant.send(method, id, *opt) + + # finalize all dependants registered to the Finalizer. + def finalize_all + for id, assocs in @dependency + for dependant, method, *opt in assocs + dependant.send(method, id, *opt) + end + assocs.clear end - assocs.clear end - end - - # method to call finalize_* safely. - def safe - old_status = Thread.critical - Thread.critical = true - ObjectSpace.remove_finalizer(@proc) - yield - ObjectSpace.add_finalizer(@proc) - Thread.critical = old_status - end - - # registering function to ObjectSpace#add_finalizer - def final_of(id) - if assocs = @dependency.delete(id) - for dependant, method, *opt in assocs - dependant.send(method, id, *opt) + + # method to call finalize_* safely. + def safe + old_status = Thread.critical + Thread.critical = true + ObjectSpace.remove_finalizer(@proc) + begin + yield + ensure + ObjectSpace.add_finalizer(@proc) + Thread.critical = old_status + end + end + + private + + # registering function to ObjectSpace#add_finalizer + def final_of(id) + if assocs = @dependency.delete(id) + for dependant, method, *opt in assocs + dependant.send(method, id, *opt) + end end end + end - @dependency = Hash.new @proc = proc{|id| final_of(id)} ObjectSpace.add_finalizer(@proc) - - module_function :add - module_function :add_dependency - - module_function :delete - module_function :delete_dependency - module_function :delete_all_dependency - module_function :delete_by_dependant - module_function :delete_all_by_dependant - - module_function :finalize - module_function :finalize_dependency - module_function :finalize_all_dependency - module_function :finalize_by_dependant - module_function :finalize_all_by_dependant - module_function :finalize_all - - module_function :safe - - module_function :final_of - private_class_method :final_of - end @@ -466,11 +466,15 @@ w_object(obj, arg, limit) case T_HASH: w_uclass(obj, rb_cHash, arg); - if (!NIL_P(RHASH(obj)->ifnone)) { - w_byte(TYPE_HASH_DEF, arg); + if (NIL_P(RHASH(obj)->ifnone)) { + w_byte(TYPE_HASH, arg); + } + else if (FL_TEST(obj, FL_USER2)) { + /* FL_USER2 means HASH_PROC_DEFAULT (see hash.c) */ + rb_raise(rb_eArgError, "cannot dump hash with default proc"); } else { - w_byte(TYPE_HASH, arg); + w_byte(TYPE_HASH_DEF, arg); } w_long(RHASH(obj)->tbl->num_entries, arg); st_foreach(RHASH(obj)->tbl, hash_each, &c_arg); @@ -1047,12 +1051,17 @@ r_object0(arg, proc) VALUE klass; klass = rb_path2class(r_unique(arg)); - if (!rb_respond_to(klass, s_alloc)) { - rb_raise(rb_eTypeError, - "class %s needs to have class method `_alloc'", - rb_class2name(klass)); + if (rb_respond_to(klass, s_alloc)) { + static int warn = Qtrue; + if (warn) { + rb_warn("define `allocate' instead of `_alloc'"); + warn = Qfalse; + } + v = rb_funcall(klass, s_alloc, 0); } - v = rb_funcall(klass, s_alloc, 0); + else { + v = rb_obj_alloc(klass); + } if (TYPE(v) != T_DATA) { rb_raise(rb_eArgError, "dump format error"); } @@ -1333,7 +1333,7 @@ rb_reg_become(clone, re) VALUE re; { /* need better argument type check */ - if (!rb_obj_is_kind_of(re, rb_obj_class(clone))) { + if (!rb_obj_is_instance_of(re, rb_obj_class(clone))) { rb_raise(rb_eTypeError, "wrong argument type"); } RREGEXP(clone)->ptr = 0; @@ -211,6 +211,7 @@ void rb_check_type _((VALUE,int)); VALUE rb_str_to_str _((VALUE)); VALUE rb_string_value _((volatile VALUE*)); +char *rb_string_value_ptr _((volatile VALUE*)); #define StringValue(v) if (TYPE(v) != T_STRING) rb_string_value(&(v)) void rb_check_safe_str _((VALUE)); @@ -218,7 +219,7 @@ void rb_check_safe_str _((VALUE)); StringValue(v);\ rb_check_safe_str(v);\ } while (0) -#define StringValuePtr(v) RSTRING((TYPE(v) == T_STRING) ? (v) : rb_string_value(&(v)))->ptr +#define StringValuePtr(v) rb_string_value_ptr(&(v)) /* obsolete macro - use SafeStringValue(v) */ #define Check_SafeStr(v) rb_check_safe_str((VALUE)(v)) @@ -440,6 +440,21 @@ rb_string_value(ptr) return *ptr = rb_str_to_str(*ptr); } +char * +rb_string_value_ptr(ptr) + volatile VALUE *ptr; +{ + VALUE s = *ptr; + if (TYPE(s) != T_STRING) { + s = rb_str_to_str(s); + *ptr = s; + } + if (!RSTRING(s)->ptr) { + str_make_independent(s); + } + return RSTRING(s)->ptr; +} + VALUE rb_str_substr(str, beg, len) VALUE str; @@ -1609,18 +1624,17 @@ rb_str_replace(str, str2) } RSTRING(str)->len = RSTRING(str2)->len; RSTRING(str)->ptr = RSTRING(str2)->ptr; - if (FL_TEST(str2, ELTS_SHARED|STR_ASSOC)) { - FL_SET(str, RBASIC(str2)->flags & (ELTS_SHARED|STR_ASSOC)); - RSTRING(str)->aux.shared = RSTRING(str2)->aux.shared; - } - else { - RSTRING(str)->aux.capa = RSTRING(str2)->aux.capa; - } + FL_SET(str, RBASIC(str2)->flags & (ELTS_SHARED|STR_ASSOC)); + RSTRING(str)->aux.shared = RSTRING(str2)->aux.shared; } else { rb_str_modify(str); rb_str_resize(str, RSTRING(str2)->len); memcpy(RSTRING(str)->ptr, RSTRING(str2)->ptr, RSTRING(str2)->len); + if (FL_TEST(str2, STR_ASSOC)) { + FL_SET(str, RBASIC(str2)->flags & (ELTS_SHARED|STR_ASSOC)); + RSTRING(str)->aux.shared = RSTRING(str2)->aux.shared; + } } OBJ_INFECT(str, str2); @@ -424,8 +424,8 @@ static VALUE rb_struct_become(clone, s) VALUE clone, s; { - if (!rb_obj_is_kind_of(s, rb_obj_class(clone))) { - rb_raise(rb_eTypeError, "wrong argument type"); + if (!rb_obj_is_instance_of(s, rb_obj_class(clone))) { + rb_raise(rb_eTypeError, "wrong argument class"); } RSTRUCT(clone)->ptr = ALLOC_N(VALUE, RSTRUCT(s)->len); RSTRUCT(clone)->len = RSTRUCT(s)->len; |