extend the rules/c-objs macro to take the way as a parameter
[ghc-hetmet.git] / rts / Interpreter.c
index 3962856..3a99d42 100644 (file)
@@ -28,9 +28,7 @@
 #include <errno.h>
 #endif
 
-#ifdef USE_LIBFFI
-#include <ffi.h>
-#endif
+#include "ffi.h"
 
 /* --------------------------------------------------------------------------
  * The bytecode interpreter
@@ -65,6 +63,7 @@
     SpLim = cap->r.rCurrentTSO->stack + RESERVED_STACK_WORDS;
 
 #define SAVE_STACK_POINTERS                    \
+    ASSERT(Sp > SpLim); \
     cap->r.rCurrentTSO->sp = Sp
 
 #define RETURN_TO_SCHEDULER(todo,retcode)      \
@@ -197,6 +196,9 @@ interpretBCO (Capability* cap)
 
     LOAD_STACK_POINTERS;
 
+    cap->r.rHpLim = (P_)1; // HpLim is the context-switch flag; when it
+                           // goes to zero we must return to the scheduler.
+
     // ------------------------------------------------------------------------
     // Case 1:
     // 
@@ -551,6 +553,16 @@ do_apply:
                goto defer_apply_to_sched;
            }
 
+            // Stack check: we're about to unpack the PAP onto the
+            // stack.  The (+1) is for the (arity < n) case, where we
+            // also need space for an extra info pointer.
+            if (Sp - (pap->n_args + 1) < SpLim) {
+                Sp -= 2;
+                Sp[1] = (W_)tagged_obj;
+                Sp[0] = (W_)&stg_enter_info;
+                RETURN_TO_SCHEDULER(ThreadInterpret, StackOverflow);
+            }
+
            Sp++;
            arity = pap->arity;
            ASSERT(arity > 0);
@@ -1272,7 +1284,7 @@ run_BCO:
            // context switching: sometimes the scheduler can invoke
            // the interpreter with context_switch == 1, particularly
            // if the -C0 flag has been given on the cmd line.
-           if (context_switch) {
+           if (cap->r.rHpLim == NULL) {
                Sp--; Sp[0] = (W_)&stg_enter_info;
                RETURN_TO_SCHEDULER(ThreadInterpret, ThreadYielding);
            }
@@ -1347,7 +1359,6 @@ run_BCO:
                So we make a copy of the argument block.
             */
 
-#ifdef USE_LIBFFI
 #define ROUND_UP_WDS(p)  ((((StgWord)(p)) + sizeof(W_)-1)/sizeof(W_))
 
             ffi_cif *cif = (ffi_cif *)marshall_fn;
@@ -1384,10 +1395,6 @@ run_BCO:
 
             // this is the function we're going to call
             fn = (void(*)(void))Sp[ret_size];
-#else
-           W_ arguments[stk_offset];
-           memcpy(arguments, Sp, sizeof(W_) * stk_offset);
-#endif
 
            // Restore the Haskell thread's current value of errno
            errno = cap->r.rCurrentTSO->saved_errno;
@@ -1415,14 +1422,10 @@ run_BCO:
            tok = suspendThread(&cap->r);
 
            // We already made a copy of the arguments above.
-#ifdef USE_LIBFFI
             ffi_call(cif, fn, ret, argptrs);
-#else
-           marshall_fn ( arguments );
-#endif
 
            // And restart the thread again, popping the RET_DYN frame.
-           cap = (Capability *)((void *)((unsigned char*)resumeThread(tok) - sizeof(StgFunTable)));
+           cap = (Capability *)((void *)((unsigned char*)resumeThread(tok) - STG_FIELD_OFFSET(Capability,r)));
            LOAD_STACK_POINTERS;
 
             // Re-load the pointer to the BCO from the RET_DYN frame,
@@ -1441,11 +1444,7 @@ run_BCO:
                
            // Copy the return value back to the TSO stack.  It is at
             // most 2 words large, and resides at arguments[0].
-#ifdef USE_LIBFFI
             memcpy(Sp, ret, sizeof(W_) * stg_min(stk_offset,ret_size));
-#else
-           memcpy(Sp, arguments, sizeof(W_) * stg_min(stk_offset,2));
-#endif
 
            goto nextInsn;
        }