File: interp.h

package info (click to toggle)
gnu-smalltalk 3.2.4-2.1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 32,688 kB
  • ctags: 14,104
  • sloc: ansic: 87,424; sh: 22,729; asm: 8,465; perl: 4,513; cpp: 3,548; xml: 1,669; awk: 1,581; yacc: 1,357; makefile: 1,237; lisp: 855; lex: 843; sed: 258; objc: 124
file content (625 lines) | stat: -rw-r--r-- 23,365 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
/******************************** -*- C -*- ****************************
 *
 *	Byte Code interpreter declarations.
 *
 *
 ***********************************************************************/

/***********************************************************************
 *
 * Copyright 1988,89,90,91,92,94,95,99,2000,2001,2002,2006,2007,2008,2009
 * Free Software Foundation, Inc.
 * Written by Steve Byrne.
 *
 * This file is part of GNU Smalltalk.
 *
 * GNU Smalltalk is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2, or (at your option) any later 
 * version.
 * 
 * Linking GNU Smalltalk statically or dynamically with other modules is
 * making a combined work based on GNU Smalltalk.  Thus, the terms and
 * conditions of the GNU General Public License cover the whole
 * combination.
 *
 * In addition, as a special exception, the Free Software Foundation
 * give you permission to combine GNU Smalltalk with free software
 * programs or libraries that are released under the GNU LGPL and with
 * independent programs running under the GNU Smalltalk virtual machine.
 *
 * You may copy and distribute such a system following the terms of the
 * GNU GPL for GNU Smalltalk and the licenses of the other code
 * concerned, provided that you include the source code of that other
 * code when and as the GNU GPL requires distribution of source code.
 *
 * Note that people who make modified versions of GNU Smalltalk are not
 * obligated to grant this special exception for their modified
 * versions; it is their choice whether to do so.  The GNU General
 * Public License gives permission to release a modified version without
 * this exception; this exception also makes it possible to release a
 * modified version which carries forward this exception.
 *
 * GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * GNU Smalltalk; see the file COPYING.  If not, write to the Free Software
 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  
 *
 ***********************************************************************/


#ifndef GST_INTERP_H
#define GST_INTERP_H

/* The number of available process priorities */
#define NUM_PRIORITIES		 9
#define USER_SCHEDULING_PRIORITY 4

/* Ordering of file operations must match that used in
   FileStream.st */
enum
{
  PRIM_OPEN_FILE,               /* open:mode: */
  PRIM_CLOSE_FILE,              /* no args */
  PRIM_PUT_CHARS,               /* data:from:to: */
  PRIM_GET_CHARS,               /* data:from:to: */
  PRIM_FSEEK_SET,               /* position: */
  PRIM_FTELL,                   /* no args */
  PRIM_FEOF,                    /* no args */
  PRIM_OPEN_PIPE,               /* open:mode: */
  PRIM_FSEEK_CUR,               /* skip: */
  PRIM_FSIZE,                   /* no args */
  PRIM_FTRUNCATE,               /* no args */
  PRIM_FILEIN,                  /* no args */
  PRIM_FILEIN_AT,               /* line:file:charPos: */
  PRIM_SYNC_POLL,               /* read/write/exception */
  PRIM_ASYNC_POLL,              /* operation:semaphore: */
  PRIM_IS_PIPE,                 /* no args */
  PRIM_MK_TEMP,                 /* base: */
  PRIM_GET_CHARS_AT,            /* data:from:to:absOfs: */
  PRIM_PUT_CHARS_AT,            /* data:from:to:absOfs: */
  PRIM_SHUTDOWN_WRITE           /* shutdown */
};

/* These macros are used to quickly compute the number of words needed
   for a context with a maximum allowable stack depth of DEPTH.  */
#define FIXED_CTX_SIZE	(sizeof(struct gst_method_context) / sizeof(PTR) - 1)
#define CTX_SIZE(depth) (((depth) << DEPTH_SCALE) + FIXED_CTX_SIZE)

#define DUMMY_NATIVE_IP FROM_INT(0)

/* The structure of execution context objects.  */
typedef struct gst_context_part
{
  OBJ_HEADER;
  OOP parentContext;
  OOP native_ip;		/* used by JIT */
  OOP ipOffset;			/* an integer byte index into method */
  OOP spOffset;			/* an integer index into cur context
				   stack */
  OOP receiver;			/* the receiver OOP */
  OOP method;			/* the method that we're executing */
  OOP x;			/* depends on the subclass */
  OOP contextStack[1];
} *gst_context_part;

typedef struct gst_method_context
{
  OBJ_HEADER;
  OOP parentContext;
  OOP native_ip;		/* used by JIT */
  OOP ipOffset;			/* an integer byte index into method */
  OOP spOffset;			/* an integer index into cur context
				   stack */
  OOP receiver;			/* the receiver OOP */
  OOP method;			/* the method that we're executing */
  intptr_t flags;		/* must be an int to distinguish
				   gst_compiled_block/gst_method_context 
				 */
  OOP contextStack[1];
} *gst_method_context;

/* CompiledMethod cache (see descriptions in interp-bc.inl and
   interp-jit.inl) */
typedef struct method_cache_entry
{
  OOP selectorOOP;
  OOP startingClassOOP;
  OOP methodOOP; 
  OOP methodClassOOP; 
  method_header methodHeader;
#ifdef ENABLE_JIT_TRANSLATION
  OOP receiverClass;
  PTR nativeCode;
  PTR dummy;                    /* 32 bytes are usually a sweet spot */
#endif
} method_cache_entry;
 

/* MCF stands for MethodContext Flag.  */

/* This is always set so that Smalltalk sees the flags member as
   a SmallInteger.  BlockContexts store the outer context there,
   so it is never a SmallInteger.  */
#define MCF_IS_METHOD_CONTEXT         1

/* Answer whether this context must be skipped when doing a local
   method return.  Contexts are marked this way when an exception
   occurs or if there is a non-local method return and there are
   active #ensure: calls.  */
#define MCF_IS_DISABLED_CONTEXT       2

/* Answer whether this context must not be discarded upon a non-local
   method return.  Contexts evaluating #ensure: and/or #ifCurtailed:
   are marked this way.  */
#define MCF_IS_UNWIND_CONTEXT         4

/* Answer whether execution started from this context (this kind
   of MethodContext is used to mark call-ins from C to Smalltalk
   and is placed on top of the context that was executing at the
   time of the call-in, and is the parent of the called-in method).  */
#define MCF_IS_EXECUTION_ENVIRONMENT  8


typedef struct gst_block_context
{
  OBJ_HEADER;
  OOP parentContext;
  OOP native_ip;		/* used by JIT */
  OOP ipOffset;			/* an integer byte index into method */
  OOP spOffset;			/* an integer index into cur context
				   stack */
  OOP receiver;			/* the receiver OOP */
  OOP method;			/* the method that we're executing */
  OOP outerContext;		/* the parent gst_block_context or
				   gst_method_context */
  OOP contextStack[1];
}
 *gst_block_context;

typedef struct gst_continuation
{
  OBJ_HEADER;
  OOP stack;
}
 *gst_continuation;

/* The structure of various objects related to the process system.  */
typedef struct gst_semaphore
{
  OBJ_HEADER;
  OOP firstLink;
  OOP lastLink;
  OOP signals;
  OOP name;
}
 *gst_semaphore;

#define PROCESS_HEADER \
  OBJ_HEADER; \
  OOP nextLink; \
  OOP suspendedContext; \
  OOP priority; \
  OOP myList; \
  OOP name; \
  OOP unwindPoints; \
  OOP interrupts; \
  OOP interruptLock

typedef struct gst_process
{
  PROCESS_HEADER;
}
 *gst_process;

typedef struct gst_callin_process
{
  PROCESS_HEADER;
  OOP returnedValue;
}
 *gst_callin_process;

typedef struct gst_processor_scheduler
{
  OBJ_HEADER;
  OOP processLists;
  OOP activeProcess;
  OOP idleTasks;
  OOP processTimeslice;
  OOP gcSemaphore;
  OOP gcArray;
}
 *gst_processor_scheduler;

/* Some performance counters from the interpreter: these
   count the number of special returns.  */
extern unsigned long _gst_literal_returns 
  ATTRIBUTE_HIDDEN, _gst_inst_var_returns 
  ATTRIBUTE_HIDDEN,
  _gst_self_returns 
  ATTRIBUTE_HIDDEN;

/* The number of primitives executed.  */
extern unsigned long _gst_primitives_executed 
  ATTRIBUTE_HIDDEN;

/* The number of bytecodes executed.  */
extern unsigned long _gst_bytecode_counter 
  ATTRIBUTE_HIDDEN;

/* The number of method cache misses */
extern unsigned long _gst_cache_misses 
  ATTRIBUTE_HIDDEN;

/* The number of cache lookups - either hits or misses */
extern unsigned long _gst_sample_counter 
  ATTRIBUTE_HIDDEN;

/* If this is true, for each byte code that is executed, we print on
   stdout the byte index within the current gst_compiled_method and a
   decoded interpretation of the byte code.  If > 1, it applies also
   to code not invoked by the user.  */
extern int _gst_execution_tracing 
  ATTRIBUTE_HIDDEN;

/* When this is true, and an interrupt occurs (such as SIGSEGV),
   Smalltalk will terminate itself by making a core dump (normally it
   produces a backtrace).  */
extern mst_Boolean _gst_make_core_file 
  ATTRIBUTE_HIDDEN;

/* When true, this indicates that there is no top level loop for
   control to return to, so it causes the system to exit.  */
extern mst_Boolean _gst_non_interactive 
  ATTRIBUTE_HIDDEN;

/* The OOP for a gst_compiled_method or gst_compiled_block that is the
   currently executing method.  */
extern OOP _gst_this_method 
  ATTRIBUTE_HIDDEN;

/* Physical address of the base of the method temporary variables.
   Typically a small number of bytes (multiple of 4 since it points to
   OOPs) lower than sp.  */
extern OOP *_gst_temporaries 
  ATTRIBUTE_HIDDEN;

/* Physical address of the base of the method literals.  */
extern OOP *_gst_literals 
  ATTRIBUTE_HIDDEN;

/* An OOP that is the current receiver of the current message.  */
extern OOP _gst_self 
  ATTRIBUTE_HIDDEN;

/* A gst_block_context or gst_method_context that indicates the
   context that the interpreter is currently running in.  */
extern OOP _gst_this_context_oop 
  ATTRIBUTE_HIDDEN;

/* The OOP for an IdentityDictionary that stores the raw profile. */
extern OOP _gst_raw_profile
  ATTRIBUTE_HIDDEN;

/* A bytecode counter value used while profiling. */
extern unsigned long _gst_saved_bytecode_counter
  ATTRIBUTE_HIDDEN;

/* The type used to hold the instruction pointer.  For the JIT, this
   is an offset from a location which is deemed the `base' of
   native-compiled methods (because this way it will fit in a
   SmallInteger and can be stored in the returnIP field of the context
   objects); for the interpreter, this is the physical address of the
   next executed bytecode (note: the global is usually synchronized at
   sequence points only).  */
#ifdef ENABLE_JIT_TRANSLATION
typedef int ip_type;
extern char *native_ip;
#else /* plain bytecode interpreter */
typedef gst_uchar *ip_type;
#endif
#define ip			_gst_ip

extern ip_type ip 
  ATTRIBUTE_HIDDEN;

/* When not NULL, this causes the byte code interpreter to immediately
   send the message whose selector is here to the current stack
   top.  */
extern const char *_gst_abort_execution
  ATTRIBUTE_HIDDEN;


/* Set to true when some special action must be done at the next
   sequence point.  */
#ifdef ENABLE_JIT_TRANSLATION
extern mst_Boolean _gst_except_flag 
  ATTRIBUTE_HIDDEN;
#endif

/* Create a new Process on the top of the stack, which is specially
   marked so that it stops the interpreter's execution.  This kind
   of MethodContext is used to mark call-ins from C to Smalltalk
   and is the parent of the called-in method.  Return the Process.  */
extern OOP _gst_prepare_execution_environment (void) 
  ATTRIBUTE_HIDDEN;

/* Sends SELECTOR (which should be a Symbol, otherwise _gst_nil_oop is
   returned) to RECEIVER.  The message arguments should also be OOPs
   (otherwise, an access violation exception is pretty likely) and are
   passed in an array ARGS of size NARGS.  The value returned from the
   method is passed back as an OOP to the C program as the result of
   the function, or _gst_nil_oop if the number of arguments is wrong.  */
extern OOP _gst_nvmsg_send (OOP receiver,
			    OOP selector,
			    OOP *args,
			    int nArgs) 
  ATTRIBUTE_HIDDEN;

/* Start the interpreter, and go on until we terminate PROCESSOOP.  */
extern OOP _gst_interpret (OOP processOOP) 
  ATTRIBUTE_HIDDEN;

/* Internal function for SEND_MESSAGE and for sends to super; send
   SENDSELECTOR, with SENDARGS arguments, to RECEIVER.  Start looking
   for the method in METHOD_CLASS. 

   On entry to this routine, the stack should have the receiver and
   the arguments pushed on the stack.  We need to get a new context,
   setup things like the IP, SP, and Temporary pointers, and then
   return.  Note that this routine DOES NOT invoke the interpreter; it
   merely sets up a new context so that calling (or, more typically,
   returning to) the interpreter will operate properly.  This kind of
   sending is for normal messages only.  Things like sending a "value"
   message to a block context are handled by primitives which do
   similar things, but they use information from gst_block_closure
   objects that we don't have available (nor need) here.  */
extern void _gst_send_message_internal (OOP sendSelector,
			      int sendArgs,
			      OOP receiver,
			      OOP method_class) 
  ATTRIBUTE_HIDDEN;

/* Prepare the data structures held by the interpreter.  */
extern void _gst_init_interpreter (void) 
  ATTRIBUTE_HIDDEN;

/* Reset the fast allocator for context objects, telling it that
   all contexts living there have been tenured and thus the space
   can be reused.  */
extern void _gst_empty_context_pool (void) 
  ATTRIBUTE_HIDDEN;

/* Return whether there are pending asynchronous calls.  */
extern mst_Boolean _gst_have_pending_async_calls (void)
  ATTRIBUTE_HIDDEN;

/* Set up so that FUNC will be called, with ARGOOP as its argument,
   as soon as the next sequence point is reached.  */
extern void _gst_async_call (void (*func) (OOP),
			     OOP argOOP) 
  ATTRIBUTE_HIDDEN;

/* Signal SEMAPHOREOOP so that one of the processes waiting on that
   semaphore is waken up.  Since a Smalltalk call-in is not an atomic
   operation, the correct way to signal a semaphore is not to send
   #signal to the object but, rather, to use this function.  The
   signal request will be processed as soon as the next sequence point
   is reached.  */
extern void _gst_async_signal (OOP semaphoreOOP) 
  ATTRIBUTE_HIDDEN;

/* Signal SEMAPHOREOOP so that one of the processes waiting on that
   semaphore is waken up, and remove it from the registry.  Since a
   Smalltalk call-in is not an atomic operation, the correct way to
   signal a semaphore is not to send #signal to the object but,
   rather, to use this function.  The signal request will be processed
   as soon as the next sequence point is reached.  */
extern void _gst_async_signal_and_unregister (OOP semaphoreOOP) 
  ATTRIBUTE_HIDDEN;

/* Invalidate all the cached CompiledMethod lookups.  This does NOT
   include inline caches when the JIT compiler is active.  */
extern void _gst_invalidate_method_cache (void) 
  ATTRIBUTE_HIDDEN;

/* Show a backtrace of the current state of the stack of execution
   contexts.  */
extern void _gst_show_backtrace (FILE *) 
  ATTRIBUTE_HIDDEN;

/* Trap the signals that we care about, basically SIGBUS and
   SIGSEGV.  */
extern void _gst_init_signals (void) 
  ATTRIBUTE_HIDDEN;

/* Store the context of the VM registers into the currently executing
   contexts.  Since the contexts store relative addresses, these are
   valid across GCs and we can count on them and on the OOPs (which do
   not move) to adjust the interior pointers that the VM uses.  Note
   that normally fields such as SP or IP are not valid for the
   currently executing contexts (they are only used after a message
   send) so we need a special function to ensure that even that
   context has the information saved in it.  */
extern void _gst_fixup_object_pointers (void) 
  ATTRIBUTE_HIDDEN;

/* Complementary to _gst_fixup_object_pointers, this function picks
   the relative addresses stored in the current context and uses
   them to adjust the VM registers after the heap is compacted or
   grown.  */
extern void _gst_restore_object_pointers (void) 
  ATTRIBUTE_HIDDEN;

/* This runs before every evaluation and before GC turned on.  It creates an
   initial process if no process is ready to run or if no process has been
   created yet.  */
extern void _gst_init_process_system (void) 
  ATTRIBUTE_HIDDEN;

/* These function mark or copy all the objects that the interpreter keeps in
   the root set.  These are the semaphores that are held to be
   signaled by an asynchronous event (note that they *are* in the root
   set because they could be the only way from which we can get to the
   suspended process!), the semaphores that are queued to be signaled
   at the next sequence point (_gst_async_signals queues them) and the
   currently executing context.  Everything else is supposedly
   reachable from the current context (including the current method,
   the receiver, the receiver class even if it does not live in a
   namespace, and all the context on the execution stack) or from
   Processor (including the current process and the other active
   processes).  Processor itself is reachable from the Smalltalk
   dictionary.  */
extern void _gst_mark_processor_registers (void) 
  ATTRIBUTE_HIDDEN;
extern void _gst_copy_processor_registers (void) 
  ATTRIBUTE_HIDDEN;

/* Print the current state of the lists of ready to run processes for
   each priority, for debugging purposes.  */
extern void _gst_print_process_state (void) 
  ATTRIBUTE_HIDDEN;

/* Sanity check the process lists that the sole instance of ProcessorScheduler
   holds.  */
extern void _gst_check_process_state (void) 
  ATTRIBUTE_HIDDEN;

/* Print the objects currently on the stack, for debugging
   purposes.  */
extern void _gst_show_stack_contents (void) 
  ATTRIBUTE_HIDDEN;

/* Called after the mark phase, but before the sweep phase, so that if
   a method cache entry is not valid anymore it is cleared.  This is
   because in the JIT case a method cache entry is invalidated not
   only if the related method does not exist anymore (and this is done
   by the Smalltalk implementation of the MethodDictionary class) but
   also if the translation to native code for the method is garbage
   collected.  In particular, this function is called *after* the
   unused method translations are marked as such, and *before* they
   are actually freed.  */
extern void _gst_validate_method_cache_entries (void) 
  ATTRIBUTE_HIDDEN;

/* Terminate execution of the given PROCESSOOP.  */
extern void _gst_terminate_process (OOP processOOP) 
  ATTRIBUTE_HIDDEN;

/* This is a further simplified lookup_method which does not care
   about preparing for #doesNotUnderstand:.  */
extern mst_Boolean _gst_find_method (OOP classOOP, OOP sendSelector,
				     method_cache_entry *mce) 
  ATTRIBUTE_HIDDEN;

/* Similar to _gst_send_message_internal, but forces the specified
   CompiledMethod to be sent.  If it is not valid for the current
   receiver, well, you are looking for trouble and well deserve it.
   The number of arguments is looked in METHODOOP.  */
extern void _gst_send_method (OOP methodOOP) 
  ATTRIBUTE_HIDDEN;

/* This functions accepts an OOP for a Semaphore object and puts the
   current process to sleep, unless the semaphore has excess signals
   on it.  Since a Smalltalk call-in is not an atomic operation, the
   correct way to signal a semaphore is not to send the wait method to
   the object but, rather, to use _gst_sync_wait.  The `sync' in the
   name of this function distinguishes it from _gst_async_signal, in
   that it cannot be called from within a signal handler.  */
extern void _gst_sync_wait (OOP semaphoreOOP) 
  ATTRIBUTE_HIDDEN;

/* Signal the given SEMAPHOREOOP and if processes were queued on it
   resume the one that has waited for the longest time and is still
   alive.  If INCR is true, increment its value if no processes were
   queued.  Return true if a process was woken.

   This functions also cannot be called from within a signal handler.
   It can be called from a function that is registered with
   _gst_async_call, though.  */
extern mst_Boolean _gst_sync_signal (OOP semaphoreOOP,
			      mst_Boolean incr_if_empty)
  ATTRIBUTE_HIDDEN;

/* Take a CompiledBlock and turn it into a BlockClosure that references
   thisContext as its static link.  */
extern OOP _gst_make_block_closure (OOP blockOOP) 
  ATTRIBUTE_HIDDEN;

/************************************************* PRIMITIVES ****************/

/* The type for a routine providing the definition for one or more
   primitive methods in the GNU Smalltalk system.  They normally
   remove the arguments to the primitive methods from the stack, but
   if the primitive fails, the arguments are put back onto the stack
   and the routine returns true (-1 for the JIT), indicating failure
   to invoke the primitive.  Such a function must execute a primitive,
   aided in the choice of which by the user-defined parameter ID,
   popping NUMARGS methods off the stack if they succeed.  */
typedef intptr_t (*primitive_func) (int primitive, 
				    volatile int numArgs);

/* Table of primitives, including a primitive and its attributes.  */
typedef struct prim_table_entry
{
  const char *name;
  primitive_func func;
  int attributes;
  int id;
}
prim_table_entry;

#define PRIM_SUCCEED			0x0001
#define PRIM_FAIL			0x0002
#define PRIM_RELOAD_IP			0x0004
#define PRIM_OUTCOMES			0x0007
#define PRIM_CACHE_NEW_IP		0x0008
#define PRIM_INLINED			0x0010
#define PRIM_CHECK_INTERRUPT		0x0020
#define PRIM_RETURN_SMALL_INTEGER	0x0100	/* 31 or 63 bits */
#define PRIM_RETURN_SMALL_SMALLINTEGER	0x0300	/* 30 or 62 bits */

/* The checksum of the table of primitive numbers.  Right now it is an MD5,
   computed from part of the C source code of prims.inl.  We compare it when
   loading an image, to avoid having to reload the primitive table.  */
extern unsigned char _gst_primitives_md5[16];

/* The table of functions that implement the primitives.  */
extern prim_table_entry _gst_primitive_table[NUM_PRIMITIVES];
extern prim_table_entry _gst_default_primitive_table[NUM_PRIMITIVES];
 
/* This can be used to obtain information on a particular primitive
   operations in the GNU Smalltalk system.  */
extern prim_table_entry * _gst_get_primitive_attributes (int primitive)
  ATTRIBUTE_PURE 
  ATTRIBUTE_HIDDEN;

/* Dually, this maps the primitive number that will be used for running
   the image, to the entry which was returned by _gst_get_primitive_attributes.
   If PTE is NULL, the primitive will be invalid.  */
extern void _gst_set_primitive_attributes (int primitive,
					   prim_table_entry *pte)
  ATTRIBUTE_HIDDEN;

/* Initialize the table of primitives.  */
extern void _gst_init_primitives () 
  ATTRIBUTE_HIDDEN;

/* Get the value of internal variable whose number is INDEX; the
   list of valid variables is in gstpub.h.  Return -1 if the index
   is invalid.  */
extern int _gst_get_var (enum gst_var_index index)
  ATTRIBUTE_HIDDEN;

/* Set the value of internal variable whose number is INDEX; the
   list of valid variables is in gstpub.h.  Return -1 if the index
   is invalid or the value is negative, otherwise return the previous
   value.  */
extern int _gst_set_var (enum gst_var_index index, int value)
  ATTRIBUTE_HIDDEN;

#endif /* GST_INTERP_H */