<commit_before>/* -----------------------------------------------------------------------------
 * $Id: Updates.h,v 1.12 1999/08/25 16:11:44 simonmar Exp $
 *
 * (c) The GHC Team, 1998-1999
 *
 * Definitions related to updates.
 *
 * ---------------------------------------------------------------------------*/

#ifndef UPDATES_H
#define UPDATES_H

/* -----------------------------------------------------------------------------
   Update a closure with an indirection.  This may also involve waking
   up a queue of blocked threads waiting on the result of this
   computation.
   -------------------------------------------------------------------------- */

/* ToDo: overwrite slop words with something safe in case sanity checking 
 *       is turned on.  
 *       (I think the fancy version of the GC is supposed to do this too.)
 */

/* This expands to a fair chunk of code, what with waking up threads 
 * and checking whether we're updating something in a old generation.
 * preferably don't use this macro inline in compiled code.
 */

#ifdef TICKY_TICKY
# define UPD_IND(updclosure, heapptr) UPD_PERM_IND(updclosure,heapptr)
#else
# define UPD_IND(updclosure, heapptr) UPD_REAL_IND(updclosure,heapptr)
#endif

/* UPD_IND actually does a PERM_IND if TICKY_TICKY is on;
   if you *really* need an IND use UPD_REAL_IND
 */
#define UPD_REAL_IND(updclosure, heapptr)                       \
        AWAKEN_BQ(updclosure);                                  \
	updateWithIndirection((StgClosure *)updclosure,         \
			      (StgClosure *)heapptr);

#if defined(PROFILING) || defined(TICKY_TICKY)
#define UPD_PERM_IND(updclosure, heapptr)                       \
        AWAKEN_BQ(updclosure);                                  \
	updateWithPermIndirection((StgClosure *)updclosure,     \
			          (StgClosure *)heapptr);
#endif

/* -----------------------------------------------------------------------------
   Awaken any threads waiting on this computation
   -------------------------------------------------------------------------- */

extern void awakenBlockedQueue(StgTSO *q);

#define AWAKEN_BQ(closure)						\
     	if (closure->header.info == &BLACKHOLE_BQ_info) {		\
		StgTSO *bq = ((StgBlockingQueue *)closure)->blocking_queue;\
		if (bq != (StgTSO *)&END_TSO_QUEUE_closure) {		\
			STGCALL1(awakenBlockedQueue, bq);		\
		}							\
	}


/* -----------------------------------------------------------------------------
   Push an update frame on the stack.
   -------------------------------------------------------------------------- */

#if defined(PROFILING)
#define PUSH_STD_CCCS(frame) frame->header.prof.ccs = CCCS
#else
#define PUSH_STD_CCCS(frame)
#endif

extern DLL_IMPORT_DATA const StgPolyInfoTable Upd_frame_info; 

#define PUSH_UPD_FRAME(target, Sp_offset)			\
	{							\
		StgUpdateFrame *__frame;			\
		TICK_UPDF_PUSHED(target, GET_INFO((StgClosure*)target)); \
		__frame = stgCast(StgUpdateFrame*,Sp + (Sp_offset)) - 1; \
		SET_INFO(__frame,stgCast(StgInfoTable*,&Upd_frame_info));   \
		__frame->link = Su;				\
		__frame->updatee = (StgClosure *)(target);	\
		PUSH_STD_CCCS(__frame);				\
		Su = __frame;					\
	}

/* -----------------------------------------------------------------------------
   Entering CAFs

   When a CAF is first entered, it creates a black hole in the heap,
   and updates itself with an indirection to this new black hole.

   We update the CAF with an indirection to a newly-allocated black
   hole in the heap.  We also set the blocking queue on the newly
   allocated black hole to be empty.

   Why do we make a black hole in the heap when we enter a CAF?
      
       - for a  generational garbage collector, which needs a fast
         test for whether an updatee is in an old generation or not

       - for the parallel system, which can implement updates more
         easily if the updatee is always in the heap. (allegedly).

   When debugging, we maintain a separate CAF list so we can tell when
   a CAF has been garbage collected.
   -------------------------------------------------------------------------- */<commit_msg>[project @ 1999-10-20 10:14:47 by simonmar] Micro-optimisation: don't need to test for an empty queue in a BLACKHOLE_BQ, now that we're distinguishing BLACKHOLE and BLACKHOLE_BQ.  Shortens the update code by a couple of instructions.<commit_after>/* -----------------------------------------------------------------------------
 * $Id: Updates.h,v 1.13 1999/10/20 10:14:47 simonmar Exp $
 *
 * (c) The GHC Team, 1998-1999
 *
 * Definitions related to updates.
 *
 * ---------------------------------------------------------------------------*/

#ifndef UPDATES_H
#define UPDATES_H

/* -----------------------------------------------------------------------------
   Update a closure with an indirection.  This may also involve waking
   up a queue of blocked threads waiting on the result of this
   computation.
   -------------------------------------------------------------------------- */

/* ToDo: overwrite slop words with something safe in case sanity checking 
 *       is turned on.  
 *       (I think the fancy version of the GC is supposed to do this too.)
 */

/* This expands to a fair chunk of code, what with waking up threads 
 * and checking whether we're updating something in a old generation.
 * preferably don't use this macro inline in compiled code.
 */

#ifdef TICKY_TICKY
# define UPD_IND(updclosure, heapptr) UPD_PERM_IND(updclosure,heapptr)
#else
# define UPD_IND(updclosure, heapptr) UPD_REAL_IND(updclosure,heapptr)
#endif

/* UPD_IND actually does a PERM_IND if TICKY_TICKY is on;
   if you *really* need an IND use UPD_REAL_IND
 */
#define UPD_REAL_IND(updclosure, heapptr)                       \
        AWAKEN_BQ(updclosure);                                  \
	updateWithIndirection((StgClosure *)updclosure,         \
			      (StgClosure *)heapptr);

#if defined(PROFILING) || defined(TICKY_TICKY)
#define UPD_PERM_IND(updclosure, heapptr)                       \
        AWAKEN_BQ(updclosure);                                  \
	updateWithPermIndirection((StgClosure *)updclosure,     \
			          (StgClosure *)heapptr);
#endif

/* -----------------------------------------------------------------------------
   Awaken any threads waiting on this computation
   -------------------------------------------------------------------------- */

extern void awakenBlockedQueue(StgTSO *q);

#define AWAKEN_BQ(closure)						 \
     	if (closure->header.info == &BLACKHOLE_BQ_info) {		 \
		STGCALL1(awakenBlockedQueue, 				 \
			 ((StgBlockingQueue *)closure)->blocking_queue); \
	}


/* -----------------------------------------------------------------------------
   Push an update frame on the stack.
   -------------------------------------------------------------------------- */

#if defined(PROFILING)
#define PUSH_STD_CCCS(frame) frame->header.prof.ccs = CCCS
#else
#define PUSH_STD_CCCS(frame)
#endif

extern DLL_IMPORT_DATA const StgPolyInfoTable Upd_frame_info; 

#define PUSH_UPD_FRAME(target, Sp_offset)			\
	{							\
		StgUpdateFrame *__frame;			\
		TICK_UPDF_PUSHED(target, GET_INFO((StgClosure*)target)); \
		__frame = (StgUpdateFrame *)(Sp + (Sp_offset)) - 1; \
		SET_INFO(__frame, (StgInfoTable *)&Upd_frame_info);   \
		__frame->link = Su;				\
		__frame->updatee = (StgClosure *)(target);	\
		PUSH_STD_CCCS(__frame);				\
		Su = __frame;					\
	}

/* -----------------------------------------------------------------------------
   Entering CAFs

   When a CAF is first entered, it creates a black hole in the heap,
   and updates itself with an indirection to this new black hole.

   We update the CAF with an indirection to a newly-allocated black
   hole in the heap.  We also set the blocking queue on the newly
   allocated black hole to be empty.

   Why do we make a black hole in the heap when we enter a CAF?
      
       - for a  generational garbage collector, which needs a fast
         test for whether an updatee is in an old generation or not

       - for the parallel system, which can implement updates more
         easily if the updatee is always in the heap. (allegedly).

   When debugging, we maintain a separate CAF list so we can tell when
   a CAF has been garbage collected.
   -------------------------------------------------------------------------- */
{'fraction_non_alphanumeric': 0.25020960594083125, 'fraction_numerical': 0.00814468798658522, 'mean_word_length': 1.5295365040896698, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6681181', 'n_tokens_mistral': 2503, 'n_tokens_neox': 2289, 'n_words': 734}