[project @ 2002-12-18 11:17:15 by simonmar]
authorsimonmar <unknown>
Wed, 18 Dec 2002 11:17:16 +0000 (11:17 +0000)
committersimonmar <unknown>
Wed, 18 Dec 2002 11:17:16 +0000 (11:17 +0000)
Correctly describe the stack during a GHCi CCALL instruction to the
RTS.  The previous hack, temporarily truncating the stack to the
topmost valid stack frame, didn't work because stack-squeezing tends
to move the stack around before the call.

The right thing to do is correctly describe the chunk of ccall args
with an info table, which is what this change does.  We use a RET_DYN
info table with the number of non-ptrs from the CCALL instruction.

ghc/compiler/ghci/ByteCodeGen.lhs
ghc/rts/Interpreter.c

index faed478..3ce7789 100644 (file)
@@ -953,8 +953,7 @@ generateCCall d0 s p ccall_spec@(CCallSpec target cconv safety) fn args_r_to_l
          depth, and we RETURN.
 
          This arrangement makes it simple to do f-i-dynamic since the Addr#
-         value is the first arg anyway.  It also has the virtue that the
-         stack is GC-understandable at all times.
+         value is the first arg anyway.
 
          The marshalling code is generated specifically for this
          call site, and so knows exactly the (Haskell) stack
@@ -1015,13 +1014,9 @@ generateCCall d0 s p ccall_spec@(CCallSpec target cconv safety) fn args_r_to_l
          recordMallocBc addr_of_marshaller     `thenBc_`
      let
         -- Offset of the next stack frame down the stack.  The CCALL
-        -- instruction will temporarily shift the stack pointer up by
-        -- this much during the call, and shift it down again afterwards.
-        -- This is so that we don't have to worry about constructing
-        -- a bitmap to describe the stack layout of the call: the
-        -- contents of this part of the stack are irrelevant anyway,
-        -- it is only used to communicate the arguments to the
-        -- marshalling code.
+        -- instruction needs to describe the chunk of stack containing
+        -- the ccall args to the GC, so it needs to know how large it
+        -- is.  See comment in Interpreter.c with the CCALL instruction.
         stk_offset   = d_after_r - s
 
          -- do the call
index cbbbc29..89a5e59 100644 (file)
@@ -1161,15 +1161,33 @@ run_BCO:
            int o_itbl                = BCO_NEXT;
            void(*marshall_fn)(void*) = (void (*)(void*))BCO_LIT(o_itbl);
 
-           // Shift the stack pointer down to the next relevant stack
-           // frame during the call.  See comment in ByteCodeGen.lhs.
-           Sp += stk_offset;
+           // There are a bunch of non-ptr words on the stack (the
+           // ccall args, the ccall fun address and space for the
+           // result), which we need to cover with an info table
+           // since we might GC during this call.
+           //
+           // We know how many (non-ptr) words there are before the
+           // next valid stack frame: it is the stk_offset arg to the
+           // CCALL instruction.   So we build a RET_DYN stack frame
+           // on the stack frame to describe this chunk of stack.
+           //
+           Sp -= RET_DYN_SIZE + sizeofW(StgRetDyn);
+           ((StgRetDyn *)Sp)->liveness = ALL_NON_PTRS | N_NONPTRS(stk_offset);
+           ((StgRetDyn *)Sp)->info = (StgInfoTable *)&stg_gc_gen_info;
+
            SAVE_STACK_POINTERS;
            tok = suspendThread(&cap->r,rtsFalse);
-           marshall_fn ( (void*)(& Sp[-stk_offset] ) );
+
+           // Careful: suspendThread might have shifted the stack
+           // around (stack squeezing), so we have to grab the real
+           // Sp out of the TSO to find the ccall args again:
+           marshall_fn ( (void*)(cap->r.rCurrentTSO->sp + RET_DYN_SIZE
+               + sizeofW(StgRetDyn)) );
+
+           // And restart the thread again, popping the RET_DYN frame.
            cap = (Capability *)((void *)resumeThread(tok,rtsFalse) - sizeof(StgFunTable));
            LOAD_STACK_POINTERS;
-           Sp -= stk_offset;
+           Sp += RET_DYN_SIZE + sizeofW(StgRetDyn);
            goto nextInsn;
        }