summaryrefslogtreecommitdiff
path: root/rts/PrimOps.cmm
diff options
context:
space:
mode:
Diffstat (limited to 'rts/PrimOps.cmm')
-rw-r--r--rts/PrimOps.cmm131
1 files changed, 131 insertions, 0 deletions
diff --git a/rts/PrimOps.cmm b/rts/PrimOps.cmm
index b82eebe07f..60d8106983 100644
--- a/rts/PrimOps.cmm
+++ b/rts/PrimOps.cmm
@@ -1917,6 +1917,137 @@ stg_deRefStablePtrzh ( P_ sp )
}
/* -----------------------------------------------------------------------------
+ CompactNFData primitives
+
+ See Note [Compact Normal Forms]
+ ------------------------------------------------------------------------- */
+
+stg_compactNewzh ( W_ size )
+{
+ P_ str;
+
+ again: MAYBE_GC(again);
+
+ ("ptr" str) = ccall compactNew(MyCapability() "ptr", size);
+ return (str);
+}
+
+stg_compactAppendzh ( P_ str, P_ val , W_ share)
+{
+ P_ root;
+
+ again: MAYBE_GC(again);
+
+ ("ptr" root) = ccall compactAppend(MyCapability() "ptr", str "ptr", val "ptr", share);
+ return (root);
+}
+
+stg_compactResizzezh ( P_ str, W_ new_size )
+{
+ again: MAYBE_GC(again);
+
+ ccall compactResize(MyCapability() "ptr", str "ptr", new_size);
+ return ();
+}
+
+stg_compactContainszh ( P_ str, P_ val )
+{
+ W_ rval;
+
+ (rval) = ccall compactContains(str "ptr", val "ptr");
+ return (rval);
+}
+
+stg_compactContainsAnyzh ( P_ val )
+{
+ W_ rval;
+
+ (rval) = ccall compactContains(0 "ptr", val "ptr");
+ return (rval);
+}
+
+stg_compactGetFirstBlockzh ( P_ str )
+{
+ /* W_, not P_, because it is not a gc pointer */
+ W_ block;
+ W_ bd;
+ W_ size;
+
+ block = str - SIZEOF_StgCompactNFDataBlock::W_;
+ ASSERT (StgCompactNFDataBlock_owner(block) == str);
+
+ bd = Bdescr(str);
+ size = bdescr_free(bd) - bdescr_start(bd);
+ ASSERT (size <= TO_W_(bdescr_blocks(bd)) * BLOCK_SIZE);
+
+ return (block, size);
+}
+
+stg_compactGetNextBlockzh ( P_ str, W_ block )
+{
+ /* str is a pointer to the closure holding the Compact#
+ it is there primarily to keep everything reachable from
+ the GC: by having it on the stack of type P_, the GC will
+ see all the blocks as live (any pointer in the Compact#
+ keeps it alive), and will not collect the block
+ We don't run a GC inside this primop, but it could
+ happen right after, or we could be preempted.
+
+ str is also useful for debugging, as it can be casted
+ to a useful C struct from the gdb command line and all
+ blocks can be inspected
+ */
+ W_ bd;
+ W_ next_block;
+ W_ size;
+
+ next_block = StgCompactNFDataBlock_next(block);
+
+ if (next_block == 0::W_) {
+ return (0::W_, 0::W_);
+ }
+
+ ASSERT (StgCompactNFDataBlock_owner(next_block) == str ||
+ StgCompactNFDataBlock_owner(next_block) == NULL);
+
+ bd = Bdescr(next_block);
+ size = bdescr_free(bd) - bdescr_start(bd);
+ ASSERT (size <= TO_W_(bdescr_blocks(bd)) * BLOCK_SIZE);
+
+ return (next_block, size);
+}
+
+stg_compactAllocateBlockzh ( W_ size, W_ previous )
+{
+ W_ actual_block;
+
+ again: MAYBE_GC(again);
+
+ ("ptr" actual_block) = ccall compactAllocateBlock(MyCapability(),
+ size,
+ previous "ptr");
+
+ return (actual_block);
+}
+
+stg_compactFixupPointerszh ( W_ first_block, W_ root )
+{
+ W_ str;
+ P_ gcstr;
+ W_ ok;
+
+ str = first_block + SIZEOF_StgCompactNFDataBlock::W_;
+ (ok) = ccall compactFixupPointers (str "ptr", root "ptr");
+
+ // Now we can let the GC know about str, because it was linked
+ // into the generation list and the book-keeping pointers are
+ // guaranteed to be valid
+ // (this is true even if the fixup phase failed)
+ gcstr = str;
+ return (gcstr, ok);
+}
+
+/* -----------------------------------------------------------------------------
Bytecode object primitives
------------------------------------------------------------------------- */