summaryrefslogtreecommitdiff
path: root/rts/PrimOps.cmm
diff options
context:
space:
mode:
authorHerbert Valerio Riedel <hvr@gnu.org>2017-10-16 21:01:57 +0200
committerHerbert Valerio Riedel <hvr@gnu.org>2017-10-16 21:09:06 +0200
commite3ba26f8b49700b41ff4672f3f7f6a4e453acdcc (patch)
tree26880006ca2615143f18349dcf892aa25e3fe29b /rts/PrimOps.cmm
parentadd85cc2a3ec0bda810dca2a35264308ffaab069 (diff)
downloadhaskell-e3ba26f8b49700b41ff4672f3f7f6a4e453acdcc.tar.gz
Implement new `compareByteArrays#` primop
The new primop compareByteArrays# :: ByteArray# -> Int# {- offset -} -> ByteArray# -> Int# {- offset -} -> Int# {- length -} -> Int# allows to compare the subrange of the first `ByteArray#` to the (same-length) subrange of the second `ByteArray#` and returns a value less than, equal to, or greater than zero if the range is found, respectively, to be byte-wise lexicographically less than, to match, or be greater than the second range. Under the hood, the new primop is implemented in terms of the standard ISO C `memcmp(3)` function. It is currently an out-of-line primop but work is underway to optimise this into an inline primop for a future follow-up Differential (see D4091). This primop has applications in packages like `text`, `text-short`, `bytestring`, `text-containers`, `primitive`, etc. which currently have to incur the overhead of an ordinary FFI call to directly or indirectly invoke `memcmp(3)` as well has having to deal with some `unsafePerformIO`-variant. While at it, this also improves the documentation for the existing `copyByteArray#` primitive which has a non-trivial type-signature that significantly benefits from a more explicit description of its arguments. Reviewed By: bgamari Differential Revision: https://phabricator.haskell.org/D4090
Diffstat (limited to 'rts/PrimOps.cmm')
-rw-r--r--rts/PrimOps.cmm14
1 files changed, 14 insertions, 0 deletions
diff --git a/rts/PrimOps.cmm b/rts/PrimOps.cmm
index b43dfbf554..bcf7b62fb7 100644
--- a/rts/PrimOps.cmm
+++ b/rts/PrimOps.cmm
@@ -151,6 +151,20 @@ stg_newAlignedPinnedByteArrayzh ( W_ n, W_ alignment )
return (p);
}
+stg_compareByteArrayszh ( gcptr src1, W_ src1_ofs, gcptr src2, W_ src2_ofs, W_ size )
+// ByteArray# -> Int# -> ByteArray# -> Int# -> Int# -> Int#
+{
+ CInt res;
+ W_ src1p, src2p;
+
+ src1p = src1 + SIZEOF_StgHeader + OFFSET_StgArrBytes_payload + src1_ofs;
+ src2p = src2 + SIZEOF_StgHeader + OFFSET_StgArrBytes_payload + src2_ofs;
+
+ (res) = ccall memcmp(src1p "ptr", src2p "ptr", size);
+
+ return (TO_W_(res));
+}
+
stg_isByteArrayPinnedzh ( gcptr ba )
// ByteArray# s -> Int#
{