Browse Source

Unify `new`/`make` the internal logic between runtime and mem

gingerBill 4 years ago
parent
commit
4ccf135892
3 changed files with 77 additions and 50 deletions
  1. 39 26
      core/mem/alloc.odin
  2. 4 3
      core/mem/allocators.odin
  3. 34 21
      core/runtime/core_builtin.odin

+ 39 - 26
core/mem/alloc.odin

@@ -207,51 +207,54 @@ delete :: proc{
 };
 };
 
 
 
 
-new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> ^T {
+new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> (^T, Allocator_Error) {
 	return new_aligned(T, align_of(T), allocator, loc);
 	return new_aligned(T, align_of(T), allocator, loc);
 }
 }
-new_aligned :: proc($T: typeid, alignment: int, allocator := context.allocator, loc := #caller_location) -> ^T {
-	ptr := (^T)(alloc(size_of(T), alignment, allocator, loc));
-	if ptr != nil { ptr^ = T{}; }
-	return ptr;
+new_aligned :: proc($T: typeid, alignment: int, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) {
+	data := alloc_bytes(size_of(T), alignment, allocator, loc) or_return;
+	t = (^T)(raw_data(data));
+	return;
 }
 }
 new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> ^T {
 new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> ^T {
-	ptr := (^T)(alloc(size_of(T), align_of(T), allocator, loc));
-	if ptr != nil { ptr^ = data; }
-	return ptr;
+	data := alloc_bytes(size_of(T), alignment, allocator, loc) or_return;
+	t = (^T)(raw_data(data));
+	if t != nil {
+		t^ = data;
+	}
+	return;
 }
 }
 
 
+DEFAULT_RESERVE_CAPACITY :: 16;
 
 
-make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> T {
-	return make_aligned(T, len, align_of(E), allocator, loc);
-}
-make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> T {
+make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (slice: T, err: Allocator_Error) {
 	runtime.make_slice_error_loc(loc, len);
 	runtime.make_slice_error_loc(loc, len);
-	data := alloc(size_of(E)*len, alignment, allocator, loc);
+	data := alloc_bytes(size_of(E)*len, alignment, allocator, loc) or_return;
 	if data == nil && size_of(E) != 0 {
 	if data == nil && size_of(E) != 0 {
-		return nil;
+		return;
 	}
 	}
-	zero(data, size_of(E)*len);
-	s := Raw_Slice{data, len};
-	return transmute(T)s;
+	slice = transmute(T)Raw_Slice{raw_data(data), len};
+	return;
 }
 }
-make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> T {
-	return make_dynamic_array_len_cap(T, 0, 16, allocator, loc);
+make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) {
+	return make_aligned(T, len, align_of(E), allocator, loc);
 }
 }
-make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> T {
+make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) {
+	return make_dynamic_array_len_cap(T, 0, DEFAULT_RESERVE_CAPACITY, allocator, loc);
+}
+make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) {
 	return make_dynamic_array_len_cap(T, len, len, allocator, loc);
 	return make_dynamic_array_len_cap(T, len, len, allocator, loc);
 }
 }
-make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> T {
+make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) {
 	runtime.make_dynamic_array_error_loc(loc, len, cap);
 	runtime.make_dynamic_array_error_loc(loc, len, cap);
-	data := alloc(size_of(E)*cap, align_of(E), allocator, loc);
-	s := Raw_Dynamic_Array{data, len, cap, allocator};
+	data := alloc_bytes(size_of(E)*cap, align_of(E), allocator, loc) or_return;
+	s := Raw_Dynamic_Array{raw_data(data), len, cap, allocator};
 	if data == nil && size_of(E) != 0 {
 	if data == nil && size_of(E) != 0 {
 		s.len, s.cap = 0, 0;
 		s.len, s.cap = 0, 0;
 	}
 	}
-	zero(data, size_of(E)*len);
-	return transmute(T)s;
+	array = transmute(T)s;
+	return;
 }
 }
-make_map :: proc($T: typeid/map[$K]$E, #any_int cap: int = 16, allocator := context.allocator, loc := #caller_location) -> T {
+make_map :: proc($T: typeid/map[$K]$E, #any_int cap: int = DEFAULT_RESERVE_CAPACITY, allocator := context.allocator, loc := #caller_location) -> T {
 	runtime.make_map_expr_error_loc(loc, cap);
 	runtime.make_map_expr_error_loc(loc, cap);
 	context.allocator = allocator;
 	context.allocator = allocator;
 
 
@@ -259,6 +262,15 @@ make_map :: proc($T: typeid/map[$K]$E, #any_int cap: int = 16, allocator := cont
 	reserve_map(&m, cap);
 	reserve_map(&m, cap);
 	return m;
 	return m;
 }
 }
+make_multi_pointer :: proc($T: typeid/[^]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (mp: T, err: Allocator_Error) {
+	runtime.make_slice_error_loc(loc, len);
+	data := alloc_bytes(size_of(E)*len, align_of(E), allocator, loc) or_return;
+	if data == nil && size_of(E) != 0 {
+		return;
+	}
+	mp = cast(T)raw_data(data);
+	return;
+}
 
 
 make :: proc{
 make :: proc{
 	make_slice,
 	make_slice,
@@ -266,6 +278,7 @@ make :: proc{
 	make_dynamic_array_len,
 	make_dynamic_array_len,
 	make_dynamic_array_len_cap,
 	make_dynamic_array_len_cap,
 	make_map,
 	make_map,
+	make_multi_pointer,
 };
 };
 
 
 
 

+ 4 - 3
core/mem/allocators.odin

@@ -114,12 +114,13 @@ Scratch_Allocator :: struct {
 	leaked_allocations: [dynamic][]byte,
 	leaked_allocations: [dynamic][]byte,
 }
 }
 
 
-scratch_allocator_init :: proc(s: ^Scratch_Allocator, size: int, backup_allocator := context.allocator) {
-	s.data = make_aligned([]byte, size, 2*align_of(rawptr), backup_allocator);
+scratch_allocator_init :: proc(s: ^Scratch_Allocator, size: int, backup_allocator := context.allocator) -> Allocator_Error {
+	s.data = make_aligned([]byte, size, 2*align_of(rawptr), backup_allocator) or_return;
 	s.curr_offset = 0;
 	s.curr_offset = 0;
 	s.prev_allocation = nil;
 	s.prev_allocation = nil;
 	s.backup_allocator = backup_allocator;
 	s.backup_allocator = backup_allocator;
 	s.leaked_allocations.allocator = backup_allocator;
 	s.leaked_allocations.allocator = backup_allocator;
+	return nil;
 }
 }
 
 
 scratch_allocator_destroy :: proc(s: ^Scratch_Allocator) {
 scratch_allocator_destroy :: proc(s: ^Scratch_Allocator) {
@@ -188,7 +189,7 @@ scratch_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
 			return ptr, err;
 			return ptr, err;
 		}
 		}
 		if s.leaked_allocations == nil {
 		if s.leaked_allocations == nil {
-			s.leaked_allocations = make([dynamic][]byte, a);
+			s.leaked_allocations, err = make([dynamic][]byte, a);
 		}
 		}
 		append(&s.leaked_allocations, ptr);
 		append(&s.leaked_allocations, ptr);
 
 

+ 34 - 21
core/runtime/core_builtin.odin

@@ -170,18 +170,22 @@ delete :: proc{
 // return is a pointer to a newly allocated value of that type using the specified allocator, default is context.allocator
 // return is a pointer to a newly allocated value of that type using the specified allocator, default is context.allocator
 @builtin
 @builtin
 new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> (^T, Allocator_Error) #optional_second {
 new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> (^T, Allocator_Error) #optional_second {
-	ptr, err := mem_alloc(size_of(T), align_of(T), allocator, loc);
-	return (^T)(ptr), err;
+	return new_aligned(T, align_of(T), allocator, loc);
+}
+new_aligned :: proc($T: typeid, alignment: int, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) {
+	data := mem_alloc_bytes(size_of(T), alignment, allocator, loc) or_return;
+	t = (^T)(raw_data(data));
+	return;
 }
 }
 
 
 @builtin
 @builtin
-new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> (^T, Allocator_Error) #optional_second {
-	ptr, err := mem_alloc(size_of(T), align_of(T), allocator, loc);
-	res := (^T)(ptr);
-	if ptr != nil && err != .Out_Of_Memory {
-		res^ = data;
+new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) #optional_second {
+	data := alloc_bytes(size_of(T), alignment, allocator, loc) or_return;
+	t = (^T)(raw_data(data));
+	if t != nil {
+		t^ = data;
 	}
 	}
-	return res, err;
+	return;
 }
 }
 
 
 DEFAULT_RESERVE_CAPACITY :: 16;
 DEFAULT_RESERVE_CAPACITY :: 16;
@@ -196,33 +200,30 @@ make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocat
 	return transmute(T)s, err;
 	return transmute(T)s, err;
 }
 }
 
 
-@builtin
+@(builtin)
 make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second {
 make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second {
 	return make_aligned(T, len, align_of(E), allocator, loc);
 	return make_aligned(T, len, align_of(E), allocator, loc);
 }
 }
-
-@builtin
+@(builtin)
 make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second {
 make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second {
 	return make_dynamic_array_len_cap(T, 0, DEFAULT_RESERVE_CAPACITY, allocator, loc);
 	return make_dynamic_array_len_cap(T, 0, DEFAULT_RESERVE_CAPACITY, allocator, loc);
 }
 }
-
-@builtin
+@(builtin)
 make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second {
 make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second {
 	return make_dynamic_array_len_cap(T, len, len, allocator, loc);
 	return make_dynamic_array_len_cap(T, len, len, allocator, loc);
 }
 }
-
-@builtin
-make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second {
+@(builtin)
+make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_second {
 	make_dynamic_array_error_loc(loc, len, cap);
 	make_dynamic_array_error_loc(loc, len, cap);
-	data, err := mem_alloc(size_of(E)*cap, align_of(E), allocator, loc);
-	s := Raw_Dynamic_Array{data, len, cap, allocator};
+	data := mem_alloc_bytes(size_of(E)*cap, align_of(E), allocator, loc) or_return;
+	s := Raw_Dynamic_Array{raw_data(data), len, cap, allocator};
 	if data == nil && size_of(E) != 0 {
 	if data == nil && size_of(E) != 0 {
 		s.len, s.cap = 0, 0;
 		s.len, s.cap = 0, 0;
 	}
 	}
-	return transmute(T)s, err;
+	array = transmute(T)s;
+	return;
 }
 }
-
-@builtin
+@(builtin)
 make_map :: proc($T: typeid/map[$K]$E, #any_int cap: int = DEFAULT_RESERVE_CAPACITY, allocator := context.allocator, loc := #caller_location) -> T {
 make_map :: proc($T: typeid/map[$K]$E, #any_int cap: int = DEFAULT_RESERVE_CAPACITY, allocator := context.allocator, loc := #caller_location) -> T {
 	make_map_expr_error_loc(loc, cap);
 	make_map_expr_error_loc(loc, cap);
 	context.allocator = allocator;
 	context.allocator = allocator;
@@ -231,6 +232,17 @@ make_map :: proc($T: typeid/map[$K]$E, #any_int cap: int = DEFAULT_RESERVE_CAPAC
 	reserve_map(&m, cap);
 	reserve_map(&m, cap);
 	return m;
 	return m;
 }
 }
+@(builtin)
+make_multi_pointer :: proc($T: typeid/[^]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (mp: T, err: Allocator_Error) #optional_second {
+	make_slice_error_loc(loc, len);
+	data := mem_alloc_bytes(size_of(E)*len, align_of(E), allocator, loc) or_return;
+	if data == nil && size_of(E) != 0 {
+		return;
+	}
+	mp = cast(T)raw_data(data);
+	return;
+}
+
 
 
 // The make built-in procedure allocates and initializes a value of type slice, dynamic array, or map (only)
 // The make built-in procedure allocates and initializes a value of type slice, dynamic array, or map (only)
 // Similar to new, the first argument is a type, not a value. Unlike new, make's return type is the same as the
 // Similar to new, the first argument is a type, not a value. Unlike new, make's return type is the same as the
@@ -243,6 +255,7 @@ make :: proc{
 	make_dynamic_array_len,
 	make_dynamic_array_len,
 	make_dynamic_array_len_cap,
 	make_dynamic_array_len_cap,
 	make_map,
 	make_map,
+	make_multi_pointer,
 };
 };