1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-14 23:50:19 +02:00

Rework VM approach to shuffling unknown numbers of args

* libguile/vm-engine.c (shuffle-down, expand-apply-argument): New
  instructions.
  (tail-call, tail-call-label, return-values): Don't reset the frame.
  The compiler should reset the frame appropriately.
  (tail-call/shuffle, tail-apply): Remove unused instructions.
* libguile/vm.c (vm_builtin_apply_code): Use new shuffle-down and
  expand-apply-argument opcodes.
  (vm_builtin_call_with_values_code): Replace tail-call/shuffle with
  shuffle-down then tail-call.
* libguile/jit.c (compile_shuffle_down, compile_expand_apply_argument):
  Add compiler stubs
  (COMPILE_X8_F12_F12): New definition.
  (compile_tail_call_shuffle, compile_tail_apply): Remove unused
  compilers.
* module/language/cps/compile-bytecode.scm (compile-function): Emit
  reset-frame before tail calls and returns.
* module/system/vm/assembler.scm (system): Remove unbound "emit-return"
  export.
* module/system/vm/disassembler.scm (code-annotation)
  (instruction-has-fallthrough?, define-stack-effect-parser): Adapt for
  opcode changes.
This commit is contained in:
Andy Wingo 2018-07-19 10:56:44 +02:00
parent 043432fd57
commit c2a8224a63
6 changed files with 106 additions and 151 deletions

View file

@ -428,20 +428,14 @@ VM_NAME (scm_thread *thread)
NEXT (0);
}
/* tail-call nlocals:24
/* tail-call _:24
*
* Tail-call a procedure. Requires that the procedure and all of the
* arguments have already been shuffled into position. Will reset the
* frame to NLOCALS.
* Tail-call the procedure in slot 0 with the arguments in the current
* stack frame. Requires that the procedure and all of the arguments
* have already been shuffled into position.
*/
VM_DEFINE_OP (3, tail_call, "tail-call", OP1 (X8_C24))
VM_DEFINE_OP (3, tail_call, "tail-call", OP1 (X32))
{
uint32_t nlocals;
UNPACK_24 (op, nlocals);
RESET_FRAME (nlocals);
if (SCM_LIKELY (SCM_PROGRAM_P (FP_REF (0))))
ip = SCM_PROGRAM_CODE (FP_REF (0));
else
@ -456,21 +450,17 @@ VM_NAME (scm_thread *thread)
NEXT (0);
}
/* tail-call-label nlocals:24 label:32
/* tail-call-label _:24 label:32
*
* Tail-call a known procedure. As call is to call-label, tail-call
* is to tail-call-label.
*/
VM_DEFINE_OP (4, tail_call_label, "tail-call-label", OP2 (X8_C24, L32))
VM_DEFINE_OP (4, tail_call_label, "tail-call-label", OP2 (X32, L32))
{
uint32_t nlocals;
int32_t label;
UNPACK_24 (op, nlocals);
label = ip[1];
RESET_FRAME (nlocals);
ip += label;
APPLY_HOOK ();
@ -478,39 +468,10 @@ VM_NAME (scm_thread *thread)
NEXT (0);
}
/* tail-call/shuffle from:24
*
* Tail-call a procedure. The procedure should already be set to slot
* 0. The rest of the args are taken from the frame, starting at
* FROM, shuffled down to start at slot 0. This is part of the
* implementation of the call-with-values builtin.
*/
VM_DEFINE_OP (5, tail_call_shuffle, "tail-call/shuffle", OP1 (X8_F24))
VM_DEFINE_OP (5, unused_5, NULL, NOP)
{
uint32_t n, from, nlocals;
UNPACK_24 (op, from);
VM_ASSERT (from > 0, abort ());
nlocals = FRAME_LOCALS_COUNT ();
for (n = 0; from + n < nlocals; n++)
FP_SET (n + 1, FP_REF (from + n));
RESET_FRAME (n + 1);
if (SCM_LIKELY (SCM_PROGRAM_P (FP_REF (0))))
ip = SCM_PROGRAM_CODE (FP_REF (0));
else
{
SYNC_IP ();
CALL_INTRINSIC (apply_non_program, (thread));
CACHE_REGISTER ();
}
APPLY_HOOK ();
NEXT (0);
vm_error_bad_instruction (op);
abort (); /* never reached */
}
/* receive dst:12 proc:12 _:8 nlocals:24
@ -554,29 +515,36 @@ VM_NAME (scm_thread *thread)
NEXT (2);
}
VM_DEFINE_OP (8, unused_8, NULL, NOP)
/* shuffle-down from:12 to:12
*
* Shuffle down values from FROM to TO, reducing the frame size by
* (FROM-TO) slots. Part of the internal implementation of
* call-with-values, values, and apply.
*/
VM_DEFINE_OP (8, shuffle_down, "shuffle-down", OP1 (X8_F12_F12))
{
vm_error_bad_instruction (op);
abort (); /* never reached */
uint32_t n, from, to, nlocals;
UNPACK_12_12 (op, from, to);
VM_ASSERT (from > to, abort ());
nlocals = FRAME_LOCALS_COUNT ();
for (n = 0; from + n < nlocals; n++)
FP_SET (to + n, FP_REF (from + n));
RESET_FRAME (to + n);
NEXT (1);
}
/* return-values nlocals:24
/* return-values _:24
*
* Return a number of values from a call frame. This opcode
* corresponds to an application of `values' in tail position. As
* with tail calls, we expect that the values have already been
* shuffled down to a contiguous array starting at slot 1.
* If NLOCALS is not zero, we also reset the frame to hold NLOCALS
* values.
* Return all values from a call frame.
*/
VM_DEFINE_OP (9, return_values, "return-values", OP1 (X8_C24))
VM_DEFINE_OP (9, return_values, "return-values", OP1 (X32))
{
union scm_vm_stack_element *old_fp;
uint32_t nlocals;
UNPACK_24 (op, nlocals);
if (nlocals)
RESET_FRAME (nlocals);
old_fp = VP->fp;
ip = SCM_FRAME_VIRTUAL_RETURN_ADDRESS (VP->fp);
@ -706,51 +674,10 @@ VM_NAME (scm_thread *thread)
NEXT (0);
}
/* tail-apply _:24
*
* Tail-apply the procedure in local slot 1 to the rest of the
* arguments. This instruction is part of the implementation of
* `apply', and is not generated by the compiler.
*/
VM_DEFINE_OP (14, tail_apply, "tail-apply", OP1 (X32))
VM_DEFINE_OP (14, unused_14, NULL, NOP)
{
int i, list_idx, list_len, nlocals;
SCM list;
nlocals = FRAME_LOCALS_COUNT ();
// At a minimum, there should be apply, f, and the list.
VM_ASSERT (nlocals >= 3, abort ());
list_idx = nlocals - 1;
list = FP_REF (list_idx);
SYNC_IP ();
list_len = CALL_INTRINSIC (rest_arg_length, (list));
nlocals = nlocals - 2 + list_len;
ALLOC_FRAME (nlocals);
for (i = 1; i < list_idx; i++)
FP_SET (i - 1, FP_REF (i));
/* Null out these slots, just in case there are less than 2 elements
in the list. */
FP_SET (list_idx - 1, SCM_UNDEFINED);
FP_SET (list_idx, SCM_UNDEFINED);
for (i = 0; i < list_len; i++, list = SCM_CDR (list))
FP_SET (list_idx - 1 + i, SCM_CAR (list));
if (SCM_LIKELY (SCM_PROGRAM_P (FP_REF (0))))
ip = SCM_PROGRAM_CODE (FP_REF (0));
else
{
CALL_INTRINSIC (apply_non_program, (thread));
CACHE_REGISTER ();
}
APPLY_HOOK ();
NEXT (0);
vm_error_bad_instruction (op);
abort (); /* never reached */
}
/* call/cc _:24
@ -1042,10 +969,30 @@ VM_NAME (scm_thread *thread)
NEXT (1);
}
VM_DEFINE_OP (30, unused_30, NULL, NOP)
/* expand-apply-argument _:24
*
* Take the last local in a frame and expand it out onto the stack, as
* for the last argument to "apply".
*/
VM_DEFINE_OP (30, expand_apply_argument, "expand-apply-argument", OP1 (X32))
{
vm_error_bad_instruction (op);
abort ();
int list_len;
SCM list;
list = SP_REF (0);
SYNC_IP ();
list_len = CALL_INTRINSIC (rest_arg_length, (list));
ALLOC_FRAME (FRAME_LOCALS_COUNT () - 1 + list_len);
while (list_len--)
{
SP_SET (list_len, SCM_CAR (list));
list = SCM_CDR (list);
}
NEXT (1);
}
/* bind-kwargs nreq:24 flags:8 nreq-and-opt:24 _:8 ntotal:24 kw-offset:32