/* -----------------------------------------------------------------------------
- * $Id: StgMacros.h,v 1.36 2000/11/13 14:40:36 simonmar Exp $
+ * $Id: StgMacros.h,v 1.49 2002/10/12 23:19:54 wolfgang Exp $
*
* (c) The GHC Team, 1998-1999
*
#define STK_CHK(headroom,ret,r,layout,tag_assts) \
if (Sp - headroom < SpLim) { \
- EXTFUN_RTS(stg_chk_##layout); \
tag_assts \
(r) = (P_)ret; \
JMP_(stg_chk_##layout); \
#define HP_CHK(headroom,ret,r,layout,tag_assts) \
DO_GRAN_ALLOCATE(headroom) \
if ((Hp += headroom) > HpLim) { \
- EXTFUN_RTS(stg_chk_##layout); \
+ HpAlloc = (headroom); \
tag_assts \
(r) = (P_)ret; \
JMP_(stg_chk_##layout); \
- }
+ }
#define HP_STK_CHK(stk_headroom,hp_headroom,ret,r,layout,tag_assts) \
DO_GRAN_ALLOCATE(hp_headroom) \
- if (Sp - stk_headroom < SpLim || (Hp += hp_headroom) > HpLim) { \
- EXTFUN_RTS(stg_chk_##layout); \
+ if ((Hp += hp_headroom) > HpLim || Sp - stk_headroom < SpLim) { \
+ HpAlloc = (hp_headroom); \
tag_assts \
(r) = (P_)ret; \
JMP_(stg_chk_##layout); \
- }
+ }
/* -----------------------------------------------------------------------------
A Heap Check in a case alternative are much simpler: everything is
#define STK_CHK_NP(headroom,ptrs,tag_assts) \
if ((Sp - (headroom)) < SpLim) { \
- EXTFUN_RTS(stg_gc_enter_##ptrs); \
tag_assts \
JMP_(stg_gc_enter_##ptrs); \
}
#define HP_CHK_NP(headroom,ptrs,tag_assts) \
DO_GRAN_ALLOCATE(headroom) \
if ((Hp += (headroom)) > HpLim) { \
- EXTFUN_RTS(stg_gc_enter_##ptrs); \
+ HpAlloc = (headroom); \
tag_assts \
JMP_(stg_gc_enter_##ptrs); \
- }
+ }
#define HP_CHK_SEQ_NP(headroom,ptrs,tag_assts) \
DO_GRAN_ALLOCATE(headroom) \
if ((Hp += (headroom)) > HpLim) { \
- EXTFUN_RTS(stg_gc_seq_##ptrs); \
+ HpAlloc = (headroom); \
tag_assts \
JMP_(stg_gc_seq_##ptrs); \
- }
+ }
#define HP_STK_CHK_NP(stk_headroom, hp_headroom, ptrs, tag_assts) \
DO_GRAN_ALLOCATE(hp_headroom) \
- if ((Sp - (stk_headroom)) < SpLim || (Hp += (hp_headroom)) > HpLim) { \
- EXTFUN_RTS(stg_gc_enter_##ptrs); \
+ if ((Hp += (hp_headroom)) > HpLim || (Sp - (stk_headroom)) < SpLim) { \
+ HpAlloc = (hp_headroom); \
tag_assts \
JMP_(stg_gc_enter_##ptrs); \
- }
+ }
/* Heap checks for branches of a primitive case / unboxed tuple return */
DO_GRAN_ALLOCATE(headroom) \
if ((Hp += (headroom)) > HpLim) { \
EXTFUN_RTS(lbl); \
+ HpAlloc = (headroom); \
tag_assts \
JMP_(lbl); \
- }
+ }
#define HP_CHK_NOREGS(headroom,tag_assts) \
GEN_HP_CHK_ALT(headroom,stg_gc_noregs,tag_assts);
GEN_HP_CHK_ALT(headroom,stg_gc_d1,tag_assts);
#define HP_CHK_L1(headroom,tag_assts) \
- GEN_HP_CHK_ALT(headroom,stg_gc_d1,tag_assts);
+ GEN_HP_CHK_ALT(headroom,stg_gc_l1,tag_assts);
#define HP_CHK_UT_ALT(headroom, ptrs, nptrs, r, ret, tag_assts) \
GEN_HP_CHK_ALT(headroom, stg_gc_ut_##ptrs##_##nptrs, \
#define HP_CHK_GEN(headroom,liveness,reentry,tag_assts) \
if ((Hp += (headroom)) > HpLim ) { \
- EXTFUN_RTS(stg_gen_chk); \
+ HpAlloc = (headroom); \
tag_assts \
R9.w = (W_)LIVENESS_MASK(liveness); \
R10.w = (W_)reentry; \
JMP_(stg_gen_chk); \
- }
+ }
#define HP_CHK_GEN_TICKY(headroom,liveness,reentry,tag_assts) \
HP_CHK_GEN(headroom,liveness,reentry,tag_assts); \
#define STK_CHK_GEN(headroom,liveness,reentry,tag_assts) \
if ((Sp - (headroom)) < SpLim) { \
- EXTFUN_RTS(stg_gen_chk); \
tag_assts \
R9.w = (W_)LIVENESS_MASK(liveness); \
R10.w = (W_)reentry; \
#define MAYBE_GC(liveness,reentry) \
if (doYouWantToGC()) { \
- EXTFUN_RTS(stg_gen_hp); \
R9.w = (W_)LIVENESS_MASK(liveness); \
R10.w = (W_)reentry; \
JMP_(stg_gen_hp); \
TICK_UPD_BH_UPDATABLE(); \
{ \
bdescr *bd = Bdescr(R1.p); \
- if (bd->back != (bdescr *)BaseReg) { \
- if (bd->gen->no >= 1 || bd->step->no >= 1) { \
+ if (bd->u.back != (bdescr *)BaseReg) { \
+ if (bd->gen_no >= 1 || bd->step->no >= 1) { \
LOCK_THUNK(info); \
} else { \
EXTFUN_RTS(stg_gc_enter_1_hponly); \
TICK_UPD_BH_SINGLE_ENTRY(); \
{ \
bdescr *bd = Bdescr(R1.p); \
- if (bd->back != (bdescr *)BaseReg) { \
- if (bd->gen->no >= 1 || bd->step->no >= 1) { \
+ if (bd->u.back != (bdescr *)BaseReg) { \
+ if (bd->gen_no >= 1 || bd->step->no >= 1) { \
LOCK_THUNK(info); \
} else { \
EXTFUN_RTS(stg_gc_enter_1_hponly); \
} \
SET_INFO(R1.cl,&stg_BLACKHOLE_info)
# else
+# ifndef PROFILING
# define UPD_BH_UPDATABLE(info) \
TICK_UPD_BH_UPDATABLE(); \
SET_INFO(R1.cl,&stg_BLACKHOLE_info)
# define UPD_BH_SINGLE_ENTRY(info) \
TICK_UPD_BH_SINGLE_ENTRY(); \
SET_INFO(R1.cl,&stg_SE_BLACKHOLE_info)
+# else
+// An object is replaced by a blackhole, so we fill the slop with zeros.
+//
+// Todo: maybe use SET_HDR() and remove LDV_recordCreate()?
+//
+# define UPD_BH_UPDATABLE(info) \
+ TICK_UPD_BH_UPDATABLE(); \
+ LDV_recordDead_FILL_SLOP_DYNAMIC(R1.cl); \
+ SET_INFO(R1.cl,&stg_BLACKHOLE_info); \
+ LDV_recordCreate(R1.cl)
+# define UPD_BH_SINGLE_ENTRY(info) \
+ TICK_UPD_BH_SINGLE_ENTRY(); \
+ LDV_recordDead_FILL_SLOP_DYNAMIC(R1.cl); \
+ SET_INFO(R1.cl,&stg_SE_BLACKHOLE_info) \
+ LDV_recordCreate(R1.cl)
+# endif /* PROFILING */
# endif
#else /* !EAGER_BLACKHOLING */
# define UPD_BH_UPDATABLE(thunk) /* nothing */
y.iu.dlo = p_src[1];
return(y.i);
}
+
+#elif SIZEOF_VOID_P == 8
+
+static inline void ASSIGN_Word64(W_ p_dest[], StgWord64 src)
+{
+ p_dest[0] = src;
+}
+
+static inline StgWord64 PK_Word64(W_ p_src[])
+{
+ return p_src[0];
+}
+
+static inline void ASSIGN_Int64(W_ p_dest[], StgInt64 src)
+{
+ p_dest[0] = src;
+}
+
+static inline StgInt64 PK_Int64(W_ p_src[])
+{
+ return p_src[0];
+}
+
#endif
/* -----------------------------------------------------------------------------
StgSeqFrame *__frame; \
TICK_SEQF_PUSHED(); \
__frame = (StgSeqFrame *)(sp); \
- SET_HDR_(__frame,&stg_seq_frame_info,CCCS); \
+ SET_HDR((StgClosure *)__frame,(StgInfoTable *)&stg_seq_frame_info,CCCS);\
__frame->link = Su; \
Su = (StgUpdateFrame *)__frame; \
}
-------------------------------------------------------------------------- */
#if defined(USE_SPLIT_MARKERS)
-#if defined(cygwin32_TARGET_OS) || defined(mingw32_TARGET_OS)
+#if defined(LEADING_UNDERSCORE)
#define __STG_SPLIT_MARKER __asm__("\n___stg_split_marker:");
#else
#define __STG_SPLIT_MARKER __asm__("\n__stg_split_marker:");
Closure and Info Macros with casting.
We don't want to mess around with casts in the generated C code, so
- we use these casting versions of the closure/info tables macros.
+ we use this casting versions of the closure macro.
+
+ This version of SET_HDR also includes CCS_ALLOC for profiling - the
+ reason we don't use two separate macros is that the cost centre
+ field is sometimes a non-simple expression and we want to share its
+ value between SET_HDR and CCS_ALLOC.
-------------------------------------------------------------------------- */
-#define SET_HDR_(c,info,ccs) \
- SET_HDR((StgClosure *)(c),(StgInfoTable *)(info),ccs)
+#define SET_HDR_(c,info,ccs,size) \
+ { \
+ CostCentreStack *tmp = (ccs); \
+ SET_HDR((StgClosure *)(c),(StgInfoTable *)(info),tmp); \
+ CCS_ALLOC(tmp,size); \
+ }
/* -----------------------------------------------------------------------------
Saving context for exit from the STG world, and loading up context
/* -----------------------------------------------------------------------------
Module initialisation
+
+ The module initialisation code looks like this, roughly:
+
+ FN(__stginit_Foo) {
+ JMP_(__stginit_Foo_1_p)
+ }
+
+ FN(__stginit_Foo_1_p) {
+ ...
+ }
+
+ We have one version of the init code with a module version and the
+ 'way' attached to it. The version number helps to catch cases
+ where modules are not compiled in dependency order before being
+ linked: if a module has been compiled since any modules which depend on
+ it, then the latter modules will refer to a different version in their
+ init blocks and a link error will ensue.
+
+ The 'way' suffix helps to catch cases where modules compiled in different
+ ways are linked together (eg. profiled and non-profiled).
+
+ We provide a plain, unadorned, version of the module init code
+ which just jumps to the version with the label and way attached. The
+ reason for this is that when using foreign exports, the caller of
+ startupHaskell() must supply the name of the init function for the "top"
+ module in the program, and we don't want to require that this name
+ has the version and way info appended to it.
-------------------------------------------------------------------------- */
#define PUSH_INIT_STACK(reg_function) \
#define POP_INIT_STACK() \
*(--Sp)
-#define START_MOD_INIT(reg_mod_name) \
+#define MOD_INIT_WRAPPER(label,real_init) \
+
+
+#define START_MOD_INIT(plain_lbl, real_lbl) \
static int _module_registered = 0; \
- FN_(reg_mod_name) { \
+ EF_(real_lbl); \
+ FN_(plain_lbl) { \
+ FB_ \
+ JMP_(real_lbl); \
+ FE_ \
+ } \
+ FN_(real_lbl) { \
FB_; \
if (! _module_registered) { \
_module_registered = 1; \
* Suspending/resuming threads for doing external C-calls (_ccall_GC).
* These functions are defined in rts/Schedule.c.
*/
-StgInt suspendThread ( StgRegTable *cap );
-StgRegTable * resumeThread ( StgInt );
+StgInt suspendThread ( StgRegTable *, rtsBool);
+StgRegTable * resumeThread ( StgInt, rtsBool );
-#define SUSPEND_THREAD(token) \
+#define SUSPEND_THREAD(token,threaded) \
SaveThreadState(); \
- token = suspendThread(BaseReg);
+ token = suspendThread(BaseReg,threaded);
#ifdef SMP
-#define RESUME_THREAD(token) \
- BaseReg = resumeThread(token); \
- LoadThreadState();
+#define RESUME_THREAD(token,threaded) \
+ BaseReg = resumeThread(token,threaded); \
+ LoadThreadState();
#else
-#define RESUME_THREAD(token) \
- (void)resumeThread(token); \
+#define RESUME_THREAD(token,threaded) \
+ (void)resumeThread(token,threaded); \
LoadThreadState();
#endif