gc-mark.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2004, 2005, 2006, 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. #ifdef HAVE_CONFIG_H
  19. # include <config.h>
  20. #endif
  21. #include <stdio.h>
  22. #include <errno.h>
  23. #include <string.h>
  24. #include <assert.h>
  25. #ifdef __ia64__
  26. #include <ucontext.h>
  27. extern unsigned long * __libc_ia64_register_backing_store_base;
  28. #endif
  29. #include "libguile/_scm.h"
  30. #include "libguile/eval.h"
  31. #include "libguile/stime.h"
  32. #include "libguile/stackchk.h"
  33. #include "libguile/struct.h"
  34. #include "libguile/smob.h"
  35. #include "libguile/unif.h"
  36. #include "libguile/async.h"
  37. #include "libguile/ports.h"
  38. #include "libguile/root.h"
  39. #include "libguile/strings.h"
  40. #include "libguile/vectors.h"
  41. #include "libguile/weaks.h"
  42. #include "libguile/hashtab.h"
  43. #include "libguile/tags.h"
  44. #include "libguile/private-gc.h"
  45. #include "libguile/validate.h"
  46. #include "libguile/deprecation.h"
  47. #include "libguile/gc.h"
  48. #include "libguile/guardians.h"
  49. #ifdef GUILE_DEBUG_MALLOC
  50. #include "libguile/debug-malloc.h"
  51. #endif
  52. #ifdef HAVE_MALLOC_H
  53. #include <malloc.h>
  54. #endif
  55. #ifdef HAVE_UNISTD_H
  56. #include <unistd.h>
  57. #endif
  58. int scm_i_marking = 0;
  59. /*
  60. Entry point for this file.
  61. */
  62. void
  63. scm_mark_all (void)
  64. {
  65. long j;
  66. int loops;
  67. scm_i_marking = 1;
  68. scm_i_init_weak_vectors_for_gc ();
  69. scm_i_init_guardians_for_gc ();
  70. scm_i_clear_mark_space ();
  71. scm_i_find_heap_calls = 0;
  72. /* Mark every thread's stack and registers */
  73. scm_threads_mark_stacks ();
  74. j = SCM_NUM_PROTECTS;
  75. while (j--)
  76. scm_gc_mark (scm_sys_protects[j]);
  77. /* mark the registered roots */
  78. {
  79. size_t i;
  80. for (i = 0; i < SCM_HASHTABLE_N_BUCKETS (scm_gc_registered_roots); ++i)
  81. {
  82. SCM l = SCM_HASHTABLE_BUCKET (scm_gc_registered_roots, i);
  83. for (; !scm_is_null (l); l = SCM_CDR (l))
  84. {
  85. SCM *p = (SCM *) (scm_to_ulong (SCM_CAAR (l)));
  86. scm_gc_mark (*p);
  87. }
  88. }
  89. }
  90. loops = 0;
  91. while (1)
  92. {
  93. int again;
  94. loops++;
  95. /* Mark the non-weak references of weak vectors. For a weak key
  96. alist vector, this would mark the values for keys that are
  97. marked. We need to do this in a loop until everything
  98. settles down since the newly marked values might be keys in
  99. other weak key alist vectors, for example.
  100. */
  101. again = scm_i_mark_weak_vectors_non_weaks ();
  102. if (again)
  103. continue;
  104. /* Now we scan all marked guardians and move all unmarked objects
  105. from the accessible to the inaccessible list.
  106. */
  107. scm_i_identify_inaccessible_guardeds ();
  108. /* When we have identified all inaccessible objects, we can mark
  109. them.
  110. */
  111. again = scm_i_mark_inaccessible_guardeds ();
  112. /* This marking might have changed the situation for weak vectors
  113. and might have turned up new guardians that need to be processed,
  114. so we do it all over again.
  115. */
  116. if (again)
  117. continue;
  118. /* Nothing new marked in this round, we are done.
  119. */
  120. break;
  121. }
  122. /* Remove all unmarked entries from the weak vectors.
  123. */
  124. scm_i_remove_weaks_from_weak_vectors ();
  125. /* Bring hashtables upto date.
  126. */
  127. scm_i_scan_weak_hashtables ();
  128. scm_i_marking = 0;
  129. }
  130. /* {Mark/Sweep}
  131. */
  132. /*
  133. Mark an object precisely, then recurse.
  134. */
  135. void
  136. scm_gc_mark (SCM ptr)
  137. {
  138. if (SCM_IMP (ptr))
  139. return;
  140. if (SCM_GC_MARK_P (ptr))
  141. return;
  142. if (!scm_i_marking)
  143. {
  144. static const char msg[]
  145. = "Should only call scm_gc_mark() during GC.";
  146. scm_c_issue_deprecation_warning (msg);
  147. }
  148. SCM_SET_GC_MARK (ptr);
  149. scm_gc_mark_dependencies (ptr);
  150. }
  151. void
  152. scm_i_ensure_marking (void)
  153. {
  154. assert (scm_i_marking);
  155. }
  156. /*
  157. Mark the dependencies of an object.
  158. Prefetching:
  159. Should prefetch objects before marking, i.e. if marking a cell, we
  160. should prefetch the car, and then mark the cdr. This will improve CPU
  161. cache misses, because the car is more likely to be in cache when we
  162. finish the cdr.
  163. See http://www.hpl.hp.com/techreports/2000/HPL-2000-99.pdf, reducing
  164. garbage collector cache misses.
  165. Prefetch is supported on GCC >= 3.1
  166. (Some time later.)
  167. Tried this with GCC 3.1.1 -- the time differences are barely measurable.
  168. Perhaps this would work better with an explicit markstack?
  169. */
  170. void
  171. scm_gc_mark_dependencies (SCM p)
  172. #define FUNC_NAME "scm_gc_mark_dependencies"
  173. {
  174. register long i;
  175. register SCM ptr;
  176. SCM cell_type;
  177. ptr = p;
  178. scm_mark_dependencies_again:
  179. cell_type = SCM_GC_CELL_TYPE (ptr);
  180. switch (SCM_ITAG7 (cell_type))
  181. {
  182. case scm_tcs_cons_nimcar:
  183. if (SCM_IMP (SCM_CDR (ptr)))
  184. {
  185. ptr = SCM_CAR (ptr);
  186. goto gc_mark_nimp;
  187. }
  188. scm_gc_mark (SCM_CAR (ptr));
  189. ptr = SCM_CDR (ptr);
  190. goto gc_mark_nimp;
  191. case scm_tcs_cons_imcar:
  192. ptr = SCM_CDR (ptr);
  193. goto gc_mark_loop;
  194. case scm_tc7_pws:
  195. scm_gc_mark (SCM_SETTER (ptr));
  196. ptr = SCM_PROCEDURE (ptr);
  197. goto gc_mark_loop;
  198. case scm_tcs_struct:
  199. {
  200. /* XXX - use less explicit code. */
  201. scm_t_bits word0 = SCM_CELL_WORD_0 (ptr) - scm_tc3_struct;
  202. scm_t_bits * vtable_data = (scm_t_bits *) word0;
  203. SCM layout = SCM_PACK (vtable_data [scm_vtable_index_layout]);
  204. long len = scm_i_symbol_length (layout);
  205. const char *fields_desc = scm_i_symbol_chars (layout);
  206. scm_t_bits *struct_data = (scm_t_bits *) SCM_STRUCT_DATA (ptr);
  207. if (vtable_data[scm_struct_i_flags] & SCM_STRUCTF_ENTITY)
  208. {
  209. scm_gc_mark (SCM_PACK (struct_data[scm_struct_i_procedure]));
  210. scm_gc_mark (SCM_PACK (struct_data[scm_struct_i_setter]));
  211. }
  212. if (len)
  213. {
  214. long x;
  215. for (x = 0; x < len - 2; x += 2, ++struct_data)
  216. if (fields_desc[x] == 'p')
  217. scm_gc_mark (SCM_PACK (*struct_data));
  218. if (fields_desc[x] == 'p')
  219. {
  220. if (SCM_LAYOUT_TAILP (fields_desc[x + 1]))
  221. for (x = *struct_data++; x; --x, ++struct_data)
  222. scm_gc_mark (SCM_PACK (*struct_data));
  223. else
  224. scm_gc_mark (SCM_PACK (*struct_data));
  225. }
  226. }
  227. /* mark vtable */
  228. ptr = SCM_PACK (vtable_data [scm_vtable_index_vtable]);
  229. goto gc_mark_loop;
  230. }
  231. break;
  232. case scm_tcs_closures:
  233. if (SCM_IMP (SCM_ENV (ptr)))
  234. {
  235. ptr = SCM_CLOSCAR (ptr);
  236. goto gc_mark_nimp;
  237. }
  238. scm_gc_mark (SCM_CLOSCAR (ptr));
  239. ptr = SCM_ENV (ptr);
  240. goto gc_mark_nimp;
  241. case scm_tc7_vector:
  242. i = SCM_SIMPLE_VECTOR_LENGTH (ptr);
  243. if (i == 0)
  244. break;
  245. while (--i > 0)
  246. {
  247. SCM elt = SCM_SIMPLE_VECTOR_REF (ptr, i);
  248. if (SCM_NIMP (elt))
  249. scm_gc_mark (elt);
  250. }
  251. ptr = SCM_SIMPLE_VECTOR_REF (ptr, 0);
  252. goto gc_mark_loop;
  253. case scm_tc7_string:
  254. ptr = scm_i_string_mark (ptr);
  255. goto gc_mark_loop;
  256. case scm_tc7_stringbuf:
  257. ptr = scm_i_stringbuf_mark (ptr);
  258. goto gc_mark_loop;
  259. case scm_tc7_number:
  260. if (SCM_TYP16 (ptr) == scm_tc16_fraction)
  261. {
  262. scm_gc_mark (SCM_CELL_OBJECT_1 (ptr));
  263. ptr = SCM_CELL_OBJECT_2 (ptr);
  264. goto gc_mark_loop;
  265. }
  266. break;
  267. case scm_tc7_wvect:
  268. scm_i_mark_weak_vector (ptr);
  269. break;
  270. case scm_tc7_symbol:
  271. ptr = scm_i_symbol_mark (ptr);
  272. goto gc_mark_loop;
  273. case scm_tc7_variable:
  274. ptr = SCM_CELL_OBJECT_1 (ptr);
  275. goto gc_mark_loop;
  276. case scm_tcs_subrs:
  277. if (SCM_CELL_WORD_2 (ptr) && *(SCM*)SCM_CELL_WORD_2 (ptr))
  278. /* the generic associated with this primitive */
  279. scm_gc_mark (*(SCM*)SCM_CELL_WORD_2 (ptr));
  280. if (SCM_NIMP (((SCM*)SCM_CELL_WORD_3 (ptr))[1]))
  281. scm_gc_mark (((SCM*)SCM_CELL_WORD_3 (ptr))[1]); /* props */
  282. ptr = ((SCM*)SCM_CELL_WORD_3 (ptr))[0]; /* name */
  283. goto gc_mark_loop;
  284. case scm_tc7_port:
  285. i = SCM_PTOBNUM (ptr);
  286. #if (SCM_DEBUG_CELL_ACCESSES == 1)
  287. if (!(i < scm_numptob))
  288. {
  289. fprintf (stderr, "undefined port type");
  290. abort ();
  291. }
  292. #endif
  293. if (SCM_PTAB_ENTRY (ptr))
  294. scm_gc_mark (SCM_FILENAME (ptr));
  295. if (scm_ptobs[i].mark)
  296. {
  297. ptr = (scm_ptobs[i].mark) (ptr);
  298. goto gc_mark_loop;
  299. }
  300. else
  301. return;
  302. break;
  303. case scm_tc7_smob:
  304. switch (SCM_TYP16 (ptr))
  305. { /* should be faster than going through scm_smobs */
  306. case scm_tc_free_cell:
  307. /* We have detected a free cell. This can happen if non-object data
  308. * on the C stack points into guile's heap and is scanned during
  309. * conservative marking. */
  310. break;
  311. default:
  312. i = SCM_SMOBNUM (ptr);
  313. #if (SCM_DEBUG_CELL_ACCESSES == 1)
  314. if (!(i < scm_numsmob))
  315. {
  316. fprintf (stderr, "undefined smob type");
  317. abort ();
  318. }
  319. #endif
  320. if (scm_smobs[i].mark)
  321. {
  322. ptr = (scm_smobs[i].mark) (ptr);
  323. goto gc_mark_loop;
  324. }
  325. else
  326. return;
  327. }
  328. break;
  329. default:
  330. fprintf (stderr, "unknown type");
  331. abort ();
  332. }
  333. /*
  334. If we got here, then exhausted recursion options for PTR. we
  335. return (careful not to mark PTR, it might be the argument that we
  336. were called with.)
  337. */
  338. return ;
  339. gc_mark_loop:
  340. if (SCM_IMP (ptr))
  341. return;
  342. gc_mark_nimp:
  343. {
  344. int valid_cell = CELL_P (ptr);
  345. #if (SCM_DEBUG_CELL_ACCESSES == 1)
  346. if (scm_debug_cell_accesses_p)
  347. {
  348. /* We are in debug mode. Check the ptr exhaustively. */
  349. valid_cell = valid_cell && scm_in_heap_p (ptr);
  350. }
  351. #endif
  352. if (!valid_cell)
  353. {
  354. fprintf (stderr, "rogue pointer in heap");
  355. abort ();
  356. }
  357. }
  358. if (SCM_GC_MARK_P (ptr))
  359. return;
  360. SCM_SET_GC_MARK (ptr);
  361. goto scm_mark_dependencies_again;
  362. }
  363. #undef FUNC_NAME
  364. /* Mark a region conservatively */
  365. void
  366. scm_mark_locations (SCM_STACKITEM x[], unsigned long n)
  367. {
  368. unsigned long m;
  369. for (m = 0; m < n; ++m)
  370. {
  371. SCM obj = * (SCM *) &x[m];
  372. long int segment = scm_i_find_heap_segment_containing_object (obj);
  373. if (segment >= 0)
  374. scm_gc_mark (obj);
  375. }
  376. }
  377. /* The function scm_in_heap_p determines whether an SCM value can be regarded as a
  378. * pointer to a cell on the heap.
  379. */
  380. int
  381. scm_in_heap_p (SCM value)
  382. {
  383. long int segment = scm_i_find_heap_segment_containing_object (value);
  384. return (segment >= 0);
  385. }
  386. #if SCM_ENABLE_DEPRECATED == 1
  387. /* If an allocated cell is detected during garbage collection, this
  388. * means that some code has just obtained the object but was preempted
  389. * before the initialization of the object was completed. This meanst
  390. * that some entries of the allocated cell may already contain SCM
  391. * objects. Therefore, allocated cells are scanned conservatively.
  392. */
  393. scm_t_bits scm_tc16_allocated;
  394. static SCM
  395. allocated_mark (SCM cell)
  396. {
  397. unsigned long int cell_segment = scm_i_find_heap_segment_containing_object (cell);
  398. unsigned int span = scm_i_heap_segment_table[cell_segment]->span;
  399. unsigned int i;
  400. for (i = 1; i != span * 2; ++i)
  401. {
  402. SCM obj = SCM_CELL_OBJECT (cell, i);
  403. long int obj_segment = scm_i_find_heap_segment_containing_object (obj);
  404. if (obj_segment >= 0)
  405. scm_gc_mark (obj);
  406. }
  407. return SCM_BOOL_F;
  408. }
  409. SCM
  410. scm_deprecated_newcell (void)
  411. {
  412. scm_c_issue_deprecation_warning
  413. ("SCM_NEWCELL is deprecated. Use `scm_cell' instead.\n");
  414. return scm_cell (scm_tc16_allocated, 0);
  415. }
  416. SCM
  417. scm_deprecated_newcell2 (void)
  418. {
  419. scm_c_issue_deprecation_warning
  420. ("SCM_NEWCELL2 is deprecated. Use `scm_double_cell' instead.\n");
  421. return scm_double_cell (scm_tc16_allocated, 0, 0, 0);
  422. }
  423. #endif /* SCM_ENABLE_DEPRECATED == 1 */
  424. void
  425. scm_gc_init_mark (void)
  426. {
  427. #if SCM_ENABLE_DEPRECATED == 1
  428. scm_tc16_allocated = scm_make_smob_type ("allocated cell", 0);
  429. scm_set_smob_mark (scm_tc16_allocated, allocated_mark);
  430. #endif
  431. }