X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;ds=sidebyside;f=ghc%2Fincludes%2FRegs.h;h=b6e29217eb19b2c554cfe2d7d5482f01443ac414;hb=5c67b7e313b2455ca65d5aa5970d86889145e97e;hp=cd5ff95971cf02e46bdb0bba65fbb33652e48b08;hpb=423d477bfecd490de1449c59325c8776f91d7aac;p=ghc-hetmet.git diff --git a/ghc/includes/Regs.h b/ghc/includes/Regs.h index cd5ff95..b6e2921 100644 --- a/ghc/includes/Regs.h +++ b/ghc/includes/Regs.h @@ -22,16 +22,20 @@ #ifndef REGS_H #define REGS_H +#include "gmp.h" // Needs MP_INT definition -/* - * This is the table that holds shadow-locations for all the STG - * registers. The shadow locations are used when: - * - * 1) the particular register isn't mapped to a real machine - * register, probably because there's a shortage of real registers. - * 2) caller-saves registers are saved across a CCall +/* + * Spark pools: used to store pending sparks + * (THREADED_RTS & PARALLEL_HASKELL only) + * This is a circular buffer. Invariants: + * - base <= hd < lim + * - base <= tl < lim + * - if hd==tl, then the pool is empty. + * - if hd == tl+1, then the pool is full. + * Adding to the pool is done by assigning to *tl++ (wrapping round as + * necessary). When adding to a full pool, we have the option of + * throwing away either the oldest (hd++) or the most recent (tl--) entry. */ - typedef struct StgSparkPool_ { StgClosure **base; StgClosure **lim; @@ -39,6 +43,12 @@ typedef struct StgSparkPool_ { StgClosure **tl; } StgSparkPool; +#define ASSERT_SPARK_POOL_INVARIANTS(p) \ + ASSERT((p)->base <= (p)->hd); \ + ASSERT((p)->hd < (p)->lim); \ + ASSERT((p)->base <= (p)->tl); \ + ASSERT((p)->tl < (p)->lim); + typedef struct { StgFunPtr stgGCEnter1; StgFunPtr stgGCFun; @@ -63,6 +73,14 @@ typedef union { StgTSOPtr t; } StgUnion; +/* + * This is the table that holds shadow-locations for all the STG + * registers. The shadow locations are used when: + * + * 1) the particular register isn't mapped to a real machine + * register, probably because there's a shortage of real registers. + * 2) caller-saves registers are saved across a CCall + */ typedef struct StgRegTable_ { StgUnion rR1; StgUnion rR2; @@ -72,8 +90,8 @@ typedef struct StgRegTable_ { StgUnion rR6; StgUnion rR7; StgUnion rR8; - StgUnion rR9; // used occasionally by heap/stack checks - StgUnion rR10; // used occasionally by heap/stack checks + StgUnion rR9; /* used occasionally by heap/stack checks */ + StgUnion rR10; /* used occasionally by heap/stack checks */ StgFloat rF1; StgFloat rF2; StgFloat rF3; @@ -86,39 +104,24 @@ typedef struct StgRegTable_ { StgPtr rHp; StgPtr rHpLim; struct StgTSO_ *rCurrentTSO; - struct bdescr_ *rNursery; - struct bdescr_ *rCurrentNursery; - StgWord rHpAlloc; // number of *bytes* being allocated in heap -#if defined(SMP) || defined(PAR) - StgSparkPool rSparks; // per-task spark pool + struct step_ *rNursery; + struct bdescr_ *rCurrentNursery; /* Hp/HpLim point into this block */ + struct bdescr_ *rCurrentAlloc; /* for allocation using allocate() */ + StgWord rHpAlloc; /* number of *bytes* being allocated in heap */ + // rmp_tmp1..rmp_result2 are only used in THREADED_RTS builds to + // avoid per-thread temps in bss, but currently always incldue here + // so we just run mkDerivedConstants once + StgInt rmp_tmp_w; + MP_INT rmp_tmp1; + MP_INT rmp_tmp2; + MP_INT rmp_result1; + MP_INT rmp_result2; + StgWord rRet; // holds the return code of the thread +#if defined(THREADED_RTS) || defined(PAR) + StgSparkPool rSparks; /* per-task spark pool */ #endif } StgRegTable; - -/* A capability is a combination of a FunTable and a RegTable. In STG - * code, BaseReg normally points to the RegTable portion of this - * structure, so that we can index both forwards and backwards to take - * advantage of shorter instruction forms on some archs (eg. x86). - */ -typedef struct Capability_ { - StgFunTable f; - StgRegTable r; -#if defined(SMP) - struct Capability_ *link; /* per-task register tables are linked together */ -#endif -} Capability; - -/* No such thing as a MainCapability under SMP - each thread must have - * its own Capability. - */ -#ifndef SMP -#if IN_STG_CODE -extern W_ MainCapability[]; -#else -extern DLL_IMPORT_RTS Capability MainCapability; -#endif -#endif - #if IN_STG_CODE /* @@ -159,12 +162,10 @@ extern DLL_IMPORT_RTS Capability MainCapability; #define SAVE_CurrentTSO (BaseReg->rCurrentTSO) #define SAVE_CurrentNursery (BaseReg->rCurrentNursery) #define SAVE_HpAlloc (BaseReg->rHpAlloc) -#if defined(SMP) || defined(PAR) #define SAVE_SparkHd (BaseReg->rSparks.hd) #define SAVE_SparkTl (BaseReg->rSparks.tl) #define SAVE_SparkBase (BaseReg->rSparks.base) #define SAVE_SparkLim (BaseReg->rSparks.lim) -#endif /* We sometimes need to save registers across a C-call, eg. if they * are clobbered in the standard calling convention. We define the @@ -205,105 +206,109 @@ extern DLL_IMPORT_RTS Capability MainCapability; * again for no good reason (on register-poor architectures). */ +/* define NO_REGS to omit register declarations - used in RTS C code + * that needs all the STG definitions but not the global register + * settings. + */ #define GLOBAL_REG_DECL(type,name,reg) register type name REG(reg); -#ifdef REG_R1 +#if defined(REG_R1) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(StgUnion,R1,REG_R1) #else -#define R1 (BaseReg->rR1) +# define R1 (BaseReg->rR1) #endif -#ifdef REG_R2 +#if defined(REG_R2) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(StgUnion,R2,REG_R2) #else -#define R2 (BaseReg->rR2) +# define R2 (BaseReg->rR2) #endif -#ifdef REG_R3 +#if defined(REG_R3) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(StgUnion,R3,REG_R3) #else # define R3 (BaseReg->rR3) #endif -#ifdef REG_R4 +#if defined(REG_R4) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(StgUnion,R4,REG_R4) #else # define R4 (BaseReg->rR4) #endif -#ifdef REG_R5 +#if defined(REG_R5) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(StgUnion,R5,REG_R5) #else # define R5 (BaseReg->rR5) #endif -#ifdef REG_R6 +#if defined(REG_R6) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(StgUnion,R6,REG_R6) #else # define R6 (BaseReg->rR6) #endif -#ifdef REG_R7 +#if defined(REG_R7) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(StgUnion,R7,REG_R7) #else # define R7 (BaseReg->rR7) #endif -#ifdef REG_R8 +#if defined(REG_R8) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(StgUnion,R8,REG_R8) #else # define R8 (BaseReg->rR8) #endif -#ifdef REG_R9 +#if defined(REG_R9) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(StgUnion,R9,REG_R9) #else # define R9 (BaseReg->rR9) #endif -#ifdef REG_R10 +#if defined(REG_R10) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(StgUnion,R10,REG_R10) #else # define R10 (BaseReg->rR10) #endif -#ifdef REG_F1 +#if defined(REG_F1) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(StgFloat,F1,REG_F1) #else #define F1 (BaseReg->rF1) #endif -#ifdef REG_F2 +#if defined(REG_F2) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(StgFloat,F2,REG_F2) #else #define F2 (BaseReg->rF2) #endif -#ifdef REG_F3 +#if defined(REG_F3) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(StgFloat,F3,REG_F3) #else #define F3 (BaseReg->rF3) #endif -#ifdef REG_F4 +#if defined(REG_F4) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(StgFloat,F4,REG_F4) #else #define F4 (BaseReg->rF4) #endif -#ifdef REG_D1 +#if defined(REG_D1) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(StgDouble,D1,REG_D1) #else #define D1 (BaseReg->rD1) #endif -#ifdef REG_D2 +#if defined(REG_D2) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(StgDouble,D2,REG_D2) #else #define D2 (BaseReg->rD2) #endif -#ifdef REG_L1 +#if defined(REG_L1) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(StgWord64,L1,REG_L1) #else #define L1 (BaseReg->rL1) @@ -315,76 +320,105 @@ GLOBAL_REG_DECL(StgWord64,L1,REG_L1) * concurrent Haskell, MainRegTable otherwise). */ -#ifdef REG_Base +/* A capability is a combination of a FunTable and a RegTable. In STG + * code, BaseReg normally points to the RegTable portion of this + * structure, so that we can index both forwards and backwards to take + * advantage of shorter instruction forms on some archs (eg. x86). + * This is a cut-down version of the Capability structure; the full + * version is defined in Capability.h. + */ +struct PartCapability_ { + StgFunTable f; + StgRegTable r; +}; + +/* No such thing as a MainCapability under THREADED_RTS - each thread must have + * its own Capability. + */ +#if IN_STG_CODE && !defined(THREADED_RTS) +extern W_ MainCapability[]; +#endif + +/* + * Assigning to BaseReg (the ASSIGN_BaseReg macro): this happens on + * return from a "safe" foreign call, when the thread might be running + * on a new Capability. Obviously if BaseReg is not a register, then + * we are restricted to a single Capability (this invariant is enforced + * in Capability.c:initCapabilities), and assigning to BaseReg can be omitted. + */ + +#if defined(REG_Base) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(StgRegTable *,BaseReg,REG_Base) +#define ASSIGN_BaseReg(e) (BaseReg = (e)) #else -#ifdef SMP -#error BaseReg must be in a register for SMP +#ifdef THREADED_RTS +#error BaseReg must be in a register for THREADED_RTS #endif -#define BaseReg (&((Capability *)MainCapability)[0].r) +#define BaseReg (&((struct PartCapability_ *)MainCapability)->r) +#define ASSIGN_BaseReg(e) (e) #endif -#ifdef REG_Sp +#if defined(REG_Sp) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(P_,Sp,REG_Sp) #else #define Sp (BaseReg->rSp) #endif -#ifdef REG_SpLim +#if defined(REG_SpLim) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(P_,SpLim,REG_SpLim) #else #define SpLim (BaseReg->rSpLim) #endif -#ifdef REG_Hp +#if defined(REG_Hp) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(P_,Hp,REG_Hp) #else #define Hp (BaseReg->rHp) #endif -#ifdef REG_HpLim +#if defined(REG_HpLim) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(P_,HpLim,REG_HpLim) #else #define HpLim (BaseReg->rHpLim) #endif -#ifdef REG_CurrentTSO +#if defined(REG_CurrentTSO) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(struct _StgTSO *,CurrentTSO,REG_CurrentTSO) #else #define CurrentTSO (BaseReg->rCurrentTSO) #endif -#ifdef REG_CurrentNursery +#if defined(REG_CurrentNursery) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(bdescr *,CurrentNursery,REG_CurrentNursery) #else #define CurrentNursery (BaseReg->rCurrentNursery) #endif -#ifdef REG_HpAlloc +#if defined(REG_HpAlloc) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(bdescr *,HpAlloc,REG_HpAlloc) #else #define HpAlloc (BaseReg->rHpAlloc) #endif -#ifdef REG_SparkHd +#if defined(REG_SparkHd) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(bdescr *,SparkHd,REG_SparkHd) #else #define SparkHd (BaseReg->rSparks.hd) #endif -#ifdef REG_SparkTl +#if defined(REG_SparkTl) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(bdescr *,SparkTl,REG_SparkTl) #else #define SparkTl (BaseReg->rSparks.tl) #endif -#ifdef REG_SparkBase +#if defined(REG_SparkBase) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(bdescr *,SparkBase,REG_SparkBase) #else #define SparkBase (BaseReg->rSparks.base) #endif -#ifdef REG_SparkLim +#if defined(REG_SparkLim) && !defined(NO_GLOBAL_REG_DECLS) GLOBAL_REG_DECL(bdescr *,SparkLim,REG_SparkLim) #else #define SparkLim (BaseReg->rSparks.lim) @@ -596,8 +630,8 @@ GLOBAL_REG_DECL(bdescr *,SparkLim,REG_SparkLim) #endif #ifdef CALLER_SAVES_Base -#ifdef SMP -#error "Can't have caller-saved BaseReg with SMP" +#ifdef THREADED_RTS +#error "Can't have caller-saved BaseReg with THREADED_RTS" #endif #define CALLER_SAVE_Base /* nothing */ #define CALLER_RESTORE_Base BaseReg = &MainRegTable;