[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Guile-commits] 06/08: Rework VM approach to shuffling unknown numbers o
From: |
Andy Wingo |
Subject: |
[Guile-commits] 06/08: Rework VM approach to shuffling unknown numbers of args |
Date: |
Fri, 20 Jul 2018 05:58:56 -0400 (EDT) |
wingo pushed a commit to branch lightning
in repository guile.
commit c2a8224a63da432c82f24a76c008e4cfe9cba25b
Author: Andy Wingo <address@hidden>
Date: Thu Jul 19 10:56:44 2018 +0200
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.
---
libguile/jit.c | 31 ++++--
libguile/vm-engine.c | 171 +++++++++++--------------------
libguile/vm.c | 9 +-
module/language/cps/compile-bytecode.scm | 12 ++-
module/system/vm/assembler.scm | 3 +-
module/system/vm/disassembler.scm | 27 ++---
6 files changed, 104 insertions(+), 149 deletions(-)
diff --git a/libguile/jit.c b/libguile/jit.c
index 3cb3ddd..04e2810 100644
--- a/libguile/jit.c
+++ b/libguile/jit.c
@@ -61,32 +61,32 @@ compile_call_label (scm_jit_state *j, uint32_t a, uint32_t
b, int32_t offset)
}
static void
-compile_tail_call (scm_jit_state *j, uint32_t a)
+compile_tail_call (scm_jit_state *j)
{
}
static void
-compile_tail_call_label (scm_jit_state *j, uint32_t a, int32_t offset)
+compile_tail_call_label (scm_jit_state *j, int32_t offset)
{
}
static void
-compile_tail_call_shuffle (scm_jit_state *j, uint32_t a)
+compile_receive (scm_jit_state *j, uint16_t dst, uint16_t a, uint32_t b)
{
}
static void
-compile_receive (scm_jit_state *j, uint16_t dst, uint16_t a, uint32_t b)
+compile_receive_values (scm_jit_state *j, uint32_t a, uint8_t b, uint32_t c)
{
}
static void
-compile_receive_values (scm_jit_state *j, uint32_t a, uint8_t b, uint32_t c)
+compile_shuffle_down (scm_jit_state *j, uint16_t from, uint16_t to)
{
}
static void
-compile_return_values (scm_jit_state *j, uint32_t a)
+compile_return_values (scm_jit_state *j)
{
}
@@ -111,11 +111,6 @@ compile_compose_continuation (scm_jit_state *j, uint32_t a)
}
static void
-compile_tail_apply (scm_jit_state *j)
-{
-}
-
-static void
compile_call_cc (scm_jit_state *j)
{
}
@@ -191,6 +186,11 @@ compile_assert_nargs_ee_locals (scm_jit_state *j, uint16_t
a, uint16_t b)
}
static void
+compile_expand_apply_argument (scm_jit_state *j)
+{
+}
+
+static void
compile_bind_kwargs (scm_jit_state *j, uint32_t a, uint8_t b, uint32_t c,
uint32_t d, int32_t offset)
{
}
@@ -917,6 +917,8 @@ compile_f64_set (scm_jit_state *j, uint8_t a, uint8_t b,
uint8_t c)
COMPILE_X8_C12_C12 (j, comp)
#define COMPILE_X8_S12_S12(j, comp) \
COMPILE_X8_C12_C12 (j, comp)
+#define COMPILE_X8_F12_F12(j, comp) \
+ COMPILE_X8_C12_C12 (j, comp)
#define COMPILE_X8_S12_Z12(j, comp) \
{ \
@@ -953,6 +955,13 @@ compile_f64_set (scm_jit_state *j, uint8_t a, uint8_t b,
uint8_t c)
j->ip += 2; \
}
+#define COMPILE_X32__L32(j, comp) \
+ { \
+ int32_t a = j->ip[1]; \
+ comp (j, a); \
+ j->ip += 1; \
+ }
+
#define COMPILE_X8_C24__L32(j, comp) \
{ \
uint32_t a; \
diff --git a/libguile/vm-engine.c b/libguile/vm-engine.c
index 341a006..383b4f5 100644
--- a/libguile/vm-engine.c
+++ b/libguile/vm-engine.c
@@ -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
diff --git a/libguile/vm.c b/libguile/vm.c
index 1f2373a..0e61120 100644
--- a/libguile/vm.c
+++ b/libguile/vm.c
@@ -335,11 +335,13 @@ static const uint32_t vm_boot_continuation_code[] = {
static const uint32_t vm_builtin_apply_code[] = {
SCM_PACK_OP_24 (assert_nargs_ge, 3),
- SCM_PACK_OP_24 (tail_apply, 0), /* proc in r1, args from r2 */
+ SCM_PACK_OP_12_12 (shuffle_down, 1, 0),
+ SCM_PACK_OP_24 (expand_apply_argument, 0),
+ SCM_PACK_OP_24 (tail_call, 0),
};
static const uint32_t vm_builtin_values_code[] = {
- SCM_PACK_OP_24 (return_values, 0) /* vals from r1 */
+ SCM_PACK_OP_24 (return_values, 0)
};
static const uint32_t vm_builtin_abort_to_prompt_code[] = {
@@ -355,7 +357,8 @@ static const uint32_t vm_builtin_call_with_values_code[] = {
SCM_PACK_OP_12_12 (mov, 0, 6),
SCM_PACK_OP_24 (call, 7), SCM_PACK_OP_ARG_8_24 (0, 1),
SCM_PACK_OP_24 (long_fmov, 0), SCM_PACK_OP_ARG_8_24 (0, 2),
- SCM_PACK_OP_24 (tail_call_shuffle, 8)
+ SCM_PACK_OP_12_12 (shuffle_down, 8, 1),
+ SCM_PACK_OP_24 (tail_call, 0)
};
static const uint32_t vm_builtin_call_with_current_continuation_code[] = {
diff --git a/module/language/cps/compile-bytecode.scm
b/module/language/cps/compile-bytecode.scm
index 91ae19c..4b2f358 100644
--- a/module/language/cps/compile-bytecode.scm
+++ b/module/language/cps/compile-bytecode.scm
@@ -110,22 +110,28 @@
(define (compile-tail label exp)
;; There are only three kinds of expressions in tail position:
;; tail calls, multiple-value returns, and single-value returns.
+ (define (maybe-reset-frame nlocals)
+ (unless (= frame-size nlocals)
+ (emit-reset-frame asm nlocals)))
(match exp
(($ $call proc args)
(for-each (match-lambda
((src . dst) (emit-mov asm (from-sp dst) (from-sp src))))
(lookup-parallel-moves label allocation))
- (emit-tail-call asm (1+ (length args))))
+ (maybe-reset-frame (1+ (length args)))
+ (emit-tail-call asm))
(($ $callk k proc args)
(for-each (match-lambda
((src . dst) (emit-mov asm (from-sp dst) (from-sp src))))
(lookup-parallel-moves label allocation))
- (emit-tail-call-label asm (1+ (length args)) k))
+ (maybe-reset-frame (1+ (length args)))
+ (emit-tail-call-label asm k))
(($ $values args)
(for-each (match-lambda
((src . dst) (emit-mov asm (from-sp dst) (from-sp src))))
(lookup-parallel-moves label allocation))
- (emit-return-values asm (1+ (length args))))))
+ (maybe-reset-frame (1+ (length args)))
+ (emit-return-values asm))))
(define (compile-value label exp dst)
(match exp
diff --git a/module/system/vm/assembler.scm b/module/system/vm/assembler.scm
index e57e1ba..83d29f4 100644
--- a/module/system/vm/assembler.scm
+++ b/module/system/vm/assembler.scm
@@ -237,7 +237,6 @@
emit-tail-call
emit-tail-call-label
emit-receive-values
- emit-return
emit-return-values
emit-call/cc
emit-abort
@@ -1562,7 +1561,7 @@ a procedure to do that and return its label. Otherwise
return
(assert-nargs-ee/locals 1 1)
,@(reverse inits)
(load-constant 0 ,*unspecified*)
- (return-values 2)
+ (return-values)
(end-program)))
label))))
diff --git a/module/system/vm/disassembler.scm
b/module/system/vm/disassembler.scm
index f46b160..8349933 100644
--- a/module/system/vm/disassembler.scm
+++ b/module/system/vm/disassembler.scm
@@ -235,14 +235,8 @@ address of that offset."
(list "~a slot~:p" nlocals))
(('reset-frame nlocals)
(list "~a slot~:p" nlocals))
- (('return-values nlocals)
- (if (zero? nlocals)
- (list "all values")
- (list "~a value~:p" (1- nlocals))))
(('bind-rest dst)
(list "~a slot~:p" (1+ dst)))
- (('tail-call nargs proc)
- (list "~a arg~:p" nargs))
(('make-closure dst target nfree)
(let* ((addr (u32-offset->addr (+ offset target) context))
(pdi (find-program-debug-info addr context))
@@ -264,7 +258,7 @@ address of that offset."
"anonymous procedure")))
(push-addr! addr name)
(list "~A at #x~X" name addr)))
- (('tail-call-label nlocals target)
+ (('tail-call-label target)
(let* ((addr (u32-offset->addr (+ offset target) context))
(pdi (find-program-debug-info addr context))
(name (or (and pdi (program-debug-info-name pdi))
@@ -507,17 +501,10 @@ address of that offset."
(define (instruction-has-fallthrough? code pos)
(define non-fallthrough-set
(static-opcode-set halt
- ;; FIXME: add throw, throw/value,
- ;; throw/value+data. Currently control flow
- ;; nominally continues; we don't add these ops to
- ;; the non-fallthrough-set currently to allow the
- ;; frame parser to be able to compute the stack
- ;; size for following code.
throw throw/value throw/value+data
- tail-call tail-call-label tail-call/shuffle
+ tail-call tail-call-label
return-values
subr-call foreign-call continuation-call
- tail-apply
j))
(let ((opcode (logand (bytevector-u32-native-ref code pos) #xff)))
(not (bitvector-ref non-fallthrough-set opcode))))
@@ -582,10 +569,14 @@ address of that offset."
#xfff))
(nlocals (ash (bytevector-u32-native-ref code pos) -20)))
(+ nargs nlocals))))
- ((call call-label)
- #'(lambda (code pos size) #f))
- ((tail-call tail-call-label tail-call/shuffle tail-apply)
+ ((call call-label tail-call tail-call-label expand-apply-argument)
#'(lambda (code pos size) #f))
+ ((shuffle-down)
+ #'(lambda (code pos size)
+ (let ((from (logand (ash (bytevector-u32-native-ref code pos) -8)
+ #xfff))
+ (to (ash (bytevector-u32-native-ref code pos) -20)))
+ (and size (- size (- from to))))))
(else
#f)))
(syntax-case x ()
- [Guile-commits] branch lightning updated (5577392 -> 950a762), Andy Wingo, 2018/07/20
- [Guile-commits] 07/08: Fix stale stack frame clearing for frame size change, Andy Wingo, 2018/07/20
- [Guile-commits] 03/08: Add support for reading ELF symbol table from C, Andy Wingo, 2018/07/20
- [Guile-commits] 05/08: Reserve frame word for machine return address, Andy Wingo, 2018/07/20
- [Guile-commits] 04/08: Prepare for frames having separate virtual and machine return addrs, Andy Wingo, 2018/07/20
- [Guile-commits] 08/08: Multiple-value returns now start from slot 0, not slot 1, Andy Wingo, 2018/07/20
- [Guile-commits] 06/08: Rework VM approach to shuffling unknown numbers of args,
Andy Wingo <=
- [Guile-commits] 01/08: Merge 'master' into 'lightning', Andy Wingo, 2018/07/20
- [Guile-commits] 02/08: Make JIT compiler skeleton more terse, Andy Wingo, 2018/07/20