{Create a mutable byte array that the GC guarantees not to move.}
with out_of_line = True
+primop NewAlignedPinnedByteArrayOp_Char "newAlignedPinnedByteArray#" GenPrimOp
+ Int# -> Int# -> State# s -> (# State# s, MutableByteArray# s #)
+ {Create a mutable byte array, aligned by the specified amount, that the GC guarantees not to move.}
+ with out_of_line = True
+
primop ByteArrayContents_Char "byteArrayContents#" GenPrimOp
ByteArray# -> Addr#
{Intended for use with pinned arrays; otherwise very unsafe!}
RTS_FUN(unsafeThawArrayzh_fast);
RTS_FUN(newByteArrayzh_fast);
RTS_FUN(newPinnedByteArrayzh_fast);
+RTS_FUN(newAlignedPinnedByteArrayzh_fast);
RTS_FUN(newArrayzh_fast);
RTS_FUN(newMutVarzh_fast);
SymI_HasProto(noDuplicatezh_fast) \
SymI_HasProto(atomicModifyMutVarzh_fast) \
SymI_HasProto(newPinnedByteArrayzh_fast) \
+ SymI_HasProto(newAlignedPinnedByteArrayzh_fast) \
SymI_HasProto(newSpark) \
SymI_HasProto(orIntegerzh_fast) \
SymI_HasProto(performGC) \
RET_P(p);
}
+#define BA_ALIGN 16
+#define BA_MASK (BA_ALIGN-1)
+
newPinnedByteArrayzh_fast
{
W_ words, payload_words, n, p;
n = R1;
payload_words = ROUNDUP_BYTES_TO_WDS(n);
- // We want an 8-byte aligned array. allocatePinned() gives us
+ words = payload_words + ((SIZEOF_StgArrWords + BA_MASK) & ~BA_MASK);
+
+ ("ptr" p) = foreign "C" allocatePinned(words) [];
+ TICK_ALLOC_PRIM(SIZEOF_StgArrWords,WDS(payload_words),0);
+
+ // This bumps p forwards so that the payload falls on an R2-byte boundary.
+ p = p + ((-p - SIZEOF_StgArrWords) & BA_MASK);
+
+ SET_HDR(p, stg_ARR_WORDS_info, W_[CCCS]);
+ StgArrWords_words(p) = payload_words;
+ RET_P(p);
+}
+
+newAlignedPinnedByteArrayzh_fast
+{
+ W_ words, payload_words, n, p, mask;
+
+ MAYBE_GC(NO_PTRS,newAlignedPinnedByteArrayzh_fast);
+ n = R1;
+
+ if (R2 > SIZEOF_W) {
+ mask = R2 - 1;
+ } else {
+ mask = 0;
+ }
+
+ payload_words = ROUNDUP_BYTES_TO_WDS(n);
+
+ // We want an <align>-byte aligned array. allocatePinned() gives us
// 8-byte aligned memory by default, but we want to align the
// *goods* inside the ArrWords object, so we have to check the
// size of the ArrWords header and adjust our size accordingly.
- words = BYTES_TO_WDS(SIZEOF_StgArrWords) + payload_words;
- if ((SIZEOF_StgArrWords & 7) != 0) {
- words = words + 1;
- }
+ words = payload_words + ((SIZEOF_StgArrWords + mask) & ~mask);
("ptr" p) = foreign "C" allocatePinned(words) [];
TICK_ALLOC_PRIM(SIZEOF_StgArrWords,WDS(payload_words),0);
- // Again, if the ArrWords header isn't a multiple of 8 bytes, we
- // have to push the object forward one word so that the goods
- // fall on an 8-byte boundary.
- if ((SIZEOF_StgArrWords & 7) != 0) {
- p = p + WDS(1);
- }
+ // This bumps p forwards so that the payload falls on an R2-byte boundary.
+ p = p + ((-p - SIZEOF_StgArrWords) & mask);
SET_HDR(p, stg_ARR_WORDS_info, W_[CCCS]);
StgArrWords_words(p) = payload_words;
for (; bd != NULL; bd = bd->link) {
+ // nothing to do in a pinned block; it might not even have an object
+ // at the beginning.
+ if (bd->flags & BF_PINNED) continue;
+
p = bd->start;
info = get_itbl((StgClosure *)p);
stp = bd->step;
ACQUIRE_SPIN_LOCK(&stp->sync_large_objects);
- // object must be at the beginning of the block (or be a ByteArray)
- ASSERT(get_itbl((StgClosure *)p)->type == ARR_WORDS ||
- (((W_)p & BLOCK_MASK) == 0));
-
// already evacuated?
if (bd->flags & BF_EVACUATED) {
/* Don't forget to set the gct->failed_to_evac flag if we didn't get
}
ws = &gct->steps[new_stp->abs_no];
+
bd->flags |= BF_EVACUATED;
bd->step = new_stp;
bd->gen_no = new_stp->gen_no;
- bd->link = ws->todo_large_objects;
- ws->todo_large_objects = bd;
+
+ // If this is a block of pinned objects, we don't have to scan
+ // these objects, because they aren't allowed to contain any
+ // pointers. For these blocks, we skip the scavenge stage and put
+ // them straight on the scavenged_large_objects list.
+ if (bd->flags & BF_PINNED) {
+ ASSERT(get_itbl((StgClosure *)p)->type == ARR_WORDS);
+ dbl_link_onto(bd, &ws->step->scavenged_large_objects);
+ ws->step->n_scavenged_large_blocks += bd->blocks;
+ } else {
+ bd->link = ws->todo_large_objects;
+ ws->todo_large_objects = bd;
+ }
RELEASE_SPIN_LOCK(&stp->sync_large_objects);
}
// If the request is for a large object, then allocate()
// will give us a pinned object anyway.
if (n >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
- return allocate(n);
+ p = allocate(n);
+ Bdescr(p)->flags |= BF_PINNED;
+ return p;
}
ACQUIRE_SM_LOCK;
TICK_ALLOC_HEAP_NOCTR(n);
CCS_ALLOC(CCCS,n);
- // we always return 8-byte aligned memory. bd->free must be
- // 8-byte aligned to begin with, so we just round up n to
- // the nearest multiple of 8 bytes.
- if (sizeof(StgWord) == 4) {
- n = (n+1) & ~1;
- }
-
// If we don't have a block of pinned objects yet, or the current
// one isn't large enough to hold the new object, allocate a new one.
if (bd == NULL || (bd->free + n) > (bd->start + BLOCK_SIZE_W)) {