shithub: mc

Download patch

ref: 231b0fd0e1e70376bcf747a797a76b07521987b7
parent: 2a3b64a5642729ab3bf83a21ea6bf59fc2a88f2c
author: Ori Bernstein <[email protected]>
date: Thu Apr 4 09:07:38 EDT 2013

Add slice appending code.

--- a/libstd/alloc.myr
+++ b/libstd/alloc.myr
@@ -1,12 +1,12 @@
 use "die.use"
+use "extremum.use"
 use "sys.use"
 use "types.use"
-use "extremum.use"
 
-/* 
+/*
 The allocator implementation here is based on Bonwick's slab allocator.
 
-For small allocations (up to Bucketmax), it works by requesting large,
+For small allocations (up to Bktmax), it works by requesting large,
 power of two aligned chunks from the operating system, and breaking
 them into a linked list of equal sized chunks. Allocations are then
 satisfied by taking the head of the list of chunks. Empty slabs
@@ -13,7 +13,7 @@
 are removed from the freelist.
 
 The data structure looks something like this:
-   Buckets:
+   Bkts:
 	[16  byte] -> [slab hdr | chunk -> chunk -> chunk] -> [slab hdr | chunk -> chunk -> chunk]
 	[32  byte] -> Zslab
 	[64  byte] -> [slab hdr | chunk -> chunk]
@@ -34,6 +34,9 @@
 
 	const bytealloc	: (sz:size	-> byte#)
 	const bytefree	: (m:byte#, sz:size	-> void)
+
+	/* FIXME: This should be automatically exported as a hidden decl. */
+	const samebucket
 ;;
 
 /* null pointers. only used internally. */
@@ -43,7 +46,7 @@
 
 const Slabsz 	= 1048576	/* 1 meg slabs */
 const Cachemax	= 16	/* maximum number of slabs in the cache */
-const Bucketmax	= 32768	/* Slabsz / 8; a balance. */
+const Bktmax	= 32768	/* Slabsz / 8; a balance. */
 const Align	= 16	/* minimum allocation alignment */
 
 var buckets	: bucket[32] /* excessive */
@@ -92,20 +95,35 @@
 }
 
 /* Grows a slice */
-generic slgrow = {sl, len
+generic slgrow = {sl : @a[:], len
 	var i
 	var n
 	var new
 
+	/* if the slice wouldn't change buckets, we don't need to realloc. */
+	if samebucket(sl.len * sizeof(@a), len * sizeof(@a))
+		-> sl
+	;;
+
 	new = slalloc(len)
 	n = min(len, sl.len)
 	for i = 0; i < n; i++
 		new[i] = sl[i]
 	;;
-	slfree(sl)
+	if sl.len > 0
+		slfree(sl)
+	;;
 	-> new
 }
 
+const samebucket = {oldsz, newsz
+	if oldsz > 0 && newsz < Bktmax
+		-> bktnum(oldsz) == bktnum(newsz)
+	else
+		-> false
+	;;
+}
+
 /* Allocates a blob that is 'sz' bytes long. Dies if the allocation fails */
 const bytealloc = {sz
 	var i
@@ -112,13 +130,13 @@
 	var bkt
 
 	if !initdone
-		for i = 0; i < buckets.len && (Align << i) <= Bucketmax; i++
+		for i = 0; i < buckets.len && (Align << i) <= Bktmax; i++
 			bktinit(&buckets[i], Align << i)
 		;;
 		initdone = 1
 	;;
 
-	if (sz <= Bucketmax)
+	if (sz <= Bktmax)
 		bkt = &buckets[bktnum(sz)]
 		-> bktalloc(bkt)
 	else
@@ -130,7 +148,7 @@
 const bytefree = {m, sz
 	var bkt
 
-	if (sz < Bucketmax)
+	if (sz < Bktmax)
 		bkt = &buckets[bktnum(sz)]
 		bktfree(bkt, m)
 	else
@@ -258,7 +276,7 @@
 	var bktsz
 
 	bktsz = Align
-	for i = 0; bktsz <= Bucketmax; i++
+	for i = 0; bktsz <= Bktmax; i++
 		if bktsz >= sz
 			-> i
 		;;
--- /dev/null
+++ b/libstd/slappend.myr
@@ -1,0 +1,11 @@
+use "alloc.use"
+
+pkg std =
+	generic slappend	: (sl : @a[:], v : @a	-> @a[:])
+;;
+
+generic slappend = {sl, v
+	sl = slgrow(sl, sl.len + 1)
+	sl[sl.len - 1] = v
+	-> sl
+}