Skip to content
This repository
Browse code

Automate object_type enum and kind_of<>

* object_type is now automatically generate from the field_extract data.
* kind_of<> specializations are now autogenerated from field_extract
  data.
  • Loading branch information...
commit 8d2c2b9ea32933ccf03ac0e560233d082a87b5dd 1 parent d69cfff
authored

Showing 39 changed files with 158 additions and 384 deletions. Show diff stats Hide diff stats

  1. 2  vm/builtin/block_environment.cpp
  2. 2  vm/builtin/block_environment.hpp
  3. 17  vm/builtin/class.cpp
  4. 2  vm/builtin/class.hpp
  5. 6  vm/builtin/compiledmethod.cpp
  6. 2  vm/builtin/compiledmethod.hpp
  7. 16  vm/builtin/contexts.cpp
  8. 4  vm/builtin/contexts.hpp
  9. 12  vm/builtin/executable.cpp
  10. 24  vm/builtin/fixnum.cpp
  11. 2  vm/builtin/float.hpp
  12. 22  vm/builtin/immediates.cpp
  13. 9  vm/builtin/integer.cpp
  14. 2  vm/builtin/iseq.cpp
  15. 2  vm/builtin/iseq.hpp
  16. 7  vm/builtin/lookuptable.cpp
  17. 4  vm/builtin/memorypointer.cpp
  18. 2  vm/builtin/memorypointer.hpp
  19. 2  vm/builtin/methodtable.hpp
  20. 2  vm/builtin/methodvisibility.hpp
  21. 2  vm/builtin/module.hpp
  22. 4  vm/builtin/nativefunction.cpp
  23. 2  vm/builtin/nativefunction.hpp
  24. 4  vm/builtin/nativemethod.hpp
  25. 4  vm/builtin/nativemethodcontext.cpp
  26. 4  vm/builtin/nativemethodcontext.hpp
  27. 132  vm/builtin/object.cpp
  28. 2  vm/builtin/object.hpp
  29. 6  vm/builtin/symbol.cpp
  30. 8  vm/builtin/tuple.cpp
  31. 64  vm/codegen/field_extract.rb
  32. 51  vm/object.hpp
  33. 60  vm/object_types.hpp
  34. 4  vm/ontology.cpp
  35. 2  vm/oop.hpp
  36. 4  vm/test/test_memorypointer.hpp
  37. 40  vm/test/test_nativefunction.hpp
  38. 4  vm/test/test_ontology.hpp
  39. 4  vm/vmmethod.cpp
2  vm/builtin/block_environment.cpp
@@ -22,7 +22,7 @@ namespace rubinius {
22 22
   void BlockEnvironment::init(STATE) {
23 23
     GO(blokenv).set(state->new_class("BlockEnvironment", G(object), 
24 24
           BlockEnvironment::fields));
25  
-    G(blokenv)->set_object_type(state, BlockEnvType);
  25
+    G(blokenv)->set_object_type(state, BlockEnvironmentType);
26 26
   }
27 27
 
28 28
   void BlockEnvironment::call(STATE, Task* task, size_t args) {
2  vm/builtin/block_environment.hpp
@@ -16,7 +16,7 @@ namespace rubinius {
16 16
   class BlockEnvironment : public Object {
17 17
   public:
18 18
     const static size_t fields = 5;
19  
-    const static object_type type = BlockEnvType;
  19
+    const static object_type type = BlockEnvironmentType;
20 20
 
21 21
   private:
22 22
     MethodContext* home_;       // slot
17  vm/builtin/class.cpp
@@ -13,23 +13,6 @@
13 13
 
14 14
 namespace rubinius {
15 15
 
16  
-  template <>
17  
-    bool kind_of<Class>(OBJECT obj) {
18  
-      return obj->obj_type == ClassType ||
19  
-        obj->obj_type == MetaclassType ||
20  
-        obj->obj_type == IncModType;
21  
-    }
22  
-
23  
-  template <>
24  
-    bool kind_of<Module>(OBJECT obj) {
25  
-      return obj->reference_p() &&
26  
-        (obj->obj_type == Module::type ||
27  
-         obj->obj_type == Class::type ||
28  
-         obj->obj_type == MetaClass::type ||
29  
-         obj->obj_type == IncludedModule::type);
30  
-    }
31  
-
32  
-
33 16
   Class* Class::create(STATE, Class* super) {
34 17
     Class* cls = (Class*)state->new_object(G(klass));
35 18
 
2  vm/builtin/class.hpp
@@ -46,7 +46,7 @@ namespace rubinius {
46 46
   class MetaClass : public Class {
47 47
   public:
48 48
     const static size_t fields = Class::fields + 1;
49  
-    const static object_type type = MetaclassType;
  49
+    const static object_type type = MetaClassType;
50 50
 
51 51
   private:
52 52
     OBJECT attached_instance_; // slot
6  vm/builtin/compiledmethod.cpp
@@ -18,11 +18,11 @@ namespace rubinius {
18 18
 
19 19
   void CompiledMethod::init(STATE) {
20 20
     GO(cmethod).set(state->new_class("CompiledMethod", G(executable), CompiledMethod::fields));
21  
-    G(cmethod)->set_object_type(state, CMethodType);
  21
+    G(cmethod)->set_object_type(state, CompiledMethodType);
22 22
 
23 23
     GO(cmethod_vis).set(state->new_class("Visibility", G(object),
24 24
         MethodVisibility::fields, G(cmethod)));
25  
-    G(cmethod_vis)->set_object_type(state, CMVisibilityType);
  25
+    G(cmethod_vis)->set_object_type(state, MethodVisibilityType);
26 26
   }
27 27
 
28 28
   CompiledMethod* CompiledMethod::create(STATE) {
@@ -63,7 +63,7 @@ namespace rubinius {
63 63
 
64 64
   VMMethod* CompiledMethod::formalize(STATE, bool ondemand) {
65 65
     if(!backend_method_) {
66  
-      VMMethod* vmm;
  66
+      VMMethod* vmm = NULL;
67 67
       /* Controls whether we use LLVM out of the gate or not. */
68 68
       if(state->config.compile_up_front) {
69 69
         if(ondemand) {
2  vm/builtin/compiledmethod.hpp
@@ -14,7 +14,7 @@ namespace rubinius {
14 14
   class CompiledMethod : public Executable {
15 15
   public:
16 16
     const static size_t fields = 18;
17  
-    const static object_type type = CMethodType;
  17
+    const static object_type type = CompiledMethodType;
18 18
     const static size_t saved_fields = 16;
19 19
 
20 20
   private:
16  vm/builtin/contexts.cpp
@@ -15,20 +15,12 @@
15 15
 
16 16
 namespace rubinius {
17 17
 
18  
-  template <>
19  
-    bool kind_of<MethodContext>(OBJECT obj) {
20  
-      return    obj->obj_type == MethodContext::type
21  
-             || obj->obj_type == BlockContext::type
22  
-             || obj->obj_type == NativeMethodContext::type
23  
-             ;
24  
-    }
25  
-
26 18
   void MethodContext::init(STATE) {
27 19
     GO(methctx).set(state->new_class("MethodContext", G(object)));
28  
-    G(methctx)->set_object_type(state, MContextType);
  20
+    G(methctx)->set_object_type(state, MethodContextType);
29 21
 
30 22
     GO(blokctx).set(state->new_class("BlockContext", G(methctx)));
31  
-    G(blokctx)->set_object_type(state, BContextType);
  23
+    G(blokctx)->set_object_type(state, BlockContextType);
32 24
   }
33 25
 
34 26
   /* Calculate how much big of an object (in bytes) to allocate
@@ -118,7 +110,7 @@ namespace rubinius {
118 110
   void MethodContext::post_copy(MethodContext* old) {
119 111
     this->position_stack(old->calculate_sp());
120 112
     this->js.stack_top = this->stk + this->stack_size;
121  
-    if(this->obj_type == MContextType) {
  113
+    if(this->obj_type == MethodContextType) {
122 114
       assert(this->home() == old);
123 115
     }
124 116
   }
@@ -234,7 +226,7 @@ namespace rubinius {
234 226
 
235 227
     MethodContext* ctx = as<MethodContext>(obj);
236 228
 
237  
-    if(ctx->obj_type == MContextType) {
  229
+    if(ctx->obj_type == MethodContextType) {
238 230
       assert(ctx->home() == obj);
239 231
     }
240 232
 
4  vm/builtin/contexts.hpp
@@ -19,7 +19,7 @@ namespace rubinius {
19 19
   public:
20 20
     // fields is 0 because it is dynamically calculated
21 21
     const static size_t fields = 0;
22  
-    const static object_type type = MContextType;
  22
+    const static object_type type = MethodContextType;
23 23
 
24 24
   private:
25 25
     MethodContext* sender_; // slot
@@ -143,7 +143,7 @@ namespace rubinius {
143 143
     public:
144 144
     // fields is 0 because it is dynamically calculated
145 145
     const static size_t fields = 0;
146  
-    const static object_type type = BContextType;
  146
+    const static object_type type = BlockContextType;
147 147
 
148 148
     BlockEnvironment* env();
149 149
 
12  vm/builtin/executable.cpp
@@ -10,18 +10,6 @@
10 10
 #include "objectmemory.hpp"
11 11
 
12 12
 namespace rubinius {
13  
-  template <>
14  
-    bool kind_of<Executable>(OBJECT obj) {
15  
-      if(obj->obj_type == Executable::type ||
16  
-         obj->obj_type == AccessVariableType ||
17  
-         obj->obj_type == CMethodType ||
18  
-         obj->obj_type == NativeFuncType ||
19  
-         obj->obj_type == NMethodType) {
20  
-        return true;
21  
-      }
22  
-
23  
-      return false;
24  
-    }
25 13
 
26 14
   void Executable::init(STATE) {
27 15
     GO(executable).set(state->new_class("Executable", G(object), Executable::fields));
24  vm/builtin/fixnum.cpp
@@ -8,30 +8,6 @@
8 8
 #include <iostream>
9 9
 
10 10
 namespace rubinius {
11  
-
12  
-  /* See t1 */
13  
-  template <>
14  
-  bool kind_of<Integer>(OBJECT obj) {
15  
-    return obj->fixnum_p() || (obj->reference_p() && obj->obj_type == Bignum::type);
16  
-  }
17  
-
18  
-  template <>
19  
-  bool kind_of<Fixnum>(OBJECT obj) {
20  
-    return obj->fixnum_p();
21  
-  }
22  
-
23  
-  /* For some reason, the as<> template doesn't pick up the
24  
-   * specialized kind_of<>, until we figure out why, just special as<>
25  
-   * too. */
26  
-  template <>
27  
-  INTEGER as<Integer>(OBJECT obj) {
28  
-    if(!kind_of<Integer>(obj)) {
29  
-      TypeError::raise(obj->obj_type, obj, "can't be cast as an Integer");
30  
-    }
31  
-    return (Integer*)obj;
32  
-  }
33  
-
34  
-
35 11
   /* WARNING. Do not use this version if +num+ has the chance of being
36 12
    * greater than FIXNUM_MAX or less than FIXNUM_MIN. */
37 13
   FIXNUM Fixnum::from(native_int num) {
2  vm/builtin/float.hpp
@@ -16,7 +16,7 @@
16 16
 namespace rubinius {
17 17
   class Array;
18 18
 
19  
-  class Float : public Object {
  19
+  class Float : public Numeric {
20 20
     public:
21 21
     const static size_t fields = 0;
22 22
     const static object_type type = FloatType;
22  vm/builtin/immediates.cpp
@@ -4,28 +4,6 @@
4 4
 
5 5
 namespace rubinius {
6 6
 
7  
-  /* NOTE(t1):
8  
-   * This looks scary, but it's pretty simple. We're specializing
9  
-   * the kind_of when passed NilClass to just test using nil_p().
10  
-   * This makes kind_of smarter, letting us use it everywhere for
11  
-   * type checks. */
12  
-  template <>
13  
-    bool kind_of<NilClass>(OBJECT obj) {
14  
-      return obj == Qnil;
15  
-    }
16  
-
17  
-  /* See t1 */
18  
-  template <>
19  
-    bool kind_of<TrueClass>(OBJECT obj) {
20  
-      return obj == Qtrue;
21  
-    }
22  
-
23  
-  /* See t1 */
24  
-  template <>
25  
-    bool kind_of<FalseClass>(OBJECT obj) {
26  
-      return obj == Qfalse;
27  
-    }
28  
-
29 7
   void FalseClass::Info::mark(OBJECT t, ObjectMark& mark) { }
30 8
 
31 9
   void FalseClass::Info::show(STATE, OBJECT self, int level) {
9  vm/builtin/integer.cpp
@@ -20,15 +20,6 @@ namespace rubinius {
20 20
     return as<Bignum>(this)->to_long_long();
21 21
   }
22 22
 
23  
-  // TODO: double check that this links. Evan says it doesn't. I'll
24  
-  // check my Meiers books when I get home
25  
-  template <>
26  
-  bool kind_of<Numeric>(OBJECT obj) {
27  
-    return obj->fixnum_p() ||
28  
-      (obj->reference_p() && (obj->obj_type == Bignum::type ||
29  
-                              obj->obj_type == Float::type));
30  
-  }
31  
-
32 23
   INTEGER Integer::from(STATE, int num) {
33 24
 #if (CONFIG_WORDSIZE != 64)
34 25
     if(num > FIXNUM_MAX || num < FIXNUM_MIN) {
2  vm/builtin/iseq.cpp
@@ -7,7 +7,7 @@
7 7
 namespace rubinius {
8 8
   void InstructionSequence::init(STATE) {
9 9
     GO(iseq).set(state->new_class("InstructionSequence", G(object), InstructionSequence::fields));
10  
-    G(iseq)->set_object_type(state, ISeqType);
  10
+    G(iseq)->set_object_type(state, InstructionSequenceType);
11 11
   }
12 12
 
13 13
   InstructionSequence* InstructionSequence::create(STATE, size_t instructions) {
2  vm/builtin/iseq.hpp
@@ -10,7 +10,7 @@ namespace rubinius {
10 10
   class InstructionSequence : public Object {
11 11
   public:
12 12
     const static size_t fields = 2;
13  
-    const static object_type type = ISeqType;
  13
+    const static object_type type = InstructionSequenceType;
14 14
 
15 15
   private:
16 16
     Tuple* opcodes_;     // slot
7  vm/builtin/lookuptable.cpp
@@ -26,13 +26,6 @@
26 26
 
27 27
 namespace rubinius {
28 28
 
29  
-  template <>
30  
-    bool kind_of<LookupTable>(OBJECT obj) {
31  
-      return obj->reference_p() &&
32  
-        (obj->obj_type == LookupTable::type ||
33  
-         obj->obj_type == MTType);
34  
-    }
35  
-
36 29
   LookupTable* LookupTable::create(STATE, size_t size) {
37 30
     LookupTable *tbl;
38 31
 
4  vm/builtin/memorypointer.cpp
@@ -30,7 +30,7 @@ namespace rubinius {
30 30
 
31 31
   void MemoryPointer::init(STATE) {
32 32
     GO(memory_pointer).set(state->new_class("MemoryPointer"));
33  
-    G(memory_pointer)->set_object_type(state, MemPtrType);
  33
+    G(memory_pointer)->set_object_type(state, MemoryPointerType);
34 34
   }
35 35
 
36 36
   MemoryPointer* MemoryPointer::create(STATE, void* ptr) {
@@ -299,7 +299,7 @@ namespace rubinius {
299 299
         WRITE(void*, NULL);
300 300
       } else {
301 301
         MemoryPointer *mp = as<MemoryPointer>(val);
302  
-        type_assert(val, MemPtrType, "converting to pointer");
  302
+        type_assert(val, MemoryPointerType, "converting to pointer");
303 303
         WRITE(void*, mp->pointer);
304 304
       }
305 305
       break;
2  vm/builtin/memorypointer.hpp
@@ -8,7 +8,7 @@ namespace rubinius {
8 8
   class MemoryPointer : public Object {
9 9
     public:
10 10
     const static size_t fields = 0;
11  
-    const static object_type type = MemPtrType;
  11
+    const static object_type type = MemoryPointerType;
12 12
 
13 13
     void* pointer;
14 14
     bool autorelease;
2  vm/builtin/methodtable.hpp
@@ -6,7 +6,7 @@
6 6
 namespace rubinius {
7 7
   class MethodTable : public LookupTable {
8 8
     public:
9  
-    const static object_type type = MTType;
  9
+    const static object_type type = MethodTableType;
10 10
 
11 11
     static MethodTable* create(STATE);
12 12
 
2  vm/builtin/methodvisibility.hpp
@@ -9,7 +9,7 @@ namespace rubinius {
9 9
   class MethodVisibility : public Object {
10 10
   public:
11 11
     const static size_t fields = 2;
12  
-    const static object_type type = CMVisibilityType;
  12
+    const static object_type type = MethodVisibilityType;
13 13
 
14 14
   private:
15 15
     SYMBOL visibility_;  // slot
2  vm/builtin/module.hpp
@@ -54,7 +54,7 @@ namespace rubinius {
54 54
   class IncludedModule : public Module {
55 55
   public:
56 56
     const static size_t fields = Module::fields + 1;
57  
-    const static object_type type = IncModType;
  57
+    const static object_type type = IncludedModuleType;
58 58
 
59 59
   private:
60 60
     OBJECT module_; // slot
4  vm/builtin/nativefunction.cpp
@@ -64,7 +64,7 @@ namespace rubinius {
64 64
   void NativeFunction::init(STATE) {
65 65
     GO(native_function).set(state->new_class("NativeFunction", G(executable),
66 66
           NativeFunction::fields));
67  
-    G(native_function)->set_object_type(state, NativeFuncType);
  67
+    G(native_function)->set_object_type(state, NativeFunctionType);
68 68
 
69 69
     G(rubinius)->set_const(state, "LIBSUFFIX", String::create(state, LIBSUFFIX));
70 70
   }
@@ -505,7 +505,7 @@ namespace rubinius {
505 505
           *tmp = NULL;
506 506
         } else {
507 507
           MemoryPointer *mp = as<MemoryPointer>(obj);
508  
-          type_assert(obj, MemPtrType, "converting to pointer");
  508
+          type_assert(obj, MemoryPointerType, "converting to pointer");
509 509
           *tmp = mp->pointer;
510 510
         }
511 511
         values[i] = tmp;
2  vm/builtin/nativefunction.hpp
@@ -9,7 +9,7 @@ namespace rubinius {
9 9
   class NativeFunction : public Executable {
10 10
   public:
11 11
     static const size_t fields = 7;
12  
-    static const object_type type = NativeFuncType;
  12
+    static const object_type type = NativeFunctionType;
13 13
 
14 14
   private:
15 15
     OBJECT name_;         // slot
4  vm/builtin/nativemethod.hpp
@@ -87,12 +87,12 @@ namespace rubinius {
87 87
     public:   /* Ruby slots and bookkeeping */
88 88
 
89 89
     const static size_t fields = 5;
90  
-    const static object_type type = NMethodType;
  90
+    const static object_type type = NativeMethodType;
91 91
 
92 92
   static void register_class_with(VM* state)
93 93
   {
94 94
     state->globals.nmethod.set(state->new_class("NativeMethod", state->globals.executable.get(), NativeMethod::fields));
95  
-    state->globals.nmethod.get()->set_object_type(state, NMethodType);
  95
+    state->globals.nmethod.get()->set_object_type(state, NativeMethodType);
96 96
   }
97 97
 
98 98
     private:  /* Instance vars */
4  vm/builtin/nativemethodcontext.cpp
@@ -41,7 +41,7 @@ namespace rubinius {
41 41
 
42 42
     this->module(my_state, my_message->module);
43 43
 
44  
-    this->name(my_state, as<Object>(my_message->name));
  44
+    this->name(my_state, my_message->name);
45 45
 
46 46
 //    my_stack_size = DEFAULT_STACK_SIZE;
47 47
 //    my_stack = new char[my_stack_size];
@@ -97,7 +97,7 @@ namespace rubinius {
97 97
    */
98 98
   void NativeMethodContext::register_class_with(VM* state) {
99 99
     state->globals.nativectx.set(state->new_class("NativeMethodContext", state->globals.methctx.get()));
100  
-    state->globals.nativectx.get()->set_object_type(state, NContextType);
  100
+    state->globals.nativectx.get()->set_object_type(state, NativeMethodContextType);
101 101
   }
102 102
 }
103 103
 
4  vm/builtin/nativemethodcontext.hpp
@@ -50,7 +50,7 @@ namespace rubinius {
50 50
           : my_index(0)
51 51
           , my_storage(&storage)
52 52
         {
53  
-          my_storage->push_back(as<Object>(obj));
  53
+          my_storage->push_back(obj);
54 54
           my_index = my_storage->size() - 1;
55 55
         }
56 56
 
@@ -178,7 +178,7 @@ namespace rubinius {
178 178
     public:   /* Slots and bookkeeping. */
179 179
 
180 180
         const static size_t   fields  = 0;      // TODO: Check this
181  
-    const static object_type  type    = NContextType;
  181
+    const static object_type  type    = NativeMethodContextType;
182 182
 
183 183
 
184 184
     /*  OK, these are the slots we get from MethodContext (and all we really need.)
132  vm/builtin/object.cpp
@@ -24,50 +24,6 @@
24 24
 
25 25
 namespace rubinius {
26 26
 
27  
-  template <>
28  
-    bool kind_of<Object>(OBJECT obj) {
29  
-      return true;
30  
-    }
31  
-
32  
-  template <>
33  
-    bool instance_of<Object>(OBJECT obj) {
34  
-      return obj->get_type() == ObjectType;
35  
-    }
36  
-
37  
-  /**
38  
-   *  Cast any class into an Object (specialised.)
39  
-   *
40  
-   *  Specialised version of  as().
41  
-   *
42  
-   *  Everything but NULL pointers can be cast into Objects.
43  
-   *  NULLs cause an assertion.
44  
-   *
45  
-   *  @see  vm/object.hpp for the general version.
46  
-   */
47  
-  template <>
48  
-    Object* as<Object>(OBJECT obj)
49  
-    {
50  
-      sassert(obj);
51  
-      return obj;
52  
-    }
53  
-
54  
-  /**
55  
-   *  Cast any class into an Object (specialised.)
56  
-   *
57  
-   *  Specialised version of try_as().
58  
-   *
59  
-   *  Everything but NULL pointers can be cast into Objects.
60  
-   *  NULLs cause an assertion.
61  
-   *
62  
-   *  @see  vm/object.hpp for the general version.
63  
-   */
64  
-  template <>
65  
-    Object* try_as<Object>(OBJECT obj)
66  
-    {
67  
-      sassert(obj);
68  
-      return obj;
69  
-    }
70  
-
71 27
   bool Object::fixnum_p() {
72 28
     return FIXNUM_P(this);
73 29
   }
@@ -217,92 +173,6 @@ namespace rubinius {
217 173
     }
218 174
   }
219 175
 
220  
-  const char* Object::type_to_name(object_type t) {
221  
-    const char* type;
222  
-
223  
-    switch(t) {
224  
-    case ObjectType:
225  
-      type = "Object";
226  
-      break;
227  
-    case MContextType:
228  
-      type = "MethodContext";
229  
-      break;
230  
-    case BContextType:
231  
-      type = "BlockContext";
232  
-      break;
233  
-    case NContextType:
234  
-      type = "NativeMethodContext";
235  
-      break;
236  
-    case ClassType:
237  
-      type = "Class";
238  
-      break;
239  
-    case MetaclassType:
240  
-      type = "Metaclass";
241  
-      break;
242  
-    case MTType:
243  
-      type = "MethodTable";
244  
-      break;
245  
-    case WrapsStructType:
246  
-      type = "SubtendCStructure";
247  
-      break;
248  
-    case IncModType:
249  
-      type = "included Module";
250  
-      break;
251  
-    case TaskType:
252  
-      type = "Task";
253  
-      break;
254  
-    case FixnumType:
255  
-      type = "Fixnum";
256  
-      break;
257  
-    case BignumType:
258  
-      type = "Bignum";
259  
-      break;
260  
-    case FloatType:
261  
-      type = "Float";
262  
-      break;
263  
-    case MemPtrType:
264  
-      type = "MemoryPointer";
265  
-      break;
266  
-    case StringType:
267  
-      type = "String";
268  
-      break;
269  
-    case SymbolType:
270  
-      type = "Symbol";
271  
-      break;
272  
-    case CMethodType:
273  
-      type = "CompiledMethod";
274  
-      break;
275  
-    case NativeFuncType:
276  
-      type = "NativeFunction";
277  
-      break;
278  
-    case NMethodType:
279  
-      type = "NativeMethod";
280  
-      break;
281  
-    case NilType:
282  
-      type = "nil";
283  
-      break;
284  
-    case LookupTableType:
285  
-      type = "LookupTable";
286  
-      break;
287  
-    case DirType:
288  
-      type = "Dir";
289  
-      break;
290  
-    case CompactLookupTableType:
291  
-      type = "CompactLookupTable";
292  
-      break;
293  
-    case TimeType:
294  
-      type = "Time";
295  
-      break;
296  
-    case TaskProbeType:
297  
-      type = "TaskProbe";
298  
-      break;
299  
-    default:
300  
-      type = "unknown";
301  
-      break;
302  
-    }
303  
-    return type;
304  
-  }
305  
-
306 176
   Class* Object::class_object(STATE) {
307 177
     if(reference_p()) {
308 178
       Class* cls = klass_;
@@ -378,7 +248,7 @@ namespace rubinius {
378 248
       found = (Class*)found->superclass();
379 249
       if(found == cls) return true;
380 250
 
381  
-      if(found->reference_p() && found->obj_type == IncModType) {
  251
+      if(found->reference_p() && found->obj_type == IncludedModuleType) {
382 252
         if(((IncludedModule*)found)->module() == cls) return true;
383 253
       }
384 254
     }
2  vm/builtin/object.hpp
@@ -168,8 +168,6 @@ namespace rubinius {
168 168
     void copy_ivars(STATE, OBJECT other);
169 169
     void copy_metaclass(STATE, OBJECT other);
170 170
 
171  
-    static const char* type_to_name(object_type type);
172  
-
173 171
     /* VM level primitives. It's dumb to have them here, but it's more
174 172
      * complicated to make field_extract parse non-Object classes. */
175 173
 
6  vm/builtin/symbol.cpp
@@ -14,12 +14,6 @@
14 14
 #define Increments 32
15 15
 
16 16
 namespace rubinius {
17  
-  /* See Note(t1) in immediates.cpp */
18  
-  template <>
19  
-    bool kind_of<Symbol>(OBJECT obj) {
20  
-      return obj->symbol_p();
21  
-    }
22  
-
23 17
   void Symbol::init(STATE) {
24 18
     GO(symbol).set(state->new_class("Symbol"));
25 19
   }
8  vm/builtin/tuple.cpp
@@ -8,14 +8,6 @@
8 8
 #include <iostream>
9 9
 
10 10
 namespace rubinius {
11  
-
12  
-  template <>
13  
-    bool kind_of<Tuple>(OBJECT obj) {
14  
-      return obj->reference_p() && (
15  
-              obj->obj_type == Tuple::type ||
16  
-              obj->obj_type == CompactLookupTable::type);
17  
-    }
18  
-
19 11
   OBJECT Tuple::at(size_t index) {
20 12
     if(num_fields() <= index) {
21 13
       ObjectBoundsExceeded::raise(this, index);
64  vm/codegen/field_extract.rb
@@ -141,9 +141,11 @@ def initialize(name)
141 141
     @flags = {}
142 142
     @primitives = {}
143 143
     @num_fields = 0
  144
+    @subclasses = []
144 145
   end
145 146
 
146 147
   attr_accessor :name, :super, :fields, :primitives, :flags, :num_fields
  148
+  attr_accessor :subclasses
147 149
 
148 150
   def add_field(idx, name, type, flag=nil)
149 151
     if flag
@@ -308,6 +310,42 @@ def generate_mark
308 310
 
309 311
     str
310 312
   end
  313
+
  314
+  def kind_of_code(what)
  315
+    case @name
  316
+    when "Fixnum"
  317
+      return "FIXNUM_P(#{what})"
  318
+    when "Symbol"
  319
+      return "SYMBOL_P(#{what})"
  320
+    when "TrueClass"
  321
+      return "#{what} == Qtrue"
  322
+    when "FalseClass"
  323
+      return "#{what} == Qfalse"
  324
+    when "NilClass"
  325
+      return "#{what} == Qnil"
  326
+    else
  327
+      return "(REFERENCE_P(#{what}) && #{what}->obj_type == #{@name}Type)"
  328
+    end
  329
+  end
  330
+
  331
+  def kind_of_conditions(what)
  332
+    [kind_of_code(what)] + @subclasses.map do |cpp|
  333
+      cpp.kind_of_conditions(what)
  334
+    end
  335
+  end
  336
+
  337
+  def generate_kind_of
  338
+    checks = kind_of_conditions("obj")
  339
+
  340
+    # We forward declare the class in here to keep everything happy
  341
+    str = <<-CPP
  342
+template <>
  343
+static bool kind_of<#{@name}>(Object* obj) {
  344
+  return #{checks.join(' || ')};
  345
+}
  346
+
  347
+    CPP
  348
+  end
311 349
 end
312 350
 
313 351
 class CPPParser
@@ -374,6 +412,7 @@ def parse_stream(f)
374 412
         if sup = @classes[m[2]]
375 413
           cpp = CPPClass.new(m[1])
376 414
           cpp.super = sup
  415
+          sup.subclasses << cpp
377 416
         else
378 417
           next
379 418
         end
@@ -490,7 +529,7 @@ def write_if_new(path)
490 529
     yield f
491 530
   end
492 531
 
493  
-  File.rename tmp_path, path unless system("diff -q #{path} #{tmp_path} 2>&1")
  532
+  File.rename tmp_path, path unless system("diff -q #{path} #{tmp_path} > /dev/null 2>&1")
494 533
 ensure
495 534
   File.unlink tmp_path if File.exist? tmp_path
496 535
 end
@@ -585,6 +624,29 @@ def write_if_new(path)
585 624
   end
586 625
 end
587 626
 
  627
+write_if_new "vm/gen/object_types.hpp" do |f|
  628
+  f.puts "typedef enum {"
  629
+  f.puts "  InvalidType = 0,"
  630
+  f.puts "  NilType,"
  631
+  f.puts "  TrueType,"
  632
+  f.puts "  FalseType,"
  633
+  parser.classes.map { |n, cpp| cpp.name}.sort.each do |name|
  634
+    f.puts "  #{name}Type,"
  635
+  end
  636
+  f.puts "  LastObjectType"
  637
+  f.puts "} object_type;"
  638
+  f.puts
  639
+end
  640
+
  641
+write_if_new "vm/gen/kind_of.hpp" do |f|
  642
+
  643
+  parser.classes.each do |n, cpp|
  644
+    next if cpp.name == "Object"
  645
+    f.puts "class #{cpp.name};"
  646
+    f.puts cpp.generate_kind_of
  647
+  end
  648
+end
  649
+
588 650
 write_if_new "vm/gen/primitives_glue.gen.cpp" do |f|
589 651
   names = []
590 652
   parser.classes.sort_by { |name,| name }.each do |n, cpp|
51  vm/object.hpp
@@ -21,20 +21,28 @@
21 21
 
22 22
 namespace rubinius {
23 23
 
  24
+#define sassert(cond) if(!(cond)) Assertion::raise(#cond)
  25
+
24 26
   /**
25 27
    *  Ruby type system subtype check.
26 28
    *
27 29
    *  Given builtin-class +T+, return true if +obj+ is of class +T+
28 30
    */
29 31
   template <class T>
30  
-    bool kind_of(OBJECT obj) {
31  
-      if(obj->reference_p()) {
  32
+    static bool kind_of(Object* obj) {
  33
+      if(REFERENCE_P(obj)) {
32 34
         return obj->obj_type == T::type;
33 35
       }
34 36
       return false;
35 37
     }
36 38
 
37  
-  template <> bool kind_of<Object>(OBJECT obj);
  39
+  /**
  40
+   * A specialized version for completeness.
  41
+   */
  42
+  template <>
  43
+    static bool kind_of<Object>(Object* obj) {
  44
+      return true;
  45
+    }
38 46
 
39 47
   /**
40 48
    *  Ruby type system class check.
@@ -44,16 +52,20 @@ namespace rubinius {
44 52
    *  one.
45 53
    */
46 54
   template <class T>
47  
-    bool instance_of(OBJECT obj) {
48  
-      if(obj->reference_p()) {
  55
+    static bool instance_of(Object* obj) {
  56
+      if(REFERENCE_P(obj)) {
49 57
         return obj->obj_type == T::type;
50 58
       }
51 59
       return false;
52 60
     }
53 61
 
54  
-  template <> bool instance_of<Object>(OBJECT obj);
55  
-
56  
-#define sassert(cond) if (!(cond)) Assertion::raise(#cond)
  62
+  /**
  63
+   * A specialized version for completeness.
  64
+   */
  65
+  template <>
  66
+    static bool instance_of<Object>(Object* obj) {
  67
+      return obj->reference_p() && (obj->get_type() == ObjectType);
  68
+    }
57 69
 
58 70
   /*
59 71
    *  There is NO reason why as() or try_as() should be getting
@@ -70,7 +82,7 @@ namespace rubinius {
70 82
    *  @see  builtin/object.cpp has specialised versions.
71 83
    */
72 84
   template <class T>
73  
-    T* as(OBJECT obj) {
  85
+    static T* as(Object* obj) {
74 86
       sassert(NULL != obj);
75 87
 
76 88
       if(!kind_of<T>(obj))
@@ -79,11 +91,13 @@ namespace rubinius {
79 91
       return static_cast<T*>(obj);
80 92
     }
81 93
 
82  
-  /** Specialised cast to always succeed if not NULL.
83  
-   *
84  
-   *  Implemented in builtin/object.cpp.
  94
+  /**
  95
+   * A specialized version for completeness.
85 96
    */
86  
-  template <> Object* as<Object>(OBJECT obj);
  97
+  template <>
  98
+    static Object* as<Object>(Object* obj) {
  99
+      return obj;
  100
+    }
87 101
 
88 102
   /**
89 103
    *  Non-raising version of as().
@@ -94,7 +108,7 @@ namespace rubinius {
94 108
    *  @see  builtin/object.cpp has specialised versions.
95 109
    */
96 110
   template <class T>
97  
-    T* try_as(OBJECT obj) {
  111
+    static T* try_as(Object* obj) {
98 112
       sassert(NULL != obj);
99 113
 
100 114
       if(!kind_of<T>(obj))
@@ -103,11 +117,6 @@ namespace rubinius {
103 117
       return static_cast<T*>(obj);
104 118
     }
105 119
 
106  
-  /** Specialised cast to always succeed if not NULL.
107  
-   *
108  
-   *  Implemented in builtin/object.cpp.
109  
-   */
110  
-  template <> Object* try_as<Object>(OBJECT obj);
111 120
 
112 121
   void type_assert(OBJECT obj, object_type type, const char* reason);
113 122
 
@@ -135,6 +144,8 @@ namespace rubinius {
135 144
   if(s->free != NULL) { s->free(s->ptr); } \
136 145
 } while (0)
137 146
 
138  
-};
  147
+#include "gen/kind_of.hpp"
  148
+
  149
+}
139 150
 
140 151
 #endif
60  vm/object_types.hpp
@@ -2,65 +2,7 @@
2 2
 #define RBX_VM_OBJECT_TYPES_HPP
3 3
 
4 4
 namespace rubinius {
5  
-  /* rubinius_object types, takes up 3 bits */
6  
-  typedef enum
7  
-  {
8  
-    InvalidType     = 0,
9  
-    NumericType     ,
10  
-    IntegerType     ,
11  
-    FalseType       ,
12  
-    TrueType        ,
13  
-    NilType         ,
14  
-    ObjectType      ,
15  
-    MContextType    ,
16  
-    BContextType    ,
17  
-    ClassType       ,
18  
-    MetaclassType   ,
19  
-    MTType          ,
20  
-    WrapsStructType ,
21  
-    IncModType      ,
22  
-    TaskType        ,
23  
-    FixnumType      ,
24  
-    BignumType      ,
25  
-    FloatType       ,
26  
-    MemPtrType      ,
27  
-    StringType      ,
28  
-    SymbolType      ,
29  
-    CMethodType     ,
30  
-    BlockEnvType    ,
31  
-    TupleType       ,
32  
-    ArrayType       ,
33  
-    RegexpDataType  ,
34  
-    RegexpType      ,
35  
-    ByteArrayType   ,
36  
-    ISeqType        ,
37  
-    ChannelType     ,
38  
-    ThreadType      ,
39  
-    ModuleType      ,
40  
-    SendSiteType    ,
41  
-    SelectorType    ,
42  
-    LookupTableType ,
43  
-    IOBufferType    ,
44  
-    StaticScopeType ,
45  
-    MatchDataType   ,
46  
-    ExceptionType   ,
47  
-    IOType          ,
48  
-    ExecutableType  ,
49  
-    CMVisibilityType,
50  
-    ListType        ,
51  
-    ListNodeType    ,
52  
-    NativeFuncType  ,
53  
-    DirType         ,
54  
-    CompactLookupTableType,
55  
-    AccessVariableType,
56  
-    TimeType        ,
57  
-    TaskProbeType   ,
58  
-
59  
-    NMethodType     ,
60  
-    NContextType    ,
61  
-
62  
-    LastObjectType   // must remain at end
63  
-  } object_type;
  5
+  #include "gen/object_types.hpp"
64 6
 }
65 7
 
66 8
 #endif
4  vm/ontology.cpp
@@ -84,7 +84,7 @@ namespace rubinius {
84 84
 
85 85
     /* Create MetaClass */
86 86
     GO(metaclass).set(new_basic_class(cls, MetaClass::fields));
87  
-    G(metaclass)->set_object_type(state, MetaclassType);
  87
+    G(metaclass)->set_object_type(state, MetaClassType);
88 88
 
89 89
     /* Create Tuple */
90 90
     GO(tuple).set(new_basic_class(object, Tuple::fields));
@@ -96,7 +96,7 @@ namespace rubinius {
96 96
 
97 97
     /* Create MethodTable */
98 98
     GO(methtbl).set(new_basic_class(G(lookuptable), MethodTable::fields));
99  
-    G(methtbl)->set_object_type(state, MTType);
  99
+    G(methtbl)->set_object_type(state, MethodTableType);
100 100
 
101 101
     /* Now, we have:
102 102
      *  Class
2  vm/oop.hpp
@@ -4,6 +4,7 @@
4 4
 #include <cstddef>
5 5
 #include <ctype.h>
6 6
 #include <stdint.h>
  7
+
7 8
 #include "object_types.hpp"
8 9
 
9 10
 namespace rubinius {
@@ -181,4 +182,5 @@ to be a simple test for that bit pattern.
181 182
 
182 183
 }
183 184
 
  185
+
184 186
 #endif
4  vm/test/test_memorypointer.hpp
@@ -272,7 +272,7 @@ class TestMemoryPointer : public CxxTest::TestSuite {
272 272
     MemoryPointer* ptr = MemoryPointer::create(state, &val);
273 273
 
274 274
     OBJECT obj = ptr->get_field(state, 0, RBX_FFI_TYPE_PTR);
275  
-    TS_ASSERT(obj->check_type(MemPtrType));
  275
+    TS_ASSERT(obj->check_type(MemoryPointerType));
276 276
 
277 277
     TS_ASSERT_EQUALS(as<MemoryPointer>(obj)->pointer, val);
278 278
   }
@@ -323,7 +323,7 @@ class TestMemoryPointer : public CxxTest::TestSuite {
323 323
     String *so = as<String>(ary->get(state, 0));
324 324
     TS_ASSERT(!strncmp(str, so->byte_address(), 4));
325 325
 
326  
-    TS_ASSERT(ary->get(state, 1)->check_type(MemPtrType));
  326
+    TS_ASSERT(ary->get(state, 1)->check_type(MemoryPointerType));
327 327
     MemoryPointer* mp = as<MemoryPointer>(ary->get(state, 1));
328 328
     TS_ASSERT_EQUALS(mp->pointer, str);
329 329
   }
40  vm/test/test_nativefunction.hpp
@@ -91,7 +91,7 @@ class TestNativeFunction : public CxxTest::TestSuite {
91 91
     NativeFunction *func = NativeFunction::bind(state, Qnil, name, args, ret);
92 92
 
93 93
     TS_ASSERT(!func->nil_p());
94  
-    TS_ASSERT(func->data()->check_type(MemPtrType));
  94
+    TS_ASSERT(func->data()->check_type(MemoryPointerType));
95 95
 
96 96
     Array* input = Array::create(state, 1);
97 97
     input->set(state, 0, name);
@@ -116,7 +116,7 @@ class TestNativeFunction : public CxxTest::TestSuite {
116 116
     NativeFunction *func = NativeFunction::bind(state, Qnil, name, args, ret);
117 117
 
118 118
     TS_ASSERT(!func->nil_p());
119  
-    TS_ASSERT(func->data()->check_type(MemPtrType));
  119
+    TS_ASSERT(func->data()->check_type(MemoryPointerType));
120 120
 
121 121
     Array* input = Array::create(state, 2);
122 122
     input->set(state, 0, Qnil);
@@ -140,7 +140,7 @@ class TestNativeFunction : public CxxTest::TestSuite {
140 140
     NativeFunction *func = NativeFunction::bind(state, Qnil, name, args, ret);
141 141
 
142 142
     TS_ASSERT(!func->nil_p());
143  
-    TS_ASSERT(func->data()->check_type(MemPtrType));
  143
+    TS_ASSERT(func->data()->check_type(MemoryPointerType));
144 144
 
145 145
     Array* input = Array::create(state, 1);
146 146
     input->set(state, 0, Fixnum::from(13));
@@ -164,7 +164,7 @@ class TestNativeFunction : public CxxTest::TestSuite {
164 164
     NativeFunction *func = NativeFunction::bind(state, Qnil, name, args, ret);
165 165
 
166 166
     TS_ASSERT(!func->nil_p());
167  
-    TS_ASSERT(func->data()->check_type(MemPtrType));
  167
+    TS_ASSERT(func->data()->check_type(MemoryPointerType));
168 168
 
169 169
     Array* input = Array::create(state, 1);
170 170
     input->set(state, 0, Fixnum::from(13));
@@ -188,7 +188,7 @@ class TestNativeFunction : public CxxTest::TestSuite {
188 188
     NativeFunction *func = NativeFunction::bind(state, Qnil, name, args, ret);
189 189
 
190 190
     TS_ASSERT(!func->nil_p());
191  
-    TS_ASSERT(func->data()->check_type(MemPtrType));
  191
+    TS_ASSERT(func->data()->check_type(MemoryPointerType));
192 192
 
193 193
     Array* input = Array::create(state, 1);
194 194
     input->set(state, 0, Fixnum::from(13));
@@ -212,7 +212,7 @@ class TestNativeFunction : public CxxTest::TestSuite {
212 212
     NativeFunction *func = NativeFunction::bind(state, Qnil, name, args, ret);
213 213
 
214 214
     TS_ASSERT(!func->nil_p());
215  
-    TS_ASSERT(func->data()->check_type(MemPtrType));
  215
+    TS_ASSERT(func->data()->check_type(MemoryPointerType));
216 216
 
217 217
     Array* input = Array::create(state, 2);
218 218
     input->set(state, 0, Fixnum::from(0));
@@ -245,7 +245,7 @@ class TestNativeFunction : public CxxTest::TestSuite {
245 245
     NativeFunction *func = NativeFunction::bind(state, Qnil, name, args, ret);
246 246
 
247 247
     TS_ASSERT(!func->nil_p());
248  
-    TS_ASSERT(func->data()->check_type(MemPtrType));
  248
+    TS_ASSERT(func->data()->check_type(MemoryPointerType));
249 249
 
250 250
     Array* input = Array::create(state, 1);
251 251
     input->set(state, 0, Fixnum::from(13));
@@ -279,7 +279,7 @@ class TestNativeFunction : public CxxTest::TestSuite {
279 279
     NativeFunction *func = NativeFunction::bind(state, Qnil, name, args, ret);
280 280
 
281 281
     TS_ASSERT(!func->nil_p());
282  
-    TS_ASSERT(func->data()->check_type(MemPtrType));
  282
+    TS_ASSERT(func->data()->check_type(MemoryPointerType));
283 283
 
284 284
     Array* input = Array::create(state, 1);
285 285
     input->set(state, 0, Fixnum::from(13));
@@ -313,7 +313,7 @@ class TestNativeFunction : public CxxTest::TestSuite {
313 313
     NativeFunction *func = NativeFunction::bind(state, Qnil, name, args, ret);
314 314
 
315 315
     TS_ASSERT(!func->nil_p());
316  
-    TS_ASSERT(func->data()->check_type(MemPtrType));
  316
+    TS_ASSERT(func->data()->check_type(MemoryPointerType));
317 317
 
318 318
     Array* input = Array::create(state, 1);
319 319
     input->set(state, 0, Fixnum::from(13));
@@ -347,7 +347,7 @@ class TestNativeFunction : public CxxTest::TestSuite {
347 347
     NativeFunction *func = NativeFunction::bind(state, Qnil, name, args, ret);
348 348
 
349 349
     TS_ASSERT(!func->nil_p());
350  
-    TS_ASSERT(func->data()->check_type(MemPtrType));
  350
+    TS_ASSERT(func->data()->check_type(MemoryPointerType));
351 351
 
352 352
     Array* input = Array::create(state, 1);
353 353
     input->set(state, 0, Fixnum::from(13));
@@ -381,7 +381,7 @@ class TestNativeFunction : public CxxTest::TestSuite {
381 381
     NativeFunction *func = NativeFunction::bind(state, Qnil, name, args, ret);
382 382
 
383 383
     TS_ASSERT(!func->nil_p());
384  
-    TS_ASSERT(func->data()->check_type(MemPtrType));
  384
+    TS_ASSERT(func->data()->check_type(MemoryPointerType));
385 385
 
386 386
     Array* input = Array::create(state, 1);
387 387
     input->set(state, 0, Fixnum::from(13));
@@ -415,7 +415,7 @@ class TestNativeFunction : public CxxTest::TestSuite {
415 415
     NativeFunction *func = NativeFunction::bind(state, Qnil, name, args, ret);
416 416
 
417 417
     TS_ASSERT(!func->nil_p());
418  
-    TS_ASSERT(func->data()->check_type(MemPtrType));
  418
+    TS_ASSERT(func->data()->check_type(MemoryPointerType));
419 419
 
420 420
     Array* input = Array::create(state, 1);
421 421
     input->set(state, 0, Fixnum::from(13));
@@ -448,7 +448,7 @@ class TestNativeFunction : public CxxTest::TestSuite {
448 448
     NativeFunction *func = NativeFunction::bind(state, Qnil, name, args, ret);
449 449
 
450 450
     TS_ASSERT(!func->nil_p());
451  
-    TS_ASSERT(func->data()->check_type(MemPtrType));
  451
+    TS_ASSERT(func->data()->check_type(MemoryPointerType));
452 452
 
453 453
     Message* msg = new Message(state);
454 454
 
@@ -468,7 +468,7 @@ class TestNativeFunction : public CxxTest::TestSuite {
468 468
     NativeFunction *func = NativeFunction::bind(state, Qnil, name, args, ret);
469 469
 
470 470
     TS_ASSERT(!func->nil_p());
471  
-    TS_ASSERT(func->data()->check_type(MemPtrType));
  471
+    TS_ASSERT(func->data()->check_type(MemoryPointerType));
472 472
 
473 473
     char buffer[1];
474 474
     buffer[0] = 0;
@@ -505,7 +505,7 @@ class TestNativeFunction : public CxxTest::TestSuite {
505 505
     NativeFunction *func = NativeFunction::bind(state, Qnil, name, args, ret);
506 506
 
507 507
     TS_ASSERT(!func->nil_p());
508  
-    TS_ASSERT(func->data()->check_type(MemPtrType));
  508
+    TS_ASSERT(func->data()->check_type(MemoryPointerType));
509 509
 
510 510
     Array* input = Array::create(state, 1);
511 511
     input->set(state, 0, Float::create(state, 13.2));
@@ -530,7 +530,7 @@ class TestNativeFunction : public CxxTest::TestSuite {
530 530
     NativeFunction *func = NativeFunction::bind(state, Qnil, name, args, ret);
531 531
 
532 532
     TS_ASSERT(!func->nil_p());
533  
-    TS_ASSERT(func->data()->check_type(MemPtrType));
  533
+    TS_ASSERT(func->data()->check_type(MemoryPointerType));