Skip to content

Commit

Permalink
rewrote class flags to not use the version field anymore, better typi…
Browse files Browse the repository at this point in the history
…ng system, fixed misc bugs

git-svn-id: http://svn.macosforge.org/repository/ruby/MacRuby/trunk@3968 23306eb0-4c56-4727-a40e-e92c0eb68959
  • Loading branch information
lrz committed Apr 28, 2010
1 parent fe5ae13 commit 311a41b
Show file tree
Hide file tree
Showing 23 changed files with 246 additions and 332 deletions.
2 changes: 0 additions & 2 deletions NSArray.m
Expand Up @@ -938,8 +938,6 @@
void
Init_NSArray(void)
{
rb_cNSArray = (VALUE)objc_getClass("NSArray");
assert(rb_cNSArray != 0);
rb_cArray = rb_cNSArray;
rb_cNSMutableArray = (VALUE)objc_getClass("NSMutableArray");
assert(rb_cNSMutableArray != 0);
Expand Down
2 changes: 0 additions & 2 deletions NSDictionary.m
Expand Up @@ -435,8 +435,6 @@
void
Init_NSDictionary(void)
{
rb_cNSHash = (VALUE)objc_getClass("NSDictionary");
assert(rb_cNSHash != 0);
rb_cHash = rb_cNSHash;
rb_cNSMutableHash = (VALUE)objc_getClass("NSMutableDictionary");
assert(rb_cNSMutableHash != 0);
Expand Down
2 changes: 0 additions & 2 deletions NSString.m
Expand Up @@ -204,8 +204,6 @@
void
Init_NSString(void)
{
rb_cNSString = (VALUE)objc_getClass("NSString");
assert(rb_cNSString != 0);
rb_cString = rb_cNSString;
rb_include_module(rb_cString, rb_mComparable);
rb_cNSMutableString = (VALUE)objc_getClass("NSMutableString");
Expand Down
2 changes: 1 addition & 1 deletion array.c
Expand Up @@ -16,6 +16,7 @@
#include "objc.h"
#include "ruby/node.h"
#include "vm.h"
#include "class.h"
#include "array.h"

VALUE rb_cRubyArray;
Expand Down Expand Up @@ -3484,7 +3485,6 @@ Init_Array(void)
Init_NSArray();

rb_cRubyArray = rb_define_class("Array", rb_cNSMutableArray);
RCLASS_SET_VERSION_FLAG(rb_cRubyArray, RCLASS_IS_ARRAY_SUBCLASS);

rb_objc_define_method(*(VALUE *)rb_cRubyArray, "new",
rb_class_new_instance_imp, -1);
Expand Down
1 change: 1 addition & 0 deletions bridgesupport.cpp
Expand Up @@ -25,6 +25,7 @@ using namespace llvm;
#include "compiler.h"
#include "bridgesupport.h"
#include "objc.h"
#include "class.h"

#include <execinfo.h>
#include <dlfcn.h>
Expand Down
171 changes: 137 additions & 34 deletions class.c
Expand Up @@ -14,9 +14,11 @@
#include "ruby/node.h"
#include "ruby/st.h"
#include <ctype.h>
#include <stdarg.h>
#include "id.h"
#include "vm.h"
#include "objc.h"
#include "class.h"

extern st_table *rb_class_tbl;

Expand All @@ -35,18 +37,6 @@ rb_objc_class_sync_version(Class ocklass, Class ocsuper)
== RCLASS_IS_OBJECT_SUBCLASS) {
klass_version |= RCLASS_IS_OBJECT_SUBCLASS;
}
if ((super_version & RCLASS_IS_ARRAY_SUBCLASS)
== RCLASS_IS_ARRAY_SUBCLASS) {
klass_version |= RCLASS_IS_ARRAY_SUBCLASS;
}
if ((super_version & RCLASS_IS_HASH_SUBCLASS)
== RCLASS_IS_HASH_SUBCLASS) {
klass_version |= RCLASS_IS_HASH_SUBCLASS;
}
if ((super_version & RCLASS_IS_STRING_SUBCLASS)
== RCLASS_IS_STRING_SUBCLASS) {
klass_version |= RCLASS_IS_STRING_SUBCLASS;
}

RCLASS_SET_VERSION(ocklass, klass_version);
}
Expand Down Expand Up @@ -109,7 +99,7 @@ rb_obj_superclass(VALUE klass, SEL sel)
while (RCLASS_SINGLETON(cl)) {
cl = RCLASS_SUPER(cl);
}
return rb_class_real(cl);
return rb_class_real(cl, true);
}

VALUE rb_obj_init_copy(VALUE, SEL, VALUE);
Expand Down Expand Up @@ -198,22 +188,7 @@ rb_objc_alloc_class(const char *name, VALUE super, VALUE flags, VALUE klass)
VALUE
rb_objc_create_class(const char *name, VALUE super)
{
VALUE klass;

if (!RCLASS_RUBY(super)) {
const long v = RCLASS_VERSION(super);
if (v & RCLASS_IS_STRING_SUBCLASS) {
super = rb_cNSMutableString;
}
else if (v & RCLASS_IS_HASH_SUBCLASS) {
super = rb_cNSMutableHash;
}
else if (v & RCLASS_IS_ARRAY_SUBCLASS) {
super = rb_cNSMutableArray;
}
}

klass = rb_objc_alloc_class(name, super, T_CLASS, rb_cClass);
VALUE klass = rb_objc_alloc_class(name, super, T_CLASS, rb_cClass);

if (super != rb_cNSObject && super != 0
&& ((RCLASS_VERSION(*(VALUE *)super) & RCLASS_HAS_ROBJECT_ALLOC)
Expand Down Expand Up @@ -277,7 +252,7 @@ rb_mod_init_copy(VALUE clone, SEL sel, VALUE orig)
rb_obj_init_copy(clone, 0, orig);
{
VALUE super;
int version_flag;
unsigned long version_flag;

if (!RCLASS_RUBY(orig)) {
super = orig;
Expand Down Expand Up @@ -462,7 +437,7 @@ rb_define_class(const char *name, VALUE super)
if (TYPE(klass) != T_CLASS) {
rb_raise(rb_eTypeError, "%s is not a class", name);
}
if (rb_class_real(RCLASS_SUPER(klass)) != super) {
if (rb_class_real(RCLASS_SUPER(klass), true) != super) {
rb_name_error(id, "%s is already defined", name);
}
return klass;
Expand Down Expand Up @@ -492,7 +467,7 @@ rb_define_class_under(VALUE outer, const char *name, VALUE super)
if (TYPE(klass) != T_CLASS) {
rb_raise(rb_eTypeError, "%s is not a class", name);
}
if (rb_class_real(RCLASS_SUPER(klass)) != super) {
if (rb_class_real(RCLASS_SUPER(klass), true) != super) {
rb_name_error(id, "%s is already defined", name);
}
return klass;
Expand Down Expand Up @@ -1203,8 +1178,6 @@ rb_define_attr(VALUE klass, const char *name, int read, int write)
rb_attr(klass, rb_intern(name), read, write, Qfalse);
}

#include <stdarg.h>

int
rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
{
Expand Down Expand Up @@ -1284,3 +1257,133 @@ rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
rb_fatal("bad scan arg format: %s", fmt);
return 0;
}

static void *rb_class_flags_key = NULL;

static unsigned long
rb_class_get_mask(Class k)
{
return (unsigned long)rb_objc_get_associative_ref(k, &rb_class_flags_key);
}

static void
rb_class_set_mask(Class k, unsigned long mask)
{
rb_objc_set_associative_ref(k, &rb_class_flags_key, (void *)mask);
}

#define RCLASS_MASK_TYPE_SHIFT 16

unsigned long
rb_class_get_flags(Class k)
{
return rb_class_get_mask(k) >> RCLASS_MASK_TYPE_SHIFT;
}

void
rb_class_set_flags(Class k, unsigned long flags)
{
rb_class_set_mask(k, flags << RCLASS_MASK_TYPE_SHIFT);
}

static int
foundation_type(Class k)
{
Class tmp = k;
do {
if (tmp == (Class)rb_cNSString) {
return T_STRING;
}
if (tmp == (Class)rb_cNSArray) {
return T_ARRAY;
}
if (tmp == (Class)rb_cNSHash) {
return T_HASH;
}
tmp = class_getSuperclass(tmp);
}
while (tmp != NULL);
return 0;
}

int
rb_objc_type(VALUE obj)
{
Class k = *(Class *)obj;

if (k != NULL) {
unsigned long mask = rb_class_get_mask(k);
int type = mask & 0xff;
if (type == 0) {
// Type is not available, let's compute it.
if (k == (Class)rb_cSymbol) {
type = T_SYMBOL;
goto done;
}
if (k == (Class)rb_cFixnum) {
type = T_FIXNUM;
goto done;
}
if ((type = foundation_type(k)) != 0) {
goto done;
}
if (RCLASS_META(k)) {
if (RCLASS_MODULE(obj)) {
type = T_MODULE;
goto done;
}
else {
type = T_CLASS;
goto done;
}
}
const unsigned long flags = mask >> RCLASS_MASK_TYPE_SHIFT;
if ((flags & RCLASS_IS_OBJECT_SUBCLASS)
!= RCLASS_IS_OBJECT_SUBCLASS) {
type = T_NATIVE;
goto done;
}
type = BUILTIN_TYPE(obj);

done:
assert(type != 0);
mask |= type;
rb_class_set_mask(k, mask);
}
return type;
}
return BUILTIN_TYPE(obj);
}

bool
rb_obj_is_native(VALUE obj)
{
Class k = *(Class *)obj;
return k != NULL && (RCLASS_VERSION(k) & RCLASS_IS_OBJECT_SUBCLASS)
!= RCLASS_IS_OBJECT_SUBCLASS;
}

VALUE
rb_class_real(VALUE cl, bool hide_builtin_foundation_classes)
{
if (cl == 0) {
return 0;
}
if (RCLASS_META(cl)) {
return RCLASS_MODULE(cl) ? rb_cModule : rb_cClass;
}
while (RCLASS_SINGLETON(cl)) {
cl = RCLASS_SUPER(cl);
}
if (hide_builtin_foundation_classes && !RCLASS_RUBY(cl)) {
switch (foundation_type((Class)cl)) {
case T_STRING:
return rb_cRubyString;
case T_ARRAY:
return rb_cRubyArray;
case T_HASH:
return rb_cRubyHash;
}
}
return cl;
}
47 changes: 47 additions & 0 deletions class.h
@@ -0,0 +1,47 @@
/*
* This file is covered by the Ruby license. See COPYING for more details.
*
* Copyright (C) 2010, Apple Inc. All rights reserved.
*/

#ifndef __CLASS_H_
#define __CLASS_H_

#if defined(__cplusplus)
extern "C" {
#endif

#define RCLASS_IS_OBJECT_SUBCLASS (1<<1) /* class is a true RBObject subclass */
#define RCLASS_IS_RUBY_CLASS (1<<2) /* class was created from Ruby */
#define RCLASS_IS_MODULE (1<<3) /* class represents a Ruby Module */
#define RCLASS_IS_SINGLETON (1<<4) /* class represents a singleton */
#define RCLASS_IS_FROZEN (1<<5) /* class is frozen */
#define RCLASS_IS_TAINTED (1<<6) /* class is tainted */
#define RCLASS_IS_INCLUDED (1<<10) /* module is included */
#define RCLASS_HAS_ROBJECT_ALLOC (1<<11) /* class uses the default RObject alloc */
#define RCLASS_SCOPE_PRIVATE (1<<12) /* class opened for private methods */
#define RCLASS_SCOPE_PROTECTED (1<<13) /* class opened for protected methods */
#define RCLASS_SCOPE_MOD_FUNC (1<<14) /* class opened for module_function methods */
#define RCLASS_KVO_CHECK_DONE (1<<15) /* class created by KVO and flags merged */
#define RCLASS_NO_IV_SLOTS (1<<16) /* class cannot hold ivar slots (T_DATA & friends) */

unsigned long rb_class_get_flags(Class k);
void rb_class_set_flags(Class k, unsigned long flags);

#define RCLASS_VERSION(m) (rb_class_get_flags((Class)m))
#define RCLASS_SET_VERSION(m,f) (rb_class_set_flags((Class)m, (unsigned long)f))
#define RCLASS_SET_VERSION_FLAG(m,f) (RCLASS_SET_VERSION((Class)m, (RCLASS_VERSION(m) | f)))

#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)

CFMutableDictionaryRef rb_class_ivar_dict(VALUE);
CFMutableDictionaryRef rb_class_ivar_dict_or_create(VALUE);
void rb_class_ivar_set_dict(VALUE, CFMutableDictionaryRef);

#if defined(__cplusplus)
} // extern "C"
#endif

#endif // __CLASS_H_
3 changes: 2 additions & 1 deletion dispatcher.cpp
Expand Up @@ -18,6 +18,7 @@
#include "hash.h"
#include "encoding.h"
#include "re.h"
#include "class.h"

#include <execinfo.h>
#include <dlfcn.h>
Expand Down Expand Up @@ -842,7 +843,7 @@ __rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE top, VALUE self,
if (self == Qfalse) {
return rb_cFalseClass;
}
return rb_class_real((VALUE)klass);
return rb_class_real((VALUE)klass, true);
}

#if ROXOR_VM_DEBUG
Expand Down
1 change: 1 addition & 0 deletions eval.c
Expand Up @@ -14,6 +14,7 @@
#include "vm.h"
#include "dtrace.h"
#include "id.h"
#include "class.h"

VALUE proc_invoke(VALUE, VALUE, VALUE, VALUE);

Expand Down
4 changes: 1 addition & 3 deletions gc.c
Expand Up @@ -26,9 +26,7 @@
#include "objc.h"
#include "vm.h"
#include "id.h"
#include <stdio.h>
#include <setjmp.h>
#include <sys/types.h>
#include "class.h"

#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
Expand Down
2 changes: 1 addition & 1 deletion hash.c
Expand Up @@ -18,6 +18,7 @@
#include "objc.h"
#include "vm.h"
#include "hash.h"
#include "class.h"

static VALUE rhash_try_convert(VALUE, SEL, VALUE);

Expand Down Expand Up @@ -1774,7 +1775,6 @@ Init_Hash(void)
id_yield = rb_intern("yield");

rb_cRubyHash = rb_define_class("Hash", rb_cNSMutableHash);
RCLASS_SET_VERSION_FLAG(rb_cRubyHash, RCLASS_IS_HASH_SUBCLASS);

rb_objc_define_method(*(VALUE *)rb_cRubyHash, "new",
rb_class_new_instance_imp, -1);
Expand Down
2 changes: 1 addition & 1 deletion include/ruby/intern.h
Expand Up @@ -444,7 +444,7 @@ VALUE rb_obj_freeze(VALUE);
VALUE rb_obj_frozen_p(VALUE);
//VALUE rb_obj_id(VALUE);
VALUE rb_obj_class(VALUE);
VALUE rb_class_real(VALUE);
VALUE rb_class_real(VALUE, bool hide_builtin_foundation_classes);
VALUE rb_class_inherited_p(VALUE, VALUE);
VALUE rb_convert_type(VALUE,int,const char*,const char*);
VALUE rb_check_convert_type(VALUE,int,const char*,const char*);
Expand Down

0 comments on commit 311a41b

Please sign in to comment.