+// An alternate version of newCaf which is used for dynamically loaded
+// object code in GHCi. In this case we want to retain *all* CAFs in
+// the object code, because they might be demanded at any time from an
+// expression evaluated on the command line.
+// Also, GHCi might want to revert CAFs, so we add these to the
+// revertible_caf_list.
+//
+// The linker hackily arranges that references to newCaf from dynamic
+// code end up pointing to newDynCAF.
+void
+newDynCAF(StgClosure *caf)
+{
+ ACQUIRE_SM_LOCK;
+
+ ((StgIndStatic *)caf)->saved_info = (StgInfoTable *)caf->header.info;
+ ((StgIndStatic *)caf)->static_link = revertible_caf_list;
+ revertible_caf_list = caf;
+
+ RELEASE_SM_LOCK;
+}
+
+/* -----------------------------------------------------------------------------
+ Nursery management.
+ -------------------------------------------------------------------------- */
+
+static bdescr *
+allocNursery (step *stp, bdescr *tail, nat blocks)
+{
+ bdescr *bd;
+ nat i;
+
+ // Allocate a nursery: we allocate fresh blocks one at a time and
+ // cons them on to the front of the list, not forgetting to update
+ // the back pointer on the tail of the list to point to the new block.
+ for (i=0; i < blocks; i++) {
+ // @LDV profiling
+ /*
+ processNursery() in LdvProfile.c assumes that every block group in
+ the nursery contains only a single block. So, if a block group is
+ given multiple blocks, change processNursery() accordingly.
+ */
+ bd = allocBlock();
+ bd->link = tail;
+ // double-link the nursery: we might need to insert blocks
+ if (tail != NULL) {
+ tail->u.back = bd;
+ }
+ bd->step = stp;
+ bd->gen_no = 0;
+ bd->flags = 0;
+ bd->free = bd->start;
+ tail = bd;
+ }
+ tail->u.back = NULL;
+ return tail;
+}
+
+static void
+assignNurseriesToCapabilities (void)
+{
+#ifdef SMP
+ nat i;
+
+ for (i = 0; i < n_nurseries; i++) {
+ capabilities[i].r.rNursery = &nurseries[i];
+ capabilities[i].r.rCurrentNursery = nurseries[i].blocks;
+ capabilities[i].r.rCurrentAlloc = NULL;
+ }
+#else /* SMP */
+ MainCapability.r.rNursery = &nurseries[0];
+ MainCapability.r.rCurrentNursery = nurseries[0].blocks;
+ MainCapability.r.rCurrentAlloc = NULL;
+#endif
+}
+
+void
+allocNurseries( void )
+{
+ nat i;
+
+ for (i = 0; i < n_nurseries; i++) {
+ nurseries[i].blocks =
+ allocNursery(&nurseries[i], NULL,
+ RtsFlags.GcFlags.minAllocAreaSize);
+ nurseries[i].n_blocks = RtsFlags.GcFlags.minAllocAreaSize;
+ nurseries[i].old_blocks = NULL;
+ nurseries[i].n_old_blocks = 0;
+ /* hp, hpLim, hp_bd, to_space etc. aren't used in the nursery */
+ }
+ assignNurseriesToCapabilities();
+}
+
+void
+resetNurseries( void )
+{
+ nat i;
+ bdescr *bd;
+ step *stp;
+
+ for (i = 0; i < n_nurseries; i++) {
+ stp = &nurseries[i];
+ for (bd = stp->blocks; bd; bd = bd->link) {
+ bd->free = bd->start;
+ ASSERT(bd->gen_no == 0);
+ ASSERT(bd->step == stp);
+ IF_DEBUG(sanity,memset(bd->start, 0xaa, BLOCK_SIZE));
+ }
+ }
+ assignNurseriesToCapabilities();
+}
+
+lnat
+countNurseryBlocks (void)
+{
+ nat i;
+ lnat blocks = 0;
+
+ for (i = 0; i < n_nurseries; i++) {
+ blocks += nurseries[i].n_blocks;
+ }
+ return blocks;
+}
+
+static void
+resizeNursery ( step *stp, nat blocks )