mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 07:38:48 +00:00
Add free for maps (a previous oversight)
This commit is contained in:
+69
-112
@@ -117,6 +117,39 @@ __type_table: []TypeInfo;
|
|||||||
__argv__: ^^u8;
|
__argv__: ^^u8;
|
||||||
__argc__: i32;
|
__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;
|
__INITIAL_MAP_CAP :: 16;
|
||||||
|
|
||||||
@@ -181,48 +214,14 @@ foreign __llvm_core {
|
|||||||
read_cycle_counter :: proc() -> u64 #link_name "llvm.readcyclecounter" ---;
|
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 {
|
make_source_code_location :: proc(file: string, line, column: i64, procedure: string) -> SourceCodeLocation #cc_contextless #inline {
|
||||||
return SourceCodeLocation{file, line, column, procedure};
|
return SourceCodeLocation{file, line, column, procedure};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_ALIGNMENT :: align_of([vector 4]f32);
|
|
||||||
|
|
||||||
__init_context_from_ptr :: proc(c: ^Context, other: ^Context) #cc_contextless {
|
__init_context_from_ptr :: proc(c: ^Context, other: ^Context) #cc_contextless {
|
||||||
if c == nil do return;
|
if c == nil do return;
|
||||||
@@ -255,35 +254,25 @@ __check_context :: proc() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
alloc :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT) -> rawptr #inline {
|
alloc :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT) -> rawptr #inline {
|
||||||
// __check_context();
|
|
||||||
a := context.allocator;
|
a := context.allocator;
|
||||||
return a.procedure(a.data, AllocatorMode.Alloc, size, alignment, nil, 0, 0);
|
return a.procedure(a.data, AllocatorMode.Alloc, size, alignment, nil, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
free_ptr_with_allocator :: proc(a: Allocator, ptr: rawptr) #inline {
|
free_ptr_with_allocator :: proc(a: Allocator, ptr: rawptr) #inline {
|
||||||
if ptr == nil {
|
if ptr == nil do return;
|
||||||
return;
|
if a.procedure == nil do return;
|
||||||
}
|
|
||||||
if a.procedure == nil {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
a.procedure(a.data, AllocatorMode.Free, 0, 0, ptr, 0, 0);
|
a.procedure(a.data, AllocatorMode.Free, 0, 0, ptr, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
free_ptr :: proc(ptr: rawptr) #inline {
|
free_ptr :: proc(ptr: rawptr) #inline do free_ptr_with_allocator(context.allocator, ptr);
|
||||||
// __check_context();
|
|
||||||
free_ptr_with_allocator(context.allocator, ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
free_all :: proc() #inline {
|
free_all :: proc() #inline {
|
||||||
// __check_context();
|
|
||||||
a := context.allocator;
|
a := context.allocator;
|
||||||
a.procedure(a.data, AllocatorMode.FreeAll, 0, 0, nil, 0, 0);
|
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 {
|
resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT) -> rawptr #inline {
|
||||||
// __check_context();
|
|
||||||
a := context.allocator;
|
a := context.allocator;
|
||||||
return a.procedure(a.data, AllocatorMode.Resize, new_size, alignment, ptr, old_size, 0);
|
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 {
|
append :: proc(array: ^[]$T, args: ..T) -> int {
|
||||||
if array == nil {
|
if array == nil do return 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
slice := ^raw.Slice(array);
|
slice := ^raw.Slice(array);
|
||||||
|
|
||||||
arg_len := len(args);
|
arg_len := len(args);
|
||||||
if arg_len <= 0 {
|
if arg_len <= 0 do return slice.len;
|
||||||
return slice.len;
|
|
||||||
}
|
|
||||||
|
|
||||||
arg_len = min(slice.cap-slice.len, arg_len);
|
arg_len = min(slice.cap-slice.len, arg_len);
|
||||||
if arg_len > 0 {
|
if arg_len > 0 {
|
||||||
@@ -319,15 +306,12 @@ append :: proc(array: ^[]$T, args: ..T) -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
append :: proc(array: ^[dynamic]$T, args: ..T) -> int {
|
append :: proc(array: ^[dynamic]$T, args: ..T) -> int {
|
||||||
if array == nil {
|
if array == nil do return 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
a := ^raw.DynamicArray(array);
|
a := ^raw.DynamicArray(array);
|
||||||
|
|
||||||
arg_len := len(args);
|
arg_len := len(args);
|
||||||
if arg_len <= 0 {
|
if arg_len <= 0 do return a.len;
|
||||||
return a.len;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ok := true;
|
ok := true;
|
||||||
@@ -345,7 +329,7 @@ append :: proc(array: ^[dynamic]$T, args: ..T) -> int {
|
|||||||
return a.len;
|
return a.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
pop :: proc(array: ^[]$T) -> T {
|
pop :: proc(array: ^[]$T) -> T #cc_contextless {
|
||||||
res: T;
|
res: T;
|
||||||
if array do return res;
|
if array do return res;
|
||||||
assert(len(array) > 0);
|
assert(len(array) > 0);
|
||||||
@@ -354,7 +338,7 @@ pop :: proc(array: ^[]$T) -> T {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
pop :: proc(array: ^[dynamic]$T) -> T {
|
pop :: proc(array: ^[dynamic]$T) -> T #cc_contextless {
|
||||||
res: T;
|
res: T;
|
||||||
if array do return res;
|
if array do return res;
|
||||||
assert(len(array) > 0);
|
assert(len(array) > 0);
|
||||||
@@ -384,7 +368,6 @@ reserve :: proc(array: ^[dynamic]$T, capacity: int) -> bool {
|
|||||||
|
|
||||||
if capacity <= a.cap do return true;
|
if capacity <= a.cap do return true;
|
||||||
|
|
||||||
// __check_context();
|
|
||||||
if a.allocator.procedure == nil {
|
if a.allocator.procedure == nil {
|
||||||
a.allocator = context.allocator;
|
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)};
|
header := __MapHeader{m = ^raw.DynamicMap(m)};
|
||||||
Entry :: struct {
|
Entry :: struct {
|
||||||
key: __MapKey,
|
key: __MapKey,
|
||||||
@@ -419,9 +402,9 @@ __get_map_header :: proc(m: ^map[$K]$V) -> __MapHeader {
|
|||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
__get_map_key :: proc(key: $K) -> __MapKey {
|
__get_map_key :: proc(key: $K) -> __MapKey #cc_contextless {
|
||||||
map_key: __MapKey;
|
map_key: __MapKey;
|
||||||
ti := type_info(K);
|
ti := type_info_base_without_enum(type_info(K));
|
||||||
match {
|
match {
|
||||||
case types.is_integer(ti):
|
case types.is_integer(ti):
|
||||||
match 8*size_of(key) {
|
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)));
|
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(array: [dynamic]$T) do free_ptr(^raw.DynamicArray(&array).data);
|
||||||
free :: proc(slice: []$T) do free_ptr(^raw.Slice(&slice).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(m: map[$K]$V) {
|
||||||
free :: proc(ptr: rawptr) do free_ptr(ptr);
|
raw := ^raw.DynamicMap(&m);
|
||||||
|
free(raw.hashes);
|
||||||
slice_to_bytes :: proc(slice: []$T) -> []u8 {
|
free(raw.entries.data);
|
||||||
s := ^raw.Slice(&slice);
|
|
||||||
s.len *= size_of(T);
|
|
||||||
s.cap *= size_of(T);
|
|
||||||
return ^[]u8(s)^;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int) -> rawptr {
|
||||||
if old_memory == nil do return alloc(new_size, alignment);
|
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 {
|
__mem_set :: proc(data: rawptr, value: i32, len: int) -> rawptr #cc_contextless {
|
||||||
when size_of(rawptr) == 8 {
|
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" ---;
|
foreign __llvm_core llvm_memset :: 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;
|
|
||||||
} else {
|
} 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" ---;
|
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_32bit(data, u8(value), len, 1, false);
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
llvm_memset(data, u8(value), len, 1, false);
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
__mem_zero :: proc(data: rawptr, len: int) -> rawptr #cc_contextless {
|
__mem_zero :: proc(data: rawptr, len: int) -> rawptr #cc_contextless {
|
||||||
return __mem_set(data, 0, len);
|
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 {
|
__mem_copy :: proc(dst, src: rawptr, len: int) -> rawptr #cc_contextless {
|
||||||
// NOTE(bill): This _must_ be implemented like C's memmove
|
// NOTE(bill): This _must_ be implemented like C's memmove
|
||||||
when size_of(rawptr) == 8 {
|
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" ---;
|
foreign __llvm_core llvm_memmove :: 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;
|
|
||||||
} else {
|
} 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" ---;
|
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_32bit(dst, src, len, 1, false);
|
|
||||||
return dst;
|
|
||||||
}
|
}
|
||||||
|
llvm_memmove(dst, src, len, 1, false);
|
||||||
|
return dst;
|
||||||
}
|
}
|
||||||
__mem_copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #cc_contextless {
|
__mem_copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #cc_contextless {
|
||||||
// NOTE(bill): This _must_ be implemented like C's memcpy
|
// NOTE(bill): This _must_ be implemented like C's memcpy
|
||||||
when size_of(rawptr) == 8 {
|
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" ---;
|
foreign __llvm_core llvm_memcpy_ :: 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;
|
|
||||||
} else {
|
} 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";
|
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_32bit(dst, src, len, 1, false);
|
|
||||||
return dst;
|
|
||||||
}
|
}
|
||||||
|
llvm_memcpy_(dst, src, len, 1, false);
|
||||||
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
__mem_compare :: proc(a, b: ^u8, n: int) -> int #cc_contextless {
|
__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) {
|
__dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, cap: int) {
|
||||||
array := ^raw.DynamicArray(array_);
|
array := ^raw.DynamicArray(array_);
|
||||||
// __check_context();
|
|
||||||
array.allocator = context.allocator;
|
array.allocator = context.allocator;
|
||||||
assert(array.allocator.procedure != nil);
|
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;
|
if cap <= array.cap do return true;
|
||||||
|
|
||||||
// __check_context();
|
|
||||||
if array.allocator.procedure == nil {
|
if array.allocator.procedure == nil {
|
||||||
array.allocator = context.allocator;
|
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;
|
index := __dynamic_map_find(h, key).entry_index;
|
||||||
if index >= 0 {
|
if index >= 0 {
|
||||||
data := ^u8(__dynamic_map_get_entry(h, index));
|
data := ^u8(__dynamic_map_get_entry(h, index));
|
||||||
val := data + h.value_offset;
|
return data + h.value_offset;
|
||||||
return val;
|
|
||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
@@ -932,9 +892,7 @@ __dynamic_map_find :: proc(using h: __MapHeader, key: __MapKey) -> __MapFindResu
|
|||||||
fr.entry_index = m.hashes[fr.hash_index];
|
fr.entry_index = m.hashes[fr.hash_index];
|
||||||
for fr.entry_index >= 0 {
|
for fr.entry_index >= 0 {
|
||||||
entry := __dynamic_map_get_entry(h, fr.entry_index);
|
entry := __dynamic_map_get_entry(h, fr.entry_index);
|
||||||
if __dynamic_map_hash_equal(h, entry.key, key) {
|
if __dynamic_map_hash_equal(h, entry.key, key) do return fr;
|
||||||
return fr;
|
|
||||||
}
|
|
||||||
fr.entry_prev = fr.entry_index;
|
fr.entry_prev = fr.entry_index;
|
||||||
fr.entry_index = entry.next;
|
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 {
|
__dynamic_map_get_entry :: proc(using h: __MapHeader, index: int) -> ^__MapEntryHeader {
|
||||||
data := ^u8(m.entries.data) + index*entry_size;
|
return ^__MapEntryHeader(^u8(m.entries.data) + index*entry_size);
|
||||||
return ^__MapEntryHeader(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_map_erase :: proc(using h: __MapHeader, fr: __MapFindResult) {
|
__dynamic_map_erase :: proc(using h: __MapHeader, fr: __MapFindResult) {
|
||||||
|
|||||||
+4
-2
@@ -1,3 +1,5 @@
|
|||||||
|
import "mem.odin";
|
||||||
|
|
||||||
crc32 :: proc(data: []u8) -> u32 {
|
crc32 :: proc(data: []u8) -> u32 {
|
||||||
result := ~u32(0);
|
result := ~u32(0);
|
||||||
for b in data {
|
for b in data {
|
||||||
@@ -102,7 +104,7 @@ murmur64 :: proc(data: []u8) -> u64 {
|
|||||||
r :: 47;
|
r :: 47;
|
||||||
|
|
||||||
h: u64 = SEED ~ (u64(len(data)) * m);
|
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 {
|
for _, i in data64 {
|
||||||
k := data64[i];
|
k := data64[i];
|
||||||
@@ -138,7 +140,7 @@ murmur64 :: proc(data: []u8) -> u64 {
|
|||||||
|
|
||||||
h1 := u32(SEED) ~ u32(len(data));
|
h1 := u32(SEED) ~ u32(len(data));
|
||||||
h2 := u32(SEED) >> 32;
|
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);
|
len := len(data);
|
||||||
i := 0;
|
i := 0;
|
||||||
|
|
||||||
|
|||||||
+6
-3
@@ -25,7 +25,7 @@ compare :: proc(a, b: []u8) -> int #cc_contextless {
|
|||||||
return __mem_compare(&a[0], &b[0], min(len(a), len(b)));
|
return __mem_compare(&a[0], &b[0], min(len(a), len(b)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
slice_ptr :: proc(ptr: ^$T, len: int) -> []T #cc_contextless {
|
slice_ptr :: proc(ptr: ^$T, len: int) -> []T #cc_contextless {
|
||||||
assert(len >= 0);
|
assert(len >= 0);
|
||||||
slice := raw.Slice{data = ptr, len = len, cap = len};
|
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);
|
s.cap *= size_of(T);
|
||||||
return ^[]u8(s)^;
|
return ^[]u8(s)^;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
kilobytes :: proc(x: int) -> int #inline #cc_contextless { return (x) * 1024; }
|
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;
|
temp_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
free_arena :: proc(using a: ^Arena) {
|
destroy_arena :: proc(using a: ^Arena) {
|
||||||
if backing.procedure != nil {
|
if backing.procedure != nil {
|
||||||
push_allocator backing {
|
push_allocator backing {
|
||||||
free(memory);
|
free(memory);
|
||||||
@@ -214,6 +213,8 @@ align_of_type_info :: proc(type_info: ^TypeInfo) -> int {
|
|||||||
return align_of_type_info(info.base);
|
return align_of_type_info(info.base);
|
||||||
case Integer:
|
case Integer:
|
||||||
return info.size;
|
return info.size;
|
||||||
|
case Rune:
|
||||||
|
return info.size;
|
||||||
case Float:
|
case Float:
|
||||||
return info.size;
|
return info.size;
|
||||||
case String:
|
case String:
|
||||||
@@ -267,6 +268,8 @@ size_of_type_info :: proc(type_info: ^TypeInfo) -> int {
|
|||||||
return size_of_type_info(info.base);
|
return size_of_type_info(info.base);
|
||||||
case Integer:
|
case Integer:
|
||||||
return info.size;
|
return info.size;
|
||||||
|
case Rune:
|
||||||
|
return info.size;
|
||||||
case Float:
|
case Float:
|
||||||
return info.size;
|
return info.size;
|
||||||
case String:
|
case String:
|
||||||
|
|||||||
@@ -57,9 +57,7 @@ args := _alloc_command_line_arguments();
|
|||||||
|
|
||||||
|
|
||||||
open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errno) {
|
open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errno) {
|
||||||
if len(path) == 0 {
|
if len(path) == 0 do return INVALID_HANDLE, ERROR_FILE_NOT_FOUND;
|
||||||
return INVALID_HANDLE, ERROR_FILE_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
access: u32;
|
access: u32;
|
||||||
match mode & (O_RDONLY|O_WRONLY|O_RDWR) {
|
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);
|
return win32.heap_realloc(win32.get_process_heap(), win32.HEAP_ZERO_MEMORY, ptr, new_size);
|
||||||
}
|
}
|
||||||
heap_free :: proc(ptr: rawptr) {
|
heap_free :: proc(ptr: rawptr) {
|
||||||
if ptr == nil {
|
if ptr == nil do return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
win32.heap_free(win32.get_process_heap(), 0, ptr);
|
win32.heap_free(win32.get_process_heap(), 0, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,7 +268,7 @@ _alloc_command_line_arguments :: proc() -> []string {
|
|||||||
|
|
||||||
len := 2*wstr_len-1;
|
len := 2*wstr_len-1;
|
||||||
buf := make([]u8, 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;
|
i, j := 0, 0;
|
||||||
for str[j] != 0 {
|
for str[j] != 0 {
|
||||||
|
|||||||
+3
-1
@@ -1,3 +1,5 @@
|
|||||||
|
import "mem.odin";
|
||||||
|
|
||||||
new_string :: proc(s: string) -> string {
|
new_string :: proc(s: string) -> string {
|
||||||
c := make([]u8, len(s)+1);
|
c := make([]u8, len(s)+1);
|
||||||
copy(c, []u8(s));
|
copy(c, []u8(s));
|
||||||
@@ -15,5 +17,5 @@ new_c_string :: proc(s: string) -> ^u8 {
|
|||||||
to_odin_string :: proc(c: ^u8) -> string {
|
to_odin_string :: proc(c: ^u8) -> string {
|
||||||
len := 0;
|
len := 0;
|
||||||
for (c+len)^ != 0 do len++;
|
for (c+len)^ != 0 do len++;
|
||||||
return string(slice_ptr(c, len));
|
return string(mem.slice_ptr(c, len));
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-5
@@ -305,9 +305,10 @@ struct Checker {
|
|||||||
Array<DelayedDecl> delayed_foreign_libraries;
|
Array<DelayedDecl> delayed_foreign_libraries;
|
||||||
Array<CheckerFileNode> file_nodes;
|
Array<CheckerFileNode> file_nodes;
|
||||||
|
|
||||||
|
Pool pool;
|
||||||
|
gbAllocator allocator;
|
||||||
gbArena arena;
|
gbArena arena;
|
||||||
gbArena tmp_arena;
|
gbArena tmp_arena;
|
||||||
gbAllocator allocator;
|
|
||||||
gbAllocator tmp_allocator;
|
gbAllocator tmp_allocator;
|
||||||
|
|
||||||
CheckerContext context;
|
CheckerContext context;
|
||||||
@@ -773,11 +774,13 @@ void init_checker(Checker *c, Parser *parser) {
|
|||||||
total_token_count += f->tokens.count;
|
total_token_count += f->tokens.count;
|
||||||
}
|
}
|
||||||
isize arena_size = 2 * item_size * total_token_count;
|
isize arena_size = 2 * item_size * total_token_count;
|
||||||
gb_arena_init_from_allocator(&c->arena, a, arena_size);
|
|
||||||
gb_arena_init_from_allocator(&c->tmp_arena, a, arena_size);
|
gb_arena_init_from_allocator(&c->tmp_arena, a, arena_size);
|
||||||
|
gb_arena_init_from_allocator(&c->arena, a, arena_size);
|
||||||
|
|
||||||
|
pool_init(&c->pool, gb_megabytes(4), gb_kilobytes(384));
|
||||||
c->allocator = gb_arena_allocator(&c->arena);
|
// c->allocator = pool_allocator(&c->pool);
|
||||||
|
c->allocator = heap_allocator();
|
||||||
|
// c->allocator = gb_arena_allocator(&c->arena);
|
||||||
c->tmp_allocator = gb_arena_allocator(&c->tmp_arena);
|
c->tmp_allocator = gb_arena_allocator(&c->tmp_arena);
|
||||||
|
|
||||||
c->global_scope = make_scope(universal_scope, c->allocator);
|
c->global_scope = make_scope(universal_scope, c->allocator);
|
||||||
@@ -793,7 +796,9 @@ void destroy_checker(Checker *c) {
|
|||||||
array_free(&c->delayed_foreign_libraries);
|
array_free(&c->delayed_foreign_libraries);
|
||||||
array_free(&c->file_nodes);
|
array_free(&c->file_nodes);
|
||||||
|
|
||||||
gb_arena_free(&c->arena);
|
pool_destroy(&c->pool);
|
||||||
|
gb_arena_free(&c->tmp_arena);
|
||||||
|
// gb_arena_free(&c->arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+118
-58
@@ -23,6 +23,9 @@ gbAllocator heap_allocator(void) {
|
|||||||
#include "integer128.cpp"
|
#include "integer128.cpp"
|
||||||
#include "murmurhash3.cpp"
|
#include "murmurhash3.cpp"
|
||||||
|
|
||||||
|
#define for_array(index_, array_) for (isize index_ = 0; index_ < (array_).count; index_++)
|
||||||
|
|
||||||
|
|
||||||
u128 fnv128a(void const *data, isize len) {
|
u128 fnv128a(void const *data, isize len) {
|
||||||
u128 o = u128_lo_hi(0x13bull, 0x1000000ull);
|
u128 o = u128_lo_hi(0x13bull, 0x1000000ull);
|
||||||
u128 h = u128_lo_hi(0x62b821756295c58dull, 0x6c62272e07bb0142ull);
|
u128 h = u128_lo_hi(0x62b821756295c58dull, 0x6c62272e07bb0142ull);
|
||||||
@@ -52,87 +55,145 @@ gbAllocator scratch_allocator(void) {
|
|||||||
return gb_scratch_allocator(&scratch_memory);
|
return gb_scratch_allocator(&scratch_memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Pool {
|
||||||
|
isize memblock_size;
|
||||||
|
isize out_of_band_size;
|
||||||
|
isize alignment;
|
||||||
|
|
||||||
struct DynamicArenaBlock {
|
Array<u8 *> unused_memblock;
|
||||||
DynamicArenaBlock *prev;
|
Array<u8 *> used_memblock;
|
||||||
DynamicArenaBlock *next;
|
Array<u8 *> out_of_band_allocations;
|
||||||
u8 * start;
|
|
||||||
isize count;
|
|
||||||
isize capacity;
|
|
||||||
|
|
||||||
gbVirtualMemory vm;
|
u8 * current_memblock;
|
||||||
|
u8 * current_pos;
|
||||||
|
isize bytes_left;
|
||||||
|
|
||||||
|
gbAllocator block_allocator;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DynamicArena {
|
enum {
|
||||||
DynamicArenaBlock *start_block;
|
POOL_BUCKET_SIZE_DEFAULT = 65536,
|
||||||
DynamicArenaBlock *current_block;
|
POOL_OUT_OF_BAND_SIZE_DEFAULT = 6554,
|
||||||
isize block_size;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DynamicArenaBlock *add_dynamic_arena_block(DynamicArena *a) {
|
void pool_init(Pool *pool,
|
||||||
GB_ASSERT(a != NULL);
|
isize memblock_size = POOL_BUCKET_SIZE_DEFAULT,
|
||||||
GB_ASSERT(a->block_size > 0);
|
isize out_of_band_size = POOL_OUT_OF_BAND_SIZE_DEFAULT,
|
||||||
|
isize alignment = 8,
|
||||||
|
gbAllocator block_allocator = heap_allocator(),
|
||||||
|
gbAllocator array_allocator = heap_allocator()) {
|
||||||
|
pool->memblock_size = memblock_size;
|
||||||
|
pool->out_of_band_size = out_of_band_size;
|
||||||
|
pool->alignment = alignment;
|
||||||
|
pool->block_allocator = block_allocator;
|
||||||
|
|
||||||
gbVirtualMemory vm = gb_vm_alloc(NULL, a->block_size);
|
array_init(&pool->unused_memblock, array_allocator);
|
||||||
DynamicArenaBlock *block = cast(DynamicArenaBlock *)vm.data;
|
array_init(&pool->used_memblock, array_allocator);
|
||||||
|
array_init(&pool->out_of_band_allocations, array_allocator);
|
||||||
|
}
|
||||||
|
|
||||||
u8 *start = cast(u8 *)gb_align_forward(cast(u8 *)(block + 1), GB_DEFAULT_MEMORY_ALIGNMENT);
|
void pool_free_all(Pool *p) {
|
||||||
u8 *end = cast(u8 *)vm.data + vm.size;
|
if (p->current_memblock != NULL) {
|
||||||
|
array_add(&p->unused_memblock, p->current_memblock);
|
||||||
block->vm = vm;
|
p->current_memblock = NULL;
|
||||||
block->start = start;
|
|
||||||
block->count = 0;
|
|
||||||
block->capacity = end-start;
|
|
||||||
|
|
||||||
if (a->current_block != NULL) {
|
|
||||||
a->current_block->next = block;
|
|
||||||
block->prev = a->current_block;
|
|
||||||
}
|
}
|
||||||
a->current_block = block;
|
|
||||||
return block;
|
for_array(i, p->used_memblock) {
|
||||||
|
array_add(&p->unused_memblock, p->used_memblock[i]);
|
||||||
|
}
|
||||||
|
array_clear(&p->unused_memblock);
|
||||||
|
|
||||||
|
for_array(i, p->out_of_band_allocations) {
|
||||||
|
gb_free(p->block_allocator, p->out_of_band_allocations[i]);
|
||||||
|
}
|
||||||
|
array_clear(&p->out_of_band_allocations);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_dynamic_arena(DynamicArena *a, isize block_size) {
|
void pool_destroy(Pool *p) {
|
||||||
isize size = gb_size_of(DynamicArenaBlock) + block_size;
|
pool_free_all(p);
|
||||||
size = cast(isize)gb_align_forward(cast(void *)cast(uintptr)size, GB_DEFAULT_MEMORY_ALIGNMENT);
|
|
||||||
a->block_size = size;
|
|
||||||
a->start_block = add_dynamic_arena_block(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroy_dynamic_arena(DynamicArena *a) {
|
for_array(i, p->unused_memblock) {
|
||||||
DynamicArenaBlock *b = a->current_block;
|
gb_free(p->block_allocator, p->unused_memblock[i]);
|
||||||
while (b != NULL) {
|
|
||||||
gbVirtualMemory vm = b->vm;
|
|
||||||
b = b->prev;
|
|
||||||
gb_vm_free(b->vm);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GB_ALLOCATOR_PROC(dynamic_arena_allocator_proc) {
|
void pool_cycle_new_block(Pool *p) {
|
||||||
DynamicArena *a = cast(DynamicArena *)allocator_data;
|
GB_ASSERT_MSG(p->block_allocator.proc != NULL,
|
||||||
|
"You must call pool_init on a Pool before using it!");
|
||||||
|
|
||||||
|
if (p->current_memblock != NULL) {
|
||||||
|
array_add(&p->used_memblock, p->current_memblock);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 *new_block = NULL;
|
||||||
|
|
||||||
|
if (p->unused_memblock.count > 0) {
|
||||||
|
new_block = array_pop(&p->unused_memblock);
|
||||||
|
} else {
|
||||||
|
GB_ASSERT(p->block_allocator.proc != NULL);
|
||||||
|
new_block = cast(u8 *)gb_alloc_align(p->block_allocator, p->memblock_size, p->alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
p->bytes_left = p->memblock_size;
|
||||||
|
p->current_memblock = new_block;
|
||||||
|
p->current_memblock = new_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *pool_get(Pool *p,
|
||||||
|
isize size, isize alignment = 0) {
|
||||||
|
if (alignment <= 0) alignment = p->alignment;
|
||||||
|
|
||||||
|
isize extra = alignment - (size & alignment);
|
||||||
|
size += extra;
|
||||||
|
if (size >= p->out_of_band_size) {
|
||||||
|
GB_ASSERT(p->block_allocator.proc != NULL);
|
||||||
|
u8 *memory = cast(u8 *)gb_alloc_align(p->block_allocator, p->memblock_size, alignment);
|
||||||
|
if (memory != NULL) {
|
||||||
|
array_add(&p->out_of_band_allocations, memory);
|
||||||
|
}
|
||||||
|
return memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->bytes_left < size) {
|
||||||
|
pool_cycle_new_block(p);
|
||||||
|
if (p->current_memblock != NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 *res = p->current_pos;
|
||||||
|
p->current_pos += size;
|
||||||
|
p->bytes_left -= size;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gbAllocator pool_allocator(Pool *pool);
|
||||||
|
|
||||||
|
GB_ALLOCATOR_PROC(pool_allocator_procedure) {
|
||||||
|
Pool *p = cast(Pool *)allocator_data;
|
||||||
void *ptr = NULL;
|
void *ptr = NULL;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case gbAllocation_Alloc: {
|
case gbAllocation_Alloc:
|
||||||
|
return pool_get(p, size, alignment);
|
||||||
} break;
|
case gbAllocation_Free:
|
||||||
|
// Does nothing
|
||||||
case gbAllocation_Free: {
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case gbAllocation_Resize: {
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case gbAllocation_FreeAll:
|
|
||||||
GB_PANIC("free_all is not supported by this allocator");
|
|
||||||
break;
|
break;
|
||||||
|
case gbAllocation_FreeAll:
|
||||||
|
pool_free_all(p);
|
||||||
|
break;
|
||||||
|
case gbAllocation_Resize:
|
||||||
|
return gb_default_resize_align(pool_allocator(p), old_memory, old_size, size, alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
gbAllocator dynamic_arena_allocator(DynamicArena *a) {
|
gbAllocator pool_allocator(Pool *pool) {
|
||||||
gbAllocator allocator = {dynamic_arena_allocator_proc, a};
|
gbAllocator allocator;
|
||||||
|
allocator.proc = pool_allocator_procedure;
|
||||||
|
allocator.data = pool;
|
||||||
return allocator;
|
return allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,7 +285,6 @@ f64 gb_sqrt(f64 x) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define for_array(index_, array_) for (isize index_ = 0; index_ < (array_).count; index_++)
|
|
||||||
|
|
||||||
|
|
||||||
// Doubly Linked Lists
|
// Doubly Linked Lists
|
||||||
|
|||||||
+10
-9
@@ -7123,20 +7123,21 @@ void ir_init_module(irModule *m, Checker *c) {
|
|||||||
// TODO(bill): Determine a decent size for the arena
|
// TODO(bill): Determine a decent size for the arena
|
||||||
isize token_count = c->parser->total_token_count;
|
isize token_count = c->parser->total_token_count;
|
||||||
isize arena_size = 4 * token_count * gb_size_of(irValue);
|
isize arena_size = 4 * token_count * gb_size_of(irValue);
|
||||||
gb_arena_init_from_allocator(&m->arena, heap_allocator(), arena_size);
|
gb_arena_init_from_allocator(&m->arena, heap_allocator(), arena_size);
|
||||||
gb_arena_init_from_allocator(&m->tmp_arena, heap_allocator(), arena_size);
|
gb_arena_init_from_allocator(&m->tmp_arena, heap_allocator(), arena_size);
|
||||||
m->allocator = gb_arena_allocator(&m->arena);
|
// m->allocator = gb_arena_allocator(&m->arena);
|
||||||
|
m->allocator = heap_allocator();
|
||||||
m->tmp_allocator = gb_arena_allocator(&m->tmp_arena);
|
m->tmp_allocator = gb_arena_allocator(&m->tmp_arena);
|
||||||
m->info = &c->info;
|
m->info = &c->info;
|
||||||
|
|
||||||
map_init(&m->values, heap_allocator());
|
map_init(&m->values, heap_allocator());
|
||||||
map_init(&m->members, heap_allocator());
|
map_init(&m->members, heap_allocator());
|
||||||
map_init(&m->debug_info, heap_allocator());
|
map_init(&m->debug_info, heap_allocator());
|
||||||
map_init(&m->entity_names, heap_allocator());
|
map_init(&m->entity_names, heap_allocator());
|
||||||
array_init(&m->procs, heap_allocator());
|
array_init(&m->procs, heap_allocator());
|
||||||
array_init(&m->procs_to_generate, heap_allocator());
|
array_init(&m->procs_to_generate, heap_allocator());
|
||||||
array_init(&m->foreign_library_paths, heap_allocator());
|
array_init(&m->foreign_library_paths, heap_allocator());
|
||||||
map_init(&m->const_strings, heap_allocator());
|
map_init(&m->const_strings, heap_allocator());
|
||||||
|
|
||||||
// Default states
|
// Default states
|
||||||
m->stmt_state_flags = 0;
|
m->stmt_state_flags = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user