From 01dd712a50e82b6e7a29b9be32e3790e0b37d35f Mon Sep 17 00:00:00 2001
From: Alex Shinn <ashinn@users.noreply.github.com>
Date: Sun, 27 Feb 2011 18:14:22 +0900
Subject: [PATCH] resume/cc can grow the current stack if the continuation is
 larger (as could happen resuming a continuation from a separate thread)

---
 include/chibi/features.h |  4 ++++
 vm.c                     | 47 ++++++++++++++++++++++++----------------
 2 files changed, 32 insertions(+), 19 deletions(-)

diff --git a/include/chibi/features.h b/include/chibi/features.h
index f5f9cc89..aad53596 100644
--- a/include/chibi/features.h
+++ b/include/chibi/features.h
@@ -444,8 +444,12 @@
 #define SEXP_INIT_BCODE_SIZE 128
 #endif
 #ifndef SEXP_INIT_STACK_SIZE
+#if SEXP_USE_CHECK_STACK
+#define SEXP_INIT_STACK_SIZE 1024
+#else
 #define SEXP_INIT_STACK_SIZE 8192
 #endif
+#endif
 #ifndef SEXP_MAX_STACK_SIZE
 #define SEXP_MAX_STACK_SIZE SEXP_INIT_STACK_SIZE*1000
 #endif
diff --git a/vm.c b/vm.c
index 5b760680..bac26447 100644
--- a/vm.c
+++ b/vm.c
@@ -482,24 +482,6 @@ static sexp make_opcode_procedure (sexp ctx, sexp op, sexp_uint_t i) {
 
 /*********************** the virtual machine **************************/
 
-static sexp sexp_save_stack (sexp ctx, sexp *stack, sexp_uint_t to) {
-  sexp res, *data;
-  sexp_uint_t i;
-  res = sexp_make_vector(ctx, sexp_make_fixnum(to), SEXP_VOID);
-  data = sexp_vector_data(res);
-  for (i=0; i<to; i++)
-    data[i] = stack[i];
-  return res;
-}
-
-static sexp_uint_t sexp_restore_stack (sexp saved, sexp *current) {
-  sexp_uint_t len = sexp_vector_length(saved), i;
-  sexp *from = sexp_vector_data(saved);
-  for (i=0; i<len; i++)
-    current[i] = from[i];
-  return len;
-}
-
 #if SEXP_USE_CHECK_STACK
 static int sexp_grow_stack (sexp ctx) {
   sexp stack, *from, *to;
@@ -523,6 +505,31 @@ static int sexp_grow_stack (sexp ctx) {
 }
 #endif
 
+static sexp sexp_save_stack (sexp ctx, sexp *stack, sexp_uint_t to) {
+  sexp res, *data;
+  sexp_uint_t i;
+  res = sexp_make_vector(ctx, sexp_make_fixnum(to), SEXP_VOID);
+  data = sexp_vector_data(res);
+  for (i=0; i<to; i++)
+    data[i] = stack[i];
+  return res;
+}
+
+static sexp sexp_restore_stack (sexp ctx, sexp saved) {
+  sexp_uint_t len = sexp_vector_length(saved), i;
+  sexp *from = sexp_vector_data(saved), *to;
+#if SEXP_USE_CHECK_STACK
+  if ((len+64 >= sexp_stack_length(sexp_context_stack(ctx)))
+      && !sexp_grow_stack(ctx))
+    return sexp_global(ctx, SEXP_G_OOS_ERROR);
+#endif
+  to = sexp_stack_data(sexp_context_stack(ctx));
+  for (i=0; i<len; i++)
+    to[i] = from[i];
+  sexp_context_top(ctx) = len;
+  return SEXP_VOID;
+}
+
 #define _ARG1 stack[top-1]
 #define _ARG2 stack[top-2]
 #define _ARG3 stack[top-3]
@@ -679,7 +686,9 @@ sexp sexp_vm (sexp ctx, sexp proc) {
   case SEXP_OP_RESUMECC:
     sexp_context_top(ctx) = top;
     tmp1 = stack[fp-1];
-    top = sexp_restore_stack(sexp_vector_ref(cp, 0), stack);
+    tmp2 = sexp_restore_stack(ctx, sexp_vector_ref(cp, 0));
+    if (sexp_exceptionp(tmp2)) {_ARG1 = tmp2; goto call_error_handler;}
+    top = sexp_context_top(ctx);
     fp = sexp_unbox_fixnum(_ARG1);
     self = _ARG2;
     bc = sexp_procedure_code(self);