control.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /* Copyright 2010-2013,2018
  2. Free Software Foundation, Inc.
  3. This file is part of Guile.
  4. Guile is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Lesser General Public License as published
  6. by the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. Guile is distributed in the hope that it will be useful, but WITHOUT
  9. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
  11. License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with Guile. If not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #if HAVE_CONFIG_H
  16. # include <config.h>
  17. #endif
  18. #include <alloca.h>
  19. #include "dynstack.h"
  20. #include "extensions.h"
  21. #include "frames.h"
  22. #include "gsubr.h"
  23. #include "instructions.h"
  24. #include "jit.h"
  25. #include "list.h"
  26. #include "pairs.h"
  27. #include "programs.h"
  28. #include "threads.h"
  29. #include "version.h"
  30. #include "vm.h"
  31. #include "control.h"
  32. #define PROMPT_ESCAPE_P(p) \
  33. (SCM_DYNSTACK_TAG_FLAGS (SCM_DYNSTACK_TAG (p)) \
  34. & SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY)
  35. /* Only to be called if the setjmp returns 1 */
  36. SCM
  37. scm_i_prompt_pop_abort_args_x (struct scm_vm *vp,
  38. ptrdiff_t saved_stack_depth)
  39. {
  40. size_t i, n;
  41. ptrdiff_t stack_depth;
  42. SCM vals = SCM_EOL;
  43. stack_depth = vp->stack_top - vp->sp;
  44. if (stack_depth < saved_stack_depth)
  45. abort ();
  46. n = stack_depth - saved_stack_depth;
  47. for (i = 0; i < n; i++)
  48. vals = scm_cons (vp->sp[i].as_scm, vals);
  49. vp->sp += n;
  50. return vals;
  51. }
  52. struct compose_continuation_code
  53. {
  54. struct scm_jit_function_data data;
  55. uint32_t code[3];
  56. };
  57. struct compose_continuation_code compose_continuation_code = {
  58. {
  59. /* mcode = */ 0,
  60. /* counter = */ 0,
  61. /* start = */ sizeof (struct scm_jit_function_data),
  62. /* end = */ sizeof (struct scm_jit_function_data) + 12
  63. },
  64. {
  65. SCM_PACK_OP_24 (instrument_entry, 0),
  66. ((uint32_t) -(sizeof (struct scm_jit_function_data) / 4)),
  67. SCM_PACK_OP_24 (compose_continuation, 0),
  68. }
  69. };
  70. SCM
  71. scm_i_make_composable_continuation (SCM vmcont)
  72. {
  73. scm_t_bits nfree = 1;
  74. scm_t_bits flags = SCM_F_PROGRAM_IS_PARTIAL_CONTINUATION;
  75. SCM ret;
  76. ret = scm_words (scm_tc7_program | (nfree << 16) | flags, nfree + 2);
  77. SCM_SET_CELL_WORD_1 (ret, compose_continuation_code.code);
  78. SCM_PROGRAM_FREE_VARIABLE_SET (ret, 0, vmcont);
  79. return ret;
  80. }
  81. SCM_DEFINE (scm_abort_to_prompt_star, "abort-to-prompt*", 2, 0, 0,
  82. (SCM tag, SCM args),
  83. "Abort to the nearest prompt with tag @var{tag}, yielding the\n"
  84. "values in the list, @var{args}.")
  85. #define FUNC_NAME s_scm_abort_to_prompt_star
  86. {
  87. SCM *tag_and_argv;
  88. size_t i;
  89. long n;
  90. SCM_VALIDATE_LIST_COPYLEN (SCM_ARG2, args, n);
  91. n = n + 1; /* Add space for the tag. */
  92. tag_and_argv = alloca (sizeof (SCM)*(n+1));
  93. tag_and_argv[0] = tag;
  94. for (i = 1; i < n; i++, args = scm_cdr (args))
  95. tag_and_argv[i] = scm_car (args);
  96. scm_i_vm_abort (tag_and_argv, n);
  97. /* Oh, what, you're still here? The abort must have been reinstated. Actually,
  98. that's quite impossible, given that we're already in C-land here, so...
  99. abort! */
  100. abort ();
  101. }
  102. #undef FUNC_NAME
  103. static SCM
  104. scm_suspendable_continuation_p (SCM tag)
  105. {
  106. scm_t_dynstack_prompt_flags flags;
  107. scm_thread *thread = SCM_I_CURRENT_THREAD;
  108. jmp_buf *registers;
  109. if (scm_dynstack_find_prompt (&thread->dynstack, tag, &flags,
  110. NULL, NULL, NULL, NULL, &registers))
  111. return scm_from_bool (registers == thread->vm.registers);
  112. return SCM_BOOL_F;
  113. }
  114. static void
  115. scm_init_ice_9_control (void *unused)
  116. {
  117. scm_c_define_gsubr ("suspendable-continuation?", 1, 0, 0,
  118. scm_suspendable_continuation_p);
  119. }
  120. void
  121. scm_init_control (void)
  122. {
  123. #include "control.x"
  124. scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
  125. "scm_init_ice_9_control", scm_init_ice_9_control,
  126. NULL);
  127. }