ffi.c 18 KB

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