1 /* $Header$ */
2 
3 /* Copyright (c) 2000, 2002 Michael J. Roberts.  All Rights Reserved. */
4 /*
5 Name
6   vmintcls.h - T3 metaclass - intrinsic class
7 Function
8 
9 Notes
10 
11 Modified
12   03/08/00 MJRoberts  - Creation
13 */
14 
15 #ifndef VMINTCLS_H
16 #define VMINTCLS_H
17 
18 
19 #include <stdlib.h>
20 
21 #include "vmtype.h"
22 #include "vmobj.h"
23 #include "vmglob.h"
24 
25 /*
26  *   An IntrinsicClass object represents the class of an instance of an
27  *   intrinsic class.  For example, if we create a BigNumber instance,
28  *   then ask for its class, the result is the IntrinsicClass object
29  *   associated with the BigNumber intrinsic class:
30  *
31  *   Each metaclass in the metaclass dependency table will be associated
32  *   with an IntrinsicClass object.
33  *
34  *   The image file format for an IntrinsicClass object consists of the
35  *   following:
36  *
37  *   UINT2 byte_count (currently, this is always 8)
38  *.  UINT2 metaclass_dependency_table_index
39  *.  UINT4 modifier_object_id
40  */
41 
42 /*
43  *   intrinsic class object
44  */
45 class CVmObjClass: public CVmObject
46 {
47     friend class CVmMetaclassClass;
48 
49 public:
50     /* metaclass registration object */
51     static class CVmMetaclass *metaclass_reg_;
get_metaclass_reg()52     class CVmMetaclass *get_metaclass_reg() const { return metaclass_reg_; }
53 
54     /* am I of the given metaclass? */
is_of_metaclass(class CVmMetaclass * meta)55     virtual int is_of_metaclass(class CVmMetaclass *meta) const
56     {
57         /* try my own metaclass and my base class */
58         return (meta == metaclass_reg_
59                 || CVmObject::is_of_metaclass(meta));
60     }
61 
62     /* is the given object an IntrinsicClass object? */
is_intcls_obj(VMG_ vm_obj_id_t obj)63     static int is_intcls_obj(VMG_ vm_obj_id_t obj)
64         { return vm_objp(vmg_ obj)->is_of_metaclass(metaclass_reg_); }
65 
66     /* create dynamically using stack arguments */
67     static vm_obj_id_t create_from_stack(VMG_ const uchar **pc_ptr,
68                                          uint argc);
69 
70     /* create for a given dependency table index */
71     static vm_obj_id_t create_dyn(VMG_ uint meta_idx);
72 
73     /*
74      *   call a static property - we don't have any of our own, so simply
75      *   "inherit" the base class handling
76      */
call_stat_prop(VMG_ vm_val_t * result,const uchar ** pc_ptr,uint * argc,vm_prop_id_t prop)77     static int call_stat_prop(VMG_ vm_val_t *result,
78                               const uchar **pc_ptr, uint *argc,
79                               vm_prop_id_t prop)
80         { return CVmObject::call_stat_prop(vmg_ result, pc_ptr, argc, prop); }
81 
82     /* determine if I'm an instance of the given object */
83     virtual int is_instance_of(VMG_ vm_obj_id_t obj);
84 
85     /* get superclass information */
86     int get_superclass_count(VMG_ vm_obj_id_t self) const;
87     vm_obj_id_t get_superclass(VMG_ vm_obj_id_t self, int idx) const;
88 
89     /*
90      *   Determine if this is a class object.  All intrinsic class objects
91      *   indicate true.
92      */
is_class_object(VMG_ vm_obj_id_t)93     virtual int is_class_object(VMG_ vm_obj_id_t /*self*/) const
94         { return TRUE; }
95 
96     /* reserve constant data */
reserve_const_data(VMG_ class CVmConstMapper * mapper,vm_obj_id_t self)97     virtual void reserve_const_data(VMG_ class CVmConstMapper *mapper,
98                                     vm_obj_id_t self)
99     {
100         /*
101          *   we reference no other data and cannot be converted to constant
102          *   data ourselves, so there's nothing to do here
103          */
104     }
105 
106     /* convert to constant data */
convert_to_const_data(VMG_ class CVmConstMapper * mapper,vm_obj_id_t self)107     virtual void convert_to_const_data(VMG_ class CVmConstMapper *mapper,
108                                        vm_obj_id_t self)
109     {
110         /*
111          *   we reference no other data and cannot be converted to constant
112          *   data ourselves, so there's nothing to do here
113          */
114     }
115 
116     /* create with no initial contents */
117     static vm_obj_id_t create(VMG_ int in_root_set);
118 
119     /* notify of deletion */
120     void notify_delete(VMG_ int in_root_set);
121 
122     /* set a property */
123     void set_prop(VMG_ class CVmUndo *undo,
124                   vm_obj_id_t self, vm_prop_id_t prop, const vm_val_t *val);
125 
126     /* get a property */
127     int get_prop(VMG_ vm_prop_id_t prop, vm_val_t *val,
128                  vm_obj_id_t self, vm_obj_id_t *source_obj, uint *argc);
129 
130     /* build a list of my properties */
131     void build_prop_list(VMG_ vm_obj_id_t self, vm_val_t *retval);
132 
133     /* undo operations - classes are immutable and hence keep no undo */
notify_new_savept()134     void notify_new_savept() { }
apply_undo(VMG_ struct CVmUndoRecord *)135     void apply_undo(VMG_ struct CVmUndoRecord *) { }
mark_undo_ref(VMG_ struct CVmUndoRecord *)136     void mark_undo_ref(VMG_ struct CVmUndoRecord *) { }
remove_stale_undo_weak_ref(VMG_ struct CVmUndoRecord *)137     void remove_stale_undo_weak_ref(VMG_ struct CVmUndoRecord *) { }
138 
139     /* mark references - we have none */
mark_refs(VMG_ uint)140     void mark_refs(VMG_ uint) { }
141 
142     /* remove weak references - we have none */
remove_stale_weak_refs(VMG0_)143     void remove_stale_weak_refs(VMG0_) { }
144 
145     /* load from an image file */
146     void load_from_image(VMG_ vm_obj_id_t self, const char *ptr, size_t siz);
147 
148     /* rebuild for image file */
149     virtual ulong rebuild_image(VMG_ char *buf, ulong buflen);
150 
151     /* save to a file */
152     void save_to_file(VMG_ class CVmFile *fp);
153 
154     /* restore from a file */
155     void restore_from_file(VMG_ vm_obj_id_t self,
156                            class CVmFile *fp, class CVmObjFixup *fixups);
157 
158     /* reset to the initial load state */
159     void reset_to_image(VMG_ vm_obj_id_t self);
160 
161     /* get the user modifier object for the intrinsic class */
get_mod_obj()162     vm_obj_id_t get_mod_obj() const
163     {
164         /* return the modifier object ID from our extension */
165         return (vm_obj_id_t)osrp4(ext_ + 4);
166     }
167 
168     /*
169      *   find the intrinsic class for the given modifier object, searching
170      *   myself and my intrinsic superclasses
171      */
172     vm_obj_id_t find_mod_src_obj(VMG_ vm_obj_id_t self, vm_obj_id_t mod_obj);
173 
174 protected:
175     /* create with no initial contents */
CVmObjClass()176     CVmObjClass() { ext_ = 0; }
177 
178     /* create with a given dependency table index */
179     CVmObjClass(VMG_ int in_root_set, uint meta_idx, vm_obj_id_t self);
180 
181     /*
182      *   get my metaclass registration table index - this can be compared to
183      *   the metaclass_reg_ element for a given C++ intrinsic class
184      *   implementation to determine if this intrinsic class object is the
185      *   intrinsic class object for a given C++ intrinsic class
186      */
get_meta_idx()187     uint get_meta_idx() const { return osrp2(ext_ + 2); }
188 
189     /* get my metaclass table entry */
190     struct vm_meta_entry_t *get_meta_entry(VMG0_) const;
191 
192     /* list our intrinsic class's properties */
193     size_t list_class_props(VMG_ vm_obj_id_t self,
194                             struct vm_meta_entry_t *entry,
195                             class CVmObjList *lst, size_t starting_idx,
196                             int static_only);
197 
198     /*
199      *   Find the intrinsic class for the given modifier object.  We override
200      *   this because we want an intrinsic class's effective intrinsic class
201      *   to be its intrinsic superclass, not its metaclass.  The metaclass of
202      *   an intrinsic class object is always IntrinsicClass; instead, we want
203      *   to see, for example, List->Collection->Object, which is the
204      *   intrinsic superclass hierarchy.
205      */
find_intcls_for_mod(VMG_ vm_obj_id_t self,vm_obj_id_t mod_obj)206     vm_obj_id_t find_intcls_for_mod(VMG_ vm_obj_id_t self,
207                                     vm_obj_id_t mod_obj)
208     {
209         /*
210          *   The implementation is very simple: just look for a modifier
211          *   object attached to this object or one of its intrinsic
212          *   superclasses.  The difference between this and the regular
213          *   CVmObject implementation is that the CVmObject implementation
214          *   looks in the object's metaclass; we simply look in our intrinsic
215          *   superclasses directly, since, for reflection purposes, we are
216          *   our own metaclass.
217          */
218         return find_mod_src_obj(vmg_ self, mod_obj);
219     }
220 
221     /*
222      *   search for a property among our modifiers, searching our own
223      *   modifier and modifiers for our superclasses
224      */
225     int get_prop_from_mod(VMG_ vm_prop_id_t prop, vm_val_t *val,
226                           vm_obj_id_t self, vm_obj_id_t *source_obj,
227                           uint *argc);
228 
229     /* register myself with the dependency table */
230     void register_meta(VMG_ vm_obj_id_t self);
231 };
232 
233 /* ------------------------------------------------------------------------ */
234 /*
235  *   Registration table object
236  */
237 class CVmMetaclassClass: public CVmMetaclass
238 {
239 public:
240     /* get the global name */
get_meta_name()241     const char *get_meta_name() const { return "intrinsic-class/030000"; }
242 
243     /* create from image file */
create_for_image_load(VMG_ vm_obj_id_t id)244     void create_for_image_load(VMG_ vm_obj_id_t id)
245     {
246         new (vmg_ id) CVmObjClass();
247         G_obj_table->set_obj_gc_characteristics(id, FALSE, FALSE);
248     }
249 
250     /* create from restoring from saved state */
create_for_restore(VMG_ vm_obj_id_t id)251     void create_for_restore(VMG_ vm_obj_id_t id)
252     {
253         new (vmg_ id) CVmObjClass();
254         G_obj_table->set_obj_gc_characteristics(id, FALSE, FALSE);
255     }
256 
257     /* create dynamically using stack arguments */
create_from_stack(VMG_ const uchar ** pc_ptr,uint argc)258     vm_obj_id_t create_from_stack(VMG_ const uchar **pc_ptr, uint argc)
259         { return CVmObjClass::create_from_stack(vmg_ pc_ptr, argc); }
260 
261     /* call a static property */
call_stat_prop(VMG_ vm_val_t * result,const uchar ** pc_ptr,uint * argc,vm_prop_id_t prop)262     int call_stat_prop(VMG_ vm_val_t *result,
263                        const uchar **pc_ptr, uint *argc,
264                        vm_prop_id_t prop)
265     {
266         return CVmObjClass::call_stat_prop(vmg_ result, pc_ptr, argc, prop);
267     }
268 };
269 
270 #endif /* VMINTCLS_H */
271 
272 /*
273  *   Register the class
274  */
275 VM_REGISTER_METACLASS(CVmObjClass)
276