diff options
Diffstat (limited to 'rts/PrimOps.cmm')
-rw-r--r-- | rts/PrimOps.cmm | 131 |
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 ------------------------------------------------------------------------- */ |