1 /* Copyright (C) 2001, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 /* This file is included in vm_engine.c */
26 /* Register optimization. [ stolen from librep/src/lispmach.h,v 1.3 ]
28 Some compilers underestimate the use of the local variables representing
29 the abstract machine registers, and don't put them in hardware registers,
30 which slows down the interpreter considerably.
31 For GCC, I have hand-assigned hardware registers for several architectures.
36 #define IP_REG asm("$16")
37 #define SP_REG asm("$17")
38 #define FP_REG asm("$18")
41 #define IP_REG asm("%l0")
42 #define SP_REG asm("%l1")
43 #define FP_REG asm("%l2")
47 #define IP_REG asm("r9")
48 #define SP_REG asm("r10")
49 #define FP_REG asm("r11")
51 #define IP_REG asm("$9")
52 #define SP_REG asm("$10")
53 #define FP_REG asm("$11")
57 /* too few registers! because of register allocation errors with various gcs,
58 just punt on explicit assignments on i386, hoping that the "register"
59 declaration will be sufficient. */
60 #elif defined __x86_64__
61 /* GCC 4.6 chooses %rbp for IP_REG and %rbx for SP_REG, which works
62 well. Tell it to keep the jump table in a r12, which is
64 #define JT_REG asm ("r12")
66 #if defined(PPC) || defined(_POWER) || defined(_IBMR2)
67 #define IP_REG asm("26")
68 #define SP_REG asm("27")
69 #define FP_REG asm("28")
72 #define IP_REG asm("%r18")
73 #define SP_REG asm("%r17")
74 #define FP_REG asm("%r16")
77 #define IP_REG asm("a5")
78 #define SP_REG asm("a4")
82 #define IP_REG asm("r9")
83 #define SP_REG asm("r8")
84 #define FP_REG asm("r7")
106 #ifdef VM_ENABLE_ASSERTIONS
107 # define ASSERT(condition) if (SCM_UNLIKELY (!(condition))) abort()
109 # define ASSERT(condition)
113 /* Cache the VM's instruction, stack, and frame pointer in local variables. */
114 #define CACHE_REGISTER() \
121 /* Update the registers in VP, a pointer to the current VM. This must be done
122 at least before any GC invocation so that `vp->sp' is up-to-date and the
123 whole stack gets marked. */
124 #define SYNC_REGISTER() \
132 #define ASSERT_VARIABLE(x) \
133 do { if (!SCM_VARIABLEP (x)) { SYNC_REGISTER (); abort(); } \
135 #define ASSERT_BOUND_VARIABLE(x) \
136 do { ASSERT_VARIABLE (x); \
137 if (scm_is_eq (SCM_VARIABLE_REF (x), SCM_UNDEFINED)) \
138 { SYNC_REGISTER (); abort(); } \
141 #ifdef VM_ENABLE_PARANOID_ASSERTIONS
143 do { if (ip < bp->base || ip - bp->base > bp->len) abort (); } while (0)
144 #define ASSERT_ALIGNED_PROCEDURE() \
145 do { if ((scm_t_bits)bp % 8) abort (); } while (0)
146 #define ASSERT_BOUND(x) \
147 do { if (scm_is_eq ((x), SCM_UNDEFINED)) { SYNC_REGISTER (); abort(); } \
151 #define ASSERT_ALIGNED_PROCEDURE()
152 #define ASSERT_BOUND(x)
155 #define DEAD(v) v = SCM_UNDEFINED
158 #define SET_OBJECT_COUNT(n) object_count = n
160 #define SET_OBJECT_COUNT(n) /* nop */
163 /* Cache the object table and free variables. */
164 #define CACHE_PROGRAM() \
166 if (bp != SCM_PROGRAM_DATA (program)) { \
167 bp = SCM_PROGRAM_DATA (program); \
168 ASSERT_ALIGNED_PROCEDURE (); \
169 if (SCM_I_IS_VECTOR (SCM_PROGRAM_OBJTABLE (program))) { \
170 objects = SCM_I_VECTOR_WELTS (SCM_PROGRAM_OBJTABLE (program)); \
171 SET_OBJECT_COUNT (SCM_I_VECTOR_LENGTH (SCM_PROGRAM_OBJTABLE (program))); \
174 SET_OBJECT_COUNT (0); \
179 #define SYNC_BEFORE_GC() \
194 /* Accesses to a program's object table. */
196 #define CHECK_OBJECT(_num) \
197 do { if (SCM_UNLIKELY ((_num) >= object_count)) goto vm_error_object; } while (0)
199 #define CHECK_OBJECT(_num)
202 #if VM_CHECK_FREE_VARIABLES
203 #define CHECK_FREE_VARIABLE(_num) \
205 if (SCM_UNLIKELY ((_num) >= SCM_PROGRAM_NUM_FREE_VARIABLES (program))) \
206 goto vm_error_free_variable; \
209 #define CHECK_FREE_VARIABLE(_num)
220 #define RUN_HOOK(h) \
222 if (SCM_UNLIKELY (vp->trace_level > 0)) \
225 vm_dispatch_hook (vm, h); \
228 #define RUN_HOOK1(h, x) \
230 if (SCM_UNLIKELY (vp->trace_level > 0)) \
234 vm_dispatch_hook (vm, h); \
240 #define RUN_HOOK1(h, x)
243 #define APPLY_HOOK() \
244 RUN_HOOK (SCM_VM_APPLY_HOOK)
245 #define PUSH_CONTINUATION_HOOK() \
246 RUN_HOOK (SCM_VM_PUSH_CONTINUATION_HOOK)
247 #define POP_CONTINUATION_HOOK(n) \
248 RUN_HOOK1 (SCM_VM_POP_CONTINUATION_HOOK, SCM_I_MAKINUM (n))
249 #define NEXT_HOOK() \
250 RUN_HOOK (SCM_VM_NEXT_HOOK)
251 #define ABORT_CONTINUATION_HOOK() \
252 RUN_HOOK (SCM_VM_ABORT_CONTINUATION_HOOK)
253 #define RESTORE_CONTINUATION_HOOK() \
254 RUN_HOOK (SCM_VM_RESTORE_CONTINUATION_HOOK)
256 #define VM_HANDLE_INTERRUPTS \
257 SCM_ASYNC_TICK_WITH_CODE (current_thread, SYNC_REGISTER ())
264 #ifdef VM_ENABLE_STACK_NULLING
265 # define CHECK_STACK_LEAKN(_n) ASSERT (!sp[_n]);
266 # define CHECK_STACK_LEAK() CHECK_STACK_LEAKN(1)
267 # define NULLSTACK(_n) { int __x = _n; CHECK_STACK_LEAKN (_n+1); while (__x > 0) sp[__x--] = NULL; }
268 /* If you have a nonlocal exit in a pre-wind proc while invoking a continuation
269 inside a dynwind (phew!), the stack is fully rewound but vm_reset_stack for
270 that continuation doesn't have a chance to run. It's not important on a
271 semantic level, but it does mess up our stack nulling -- so this macro is to
273 # define NULLSTACK_FOR_NONLOCAL_EXIT() if (vp->sp > sp) NULLSTACK (vp->sp - sp);
275 # define CHECK_STACK_LEAKN(_n)
276 # define CHECK_STACK_LEAK()
277 # define NULLSTACK(_n)
278 # define NULLSTACK_FOR_NONLOCAL_EXIT()
281 #define CHECK_OVERFLOW() \
282 if (SCM_UNLIKELY (sp >= stack_limit)) \
283 goto vm_error_stack_overflow
286 #ifdef VM_CHECK_UNDERFLOW
287 #define CHECK_UNDERFLOW() \
288 if (SCM_UNLIKELY (sp <= SCM_FRAME_UPPER_ADDRESS (fp))) \
289 goto vm_error_stack_underflow
290 #define PRE_CHECK_UNDERFLOW(N) \
291 if (SCM_UNLIKELY (sp - N <= SCM_FRAME_UPPER_ADDRESS (fp))) \
292 goto vm_error_stack_underflow
294 #define CHECK_UNDERFLOW() /* nop */
295 #define PRE_CHECK_UNDERFLOW(N) /* nop */
299 #define PUSH(x) do { sp++; CHECK_OVERFLOW (); *sp = x; } while (0)
300 #define DROP() do { sp--; CHECK_UNDERFLOW (); NULLSTACK (1); } while (0)
301 #define DROPN(_n) do { sp -= (_n); CHECK_UNDERFLOW (); NULLSTACK (_n); } while (0)
302 #define POP(x) do { PRE_CHECK_UNDERFLOW (1); x = *sp--; NULLSTACK (1); } while (0)
303 #define POP2(x,y) do { PRE_CHECK_UNDERFLOW (2); x = *sp--; y = *sp--; NULLSTACK (2); } while (0)
304 #define POP3(x,y,z) do { PRE_CHECK_UNDERFLOW (3); x = *sp--; y = *sp--; z = *sp--; NULLSTACK (3); } while (0)
306 /* A fast CONS. This has to be fast since its used, for instance, by
307 POP_LIST when fetching a function's argument list. Note: `scm_cell' is an
308 inlined function in Guile 1.7. Unfortunately, it calls
309 `scm_gc_for_newcell ()' which is _not_ inlined and allocated cells on the
311 #define CONS(x,y,z) \
314 x = scm_cell (SCM_UNPACK (y), SCM_UNPACK (z)); \
317 /* Pop the N objects on top of the stack and push a list that contains
319 #define POP_LIST(n) \
323 SCM l = SCM_EOL, x; \
324 for (i = n; i; i--) \
333 /* The opposite: push all of the elements in L onto the list. */
334 #define PUSH_LIST(l, NILP) \
337 for (; scm_is_pair (l); l = SCM_CDR (l)) \
338 PUSH (SCM_CAR (l)); \
339 if (SCM_UNLIKELY (!NILP (l))) { \
340 finish_args = scm_list_1 (l); \
341 goto vm_error_improper_list; \
346 #define POP_LIST_MARK() \
351 while (!SCM_UNBNDP (o)) \
361 #define POP_CONS_MARK() \
366 while (!SCM_UNBNDP (o)) \
378 * Instruction operation
381 #define FETCH() (*ip++)
382 #define FETCH_LENGTH(len) do { len=*ip++; len<<=8; len+=*ip++; len<<=8; len+=*ip++; } while (0)
385 #ifdef HAVE_LABELS_AS_VALUES
386 #define NEXT_JUMP() goto *jump_table[FETCH () & SCM_VM_INSTRUCTION_MASK]
388 #define NEXT_JUMP() goto vm_start
394 CHECK_STACK_LEAK (); \
399 /* See frames.h for the layout of stack frames */
400 /* When this is called, bp points to the new program data,
401 and the arguments are already on the stack */
402 #define DROP_FRAME() \
406 CHECK_UNDERFLOW (); \