1 /* Copyright (C) 2001 Free Software Foundation, Inc.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
45 #include "instructions.h"
50 /* I sometimes use this for debugging. */
51 #define vm_puts(OBJ) \
53 scm_display (OBJ, scm_def_errp); \
54 scm_newline (scm_def_errp); \
62 scm_t_bits scm_tc16_vm_cont
;
65 #define SCM_VM_CONT_P(OBJ) SCM_SMOB_PREDICATE (scm_tc16_vm_cont, OBJ)
66 #define SCM_VM_CONT_VP(CONT) ((struct scm_vm *) SCM_CELL_WORD_1 (CONT))
69 capture_vm_cont (struct scm_vm
*vp
)
71 struct scm_vm
*p
= scm_gc_malloc (sizeof (*p
), "capture_vm_cont");
72 p
->stack_size
= vp
->stack_limit
- vp
->sp
;
73 p
->stack_base
= scm_gc_malloc (p
->stack_size
* sizeof (SCM
),
75 p
->stack_limit
= p
->stack_base
+ p
->stack_size
- 2;
77 p
->sp
= (SCM
*) (vp
->stack_limit
- vp
->sp
);
78 p
->fp
= (SCM
*) (vp
->stack_limit
- vp
->fp
);
79 memcpy (p
->stack_base
, vp
->sp
+ 1, vp
->stack_size
* sizeof (SCM
));
80 SCM_RETURN_NEWSMOB (scm_tc16_vm_cont
, p
);
84 reinstate_vm_cont (struct scm_vm
*vp
, SCM cont
)
86 struct scm_vm
*p
= SCM_VM_CONT_VP (cont
);
87 if (vp
->stack_size
< p
->stack_size
)
89 /* puts ("FIXME: Need to expand"); */
93 vp
->sp
= vp
->stack_limit
- (int) p
->sp
;
94 vp
->fp
= vp
->stack_limit
- (int) p
->fp
;
95 memcpy (vp
->sp
+ 1, p
->stack_base
, p
->stack_size
* sizeof (SCM
));
99 vm_cont_mark (SCM obj
)
102 struct scm_vm
*vp
= SCM_VM_CONT_VP (obj
);
103 for (p
= vp
->stack_base
; p
<= vp
->stack_limit
; p
++)
110 vm_cont_free (SCM obj
)
112 struct scm_vm
*p
= SCM_VM_CONT_VP (obj
);
114 scm_gc_free (p
->stack_base
, p
->stack_size
* sizeof (SCM
), "stack-base");
115 scm_gc_free (p
, sizeof (struct scm_vm
), "vm");
122 * VM Internal functions
125 SCM_SYMBOL (sym_vm_run
, "vm-run");
126 SCM_SYMBOL (sym_vm_error
, "vm-error");
129 vm_fetch_length (scm_byte_t
*ip
, size_t *lenp
)
131 /* NOTE: format defined in system/vm/conv.scm */
135 else if (*lenp
== 254)
139 *lenp
= (b1
<< 8) + b2
;
147 *lenp
= (b1
<< 24) + (b2
<< 16) + (b3
<< 8) + b4
;
153 vm_heapify_frames_1 (struct scm_vm
*vp
, SCM
*fp
, SCM
*sp
, SCM
**destp
)
156 SCM
*dl
= SCM_FRAME_DYNAMIC_LINK (fp
);
157 SCM
*src
= SCM_FRAME_UPPER_ADDRESS (fp
);
158 SCM
*dest
= SCM_FRAME_LOWER_ADDRESS (fp
);
163 frame
= scm_c_make_heap_frame (fp
);
164 fp
= SCM_HEAP_FRAME_POINTER (frame
);
165 SCM_FRAME_HEAP_LINK (fp
) = SCM_BOOL_T
;
170 SCM link
= SCM_FRAME_HEAP_LINK (dl
);
171 if (!SCM_FALSEP (link
))
172 link
= SCM_FRAME_LOWER_ADDRESS (dl
)[-1]; /* self link */
174 link
= vm_heapify_frames_1 (vp
, dl
, dest
- 1, &dest
);
175 frame
= scm_c_make_heap_frame (fp
);
176 fp
= SCM_HEAP_FRAME_POINTER (frame
);
177 SCM_FRAME_HEAP_LINK (fp
) = link
;
178 SCM_FRAME_DYNAMIC_LINK (fp
) = SCM_HEAP_FRAME_POINTER (link
);
181 /* Move stack data */
182 for (; src
<= sp
; src
++, dest
++)
190 vm_heapify_frames (SCM vm
)
192 struct scm_vm
*vp
= SCM_VM_DATA (vm
);
193 if (SCM_FALSEP (SCM_FRAME_HEAP_LINK (vp
->fp
)))
196 vp
->this_frame
= vm_heapify_frames_1 (vp
, vp
->fp
, vp
->sp
, &dest
);
197 vp
->fp
= SCM_HEAP_FRAME_POINTER (vp
->this_frame
);
200 return vp
->this_frame
;
208 #define VM_DEFAULT_STACK_SIZE (16 * 1024)
210 #define VM_REGULAR_ENGINE 0
211 #define VM_DEBUG_ENGINE 1
214 #define VM_NAME vm_regular_engine
215 #define VM_ENGINE VM_REGULAR_ENGINE
216 #include "vm_engine.c"
221 #define VM_NAME vm_debug_engine
222 #define VM_ENGINE VM_DEBUG_ENGINE
223 #include "vm_engine.c"
227 scm_t_bits scm_tc16_vm
;
233 #define FUNC_NAME "make_vm"
236 struct scm_vm
*vp
= scm_gc_malloc (sizeof (struct scm_vm
), "vm");
238 vp
->stack_size
= VM_DEFAULT_STACK_SIZE
;
239 vp
->stack_base
= scm_gc_malloc (vp
->stack_size
* sizeof (SCM
),
241 vp
->stack_limit
= vp
->stack_base
+ vp
->stack_size
- 3;
243 vp
->sp
= vp
->stack_base
- 1;
247 vp
->options
= SCM_EOL
;
248 vp
->this_frame
= SCM_BOOL_F
;
249 vp
->last_frame
= SCM_BOOL_F
;
250 for (i
= 0; i
< SCM_VM_NUM_HOOKS
; i
++)
251 vp
->hooks
[i
] = SCM_BOOL_F
;
252 SCM_RETURN_NEWSMOB (scm_tc16_vm
, vp
);
260 struct scm_vm
*vp
= SCM_VM_DATA (obj
);
262 /* mark the stack conservatively */
263 scm_mark_locations ((SCM_STACKITEM
*) vp
->stack_base
,
264 sizeof (SCM
) * (vp
->sp
- vp
->stack_base
+ 1));
266 /* mark other objects */
267 for (i
= 0; i
< SCM_VM_NUM_HOOKS
; i
++)
268 scm_gc_mark (vp
->hooks
[i
]);
269 scm_gc_mark (vp
->this_frame
);
270 scm_gc_mark (vp
->last_frame
);
277 struct scm_vm
*vp
= SCM_VM_DATA (obj
);
279 scm_gc_free (vp
->stack_base
, vp
->stack_size
* sizeof (SCM
),
281 scm_gc_free (vp
, sizeof (struct scm_vm
), "vm");
286 SCM_SYMBOL (sym_debug
, "debug");
289 scm_vm_apply (SCM vm
, SCM program
, SCM args
)
290 #define FUNC_NAME "scm_vm_apply"
292 SCM_VALIDATE_PROGRAM (1, program
);
293 return vm_run (vm
, program
, args
);
297 /* Scheme interface */
299 SCM_DEFINE (scm_vm_version
, "vm-version", 0, 0, 0,
302 #define FUNC_NAME s_scm_vm_version
304 return scm_from_locale_string (VERSION
);
308 SCM_DEFINE (scm_the_vm
, "the-vm", 0, 0, 0,
311 #define FUNC_NAME s_scm_the_vm
318 SCM_DEFINE (scm_vm_p
, "vm?", 1, 0, 0,
321 #define FUNC_NAME s_scm_vm_p
323 return SCM_BOOL (SCM_VM_P (obj
));
327 SCM_DEFINE (scm_make_vm
, "make-vm", 0, 0, 0,
330 #define FUNC_NAME s_scm_make_vm,
336 SCM_DEFINE (scm_vm_ip
, "vm:ip", 1, 0, 0,
339 #define FUNC_NAME s_scm_vm_ip
341 SCM_VALIDATE_VM (1, vm
);
342 return scm_ulong2num ((unsigned long) SCM_VM_DATA (vm
)->ip
);
346 SCM_DEFINE (scm_vm_sp
, "vm:sp", 1, 0, 0,
349 #define FUNC_NAME s_scm_vm_sp
351 SCM_VALIDATE_VM (1, vm
);
352 return scm_ulong2num ((unsigned long) SCM_VM_DATA (vm
)->sp
);
356 SCM_DEFINE (scm_vm_fp
, "vm:fp", 1, 0, 0,
359 #define FUNC_NAME s_scm_vm_fp
361 SCM_VALIDATE_VM (1, vm
);
362 return scm_ulong2num ((unsigned long) SCM_VM_DATA (vm
)->fp
);
366 #define VM_DEFINE_HOOK(n) \
369 SCM_VALIDATE_VM (1, vm); \
370 vp = SCM_VM_DATA (vm); \
371 if (SCM_FALSEP (vp->hooks[n])) \
372 vp->hooks[n] = scm_make_hook (SCM_I_MAKINUM (1)); \
373 return vp->hooks[n]; \
376 SCM_DEFINE (scm_vm_boot_hook
, "vm-boot-hook", 1, 0, 0,
379 #define FUNC_NAME s_scm_vm_boot_hook
381 VM_DEFINE_HOOK (SCM_VM_BOOT_HOOK
);
385 SCM_DEFINE (scm_vm_halt_hook
, "vm-halt-hook", 1, 0, 0,
388 #define FUNC_NAME s_scm_vm_halt_hook
390 VM_DEFINE_HOOK (SCM_VM_HALT_HOOK
);
394 SCM_DEFINE (scm_vm_next_hook
, "vm-next-hook", 1, 0, 0,
397 #define FUNC_NAME s_scm_vm_next_hook
399 VM_DEFINE_HOOK (SCM_VM_NEXT_HOOK
);
403 SCM_DEFINE (scm_vm_break_hook
, "vm-break-hook", 1, 0, 0,
406 #define FUNC_NAME s_scm_vm_break_hook
408 VM_DEFINE_HOOK (SCM_VM_BREAK_HOOK
);
412 SCM_DEFINE (scm_vm_enter_hook
, "vm-enter-hook", 1, 0, 0,
415 #define FUNC_NAME s_scm_vm_enter_hook
417 VM_DEFINE_HOOK (SCM_VM_ENTER_HOOK
);
421 SCM_DEFINE (scm_vm_apply_hook
, "vm-apply-hook", 1, 0, 0,
424 #define FUNC_NAME s_scm_vm_apply_hook
426 VM_DEFINE_HOOK (SCM_VM_APPLY_HOOK
);
430 SCM_DEFINE (scm_vm_exit_hook
, "vm-exit-hook", 1, 0, 0,
433 #define FUNC_NAME s_scm_vm_exit_hook
435 VM_DEFINE_HOOK (SCM_VM_EXIT_HOOK
);
439 SCM_DEFINE (scm_vm_return_hook
, "vm-return-hook", 1, 0, 0,
442 #define FUNC_NAME s_scm_vm_return_hook
444 VM_DEFINE_HOOK (SCM_VM_RETURN_HOOK
);
448 SCM_DEFINE (scm_vm_option
, "vm-option", 2, 0, 0,
451 #define FUNC_NAME s_scm_vm_option
453 SCM_VALIDATE_VM (1, vm
);
454 return scm_assq_ref (SCM_VM_DATA (vm
)->options
, key
);
458 SCM_DEFINE (scm_set_vm_option_x
, "set-vm-option!", 3, 0, 0,
459 (SCM vm
, SCM key
, SCM val
),
461 #define FUNC_NAME s_scm_set_vm_option_x
463 SCM_VALIDATE_VM (1, vm
);
464 SCM_VM_DATA (vm
)->options
465 = scm_assq_set_x (SCM_VM_DATA (vm
)->options
, key
, val
);
466 return SCM_UNSPECIFIED
;
470 SCM_DEFINE (scm_vm_stats
, "vm-stats", 1, 0, 0,
473 #define FUNC_NAME s_scm_vm_stats
477 SCM_VALIDATE_VM (1, vm
);
479 stats
= scm_make_vector (SCM_I_MAKINUM (2), SCM_UNSPECIFIED
);
480 scm_vector_set_x (stats
, SCM_I_MAKINUM (0),
481 scm_from_ulong (SCM_VM_DATA (vm
)->time
));
482 scm_vector_set_x (stats
, SCM_I_MAKINUM (1),
483 scm_from_ulong (SCM_VM_DATA (vm
)->clock
));
489 #define VM_CHECK_RUNNING(vm) \
490 if (!SCM_VM_DATA (vm)->ip) \
491 SCM_MISC_ERROR ("Not running", SCM_LIST1 (vm))
493 SCM_DEFINE (scm_vm_this_frame
, "vm-this-frame", 1, 0, 0,
496 #define FUNC_NAME s_scm_vm_this_frame
498 SCM_VALIDATE_VM (1, vm
);
499 return SCM_VM_DATA (vm
)->this_frame
;
503 SCM_DEFINE (scm_vm_last_frame
, "vm-last-frame", 1, 0, 0,
506 #define FUNC_NAME s_scm_vm_last_frame
508 SCM_VALIDATE_VM (1, vm
);
509 return SCM_VM_DATA (vm
)->last_frame
;
513 SCM_DEFINE (scm_vm_fetch_code
, "vm-fetch-code", 1, 0, 0,
516 #define FUNC_NAME s_scm_vm_fetch_code
521 struct scm_instruction
*p
;
523 SCM_VALIDATE_VM (1, vm
);
524 VM_CHECK_RUNNING (vm
);
526 ip
= SCM_VM_DATA (vm
)->ip
;
527 p
= SCM_INSTRUCTION (*ip
);
529 list
= SCM_LIST1 (scm_str2symbol (p
->name
));
530 for (i
= 1; i
<= p
->len
; i
++)
531 list
= scm_cons (SCM_I_MAKINUM (ip
[i
]), list
);
532 return scm_reverse_x (list
, SCM_EOL
);
536 SCM_DEFINE (scm_vm_fetch_stack
, "vm-fetch-stack", 1, 0, 0,
539 #define FUNC_NAME s_scm_vm_fetch_stack
545 SCM_VALIDATE_VM (1, vm
);
546 VM_CHECK_RUNNING (vm
);
548 vp
= SCM_VM_DATA (vm
);
549 for (sp
= vp
->stack_base
; sp
<= vp
->sp
; sp
++)
550 ls
= scm_cons (*sp
, ls
);
564 scm_init_instructions ();
565 scm_init_objcodes ();
566 scm_init_programs ();
568 scm_tc16_vm_cont
= scm_make_smob_type ("vm-cont", 0);
569 scm_set_smob_mark (scm_tc16_vm_cont
, vm_cont_mark
);
570 scm_set_smob_free (scm_tc16_vm_cont
, vm_cont_free
);
572 scm_tc16_vm
= scm_make_smob_type ("vm", 0);
573 scm_set_smob_mark (scm_tc16_vm
, vm_mark
);
574 scm_set_smob_free (scm_tc16_vm
, vm_free
);
575 scm_set_smob_apply (scm_tc16_vm
, scm_vm_apply
, 1, 0, 1);
577 the_vm
= scm_permanent_object (make_vm ());
579 #ifndef SCM_MAGIC_SNARFER