Add free for maps (a previous oversight)

This commit is contained in:
Ginger Bill
2017-07-05 13:51:25 +01:00
parent 3d2d461867
commit eed873c6ec
8 changed files with 223 additions and 197 deletions
+69 -112
View File
@@ -117,6 +117,39 @@ __type_table: []TypeInfo;
__argv__: ^^u8;
__argc__: i32;
// IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
AllocatorMode :: enum u8 {
Alloc,
Free,
FreeAll,
Resize,
}
AllocatorProc :: proc(allocator_data: rawptr, mode: AllocatorMode,
size, alignment: int,
old_memory: rawptr, old_size: int, flags: u64 = 0) -> rawptr;
Allocator :: struct #ordered {
procedure: AllocatorProc,
data: rawptr,
}
Context :: struct #ordered {
thread_id: int,
allocator: Allocator,
user_data: rawptr,
user_index: int,
}
DEFAULT_ALIGNMENT :: align_of([vector 4]f32);
SourceCodeLocation :: struct {
fully_pathed_filename: string,
line, column: i64,
procedure: string,
}
__INITIAL_MAP_CAP :: 16;
@@ -181,48 +214,14 @@ foreign __llvm_core {
read_cycle_counter :: proc() -> u64 #link_name "llvm.readcyclecounter" ---;
}
// IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
AllocatorMode :: enum u8 {
Alloc,
Free,
FreeAll,
Resize,
}
AllocatorProc :: proc(allocator_data: rawptr, mode: AllocatorMode,
size, alignment: int,
old_memory: rawptr, old_size: int, flags: u64 = 0) -> rawptr;
Allocator :: struct #ordered {
procedure: AllocatorProc,
data: rawptr,
}
Context :: struct #ordered {
thread_id: int,
allocator: Allocator,
user_data: rawptr,
user_index: int,
}
// #thread_local var __context: Context;
SourceCodeLocation :: struct {
fully_pathed_filename: string,
line, column: i64,
procedure: string,
}
make_source_code_location :: proc(file: string, line, column: i64, procedure: string) -> SourceCodeLocation #cc_contextless #inline {
return SourceCodeLocation{file, line, column, procedure};
}
DEFAULT_ALIGNMENT :: align_of([vector 4]f32);
__init_context_from_ptr :: proc(c: ^Context, other: ^Context) #cc_contextless {
if c == nil do return;
@@ -255,35 +254,25 @@ __check_context :: proc() {
*/
alloc :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT) -> rawptr #inline {
// __check_context();
a := context.allocator;
return a.procedure(a.data, AllocatorMode.Alloc, size, alignment, nil, 0, 0);
}
free_ptr_with_allocator :: proc(a: Allocator, ptr: rawptr) #inline {
if ptr == nil {
return;
}
if a.procedure == nil {
return;
}
if ptr == nil do return;
if a.procedure == nil do return;
a.procedure(a.data, AllocatorMode.Free, 0, 0, ptr, 0, 0);
}
free_ptr :: proc(ptr: rawptr) #inline {
// __check_context();
free_ptr_with_allocator(context.allocator, ptr);
}
free_ptr :: proc(ptr: rawptr) #inline do free_ptr_with_allocator(context.allocator, ptr);
free_all :: proc() #inline {
// __check_context();
a := context.allocator;
a.procedure(a.data, AllocatorMode.FreeAll, 0, 0, nil, 0, 0);
}
resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT) -> rawptr #inline {
// __check_context();
a := context.allocator;
return a.procedure(a.data, AllocatorMode.Resize, new_size, alignment, ptr, old_size, 0);
}
@@ -298,14 +287,12 @@ copy :: proc(dst, src: []$T) -> int #cc_contextless {
append :: proc(array: ^[]$T, args: ..T) -> int {
if array == nil {
return 0;
}
if array == nil do return 0;
slice := ^raw.Slice(array);
arg_len := len(args);
if arg_len <= 0 {
return slice.len;
}
if arg_len <= 0 do return slice.len;
arg_len = min(slice.cap-slice.len, arg_len);
if arg_len > 0 {
@@ -319,15 +306,12 @@ append :: proc(array: ^[]$T, args: ..T) -> int {
}
append :: proc(array: ^[dynamic]$T, args: ..T) -> int {
if array == nil {
return 0;
}
if array == nil do return 0;
a := ^raw.DynamicArray(array);
arg_len := len(args);
if arg_len <= 0 {
return a.len;
}
if arg_len <= 0 do return a.len;
ok := true;
@@ -345,7 +329,7 @@ append :: proc(array: ^[dynamic]$T, args: ..T) -> int {
return a.len;
}
pop :: proc(array: ^[]$T) -> T {
pop :: proc(array: ^[]$T) -> T #cc_contextless {
res: T;
if array do return res;
assert(len(array) > 0);
@@ -354,7 +338,7 @@ pop :: proc(array: ^[]$T) -> T {
return res;
}
pop :: proc(array: ^[dynamic]$T) -> T {
pop :: proc(array: ^[dynamic]$T) -> T #cc_contextless {
res: T;
if array do return res;
assert(len(array) > 0);
@@ -384,7 +368,6 @@ reserve :: proc(array: ^[dynamic]$T, capacity: int) -> bool {
if capacity <= a.cap do return true;
// __check_context();
if a.allocator.procedure == nil {
a.allocator = context.allocator;
}
@@ -403,7 +386,7 @@ reserve :: proc(array: ^[dynamic]$T, capacity: int) -> bool {
}
__get_map_header :: proc(m: ^map[$K]$V) -> __MapHeader {
__get_map_header :: proc(m: ^map[$K]$V) -> __MapHeader #cc_contextless {
header := __MapHeader{m = ^raw.DynamicMap(m)};
Entry :: struct {
key: __MapKey,
@@ -419,9 +402,9 @@ __get_map_header :: proc(m: ^map[$K]$V) -> __MapHeader {
return header;
}
__get_map_key :: proc(key: $K) -> __MapKey {
__get_map_key :: proc(key: $K) -> __MapKey #cc_contextless {
map_key: __MapKey;
ti := type_info(K);
ti := type_info_base_without_enum(type_info(K));
match {
case types.is_integer(ti):
match 8*size_of(key) {
@@ -463,30 +446,16 @@ delete :: proc(m: ^map[$K]$V, key: K) {
new :: proc(T: type) -> ^T #inline do return ^T(alloc(size_of(T), align_of(T)));
free :: proc(ptr: rawptr) do free_ptr(ptr);
free :: proc(str: string) do free_ptr(^raw.String(&str).data);
free :: proc(array: [dynamic]$T) do free_ptr(^raw.DynamicArray(&array).data);
free :: proc(slice: []$T) do free_ptr(^raw.Slice(&slice).data);
free :: proc(str: string) do free_ptr(^raw.String(&str).data);
free :: proc(ptr: rawptr) do free_ptr(ptr);
slice_to_bytes :: proc(slice: []$T) -> []u8 {
s := ^raw.Slice(&slice);
s.len *= size_of(T);
s.cap *= size_of(T);
return ^[]u8(s)^;
free :: proc(m: map[$K]$V) {
raw := ^raw.DynamicMap(&m);
free(raw.hashes);
free(raw.entries.data);
}
slice_ptr :: proc(ptr: ^$T, len: int) -> []T {
assert(0 <= len);
s := raw.Slice{ptr, len, len};
return ^[]T(&s)^;
}
slice_ptr :: proc(ptr: ^$T, len, cap: int) -> []T {
assert(0 <= len && len <= cap);
s := raw.Slice{ptr, len, cap};
return ^[]T(&s)^;
}
default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int) -> rawptr {
if old_memory == nil do return alloc(new_size, alignment);
@@ -625,14 +594,12 @@ __string_decode_rune :: proc(s: string) -> (rune, int) #cc_contextless #inline {
__mem_set :: proc(data: rawptr, value: i32, len: int) -> rawptr #cc_contextless {
when size_of(rawptr) == 8 {
foreign __llvm_core llvm_memset_64bit :: proc(dst: rawptr, val: u8, len: int, align: i32, is_volatile: bool) #link_name "llvm.memset.p0i8.i64" ---;
llvm_memset_64bit(data, u8(value), len, 1, false);
return data;
foreign __llvm_core llvm_memset :: proc(dst: rawptr, val: u8, len: int, align: i32, is_volatile: bool) #link_name "llvm.memset.p0i8.i64" ---;
} else {
foreign __llvm_core llvm_memset_32bit :: proc(dst: rawptr, val: u8, len: int, align: i32, is_volatile: bool) #link_name "llvm.memset.p0i8.i32" ---;
llvm_memset_32bit(data, u8(value), len, 1, false);
return data;
foreign __llvm_core llvm_memset :: proc(dst: rawptr, val: u8, len: int, align: i32, is_volatile: bool) #link_name "llvm.memset.p0i8.i32" ---;
}
llvm_memset(data, u8(value), len, 1, false);
return data;
}
__mem_zero :: proc(data: rawptr, len: int) -> rawptr #cc_contextless {
return __mem_set(data, 0, len);
@@ -640,26 +607,22 @@ __mem_zero :: proc(data: rawptr, len: int) -> rawptr #cc_contextless {
__mem_copy :: proc(dst, src: rawptr, len: int) -> rawptr #cc_contextless {
// NOTE(bill): This _must_ be implemented like C's memmove
when size_of(rawptr) == 8 {
foreign __llvm_core llvm_memmove_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memmove.p0i8.p0i8.i64" ---;
llvm_memmove_64bit(dst, src, len, 1, false);
return dst;
foreign __llvm_core llvm_memmove :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memmove.p0i8.p0i8.i64" ---;
} else {
foreign __llvm_core llvm_memmove_32bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memmove.p0i8.p0i8.i32" ---;
llvm_memmove_32bit(dst, src, len, 1, false);
return dst;
foreign __llvm_core llvm_memmove :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memmove.p0i8.p0i8.i32" ---;
}
llvm_memmove(dst, src, len, 1, false);
return dst;
}
__mem_copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #cc_contextless {
// NOTE(bill): This _must_ be implemented like C's memcpy
when size_of(rawptr) == 8 {
foreign __llvm_core llvm_memcpy_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memcpy.p0i8.p0i8.i64" ---;
llvm_memcpy_64bit(dst, src, len, 1, false);
return dst;
foreign __llvm_core llvm_memcpy_ :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memcpy.p0i8.p0i8.i64" ---;
} else {
foreign __llvm_core llvm_memcpy_32bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memcpy.p0i8.p0i8.i32";
llvm_memcpy_32bit(dst, src, len, 1, false);
return dst;
foreign __llvm_core llvm_memcpy_ :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memcpy.p0i8.p0i8.i32";
}
llvm_memcpy_(dst, src, len, 1, false);
return dst;
}
__mem_compare :: proc(a, b: ^u8, n: int) -> int #cc_contextless {
@@ -702,7 +665,6 @@ __abs_complex128 :: proc(x: complex128) -> f64 #inline #cc_contextless {
__dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, cap: int) {
array := ^raw.DynamicArray(array_);
// __check_context();
array.allocator = context.allocator;
assert(array.allocator.procedure != nil);
@@ -717,7 +679,6 @@ __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap:
if cap <= array.cap do return true;
// __check_context();
if array.allocator.procedure == nil {
array.allocator = context.allocator;
}
@@ -866,8 +827,7 @@ __dynamic_map_get :: proc(h: __MapHeader, key: __MapKey) -> rawptr {
index := __dynamic_map_find(h, key).entry_index;
if index >= 0 {
data := ^u8(__dynamic_map_get_entry(h, index));
val := data + h.value_offset;
return val;
return data + h.value_offset;
}
return nil;
}
@@ -932,9 +892,7 @@ __dynamic_map_find :: proc(using h: __MapHeader, key: __MapKey) -> __MapFindResu
fr.entry_index = m.hashes[fr.hash_index];
for fr.entry_index >= 0 {
entry := __dynamic_map_get_entry(h, fr.entry_index);
if __dynamic_map_hash_equal(h, entry.key, key) {
return fr;
}
if __dynamic_map_hash_equal(h, entry.key, key) do return fr;
fr.entry_prev = fr.entry_index;
fr.entry_index = entry.next;
}
@@ -961,8 +919,7 @@ __dynamic_map_delete :: proc(using h: __MapHeader, key: __MapKey) {
}
__dynamic_map_get_entry :: proc(using h: __MapHeader, index: int) -> ^__MapEntryHeader {
data := ^u8(m.entries.data) + index*entry_size;
return ^__MapEntryHeader(data);
return ^__MapEntryHeader(^u8(m.entries.data) + index*entry_size);
}
__dynamic_map_erase :: proc(using h: __MapHeader, fr: __MapFindResult) {
+4 -2
View File
@@ -1,3 +1,5 @@
import "mem.odin";
crc32 :: proc(data: []u8) -> u32 {
result := ~u32(0);
for b in data {
@@ -102,7 +104,7 @@ murmur64 :: proc(data: []u8) -> u64 {
r :: 47;
h: u64 = SEED ~ (u64(len(data)) * m);
data64 := slice_ptr(^u64(&data[0]), len(data)/size_of(u64));
data64 := mem.slice_ptr(^u64(&data[0]), len(data)/size_of(u64));
for _, i in data64 {
k := data64[i];
@@ -138,7 +140,7 @@ murmur64 :: proc(data: []u8) -> u64 {
h1 := u32(SEED) ~ u32(len(data));
h2 := u32(SEED) >> 32;
data32 := slice_ptr(^u32(&data[0]), len(data)/size_of(u32));
data32 := mem.slice_ptr(^u32(&data[0]), len(data)/size_of(u32));
len := len(data);
i := 0;
+6 -3
View File
@@ -25,7 +25,7 @@ compare :: proc(a, b: []u8) -> int #cc_contextless {
return __mem_compare(&a[0], &b[0], min(len(a), len(b)));
}
/*
slice_ptr :: proc(ptr: ^$T, len: int) -> []T #cc_contextless {
assert(len >= 0);
slice := raw.Slice{data = ptr, len = len, cap = len};
@@ -43,7 +43,6 @@ slice_to_bytes :: proc(slice: []$T) -> []u8 #cc_contextless {
s.cap *= size_of(T);
return ^[]u8(s)^;
}
*/
kilobytes :: proc(x: int) -> int #inline #cc_contextless { return (x) * 1024; }
@@ -121,7 +120,7 @@ init_arena_from_context :: proc(using a: ^Arena, size: int) {
temp_count = 0;
}
free_arena :: proc(using a: ^Arena) {
destroy_arena :: proc(using a: ^Arena) {
if backing.procedure != nil {
push_allocator backing {
free(memory);
@@ -214,6 +213,8 @@ align_of_type_info :: proc(type_info: ^TypeInfo) -> int {
return align_of_type_info(info.base);
case Integer:
return info.size;
case Rune:
return info.size;
case Float:
return info.size;
case String:
@@ -267,6 +268,8 @@ size_of_type_info :: proc(type_info: ^TypeInfo) -> int {
return size_of_type_info(info.base);
case Integer:
return info.size;
case Rune:
return info.size;
case Float:
return info.size;
case String:
+3 -7
View File
@@ -57,9 +57,7 @@ args := _alloc_command_line_arguments();
open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errno) {
if len(path) == 0 {
return INVALID_HANDLE, ERROR_FILE_NOT_FOUND;
}
if len(path) == 0 do return INVALID_HANDLE, ERROR_FILE_NOT_FOUND;
access: u32;
match mode & (O_RDONLY|O_WRONLY|O_RDWR) {
@@ -245,9 +243,7 @@ heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
return win32.heap_realloc(win32.get_process_heap(), win32.HEAP_ZERO_MEMORY, ptr, new_size);
}
heap_free :: proc(ptr: rawptr) {
if ptr == nil {
return;
}
if ptr == nil do return;
win32.heap_free(win32.get_process_heap(), 0, ptr);
}
@@ -272,7 +268,7 @@ _alloc_command_line_arguments :: proc() -> []string {
len := 2*wstr_len-1;
buf := make([]u8, len+1);
str := slice_ptr(wstr, wstr_len+1);
str := mem.slice_ptr(wstr, wstr_len+1);
i, j := 0, 0;
for str[j] != 0 {
+3 -1
View File
@@ -1,3 +1,5 @@
import "mem.odin";
new_string :: proc(s: string) -> string {
c := make([]u8, len(s)+1);
copy(c, []u8(s));
@@ -15,5 +17,5 @@ new_c_string :: proc(s: string) -> ^u8 {
to_odin_string :: proc(c: ^u8) -> string {
len := 0;
for (c+len)^ != 0 do len++;
return string(slice_ptr(c, len));
return string(mem.slice_ptr(c, len));
}