frames.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /* Copyright (C) 2001, 2009, 2010, 2011, 2012 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. #if HAVE_CONFIG_H
  19. # include <config.h>
  20. #endif
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include "_scm.h"
  24. #include "frames.h"
  25. #include <verify.h>
  26. /* Make sure assumptions on the layout of `struct scm_vm_frame' hold. */
  27. verify (sizeof (SCM) == sizeof (SCM *));
  28. verify (sizeof (struct scm_vm_frame) == 5 * sizeof (SCM));
  29. verify (offsetof (struct scm_vm_frame, dynamic_link) == 0);
  30. #define RELOC(frame, val) \
  31. (((SCM *) (val)) + SCM_VM_FRAME_OFFSET (frame))
  32. SCM
  33. scm_c_make_frame (SCM stack_holder, SCM *fp, SCM *sp,
  34. scm_t_uint8 *ip, scm_t_ptrdiff offset)
  35. {
  36. struct scm_frame *p = scm_gc_malloc (sizeof (struct scm_frame),
  37. "vmframe");
  38. p->stack_holder = stack_holder;
  39. p->fp = fp;
  40. p->sp = sp;
  41. p->ip = ip;
  42. p->offset = offset;
  43. return scm_cell (scm_tc7_frame, (scm_t_bits)p);
  44. }
  45. void
  46. scm_i_frame_print (SCM frame, SCM port, scm_print_state *pstate)
  47. {
  48. scm_puts_unlocked ("#<frame ", port);
  49. scm_uintprint (SCM_UNPACK (frame), 16, port);
  50. scm_putc_unlocked (' ', port);
  51. scm_write (scm_frame_procedure (frame), port);
  52. /* don't write args, they can get us into trouble. */
  53. scm_puts_unlocked (">", port);
  54. }
  55. /* Scheme interface */
  56. SCM_DEFINE (scm_frame_p, "frame?", 1, 0, 0,
  57. (SCM obj),
  58. "")
  59. #define FUNC_NAME s_scm_frame_p
  60. {
  61. return scm_from_bool (SCM_VM_FRAME_P (obj));
  62. }
  63. #undef FUNC_NAME
  64. SCM_DEFINE (scm_frame_procedure, "frame-procedure", 1, 0, 0,
  65. (SCM frame),
  66. "")
  67. #define FUNC_NAME s_scm_frame_procedure
  68. {
  69. SCM_VALIDATE_VM_FRAME (1, frame);
  70. return SCM_FRAME_PROGRAM (SCM_VM_FRAME_FP (frame));
  71. }
  72. #undef FUNC_NAME
  73. SCM_DEFINE (scm_frame_arguments, "frame-arguments", 1, 0, 0,
  74. (SCM frame),
  75. "")
  76. #define FUNC_NAME s_scm_frame_arguments
  77. {
  78. static SCM var = SCM_BOOL_F;
  79. SCM_VALIDATE_VM_FRAME (1, frame);
  80. if (scm_is_false (var))
  81. var = scm_c_module_lookup (scm_c_resolve_module ("system vm frame"),
  82. "frame-arguments");
  83. return scm_call_1 (SCM_VARIABLE_REF (var), frame);
  84. }
  85. #undef FUNC_NAME
  86. SCM_DEFINE (scm_frame_source, "frame-source", 1, 0, 0,
  87. (SCM frame),
  88. "")
  89. #define FUNC_NAME s_scm_frame_source
  90. {
  91. SCM proc;
  92. SCM_VALIDATE_VM_FRAME (1, frame);
  93. proc = scm_frame_procedure (frame);
  94. if (SCM_PROGRAM_P (proc))
  95. return scm_program_source (scm_frame_procedure (frame),
  96. scm_frame_instruction_pointer (frame),
  97. SCM_UNDEFINED);
  98. return SCM_BOOL_F;
  99. }
  100. #undef FUNC_NAME
  101. /* The number of locals would be a simple thing to compute, if it weren't for
  102. the presence of not-yet-active frames on the stack. So we have a cheap
  103. heuristic to detect not-yet-active frames, and skip over them. Perhaps we
  104. should represent them more usefully.
  105. */
  106. SCM_DEFINE (scm_frame_num_locals, "frame-num-locals", 1, 0, 0,
  107. (SCM frame),
  108. "")
  109. #define FUNC_NAME s_scm_frame_num_locals
  110. {
  111. SCM *fp, *sp, *p;
  112. unsigned int n = 0;
  113. SCM_VALIDATE_VM_FRAME (1, frame);
  114. fp = SCM_VM_FRAME_FP (frame);
  115. sp = SCM_VM_FRAME_SP (frame);
  116. p = SCM_FRAME_STACK_ADDRESS (SCM_VM_FRAME_FP (frame));
  117. if (SCM_RTL_PROGRAM_P (fp[-1]))
  118. /* The frame size of an RTL program is fixed, except in the case of
  119. passing a wrong number of arguments to the program. So we do
  120. need to use an SP for determining the number of locals. */
  121. return scm_from_uint32 (sp + 1 - p);
  122. sp = SCM_VM_FRAME_SP (frame);
  123. p = SCM_FRAME_STACK_ADDRESS (SCM_VM_FRAME_FP (frame));
  124. while (p <= sp)
  125. {
  126. if (SCM_UNPACK (p[0]) == 0)
  127. /* skip over not-yet-active frame */
  128. p += 3;
  129. else
  130. {
  131. p++;
  132. n++;
  133. }
  134. }
  135. return scm_from_uint (n);
  136. }
  137. #undef FUNC_NAME
  138. /* Need same not-yet-active frame logic here as in frame-num-locals */
  139. SCM_DEFINE (scm_frame_local_ref, "frame-local-ref", 2, 0, 0,
  140. (SCM frame, SCM index),
  141. "")
  142. #define FUNC_NAME s_scm_frame_local_ref
  143. {
  144. SCM *sp, *p;
  145. unsigned int n = 0;
  146. unsigned int i;
  147. SCM_VALIDATE_VM_FRAME (1, frame);
  148. SCM_VALIDATE_UINT_COPY (2, index, i);
  149. sp = SCM_VM_FRAME_SP (frame);
  150. p = SCM_FRAME_STACK_ADDRESS (SCM_VM_FRAME_FP (frame));
  151. while (p <= sp)
  152. {
  153. if (SCM_UNPACK (p[0]) == 0)
  154. /* skip over not-yet-active frame */
  155. p += 3;
  156. else if (n == i)
  157. return *p;
  158. else
  159. {
  160. p++;
  161. n++;
  162. }
  163. }
  164. SCM_OUT_OF_RANGE (SCM_ARG2, index);
  165. }
  166. #undef FUNC_NAME
  167. /* Need same not-yet-active frame logic here as in frame-num-locals */
  168. SCM_DEFINE (scm_frame_local_set_x, "frame-local-set!", 3, 0, 0,
  169. (SCM frame, SCM index, SCM val),
  170. "")
  171. #define FUNC_NAME s_scm_frame_local_set_x
  172. {
  173. SCM *sp, *p;
  174. unsigned int n = 0;
  175. unsigned int i;
  176. SCM_VALIDATE_VM_FRAME (1, frame);
  177. SCM_VALIDATE_UINT_COPY (2, index, i);
  178. sp = SCM_VM_FRAME_SP (frame);
  179. p = SCM_FRAME_STACK_ADDRESS (SCM_VM_FRAME_FP (frame));
  180. while (p <= sp)
  181. {
  182. if (SCM_UNPACK (p[0]) == 0)
  183. /* skip over not-yet-active frame */
  184. p += 3;
  185. else if (n == i)
  186. {
  187. *p = val;
  188. return SCM_UNSPECIFIED;
  189. }
  190. else
  191. {
  192. p++;
  193. n++;
  194. }
  195. }
  196. SCM_OUT_OF_RANGE (SCM_ARG2, index);
  197. }
  198. #undef FUNC_NAME
  199. SCM_DEFINE (scm_frame_address, "frame-address", 1, 0, 0,
  200. (SCM frame),
  201. "Return the frame pointer for @var{frame}.")
  202. #define FUNC_NAME s_scm_frame_address
  203. {
  204. SCM_VALIDATE_VM_FRAME (1, frame);
  205. return scm_from_unsigned_integer ((scm_t_bits) SCM_VM_FRAME_FP (frame));
  206. }
  207. #undef FUNC_NAME
  208. SCM_DEFINE (scm_frame_stack_pointer, "frame-stack-pointer", 1, 0, 0,
  209. (SCM frame),
  210. "")
  211. #define FUNC_NAME s_scm_frame_stack_pointer
  212. {
  213. SCM_VALIDATE_VM_FRAME (1, frame);
  214. return scm_from_unsigned_integer ((scm_t_bits) SCM_VM_FRAME_SP (frame));
  215. }
  216. #undef FUNC_NAME
  217. SCM_DEFINE (scm_frame_instruction_pointer, "frame-instruction-pointer", 1, 0, 0,
  218. (SCM frame),
  219. "")
  220. #define FUNC_NAME s_scm_frame_instruction_pointer
  221. {
  222. SCM program;
  223. const struct scm_objcode *c_objcode;
  224. SCM_VALIDATE_VM_FRAME (1, frame);
  225. program = scm_frame_procedure (frame);
  226. if (!SCM_PROGRAM_P (program))
  227. return SCM_INUM0;
  228. c_objcode = SCM_PROGRAM_DATA (program);
  229. return scm_from_unsigned_integer ((SCM_VM_FRAME_IP (frame)
  230. - SCM_C_OBJCODE_BASE (c_objcode)));
  231. }
  232. #undef FUNC_NAME
  233. SCM_DEFINE (scm_frame_return_address, "frame-return-address", 1, 0, 0,
  234. (SCM frame),
  235. "")
  236. #define FUNC_NAME s_scm_frame_return_address
  237. {
  238. SCM_VALIDATE_VM_FRAME (1, frame);
  239. return scm_from_unsigned_integer ((scm_t_bits)
  240. (SCM_FRAME_RETURN_ADDRESS
  241. (SCM_VM_FRAME_FP (frame))));
  242. }
  243. #undef FUNC_NAME
  244. SCM_DEFINE (scm_frame_mv_return_address, "frame-mv-return-address", 1, 0, 0,
  245. (SCM frame),
  246. "")
  247. #define FUNC_NAME s_scm_frame_mv_return_address
  248. {
  249. SCM_VALIDATE_VM_FRAME (1, frame);
  250. return scm_from_unsigned_integer ((scm_t_bits)
  251. (SCM_FRAME_MV_RETURN_ADDRESS
  252. (SCM_VM_FRAME_FP (frame))));
  253. }
  254. #undef FUNC_NAME
  255. SCM_DEFINE (scm_frame_dynamic_link, "frame-dynamic-link", 1, 0, 0,
  256. (SCM frame),
  257. "")
  258. #define FUNC_NAME s_scm_frame_dynamic_link
  259. {
  260. SCM_VALIDATE_VM_FRAME (1, frame);
  261. /* fixme: munge fp if holder is a continuation */
  262. return scm_from_ulong
  263. ((unsigned long)
  264. RELOC (frame,
  265. SCM_FRAME_DYNAMIC_LINK (SCM_VM_FRAME_FP (frame))));
  266. }
  267. #undef FUNC_NAME
  268. SCM_DEFINE (scm_frame_previous, "frame-previous", 1, 0, 0,
  269. (SCM frame),
  270. "")
  271. #define FUNC_NAME s_scm_frame_previous
  272. {
  273. SCM *this_fp, *new_fp, *new_sp;
  274. SCM proc;
  275. SCM_VALIDATE_VM_FRAME (1, frame);
  276. again:
  277. this_fp = SCM_VM_FRAME_FP (frame);
  278. new_fp = SCM_FRAME_DYNAMIC_LINK (this_fp);
  279. if (new_fp)
  280. {
  281. new_fp = RELOC (frame, new_fp);
  282. new_sp = SCM_FRAME_LOWER_ADDRESS (this_fp) - 1;
  283. frame = scm_c_make_frame (SCM_VM_FRAME_STACK_HOLDER (frame),
  284. new_fp, new_sp,
  285. SCM_FRAME_RETURN_ADDRESS (this_fp),
  286. SCM_VM_FRAME_OFFSET (frame));
  287. proc = scm_frame_procedure (frame);
  288. if (SCM_PROGRAM_P (proc) && SCM_PROGRAM_IS_BOOT (proc))
  289. goto again;
  290. else
  291. return frame;
  292. }
  293. else
  294. return SCM_BOOL_F;
  295. }
  296. #undef FUNC_NAME
  297. void
  298. scm_init_frames (void)
  299. {
  300. #ifndef SCM_MAGIC_SNARFER
  301. #include "libguile/frames.x"
  302. #endif
  303. }
  304. /*
  305. Local Variables:
  306. c-file-style: "gnu"
  307. End:
  308. */