inline.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  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. SCM *freelist = SCM_FREELIST_LOC (scm_i_freelist);
  87. if (scm_is_null (*freelist))
  88. z = scm_gc_for_newcell (&scm_i_master_freelist, freelist);
  89. else
  90. {
  91. z = *freelist;
  92. *freelist = SCM_FREE_CELL_CDR (*freelist);
  93. }
  94. /*
  95. We update scm_cells_allocated from this function. If we don't
  96. update this explicitly, we will have to walk a freelist somewhere
  97. later on, which seems a lot more expensive.
  98. */
  99. scm_cells_allocated += 1;
  100. #if (SCM_DEBUG_CELL_ACCESSES == 1)
  101. if (scm_debug_cell_accesses_p)
  102. {
  103. if (SCM_GC_MARK_P (z))
  104. {
  105. fprintf(stderr, "scm_cell tried to allocate a marked cell.\n");
  106. abort();
  107. }
  108. else if (SCM_GC_CELL_WORD(z, 0) != scm_tc_free_cell)
  109. {
  110. fprintf(stderr, "cell from freelist is not a free cell.\n");
  111. abort();
  112. }
  113. }
  114. /*
  115. Always set mark. Otherwise cells that are alloced before
  116. scm_debug_cell_accesses_p is toggled seem invalid.
  117. */
  118. SCM_SET_GC_MARK (z);
  119. /*
  120. TODO: figure out if this use of mark bits is valid with
  121. threading. What if another thread is doing GC at this point
  122. ... ?
  123. */
  124. #endif
  125. /* Initialize the type slot last so that the cell is ignored by the
  126. GC until it is completely initialized. This is only relevant
  127. when the GC can actually run during this code, which it can't
  128. since the GC only runs when all other threads are stopped.
  129. */
  130. SCM_GC_SET_CELL_WORD (z, 1, cdr);
  131. SCM_GC_SET_CELL_WORD (z, 0, car);
  132. #if (SCM_DEBUG_CELL_ACCESSES == 1)
  133. if (scm_expensive_debug_cell_accesses_p )
  134. scm_i_expensive_validation_check (z);
  135. #endif
  136. return z;
  137. }
  138. #ifndef SCM_INLINE_C_INCLUDING_INLINE_H
  139. SCM_C_EXTERN_INLINE
  140. #endif
  141. SCM
  142. scm_double_cell (scm_t_bits car, scm_t_bits cbr,
  143. scm_t_bits ccr, scm_t_bits cdr)
  144. {
  145. SCM z;
  146. SCM *freelist = SCM_FREELIST_LOC (scm_i_freelist2);
  147. if (scm_is_null (*freelist))
  148. z = scm_gc_for_newcell (&scm_i_master_freelist2, freelist);
  149. else
  150. {
  151. z = *freelist;
  152. *freelist = SCM_FREE_CELL_CDR (*freelist);
  153. }
  154. scm_cells_allocated += 2;
  155. /* Initialize the type slot last so that the cell is ignored by the
  156. GC until it is completely initialized. This is only relevant
  157. when the GC can actually run during this code, which it can't
  158. since the GC only runs when all other threads are stopped.
  159. */
  160. SCM_GC_SET_CELL_WORD (z, 1, cbr);
  161. SCM_GC_SET_CELL_WORD (z, 2, ccr);
  162. SCM_GC_SET_CELL_WORD (z, 3, cdr);
  163. SCM_GC_SET_CELL_WORD (z, 0, car);
  164. #if (SCM_DEBUG_CELL_ACCESSES == 1)
  165. if (scm_debug_cell_accesses_p)
  166. {
  167. if (SCM_GC_MARK_P (z))
  168. {
  169. fprintf(stderr,
  170. "scm_double_cell tried to allocate a marked cell.\n");
  171. abort();
  172. }
  173. }
  174. /* see above. */
  175. SCM_SET_GC_MARK (z);
  176. #endif
  177. /* When this function is inlined, it's possible that the last
  178. SCM_GC_SET_CELL_WORD above will be adjacent to a following
  179. initialization of z. E.g., it occurred in scm_make_real. GCC
  180. from around version 3 (e.g., certainly 3.2) began taking
  181. advantage of strict C aliasing rules which say that it's OK to
  182. interchange the initialization above and the one below when the
  183. pointer types appear to differ sufficiently. We don't want that,
  184. of course. GCC allows this behaviour to be disabled with the
  185. -fno-strict-aliasing option, but would also need to be supplied
  186. by Guile users. Instead, the following statements prevent the
  187. reordering.
  188. */
  189. #ifdef __GNUC__
  190. __asm__ volatile ("" : : : "memory");
  191. #else
  192. /* portable version, just in case any other compiler does the same
  193. thing. */
  194. scm_remember_upto_here_1 (z);
  195. #endif
  196. return z;
  197. }
  198. #ifndef SCM_INLINE_C_INCLUDING_INLINE_H
  199. SCM_C_EXTERN_INLINE
  200. #endif
  201. SCM
  202. scm_array_handle_ref (scm_t_array_handle *h, ssize_t p)
  203. {
  204. return h->ref (h, p);
  205. }
  206. #ifndef SCM_INLINE_C_INCLUDING_INLINE_H
  207. SCM_C_EXTERN_INLINE
  208. #endif
  209. void
  210. scm_array_handle_set (scm_t_array_handle *h, ssize_t p, SCM v)
  211. {
  212. h->set (h, p, v);
  213. }
  214. #ifndef SCM_INLINE_C_INCLUDING_INLINE_H
  215. SCM_C_EXTERN_INLINE
  216. #endif
  217. int
  218. scm_is_pair (SCM x)
  219. {
  220. /* The following "workaround_for_gcc_295" avoids bad code generated by
  221. i386 gcc 2.95.4 (the Debian packaged 2.95.4-24 at least).
  222. Under the default -O2 the inlined SCM_I_CONSP test gets "optimized" so
  223. the fetch of the tag word from x is done before confirming it's a
  224. non-immediate (SCM_NIMP). Needless to say that bombs badly if x is a
  225. immediate. This was seen to afflict scm_srfi1_split_at and something
  226. deep in the bowels of ceval(). In both cases segvs resulted from
  227. deferencing a random immediate value. srfi-1.test exposes the problem
  228. through a short list, the immediate being SCM_EOL in that case.
  229. Something in syntax.test exposed the ceval() problem.
  230. Just "volatile SCM workaround_for_gcc_295 = lst" is enough to avoid the
  231. problem, without even using that variable. The "w=w" is just to
  232. prevent a warning about it being unused.
  233. */
  234. #if defined (__GNUC__) && __GNUC__ == 2 && __GNUC_MINOR__ == 95
  235. volatile SCM workaround_for_gcc_295 = x;
  236. workaround_for_gcc_295 = workaround_for_gcc_295;
  237. #endif
  238. return SCM_I_CONSP (x);
  239. }
  240. /* Port I/O. */
  241. #ifndef SCM_INLINE_C_INCLUDING_INLINE_H
  242. SCM_C_EXTERN_INLINE
  243. #endif
  244. int
  245. scm_getc (SCM port)
  246. {
  247. int c;
  248. scm_t_port *pt = SCM_PTAB_ENTRY (port);
  249. if (pt->rw_active == SCM_PORT_WRITE)
  250. /* may be marginally faster than calling scm_flush. */
  251. scm_ptobs[SCM_PTOBNUM (port)].flush (port);
  252. if (pt->rw_random)
  253. pt->rw_active = SCM_PORT_READ;
  254. if (pt->read_pos >= pt->read_end)
  255. {
  256. if (scm_fill_input (port) == EOF)
  257. return EOF;
  258. }
  259. c = *(pt->read_pos++);
  260. switch (c)
  261. {
  262. case '\a':
  263. break;
  264. case '\b':
  265. SCM_DECCOL (port);
  266. break;
  267. case '\n':
  268. SCM_INCLINE (port);
  269. break;
  270. case '\r':
  271. SCM_ZEROCOL (port);
  272. break;
  273. case '\t':
  274. SCM_TABCOL (port);
  275. break;
  276. default:
  277. SCM_INCCOL (port);
  278. break;
  279. }
  280. return c;
  281. }
  282. #ifndef SCM_INLINE_C_INCLUDING_INLINE_H
  283. SCM_C_EXTERN_INLINE
  284. #endif
  285. void
  286. scm_putc (char c, SCM port)
  287. {
  288. SCM_ASSERT_TYPE (SCM_OPOUTPORTP (port), port, 0, NULL, "output port");
  289. scm_lfwrite (&c, 1, port);
  290. }
  291. #ifndef SCM_INLINE_C_INCLUDING_INLINE_H
  292. SCM_C_EXTERN_INLINE
  293. #endif
  294. void
  295. scm_puts (const char *s, SCM port)
  296. {
  297. SCM_ASSERT_TYPE (SCM_OPOUTPORTP (port), port, 0, NULL, "output port");
  298. scm_lfwrite (s, strlen (s), port);
  299. }
  300. #endif
  301. #endif