commit ebb371e6409074aa037052c83c93ccc110232f28
parent 2a10eb194237b03e83ab9bdda579c20e814156cb
Author: Drew DeVault <sir@cmpwn.com>
Date: Fri, 12 Feb 2021 14:11:14 -0500
all: improve slice allocation usage
Diffstat:
4 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/fmt/fmt.ha b/fmt/fmt.ha
@@ -207,7 +207,7 @@ fn format(
};
fn scan_uint(iter: *strings::iterator) uint = {
- let num = alloc([]u8, [], 1); // TODO: alloc slice w/o cap
+ let num = alloc([]u8, []);
defer free(num);
for (true) {
let r = match (strings::next(iter)) {
diff --git a/rt/ensure.ha b/rt/ensure.ha
@@ -5,10 +5,16 @@ export type slice = struct {
};
export fn ensure(s: *slice, membsz: size, length: size) void = {
- // TODO: make sure length * membsz < SIZE_MAX
- for (s.capacity < length) {
- s.capacity *= 2;
+ let cap = s.capacity;
+ for (cap < length) {
+ assert(cap >= s.capacity, "slice out of memory (overflow)");
+ if (cap == 0) {
+ cap = length;
+ } else {
+ cap *= 2;
+ };
};
+ s.capacity = cap;
let data = realloc(s.data, s.capacity * membsz);
assert(data != null);
s.data = data;
diff --git a/rt/malloc.ha b/rt/malloc.ha
@@ -47,8 +47,8 @@ fn size2bin(s: size) size = {
// Allocates n bytes of memory and returns a pointer to them, or null if there
// is insufficient memory.
export fn malloc(n: size) nullable *void = {
- assert(n > 0);
- return if (n > bin2size(len(bins) - 1)) malloc_large(n)
+ return if (n == 0) null
+ else if (n > bin2size(len(bins) - 1)) malloc_large(n)
else malloc_small(n);
};
@@ -135,8 +135,9 @@ fn free_small(p: *void, s: size) void = {
// in-place. Returns null if there is insufficient memory to support the
// request.
export fn realloc(_p: nullable *void, n: size) nullable *void = {
- assert(n > 0);
- if (_p == null) {
+ if (n == 0) {
+ return null;
+ } else if (_p == null) {
return malloc(n);
};
diff --git a/strings/tokenize.ha b/strings/tokenize.ha
@@ -54,7 +54,7 @@ export fn remaining_tokens(s: *tokenizer) str = {
// borrowed from 'in', and needn't be freed - but should be [strings::dup_all]'d
// if they should outlive 'in'.
export fn splitN(in: str, delim: str, n: size) []str = {
- let toks = alloc([]str, [], 8); // TODO: Drop explicit capacity
+ let toks = alloc([]str, []);
let tok = tokenize(in, delim);
for (let i = 0z; i < n - 1z; i += 1) {
match (next_token(&tok)) {