[macruby-changes] [3315] MacRuby/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Wed Jan 20 15:49:12 PST 2010
Revision: 3315
http://trac.macosforge.org/projects/ruby/changeset/3315
Author: lsansonetti at apple.com
Date: 2010-01-20 15:49:09 -0800 (Wed, 20 Jan 2010)
Log Message:
-----------
introduce RubyHash, fix a lot of minor bugs, start cleaning process
Modified Paths:
--------------
MacRuby/trunk/array.c
MacRuby/trunk/bin/rubyd
MacRuby/trunk/class.c
MacRuby/trunk/compiler.cpp
MacRuby/trunk/dispatcher.cpp
MacRuby/trunk/error.c
MacRuby/trunk/hash.c
MacRuby/trunk/include/ruby/intern.h
MacRuby/trunk/include/ruby/ruby.h
MacRuby/trunk/objc.m
MacRuby/trunk/object.c
MacRuby/trunk/re.c
MacRuby/trunk/spec/frozen/tags/macruby/core/marshal/load_tags.txt
MacRuby/trunk/st.c
MacRuby/trunk/string.c
MacRuby/trunk/struct.c
MacRuby/trunk/time.c
MacRuby/trunk/vm.cpp
Modified: MacRuby/trunk/array.c
===================================================================
--- MacRuby/trunk/array.c 2010-01-20 21:44:00 UTC (rev 3314)
+++ MacRuby/trunk/array.c 2010-01-20 23:49:09 UTC (rev 3315)
@@ -234,9 +234,32 @@
return NOT_FOUND;
}
-#define IS_RARY(x) (*(VALUE *)x == rb_cRubyArray)
+//#define IS_RARY(x) (*(VALUE *)x == rb_cRubyArray)
+// XXX temporary
+#define IS_RARY(x) __is_rary(*(VALUE *)x)
#define RARY(x) ((rb_ary_t *)x)
+static force_inline bool
+__is_rary(VALUE k)
+{
+ while (k != 0) {
+ if (k == rb_cRubyArray) {
+ return true;
+ }
+ if (k == rb_cCFArray) {
+ return false;
+ }
+ k = RCLASS_SUPER(k);
+ }
+ return false;
+}
+
+bool
+rb_klass_is_rary(VALUE klass)
+{
+ return __is_rary(klass);
+}
+
void
rb_mem_clear(register VALUE *mem, register long size)
{
@@ -253,11 +276,7 @@
mask = RBASIC(ary)->flags;
}
else {
-#ifdef __LP64__
- mask = RCLASS_RC_FLAGS(ary);
-#else
mask = rb_objc_flag_get_mask((void *)ary);
-#endif
if (RARRAY_IMMUTABLE(ary)) {
mask |= FL_FREEZE;
}
Modified: MacRuby/trunk/bin/rubyd
===================================================================
--- MacRuby/trunk/bin/rubyd 2010-01-20 21:44:00 UTC (rev 3314)
+++ MacRuby/trunk/bin/rubyd 2010-01-20 23:49:09 UTC (rev 3315)
@@ -15,7 +15,8 @@
raise "need at least one argument" if args.empty?
path = internal ? './miniruby' : File.join(RbConfig::CONFIG['bindir'],
RbConfig::CONFIG['RUBY_INSTALL_NAME'])
- @connector = ::MacRubyDebuggerConnector.alloc.initWithInterpreterPath(path, arguments: args)
+ @connector = ::MacRubyDebuggerConnector.alloc.initWithInterpreterPath(path,
+ arguments: args)
end
def run
Modified: MacRuby/trunk/class.c
===================================================================
--- MacRuby/trunk/class.c 2010-01-20 21:44:00 UTC (rev 3314)
+++ MacRuby/trunk/class.c 2010-01-20 23:49:09 UTC (rev 3315)
@@ -28,7 +28,7 @@
bool
rb_objc_install_primitives(Class ocklass, Class ocsuper)
{
- if (rb_cArray != 0 && rb_cHash != 0 && rb_cString != 0) {
+ if (rb_cRubyArray != 0 && rb_cRubyHash != 0 && rb_cString != 0) {
do {
if (ocsuper == (Class)rb_cRubyArray) {
RCLASS_SET_VERSION_FLAG(ocklass, RCLASS_IS_ARRAY_SUBCLASS);
@@ -39,6 +39,10 @@
RCLASS_SET_VERSION_FLAG(ocklass, RCLASS_IS_ARRAY_SUBCLASS);
return true;
}
+ if (ocsuper == (Class)rb_cRubyHash) {
+ RCLASS_SET_VERSION_FLAG(ocklass, RCLASS_IS_HASH_SUBCLASS);
+ return false;
+ }
if (ocsuper == (Class)rb_cHash) {
rb_objc_install_hash_primitives(ocklass);
RCLASS_SET_VERSION_FLAG(ocklass, RCLASS_IS_HASH_SUBCLASS);
@@ -113,8 +117,6 @@
return rcv;
}
-VALUE rb_class_new_instance_imp(VALUE klass, SEL sel, int argc, VALUE *argv);
-
void
rb_define_object_special_methods(VALUE klass)
{
Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp 2010-01-20 21:44:00 UTC (rev 3314)
+++ MacRuby/trunk/compiler.cpp 2010-01-20 23:49:09 UTC (rev 3315)
@@ -2846,6 +2846,7 @@
Value *
RoxorCompiler::compile_immutable_literal(VALUE val)
{
+ GC_RETAIN(val);
return ConstantInt::get(RubyObjTy, (long)val);
}
@@ -5230,7 +5231,7 @@
Value *val = compile_protected_call(yieldFunc, params);
if (getBrokenFunc == NULL) {
- // VALUE rb_vm_pop_broken_value(void)
+ // VALUE rb_vm_get_broken_value(void)
getBrokenFunc = cast<Function>(module->getOrInsertFunction(
"rb_vm_get_broken_value",
RubyObjTy, NULL));
Modified: MacRuby/trunk/dispatcher.cpp
===================================================================
--- MacRuby/trunk/dispatcher.cpp 2010-01-20 21:44:00 UTC (rev 3314)
+++ MacRuby/trunk/dispatcher.cpp 2010-01-20 23:49:09 UTC (rev 3315)
@@ -812,6 +812,9 @@
if (self == rb_cNSMutableArray) {
self = rb_cRubyArray;
}
+ if (self == rb_cNSMutableHash) {
+ self = rb_cRubyHash;
+ }
}
else if (sel == selClass) {
// Because +[NSObject class] returns self.
@@ -840,7 +843,7 @@
return RARRAY_IMMUTABLE(self)
? rb_cNSArray : rb_cNSMutableArray;
}
- else if (klass == (Class)rb_cRubyArray) {
+ if (klass == (Class)rb_cRubyArray) {
return rb_cNSMutableArray;
}
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
@@ -851,6 +854,9 @@
return RHASH_IMMUTABLE(self)
? rb_cNSHash : rb_cNSMutableHash;
}
+ if (klass == (Class)rb_cRubyHash) {
+ return rb_cNSMutableHash;
+ }
}
#if ROXOR_VM_DEBUG
@@ -1257,6 +1263,9 @@
if (self_type == T_ARRAY) {
return rb_ary_equal(self, other);
}
+ if (self_type == T_HASH) {
+ return rb_hash_equal(self, other);
+ }
return CFEqual((CFTypeRef)self, (CFTypeRef)other)
? Qtrue : Qfalse;
Modified: MacRuby/trunk/error.c
===================================================================
--- MacRuby/trunk/error.c 2010-01-20 21:44:00 UTC (rev 3314)
+++ MacRuby/trunk/error.c 2010-01-20 23:49:09 UTC (rev 3315)
@@ -1040,8 +1040,6 @@
* <code>Exception</code> to add additional information.
*/
-VALUE rb_class_new_instance_imp(VALUE, SEL, int, VALUE *);
-
void
Init_Exception(void)
{
Modified: MacRuby/trunk/hash.c
===================================================================
--- MacRuby/trunk/hash.c 2010-01-20 21:44:00 UTC (rev 3314)
+++ MacRuby/trunk/hash.c 2010-01-20 23:49:09 UTC (rev 3315)
@@ -35,23 +35,63 @@
#endif
VALUE rb_cNSHash;
VALUE rb_cNSMutableHash;
+VALUE rb_cRubyHash;
+typedef struct {
+ struct RBasic basic;
+ st_table *tbl;
+ VALUE ifnone;
+ bool has_proc_default;
+} rb_hash_t;
+
+//#define IS_RHASH(x) (*(VALUE *)x == rb_cRubyHash)
+// XXX temporary
+#define IS_RHASH(x) __is_rhash(*(VALUE *)x)
+#define RHASH(x) ((rb_hash_t *)x)
+
+static force_inline bool
+__is_rhash(VALUE k)
+{
+ while (k != 0) {
+ if (k == rb_cRubyHash) {
+ return true;
+ }
+ if (k == rb_cCFHash) {
+ return false;
+ }
+ k = RCLASS_SUPER(k);
+ }
+ return false;
+}
+
+bool
+rb_klass_is_rhash(VALUE klass)
+{
+ return __is_rhash(klass);
+}
+
static VALUE envtbl;
-static ID id_hash, id_yield;
+static ID id_yield;
static void *defaultCache = NULL;
+static void *hashCache = NULL;
static SEL selDefault = 0;
+static SEL selHash = 0;
VALUE
rb_hash(VALUE obj)
{
- VALUE v = rb_funcall(obj, id_hash, 0);
- if (TYPE(v) == T_BIGNUM) {
- unsigned long l = NUM2ULONG(v);
- l /= 2.0;
- v = ULONG2NUM(l);
+ VALUE v = rb_vm_call_with_cache(hashCache, obj, selHash, 0, NULL);
+retry:
+ switch (TYPE(v)) {
+ case T_FIXNUM:
+ return v;
+ case T_BIGNUM:
+ return LONG2FIX(((long *)(RBIGNUM_DIGITS(v)))[0]);
+ default:
+ v = rb_to_int(v);
+ goto retry;
}
- return v;
}
typedef int st_foreach_func(st_data_t, st_data_t, st_data_t);
@@ -65,10 +105,10 @@
static int
foreach_safe_i(st_data_t key, st_data_t value, struct foreach_safe_arg *arg)
{
- int status;
-
- if (key == Qundef) return ST_CONTINUE;
- status = (*arg->func)(key, value, arg->arg);
+ if (key == Qundef) {
+ return ST_CONTINUE;
+ }
+ const int status = (*arg->func)(key, value, arg->arg);
if (status == ST_CONTINUE) {
return ST_CHECK;
}
@@ -83,40 +123,41 @@
arg.tbl = table;
arg.func = (st_foreach_func *)func;
arg.arg = a;
- if (st_foreach(table, foreach_safe_i, (st_data_t)&arg)) {
- rb_raise(rb_eRuntimeError, "hash modified during iteration");
- }
+ st_foreach(table, foreach_safe_i, (st_data_t)&arg);
}
void
rb_hash_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg)
{
- CFIndex count = CFDictionaryGetCount((CFDictionaryRef)hash);
- if (count == 0)
- return;
-
- const void **keys = (const void **)alloca(sizeof(void *) * count);
- const void **values = (const void **)alloca(sizeof(void *) * count);
-
- CFDictionaryGetKeysAndValues((CFDictionaryRef)hash, keys, values);
-
- for (CFIndex i = 0; i < count; i++) {
- if ((*func)(OC2RB(keys[i]), OC2RB(values[i]), farg) != ST_CONTINUE) {
- break;
+ if (IS_RHASH(hash)) {
+ st_foreach_safe(RHASH(hash)->tbl, func, (st_data_t)farg);
+ }
+ else {
+ CFIndex count = CFDictionaryGetCount((CFDictionaryRef)hash);
+ if (count != 0) {
+ const void **keys = (const void **)alloca(sizeof(void *) * count);
+ const void **vals = (const void **)alloca(sizeof(void *) * count);
+ CFDictionaryGetKeysAndValues((CFDictionaryRef)hash, keys, vals);
+ for (CFIndex i = 0; i < count; i++) {
+ if ((*func)(OC2RB(keys[i]), OC2RB(vals[i]), farg)
+ != ST_CONTINUE) {
+ break;
+ }
+ }
}
}
}
-struct rb_hash_iterate_context {
+struct rb_cfhash_iterate_context {
int (*func)(ANYARGS);
VALUE farg;
};
static void
-rb_hash_iterate_i(const void *key, const void *value, void *context)
+rb_cfhash_iterate_i(const void *key, const void *value, void *context)
{
- struct rb_hash_iterate_context *ctx =
- (struct rb_hash_iterate_context *)context;
+ struct rb_cfhash_iterate_context *ctx =
+ (struct rb_cfhash_iterate_context *)context;
(*ctx->func)(OC2RB(key), OC2RB(value), ctx->farg);
}
@@ -124,84 +165,110 @@
void
rb_hash_iterate(VALUE hash, int (*func)(ANYARGS), VALUE farg)
{
- struct rb_hash_iterate_context ctx;
- ctx.func = func;
- ctx.farg = farg;
- CFDictionaryApplyFunction((CFDictionaryRef)hash, rb_hash_iterate_i,
- &ctx);
+ if (IS_RHASH(hash)) {
+ st_foreach_safe(RHASH(hash)->tbl, func, (st_data_t)farg);
+ }
+ else {
+ struct rb_cfhash_iterate_context ctx = {func, farg};
+ CFDictionaryApplyFunction((CFDictionaryRef)hash, rb_cfhash_iterate_i,
+ &ctx);
+ }
}
-# define HASH_KEY_CALLBACKS(h) \
- ((CFDictionaryKeyCallBacks *)((uint8_t *)h + 52))
+static int
+rb_any_cmp(VALUE a, VALUE b)
+{
+ if (a == b) {
+ return 0;
+ }
+ const int type = TYPE(a);
+ switch (type) {
+ case T_FIXNUM:
+ case T_FLOAT:
+ case T_SYMBOL:
+ if (type == TYPE(b)) {
+ return a != b;
+ }
+ break;
+ }
-/* TODO optimize me */
-struct rb_objc_hash_struct {
- VALUE ifnone;
- bool has_proc_default;
-};
+ // XXX optimize for string
-/* This variable will always stay NULL, we only use its address. */
-static void *rb_objc_hash_assoc_key = NULL;
-
-static struct rb_objc_hash_struct *
-rb_objc_hash_get_struct(VALUE hash)
-{
- return rb_objc_get_associative_ref((void *)hash, &rb_objc_hash_assoc_key);
+ return !rb_eql(a, b);
}
-static struct rb_objc_hash_struct *
-rb_objc_hash_get_struct2(VALUE hash)
+static int
+rb_any_hash(VALUE a)
{
- struct rb_objc_hash_struct *s;
+ switch (TYPE(a)) {
+ case T_FIXNUM:
+ case T_FLOAT:
+ case T_SYMBOL:
+ case T_NIL:
+ case T_FALSE:
+ case T_TRUE:
+ return (int)a;
- s = rb_objc_hash_get_struct(hash);
- if (s == NULL) {
- s = xmalloc(sizeof(struct rb_objc_hash_struct));
- rb_objc_set_associative_ref((void *)hash, &rb_objc_hash_assoc_key, s);
- s->ifnone = Qnil;
- s->has_proc_default = false;
+ case T_STRING:
+ return CFHash((CFTypeRef)a);
}
- return s;
-}
-static void
-rb_objc_hash_set_struct(VALUE hash, VALUE ifnone, bool has_proc_default)
-{
- struct rb_objc_hash_struct *s;
+ // XXX optimize for string
- s = rb_objc_hash_get_struct2(hash);
-
- GC_WB(&s->ifnone, ifnone);
- s->has_proc_default = has_proc_default;
+ return (int)FIX2LONG(rb_hash(a));
}
+static const struct st_hash_type objhash = {
+ rb_any_cmp,
+ rb_any_hash,
+};
+
static VALUE
hash_alloc(VALUE klass)
{
- CFMutableDictionaryRef hash;
-
- hash = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- if (klass != 0 && klass != rb_cNSHash && klass != rb_cNSMutableHash)
- *(Class *)hash = (Class)klass;
-
- CFMakeCollectable(hash);
-
- return (VALUE)hash;
+ if ((klass == 0 || klass == rb_cRubyHash || klass == rb_cNSMutableHash)
+ && rb_cRubyHash != 0) {
+ NEWOBJ(hash, rb_hash_t);
+ hash->basic.flags = 0;
+ hash->basic.klass = rb_cRubyHash;
+ GC_WB(&hash->tbl, st_init_table(&objhash));
+ hash->ifnone = Qnil;
+ hash->has_proc_default = false;
+ return (VALUE)hash;
+ }
+ else {
+ CFMutableDictionaryRef hash = CFDictionaryCreateMutable(NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ if (klass != 0 && klass != rb_cNSHash && klass != rb_cNSMutableHash) {
+ *(Class *)hash = (Class)klass;
+ }
+ CFMakeCollectable(hash);
+ return (VALUE)hash;
+ }
}
VALUE
rb_hash_dup(VALUE rcv)
{
- VALUE dup = (VALUE)CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)rcv);
- if (OBJ_TAINTED(rcv))
- OBJ_TAINT(dup);
- CFMakeCollectable((CFTypeRef)dup);
-
- struct rb_objc_hash_struct *s = rb_objc_hash_get_struct(rcv);
- if (s != NULL)
- rb_objc_hash_set_struct(dup, s->ifnone, s->has_proc_default);
-
- return dup;
+ if (IS_RHASH(rcv)) {
+ NEWOBJ(dup, rb_hash_t);
+ dup->basic.flags = 0;
+ dup->basic.klass = rb_cRubyHash;
+ GC_WB(&dup->tbl, st_copy(RHASH(rcv)->tbl));
+ GC_WB(&dup->ifnone, RHASH(rcv)->ifnone);
+ dup->has_proc_default = RHASH(rcv)->has_proc_default;
+ return (VALUE)dup;
+ }
+ else {
+ VALUE dup = (VALUE)CFDictionaryCreateMutableCopy(NULL, 0,
+ (CFDictionaryRef)rcv);
+ CFMakeCollectable((CFTypeRef)dup);
+ if (OBJ_TAINTED(rcv)) {
+ OBJ_TAINT(dup);
+ }
+ return dup;
+ }
}
static VALUE
@@ -214,8 +281,9 @@
rb_hash_clone(VALUE rcv, SEL sel)
{
VALUE clone = rb_hash_dup(rcv);
- if (OBJ_FROZEN(rcv))
+ if (OBJ_FROZEN(rcv)) {
OBJ_FREEZE(clone);
+ }
return clone;
}
@@ -228,20 +296,16 @@
VALUE
rb_hash_new_fast(int argc, ...)
{
- va_list ar;
- VALUE hash;
- int i;
+ assert(argc % 2 == 0);
- hash = hash_alloc(0);
+ VALUE hash = hash_alloc(0);
- assert(argc % 2 == 0);
-
+ va_list ar;
va_start(ar, argc);
- for (i = 0; i < argc; i += 2) {
+ for (int i = 0; i < argc; i += 2) {
VALUE key = va_arg(ar, VALUE);
VALUE val = va_arg(ar, VALUE);
- CFDictionarySetValue((CFMutableDictionaryRef)hash, (const void *)RB2OC(key),
- (const void *)RB2OC(val));
+ rb_hash_aset(hash, key, val);
}
va_end(ar);
@@ -252,14 +316,15 @@
rb_hash_modify_check(VALUE hash)
{
long mask;
-#ifdef __LP64__
- mask = RCLASS_RC_FLAGS(hash);
-#else
- mask = rb_objc_flag_get_mask((const void *)hash);
-#endif
- if (RHASH_IMMUTABLE(hash)) {
- mask |= FL_FREEZE;
+ if (IS_RHASH(hash)) {
+ mask = RBASIC(hash)->flags;
}
+ else {
+ mask = rb_objc_flag_get_mask((const void *)hash);
+ if (RHASH_IMMUTABLE(hash)) {
+ mask |= FL_FREEZE;
+ }
+ }
if ((mask & FL_FREEZE) == FL_FREEZE) {
rb_raise(rb_eRuntimeError, "can't modify frozen/immutable hash");
}
@@ -310,20 +375,24 @@
{
rb_hash_modify(hash);
- hash = (VALUE)objc_msgSend((id)hash, selInit);
+ //hash = (VALUE)objc_msgSend((id)hash, selInit);
- if (rb_block_given_p()) {
- if (argc > 0) {
- rb_raise(rb_eArgError, "wrong number of arguments");
+ if (IS_RHASH(hash)) {
+ if (rb_block_given_p()) {
+ if (argc > 0) {
+ rb_raise(rb_eArgError, "wrong number of arguments");
+ }
+ GC_WB(&RHASH(hash)->ifnone, rb_block_proc());
+ RHASH(hash)->has_proc_default = true;
}
- rb_objc_hash_set_struct(hash, rb_block_proc(), true);
+ else {
+ VALUE ifnone;
+ rb_scan_args(argc, argv, "01", &ifnone);
+ if (ifnone != Qnil) {
+ GC_WB(&RHASH(hash)->ifnone, ifnone);
+ }
+ }
}
- else {
- VALUE ifnone;
- rb_scan_args(argc, argv, "01", &ifnone);
- if (ifnone != Qnil)
- rb_objc_hash_set_struct(hash, ifnone, false);
- }
return hash;
}
@@ -352,43 +421,47 @@
static VALUE
rb_hash_s_create(VALUE klass, SEL sel, int argc, VALUE *argv)
{
- VALUE hash, tmp;
- int i;
-
if (argc == 1) {
- tmp = rb_hash_s_try_convert(Qnil, 0, argv[0]);
+ VALUE tmp = rb_hash_s_try_convert(Qnil, 0, argv[0]);
if (!NIL_P(tmp)) {
- CFIndex i, count;
- const void **keys;
- const void **values;
+ VALUE hash = hash_alloc(klass);
+ if (IS_RHASH(hash) && IS_RHASH(tmp)) {
+ GC_WB(&RHASH(hash)->tbl, st_copy(RHASH(tmp)->tbl));
+ }
+ else {
+ CFIndex count = CFDictionaryGetCount((CFDictionaryRef)tmp);
+ if (count == 0) {
+ return hash;
+ }
- hash = hash_alloc(klass);
- count = CFDictionaryGetCount((CFDictionaryRef)tmp);
- if (count == 0)
- return hash;
+ const void **keys = (const void **)alloca(sizeof(void *)
+ * count);
+ const void **values = (const void **)alloca(sizeof(void *)
+ * count);
- keys = (const void **)alloca(sizeof(void *) * count);
- values = (const void **)alloca(sizeof(void *) * count);
+ CFDictionaryGetKeysAndValues((CFDictionaryRef)tmp, keys,
+ values);
- CFDictionaryGetKeysAndValues((CFDictionaryRef)tmp, keys, values);
+ for (int i = 0; i < count; i++) {
+ CFDictionarySetValue((CFMutableDictionaryRef)hash,
+ RB2OC(keys[i]), RB2OC(values[i]));
+ }
+ }
- for (i = 0; i < count; i++)
- CFDictionarySetValue((CFMutableDictionaryRef)hash,
- RB2OC(keys[i]), RB2OC(values[i]));
-
return hash;
}
tmp = rb_check_array_type(argv[0]);
if (!NIL_P(tmp)) {
- long i;
-
- hash = hash_alloc(klass);
- for (i = 0; i < RARRAY_LEN(tmp); ++i) {
+ VALUE hash = hash_alloc(klass);
+ for (int i = 0; i < RARRAY_LEN(tmp); ++i) {
VALUE v = rb_check_array_type(RARRAY_AT(tmp, i));
-
- if (NIL_P(v)) continue;
- if (RARRAY_LEN(v) < 1 || 2 < RARRAY_LEN(v)) continue;
+ if (NIL_P(v)) {
+ continue;
+ }
+ if (RARRAY_LEN(v) < 1 || 2 < RARRAY_LEN(v)) {
+ continue;
+ }
rb_hash_aset(hash, RARRAY_AT(v, 0), RARRAY_AT(v, 1));
}
return hash;
@@ -398,8 +471,8 @@
rb_raise(rb_eArgError, "odd number of arguments for Hash");
}
- hash = hash_alloc(klass);
- for (i=0; i<argc; i+=2) {
+ VALUE hash = hash_alloc(klass);
+ for (int i = 0; i < argc; i += 2) {
rb_hash_aset(hash, argv[i], argv[i + 1]);
}
@@ -449,29 +522,44 @@
* h[a] #=> 100
*/
+static int
+rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg)
+{
+ st_table *tbl = (st_table *)arg;
+ if (key != Qundef) {
+ st_insert(tbl, key, value);
+ }
+ return ST_CONTINUE;
+}
+
static VALUE
rb_hash_rehash(VALUE hash, SEL sel)
{
- CFIndex i, count;
- const void **keys;
- const void **values;
-
rb_hash_modify_check(hash);
+ if (IS_RHASH(hash)) {
+ st_table *tbl = st_init_table_with_size(RHASH(hash)->tbl->type,
+ RHASH(hash)->tbl->num_entries);
+ rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tbl);
+ //st_free_table(RHASH(hash)->tbl);
+ GC_WB(&RHASH(hash)->tbl, tbl);
+ }
+ else {
+ CFIndex count = CFDictionaryGetCount((CFDictionaryRef)hash);
+ if (count == 0) {
+ return hash;
+ }
- count = CFDictionaryGetCount((CFDictionaryRef)hash);
- if (count == 0)
- return hash;
+ const void **keys = (const void **)alloca(sizeof(void *) * count);
+ const void **values = (const void **)alloca(sizeof(void *) * count);
- keys = (const void **)alloca(sizeof(void *) * count);
- values = (const void **)alloca(sizeof(void *) * count);
+ CFDictionaryGetKeysAndValues((CFDictionaryRef)hash, keys, values);
+ CFDictionaryRemoveAllValues((CFMutableDictionaryRef)hash);
- CFDictionaryGetKeysAndValues((CFDictionaryRef)hash, keys, values);
- CFDictionaryRemoveAllValues((CFMutableDictionaryRef)hash);
-
- for (i = 0; i < count; i++)
- CFDictionarySetValue((CFMutableDictionaryRef)hash,
- (const void *)keys[i], (const void *)values[i]);
-
+ for (CFIndex i = 0; i < count; i++) {
+ CFDictionarySetValue((CFMutableDictionaryRef)hash,
+ (const void *)keys[i], (const void *)values[i]);
+ }
+ }
return hash;
}
@@ -492,20 +580,26 @@
VALUE
rb_hash_aref(VALUE hash, VALUE key)
{
- VALUE val;
-
- if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)hash,
- (const void *)RB2OC(key), (const void **)&val)) {
- if (*(VALUE *)hash == rb_cCFHash) {
- struct rb_objc_hash_struct *s = rb_objc_hash_get_struct(hash);
- if (s == NULL || s->ifnone == Qnil) {
+ if (IS_RHASH(hash)) {
+ VALUE val;
+ if (!st_lookup(RHASH(hash)->tbl, key, &val)) {
+ if (*(VALUE *)hash == rb_cRubyHash
+ && RHASH(hash)->ifnone == Qnil) {
return Qnil;
}
+ return rb_vm_call_with_cache(defaultCache, hash, selDefault,
+ 1, &key);
}
- return rb_vm_call_with_cache(defaultCache, hash, selDefault, 1, &key);
+ return val;
}
- val = OC2RB(val);
- return val;
+ else {
+ VALUE val;
+ if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)hash,
+ (const void *)RB2OC(key), (const void **)&val)) {
+ return Qnil;
+ }
+ return OC2RB(val);
+ }
}
static VALUE
@@ -514,17 +608,30 @@
return rb_hash_aref(hash, key);
}
+static VALUE
+rb_hash_lookup0(VALUE hash, VALUE key)
+{
+ if (IS_RHASH(hash)) {
+ VALUE val;
+ if (st_lookup(RHASH(hash)->tbl, key, &val)) {
+ return val;
+ }
+ }
+ else {
+ VALUE val;
+ if (CFDictionaryGetValueIfPresent((CFDictionaryRef)hash,
+ (const void *)RB2OC(key), (const void **)&val)) {
+ return OC2RB(val);
+ }
+ }
+ return Qundef;
+}
+
VALUE
rb_hash_lookup(VALUE hash, VALUE key)
{
- VALUE val;
-
- if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)hash, (const void *)RB2OC(key),
- (const void **)&val)) {
- return Qnil;
- }
- val = OC2RB(val);
- return val;
+ VALUE v = rb_hash_lookup0(hash, key);
+ return v == Qundef ? Qnil : v;
}
/*
@@ -560,24 +667,24 @@
rb_hash_fetch(VALUE hash, SEL sel, int argc, VALUE *argv)
{
VALUE key, if_none;
- VALUE val;
- long block_given;
-
rb_scan_args(argc, argv, "11", &key, &if_none);
- block_given = rb_block_given_p();
+ const bool block_given = rb_block_given_p();
if (block_given && argc == 2) {
rb_warn("block supersedes default value argument");
}
- if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)hash, (const void *)RB2OC(key),
- (const void **)&val)) {
- if (block_given) return rb_yield(key);
- if (argc == 1) {
- rb_raise(rb_eKeyError, "key not found");
- }
- return if_none;
+
+ VALUE v = rb_hash_lookup0(hash, key);
+ if (v != Qundef) {
+ return v;
}
- return OC2RB(val);
+ if (block_given) {
+ return rb_yield(key);
+ }
+ if (argc == 1) {
+ rb_raise(rb_eKeyError, "key not found");
+ }
+ return if_none;
}
/*
@@ -604,18 +711,19 @@
static VALUE
rb_hash_default(VALUE hash, SEL sel, int argc, VALUE *argv)
{
- struct rb_objc_hash_struct *s = rb_objc_hash_get_struct(hash);
VALUE key;
+ rb_scan_args(argc, argv, "01", &key);
- if (s == NULL || s->ifnone == Qnil)
- return Qnil;
-
- rb_scan_args(argc, argv, "01", &key);
- if (s->has_proc_default) {
- if (argc == 0) return Qnil;
- return rb_funcall(s->ifnone, id_yield, 2, hash, key);
+ if (IS_RHASH(hash)) {
+ if (RHASH(hash)->has_proc_default) {
+ if (argc == 0) {
+ return Qnil;
+ }
+ return rb_funcall(RHASH(hash)->ifnone, id_yield, 2, hash, key);
+ }
+ return RHASH(hash)->ifnone;
}
- return s->ifnone;
+ return Qnil;
}
/*
@@ -642,7 +750,10 @@
rb_hash_set_default(VALUE hash, SEL sel, VALUE ifnone)
{
rb_hash_modify(hash);
- rb_objc_hash_set_struct(hash, ifnone, false);
+ if (IS_RHASH(hash)) {
+ GC_WB(&RHASH(hash)->ifnone, ifnone);
+ RHASH(hash)->has_proc_default = false;
+ }
return ifnone;
}
@@ -670,9 +781,9 @@
static VALUE
rb_hash_default_proc(VALUE hash, SEL sel)
{
- struct rb_objc_hash_struct *s = rb_objc_hash_get_struct(hash);
- if (s != NULL && s->has_proc_default)
- return s->ifnone;
+ if (IS_RHASH(hash)) {
+ return RHASH(hash)->has_proc_default ? RHASH(hash)->ifnone : Qnil;
+ }
return Qnil;
}
@@ -701,13 +812,8 @@
static VALUE
rb_hash_key(VALUE hash, SEL sel, VALUE value)
{
- VALUE args[2];
-
- args[0] = value;
- args[1] = Qnil;
-
+ VALUE args[2] = {value, Qnil};
rb_hash_iterate(hash, key_i, (st_data_t)args);
-
return args[1];
}
@@ -722,14 +828,22 @@
VALUE
rb_hash_delete_key(VALUE hash, VALUE key)
{
- VALUE val;
- id ockey = RB2OC(key);
- if (CFDictionaryGetValueIfPresent((CFDictionaryRef)hash,
- (const void *)ockey, (const void **)&val)) {
- CFDictionaryRemoveValue((CFMutableDictionaryRef)hash,
- (const void *)ockey);
- return OC2RB(val);
+ if (IS_RHASH(hash)) {
+ VALUE val;
+ if (st_delete(RHASH(hash)->tbl, &key, &val)) {
+ return val;
+ }
}
+ else {
+ VALUE val;
+ id ockey = RB2OC(key);
+ if (CFDictionaryGetValueIfPresent((CFDictionaryRef)hash,
+ (const void *)ockey, (const void **)&val)) {
+ CFDictionaryRemoveValue((CFMutableDictionaryRef)hash,
+ (const void *)ockey);
+ return OC2RB(val);
+ }
+ }
return Qundef;
}
@@ -754,11 +868,11 @@
VALUE
rb_hash_delete(VALUE hash, VALUE key)
{
- VALUE val;
-
rb_hash_modify(hash);
- val = rb_hash_delete_key(hash, key);
- if (val != Qundef) return val;
+ VALUE val = rb_hash_delete_key(hash, key);
+ if (val != Qundef) {
+ return val;
+ }
if (rb_block_given_p()) {
return rb_yield(key);
}
@@ -789,33 +903,35 @@
static VALUE
rb_hash_shift(VALUE hash, SEL sel)
{
- VALUE keys, key, val;
-
- keys = rb_hash_keys_imp(hash, 0);
+ VALUE keys = rb_hash_keys_imp(hash, 0);
if (RARRAY_LEN(keys) == 0) {
- struct rb_objc_hash_struct *s = rb_objc_hash_get_struct(hash);
-
- if (s == NULL || s->ifnone == Qnil)
- return Qnil;
-
- if (s->has_proc_default)
- return rb_funcall(s->ifnone, id_yield, 2, hash, Qnil);
- return s->ifnone;
+ if (IS_RHASH(hash)) {
+ if (RHASH(hash)->ifnone != Qnil) {
+ if (RHASH(hash)->has_proc_default) {
+ return rb_funcall(RHASH(hash)->ifnone, id_yield, 2, hash,
+ Qnil);
+ }
+ return RHASH(hash)->ifnone;
+ }
+ }
+ return Qnil;
}
- key = RARRAY_AT(keys, 0);
- val = rb_hash_aref(hash, key);
+ VALUE key = RARRAY_AT(keys, 0);
+ VALUE val = rb_hash_aref(hash, key);
rb_hash_delete(hash, key);
return rb_assoc_new(key, val);
}
static int
-delete_if_i(VALUE key, VALUE value, VALUE hash)
+delete_if_i(VALUE key, VALUE value, VALUE ary)
{
- if (key == Qundef) return ST_CONTINUE;
+ if (key == Qundef) {
+ return ST_CONTINUE;
+ }
if (RTEST(rb_yield_values(2, key, value))) {
- rb_hash_delete_key(hash, key);
+ rb_ary_push(ary, key);
}
return ST_CONTINUE;
}
@@ -837,7 +953,12 @@
{
RETURN_ENUMERATOR(hash, 0, 0);
rb_hash_modify(hash);
- rb_hash_foreach(hash, delete_if_i, hash);
+ VALUE ary = rb_ary_new();
+ rb_hash_foreach(hash, delete_if_i, ary);
+ for (int i = 0, count = RARRAY_LEN(ary); i < count; i++) {
+ VALUE key = RARRAY_AT(ary, i);
+ rb_hash_delete_key(hash, key);
+ }
return hash;
}
@@ -852,14 +973,10 @@
static VALUE
rb_hash_reject_bang(VALUE hash, SEL sel)
{
- CFIndex n;
-
RETURN_ENUMERATOR(hash, 0, 0);
- n = CFDictionaryGetCount((CFDictionaryRef)hash);
+ const long n = RHASH_SIZE(hash);
rb_hash_delete_if(hash, 0);
- if (n == CFDictionaryGetCount((CFDictionaryRef)hash))
- return Qnil;
- return hash;
+ return n == RHASH_SIZE(hash) ? Qnil : hash;
}
/*
@@ -893,9 +1010,7 @@
rb_hash_values_at(VALUE hash, SEL sel, int argc, VALUE *argv)
{
VALUE result = rb_ary_new2(argc);
- long i;
-
- for (i=0; i<argc; i++) {
+ for (int i = 0; i < argc; i++) {
rb_ary_push(result, rb_hash_aref(hash, argv[i]));
}
return result;
@@ -904,9 +1019,12 @@
static int
select_i(VALUE key, VALUE value, VALUE result)
{
- if (key == Qundef) return ST_CONTINUE;
- if (RTEST(rb_yield_values(2, key, value)))
+ if (key == Qundef) {
+ return ST_CONTINUE;
+ }
+ if (RTEST(rb_yield_values(2, key, value))) {
rb_hash_aset(result, key, value);
+ }
return ST_CONTINUE;
}
@@ -924,10 +1042,8 @@
static VALUE
rb_hash_select(VALUE hash, SEL sel)
{
- VALUE result;
-
RETURN_ENUMERATOR(hash, 0, 0);
- result = rb_hash_new();
+ VALUE result = rb_hash_new();
rb_hash_iterate(hash, select_i, result);
return result;
}
@@ -947,8 +1063,12 @@
rb_hash_clear(VALUE hash, SEL sel)
{
rb_hash_modify_check(hash);
- CFDictionaryRemoveAllValues((CFMutableDictionaryRef)hash);
-
+ if (IS_RHASH(hash)) {
+ st_clear(RHASH(hash)->tbl);
+ }
+ else {
+ CFDictionaryRemoveAllValues((CFMutableDictionaryRef)hash);
+ }
return hash;
}
@@ -974,8 +1094,14 @@
rb_hash_aset(VALUE hash, VALUE key, VALUE val)
{
rb_hash_modify(hash);
- CFDictionarySetValue((CFMutableDictionaryRef)hash, (const void *)RB2OC(key),
- (const void *)RB2OC(val));
+ if (IS_RHASH(hash)) {
+ st_insert(RHASH(hash)->tbl, key, val);
+ }
+ else {
+ CFDictionarySetValue((CFMutableDictionaryRef)hash,
+ (const void *)RB2OC(key),
+ (const void *)RB2OC(val));
+ }
return val;
}
@@ -991,7 +1117,6 @@
if (key != Qundef) {
rb_hash_aset(hash, key, val);
}
-
return ST_CONTINUE;
}
@@ -1017,11 +1142,11 @@
}
rb_hash_clear(hash, 0);
rb_hash_foreach(hash2, replace_i, hash);
- struct rb_objc_hash_struct *s = rb_objc_hash_get_struct(hash2);
- if (s != NULL) {
- rb_objc_hash_set_struct(hash, s->ifnone, s->has_proc_default);
+
+ if (IS_RHASH(hash) && IS_RHASH(hash2)) {
+ GC_WB(&RHASH(hash)->ifnone, RHASH(hash2)->ifnone);
+ RHASH(hash)->has_proc_default = RHASH(hash2)->has_proc_default;
}
-
return hash;
}
@@ -1038,13 +1163,21 @@
* h.length #=> 3
*/
+long
+rb_hash_size(VALUE hash)
+{
+ if (IS_RHASH(hash)) {
+ return RHASH(hash)->tbl->num_entries;
+ }
+ return CFDictionaryGetCount((CFDictionaryRef)hash);
+}
+
static VALUE
-rb_hash_size(VALUE hash, SEL sel)
+rb_hash_size_imp(VALUE hash, SEL sel)
{
- return INT2FIX(CFDictionaryGetCount((CFDictionaryRef)hash));
+ return LONG2NUM(rb_hash_size(hash));
}
-
/*
* call-seq:
* hsh.empty? => true or false
@@ -1098,7 +1231,9 @@
static int
each_key_i(VALUE key, VALUE value)
{
- if (key == Qundef) return ST_CONTINUE;
+ if (key == Qundef) {
+ return ST_CONTINUE;
+ }
rb_yield(key);
return ST_CONTINUE;
}
@@ -1129,7 +1264,9 @@
static int
each_pair_i(VALUE key, VALUE value)
{
- if (key == Qundef) return ST_CONTINUE;
+ if (key == Qundef) {
+ return ST_CONTINUE;
+ }
rb_yield(rb_assoc_new(key, value));
return ST_CONTINUE;
}
@@ -1163,7 +1300,9 @@
static int
to_a_i(VALUE key, VALUE value, VALUE ary)
{
- if (key == Qundef) return ST_CONTINUE;
+ if (key == Qundef) {
+ return ST_CONTINUE;
+ }
rb_ary_push(ary, rb_assoc_new(key, value));
return ST_CONTINUE;
}
@@ -1187,7 +1326,6 @@
if (OBJ_TAINTED(hash)) {
OBJ_TAINT(ary);
}
-
return ary;
}
@@ -1205,7 +1343,6 @@
rb_str_buf_cat2(str, "=>");
str2 = rb_inspect(value);
rb_str_buf_append(str, str2);
-
return ST_CONTINUE;
}
@@ -1219,7 +1356,6 @@
rb_hash_iterate(hash, inspect_i, str);
rb_str_buf_cat2(str, "}");
OBJ_INFECT(str, hash);
-
return str;
}
@@ -1237,8 +1373,9 @@
static VALUE
rb_hash_inspect(VALUE hash, SEL sel)
{
- if (RHASH_EMPTY_P(hash))
+ if (RHASH_EMPTY_P(hash)) {
return rb_usascii_str_new2("{}");
+ }
return rb_exec_recursive(inspect_hash, hash, 0);
}
@@ -1339,9 +1476,13 @@
static VALUE
rb_hash_has_key_imp(VALUE hash, SEL sel, VALUE key)
{
- return CFDictionaryContainsKey((CFDictionaryRef)hash,
- (const void *)RB2OC(key))
- ? Qtrue : Qfalse;
+ if (IS_RHASH(hash)) {
+ return st_lookup(RHASH(hash)->tbl, key, 0) ? Qtrue : Qfalse;
+ }
+ else {
+ return CFDictionaryContainsKey((CFDictionaryRef)hash,
+ (const void *)RB2OC(key)) ? Qtrue : Qfalse;
+ }
}
VALUE
@@ -1363,29 +1504,108 @@
* h.has_value?(999) #=> false
*/
+static int
+rb_hash_search_value(VALUE key, VALUE value, VALUE arg)
+{
+ VALUE *data = (VALUE *)arg;
+ if (key == Qundef) {
+ return ST_CONTINUE;
+ }
+ if (rb_equal(value, data[1])) {
+ data[0] = Qtrue;
+ return ST_STOP;
+ }
+ return ST_CONTINUE;
+}
+
static VALUE
rb_hash_has_value(VALUE hash, SEL sel, VALUE val)
{
- return CFDictionaryContainsValue((CFDictionaryRef)hash, (const void *)RB2OC(val))
- ? Qtrue : Qfalse;
+ if (IS_RHASH(hash)) {
+ VALUE data[2] = {Qfalse, val};
+ rb_hash_foreach(hash, rb_hash_search_value, (VALUE)data);
+ return data[0];
+ }
+ else {
+ return CFDictionaryContainsValue((CFDictionaryRef)hash,
+ (const void *)RB2OC(val)) ? Qtrue : Qfalse;
+ }
}
+struct equal_data {
+ VALUE result;
+ st_table *tbl;
+ bool eql;
+};
+
+static int
+eql_i(VALUE key, VALUE val1, VALUE arg)
+{
+ struct equal_data *data = (struct equal_data *)arg;
+ VALUE val2;
+
+ if (key == Qundef) {
+ return ST_CONTINUE;
+ }
+ if (!st_lookup(data->tbl, key, &val2)) {
+ data->result = Qfalse;
+ return ST_STOP;
+ }
+ if (data->eql) {
+ if (!rb_eql(val1, val2)) {
+ data->result = Qfalse;
+ return ST_STOP;
+ }
+ }
+ else {
+ if (rb_equal(val1, val2) != Qtrue) {
+ data->result = Qfalse;
+ return ST_STOP;
+ }
+ }
+ return ST_CONTINUE;
+}
+
static VALUE
-hash_equal(VALUE hash1, VALUE hash2, int eql)
+recursive_eql(VALUE hash1, VALUE data, int recur)
{
- if (hash1 == hash2) return Qtrue;
+ if (recur) {
+ return Qtrue;
+ }
+ ((struct equal_data *)data)->result = Qtrue;
+ rb_hash_foreach(hash1, eql_i, data);
+ return ((struct equal_data *)data)->result;
+}
+
+static VALUE
+hash_equal(VALUE hash1, VALUE hash2, bool eql)
+{
+ if (hash1 == hash2) {
+ return Qtrue;
+ }
if (TYPE(hash2) != T_HASH) {
if (!rb_respond_to(hash2, rb_intern("to_hash"))) {
return Qfalse;
}
- if (eql)
+ if (eql) {
return rb_eql(hash2, hash1);
- else
+ }
+ else {
return rb_equal(hash2, hash1);
+ }
}
- if (RHASH_SIZE(hash1) != RHASH_SIZE(hash2))
+ if (RHASH_SIZE(hash1) != RHASH_SIZE(hash2)) {
return Qfalse;
- return CFEqual((CFTypeRef)hash1, (CFTypeRef)hash2) ? Qtrue : Qfalse;
+ }
+ if (IS_RHASH(hash1) && IS_RHASH(hash2)) {
+ struct equal_data data;
+ data.tbl = RHASH(hash2)->tbl;
+ data.eql = eql;
+ return rb_exec_recursive(recursive_eql, hash1, (VALUE)&data);
+ }
+ else {
+ return CFEqual((CFTypeRef)hash1, (CFTypeRef)hash2) ? Qtrue : Qfalse;
+ }
}
/*
@@ -1408,11 +1628,17 @@
*/
static VALUE
-rb_hash_equal(VALUE hash1, SEL sel, VALUE hash2)
+rb_hash_equal_imp(VALUE hash1, SEL sel, VALUE hash2)
{
- return hash_equal(hash1, hash2, Qfalse);
+ return hash_equal(hash1, hash2, false);
}
+VALUE
+rb_hash_equal(VALUE hash1, VALUE hash2)
+{
+ return hash_equal(hash1, hash2, false);
+}
+
/*
* call-seq:
* hash.eql?(other) -> true or false
@@ -1424,7 +1650,7 @@
static VALUE
rb_hash_eql(VALUE hash1, SEL sel, VALUE hash2)
{
- return hash_equal(hash1, hash2, Qtrue);
+ return hash_equal(hash1, hash2, true);
}
static int
@@ -1568,10 +1794,7 @@
VALUE
rb_hash_assoc(VALUE hash, SEL sel, VALUE obj)
{
- VALUE args[2];
-
- args[0] = obj;
- args[1] = Qnil;
+ VALUE args[2] = {obj, Qnil};
rb_hash_foreach(hash, assoc_i, (st_data_t)args);
return args[1];
}
@@ -1605,10 +1828,7 @@
VALUE
rb_hash_rassoc(VALUE hash, SEL sel, VALUE obj)
{
- VALUE args[2];
-
- args[0] = obj;
- args[1] = Qnil;
+ VALUE args[2] = {obj, Qnil};
rb_hash_foreach(hash, rassoc_i, (st_data_t)args);
return args[1];
}
@@ -1632,9 +1852,7 @@
static VALUE
rb_hash_flatten(VALUE hash, SEL sel, int argc, VALUE *argv)
{
- VALUE ary, tmp;
-
- ary = rb_hash_to_a(hash, 0);
+ VALUE tmp, ary = rb_hash_to_a(hash, 0);
if (argc == 0) {
argc = 1;
tmp = INT2FIX(1);
@@ -1664,7 +1882,7 @@
rb_hash_compare_by_id(VALUE hash, SEL sel)
{
rb_hash_modify(hash);
-// HASH_KEY_CALLBACKS(hash)->equal = NULL;
+ // TODO
return hash;
}
@@ -1680,10 +1898,8 @@
static VALUE
rb_hash_compare_by_id_p(VALUE hash, SEL sel)
{
+ // TODO
return Qfalse;
-// return HASH_KEY_CALLBACKS(hash) != &kCFTypeDictionaryKeyCallBacks
-// && HASH_KEY_CALLBACKS(hash)->equal == NULL
-// ? Qtrue : Qfalse;
}
static int path_tainted = -1;
@@ -2397,9 +2613,25 @@
*(Class *)x = old;
bool
-rb_objc_hash_is_pure(VALUE ary)
+rb_objc_hash_is_pure(VALUE hash)
{
- return *(Class *)ary == (Class)rb_cCFHash;
+ return *(VALUE *)hash == rb_cCFHash || *(VALUE *)hash == rb_cRubyHash;
+#if 0
+ VALUE k = *(VALUE *)hash;
+ while (RCLASS_SINGLETON(k)) {
+ k = RCLASS_SUPER(k);
+ }
+ if (k == rb_cRubyHash) {
+ return true;
+ }
+ while (k != 0) {
+ if (k == rb_cRubyHash) {
+ return false;
+ }
+ k = RCLASS_SUPER(k);
+ }
+ return true;
+#endif
}
static CFIndex
@@ -2415,13 +2647,13 @@
static void *
imp_rb_hash_keyEnumerator(void *rcv, SEL sel)
{
- void *keys;
static SEL objectEnumerator = 0;
PREPARE_RCV(rcv);
- keys = (void *)rb_hash_keys_imp((VALUE)rcv, 0);
+ void *keys = (void *)rb_hash_keys_imp((VALUE)rcv, 0);
RESTORE_RCV(rcv);
- if (objectEnumerator == 0)
+ if (objectEnumerator == 0) {
objectEnumerator = sel_registerName("objectEnumerator");
+ }
return objc_msgSend(keys, objectEnumerator);
}
@@ -2521,6 +2753,76 @@
rb_objc_define_method(*(VALUE *)klass, "alloc", hash_alloc, 0);
}
+static VALUE rb_cRubyHashKeyEnumerator;
+
+typedef struct {
+ VALUE klass;
+ VALUE hash;
+ VALUE keys;
+ unsigned pos;
+} rb_hash_keyenum_t;
+
+static void *
+imp_rhash_keyenum_allObjects(void *rcv, SEL sel)
+{
+ rb_hash_keyenum_t *ke = (rb_hash_keyenum_t *)rcv;
+ return (void *)ke->keys;
+}
+
+static void *
+imp_rhash_keyenum_nextObject(void *rcv, SEL sel)
+{
+ rb_hash_keyenum_t *ke = (rb_hash_keyenum_t *)rcv;
+ if (ke->pos == RARRAY_LEN(ke->keys)) {
+ return NULL;
+ }
+ VALUE key = RARRAY_AT(ke->keys, ke->pos);
+ ke->pos++;
+ return (void *)RB2OC(key);
+}
+
+static CFIndex
+imp_rhash_count(void *rcv, SEL sel)
+{
+ return RHASH(rcv)->tbl->num_entries;
+}
+
+static void *
+imp_rhash_objectForKey(void *rcv, SEL sel, void *key)
+{
+ VALUE val;
+ if (!st_lookup(RHASH(rcv)->tbl, OC2RB(key), &val)) {
+ return NULL;
+ }
+ return RB2OC(val);
+}
+
+static void *
+imp_rhash_keyEnumerator(void *rcv, SEL sel)
+{
+ NEWOBJ(keyenum, rb_hash_keyenum_t);
+ keyenum->klass = rb_cRubyHashKeyEnumerator;
+ GC_WB(&keyenum->hash, rcv);
+ VALUE ary = rb_ary_new();
+ st_foreach_safe(RHASH(rcv)->tbl, keys_i, (st_data_t)ary);
+ GC_WB(&keyenum->keys, ary);
+ keyenum->pos = 0;
+ return keyenum;
+}
+
+static void
+imp_rhash_setObjectForKey(void *rcv, SEL sel, void *val, void *key)
+{
+ st_insert(RHASH(rcv)->tbl, OC2RB(key), OC2RB(val));
+}
+
+static void
+imp_rhash_removeObjectForKey(void *rcv, SEL sel, void *key)
+{
+ VALUE rkey = OC2RB(key);
+ st_delete(RHASH(rcv)->tbl, &rkey, NULL);
+}
+
/*
* A <code>Hash</code> is a collection of key-value pairs. It is
* similar to an <code>Array</code>, except that indexing is done via
@@ -2544,9 +2846,10 @@
Init_Hash(void)
{
selDefault = sel_registerName("default:");
+ selHash = sel_registerName("hash");
defaultCache = rb_vm_get_call_cache(selDefault);
+ hashCache = rb_vm_get_call_cache(selHash);
- id_hash = rb_intern("hash");
id_yield = rb_intern("yield");
rb_cCFHash = (VALUE)objc_getClass(NSCFDICTIONARY_CNAME);
@@ -2577,7 +2880,7 @@
rb_objc_define_method(rb_cHash, "to_s", rb_hash_inspect, 0);
rb_objc_define_method(rb_cHash, "inspect", rb_hash_inspect, 0);
- rb_objc_define_method(rb_cHash, "==", rb_hash_equal, 1);
+ rb_objc_define_method(rb_cHash, "==", rb_hash_equal_imp, 1);
rb_objc_define_method(rb_cHash, "[]", rb_hash_aref_imp, 1);
rb_objc_define_method(rb_cHash, "eql?", rb_hash_eql, 1);
rb_objc_define_method(rb_cHash, "fetch", rb_hash_fetch, -1);
@@ -2588,8 +2891,8 @@
rb_objc_define_method(rb_cHash, "default_proc", rb_hash_default_proc, 0);
rb_objc_define_method(rb_cHash, "key", rb_hash_key, 1);
rb_objc_define_method(rb_cHash, "index", rb_hash_index, 1);
- rb_objc_define_method(rb_cHash, "size", rb_hash_size, 0);
- rb_objc_define_method(rb_cHash, "length", rb_hash_size, 0);
+ rb_objc_define_method(rb_cHash, "size", rb_hash_size_imp, 0);
+ rb_objc_define_method(rb_cHash, "length", rb_hash_size_imp, 0);
rb_objc_define_method(rb_cHash, "empty?", rb_hash_empty_p, 0);
rb_objc_define_method(rb_cHash, "each_value", rb_hash_each_value, 0);
@@ -2631,6 +2934,28 @@
rb_objc_define_method(rb_cHash, "compare_by_identity", rb_hash_compare_by_id, 0);
rb_objc_define_method(rb_cHash, "compare_by_identity?", rb_hash_compare_by_id_p, 0);
+ rb_cRubyHash = rb_define_class("RubyHash", rb_cNSMutableHash);
+ rb_objc_define_method(*(VALUE *)rb_cRubyHash, "alloc", hash_alloc, 0);
+ rb_objc_install_method2((Class)rb_cRubyHash, "count",
+ (IMP)imp_rhash_count);
+ rb_objc_install_method2((Class)rb_cRubyHash, "objectForKey:",
+ (IMP)imp_rhash_objectForKey);
+ rb_objc_install_method2((Class)rb_cRubyHash, "keyEnumerator",
+ (IMP)imp_rhash_keyEnumerator);
+ rb_objc_install_method2((Class)rb_cRubyHash, "setObject:forKey:",
+ (IMP)imp_rhash_setObjectForKey);
+ rb_objc_install_method2((Class)rb_cRubyHash, "removeObjectForKey:",
+ (IMP)imp_rhash_removeObjectForKey);
+
+ VALUE NSEnumerator = (VALUE)objc_getClass("NSEnumerator");
+ assert(NSEnumerator != 0);
+ rb_cRubyHashKeyEnumerator = rb_define_class("RubyHashKeyEnumerator",
+ NSEnumerator);
+ rb_objc_install_method2((Class)rb_cRubyHashKeyEnumerator, "allObjects",
+ (IMP)imp_rhash_keyenum_allObjects);
+ rb_objc_install_method2((Class)rb_cRubyHashKeyEnumerator, "nextObject",
+ (IMP)imp_rhash_keyenum_nextObject);
+
origenviron = environ;
envtbl = rb_obj_alloc(rb_cObject);
rb_extend_object(envtbl, rb_mEnumerable);
Modified: MacRuby/trunk/include/ruby/intern.h
===================================================================
--- MacRuby/trunk/include/ruby/intern.h 2010-01-20 21:44:00 UTC (rev 3314)
+++ MacRuby/trunk/include/ruby/intern.h 2010-01-20 23:49:09 UTC (rev 3315)
@@ -151,6 +151,7 @@
VALUE rb_objc_create_class(const char *name, VALUE super);
bool rb_objc_install_primitives(Class ocklass, Class ocsuper);
void rb_define_object_special_methods(VALUE klass);
+VALUE rb_class_new_instance_imp(VALUE, SEL, int, VALUE *);
#endif
VALUE rb_class_boot(VALUE);
VALUE rb_class_new(VALUE);
@@ -375,6 +376,8 @@
VALUE rb_hash_has_key(VALUE hash, VALUE key);
VALUE rb_hash_keys(VALUE hash);
VALUE rb_hash_set_ifnone(VALUE hash, VALUE ifnone);
+long rb_hash_size(VALUE hash);
+VALUE rb_hash_equal(VALUE hash1, VALUE hash2);
struct st_table *rb_hash_tbl(VALUE);
int rb_path_check(const char*);
int rb_env_path_tainted(void);
Modified: MacRuby/trunk/include/ruby/ruby.h
===================================================================
--- MacRuby/trunk/include/ruby/ruby.h 2010-01-20 21:44:00 UTC (rev 3314)
+++ MacRuby/trunk/include/ruby/ruby.h 2010-01-20 23:49:09 UTC (rev 3315)
@@ -554,25 +554,12 @@
# define RCLASS_SCOPE_MOD_FUNC (1<<26) /* class opened for module_function methods */
# define RCLASS_KVO_CHECK_DONE (1<<27) /* class created by KVO and flags merged */
# define RCLASS_NO_IV_SLOTS (1<<28) /* class cannot hold ivar slots (T_DATA & friends) */
-# if defined(__LP64__)
-# define _PTR_TYPE uint64_t
-# define RCLASS_VERSION(m) (class_getVersion((Class)m))
-# define RCLASS_SET_VERSION(m,f) (class_setVersion((Class)m, f))
-# define RCLASS_SET_VERSION_FLAG(m,f) (class_setVersion((Class)m, (RCLASS_VERSION(m) | f)))
-# define RCLASS_SUPER(m) (*(VALUE *)((_PTR_TYPE)m + (sizeof(void *) * 1)))
-# define RCLASS_SET_SUPER(m, s) (class_setSuperclass((Class)m, (Class)s))
-# define RCLASS_META(m) (class_isMetaClass((Class)m))
-# define RCLASS_RC_FLAGS(m) (*(uint32_t *) ((_PTR_TYPE)(m) + sizeof(uintptr_t) + (sizeof(uint8_t) * 4)))
-# else
-# define _PTR_TYPE uint32_t
-# define RCLASS_VERSION(m) (class_getVersion((Class)m))
-# define RCLASS_SET_VERSION(m,f) (class_setVersion((Class)m, f))
-# define RCLASS_SET_VERSION_FLAG(m,f) (class_setVersion((Class)m, (RCLASS_VERSION(m) | f)))
-# define RCLASS_SUPER(m) (*(VALUE *)((_PTR_TYPE)m + (sizeof(void *) * 1)))
-# define RCLASS_SET_SUPER(m, s) (class_setSuperclass((Class)m, (Class)s))
-# define RCLASS_META(m) (class_isMetaClass((Class)m))
-# define RCLASS_RC_FLAGS(m) (*(uint32_t *) ((_PTR_TYPE)(m) + sizeof(uintptr_t) + (sizeof(uint8_t) * 4)))
-# endif
+# define RCLASS_VERSION(m) (class_getVersion((Class)m))
+# define RCLASS_SET_VERSION(m,f) (class_setVersion((Class)m, f))
+# define RCLASS_SET_VERSION_FLAG(m,f) (class_setVersion((Class)m, (RCLASS_VERSION(m) | f)))
+# define RCLASS_SUPER(m) ((VALUE)class_getSuperclass((Class)m))
+# define RCLASS_SET_SUPER(m, s) (class_setSuperclass((Class)m, (Class)s))
+# define RCLASS_META(m) (class_isMetaClass((Class)m))
# define RCLASS_RUBY(m) ((RCLASS_VERSION(m) & RCLASS_IS_RUBY_CLASS) == RCLASS_IS_RUBY_CLASS)
# define RCLASS_MODULE(m) ((RCLASS_VERSION(m) & RCLASS_IS_MODULE) == RCLASS_IS_MODULE)
# define RCLASS_SINGLETON(m) ((RCLASS_VERSION(m) & RCLASS_IS_SINGLETON) == RCLASS_IS_SINGLETON)
@@ -690,7 +677,7 @@
# define RHASH_IFNONE(h) (RHASH(h)->ifnone)
# define RHASH_SIZE(h) (RHASH(h)->ntbl ? RHASH(h)->ntbl->num_entries : 0)
#else
-# define RHASH_SIZE(h) (CFDictionaryGetCount((CFDictionaryRef)h))
+# define RHASH_SIZE(h) rb_hash_size(h)
#endif
#define RHASH_EMPTY_P(h) (RHASH_SIZE(h) == 0)
@@ -1159,6 +1146,7 @@
#endif
RUBY_EXTERN VALUE rb_cNSHash;
RUBY_EXTERN VALUE rb_cNSMutableHash;
+RUBY_EXTERN VALUE rb_cRubyHash;
RUBY_EXTERN VALUE rb_cCFSet;
RUBY_EXTERN VALUE rb_cNSSet;
RUBY_EXTERN VALUE rb_cNSMutableSet;
@@ -1374,7 +1362,7 @@
) {
return T_ARRAY;
}
- if (k == (Class)rb_cCFHash) {
+ if (k == (Class)rb_cCFHash || k == (Class)rb_cRubyHash) {
return T_HASH;
}
if (RCLASS_META(k)) {
Modified: MacRuby/trunk/objc.m
===================================================================
--- MacRuby/trunk/objc.m 2010-01-20 21:44:00 UTC (rev 3314)
+++ MacRuby/trunk/objc.m 2010-01-20 23:49:09 UTC (rev 3315)
@@ -493,39 +493,27 @@
return recv;
}
-#define FLAGS_AS_ASSOCIATIVE_REF 1
+static void *__obj_flags; // used as a static key
-static CFMutableDictionaryRef __obj_flags;
-
long
rb_objc_flag_get_mask(const void *obj)
{
-#if FLAGS_AS_ASSOCIATIVE_REF
return (long)rb_objc_get_associative_ref((void *)obj, &__obj_flags);
-#else
- if (__obj_flags == NULL)
- return 0;
-
- return (long)CFDictionaryGetValue(__obj_flags, obj);
-#endif
}
bool
rb_objc_flag_check(const void *obj, int flag)
{
- long v;
-
- v = rb_objc_flag_get_mask(obj);
- if (v == 0)
- return false;
-
+ const long v = rb_objc_flag_get_mask(obj);
+ if (v == 0) {
+ return false;
+ }
return (v & flag) == flag;
}
void
rb_objc_flag_set(const void *obj, int flag, bool val)
{
-#if FLAGS_AS_ASSOCIATIVE_REF
long v = (long)rb_objc_get_associative_ref((void *)obj, &__obj_flags);
if (val) {
v |= flag;
@@ -534,59 +522,8 @@
v ^= flag;
}
rb_objc_set_associative_ref((void *)obj, &__obj_flags, (void *)v);
-#else
- long v;
-
- if (__obj_flags == NULL) {
- __obj_flags = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
- }
- v = (long)CFDictionaryGetValue(__obj_flags, obj);
- if (val) {
- v |= flag;
- }
- else {
- v ^= flag;
- }
- CFDictionarySetValue(__obj_flags, obj, (void *)v);
-#endif
}
-long
-rb_objc_remove_flags(const void *obj)
-{
-#if FLAGS_AS_ASSOCIATIVE_REF
- long flag = (long)rb_objc_get_associative_ref((void *)obj, &__obj_flags);
- //rb_objc_set_associative_ref((void *)obj, &__obj_flags, (void *)0);
- return flag;
-#else
- long flag;
- if (CFDictionaryGetValueIfPresent(__obj_flags, obj,
- (const void **)&flag)) {
- CFDictionaryRemoveValue(__obj_flags, obj);
- return flag;
- }
- return 0;
-#endif
-}
-
-extern bool __CFStringIsMutable(void *);
-extern bool _CFArrayIsMutable(void *);
-extern bool _CFDictionaryIsMutable(void *);
-
-bool
-rb_objc_is_immutable(VALUE v)
-{
- switch(TYPE(v)) {
- case T_STRING:
- return !__CFStringIsMutable((void *)v);
- case T_ARRAY:
- return !_CFArrayIsMutable((void *)v);
- case T_HASH:
- return !_CFDictionaryIsMutable((void *)v);
- }
- return false;
-}
-
static IMP old_imp_isaForAutonotifying;
static Class
Modified: MacRuby/trunk/object.c
===================================================================
--- MacRuby/trunk/object.c 2010-01-20 21:44:00 UTC (rev 3314)
+++ MacRuby/trunk/object.c 2010-01-20 23:49:09 UTC (rev 3315)
@@ -165,7 +165,7 @@
if (cl == rb_cCFArray || cl == rb_cRubyArray) {
return rb_cNSMutableArray;
}
- if (cl == rb_cCFHash) {
+ if (cl == rb_cCFHash || cl == rb_cRubyHash) {
return rb_cNSMutableHash;
}
return cl;
@@ -302,9 +302,6 @@
clone = rb_obj_alloc(rb_obj_class(obj));
RBASIC(clone)->klass = rb_singleton_class_clone(obj);
RBASIC(clone)->flags = (RBASIC(obj)->flags | FL_TEST(clone, FL_TAINT)) & ~(FL_FREEZE|FL_FINALIZE);
-//#ifdef __LP64__
-// RCLASS_RC_FLAGS(clone) = RCLASS_RC_FLAGS(obj);
-//#endif
break;
}
@@ -782,13 +779,19 @@
* Returns <code>true</code> if the object is tainted.
*/
+bool rb_klass_is_rary(VALUE klass);
+bool rb_klass_is_rhash(VALUE klass);
+
static VALUE
rb_obj_tainted_p(VALUE obj, SEL sel)
{
if (!SPECIAL_CONST_P(obj) && NATIVE(obj)) {
switch (TYPE(obj)) {
+ case T_SYMBOL:
+ return Qfalse;
+
case T_ARRAY:
- if (*(VALUE *)obj != rb_cCFArray) {
+ if (rb_klass_is_rary(*(VALUE *)obj)) {
return RBASIC(obj)->flags & FL_TAINT ? Qtrue : Qfalse;
}
// fall through
@@ -798,9 +801,9 @@
}
// fall through
case T_HASH:
-#ifdef __LP64__
- return (RCLASS_RC_FLAGS(obj) & FL_TAINT) == FL_TAINT ? Qtrue : Qfalse;
-#endif
+ if (rb_klass_is_rhash(*(VALUE *)obj)) {
+ return RBASIC(obj)->flags & FL_TAINT ? Qtrue : Qfalse;
+ }
default:
return rb_objc_flag_check((const void *)obj, FL_TAINT) ? Qtrue : Qfalse;
}
@@ -832,8 +835,11 @@
rb_secure(4);
if (!SPECIAL_CONST_P(obj) && NATIVE(obj)) {
switch (TYPE(obj)) {
+ case T_SYMBOL:
+ break;
+
case T_ARRAY:
- if (*(VALUE *)obj != rb_cCFArray) {
+ if (rb_klass_is_rary(*(VALUE *)obj)) {
RBASIC(obj)->flags |= FL_TAINT;
break;
}
@@ -845,10 +851,10 @@
}
// fall through
case T_HASH:
-#ifdef __LP64__
- RCLASS_RC_FLAGS(obj) |= FL_TAINT;
- break;
-#endif
+ if (rb_klass_is_rhash(*(VALUE *)obj)) {
+ RBASIC(obj)->flags |= FL_TAINT;
+ break;
+ }
default:
rb_objc_flag_set((const void *)obj, FL_TAINT, true);
}
@@ -883,8 +889,11 @@
rb_secure(3);
if (!SPECIAL_CONST_P(obj) && NATIVE(obj)) {
switch (TYPE(obj)) {
+ case T_SYMBOL:
+ break;
+
case T_ARRAY:
- if (*(VALUE *)obj != rb_cCFArray) {
+ if (rb_klass_is_rary(*(VALUE *)obj)) {
RBASIC(obj)->flags &= ~FL_TAINT;
break;
}
@@ -896,10 +905,10 @@
}
// fall through
case T_HASH:
-#ifdef __LP64__
- RCLASS_RC_FLAGS(obj) &= ~FL_TAINT;
- break;
-#endif
+ if (rb_klass_is_rhash(*(VALUE *)obj)) {
+ RBASIC(obj)->flags &= ~FL_TAINT;
+ break;
+ }
default:
rb_objc_flag_set((const void *)obj, FL_TAINT, false);
}
@@ -925,8 +934,11 @@
{
if (!SPECIAL_CONST_P(obj) && NATIVE(obj)) {
switch (TYPE(obj)) {
+ case T_SYMBOL:
+ return Qfalse;
+
case T_ARRAY:
- if (*(VALUE *)obj != rb_cCFArray) {
+ if (rb_klass_is_rary(*(VALUE *)obj)) {
return RBASIC(obj)->flags & FL_UNTRUSTED ? Qtrue : Qfalse;
}
// fall through
@@ -936,9 +948,9 @@
}
// fall through
case T_HASH:
-#ifdef __LP64__
- return (RCLASS_RC_FLAGS(obj) & FL_UNTRUSTED) == FL_UNTRUSTED ? Qtrue : Qfalse;
-#endif
+ if (rb_klass_is_rhash(*(VALUE *)obj)) {
+ return RBASIC(obj)->flags & FL_UNTRUSTED ? Qtrue : Qfalse;
+ }
default:
return rb_objc_flag_check((const void *)obj, FL_UNTRUSTED) ? Qtrue : Qfalse;
}
@@ -961,8 +973,11 @@
rb_secure(4);
if (!SPECIAL_CONST_P(obj) && NATIVE(obj)) {
switch (TYPE(obj)) {
+ case T_SYMBOL:
+ break;
+
case T_ARRAY:
- if (*(VALUE *)obj != rb_cCFArray) {
+ if (rb_klass_is_rary(*(VALUE *)obj)) {
RBASIC(obj)->flags &= ~FL_UNTRUSTED;
break;
}
@@ -974,10 +989,10 @@
}
// fall through
case T_HASH:
-#ifdef __LP64__
- RCLASS_RC_FLAGS(obj) &= ~FL_UNTRUSTED;
- break;
-#endif
+ if (rb_klass_is_rhash(*(VALUE *)obj)) {
+ RBASIC(obj)->flags &= ~FL_UNTRUSTED;
+ break;
+ }
default:
rb_objc_flag_set((const void *)obj, FL_UNTRUSTED, false);
}
@@ -1004,8 +1019,11 @@
rb_secure(4);
if (!SPECIAL_CONST_P(obj) && NATIVE(obj)) {
switch (TYPE(obj)) {
+ case T_SYMBOL:
+ break;
+
case T_ARRAY:
- if (*(VALUE *)obj != rb_cCFArray) {
+ if (rb_klass_is_rary(*(VALUE *)obj)) {
RBASIC(obj)->flags |= FL_UNTRUSTED;
break;
}
@@ -1017,10 +1035,10 @@
}
// fall through
case T_HASH:
-#ifdef __LP64__
- RCLASS_RC_FLAGS(obj) |= FL_UNTRUSTED;
- break;
-#endif
+ if (rb_klass_is_rhash(*(VALUE *)obj)) {
+ RBASIC(obj)->flags |= FL_UNTRUSTED;
+ break;
+ }
default:
rb_objc_flag_set((const void *)obj, FL_UNTRUSTED, true);
}
@@ -1084,12 +1102,15 @@
st_insert(immediate_frozen_tbl, obj, (st_data_t)Qtrue);
}
else if (NATIVE(obj)) {
- switch(TYPE(obj)) {
+ switch (TYPE(obj)) {
+ case T_SYMBOL:
+ break;
+
case T_ARRAY:
- if (*(VALUE *)obj != rb_cCFArray) {
+ if (rb_klass_is_rary(*(VALUE *)obj)) {
RBASIC(obj)->flags |= FL_FREEZE;
break;
- }
+ }
// fall through
case T_STRING:
if (*(VALUE *)obj == rb_cByteString) {
@@ -1098,10 +1119,10 @@
}
// fall through
case T_HASH:
-#ifdef __LP64__
- RCLASS_RC_FLAGS(obj) |= FL_FREEZE;
- break;
-#endif
+ if (rb_klass_is_rhash(*(VALUE *)obj)) {
+ RBASIC(obj)->flags |= FL_FREEZE;
+ break;
+ }
default:
rb_objc_flag_set((const void *)obj, FL_FREEZE, true);
}
@@ -1146,8 +1167,11 @@
return Qfalse;
}
switch (TYPE(obj)) {
+ case T_SYMBOL:
+ return Qfalse;
+
case T_ARRAY:
- if (*(VALUE *)obj != rb_cCFArray) {
+ if (rb_klass_is_rary(*(VALUE *)obj)) {
return RBASIC(obj)->flags & FL_FREEZE ? Qtrue : Qfalse;
}
// fall through
@@ -1157,12 +1181,11 @@
}
// fall through
case T_HASH:
-#ifdef __LP64__
- return (RCLASS_RC_FLAGS(obj) & FL_FREEZE) == FL_FREEZE ? Qtrue : Qfalse;
-#endif
+ if (rb_klass_is_rhash(*(VALUE *)obj)) {
+ return RBASIC(obj)->flags & FL_FREEZE ? Qtrue : Qfalse;
+ }
case T_NATIVE:
- return rb_objc_is_immutable(obj)
- || rb_objc_flag_check((const void *)obj, FL_FREEZE)
+ return rb_objc_flag_check((const void *)obj, FL_FREEZE)
? Qtrue : Qfalse;
case T_CLASS:
case T_ICLASS:
@@ -1176,7 +1199,7 @@
VALUE
rb_obj_frozen_p(VALUE obj)
{
- return rb_obj_frozen(obj, 0);
+ return rb_obj_frozen(obj, 0);
}
@@ -1918,6 +1941,9 @@
if (klass == rb_cNSMutableArray) {
klass = rb_cRubyArray;
}
+ else if (klass == rb_cNSMutableHash) {
+ klass = rb_cRubyHash;
+ }
VALUE obj = rb_obj_alloc0(klass);
Modified: MacRuby/trunk/re.c
===================================================================
--- MacRuby/trunk/re.c 2010-01-20 21:44:00 UTC (rev 3314)
+++ MacRuby/trunk/re.c 2010-01-20 23:49:09 UTC (rev 3315)
@@ -3710,8 +3710,6 @@
*
*/
-VALUE rb_class_new_instance_imp(VALUE, SEL, int, VALUE *);
-
void
Init_Regexp(void)
{
Modified: MacRuby/trunk/spec/frozen/tags/macruby/core/marshal/load_tags.txt
===================================================================
--- MacRuby/trunk/spec/frozen/tags/macruby/core/marshal/load_tags.txt 2010-01-20 21:44:00 UTC (rev 3314)
+++ MacRuby/trunk/spec/frozen/tags/macruby/core/marshal/load_tags.txt 2010-01-20 23:49:09 UTC (rev 3315)
@@ -1,4 +1,6 @@
critical:Marshal::load calls the proc for recursively visited data
+critical:Marshal::load loads a Hash subclass
+critical:Marshal::load loads an extended_user_hash with a parameter to initialize
fails:Marshal::load loads an extended Object
fails:Marshal::load loads a 1...2
fails:Marshal::load loads a 1..2
Modified: MacRuby/trunk/st.c
===================================================================
--- MacRuby/trunk/st.c 2010-01-20 21:44:00 UTC (rev 3314)
+++ MacRuby/trunk/st.c 2010-01-20 23:49:09 UTC (rev 3315)
@@ -64,7 +64,10 @@
#ifdef RUBY
#define malloc xmalloc
#define calloc xcalloc
-#define free xfree
+//#define free xfree
+#define free(x) ((void)0)
+void *rb_gc_memmove(void *dst, const void *src, size_t len);
+#define xmemmove rb_gc_memmove
#endif
#define alloc(type) (type*)malloc((size_t)sizeof(type))
@@ -344,18 +347,18 @@
entry = alloc(st_table_entry);\
\
entry->hash = hash_val;\
- entry->key = key;\
+ GC_WB(&entry->key, key);\
GC_WB(&entry->record, value); \
GC_WB(&entry->next, table->bins[bin_pos]);\
if ((head = table->head) != 0) {\
- GC_WB(&entry->fore, head);\
+ entry->fore = head;\
(entry->back = head->back)->fore = entry;\
- GC_WB(&head->back, entry);\
+ head->back = entry;\
}\
else {\
- GC_WB(&table->head, entry);\
- GC_WB(&entry->fore, entry);\
- GC_WB(&entry->back, entry);\
+ table->head = entry;\
+ entry->fore = entry;\
+ entry->back = entry;\
}\
GC_WB(&table->bins[bin_pos], entry); \
table->num_entries++;\
@@ -470,21 +473,16 @@
unsigned int hash_val;
new_table = alloc(st_table);
- if (new_table == 0) {
- return 0;
- }
+ assert(new_table != NULL);
*new_table = *old_table;
GC_WB(&new_table->bins, (st_table_entry**)
Calloc((unsigned)num_bins, sizeof(st_table_entry*)));
- if (new_table->bins == 0) {
- free(new_table);
- return 0;
- }
+ assert(new_table->bins != NULL);
if (old_table->entries_packed) {
- memcpy(new_table->bins, old_table->bins, sizeof(struct st_table_entry *) * old_table->num_bins);
+ xmemmove(new_table->bins, old_table->bins, sizeof(struct st_table_entry *) * old_table->num_bins);
return new_table;
}
@@ -493,22 +491,19 @@
tail = &new_table->head;
do {
entry = alloc(st_table_entry);
- if (entry == 0) {
- st_free_table(new_table);
- return 0;
- }
+ assert(entry != NULL);
*entry = *ptr;
hash_val = entry->hash % num_bins;
- entry->next = new_table->bins[hash_val];
+ GC_WB(&entry->next, new_table->bins[hash_val]);
GC_WB(&new_table->bins[hash_val], entry);
entry->back = prev;
prev = entry;
- GC_WB(tail, entry);
+ *tail = entry;
tail = &entry->fore;
} while ((ptr = ptr->fore) != old_table->head);
entry = new_table->head;
entry->back = prev;
- GC_WB(tail, entry);
+ *tail = entry;
}
return new_table;
@@ -541,7 +536,7 @@
if ((st_data_t)table->bins[i*2] == *key) {
if (value != 0) *value = (st_data_t)table->bins[i*2+1];
table->num_entries--;
- memmove(&table->bins[i*2], &table->bins[(i+1)*2],
+ xmemmove(&table->bins[i*2], &table->bins[(i+1)*2],
sizeof(struct st_table_entry*) * 2*(table->num_entries-i));
return 1;
}
@@ -570,20 +565,33 @@
int
st_delete_safe(register st_table *table, register st_data_t *key, st_data_t *value, st_data_t never)
{
- unsigned int hash_val;
+ st_index_t hash_val;
register st_table_entry *ptr;
+ if (table->entries_packed) {
+ st_index_t i;
+ for (i = 0; i < table->num_entries; i++) {
+ if ((st_data_t)table->bins[i*2] == *key) {
+ if (value != 0) *value = (st_data_t)table->bins[i*2+1];
+ table->bins[i*2] = (void *)never;
+ return 1;
+ }
+ }
+ if (value != 0) *value = 0;
+ return 0;
+ }
+
hash_val = do_hash_bin(*key, table);
ptr = table->bins[hash_val];
for (; ptr != 0; ptr = ptr->next) {
- if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) {
- REMOVE_ENTRY(table, ptr);
- *key = ptr->key;
- if (value != 0) *value = ptr->record;
- ptr->key = ptr->record = never;
- return 1;
- }
+ if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) {
+ REMOVE_ENTRY(table, ptr);
+ *key = ptr->key;
+ if (value != 0) *value = ptr->record;
+ ptr->key = ptr->record = never;
+ return 1;
+ }
}
if (value != 0) *value = 0;
@@ -643,7 +651,7 @@
return 0;
case ST_DELETE:
table->num_entries--;
- memmove(&table->bins[i*2], &table->bins[(i+1)*2],
+ xmemmove(&table->bins[i*2], &table->bins[(i+1)*2],
sizeof(struct st_table_entry*) * 2*(table->num_entries-i));
i--;
break;
@@ -723,7 +731,7 @@
return 0;
case ST_DELETE:
table->num_entries--;
- memmove(&table->bins[i*2], &table->bins[(i+1)*2],
+ xmemmove(&table->bins[i*2], &table->bins[(i+1)*2],
sizeof(struct st_table_entry*) * 2*(table->num_entries-i));
break;
}
Modified: MacRuby/trunk/string.c
===================================================================
--- MacRuby/trunk/string.c 2010-01-20 21:44:00 UTC (rev 3314)
+++ MacRuby/trunk/string.c 2010-01-20 23:49:09 UTC (rev 3315)
@@ -531,12 +531,7 @@
static inline void
str_modifiable(VALUE str)
{
- long mask;
-#ifdef __LP64__
- mask = RCLASS_RC_FLAGS(str);
-#else
- mask = rb_objc_flag_get_mask((void *)str);
-#endif
+ long mask = rb_objc_flag_get_mask((void *)str);
if (RSTRING_IMMUTABLE(str)) {
mask |= FL_FREEZE;
}
Modified: MacRuby/trunk/struct.c
===================================================================
--- MacRuby/trunk/struct.c 2010-01-20 21:44:00 UTC (rev 3314)
+++ MacRuby/trunk/struct.c 2010-01-20 23:49:09 UTC (rev 3315)
@@ -180,8 +180,6 @@
return Qnil; /* not reached */
}
-VALUE rb_class_new_instance_imp(VALUE klass, SEL sel, int argc, VALUE *argv);
-
static VALUE
make_struct(VALUE name, VALUE members, VALUE klass)
{
Modified: MacRuby/trunk/time.c
===================================================================
--- MacRuby/trunk/time.c 2010-01-20 21:44:00 UTC (rev 3314)
+++ MacRuby/trunk/time.c 2010-01-20 23:49:09 UTC (rev 3315)
@@ -2351,7 +2351,6 @@
rb_include_module(rb_cTime, rb_mComparable);
rb_objc_define_method(*(VALUE *)rb_cTime, "alloc", time_s_alloc, 0);
- VALUE rb_class_new_instance_imp(VALUE, SEL, int, VALUE *);
rb_objc_define_method(*(VALUE *)rb_cTime, "now", rb_class_new_instance_imp, -1);
rb_objc_define_method(*(VALUE *)rb_cTime, "at", time_s_at, -1);
rb_objc_define_method(*(VALUE *)rb_cTime, "utc", time_s_mkutc, -1);
Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp 2010-01-20 21:44:00 UTC (rev 3314)
+++ MacRuby/trunk/vm.cpp 2010-01-20 23:49:09 UTC (rev 3315)
@@ -4000,7 +4000,9 @@
void
rb_iter_break(void)
{
- GET_VM()->set_broken_with(Qnil);
+ RoxorVM *vm = GET_VM();
+ GC_RELEASE(vm->get_broken_with());
+ vm->set_broken_with(Qnil);
}
extern "C"
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100120/454150da/attachment-0001.html>
More information about the macruby-changes
mailing list