cfad47cfa3/tads3/vmmeta.h

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
1
/* $Header: d:/cvsroot/tads/tads3/VMMETA.H,v 1.2 1999/05/17 02:52:28 MJRoberts Exp $ */
2
3
/* 
4
 *   Copyright (c) 1998, 2002 Michael J. Roberts.  All Rights Reserved.
5
 *   
6
 *   Please see the accompanying license file, LICENSE.TXT, for information
7
 *   on using and copying this software.  
8
 */
9
/*
10
Name
11
  vmmeta.h - metaclass dependency table
12
Function
13
  The metaclass dependency table establishes the correspondence between
14
  metaclass index numbers and metaclasses.  The load image file contains
15
  a list of the metaclasses that the program requires, identifying each
16
  required metaclass with its universally unique identifier string.  At
17
  load time, we scan this list in the load image and create a dependency
18
  table.
19
Notes
20
  
21
Modified
22
  12/01/98 MJRoberts  - Creation
23
*/
24
25
#ifndef VMMETA_H
26
#define VMMETA_H
27
28
#include <stdlib.h>
29
30
#include "t3std.h"
31
#include "vmtype.h"
32
#include "vmglob.h"
33
#include "vmobj.h"
34
35
/* ------------------------------------------------------------------------ */
36
/*
37
 *   Metaclass table entry.  This contains information on the metaclass at
38
 *   one index in the table.  
39
 */
40
struct vm_meta_entry_t
41
{
42
    /* the class descriptor object for the metaclass */
43
    class CVmMetaclass *meta_;
44
45
    /* 
46
     *   name of metaclass as read from image file (this is important for
47
     *   rewriting an image file during preinit, since it ensures that we
48
     *   store only the version number required by the compiled image
49
     *   file, not the version number actually implemented in the preinit
50
     *   interpreter) 
51
     */
52
    char *image_meta_name_;
53
54
    /* 
55
     *   the IntrinsicClass object (a CVmObjClass object) that represents
56
     *   this class 
57
     */
58
    vm_obj_id_t class_obj_;
59
60
    /*
61
     *   Property translation list.  The translation list is an array of
62
     *   internal function numbers, indexed by property ID.  However, not
63
     *   all property ID's are necessarily represented in the index -
64
     *   instead, the index contains entries only from a minimum property
65
     *   ID, and only contains a specified number of entries.  So, given
66
     *   property ID 'prop_id', we find the internal function number for
67
     *   the property at index (prop_id - min_prop_id) in the table.
68
     *   
69
     *   We use an unsigned short (16 bits) for each internal function
70
     *   number - this limits the number of functions per metaclass to
71
     *   65535, which should be more than adequate while keeping memory
72
     *   usage within reason.  
73
     */
74
    vm_prop_id_t min_prop_;
75
    size_t prop_xlat_cnt_;
76
    unsigned short *prop_xlat_;
77
78
    /*
79
     *   Function table.  This is the reverse of the property translation
80
     *   list: this table gives the property ID for each of the metaclass
81
     *   functions.  The first entry is the property of function index 1,
82
     *   the second entry is function index 2, and so on. 
83
     */
84
    vm_prop_id_t *func_xlat_;
85
    size_t func_xlat_cnt_;
86
87
    /* relese storage */
88
    void release_mem()
89
    {
90
        /* if this entry has a property table, delete it */
91
        if (prop_xlat_ != 0)
92
        {
93
            /* free it */
94
            t3free(prop_xlat_);
95
            
96
            /* forget the pointer */
97
            prop_xlat_ = 0;
98
        }
99
100
        /* if this entry has a function translation table, delete it */
101
        if (func_xlat_ != 0)
102
        {
103
            /* free it */
104
            t3free(func_xlat_);
105
            
106
            /* forget the pointer */
107
            func_xlat_ = 0;
108
        }
109
110
        /* relesae our stored name */
111
        lib_free_str(image_meta_name_);
112
    }
113
114
    /* store the metaclass name as loaded from the image file */
115
    void set_meta_name(const char *nm)
116
    {
117
        /* allocate space and store the name */
118
        image_meta_name_ = lib_copy_str(nm);
119
    }
120
121
    /*
122
     *   Add a property to the table, given the property ID and the
123
     *   1-based index of the corresponding function in the metaclass's
124
     *   internal function table.  
125
     */
126
    void add_prop_xlat(vm_prop_id_t prop, ushort func_idx)
127
    {
128
        /* 
129
         *   Add the translation entry from property ID to function index
130
         *   - note that we store this as a 1-based function table index
131
         *   value, because we reserve function index 0 to indicate that
132
         *   the property is invalid and has no function translation 
133
         */
134
        prop_xlat_[prop - min_prop_] = func_idx;
135
        
136
        /* 
137
         *   Add the translation entry from function index to property ID.
138
         *   Note that we must adjust the 1-based function index down one
139
         *   to get the index into our internal array.
140
         */
141
        func_xlat_[func_idx - 1] = prop;
142
    }
143
144
    /*
145
     *   Get the translation for a given property ID.  This returns zero
146
     *   if the property does not map to a valid function index for the
147
     *   metaclass, or the 1-based index of the function in the
148
     *   metaclass's "vtable" if the property is defined.
149
     */
150
    unsigned short xlat_prop(vm_prop_id_t prop) const
151
    {
152
        /*
153
         *   Check to see if the property is represented in the table.  If
154
         *   it's not within the range of properties in the table, there
155
         *   is no translation for the property.  
156
         */
157
        if (prop < min_prop_ || prop >= min_prop_ + prop_xlat_cnt_)
158
        {
159
            /* the property isn't in the table, so it has no translation */
160
            return 0;
161
        }
162
        
163
        /* return the function index from the table */
164
        return prop_xlat_[prop - min_prop_];
165
    }
166
167
    /*
168
     *   Translate a function index to a property ID.  The function index
169
     *   is given as a 1-based index, for consistency with the return
170
     *   value from xlat_prop(). 
171
     */
172
    vm_prop_id_t xlat_func(unsigned short func_idx) const
173
    {
174
        /* 
175
         *   if it's zero, or it's greater than the number of functions in
176
         *   our table, it has no property translation 
177
         */
178
        if (func_idx == 0 || func_idx > func_xlat_cnt_)
179
            return VM_INVALID_PROP;
180
181
        /* 
182
         *   return the entry from our table for the given index, adjusted
183
         *   to a 1-based index value 
184
         */
185
        return func_xlat_[func_idx - 1];
186
    }
187
};
188
189
190
/* ------------------------------------------------------------------------ */
191
/*
192
 *   The metaclass table.  One global instance of this table is generally
193
 *   created when the image file is loaded.  
194
 */
195
class CVmMetaTable
196
{
197
public:
198
    /* 
199
     *   Create a table with a given number of initial entries.  The table
200
     *   may be expanded in the future if necessary, but if the caller can
201
     *   predict the maximum number of entries required, we can
202
     *   preallocate the table at its final size and thus avoid the
203
     *   overhead and memory fragmentation of expanding the table.  
204
     */
205
    CVmMetaTable(size_t init_entries);
206
207
    /* delete the table */
208
    ~CVmMetaTable();
209
210
    /* clear all existing entries from the table */
211
    void clear();
212
213
    /* 
214
     *   Add an entry to the table, given the metaclass identifier (a
215
     *   string giving the universally unique name for the metaclass).
216
     *   Fills in the next available slot.  Throws an error if the
217
     *   metaclass is not present in the system.
218
     *   
219
     *   If min_prop and max_prop are both VM_INVALID_PROP, the metaclass
220
     *   has no properties in the translation table.  
221
     */
222
    void add_entry(const char *metaclass_id, size_t func_cnt,
223
                   vm_prop_id_t min_prop, vm_prop_id_t max_prop);
224
225
    /* add an entry to the table given the registration table index */
226
    void add_entry(const char *metaclass_id, uint idx, size_t func_cnt,
227
                   vm_prop_id_t min_prop, vm_prop_id_t max_prop);
228
229
    /* 
230
     *   Add an entry to the table given the registration table index, but
231
     *   only if the metaclass at this index isn't already defined in the
232
     *   dependency table; if the metaclass is already in the dependency
233
     *   table, this function has no effect.
234
     */
235
    void add_entry_if_new(uint reg_table_idx, size_t func_cnt,
236
                          vm_prop_id_t min_prop, vm_prop_id_t max_prop);
237
238
    /*
239
     *   Get the dependency table index for a metaclass, given the
240
     *   registration table index.  If the metaclass is not present in the
241
     *   metaclass table, we'll return -1. 
242
     */
243
    int get_dependency_index(uint reg_table_idx) const
244
        { return reverse_map_[reg_table_idx]; }
245
246
    /* 
247
     *   get the depencency table entry for a metaclass, given the
248
     *   registration table index 
249
     */
250
    vm_meta_entry_t *get_entry_from_reg(int reg_idx)
251
    {
252
        int dep_idx;
253
254
        /* translate the registration table index into a dependency index */
255
        dep_idx = get_dependency_index(reg_idx);
256
257
        /* 
258
         *   if we have a valid dependency index, return it; otherwise,
259
         *   return null 
260
         */
261
        if (dep_idx >= 0)
262
            return &table_[dep_idx];
263
        else
264
            return 0;
265
    }
266
267
    /*
268
     *   Given a registration table index for a metaclass and a property
269
     *   ID, retrieve the metaclass function vector index for the property
270
     *   according to the image file's property mapping for the metaclass.
271
     *   Returns zero if the property is not in the mapping, 1 for the
272
     *   first function in the vector, 2 for the second function, and so
273
     *   on.
274
     *   
275
     *   Note that we use the registration table index, NOT the dependency
276
     *   index, because this function is provided for use by the metaclass
277
     *   itself, which only has convenient access to its registration
278
     *   index.  
279
     */
280
    int prop_to_vector_idx(uint reg_table_idx, vm_prop_id_t prop)
281
    {
282
        vm_meta_entry_t *entry;
283
        
284
        /* get the entry for the registration table index */
285
        entry = get_entry_from_reg(reg_table_idx);
286
        
287
        /* 
288
         *   if there's no entry for this registration index, there's
289
         *   obviously no metaclass function mapping for the property 
290
         */
291
        if (entry == 0)
292
            return 0;
293
294
        /* return the property translation */
295
        return entry->xlat_prop(prop);
296
    }
297
298
    /* get the entry at a given dependency table index */
299
    vm_meta_entry_t *get_entry(int idx) { return &table_[idx]; }
300
301
    /* get the total number of entries in the table */
302
    size_t get_count() const { return count_; }
303
304
    /* 
305
     *   Invoke the VM-stack-based constructor for the metaclass at the
306
     *   given index to create a new instance of that metaclass.  Throws
307
     *   an error if no such entry is defined.  Returns the object ID of
308
     *   the constructed object.  
309
     */
310
    vm_obj_id_t create_from_stack(VMG_ const uchar **pc_ptr,
311
                                  uint idx, uint argc);
312
313
    /* invoke a static property of a metaclass */
314
    int call_static_prop(VMG_ vm_val_t *result, const uchar **pc_ptr,
315
                         uint idx, uint *argc, vm_prop_id_t prop);
316
317
    /*
318
     *   Create an object with the given ID and load the object from the
319
     *   image file.
320
     */
321
    void create_from_image(VMG_ uint idx, vm_obj_id_t id,
322
                           const char *ptr, size_t siz);
323
324
    /* 
325
     *   create an object in preparation for loading the object from a
326
     *   saved state file 
327
     */
328
    void create_for_restore(VMG_ uint idx, vm_obj_id_t id);
329
330
    /* 
331
     *   write the dependency table to a file, for later reloading with
332
     *   read_from_file() 
333
     */
334
    void write_to_file(class CVmFile *fp);
335
336
    /* 
337
     *   Read the dependency table from a file, as previously written by
338
     *   write_to_file().  Returns zero on success, or an error code on
339
     *   failure.  We will entirely clear the current table before
340
     *   loading, so the new table will replace the existing table.  
341
     */
342
    int read_from_file(class CVmFile *fp);
343
344
    /* rebuild the image file (for use after preinitialization) */
345
    void rebuild_image(class CVmImageWriter *writer);
346
347
    /*
348
     *   Create an IntrinsicClass object for each metaclass that doesn't
349
     *   already have an IntrinsicClass object.  This ensures that every
350
     *   intrinsic class in use has an associated IntrinsicClass instance,
351
     *   even if the compiler didn't generate one. 
352
     */
353
    void create_intrinsic_class_instances(VMG0_);
354
355
    /* forget IntrinsicClass objects we created at startup */
356
    void forget_intrinsic_class_instances(VMG0_);
357
358
private:
359
    /* 
360
     *   Ensure we have space for a given number of entries, allocating
361
     *   more if necessary.  If we must allocate more space, we'll
362
     *   increase the current allocation size by at least the given
363
     *   increment (more if necessary to bring it up to the required
364
     *   size).  
365
     */
366
    void ensure_space(size_t entries, size_t increment);
367
368
    /* the table array */
369
    vm_meta_entry_t *table_;
370
371
    /* 
372
     *   reverse dependency map - each entry in this table is the
373
     *   dependency table index of the metaclass at the given registration
374
     *   table index:
375
     *   
376
     *   reserve_map[registration_table_index] = dependency_table_index
377
     *   
378
     *   This information lets us determine if a given metaclass is in the
379
     *   current dependency table at all, and if so what it's index is.
380
     *   We store -1 in each entry that doesn't appear in the dependency
381
     *   table.  
382
     */
383
    int *reverse_map_;
384
    
385
    /* number of entries defined in the table */
386
    size_t count_;
387
388
    /* number of entries allocated for the table */
389
    size_t alloc_;
390
};
391
392
393
#endif /* VMMETA_H */