cfad47cfa3/tads3/vmglob.h

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
1
/* $Header: d:/cvsroot/tads/tads3/vmglob.h,v 1.2 1999/05/17 02:52:29 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
  vmglob.h - T3 VM globals
12
Function
13
  The T3 VM requires a number of static variables that are shared
14
  by several subsystems.  This file defines the globals and a scheme
15
  for accessing them.
16
17
  The globals can be configured in four different ways, depending on
18
  how the T3 VM is to be used:
19
20
    1. As individual external variables.  This is the most efficient
21
       way to configure the globals, but this can't be used when
22
       multiple independent VM instances are needed in a single process,
23
       because each VM would need its own copy of the globals.  This
24
       is the fastest way to lay out the globals, because it allows
25
       the compiler to generate code that accesses internal members of
26
       performance-critical global objects directly, without any pointer
27
       dereferences.
28
29
    2. As members of a static global structure.  This is the second
30
       most efficient way to configure the globals, but this can't be
31
       used when multiple independent VM instances are needed,
32
       because each VM would need its own copy of the globals, which
33
       isn't possible in this configuration.  (Note that accessing
34
       members of a global static structure is identical to accessing
35
       global variables, since the compiler can compute the relative
36
       address of a structure member at compile time and hence does
37
       not need to perform any run-time pointer arithmetic or any other
38
       computation beyond what it would normally use for global variable
39
       access.  However, in this configuration, it's not possible to
40
       allocate any of the global objects in-line within the master
41
       global structure, so each global object's internal members must
42
       be accessed through one pointer dereference.)
43
44
    3. As members of an allocated structure whose address is contained
45
       in a global static variable.  This is slightly less efficient
46
       than method 1, in that the global pointer must be dereferenced
47
       on each global variable access.  This method allows multiple VM
48
       instances to be used, as long as the host application specifically
49
       stores the correct structure pointer in the global static variable
50
       before each call to the VM; this can be used when the host system
51
       uses the VM in only one thread.
52
53
    4. As members of an allocated structure whose address is passed as
54
       a parameter to each function that needs global variable access.
55
       As with method 2, the host application creates a structure per
56
       VM instance it requires, and then passes a pointer to the correct
57
       structure on each call to a VM function; the VM internally passes
58
       this pointer in its own function calls where needed.  This is the
59
       most flexible method, in that the VM can be used in multiple
60
       thread simultaneously (as long as each thread has a separate VM
61
       global structure instance), but is the least efficient, because
62
       the structure pointer must be passed around on all calls.
63
64
  To select a configuration, define one of the following preprocessor
65
  symbols in the makefile:
66
67
     VMGLOB_VARS    - method 1 - individual global variables
68
     VMGLOB_STRUCT  - method 2 - global static structure
69
     VMGLOB_POINTER - method 3 - global static pointer to allocated structure
70
     VMGLOB_PARAM   - method 4 - pointer to structure passed as parameter
71
72
  We provide all of these different possible configurations because of
73
  the trade-offs involved in selecting one.  The host application's needs
74
  should be determined, and the most efficient configuration that meets
75
  those needs should be chosen.
76
Notes
77
  
78
Modified
79
  11/28/98 MJRoberts  - Creation
80
*/
81
82
#ifndef VMGLOB_H
83
#define VMGLOB_H
84
85
#include <stddef.h>
86
87
#include "vmpoolsl.h"
88
89
90
/* ------------------------------------------------------------------------ */
91
/*
92
 *   HOST SYSTEM GLOBAL INITIALIZATION
93
 *   
94
 *   The host system should declare a local variable as follows:
95
 *   
96
 *   vm_globals *vmg__; // two underscores
97
 *   
98
 *   The program must call vmglob_alloc() each time it wants to initialize a
99
 *   global variable context.  This routine must always be called at least
100
 *   once.  (In the VMGLOB_STRUCT or VMGLOB_VARS configuration, this routine
101
 *   has no effect, but should still be called so that the code will work
102
 *   unchanged in other configurations.)  Calling this routine will overwrite
103
 *   the current static global variable pointer in the VMGLOB_POINTER
104
 *   configuration, so the caller must take care to keep track of each set of
105
 *   globals it allocates for later restoration.
106
 *   
107
 *   When calling vmglob_alloc(), assign the return value to vmg__.  
108
 */
109
110
/*
111
 *   HOST SYSTEM GLOBAL TERMINATION
112
 *   
113
 *   The caller should invoke vmglob_delete() for each set of globals it
114
 *   allocated.  
115
 */
116
117
/*   
118
 *   HOST SYSTEM VM FUNCTION CALLS
119
 *   
120
 *   In each call to a VM function, the host system should include the
121
 *   macro "vmg_" (one underscore) at the start of each parameter list; do
122
 *   not put a comma after vmg_.  Call functions that take no other
123
 *   parameters with vmg0_ instead of vmg_.  
124
 */
125
126
/* ------------------------------------------------------------------------ */
127
/*
128
 *   INTERNAL FUNCTION DECLARATION AND CALLING
129
 *   
130
 *   Every function that requires global access, or which calls a function
131
 *   that requires global access, must put "VMG_" at the very start of its
132
 *   formal parameters declaration.  Do not put a comma after VMG_, but
133
 *   simply list the first parameter.  If the function has no parameters
134
 *   at all, use VMG0_ instead of VMG_.  For example:
135
 *   
136
 *   void CVmClass::func1(VMG_ const textchar_t *str, size_t len) { ... }
137
 *.  void CVmClass::func2(VMG0_) { ... }
138
 *   
139
 *   In each call to a function that uses global variables or calls
140
 *   functions that use global variables, put "vmg_" at the very start of
141
 *   the actual parmaeters list in the call; do not put a comma after the
142
 *   vmg_.  If the function takes no parameters at all, use vmg0_ instead
143
 *   of vmg_.
144
 *   
145
 *   func1(vmg_ "test", 4);
146
 *.  func2(vmg0_); 
147
 */
148
149
150
/* ------------------------------------------------------------------------ */
151
/*
152
 *   Functions that themselves can't participate in the prototype
153
 *   mechanism, because they present an external API to other subsystems,
154
 *   must keep track of the globals on their own.  To do this, they must
155
 *   stash the global pointer in their own context structure - use
156
 *   VMGLOB_ADDR to get the address of the global structure.  When passing
157
 *   this stashed pointer back to function calls, use vmg_var(x) (for the
158
 *   first argument to a function with multiple arguments) or vmg_var0(x)
159
 *   (for a single-argument call), as appropriate, where x is the local
160
 *   copy.
161
 *   
162
 *   To access globals from this type of routine, put the VMGLOB_PTR(x)
163
 *   macro in with the local variable decalarations for the function,
164
 *   passing as the argument the stashed address of the global structure.
165
 *   This will set things up so that the G_xxx variables are accessible
166
 *   through a local pointer, when necessary, and will also make the vmg_
167
 *   and vmg0_ argument macros work properly.  See the examples below.
168
 */
169
#if 0
170
/* EXAMPLES ONLY - THIS CODE IS FOR DOCUMENTATION ONLY */
171
172
struct my_context_def
173
{
174
    /* holder for VM globals structure pointer */
175
    vm_globals *vmg;
176
};
177
178
int func_calling_external_interfaces(VMG_ int x, int y, int z)
179
{
180
    my_context_def ctx;
181
    
182
    /* stash the address of the VM globals in my private context */
183
    ctx.vmg = VMGLOB_ADDR;
184
185
    /* call my external API function */
186
    external_api_func(&ctx);
187
}
188
189
int func_called_from_external_interface(my_context_def *ctx, int x, int y)
190
{
191
    /* set up access to the VM globals through my stashed context */
192
    VMGLOB_PTR(ctx->vmg);
193
194
    /* access a global variable */
195
    G_myvar->do_something();
196
197
    /* call a function using a VMG_ prototype */
198
    G_myvar->do_something_else(vmg_ x, y);
199
}
200
201
#endif /* 0 */
202
203
204
/* ------------------------------------------------------------------------ */
205
/*
206
 *   Set up to define the global variables.  For the POINTER and PARAM
207
 *   configurations, put pointers to the global structures in a structure.
208
 *   For the static STRUCT configuration, actually allocate all of the
209
 *   objects statically.
210
 *   
211
 *   Use VM_GLOBAL_OBJDEF() to define the entry for an object (struct or
212
 *   class) type.  The global variable will be a pointer to this type.
213
 *   
214
 *   Use VM_GLOBAL_PREOBJDEF to define the entry for an object type that's to
215
 *   be defined as pre-allocated static objects in the VARS configuration.
216
 *   This can be used for objects that (1) have very frequent access and thus
217
 *   should have their fields reachable directly as statics rather than via
218
 *   static pointers, and (2) need no constructor parameters and thus can be
219
 *   pre-allocated at compile-time.  In the VARS configuration, these
220
 *   variables can be allocated at compile-time, which allows the compiler to
221
 *   generate code that accesses the objects' internal members without any
222
 *   pointer dereferences.
223
 *   
224
 *   Any variable defined with VM_GLOBAL_PREOBJDEF MUST have its accessor
225
 *   defined through VMGLOB_PREACCESS() rather than VMGLOB_ACCESS().
226
 *   
227
 *   Use VM_GLOBAL_VARDEF to define a scalar variable.  
228
 */
229
#if defined(VMGLOB_POINTER) || defined(VMGLOB_PARAM) || defined(VMGLOB_STRUCT)
230
#define VM_GLOBALS_BEGIN  struct vm_globals {
231
#define VM_GLOBAL_OBJDEF(typ, var) typ *var;
232
#define VM_GLOBAL_PREOBJDEF(typ, var) typ *var;
233
#define VM_GLOBAL_PRECOBJDEF(typ, var, ctor_args) typ *var;
234
#define VM_GLOBAL_VARDEF(typ, var) typ var;
235
#define VM_GLOBALS_END    };
236
237
/* 
238
 *   we do allocate all global objects, including external objects; hence
239
 *   external globals are non-static 
240
 */
241
#define VM_IF_ALLOC_PRE_GLOBAL(x)          x
242
#define VM_IFELSE_ALLOC_PRE_GLOBAL(x, y)   x
243
#define VM_PRE_GLOBALS_ARE_STATIC   FALSE
244
#endif
245
246
#if defined(VMGLOB_VARS)
247
#define VM_GLOBALS_BEGIN
248
249
#define VM_GLOBAL_OBJDEF(typ, var) extern typ *G_##var##_X;
250
#define VM_GLOBAL_PREOBJDEF(typ, var) extern typ G_##var##_X;
251
#define VM_GLOBAL_PRECOBJDEF(typ, var, ctor_args) extern typ G_##var##_X;
252
#define VM_GLOBAL_VARDEF(typ, var) extern typ G_##var##_X;
253
254
#define VM_GLOBALS_END
255
256
/* we don't actually need a structure for the globals; use a dummy */
257
struct vm_globals { int x; };
258
259
/* external global objects are statically allocated */
260
#define VM_IF_ALLOC_PRE_GLOBAL(x)
261
#define VM_IFELSE_ALLOC_PRE_GLOBAL(x, y)   y
262
#define VM_PRE_GLOBALS_ARE_STATIC  TRUE
263
#endif
264
265
266
/* define the globals */
267
#include "vmglobv.h"
268
269
/* ------------------------------------------------------------------------ */
270
/*
271
 *   If we're not including from the global-defining source file, merely
272
 *   declare the globals. 
273
 */
274
#ifndef VMGLOB_DECLARE
275
#define VMGLOB_DECLARE extern
276
#endif
277
278
279
/* ------------------------------------------------------------------------ */
280
/*
281
 *   INDIVIDUAL STATIC GLOBAL VARIABLES configuration.  In this
282
 *   configuration, the globals are defined as individual global variables.
283
 *   This is the most efficient configuration, but it only allows one VM
284
 *   instance in a given process.  
285
 */
286
#ifdef VMGLOB_VARS
287
288
/* initialization - this has no effect in this mode */
289
inline vm_globals *vmglob_alloc() { return 0; }
290
291
/* termination - this has no effect in this mode */
292
inline void vmglob_delete(vm_globals *) { }
293
294
/* 
295
 *   we don't require anything for the parameter declaration or usage, since
296
 *   we don't use the local parameter mechanism at all 
297
 */
298
#define VMG_
299
#define VMG0_
300
#define vmg_
301
#define vmg0_
302
303
/* 
304
 *   get the address of the globals - this doesn't do anything in this
305
 *   configuration, as there's not really a global variables structure 
306
 */
307
#define VMGLOB_ADDR   0
308
309
/* pass a stashed copy of the global pointer, if necessary */
310
#define vmg_var(x)
311
#define vmg_var0(x)
312
313
/* declare a local variable to access the globals */
314
#define VMGLOB_PTR(x)
315
316
/* we access globals directly as individual statics */
317
#define VMGLOB_ACCESS(var) (G_##var##_X)
318
#define VMGLOB_PREACCESS(var) (&G_##var##_X)
319
320
#endif /* VMGLOB_VARS */
321
322
/* ------------------------------------------------------------------------ */
323
/*
324
 *   STATIC GLOBAL STRUCTURE configuration.  In this configuration, the
325
 *   globals are defined in a single static global structure.  This is the
326
 *   second most efficient configuration, but it only allows one VM instance
327
 *   per process.  
328
 */
329
#ifdef VMGLOB_STRUCT
330
331
/* define the global variables structure */
332
VMGLOB_DECLARE vm_globals G_vmglobals;
333
334
/* initialization - this has no effect in this mode */
335
inline vm_globals *vmglob_alloc()
336
{
337
    return &G_vmglobals;
338
}
339
340
/* termination - this has no effect in this mode */
341
inline void vmglob_delete(vm_globals *) { }
342
343
/* 
344
 *   we don't require anything for the parameter declaration or usage,
345
 *   since we don't use the local parameter mechanism at all 
346
 */
347
#define VMG_
348
#define VMG0_
349
#define vmg_
350
#define vmg0_
351
352
/* get the address of the globals */
353
#define VMGLOB_ADDR   (&G_vmglobals)
354
355
/* pass a stashed copy of the global pointer, if necessary */
356
#define vmg_var(x)
357
#define vmg_var0(x)
358
359
/* declare a local variable to access the globals */
360
#define VMGLOB_PTR(x)
361
362
/* we access globals directly as individual statics */
363
#define VMGLOB_ACCESS(var)    (G_vmglobals.var)
364
#define VMGLOB_PREACCESS(var) (G_vmglobals.var)
365
366
#endif /* VMGLOB_STRUCT */
367
368
/* ------------------------------------------------------------------------ */
369
/*
370
 *   STATIC GLOBAL POINTER configuration.  In this configuration, the
371
 *   globals are stored in an allocated structure whose address is stored
372
 *   in a global static pointer variable.
373
 */
374
#ifdef VMGLOB_POINTER
375
376
/* define our global static pointer to the global variables */
377
VMGLOB_DECLARE vm_globals *G_vmglobals;
378
379
/* initialization - allocate a new set of globals */
380
inline vm_globals *vmglob_alloc()
381
{
382
    G_vmglobals = new vm_globals();
383
    return G_vmglobals;
384
}
385
386
/* termination - delete a set of globals */
387
inline void vmglob_delete(vm_globals *glob) { delete glob; }
388
389
/* 
390
 *   we don't require anything for the parameter declaration or usage,
391
 *   since we don't use the local parameter mechanism at all 
392
 */
393
#define VMG_
394
#define VMG0_
395
#define vmg_
396
#define vmg0_
397
398
/* get the address of the globals */
399
#define VMGLOB_ADDR   G_vmglobals
400
401
/* pass a stashed copy of the global pointer, if necessary */
402
#define vmg_var(x)
403
#define vmg_var0(x)
404
405
/* declare a local variable to access the globals */
406
#define VMGLOB_PTR(x)
407
408
/* accessing a global requires dereferencing the global pointer */
409
#define VMGLOB_ACCESS(var) (G_vmglobals->var)
410
#define VMGLOB_PREACCESS(var) (G_vmglobals_var)
411
412
#endif /* VMGLOB_POINTER */
413
414
/* ------------------------------------------------------------------------ */
415
/*
416
 *   PARAMETER configuration.  In this configuration, the globals are
417
 *   stored in an allocated structure whose address is passed to each VM
418
 *   function as a parameter. 
419
 */
420
#ifdef VMGLOB_PARAM
421
422
/* initialization - allocate a new set of globals */
423
inline vm_globals *vmglob_alloc() { return new vm_globals(); }
424
425
/* termination - delete a set of globals */
426
inline void vmglob_delete(vm_globals *glob) { delete glob; }
427
428
/* function declaration for the global pointer parameter */
429
#define VMG_   vm_globals *vmg__,
430
#define VMG0_  vm_globals *vmg__
431
432
/* parameter reference for passing to a function */
433
#define vmg_   vmg__,
434
#define vmg0_  vmg__
435
436
/* get the address of the globals */
437
#define VMGLOB_ADDR   vmg__
438
439
/* pass a stashed copy of the global pointer, if necessary */
440
#define vmg_var(x)         x,
441
#define vmg_var0(x)        x
442
443
/* declare a local variable to access the globals */
444
#define VMGLOB_PTR(x) vm_globals *vmg__ = x
445
446
/* accessing a global variable requires dereferencing the parameter */
447
#define VMGLOB_ACCESS(var) (vmg__->var)
448
#define VMGLOB_PREACCESS(var) (vmg__->var)
449
450
#endif /* VMGLOB_PARAM */
451
452
/* ------------------------------------------------------------------------ */
453
/*
454
 *   Global variable accessors.  For convenience, we define these cover
455
 *   macros that access the global variables in the appropriate manner for
456
 *   our configuration.  Code can use these G_xxx symbols syntactically as
457
 *   though they were normal global variables.  
458
 */
459
#define G_mem         VMGLOB_ACCESS(mem)
460
#define G_undo        VMGLOB_ACCESS(undo)
461
#define G_meta_table  VMGLOB_ACCESS(meta_table)
462
#define G_bif_table   VMGLOB_ACCESS(bif_table)
463
#define G_varheap     VMGLOB_ACCESS(varheap)
464
#define G_preinit_mode VMGLOB_ACCESS(preinit_mode)
465
#define G_rand_seed   VMGLOB_ACCESS(rand_seed)
466
#define G_bif_tads_globals VMGLOB_ACCESS(bif_tads_globals)
467
#define G_res_loader  VMGLOB_ACCESS(res_loader)
468
#define G_host_ifc    VMGLOB_ACCESS(host_ifc)
469
#define G_image_loader VMGLOB_ACCESS(image_loader)
470
#define G_disp_cset_name  VMGLOB_ACCESS(disp_cset_name)
471
#define G_cmap_from_fname VMGLOB_ACCESS(cmap_from_fname)
472
#define G_cmap_to_fname VMGLOB_ACCESS(cmap_to_fname)
473
#define G_cmap_from_ui VMGLOB_ACCESS(cmap_from_ui)
474
#define G_cmap_to_ui  VMGLOB_ACCESS(cmap_to_ui)
475
#define G_cmap_from_file VMGLOB_ACCESS(cmap_from_file)
476
#define G_cmap_to_file VMGLOB_ACCESS(cmap_to_file)
477
#define G_cmap_to_log VMGLOB_ACCESS(cmap_to_log)
478
#define G_console     VMGLOB_ACCESS(console)
479
#define G_debugger    VMGLOB_ACCESS(debugger)
480
#define G_exc_entry_size VMGLOB_ACCESS(exc_entry_size)
481
#define G_line_entry_size VMGLOB_ACCESS(line_entry_size)
482
#define G_dbg_hdr_size VMGLOB_ACCESS(dbg_hdr_size)
483
#define G_srcf_table  VMGLOB_ACCESS(srcf_table)
484
#define G_dbg_lclsym_hdr_size VMGLOB_ACCESS(dbg_lclsym_hdr_size)
485
#define G_dbg_fmt_vsn VMGLOB_ACCESS(dbg_fmt_vsn)
486
#define G_bignum_cache VMGLOB_ACCESS(bignum_cache)
487
#define G_tadsobj_queue VMGLOB_ACCESS(tadsobj_queue)
488
#define G_predef      VMGLOB_PREACCESS(predef)
489
#define G_stk         VMGLOB_PREACCESS(stk)
490
#define G_interpreter VMGLOB_PREACCESS(interpreter)
491
#define G_const_pool  VMGLOB_PREACCESS(const_pool)
492
#define G_code_pool   VMGLOB_PREACCESS(code_pool)
493
#define G_obj_table   VMGLOB_PREACCESS(obj_table)
494
495
#endif /* VMGLOB_H */
496