ffi.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  1. /* Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees.
  2. See file COPYING. */
  3. /* Modelled on Jim Blandy's foreign function interface that he put in
  4. his Scheme implementation called Minor. */
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include "scheme48.h"
  9. #include "scheme48vm.h"
  10. #include "scheme48heap.h"
  11. #include "ffi.h"
  12. /* structs */
  13. struct ref_group;
  14. struct s48_ref_s
  15. {
  16. s48_value obj;
  17. struct ref_group *group;
  18. };
  19. struct ref;
  20. struct ref
  21. {
  22. struct s48_ref_s x;
  23. struct ref *next, *prev;
  24. };
  25. #define NUM_REFS_PER_CLUMP 85
  26. struct ref_clump;
  27. struct ref_clump
  28. {
  29. struct ref_clump *next;
  30. struct ref refs[NUM_REFS_PER_CLUMP];
  31. };
  32. struct ref_group
  33. {
  34. struct ref_clump *clumps;
  35. struct ref *free;
  36. struct ref *last_free;
  37. short first_never_used;
  38. struct ref allocated;
  39. };
  40. struct buf_group;
  41. struct buf_group
  42. {
  43. void *buffer;
  44. struct buf_group *next, *prev;
  45. };
  46. enum BV_MODE { READWRITE, READONLY };
  47. struct bv_group;
  48. struct bv_group
  49. {
  50. char *buffer;
  51. s48_ref_t byte_vector;
  52. enum BV_MODE mode;
  53. struct bv_group *next, *prev;
  54. };
  55. struct s48_call_s
  56. {
  57. s48_call_t older_call;
  58. s48_call_t subcall_parent;
  59. s48_call_t child;
  60. s48_call_t next_subcall, prev_subcall;
  61. struct ref_group *local_refs;
  62. struct buf_group *local_bufs;
  63. struct bv_group *local_bvs;
  64. };
  65. /* global states */
  66. static s48_call_t current_call = NULL;
  67. static struct ref_group *global_ref_group = NULL;
  68. #define GLOBAL_REF_P(ref) (ref->group == global_ref_group)
  69. /* REFS */
  70. static struct ref_group *
  71. make_ref_group (void)
  72. {
  73. struct ref_group *g = (struct ref_group *) malloc (sizeof (struct ref_group));
  74. if (g == NULL)
  75. s48_out_of_memory_error();
  76. g->clumps = 0;
  77. g->free = 0;
  78. g->allocated.next = &g->allocated;
  79. g->allocated.prev = &g->allocated;
  80. return g;
  81. }
  82. static void
  83. free_ref_group (struct ref_group *g)
  84. {
  85. struct ref_clump *c, *next;
  86. for (c = g->clumps; c; c = next) {
  87. next = c->next;
  88. free (c);
  89. }
  90. free (g);
  91. }
  92. static s48_ref_t
  93. make_ref (struct ref_group *g, s48_value obj)
  94. {
  95. struct ref *r;
  96. if (g->clumps && (g->first_never_used < NUM_REFS_PER_CLUMP))
  97. r = &g->clumps->refs[g->first_never_used++];
  98. else if (g->free) {
  99. r = g->free;
  100. g->free = r->next;
  101. } else {
  102. struct ref_clump *new =
  103. (struct ref_clump *) malloc (sizeof (struct ref_clump));
  104. if (new == NULL)
  105. s48_out_of_memory_error();
  106. new->next = g->clumps;
  107. g->clumps = new;
  108. r = &new->refs[0];
  109. g->first_never_used = 1;
  110. }
  111. r->next = g->allocated.next;
  112. r->prev = &g->allocated;
  113. r->next->prev = r;
  114. r->prev->next = r;
  115. r->x.group = g;
  116. r->x.obj = obj;
  117. return &r->x;
  118. }
  119. static void
  120. free_ref (s48_ref_t x)
  121. {
  122. #ifdef DEBUG_FFI
  123. fprintf (stderr, "free ref with scheme value %x\n", s48_deref(x));
  124. #endif
  125. struct ref *r = (struct ref *) x;
  126. struct ref_group *g = r->x.group;
  127. r->next->prev = r->prev;
  128. r->prev->next = r->next;
  129. r->next = 0;
  130. if (g->free) {
  131. g->last_free->next = r;
  132. g->last_free = r;
  133. } else
  134. g->free = g->last_free = r;
  135. r->x.obj = S48_FALSE;
  136. }
  137. static void
  138. walk_ref_group (struct ref_group *g,
  139. void (*func) (s48_ref_t ref, void *closure),
  140. void *closure)
  141. {
  142. struct ref *r;
  143. struct ref *head = &g->allocated;
  144. for (r = head->next; r != head; r = r->next)
  145. func (&r->x, closure);
  146. }
  147. /* LOCAL REFS */
  148. s48_ref_t
  149. s48_make_local_ref (s48_call_t call, s48_value obj)
  150. {
  151. #ifdef DEBUG_FFI
  152. fprintf (stderr, "make local ref from scheme value %x\n", obj);
  153. #endif
  154. return make_ref (call->local_refs, obj);
  155. }
  156. s48_ref_t
  157. s48_copy_local_ref (s48_call_t call, s48_ref_t ref)
  158. {
  159. s48_ref_t r = s48_make_local_ref (call, s48_deref(ref));
  160. return r;
  161. }
  162. void
  163. s48_free_local_ref (s48_call_t call, s48_ref_t ref)
  164. {
  165. #ifdef DEBUG_FFI
  166. fprintf (stderr, "free local ref with scheme value %x\n", s48_deref(ref));
  167. #endif
  168. if (!GLOBAL_REF_P (ref))
  169. free_ref (ref);
  170. else
  171. s48_assertion_violation ("s48_free_localref", "ref is not local", 0);
  172. }
  173. void
  174. s48_free_local_ref_array (s48_call_t call, s48_ref_t *refs, size_t len)
  175. {
  176. size_t i;
  177. for (i = 0; i < len; i++)
  178. s48_free_local_ref (call, refs[i]);
  179. }
  180. /* GLOBAL REFS */
  181. s48_ref_t
  182. s48_make_global_ref (s48_value obj)
  183. {
  184. #ifdef DEBUG_FFI
  185. fprintf (stderr, "make global ref from scheme value %x\n", obj);
  186. #endif
  187. return make_ref (global_ref_group, obj);
  188. }
  189. void
  190. s48_free_global_ref (s48_ref_t ref)
  191. {
  192. #ifdef DEBUG_FFI
  193. fprintf (stderr, "free global ref from scheme value %x\n", s48_deref(ref));
  194. #endif
  195. if (GLOBAL_REF_P (ref))
  196. free_ref (ref);
  197. else
  198. s48_assertion_violation ("s48_free_global_ref", "ref is not global", 0);
  199. }
  200. s48_ref_t
  201. s48_local_to_global_ref(s48_ref_t ref)
  202. {
  203. s48_value temp = s48_deref(ref);
  204. #ifdef DEBUG_FFI
  205. fprintf (stderr, "local to global ref from scheme value %x\n", s48_deref(ref));
  206. #endif
  207. free_ref (ref);
  208. return s48_make_global_ref(temp);
  209. }
  210. static void
  211. walk_global_refs (void (*func) (s48_ref_t ref, void *closure),
  212. void *closure)
  213. {
  214. walk_ref_group (global_ref_group, func, closure);
  215. }
  216. /* BUFS */
  217. struct buf_group *
  218. make_buf_group (void)
  219. {
  220. struct buf_group *g = (struct buf_group *) malloc (sizeof (struct buf_group));
  221. if (g == NULL)
  222. s48_out_of_memory_error();
  223. #ifdef DEBUG_FFI
  224. fprintf (stderr, "make buf group %x\n", g);
  225. #endif
  226. return g;
  227. }
  228. void
  229. free_buf (struct buf_group *b)
  230. {
  231. #ifdef DEBUG_FFI
  232. fprintf (stderr, "free buf %x\n", b);
  233. #endif
  234. free (b->buffer);
  235. free (b);
  236. }
  237. void
  238. free_buf_group (struct buf_group *g)
  239. {
  240. struct buf_group *b, *next;
  241. #ifdef DEBUG_FFI
  242. fprintf (stderr, "free buf group %x\n", g);
  243. #endif
  244. for (b = g; b; b = next) {
  245. next = b->next;
  246. free_buf (b);
  247. }
  248. }
  249. void *
  250. s48_make_local_buf (s48_call_t call, size_t s)
  251. {
  252. struct buf_group *g = make_buf_group ();
  253. #ifdef DEBUG_FFI
  254. fprintf (stderr, "make buf with size %x\n", s);
  255. #endif
  256. g->buffer = (void *) calloc (1, s);
  257. if (g->buffer == NULL)
  258. s48_out_of_memory_error();
  259. g->prev = NULL;
  260. g->next = call->local_bufs;
  261. if (g->next)
  262. g->next->prev = g;
  263. call->local_bufs = g;
  264. return g->buffer;
  265. }
  266. void
  267. s48_free_local_buf (s48_call_t call, void *buffer)
  268. {
  269. struct buf_group *prev, *b, *next;
  270. if (! call->local_bufs)
  271. return;
  272. #ifdef DEBUG_FFI
  273. fprintf (stderr, "free buf %x\n", buffer);
  274. #endif
  275. if (buffer == call->local_bufs->buffer) {
  276. b = call->local_bufs;
  277. call->local_bufs = call->local_bufs->next;
  278. if (call->local_bufs)
  279. call->local_bufs->prev = NULL;
  280. free_buf (b);
  281. return;
  282. }
  283. prev = call->local_bufs;
  284. b = call->local_bufs->next;
  285. while (b) {
  286. if (buffer == b->buffer) {
  287. next = b->next;
  288. prev = b->prev;
  289. prev->next = next;
  290. if (next)
  291. next->prev = prev;
  292. free_buf (b);
  293. b = NULL;
  294. } else {
  295. b = b->next;
  296. }
  297. }
  298. }
  299. /* BYTE VECTORS */
  300. struct bv_group *
  301. make_bv_group (void)
  302. {
  303. struct bv_group *g = (struct bv_group *) malloc (sizeof (struct bv_group));
  304. if (g == NULL)
  305. s48_out_of_memory_error();
  306. #ifdef DEBUG_FFI
  307. fprintf (stderr, "make bv group %x\n", g);
  308. #endif
  309. return g;
  310. }
  311. static void
  312. copy_to_bv (s48_call_t call, struct bv_group *bv, void *closure)
  313. {
  314. if (bv->mode != READONLY)
  315. s48_copy_to_byte_vector_2(call, bv->byte_vector, bv->buffer);
  316. }
  317. static void
  318. copy_from_bv (s48_call_t call, struct bv_group *bv, void *closure)
  319. {
  320. s48_copy_from_byte_vector_2(call, bv->byte_vector, bv->buffer);
  321. }
  322. void
  323. free_bv (s48_call_t call, struct bv_group *b)
  324. {
  325. #ifdef DEBUG_FFI
  326. fprintf (stderr, "free bv %x\n", b);
  327. #endif
  328. copy_to_bv (call, b, NULL);
  329. free (b->buffer);
  330. free (b);
  331. }
  332. void
  333. free_bv_group (s48_call_t call, struct bv_group *g)
  334. {
  335. struct bv_group *b, *next;
  336. #ifdef DEBUG_FFI
  337. fprintf (stderr, "free bv group %x\n", g);
  338. #endif
  339. for (b = g; b; b = next) {
  340. next = b->next;
  341. free_bv (call, b);
  342. }
  343. }
  344. struct bv_group *
  345. s48_find_local_bv (s48_call_t call, s48_ref_t byte_vector, long s)
  346. {
  347. struct bv_group *b;
  348. if (! call->local_bvs)
  349. return NULL;
  350. if (s48_eq_p_2 (call, byte_vector, call->local_bvs->byte_vector)) {
  351. return call->local_bvs;
  352. }
  353. b = call->local_bvs->next;
  354. while (b) {
  355. if (s48_eq_p_2 (call, byte_vector, b->byte_vector)) {
  356. return b;
  357. } else {
  358. b = b->next;
  359. }
  360. }
  361. return NULL;
  362. }
  363. char *
  364. s48_really_make_local_bv (s48_call_t call, s48_ref_t byte_vector, long s, enum BV_MODE mode)
  365. {
  366. struct bv_group *g = make_bv_group ();
  367. #ifdef DEBUG_FFI
  368. fprintf (stderr, "make bv with size %x\n", s);
  369. #endif
  370. g->buffer = (char *) calloc (1, s);
  371. if (g->buffer == NULL)
  372. s48_out_of_memory_error();
  373. g->byte_vector = byte_vector;
  374. g->mode = mode;
  375. g->prev = NULL;
  376. g->next = call->local_bvs;
  377. if (g->next)
  378. g->next->prev = g;
  379. call->local_bvs = g;
  380. return g->buffer;
  381. }
  382. psbool s48_unmovable_p (s48_call_t, s48_ref_t);
  383. char *
  384. s48_maybe_make_local_bv (s48_call_t call, s48_ref_t byte_vector, long s, enum BV_MODE mode)
  385. {
  386. char *buf;
  387. struct bv_group *b;
  388. if (s48_unmovable_p(call, byte_vector))
  389. {
  390. return s48_extract_unmovable_byte_vector_2(call, byte_vector);
  391. }
  392. b = s48_find_local_bv (call, byte_vector, s);
  393. if (b)
  394. {
  395. b->mode = mode;
  396. return b->buffer;
  397. }
  398. else
  399. {
  400. buf = s48_really_make_local_bv (call, byte_vector, s, mode);
  401. s48_extract_byte_vector_region_2(call, byte_vector, 0, s, buf);
  402. return buf;
  403. }
  404. }
  405. char *
  406. s48_make_local_bv (s48_call_t call, s48_ref_t byte_vector, long s)
  407. {
  408. return s48_maybe_make_local_bv(call, byte_vector, s, READWRITE);
  409. }
  410. char *
  411. s48_make_local_bv_readonly (s48_call_t call, s48_ref_t byte_vector, long s)
  412. {
  413. return s48_maybe_make_local_bv(call, byte_vector, s, READONLY);
  414. }
  415. void
  416. s48_free_local_bv (s48_call_t call, char *buffer)
  417. {
  418. struct bv_group *prev, *b, *next;
  419. if (! call->local_bvs)
  420. return;
  421. #ifdef DEBUG_FFI
  422. fprintf (stderr, "free bv %x\n", buffer);
  423. #endif
  424. if (buffer == call->local_bvs->buffer) {
  425. b = call->local_bvs;
  426. call->local_bvs = call->local_bvs->next;
  427. if (call->local_bvs)
  428. call->local_bvs->prev = NULL;
  429. free_bv (call, b);
  430. return;
  431. }
  432. prev = call->local_bvs;
  433. b = call->local_bvs->next;
  434. while (b) {
  435. if (buffer == b->buffer) {
  436. next = b->next;
  437. prev = b->prev;
  438. prev->next = next;
  439. if (next)
  440. next->prev = prev;
  441. free_bv (call, b);
  442. b = NULL;
  443. } else {
  444. b = b->next;
  445. }
  446. }
  447. }
  448. static void
  449. walk_local_bvs (s48_call_t call,
  450. void (*func) (s48_call_t call, struct bv_group *bv, void *closure),
  451. void *closure)
  452. {
  453. struct bv_group *b;
  454. for (b = call->local_bvs; b; b = b->next)
  455. func (call, b, closure);
  456. }
  457. void
  458. s48_copy_local_bvs_to_scheme (s48_call_t call)
  459. {
  460. walk_local_bvs (call, copy_to_bv, NULL);
  461. }
  462. void
  463. s48_copy_local_bvs_from_scheme (s48_call_t call)
  464. {
  465. walk_local_bvs (call, copy_from_bv, NULL);
  466. }
  467. /* CALLS */
  468. static s48_call_t
  469. really_make_call (s48_call_t older_call)
  470. {
  471. s48_call_t new = (s48_call_t ) malloc (sizeof (struct s48_call_s));
  472. if (new == NULL)
  473. s48_out_of_memory_error();
  474. memset (new, 0, sizeof (*new));
  475. new->local_refs = make_ref_group ();
  476. new->older_call = older_call;
  477. new->subcall_parent = NULL;
  478. new->child = NULL;
  479. new->local_bufs = NULL;
  480. new->local_bvs = NULL;
  481. return new;
  482. }
  483. s48_call_t
  484. s48_push_call (s48_call_t call)
  485. {
  486. #ifdef DEBUG_FFI
  487. fprintf (stderr, "push\n");
  488. #endif
  489. current_call = really_make_call (call);
  490. return current_call;
  491. }
  492. static void
  493. free_call (s48_call_t call)
  494. {
  495. if (call->child) {
  496. s48_call_t c = call->child;
  497. do {
  498. s48_call_t temp = c;
  499. c = c->next_subcall;
  500. free_call (temp);
  501. } while (c != c->child);
  502. }
  503. free_bv_group (call, call->local_bvs);
  504. free_ref_group (call->local_refs);
  505. free_buf_group (call->local_bufs);
  506. #ifdef DEBUG_FFI
  507. fprintf (stderr, "free_call\n");
  508. fprintf(stderr, " count calls: %d, localrefs: %d, globalrefs: %d\n",
  509. count_calls(), count_local_refs (), count_global_refs());
  510. #endif
  511. free (call);
  512. }
  513. void
  514. s48_pop_to (s48_call_t call)
  515. {
  516. while (current_call != call) {
  517. s48_call_t here = current_call;
  518. if (!here)
  519. s48_assertion_violation ("s48_pop_to", "current_call is null", 0);
  520. current_call = here->older_call;
  521. free_call (here);
  522. #ifdef DEBUG_FFI
  523. fprintf (stderr, "pop\n");
  524. #endif
  525. }
  526. }
  527. /* SUBCALLS */
  528. s48_call_t
  529. s48_make_subcall (s48_call_t call)
  530. {
  531. s48_call_t new = (s48_call_t ) malloc (sizeof (struct s48_call_s));
  532. if (new == NULL)
  533. s48_out_of_memory_error();
  534. memset (new, 0, sizeof (*new));
  535. new->local_refs = make_ref_group ();
  536. new->older_call = NULL;
  537. new->subcall_parent = call;
  538. new->child = NULL;
  539. if (call->child) {
  540. new->next_subcall = call->child->next_subcall;
  541. new->prev_subcall = call->child;
  542. new->next_subcall->prev_subcall = new;
  543. new->prev_subcall->next_subcall = new;
  544. } else {
  545. new->next_subcall = new->prev_subcall = new;
  546. call->child = new;
  547. }
  548. return new;
  549. }
  550. void
  551. s48_free_subcall (s48_call_t subcall)
  552. {
  553. s48_call_t parent = subcall->subcall_parent;
  554. if (subcall->next_subcall == subcall) {
  555. parent->child = NULL;
  556. } else {
  557. parent->child = subcall->next_subcall;
  558. subcall->prev_subcall->next_subcall = subcall->next_subcall;
  559. subcall->next_subcall->prev_subcall = subcall->prev_subcall;
  560. }
  561. free_call (subcall);
  562. }
  563. s48_ref_t
  564. s48_finish_subcall (s48_call_t call, s48_call_t subcall, s48_ref_t ref)
  565. {
  566. s48_ref_t result = ref ? s48_copy_local_ref (call, ref) : NULL;
  567. s48_free_subcall (subcall);
  568. return result;
  569. }
  570. static void
  571. walk_call (s48_call_t call,
  572. void (*func) (s48_ref_t, void *closure),
  573. void *closure)
  574. {
  575. s48_call_t c = NULL;
  576. walk_ref_group (call->local_refs, func, closure);
  577. c = call->child;
  578. if (c)
  579. do
  580. walk_call (c, func, closure);
  581. while ((c = c->next_subcall) != call->child);
  582. }
  583. static void
  584. walk_local_refs (void (*func) (s48_ref_t, void *closure), void *closure)
  585. {
  586. s48_call_t c;
  587. for (c = current_call; c; c = c->older_call)
  588. walk_call (c, func, closure);
  589. }
  590. #ifdef DEBUG_FFI /* for debugging */
  591. static void
  592. count_a_ref (s48_ref_t ref, void *closure)
  593. {
  594. size_t *count_p = closure;
  595. (*count_p)++;
  596. }
  597. static size_t
  598. count_global_refs ()
  599. {
  600. size_t count = 0;
  601. walk_global_refs (count_a_ref, &count);
  602. return count;
  603. }
  604. static size_t
  605. count_local_refs ()
  606. {
  607. size_t count = 0;
  608. walk_local_refs (count_a_ref, &count);
  609. return count;
  610. }
  611. static size_t
  612. count_calls ()
  613. {
  614. size_t count;
  615. s48_call_t c;
  616. for (c = current_call, count = 0; c; c = c->older_call, count++);
  617. return count;
  618. }
  619. #endif
  620. void
  621. s48_setref (s48_ref_t ref, s48_value obj)
  622. {
  623. ref->obj = obj;
  624. }
  625. s48_value
  626. s48_deref (s48_ref_t ref)
  627. {
  628. return ref->obj;
  629. }
  630. s48_call_t
  631. s48_first_call (void)
  632. {
  633. return really_make_call (NULL);
  634. }
  635. s48_call_t
  636. s48_get_current_call (void)
  637. {
  638. return current_call;
  639. }
  640. void
  641. s48_initialize_ffi (void)
  642. {
  643. if (current_call)
  644. s48_assertion_violation ("s48_init_ffi", "current_call is already set", 0);
  645. current_call = s48_first_call ();
  646. if (global_ref_group)
  647. s48_assertion_violation ("s48_init_ffi", "global_ref_group is already set", 0);
  648. global_ref_group = make_ref_group ();
  649. }
  650. static void
  651. trace_a_ref (s48_ref_t ref, void *closure)
  652. {
  653. (*(size_t *) closure)++;
  654. s48_setref(ref, s48_trace_value (s48_deref(ref)));
  655. }
  656. void
  657. s48_trace_external_calls (void)
  658. {
  659. size_t cnt_locals = 0;
  660. size_t cnt_globals = 0;
  661. walk_local_refs (trace_a_ref, &cnt_locals);
  662. walk_global_refs (trace_a_ref, &cnt_globals);
  663. #ifdef DEBUG_FFI
  664. fprintf(stderr, "### TRACED locals %d globals %d ###\n", cnt_locals, cnt_globals);
  665. #endif
  666. }
  667. #ifdef DEBUG_FFI
  668. /* TESTS */
  669. static s48_ref_t
  670. test_0 (s48_call_t call)
  671. {
  672. fprintf(stderr, "test_0\n");
  673. fprintf(stderr, " count calls: %d, localrefs: %d, globalrefs: %d\n",
  674. count_calls(), count_local_refs (), count_global_refs());
  675. return s48_make_local_ref (call, _s48_value_true);
  676. }
  677. static s48_ref_t
  678. test_1 (s48_call_t call, s48_ref_t ref_1)
  679. {
  680. s48_ref_t result;
  681. fprintf(stderr, ">>> %d <<<\n", s48_extract_fixnum (s48_deref(ref_1)));
  682. /*
  683. s48_ref_t proc =
  684. s48_make_local_ref (call,
  685. S48_SHARED_BINDING_REF(s48_get_imported_binding ("display")));
  686. fprintf(stderr, "> test_1\n");
  687. fprintf(stderr, " count calls: %d, localrefs: %d, globalrefs: %d\n",
  688. count_calls(), count_local_refs (), count_global_refs());
  689. result = s48_call_scheme_2 (call, proc, 1, ref_1);
  690. fprintf(stderr, " count calls: %d, localrefs: %d, globalrefs: %d\n",
  691. count_calls(), count_local_refs (), count_global_refs());
  692. fprintf(stderr, "< test_1\n");
  693. */
  694. return result;
  695. }
  696. static s48_ref_t
  697. call_thunk (s48_call_t call, s48_ref_t thunk)
  698. {
  699. s48_ref_t result;
  700. fprintf(stderr, "> call_thunk\n");
  701. fprintf(stderr, " count calls: %d, localrefs: %d, globalrefs: %d\n",
  702. count_calls(), count_local_refs (), count_global_refs());
  703. result = s48_call_scheme_2 (call, thunk, 0);
  704. fprintf(stderr, " count calls: %d, localrefs: %d, globalrefs: %d\n",
  705. count_calls(), count_local_refs (), count_global_refs());
  706. fprintf(stderr, "< call_thunk\n");
  707. return result;
  708. }
  709. static s48_ref_t
  710. call_unary (s48_call_t call, s48_ref_t unary, s48_ref_t arg)
  711. {
  712. s48_ref_t result;
  713. fprintf(stderr, "> call_unary\n");
  714. fprintf(stderr, " count calls: %d, localrefs: %d, globalrefs: %d\n",
  715. count_calls(), count_local_refs (), count_global_refs());
  716. result = s48_call_scheme_2 (call, unary, 1, arg);
  717. fprintf(stderr, " count calls: %d, localrefs: %d, globalrefs: %d\n",
  718. count_calls(), count_local_refs (), count_global_refs());
  719. fprintf(stderr, "< call_unary\n");
  720. return result;
  721. }
  722. void
  723. init_debug_ffi (void)
  724. {
  725. S48_EXPORT_FUNCTION(test_0);
  726. S48_EXPORT_FUNCTION(test_1);
  727. S48_EXPORT_FUNCTION(call_thunk);
  728. S48_EXPORT_FUNCTION(call_unary);
  729. S48_EXPORT_FUNCTION(s48_length_2);
  730. }
  731. /*
  732. ; ,open external-calls primitives
  733. (import-lambda-definition-2 call-thunk (thunk))
  734. (import-lambda-definition-2 call-unary (proc arg))
  735. (call-thunk
  736. (lambda ()
  737. (call-with-current-continuation
  738. (lambda (cont)
  739. (call-thunk
  740. (lambda ()
  741. (call-thunk
  742. (lambda ()
  743. (collect)
  744. (call-unary cont 23)))))))))
  745. */
  746. #endif