hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

malloc+debug.ha (2003B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 // This is a very simple "debug" allocator which works by allocating only via
      5 // mmap and returning pointers to the end of the segment such that any writes
      6 // beyond the end will cause an immediate segfault to occur.
      7 //
      8 // Ultimately, this should be replaced with a much more sophisticated debugging
      9 // allocator.
     10 let pagesz: size = 4096;
     11 
     12 def AUXV_PAGESZ: u64 = 6;
     13 
     14 type auxv64 = struct {
     15 	a_type: u64,
     16 	union {
     17 		a_val: u64,
     18 		a_ptr: *opaque,
     19 		a_fnc: *fn() void,
     20 	}
     21 };
     22 
     23 @init fn init() void = {
     24 	let i = 0;
     25 	for (envp[i] != null) {
     26 		i += 1;
     27 	};
     28 	let auxv = &envp[i + 1]: *[*]auxv64;
     29 	for (let i = 0z; auxv[i].a_type != 0; i += 1) {
     30 		if (auxv[i].a_type == AUXV_PAGESZ) {
     31 			pagesz = auxv[i].a_val: size;
     32 			break;
     33 		};
     34 	};
     35 };
     36 
     37 export fn malloc(n: size) nullable *opaque = {
     38 	if (n == 0) {
     39 		return null;
     40 	};
     41 	let z = n + size(*opaque) + size(size);
     42 	if (z % pagesz != 0) {
     43 		z += pagesz - z % pagesz;
     44 	};
     45 	let seg = match (segmalloc(z)) {
     46 	case null =>
     47 		return null;
     48 	case let ptr: *opaque =>
     49 		yield ptr;
     50 	};
     51 	let user = &(seg: *[*]u8)[z - n];
     52 	let segptr = &(user: *[*]*opaque)[-1];
     53 	let szptr = &(segptr: *[*]size)[-1];
     54 	*segptr = seg;
     55 	*szptr = n;
     56 	return user;
     57 };
     58 
     59 export @symbol("rt.free") fn free_(_p: nullable *opaque) void = {
     60 	if (_p != null) {
     61 		let user = _p: *opaque;
     62 		let segptr = &(user: *[*]*opaque)[-1];
     63 		let szptr = &(segptr: *[*]size)[-1];
     64 		let z = *szptr + size(*opaque) + size(size);
     65 		if (z % pagesz != 0) {
     66 			z += pagesz - z % pagesz;
     67 		};
     68 		segfree(*segptr, z);
     69 	};
     70 };
     71 
     72 export fn realloc(user: nullable *opaque, n: size) nullable *opaque = {
     73 	if (n == 0) {
     74 		free(user);
     75 		return null;
     76 	} else if (user == null) {
     77 		return malloc(n);
     78 	};
     79 
     80 	let user = user: *opaque;
     81 	let segptr = &(user: *[*]*opaque)[-1];
     82 	let szptr = &(segptr: *[*]size)[-1];
     83 	let z = *szptr;
     84 
     85 	let new = malloc(n);
     86 	if (new != null) {
     87 		memcpy(new: *opaque, user, if (z < n) z else n);
     88 		free(user);
     89 	};
     90 
     91 	return new;
     92 };