summaryrefslogtreecommitdiff
path: root/rts/PrimOps.cmm
diff options
context:
space:
mode:
authorGiovanni Campagna <gcampagn@cs.stanford.edu>2016-07-15 19:47:26 +0100
committerSimon Marlow <marlowsd@gmail.com>2016-07-20 16:35:23 +0100
commitcf989ffe490c146be4ed0fd7e0c00d3ff8fe1453 (patch)
tree1bdf626d6e713506852bf0015dae1e1be7d280c0 /rts/PrimOps.cmm
parent93acc02f7db7eb86967b4ec586359f408d62f75d (diff)
downloadhaskell-cf989ffe490c146be4ed0fd7e0c00d3ff8fe1453.tar.gz
Compact Regions
This brings in initial support for compact regions, as described in the ICFP 2015 paper "Efficient Communication and Collection with Compact Normal Forms" (Edward Z. Yang et.al.) and implemented by Giovanni Campagna. Some things may change before the 8.2 release, but I (Simon M.) wanted to get the main patch committed so that we can iterate. What documentation there is is in the Data.Compact module in the new compact package. We'll need to extend and polish the documentation before the release. Test Plan: validate (new test cases included) Reviewers: ezyang, simonmar, hvr, bgamari, austin Subscribers: vikraman, Yuras, RyanGlScott, qnikst, mboes, facundominguez, rrnewton, thomie, erikd Differential Revision: https://phabricator.haskell.org/D1264 GHC Trac Issues: #11493
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
------------------------------------------------------------------------- */