inline.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. /* classes: h_files */
  2. #ifndef SCM_INLINE_H
  3. #define SCM_INLINE_H
  4. /* Copyright (C) 2001, 2002, 2003, 2004, 2006, 2008 Free Software Foundation, Inc.
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. /* This file is for inline functions. On platforms that don't support
  21. inlining functions, they are turned into ordinary functions. See
  22. "inline.c".
  23. */
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include "libguile/__scm.h"
  27. #include "libguile/pairs.h"
  28. #include "libguile/gc.h"
  29. #include "libguile/threads.h"
  30. #include "libguile/unif.h"
  31. #include "libguile/ports.h"
  32. #include "libguile/error.h"
  33. #ifndef SCM_INLINE_C_INCLUDING_INLINE_H
  34. /* GCC has `__inline__' in all modes, including strict ansi. GCC 4.3 and
  35. above with `-std=c99' or `-std=gnu99' implements ISO C99 inline semantics,
  36. unless `-fgnu89-inline' is used. Here we want GNU "extern inline"
  37. semantics, hence the `__gnu_inline__' attribute, in accordance with:
  38. http://gcc.gnu.org/gcc-4.3/porting_to.html .
  39. With GCC 4.2, `__GNUC_STDC_INLINE__' is never defined (because C99 inline
  40. semantics are not supported), but a warning is issued in C99 mode if
  41. `__gnu_inline__' is not used.
  42. Apple's GCC build >5400 (since Xcode 3.0) doesn't support GNU inline in
  43. C99 mode and doesn't define `__GNUC_STDC_INLINE__'. Fall back to "static
  44. inline" in that case. */
  45. # if (defined __GNUC__) && (!(((defined __APPLE_CC__) && (__APPLE_CC__ > 5400)) && __STDC_VERSION__ >= 199901L))
  46. # define SCM_C_USE_EXTERN_INLINE 1
  47. # if (defined __GNUC_STDC_INLINE__) || (__GNUC__ == 4 && __GNUC_MINOR__ == 2)
  48. # define SCM_C_EXTERN_INLINE \
  49. extern __inline__ __attribute__ ((__gnu_inline__))
  50. # else
  51. # define SCM_C_EXTERN_INLINE extern __inline__
  52. # endif
  53. # elif (defined SCM_C_INLINE)
  54. # define SCM_C_EXTERN_INLINE static SCM_C_INLINE
  55. # endif
  56. #endif /* SCM_INLINE_C_INCLUDING_INLINE_H */
  57. #if (!defined SCM_C_INLINE) || (defined SCM_INLINE_C_INCLUDING_INLINE_H) \
  58. || (defined SCM_C_USE_EXTERN_INLINE)
  59. /* The `extern' declarations. They should only appear when used from
  60. "inline.c", when `inline' is not supported at all or when "extern inline"
  61. is used. */
  62. SCM_API SCM scm_cell (scm_t_bits car, scm_t_bits cdr);
  63. SCM_API SCM scm_double_cell (scm_t_bits car, scm_t_bits cbr,
  64. scm_t_bits ccr, scm_t_bits cdr);
  65. SCM_API SCM scm_array_handle_ref (scm_t_array_handle *h, ssize_t pos);
  66. SCM_API void scm_array_handle_set (scm_t_array_handle *h, ssize_t pos, SCM val);
  67. SCM_API int scm_is_pair (SCM x);
  68. SCM_API int scm_getc (SCM port);
  69. SCM_API void scm_putc (char c, SCM port);
  70. SCM_API void scm_puts (const char *str_data, SCM port);
  71. #endif
  72. #if defined SCM_C_EXTERN_INLINE || defined SCM_INLINE_C_INCLUDING_INLINE_H
  73. /* either inlining, or being included from inline.c. We use (and
  74. repeat) this long #if test here and below so that we don't have to
  75. introduce any extraneous symbols into the public namespace. We
  76. only need SCM_C_INLINE to be seen publically . */
  77. extern unsigned scm_newcell2_count;
  78. extern unsigned scm_newcell_count;
  79. #ifndef SCM_INLINE_C_INCLUDING_INLINE_H
  80. SCM_C_EXTERN_INLINE
  81. #endif
  82. SCM
  83. scm_cell (scm_t_bits car, scm_t_bits cdr)
  84. {
  85. SCM z;
  86. #ifdef __MINGW32__
  87. SCM *freelist = SCM_FREELIST_LOC (*scm_i_freelist_ptr);
  88. #else
  89. SCM *freelist = SCM_FREELIST_LOC (scm_i_freelist);
  90. #endif
  91. if (scm_is_null (*freelist))
  92. #ifdef __MINGW32__
  93. z = scm_gc_for_newcell (scm_i_master_freelist_ptr, freelist);
  94. #else
  95. z = scm_gc_for_newcell (&scm_i_master_freelist, freelist);
  96. #endif
  97. else
  98. {
  99. z = *freelist;
  100. *freelist = SCM_FREE_CELL_CDR (*freelist);
  101. }
  102. /*
  103. We update scm_cells_allocated from this function. If we don't
  104. update this explicitly, we will have to walk a freelist somewhere
  105. later on, which seems a lot more expensive.
  106. */
  107. scm_cells_allocated += 1;
  108. #if (SCM_DEBUG_CELL_ACCESSES == 1)
  109. if (scm_debug_cell_accesses_p)
  110. {
  111. if (SCM_GC_MARK_P (z))
  112. {
  113. fprintf(stderr, "scm_cell tried to allocate a marked cell.\n");
  114. abort();
  115. }
  116. else if (SCM_GC_CELL_WORD(z, 0) != scm_tc_free_cell)
  117. {
  118. fprintf(stderr, "cell from freelist is not a free cell.\n");
  119. abort();
  120. }
  121. }
  122. /*
  123. Always set mark. Otherwise cells that are alloced before
  124. scm_debug_cell_accesses_p is toggled seem invalid.
  125. */
  126. SCM_SET_GC_MARK (z);
  127. /*
  128. TODO: figure out if this use of mark bits is valid with
  129. threading. What if another thread is doing GC at this point
  130. ... ?
  131. */
  132. #endif
  133. /* Initialize the type slot last so that the cell is ignored by the
  134. GC until it is completely initialized. This is only relevant
  135. when the GC can actually run during this code, which it can't
  136. since the GC only runs when all other threads are stopped.
  137. */
  138. SCM_GC_SET_CELL_WORD (z, 1, cdr);
  139. SCM_GC_SET_CELL_WORD (z, 0, car);
  140. #if (SCM_DEBUG_CELL_ACCESSES == 1)
  141. if (scm_expensive_debug_cell_accesses_p )
  142. scm_i_expensive_validation_check (z);
  143. #endif
  144. return z;
  145. }
  146. #ifndef SCM_INLINE_C_INCLUDING_INLINE_H
  147. SCM_C_EXTERN_INLINE
  148. #endif
  149. SCM
  150. scm_double_cell (scm_t_bits car, scm_t_bits cbr,
  151. scm_t_bits ccr, scm_t_bits cdr)
  152. {
  153. SCM z;
  154. #ifdef __MINGW32__
  155. SCM *freelist = SCM_FREELIST_LOC (*scm_i_freelist2_ptr);
  156. #else
  157. SCM *freelist = SCM_FREELIST_LOC (scm_i_freelist2);
  158. #endif
  159. if (scm_is_null (*freelist))
  160. #ifdef __MINGW32__
  161. z = scm_gc_for_newcell (scm_i_master_freelist2_ptr, freelist);
  162. #else
  163. z = scm_gc_for_newcell (&scm_i_master_freelist2, freelist);
  164. #endif
  165. else
  166. {
  167. z = *freelist;
  168. *freelist = SCM_FREE_CELL_CDR (*freelist);
  169. }
  170. scm_cells_allocated += 2;
  171. /* Initialize the type slot last so that the cell is ignored by the
  172. GC until it is completely initialized. This is only relevant
  173. when the GC can actually run during this code, which it can't
  174. since the GC only runs when all other threads are stopped.
  175. */
  176. SCM_GC_SET_CELL_WORD (z, 1, cbr);
  177. SCM_GC_SET_CELL_WORD (z, 2, ccr);
  178. SCM_GC_SET_CELL_WORD (z, 3, cdr);
  179. SCM_GC_SET_CELL_WORD (z, 0, car);
  180. #if (SCM_DEBUG_CELL_ACCESSES == 1)
  181. if (scm_debug_cell_accesses_p)
  182. {
  183. if (SCM_GC_MARK_P (z))
  184. {
  185. fprintf(stderr,
  186. "scm_double_cell tried to allocate a marked cell.\n");
  187. abort();
  188. }
  189. }
  190. /* see above. */
  191. SCM_SET_GC_MARK (z);
  192. #endif
  193. /* When this function is inlined, it's possible that the last
  194. SCM_GC_SET_CELL_WORD above will be adjacent to a following
  195. initialization of z. E.g., it occurred in scm_make_real. GCC
  196. from around version 3 (e.g., certainly 3.2) began taking
  197. advantage of strict C aliasing rules which say that it's OK to
  198. interchange the initialization above and the one below when the
  199. pointer types appear to differ sufficiently. We don't want that,
  200. of course. GCC allows this behaviour to be disabled with the
  201. -fno-strict-aliasing option, but would also need to be supplied
  202. by Guile users. Instead, the following statements prevent the
  203. reordering.
  204. */
  205. #ifdef __GNUC__
  206. __asm__ volatile ("" : : : "memory");
  207. #else
  208. /* portable version, just in case any other compiler does the same
  209. thing. */
  210. scm_remember_upto_here_1 (z);
  211. #endif
  212. return z;
  213. }
  214. #ifndef SCM_INLINE_C_INCLUDING_INLINE_H
  215. SCM_C_EXTERN_INLINE
  216. #endif
  217. SCM
  218. scm_array_handle_ref (scm_t_array_handle *h, ssize_t p)
  219. {
  220. return h->ref (h, p);
  221. }
  222. #ifndef SCM_INLINE_C_INCLUDING_INLINE_H
  223. SCM_C_EXTERN_INLINE
  224. #endif
  225. void
  226. scm_array_handle_set (scm_t_array_handle *h, ssize_t p, SCM v)
  227. {
  228. h->set (h, p, v);
  229. }
  230. #ifndef SCM_INLINE_C_INCLUDING_INLINE_H
  231. SCM_C_EXTERN_INLINE
  232. #endif
  233. int
  234. scm_is_pair (SCM x)
  235. {
  236. /* The following "workaround_for_gcc_295" avoids bad code generated by
  237. i386 gcc 2.95.4 (the Debian packaged 2.95.4-24 at least).
  238. Under the default -O2 the inlined SCM_I_CONSP test gets "optimized" so
  239. the fetch of the tag word from x is done before confirming it's a
  240. non-immediate (SCM_NIMP). Needless to say that bombs badly if x is a
  241. immediate. This was seen to afflict scm_srfi1_split_at and something
  242. deep in the bowels of ceval(). In both cases segvs resulted from
  243. deferencing a random immediate value. srfi-1.test exposes the problem
  244. through a short list, the immediate being SCM_EOL in that case.
  245. Something in syntax.test exposed the ceval() problem.
  246. Just "volatile SCM workaround_for_gcc_295 = lst" is enough to avoid the
  247. problem, without even using that variable. The "w=w" is just to
  248. prevent a warning about it being unused.
  249. */
  250. #if defined (__GNUC__) && __GNUC__ == 2 && __GNUC_MINOR__ == 95
  251. volatile SCM workaround_for_gcc_295 = x;
  252. workaround_for_gcc_295 = workaround_for_gcc_295;
  253. #endif
  254. return SCM_I_CONSP (x);
  255. }
  256. /* Port I/O. */
  257. #ifndef SCM_INLINE_C_INCLUDING_INLINE_H
  258. SCM_C_EXTERN_INLINE
  259. #endif
  260. int
  261. scm_getc (SCM port)
  262. {
  263. int c;
  264. scm_t_port *pt = SCM_PTAB_ENTRY (port);
  265. if (pt->rw_active == SCM_PORT_WRITE)
  266. /* may be marginally faster than calling scm_flush. */
  267. scm_ptobs[SCM_PTOBNUM (port)].flush (port);
  268. if (pt->rw_random)
  269. pt->rw_active = SCM_PORT_READ;
  270. if (pt->read_pos >= pt->read_end)
  271. {
  272. if (scm_fill_input (port) == EOF)
  273. return EOF;
  274. }
  275. c = *(pt->read_pos++);
  276. switch (c)
  277. {
  278. case '\a':
  279. break;
  280. case '\b':
  281. SCM_DECCOL (port);
  282. break;
  283. case '\n':
  284. SCM_INCLINE (port);
  285. break;
  286. case '\r':
  287. SCM_ZEROCOL (port);
  288. break;
  289. case '\t':
  290. SCM_TABCOL (port);
  291. break;
  292. default:
  293. SCM_INCCOL (port);
  294. break;
  295. }
  296. return c;
  297. }
  298. #ifndef SCM_INLINE_C_INCLUDING_INLINE_H
  299. SCM_C_EXTERN_INLINE
  300. #endif
  301. void
  302. scm_putc (char c, SCM port)
  303. {
  304. SCM_ASSERT_TYPE (SCM_OPOUTPORTP (port), port, 0, NULL, "output port");
  305. scm_lfwrite (&c, 1, port);
  306. }
  307. #ifndef SCM_INLINE_C_INCLUDING_INLINE_H
  308. SCM_C_EXTERN_INLINE
  309. #endif
  310. void
  311. scm_puts (const char *s, SCM port)
  312. {
  313. SCM_ASSERT_TYPE (SCM_OPOUTPORTP (port), port, 0, NULL, "output port");
  314. scm_lfwrite (s, strlen (s), port);
  315. }
  316. #endif
  317. #endif