[project @ 2002-12-05 23:49:43 by mthomas]
[ghc-hetmet.git] / ghc / rts / PrimOps.hc
index ef07664..a860dc8 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: PrimOps.hc,v 1.93 2002/02/28 18:44:29 sof Exp $
+ * $Id: PrimOps.hc,v 1.102 2002/10/22 11:01:19 simonmar Exp $
  *
  * (c) The GHC Team, 1998-2000
  *
 #include "Itimer.h"
 #include "Prelude.h"
 
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <stdlib.h>
+
 /* ** temporary **
 
    classes CCallable and CReturnable don't really exist, but the
@@ -244,40 +250,57 @@ StgWord GHC_ZCCReturnable_static_info[1];
 
 #define BYTES_TO_STGWORDS(n) ((n) + sizeof(W_) - 1)/sizeof(W_)
 
-FN_(newByteArrayzh_fast)                               \
- {                                                     \
-   W_ size, stuff_size, n;                             \
-   StgArrWords* p;                                     \
-   FB_                                                 \
-     MAYBE_GC(NO_PTRS,newByteArrayzh_fast);            \
-     n = R1.w;                                         \
-     stuff_size = BYTES_TO_STGWORDS(n);                        \
-     size = sizeofW(StgArrWords)+ stuff_size;          \
-     p = (StgArrWords *)RET_STGCALL1(P_,allocate,size);        \
-     TICK_ALLOC_PRIM(sizeofW(StgArrWords),stuff_size,0); \
-     SET_HDR(p, &stg_ARR_WORDS_info, CCCS);            \
-     p->words = stuff_size;                            \
-     TICK_RET_UNBOXED_TUP(1)                           \
-     RET_P(p);                                         \
-   FE_                                                 \
+FN_(newByteArrayzh_fast)
+ {
+   W_ size, stuff_size, n;
+   StgArrWords* p;
+   FB_
+     MAYBE_GC(NO_PTRS,newByteArrayzh_fast);
+     n = R1.w;
+     stuff_size = BYTES_TO_STGWORDS(n);
+     size = sizeofW(StgArrWords)+ stuff_size;
+     p = (StgArrWords *)RET_STGCALL1(P_,allocate,size);
+     TICK_ALLOC_PRIM(sizeofW(StgArrWords),stuff_size,0);
+     SET_HDR(p, &stg_ARR_WORDS_info, CCCS);
+     p->words = stuff_size;
+     TICK_RET_UNBOXED_TUP(1)
+     RET_P(p);
+   FE_
  }
 
-FN_(newPinnedByteArrayzh_fast)                                 \
- {                                                             \
-   W_ size, stuff_size, n;                                     \
-   StgArrWords* p;                                             \
-   FB_                                                         \
-     MAYBE_GC(NO_PTRS,newPinnedByteArrayzh_fast);              \
-     n = R1.w;                                                 \
-     stuff_size = BYTES_TO_STGWORDS(n);                                \
-     size = sizeofW(StgArrWords)+ stuff_size;                  \
-     p = (StgArrWords *)RET_STGCALL1(P_,allocatePinned,size);  \
-     TICK_ALLOC_PRIM(sizeofW(StgArrWords),stuff_size,0);       \
-     SET_HDR(p, &stg_ARR_WORDS_info, CCCS);                    \
-     p->words = stuff_size;                                    \
-     TICK_RET_UNBOXED_TUP(1)                                   \
-     RET_P(p);                                                 \
-   FE_                                                         \
+FN_(newPinnedByteArrayzh_fast)
+ {
+   W_ size, stuff_size, n;
+   StgArrWords* p;
+   FB_
+     MAYBE_GC(NO_PTRS,newPinnedByteArrayzh_fast);
+     n = R1.w;
+     stuff_size = BYTES_TO_STGWORDS(n);
+
+     // We want an 8-byte aligned array.  allocatePinned() gives us
+     // 8-byte aligned memory by default, but we want to align the
+     // *goods* inside the ArrWords object, so we have to check the
+     // size of the ArrWords header and adjust our size accordingly.
+     size = sizeofW(StgArrWords)+ stuff_size;
+     if ((sizeof(StgArrWords) & 7) != 0) {
+        size++;
+     }
+
+     p = (StgArrWords *)RET_STGCALL1(P_,allocatePinned,size);
+     TICK_ALLOC_PRIM(sizeofW(StgArrWords),stuff_size,0);
+
+     // Again, if the ArrWords header isn't a multiple of 8 bytes, we
+     // have to push the object forward one word so that the goods
+     // fall on an 8-byte boundary.
+     if ((sizeof(StgArrWords) & 7) != 0) {
+        ((StgPtr)p)++;
+     }
+
+     SET_HDR(p, &stg_ARR_WORDS_info, CCCS);
+     p->words = stuff_size;
+     TICK_RET_UNBOXED_TUP(1)
+     RET_P(p);
+   FE_
  }
 
 FN_(newArrayzh_fast)
@@ -327,6 +350,60 @@ FN_(newMutVarzh_fast)
   FE_
 }
 
+FN_(atomicModifyMutVarzh_fast)
+{
+   StgMutVar* mv;
+   StgClosure *z, *x, *y, *r;
+   FB_
+   /* Args: R1.p :: MutVar#,  R2.p :: a -> (a,b) */
+
+   /* If x is the current contents of the MutVar#, then 
+      We want to make the new contents point to
+
+         (sel_0 (f x))
+      and the return value is
+
+        (sel_1 (f x))
+
+      obviously we can share (f x).
+
+         z = [stg_ap_2 f x]  (max (HS + 2) MIN_UPD_SIZE)
+        y = [stg_sel_0 z]   (max (HS + 1) MIN_UPD_SIZE)
+         r = [stg_sel_1 z]   (max (HS + 1) MIN_UPD_SIZE)
+   */
+
+#define THUNK_SIZE(n) (sizeofW(StgHeader) + stg_max((n), MIN_UPD_SIZE))
+#define SIZE (THUNK_SIZE(2) + THUNK_SIZE(1) + THUNK_SIZE(1))
+
+   HP_CHK_GEN_TICKY(SIZE, R1_PTR|R2_PTR, atomicModifyMutVarzh_fast,);
+   CCS_ALLOC(CCCS,SIZE);
+
+   x = ((StgMutVar *)R1.cl)->var;
+
+   TICK_ALLOC_UP_THK(2,0); // XXX
+   z = (StgClosure *) Hp - THUNK_SIZE(2) + 1;
+   SET_HDR(z, &stg_ap_2_upd_info, CCCS);
+   z->payload[0] = R2.cl;
+   z->payload[1] = x;
+
+   TICK_ALLOC_UP_THK(1,1); // XXX
+   y = (StgClosure *) (StgPtr)z - THUNK_SIZE(1);
+   SET_HDR(y, &stg_sel_0_upd_info, CCCS);
+   y->payload[0] = z;
+
+   ((StgMutVar *)R1.cl)->var = y;
+
+   TICK_ALLOC_UP_THK(1,1); // XXX
+   r = (StgClosure *) (StgPtr)y - THUNK_SIZE(1);
+   SET_HDR(r, &stg_sel_1_upd_info, CCCS);
+   r->payload[0] = z;
+
+   RET_P(r);
+   JMP_(ENTRY_CODE(Sp[0]));
+   FE_
+}
+
 /* -----------------------------------------------------------------------------
    Foreign Object Primitives
    -------------------------------------------------------------------------- */
@@ -791,7 +868,10 @@ FN_(gcdIntegerIntzh_fast)
   I_ r;
   FB_
   r = RET_STGCALL3(StgInt,mpn_gcd_1,(mp_limb_t *)(BYTE_ARR_CTS(R2.p)), R1.i, R3.i);
-  RET_N(r);
+
+  R1.i = r;
+  /* Result parked in R1, return via info-pointer at TOS */
+  JMP_(ENTRY_CODE(Sp[0]));
   FE_
 }
 
@@ -1002,7 +1082,22 @@ FN_(forkzh_fast)
   /* switch at the earliest opportunity */ 
   context_switch = 1;
   
-  RET_N(R1.t);
+  RET_P(R1.t);
+  FE_
+}
+
+FN_(forkProcesszh_fast)
+{
+  pid_t pid;
+
+  FB_
+  /* args: none */
+  /* result: Pid */
+
+  R1.i = RET_STGCALL1(StgInt, forkProcess, CurrentTSO);
+
+  JMP_(ENTRY_CODE(Sp[0]));
+
   FE_
 }
 
@@ -1017,11 +1112,22 @@ FN_(myThreadIdzh_fast)
 {
   /* no args. */
   FB_
-  RET_N((P_)CurrentTSO);
+  RET_P((P_)CurrentTSO);
   FE_
 }
 
-
+FN_(labelThreadzh_fast)
+{
+  FB_
+  /* args: 
+       R1.p = ThreadId#
+       R2.p = Addr# */
+#ifdef DEBUG
+  STGCALL2(labelThread,R1.p,(char *)R2.p);
+#endif
+  JMP_(ENTRY_CODE(Sp[0]));
+  FE_
+}
 
 
 /* -----------------------------------------------------------------------------
@@ -1089,10 +1195,19 @@ FN_(newMVarzh_fast)
   FE_
 }
 
-#define PerformTake(tso, value) ({                     \
-    (tso)->sp[1] = (W_)value;                          \
+/* If R1 isn't available, pass it on the stack */
+#ifdef REG_R1
+#define PerformTake(tso, value) ({             \
+    (tso)->sp[1] = (W_)value;                  \
     (tso)->sp[0] = (W_)&stg_gc_unpt_r1_info;   \
   })
+#else
+#define PerformTake(tso, value) ({             \
+    (tso)->sp[1] = (W_)value;                  \
+    (tso)->sp[0] = (W_)&stg_ut_1_0_unreg_info; \
+  })
+#endif
+
 
 #define PerformPut(tso) ({                             \
     StgClosure *val = (StgClosure *)(tso)->sp[2];      \