summaryrefslogtreecommitdiff
path: root/compiler/prelude
diff options
context:
space:
mode:
authorJohan Tibell <johan.tibell@gmail.com>2014-03-23 12:06:56 +0100
committerJohan Tibell <johan.tibell@gmail.com>2014-03-29 11:24:07 +0100
commit90329b6cc183b3cd05956ae6bdeb6ac6951549c2 (patch)
treeba7d31656fe75fad2555c8a66b7ebd13dd9ebeb1 /compiler/prelude
parent4c8edfd2c722504baaa6896d194fd3a8c3f9b652 (diff)
downloadhaskell-90329b6cc183b3cd05956ae6bdeb6ac6951549c2.tar.gz
Add SmallArray# and SmallMutableArray# types
These array types are smaller than Array# and MutableArray# and are faster when the array size is small, as they don't have the overhead of a card table. Having no card table reduces the closure size with 2 words in the typical small array case and leads to less work when updating or GC:ing the array. Reduces both the runtime and memory allocation by 8.8% on my insert benchmark for the HashMap type in the unordered-containers package, which makes use of lots of small arrays. With tuned GC settings (i.e. `+RTS -A6M`) the runtime reduction is 15%. Fixes #8923.
Diffstat (limited to 'compiler/prelude')
-rw-r--r--compiler/prelude/PrelNames.lhs6
-rw-r--r--compiler/prelude/TysPrim.lhs17
-rw-r--r--compiler/prelude/primops.txt.pp156
3 files changed, 172 insertions, 7 deletions
diff --git a/compiler/prelude/PrelNames.lhs b/compiler/prelude/PrelNames.lhs
index 0512607109..86f8d29229 100644
--- a/compiler/prelude/PrelNames.lhs
+++ b/compiler/prelude/PrelNames.lhs
@@ -1304,7 +1304,8 @@ addrPrimTyConKey, arrayPrimTyConKey, arrayArrayPrimTyConKey, boolTyConKey, byteA
mutableArrayPrimTyConKey, mutableArrayArrayPrimTyConKey, mutableByteArrayPrimTyConKey,
orderingTyConKey, mVarPrimTyConKey, ratioTyConKey, rationalTyConKey,
realWorldTyConKey, stablePtrPrimTyConKey, stablePtrTyConKey,
- anyTyConKey, eqTyConKey :: Unique
+ anyTyConKey, eqTyConKey, smallArrayPrimTyConKey,
+ smallMutableArrayPrimTyConKey :: Unique
addrPrimTyConKey = mkPreludeTyConUnique 1
arrayPrimTyConKey = mkPreludeTyConUnique 3
boolTyConKey = mkPreludeTyConUnique 4
@@ -1494,6 +1495,9 @@ proxyPrimTyConKey = mkPreludeTyConUnique 176
specTyConKey :: Unique
specTyConKey = mkPreludeTyConUnique 177
+smallArrayPrimTyConKey = mkPreludeTyConUnique 178
+smallMutableArrayPrimTyConKey = mkPreludeTyConUnique 179
+
---------------- Template Haskell -------------------
-- USES TyConUniques 200-299
-----------------------------------------------------
diff --git a/compiler/prelude/TysPrim.lhs b/compiler/prelude/TysPrim.lhs
index bbe5aba119..789d121519 100644
--- a/compiler/prelude/TysPrim.lhs
+++ b/compiler/prelude/TysPrim.lhs
@@ -54,9 +54,11 @@ module TysPrim(
arrayPrimTyCon, mkArrayPrimTy,
byteArrayPrimTyCon, byteArrayPrimTy,
arrayArrayPrimTyCon, mkArrayArrayPrimTy,
+ smallArrayPrimTyCon, mkSmallArrayPrimTy,
mutableArrayPrimTyCon, mkMutableArrayPrimTy,
mutableByteArrayPrimTyCon, mkMutableByteArrayPrimTy,
mutableArrayArrayPrimTyCon, mkMutableArrayArrayPrimTy,
+ smallMutableArrayPrimTyCon, mkSmallMutableArrayPrimTy,
mutVarPrimTyCon, mkMutVarPrimTy,
mVarPrimTyCon, mkMVarPrimTy,
@@ -111,6 +113,7 @@ primTyCons
, arrayPrimTyCon
, byteArrayPrimTyCon
, arrayArrayPrimTyCon
+ , smallArrayPrimTyCon
, charPrimTyCon
, doublePrimTyCon
, floatPrimTyCon
@@ -122,6 +125,7 @@ primTyCons
, mutableArrayPrimTyCon
, mutableByteArrayPrimTyCon
, mutableArrayArrayPrimTyCon
+ , smallMutableArrayPrimTyCon
, mVarPrimTyCon
, tVarPrimTyCon
, mutVarPrimTyCon
@@ -156,7 +160,7 @@ mkPrimTc fs unique tycon
(ATyCon tycon) -- Relevant TyCon
UserSyntax -- None are built-in syntax
-charPrimTyConName, intPrimTyConName, int32PrimTyConName, int64PrimTyConName, wordPrimTyConName, word32PrimTyConName, word64PrimTyConName, addrPrimTyConName, floatPrimTyConName, doublePrimTyConName, statePrimTyConName, proxyPrimTyConName, realWorldTyConName, arrayPrimTyConName, arrayArrayPrimTyConName, byteArrayPrimTyConName, mutableArrayPrimTyConName, mutableByteArrayPrimTyConName, mutableArrayArrayPrimTyConName, mutVarPrimTyConName, mVarPrimTyConName, tVarPrimTyConName, stablePtrPrimTyConName, stableNamePrimTyConName, bcoPrimTyConName, weakPrimTyConName, threadIdPrimTyConName, eqPrimTyConName, eqReprPrimTyConName, voidPrimTyConName :: Name
+charPrimTyConName, intPrimTyConName, int32PrimTyConName, int64PrimTyConName, wordPrimTyConName, word32PrimTyConName, word64PrimTyConName, addrPrimTyConName, floatPrimTyConName, doublePrimTyConName, statePrimTyConName, proxyPrimTyConName, realWorldTyConName, arrayPrimTyConName, arrayArrayPrimTyConName, smallArrayPrimTyConName, byteArrayPrimTyConName, mutableArrayPrimTyConName, mutableByteArrayPrimTyConName, mutableArrayArrayPrimTyConName, smallMutableArrayPrimTyConName, mutVarPrimTyConName, mVarPrimTyConName, tVarPrimTyConName, stablePtrPrimTyConName, stableNamePrimTyConName, bcoPrimTyConName, weakPrimTyConName, threadIdPrimTyConName, eqPrimTyConName, eqReprPrimTyConName, voidPrimTyConName :: Name
charPrimTyConName = mkPrimTc (fsLit "Char#") charPrimTyConKey charPrimTyCon
intPrimTyConName = mkPrimTc (fsLit "Int#") intPrimTyConKey intPrimTyCon
int32PrimTyConName = mkPrimTc (fsLit "Int32#") int32PrimTyConKey int32PrimTyCon
@@ -176,9 +180,11 @@ realWorldTyConName = mkPrimTc (fsLit "RealWorld") realWorldTyConKey r
arrayPrimTyConName = mkPrimTc (fsLit "Array#") arrayPrimTyConKey arrayPrimTyCon
byteArrayPrimTyConName = mkPrimTc (fsLit "ByteArray#") byteArrayPrimTyConKey byteArrayPrimTyCon
arrayArrayPrimTyConName = mkPrimTc (fsLit "ArrayArray#") arrayArrayPrimTyConKey arrayArrayPrimTyCon
+smallArrayPrimTyConName = mkPrimTc (fsLit "SmallArray#") smallArrayPrimTyConKey smallArrayPrimTyCon
mutableArrayPrimTyConName = mkPrimTc (fsLit "MutableArray#") mutableArrayPrimTyConKey mutableArrayPrimTyCon
mutableByteArrayPrimTyConName = mkPrimTc (fsLit "MutableByteArray#") mutableByteArrayPrimTyConKey mutableByteArrayPrimTyCon
mutableArrayArrayPrimTyConName= mkPrimTc (fsLit "MutableArrayArray#") mutableArrayArrayPrimTyConKey mutableArrayArrayPrimTyCon
+smallMutableArrayPrimTyConName= mkPrimTc (fsLit "SmallMutableArray#") smallMutableArrayPrimTyConKey smallMutableArrayPrimTyCon
mutVarPrimTyConName = mkPrimTc (fsLit "MutVar#") mutVarPrimTyConKey mutVarPrimTyCon
mVarPrimTyConName = mkPrimTc (fsLit "MVar#") mVarPrimTyConKey mVarPrimTyCon
tVarPrimTyConName = mkPrimTc (fsLit "TVar#") tVarPrimTyConKey tVarPrimTyCon
@@ -538,13 +544,16 @@ defined in \tr{TysWiredIn.lhs}, not here.
\begin{code}
arrayPrimTyCon, mutableArrayPrimTyCon, mutableByteArrayPrimTyCon,
- byteArrayPrimTyCon, arrayArrayPrimTyCon, mutableArrayArrayPrimTyCon :: TyCon
+ byteArrayPrimTyCon, arrayArrayPrimTyCon, mutableArrayArrayPrimTyCon,
+ smallArrayPrimTyCon, smallMutableArrayPrimTyCon :: TyCon
arrayPrimTyCon = pcPrimTyCon arrayPrimTyConName [Representational] PtrRep
mutableArrayPrimTyCon = pcPrimTyCon mutableArrayPrimTyConName [Nominal, Representational] PtrRep
mutableByteArrayPrimTyCon = pcPrimTyCon mutableByteArrayPrimTyConName [Nominal] PtrRep
byteArrayPrimTyCon = pcPrimTyCon0 byteArrayPrimTyConName PtrRep
arrayArrayPrimTyCon = pcPrimTyCon0 arrayArrayPrimTyConName PtrRep
mutableArrayArrayPrimTyCon = pcPrimTyCon mutableArrayArrayPrimTyConName [Nominal] PtrRep
+smallArrayPrimTyCon = pcPrimTyCon smallArrayPrimTyConName [Representational] PtrRep
+smallMutableArrayPrimTyCon = pcPrimTyCon smallMutableArrayPrimTyConName [Nominal, Representational] PtrRep
mkArrayPrimTy :: Type -> Type
mkArrayPrimTy elt = TyConApp arrayPrimTyCon [elt]
@@ -552,12 +561,16 @@ byteArrayPrimTy :: Type
byteArrayPrimTy = mkTyConTy byteArrayPrimTyCon
mkArrayArrayPrimTy :: Type
mkArrayArrayPrimTy = mkTyConTy arrayArrayPrimTyCon
+mkSmallArrayPrimTy :: Type -> Type
+mkSmallArrayPrimTy elt = TyConApp smallArrayPrimTyCon [elt]
mkMutableArrayPrimTy :: Type -> Type -> Type
mkMutableArrayPrimTy s elt = TyConApp mutableArrayPrimTyCon [s, elt]
mkMutableByteArrayPrimTy :: Type -> Type
mkMutableByteArrayPrimTy s = TyConApp mutableByteArrayPrimTyCon [s]
mkMutableArrayArrayPrimTy :: Type -> Type
mkMutableArrayArrayPrimTy s = TyConApp mutableArrayArrayPrimTyCon [s]
+mkSmallMutableArrayPrimTy :: Type -> Type -> Type
+mkSmallMutableArrayPrimTy s elt = TyConApp smallMutableArrayPrimTyCon [s, elt]
\end{code}
%************************************************************************
diff --git a/compiler/prelude/primops.txt.pp b/compiler/prelude/primops.txt.pp
index 553163b0af..10dd19d4bb 100644
--- a/compiler/prelude/primops.txt.pp
+++ b/compiler/prelude/primops.txt.pp
@@ -796,7 +796,7 @@ primop CloneArrayOp "cloneArray#" GenPrimOp
with
out_of_line = True
has_side_effects = True
- code_size = { primOpCodeSizeForeignCall + 4 }
+ can_fail = True
primop CloneMutableArrayOp "cloneMutableArray#" GenPrimOp
MutableArray# s a -> Int# -> Int# -> State# s -> (# State# s, MutableArray# s a #)
@@ -807,7 +807,7 @@ primop CloneMutableArrayOp "cloneMutableArray#" GenPrimOp
with
out_of_line = True
has_side_effects = True
- code_size = { primOpCodeSizeForeignCall + 4 }
+ can_fail = True
primop FreezeArrayOp "freezeArray#" GenPrimOp
MutableArray# s a -> Int# -> Int# -> State# s -> (# State# s, Array# a #)
@@ -818,7 +818,7 @@ primop FreezeArrayOp "freezeArray#" GenPrimOp
with
out_of_line = True
has_side_effects = True
- code_size = { primOpCodeSizeForeignCall + 4 }
+ can_fail = True
primop ThawArrayOp "thawArray#" GenPrimOp
Array# a -> Int# -> Int# -> State# s -> (# State# s, MutableArray# s a #)
@@ -829,7 +829,7 @@ primop ThawArrayOp "thawArray#" GenPrimOp
with
out_of_line = True
has_side_effects = True
- code_size = { primOpCodeSizeForeignCall + 4 }
+ can_fail = True
primop CasArrayOp "casArray#" GenPrimOp
MutableArray# s a -> Int# -> a -> a -> State# s -> (# State# s, Int#, a #)
@@ -840,6 +840,154 @@ primop CasArrayOp "casArray#" GenPrimOp
------------------------------------------------------------------------
+section "Small Arrays"
+
+ {Operations on {\tt SmallArray\#}. A {\tt SmallArray\#} works
+ just like an {\tt Array\#}, except that its implementation is
+ optimized for small arrays (i.e. no more than 128 elements.)}
+
+------------------------------------------------------------------------
+
+primtype SmallArray# a
+
+primtype SmallMutableArray# s a
+
+primop NewSmallArrayOp "newSmallArray#" GenPrimOp
+ Int# -> a -> State# s -> (# State# s, SmallMutableArray# s a #)
+ {Create a new mutable array with the specified number of elements,
+ in the specified state thread,
+ with each element containing the specified initial value.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop SameSmallMutableArrayOp "sameSmallMutableArray#" GenPrimOp
+ SmallMutableArray# s a -> SmallMutableArray# s a -> Int#
+
+primop ReadSmallArrayOp "readSmallArray#" GenPrimOp
+ SmallMutableArray# s a -> Int# -> State# s -> (# State# s, a #)
+ {Read from specified index of mutable array. Result is not yet evaluated.}
+ with
+ has_side_effects = True
+ can_fail = True
+
+primop WriteSmallArrayOp "writeSmallArray#" GenPrimOp
+ SmallMutableArray# s a -> Int# -> a -> State# s -> State# s
+ {Write to specified index of mutable array.}
+ with
+ has_side_effects = True
+ can_fail = True
+
+primop SizeofSmallArrayOp "sizeofSmallArray#" GenPrimOp
+ SmallArray# a -> Int#
+ {Return the number of elements in the array.}
+
+primop SizeofSmallMutableArrayOp "sizeofSmallMutableArray#" GenPrimOp
+ SmallMutableArray# s a -> Int#
+ {Return the number of elements in the array.}
+
+primop IndexSmallArrayOp "indexSmallArray#" GenPrimOp
+ SmallArray# a -> Int# -> (# a #)
+ {Read from specified index of immutable array. Result is packaged into
+ an unboxed singleton; the result itself is not yet evaluated.}
+ with
+ can_fail = True
+
+primop UnsafeFreezeSmallArrayOp "unsafeFreezeSmallArray#" GenPrimOp
+ SmallMutableArray# s a -> State# s -> (# State# s, SmallArray# a #)
+ {Make a mutable array immutable, without copying.}
+ with
+ has_side_effects = True
+
+primop UnsafeThawSmallArrayOp "unsafeThawSmallArray#" GenPrimOp
+ SmallArray# a -> State# s -> (# State# s, SmallMutableArray# s a #)
+ {Make an immutable array mutable, without copying.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+-- The code_size is only correct for the case when the copy family of
+-- primops aren't inlined. It would be nice to keep track of both.
+
+primop CopySmallArrayOp "copySmallArray#" GenPrimOp
+ SmallArray# a -> Int# -> SmallMutableArray# s a -> Int# -> Int# -> State# s -> State# s
+ {Given a source array, an offset into the source array, a
+ destination array, an offset into the destination array, and a
+ number of elements to copy, copy the elements from the source array
+ to the destination array. Both arrays must fully contain the
+ specified ranges, but this is not checked. The two arrays must not
+ be the same array in different states, but this is not checked
+ either.}
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop CopySmallMutableArrayOp "copySmallMutableArray#" GenPrimOp
+ SmallMutableArray# s a -> Int# -> SmallMutableArray# s a -> Int# -> Int# -> State# s -> State# s
+ {Given a source array, an offset into the source array, a
+ destination array, an offset into the destination array, and a
+ number of elements to copy, copy the elements from the source array
+ to the destination array. The source and destination arrays can
+ refer to the same array. Both arrays must fully contain the
+ specified ranges, but this is not checked.}
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop CloneSmallArrayOp "cloneSmallArray#" GenPrimOp
+ SmallArray# a -> Int# -> Int# -> SmallArray# a
+ {Given a source array, an offset into the source array, and a number
+ of elements to copy, create a new array with the elements from the
+ source array. The provided array must fully contain the specified
+ range, but this is not checked.}
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop CloneSmallMutableArrayOp "cloneSmallMutableArray#" GenPrimOp
+ SmallMutableArray# s a -> Int# -> Int# -> State# s -> (# State# s, SmallMutableArray# s a #)
+ {Given a source array, an offset into the source array, and a number
+ of elements to copy, create a new array with the elements from the
+ source array. The provided array must fully contain the specified
+ range, but this is not checked.}
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop FreezeSmallArrayOp "freezeSmallArray#" GenPrimOp
+ SmallMutableArray# s a -> Int# -> Int# -> State# s -> (# State# s, SmallArray# a #)
+ {Given a source array, an offset into the source array, and a number
+ of elements to copy, create a new array with the elements from the
+ source array. The provided array must fully contain the specified
+ range, but this is not checked.}
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop ThawSmallArrayOp "thawSmallArray#" GenPrimOp
+ SmallArray# a -> Int# -> Int# -> State# s -> (# State# s, SmallMutableArray# s a #)
+ {Given a source array, an offset into the source array, and a number
+ of elements to copy, create a new array with the elements from the
+ source array. The provided array must fully contain the specified
+ range, but this is not checked.}
+ with
+ out_of_line = True
+ has_side_effects = True
+ can_fail = True
+
+primop CasSmallArrayOp "casSmallArray#" GenPrimOp
+ SmallMutableArray# s a -> Int# -> a -> a -> State# s -> (# State# s, Int#, a #)
+ {Unsafe, machine-level atomic compare and swap on an element within an array.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+------------------------------------------------------------------------
section "Byte Arrays"
{Operations on {\tt ByteArray\#}. A {\tt ByteArray\#} is a just a region of
raw memory in the garbage-collected heap, which is not