vm-engine.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /* Copyright (C) 2001, 2009 Free Software Foundation, Inc.
  2. *
  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.
  7. *
  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.
  12. *
  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
  16. * 02110-1301 USA
  17. */
  18. /* This file is included in vm_engine.c */
  19. /*
  20. * Registers
  21. */
  22. /* Register optimization. [ stolen from librep/src/lispmach.h,v 1.3 ]
  23. Some compilers underestimate the use of the local variables representing
  24. the abstract machine registers, and don't put them in hardware registers,
  25. which slows down the interpreter considerably.
  26. For GCC, I have hand-assigned hardware registers for several architectures.
  27. */
  28. #ifdef __GNUC__
  29. #ifdef __mips__
  30. #define IP_REG asm("$16")
  31. #define SP_REG asm("$17")
  32. #define FP_REG asm("$18")
  33. #endif
  34. #ifdef __sparc__
  35. #define IP_REG asm("%l0")
  36. #define SP_REG asm("%l1")
  37. #define FP_REG asm("%l2")
  38. #endif
  39. #ifdef __alpha__
  40. #ifdef __CRAY__
  41. #define IP_REG asm("r9")
  42. #define SP_REG asm("r10")
  43. #define FP_REG asm("r11")
  44. #else
  45. #define IP_REG asm("$9")
  46. #define SP_REG asm("$10")
  47. #define FP_REG asm("$11")
  48. #endif
  49. #endif
  50. #ifdef __i386__
  51. /* too few registers! because of register allocation errors with various gcs,
  52. just punt on explicit assignments on i386, hoping that the "register"
  53. declaration will be sufficient. */
  54. #endif
  55. #if defined(PPC) || defined(_POWER) || defined(_IBMR2)
  56. #define IP_REG asm("26")
  57. #define SP_REG asm("27")
  58. #define FP_REG asm("28")
  59. #endif
  60. #ifdef __hppa__
  61. #define IP_REG asm("%r18")
  62. #define SP_REG asm("%r17")
  63. #define FP_REG asm("%r16")
  64. #endif
  65. #ifdef __mc68000__
  66. #define IP_REG asm("a5")
  67. #define SP_REG asm("a4")
  68. #define FP_REG
  69. #endif
  70. #ifdef __arm__
  71. #define IP_REG asm("r9")
  72. #define SP_REG asm("r8")
  73. #define FP_REG asm("r7")
  74. #endif
  75. #endif
  76. #ifndef IP_REG
  77. #define IP_REG
  78. #endif
  79. #ifndef SP_REG
  80. #define SP_REG
  81. #endif
  82. #ifndef FP_REG
  83. #define FP_REG
  84. #endif
  85. /*
  86. * Cache/Sync
  87. */
  88. #ifdef VM_ENABLE_ASSERTIONS
  89. # define ASSERT(condition) if (SCM_UNLIKELY (!(condition))) abort()
  90. #else
  91. # define ASSERT(condition)
  92. #endif
  93. #define CACHE_REGISTER() \
  94. { \
  95. ip = vp->ip; \
  96. sp = vp->sp; \
  97. fp = vp->fp; \
  98. stack_base = fp ? SCM_FRAME_UPPER_ADDRESS (fp) - 1 : vp->stack_base; \
  99. }
  100. #define SYNC_REGISTER() \
  101. { \
  102. vp->ip = ip; \
  103. vp->sp = sp; \
  104. vp->fp = fp; \
  105. }
  106. /* FIXME */
  107. #define ASSERT_VARIABLE(x) \
  108. do { if (!SCM_VARIABLEP (x)) { SYNC_REGISTER (); abort(); } \
  109. } while (0)
  110. #define ASSERT_BOUND_VARIABLE(x) \
  111. do { ASSERT_VARIABLE (x); \
  112. if (SCM_VARIABLE_REF (x) == SCM_UNDEFINED) \
  113. { SYNC_REGISTER (); abort(); } \
  114. } while (0)
  115. #ifdef VM_ENABLE_PARANOID_ASSERTIONS
  116. #define CHECK_IP() \
  117. do { if (ip < bp->base || ip - bp->base > bp->len) abort (); } while (0)
  118. #define ASSERT_ALIGNED_PROCEDURE() \
  119. do { if ((scm_t_bits)bp % 8) abort (); } while (0)
  120. #define ASSERT_BOUND(x) \
  121. do { if ((x) == SCM_UNDEFINED) { SYNC_REGISTER (); abort(); } \
  122. } while (0)
  123. #else
  124. #define CHECK_IP()
  125. #define ASSERT_ALIGNED_PROCEDURE()
  126. #define ASSERT_BOUND(x)
  127. #endif
  128. /* Cache the object table and free variables. */
  129. #define CACHE_PROGRAM() \
  130. { \
  131. if (bp != SCM_PROGRAM_DATA (program)) { \
  132. bp = SCM_PROGRAM_DATA (program); \
  133. ASSERT_ALIGNED_PROCEDURE (); \
  134. if (SCM_I_IS_VECTOR (SCM_PROGRAM_OBJTABLE (program))) { \
  135. objects = SCM_I_VECTOR_WELTS (SCM_PROGRAM_OBJTABLE (program)); \
  136. object_count = SCM_I_VECTOR_LENGTH (SCM_PROGRAM_OBJTABLE (program)); \
  137. } else { \
  138. objects = NULL; \
  139. object_count = 0; \
  140. } \
  141. } \
  142. { \
  143. SCM c = SCM_PROGRAM_FREE_VARIABLES (program); \
  144. if (SCM_I_IS_VECTOR (c)) \
  145. { \
  146. free_vars = SCM_I_VECTOR_WELTS (c); \
  147. free_vars_count = SCM_I_VECTOR_LENGTH (c); \
  148. } \
  149. else \
  150. { \
  151. free_vars = NULL; \
  152. free_vars_count = 0; \
  153. } \
  154. } \
  155. }
  156. #define SYNC_BEFORE_GC() \
  157. { \
  158. SYNC_REGISTER (); \
  159. }
  160. #define SYNC_ALL() \
  161. { \
  162. SYNC_REGISTER (); \
  163. }
  164. /*
  165. * Error check
  166. */
  167. /* Accesses to a program's object table. */
  168. #if VM_CHECK_OBJECT
  169. #define CHECK_OBJECT(_num) \
  170. do { if (SCM_UNLIKELY ((_num) >= object_count)) goto vm_error_object; } while (0)
  171. #else
  172. #define CHECK_OBJECT(_num)
  173. #endif
  174. #if VM_CHECK_FREE_VARIABLES
  175. #define CHECK_FREE_VARIABLE(_num) \
  176. do { if (SCM_UNLIKELY ((_num) >= free_vars_count)) goto vm_error_free_variable; } while (0)
  177. #else
  178. #define CHECK_FREE_VARIABLE(_num)
  179. #endif
  180. /*
  181. * Hooks
  182. */
  183. #undef RUN_HOOK
  184. #if VM_USE_HOOKS
  185. #define RUN_HOOK(h) \
  186. { \
  187. if (SCM_UNLIKELY (!SCM_FALSEP (vp->hooks[h])))\
  188. { \
  189. SYNC_REGISTER (); \
  190. vm_dispatch_hook (vp, vp->hooks[h], hook_args); \
  191. CACHE_REGISTER (); \
  192. } \
  193. }
  194. #else
  195. #define RUN_HOOK(h)
  196. #endif
  197. #define BOOT_HOOK() RUN_HOOK (SCM_VM_BOOT_HOOK)
  198. #define HALT_HOOK() RUN_HOOK (SCM_VM_HALT_HOOK)
  199. #define NEXT_HOOK() RUN_HOOK (SCM_VM_NEXT_HOOK)
  200. #define BREAK_HOOK() RUN_HOOK (SCM_VM_BREAK_HOOK)
  201. #define ENTER_HOOK() RUN_HOOK (SCM_VM_ENTER_HOOK)
  202. #define APPLY_HOOK() RUN_HOOK (SCM_VM_APPLY_HOOK)
  203. #define EXIT_HOOK() RUN_HOOK (SCM_VM_EXIT_HOOK)
  204. #define RETURN_HOOK() RUN_HOOK (SCM_VM_RETURN_HOOK)
  205. /*
  206. * Stack operation
  207. */
  208. #ifdef VM_ENABLE_STACK_NULLING
  209. # define CHECK_STACK_LEAKN(_n) ASSERT (!sp[_n]);
  210. # define CHECK_STACK_LEAK() CHECK_STACK_LEAKN(1)
  211. # define NULLSTACK(_n) { int __x = _n; CHECK_STACK_LEAKN (_n+1); while (__x > 0) sp[__x--] = NULL; }
  212. /* If you have a nonlocal exit in a pre-wind proc while invoking a continuation
  213. inside a dynwind (phew!), the stack is fully rewound but vm_reset_stack for
  214. that continuation doesn't have a chance to run. It's not important on a
  215. semantic level, but it does mess up our stack nulling -- so this macro is to
  216. fix that. */
  217. # define NULLSTACK_FOR_NONLOCAL_EXIT() if (vp->sp > sp) NULLSTACK (vp->sp - sp);
  218. #else
  219. # define CHECK_STACK_LEAKN(_n)
  220. # define CHECK_STACK_LEAK()
  221. # define NULLSTACK(_n)
  222. # define NULLSTACK_FOR_NONLOCAL_EXIT()
  223. #endif
  224. #define CHECK_OVERFLOW() \
  225. if (sp > stack_limit) \
  226. goto vm_error_stack_overflow
  227. #define CHECK_UNDERFLOW() \
  228. if (sp < stack_base) \
  229. goto vm_error_stack_underflow;
  230. #define PUSH(x) do { sp++; CHECK_OVERFLOW (); *sp = x; } while (0)
  231. #define DROP() do { sp--; CHECK_UNDERFLOW (); NULLSTACK (1); } while (0)
  232. #define DROPN(_n) do { sp -= (_n); CHECK_UNDERFLOW (); NULLSTACK (_n); } while (0)
  233. #define POP(x) do { x = *sp; DROP (); } while (0)
  234. /* A fast CONS. This has to be fast since its used, for instance, by
  235. POP_LIST when fetching a function's argument list. Note: `scm_cell' is an
  236. inlined function in Guile 1.7. Unfortunately, it calls
  237. `scm_gc_for_newcell ()' which is _not_ inlined and allocated cells on the
  238. heap. XXX */
  239. #define CONS(x,y,z) \
  240. { \
  241. SYNC_BEFORE_GC (); \
  242. x = scm_cell (SCM_UNPACK (y), SCM_UNPACK (z)); \
  243. }
  244. /* Pop the N objects on top of the stack and push a list that contains
  245. them. */
  246. #define POP_LIST(n) \
  247. do \
  248. { \
  249. int i; \
  250. SCM l = SCM_EOL, x; \
  251. for (i = n; i; i--) \
  252. { \
  253. POP (x); \
  254. CONS (l, x, l); \
  255. } \
  256. PUSH (l); \
  257. } while (0)
  258. /* The opposite: push all of the elements in L onto the list. */
  259. #define PUSH_LIST(l, NILP) \
  260. do \
  261. { \
  262. for (; scm_is_pair (l); l = SCM_CDR (l)) \
  263. PUSH (SCM_CAR (l)); \
  264. if (SCM_UNLIKELY (!NILP (l))) { \
  265. finish_args = scm_list_1 (l); \
  266. goto vm_error_improper_list; \
  267. } \
  268. } while (0)
  269. #define POP_LIST_MARK() \
  270. do { \
  271. SCM o; \
  272. SCM l = SCM_EOL; \
  273. POP (o); \
  274. while (!SCM_UNBNDP (o)) \
  275. { \
  276. CONS (l, o, l); \
  277. POP (o); \
  278. } \
  279. PUSH (l); \
  280. } while (0)
  281. #define POP_CONS_MARK() \
  282. do { \
  283. SCM o, l; \
  284. POP (l); \
  285. POP (o); \
  286. while (!SCM_UNBNDP (o)) \
  287. { \
  288. CONS (l, o, l); \
  289. POP (o); \
  290. } \
  291. PUSH (l); \
  292. } while (0)
  293. /*
  294. * Instruction operation
  295. */
  296. #define FETCH() (*ip++)
  297. #define FETCH_LENGTH(len) do { len=*ip++; len<<=8; len+=*ip++; len<<=8; len+=*ip++; } while (0)
  298. #define FETCH_WIDTH(width) do { width=*ip++; } while (0)
  299. #undef CLOCK
  300. #if VM_USE_CLOCK
  301. #define CLOCK(n) vp->clock += n
  302. #else
  303. #define CLOCK(n)
  304. #endif
  305. #undef NEXT_JUMP
  306. #ifdef HAVE_LABELS_AS_VALUES
  307. #define NEXT_JUMP() goto *jump_table[FETCH () & SCM_VM_INSTRUCTION_MASK]
  308. #else
  309. #define NEXT_JUMP() goto vm_start
  310. #endif
  311. #define NEXT \
  312. { \
  313. CLOCK (1); \
  314. NEXT_HOOK (); \
  315. CHECK_STACK_LEAK (); \
  316. NEXT_JUMP (); \
  317. }
  318. /*
  319. * Stack frame
  320. */
  321. #define INIT_ARGS() \
  322. { \
  323. if (SCM_UNLIKELY (bp->nrest)) \
  324. { \
  325. int n = nargs - (bp->nargs - 1); \
  326. if (n < 0) \
  327. goto vm_error_wrong_num_args; \
  328. /* NB, can cause GC while setting up the \
  329. stack frame */ \
  330. POP_LIST (n); \
  331. } \
  332. else \
  333. { \
  334. if (SCM_UNLIKELY (nargs != bp->nargs)) \
  335. goto vm_error_wrong_num_args; \
  336. } \
  337. }
  338. /* See frames.h for the layout of stack frames */
  339. /* When this is called, bp points to the new program data,
  340. and the arguments are already on the stack */
  341. #define NEW_FRAME() \
  342. { \
  343. int i; \
  344. SCM *dl, *data; \
  345. scm_byte_t *ra = ip; \
  346. \
  347. /* Save old registers */ \
  348. ra = ip; \
  349. dl = fp; \
  350. \
  351. /* New registers */ \
  352. fp = sp - bp->nargs + 1; \
  353. data = SCM_FRAME_DATA_ADDRESS (fp); \
  354. sp = data + 2; \
  355. CHECK_OVERFLOW (); \
  356. stack_base = sp; \
  357. ip = bp->base; \
  358. \
  359. /* Init local variables */ \
  360. for (i=bp->nlocs; i; i--) \
  361. data[-i] = SCM_UNDEFINED; \
  362. \
  363. /* Set frame data */ \
  364. data[2] = (SCM)ra; \
  365. data[1] = 0x0; \
  366. data[0] = (SCM)dl; \
  367. }
  368. /*
  369. Local Variables:
  370. c-file-style: "gnu"
  371. End:
  372. */