Browse Source

Merge pull request #3001 from colrdavidson/unsafe_mem

add non-zeroing append and resize
gingerBill 1 year ago
parent
commit
37ae9eb609

+ 9 - 0
core/log/log_allocator.odin

@@ -96,6 +96,15 @@ log_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode,
 			str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size, size, alignment)
 			str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size, size, alignment)
 			context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
 			context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
 
 
+		case .Resize_Non_Zeroed:
+			format: string
+			switch la.size_fmt {
+			case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Resize_Non_Zeroed, ptr=%p, old_size=%d, size=%d, alignment=%d)"
+			case .Human: format = "%s%s>>> ALLOCATOR(mode=.Resize_Non_Zeroed, ptr=%p, old_size=%m, size=%m, alignment=%d)"
+			}
+			str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size, size, alignment)
+			context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
+
 		case .Query_Features:
 		case .Query_Features:
 			str := fmt.bprintf(buf[:], "%s%sALLOCATOR(mode=.Query_Features)", la.prefix, padding)
 			str := fmt.bprintf(buf[:], "%s%sALLOCATOR(mode=.Query_Features)", la.prefix, padding)
 			context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
 			context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)

+ 24 - 2
core/mem/alloc.odin

@@ -11,6 +11,8 @@ Allocator_Mode :: enum byte {
 	Free_All,
 	Free_All,
 	Resize,
 	Resize,
 	Query_Features,
 	Query_Features,
+	Alloc_Non_Zeroed,
+	Resize_Non_Zeroed,
 }
 }
 */
 */
 
 
@@ -243,12 +245,26 @@ default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment:
 	res = raw_data(data)
 	res = raw_data(data)
 	return
 	return
 }
 }
+
+@(require_results)
+default_resize_bytes_align_non_zeroed :: proc(old_data: []byte, new_size, alignment: int, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
+	return _default_resize_bytes_align(old_data, new_size, alignment, false, allocator, loc)
+}
 @(require_results)
 @(require_results)
 default_resize_bytes_align :: proc(old_data: []byte, new_size, alignment: int, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
 default_resize_bytes_align :: proc(old_data: []byte, new_size, alignment: int, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
+	return _default_resize_bytes_align(old_data, new_size, alignment, true, allocator, loc)
+}
+
+@(require_results)
+_default_resize_bytes_align :: #force_inline proc(old_data: []byte, new_size, alignment: int, should_zero: bool, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
 	old_memory := raw_data(old_data)
 	old_memory := raw_data(old_data)
 	old_size := len(old_data)
 	old_size := len(old_data)
 	if old_memory == nil {
 	if old_memory == nil {
-		return alloc_bytes(new_size, alignment, allocator, loc)
+		if should_zero {
+			return alloc_bytes(new_size, alignment, allocator, loc)
+		} else {
+			return alloc_bytes_non_zeroed(new_size, alignment, allocator, loc)
+		}
 	}
 	}
 
 
 	if new_size == 0 {
 	if new_size == 0 {
@@ -260,7 +276,13 @@ default_resize_bytes_align :: proc(old_data: []byte, new_size, alignment: int, a
 		return old_data, .None
 		return old_data, .None
 	}
 	}
 
 
-	new_memory, err := alloc_bytes(new_size, alignment, allocator, loc)
+	new_memory : []byte
+	err : Allocator_Error
+	if should_zero {
+		new_memory, err = alloc_bytes(new_size, alignment, allocator, loc)
+	} else {
+		new_memory, err = alloc_bytes_non_zeroed(new_size, alignment, allocator, loc)
+	}
 	if new_memory == nil || err != nil {
 	if new_memory == nil || err != nil {
 		return nil, err
 		return nil, err
 	}
 	}

+ 23 - 16
core/mem/allocators.odin

@@ -85,13 +85,16 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
 	case .Free_All:
 	case .Free_All:
 		arena.offset = 0
 		arena.offset = 0
 
 
-	case .Resize:
-		return default_resize_bytes_align(byte_slice(old_memory, old_size), size, alignment, arena_allocator(arena))
+    case .Resize:
+        return default_resize_bytes_align(byte_slice(old_memory, old_size), size, alignment, arena_allocator(arena))
+
+    case .Resize_Non_Zeroed:
+        return default_resize_bytes_align_non_zeroed(byte_slice(old_memory, old_size), size, alignment, arena_allocator(arena))
 
 
 	case .Query_Features:
 	case .Query_Features:
 		set := (^Allocator_Mode_Set)(old_memory)
 		set := (^Allocator_Mode_Set)(old_memory)
 		if set != nil {
 		if set != nil {
-			set^ = {.Alloc, .Alloc_Non_Zeroed, .Free_All, .Resize, .Query_Features}
+			set^ = {.Alloc, .Alloc_Non_Zeroed, .Free_All, .Resize, .Resize_Non_Zeroed, .Query_Features}
 		}
 		}
 		return nil, nil
 		return nil, nil
 
 
@@ -259,7 +262,7 @@ scratch_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
 		}
 		}
 		clear(&s.leaked_allocations)
 		clear(&s.leaked_allocations)
 
 
-	case .Resize:
+	case .Resize, .Resize_Non_Zeroed:
 		begin := uintptr(raw_data(s.data))
 		begin := uintptr(raw_data(s.data))
 		end := begin + uintptr(len(s.data))
 		end := begin + uintptr(len(s.data))
 		old_ptr := uintptr(old_memory)
 		old_ptr := uintptr(old_memory)
@@ -278,7 +281,7 @@ scratch_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
 	case .Query_Features:
 	case .Query_Features:
 		set := (^Allocator_Mode_Set)(old_memory)
 		set := (^Allocator_Mode_Set)(old_memory)
 		if set != nil {
 		if set != nil {
-			set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Query_Features}
+			set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Resize_Non_Zeroed, .Query_Features}
 		}
 		}
 		return nil, nil
 		return nil, nil
 
 
@@ -406,9 +409,9 @@ stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
 		s.prev_offset = 0
 		s.prev_offset = 0
 		s.curr_offset = 0
 		s.curr_offset = 0
 
 
-	case .Resize:
+	case .Resize, .Resize_Non_Zeroed:
 		if old_memory == nil {
 		if old_memory == nil {
-			return raw_alloc(s, size, alignment, true)
+			return raw_alloc(s, size, alignment, mode == .Resize)
 		}
 		}
 		if size == 0 {
 		if size == 0 {
 			return nil, nil
 			return nil, nil
@@ -434,7 +437,7 @@ stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
 		old_offset := int(curr_addr - uintptr(header.padding) - uintptr(raw_data(s.data)))
 		old_offset := int(curr_addr - uintptr(header.padding) - uintptr(raw_data(s.data)))
 
 
 		if old_offset != header.prev_offset {
 		if old_offset != header.prev_offset {
-			data, err := raw_alloc(s, size, alignment, true)
+			data, err := raw_alloc(s, size, alignment, mode == .Resize)
 			if err == nil {
 			if err == nil {
 				runtime.copy(data, byte_slice(old_memory, old_size))
 				runtime.copy(data, byte_slice(old_memory, old_size))
 			}
 			}
@@ -455,7 +458,7 @@ stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
 	case .Query_Features:
 	case .Query_Features:
 		set := (^Allocator_Mode_Set)(old_memory)
 		set := (^Allocator_Mode_Set)(old_memory)
 		if set != nil {
 		if set != nil {
-			set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Query_Features}
+			set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Resize_Non_Zeroed, .Query_Features}
 		}
 		}
 		return nil, nil
 		return nil, nil
 	case .Query_Info:
 	case .Query_Info:
@@ -565,9 +568,9 @@ small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
 	case .Free_All:
 	case .Free_All:
 		s.offset = 0
 		s.offset = 0
 
 
-	case .Resize:
+	case .Resize, .Resize_Non_Zeroed:
 		if old_memory == nil {
 		if old_memory == nil {
-			return raw_alloc(s, size, align, true)
+			return raw_alloc(s, size, align, mode == .Resize)
 		}
 		}
 		if size == 0 {
 		if size == 0 {
 			return nil, nil
 			return nil, nil
@@ -590,7 +593,7 @@ small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
 			return byte_slice(old_memory, size), nil
 			return byte_slice(old_memory, size), nil
 		}
 		}
 
 
-		data, err := raw_alloc(s, size, align, true)
+		data, err := raw_alloc(s, size, align, mode == .Resize)
 		if err == nil {
 		if err == nil {
 			runtime.copy(data, byte_slice(old_memory, old_size))
 			runtime.copy(data, byte_slice(old_memory, old_size))
 		}
 		}
@@ -599,7 +602,7 @@ small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
 	case .Query_Features:
 	case .Query_Features:
 		set := (^Allocator_Mode_Set)(old_memory)
 		set := (^Allocator_Mode_Set)(old_memory)
 		if set != nil {
 		if set != nil {
-			set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Query_Features}
+			set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Resize_Non_Zeroed, .Query_Features}
 		}
 		}
 		return nil, nil
 		return nil, nil
 
 
@@ -649,7 +652,7 @@ dynamic_pool_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode
 	case .Free_All:
 	case .Free_All:
 		dynamic_pool_free_all(pool)
 		dynamic_pool_free_all(pool)
 		return nil, nil
 		return nil, nil
-	case .Resize:
+	case .Resize, .Resize_Non_Zeroed:
 		if old_size >= size {
 		if old_size >= size {
 			return byte_slice(old_memory, size), nil
 			return byte_slice(old_memory, size), nil
 		}
 		}
@@ -662,7 +665,7 @@ dynamic_pool_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode
 	case .Query_Features:
 	case .Query_Features:
 		set := (^Allocator_Mode_Set)(old_memory)
 		set := (^Allocator_Mode_Set)(old_memory)
 		if set != nil {
 		if set != nil {
-			set^ = {.Alloc, .Alloc_Non_Zeroed, .Free_All, .Resize, .Query_Features, .Query_Info}
+			set^ = {.Alloc, .Alloc_Non_Zeroed, .Free_All, .Resize, .Resize_Non_Zeroed, .Query_Features, .Query_Info}
 		}
 		}
 		return nil, nil
 		return nil, nil
 
 
@@ -826,6 +829,10 @@ panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
 		if size > 0 {
 		if size > 0 {
 			panic("mem: panic allocator, .Resize called", loc=loc)
 			panic("mem: panic allocator, .Resize called", loc=loc)
 		}
 		}
+	case .Resize_Non_Zeroed:
+		if size > 0 {
+			panic("mem: panic allocator, .Resize_Non_Zeroed called", loc=loc)
+		}
 	case .Free:
 	case .Free:
 		if old_memory != nil {
 		if old_memory != nil {
 			panic("mem: panic allocator, .Free called", loc=loc)
 			panic("mem: panic allocator, .Free called", loc=loc)
@@ -958,7 +965,7 @@ tracking_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
 		if data.clear_on_free_all {
 		if data.clear_on_free_all {
 			clear_map(&data.allocation_map)
 			clear_map(&data.allocation_map)
 		}	
 		}	
-	case .Resize:
+	case .Resize, .Resize_Non_Zeroed:
 		if old_memory != result_ptr {
 		if old_memory != result_ptr {
 			delete_key(&data.allocation_map, old_memory)
 			delete_key(&data.allocation_map, old_memory)
 		}
 		}

+ 1 - 1
core/mem/virtual/arena.odin

@@ -288,7 +288,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
 		err = .Mode_Not_Implemented
 		err = .Mode_Not_Implemented
 	case .Free_All:
 	case .Free_All:
 		arena_free_all(arena, location)
 		arena_free_all(arena, location)
-	case .Resize:
+	case .Resize, .Resize_Non_Zeroed:
 		old_data := ([^]byte)(old_memory)
 		old_data := ([^]byte)(old_memory)
 
 
 		switch {
 		switch {

+ 7 - 7
core/os/os.odin

@@ -210,15 +210,15 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
 		}
 		}
 	}
 	}
 
 
-	aligned_resize :: proc(p: rawptr, old_size: int, new_size: int, new_alignment: int) -> (new_memory: []byte, err: mem.Allocator_Error) {
+	aligned_resize :: proc(p: rawptr, old_size: int, new_size: int, new_alignment: int, zero_memory := true) -> (new_memory: []byte, err: mem.Allocator_Error) {
 		if p == nil {
 		if p == nil {
 			return nil, nil
 			return nil, nil
 		}
 		}
 
 
-		new_memory = aligned_alloc(new_size, new_alignment, p) or_return
+		new_memory = aligned_alloc(new_size, new_alignment, p, zero_memory) or_return
 
 
 		// NOTE: heap_resize does not zero the new memory, so we do it
 		// NOTE: heap_resize does not zero the new memory, so we do it
-		if new_size > old_size {
+		if zero_memory && new_size > old_size {
 			new_region := mem.raw_data(new_memory[old_size:])
 			new_region := mem.raw_data(new_memory[old_size:])
 			mem.zero(new_region, new_size - old_size)
 			mem.zero(new_region, new_size - old_size)
 		}
 		}
@@ -235,16 +235,16 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
 	case .Free_All:
 	case .Free_All:
 		return nil, .Mode_Not_Implemented
 		return nil, .Mode_Not_Implemented
 
 
-	case .Resize:
+	case .Resize, .Resize_Non_Zeroed:
 		if old_memory == nil {
 		if old_memory == nil {
-			return aligned_alloc(size, alignment)
+			return aligned_alloc(size, alignment, nil, mode == .Resize)
 		}
 		}
-		return aligned_resize(old_memory, old_size, size, alignment)
+		return aligned_resize(old_memory, old_size, size, alignment, mode == .Resize)
 
 
 	case .Query_Features:
 	case .Query_Features:
 		set := (^mem.Allocator_Mode_Set)(old_memory)
 		set := (^mem.Allocator_Mode_Set)(old_memory)
 		if set != nil {
 		if set != nil {
-			set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Resize, .Query_Features}
+			set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Resize, .Resize_Non_Zeroed, .Query_Features}
 		}
 		}
 		return nil, nil
 		return nil, nil
 
 

+ 1 - 0
core/runtime/core.odin

@@ -307,6 +307,7 @@ Allocator_Mode :: enum byte {
 	Query_Features,
 	Query_Features,
 	Query_Info,
 	Query_Info,
 	Alloc_Non_Zeroed,
 	Alloc_Non_Zeroed,
+	Resize_Non_Zeroed,
 }
 }
 
 
 Allocator_Mode_Set :: distinct bit_set[Allocator_Mode]
 Allocator_Mode_Set :: distinct bit_set[Allocator_Mode]

+ 90 - 15
core/runtime/core_builtin.odin

@@ -169,10 +169,16 @@ clear :: proc{clear_dynamic_array, clear_map}
 @builtin
 @builtin
 reserve :: proc{reserve_dynamic_array, reserve_map}
 reserve :: proc{reserve_dynamic_array, reserve_map}
 
 
+@builtin
+non_zero_reserve :: proc{non_zero_reserve_dynamic_array}
+
 // `resize` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`).
 // `resize` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`).
 @builtin
 @builtin
 resize :: proc{resize_dynamic_array}
 resize :: proc{resize_dynamic_array}
 
 
+@builtin
+non_zero_resize :: proc{non_zero_resize_dynamic_array}
+
 // Shrinks the capacity of a dynamic array or map down to the current length, or the given capacity.
 // Shrinks the capacity of a dynamic array or map down to the current length, or the given capacity.
 @builtin
 @builtin
 shrink :: proc{shrink_dynamic_array, shrink_map}
 shrink :: proc{shrink_dynamic_array, shrink_map}
@@ -406,10 +412,7 @@ delete_key :: proc(m: ^$T/map[$K]$V, key: K) -> (deleted_key: K, deleted_value:
 	return
 	return
 }
 }
 
 
-
-
-@builtin
-append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
+_append_elem :: #force_inline proc(array: ^$T/[dynamic]$E, arg: E, should_zero: bool, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
 	if array == nil {
 	if array == nil {
 		return 0, nil
 		return 0, nil
 	}
 	}
@@ -420,7 +423,13 @@ append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) ->
 	} else {
 	} else {
 		if cap(array) < len(array)+1 {
 		if cap(array) < len(array)+1 {
 			cap := 2 * cap(array) + max(8, 1)
 			cap := 2 * cap(array) + max(8, 1)
-			err = reserve(array, cap, loc) // do not 'or_return' here as it could be a partial success
+
+			// do not 'or_return' here as it could be a partial success
+			if should_zero {
+				err = reserve(array, cap, loc)
+			} else {
+				err = non_zero_reserve(array, cap, loc) 
+			}
 		}
 		}
 		if cap(array)-len(array) > 0 {
 		if cap(array)-len(array) > 0 {
 			a := (^Raw_Dynamic_Array)(array)
 			a := (^Raw_Dynamic_Array)(array)
@@ -437,7 +446,16 @@ append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) ->
 }
 }
 
 
 @builtin
 @builtin
-append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
+append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
+	return _append_elem(array, arg, true, loc=loc)
+}
+
+@builtin
+non_zero_append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
+	return _append_elem(array, arg, false, loc=loc)
+}
+
+_append_elems :: #force_inline proc(array: ^$T/[dynamic]$E, should_zero: bool, loc := #caller_location, args: ..E) -> (n: int, err: Allocator_Error) #optional_allocator_error {
 	if array == nil {
 	if array == nil {
 		return 0, nil
 		return 0, nil
 	}
 	}
@@ -454,7 +472,13 @@ append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location)
 	} else {
 	} else {
 		if cap(array) < len(array)+arg_len {
 		if cap(array) < len(array)+arg_len {
 			cap := 2 * cap(array) + max(8, arg_len)
 			cap := 2 * cap(array) + max(8, arg_len)
-			err = reserve(array, cap, loc)  // do not 'or_return' here as it could be a partial success
+
+			// do not 'or_return' here as it could be a partial success
+			if should_zero {
+				err = reserve(array, cap, loc)
+			} else {
+				err = non_zero_reserve(array, cap, loc)
+			}
 		}
 		}
 		arg_len = min(cap(array)-len(array), arg_len)
 		arg_len = min(cap(array)-len(array), arg_len)
 		if arg_len > 0 {
 		if arg_len > 0 {
@@ -470,11 +494,33 @@ append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location)
 	}
 	}
 }
 }
 
 
+@builtin
+append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
+	return _append_elems(array, true, loc, ..args)
+}
+
+@builtin
+non_zero_append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
+	return _append_elems(array, false, loc, ..args)
+}
+
 // The append_string built-in procedure appends a string to the end of a [dynamic]u8 like type
 // The append_string built-in procedure appends a string to the end of a [dynamic]u8 like type
+_append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, should_zero: bool, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
+	args := transmute([]E)arg
+	if should_zero { 
+		return append_elems(array, ..args, loc=loc)
+	} else {
+		return non_zero_append_elems(array, ..args, loc=loc)
+	}
+}
+
 @builtin
 @builtin
 append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
 append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
-	args := transmute([]E)arg
-	return append_elems(array, ..args, loc=loc)
+	return _append_elem_string(array, arg, true, loc)
+}
+@builtin
+non_zero_append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
+	return _append_elem_string(array, arg, false, loc)
 }
 }
 
 
 
 
@@ -494,6 +540,7 @@ append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_
 
 
 // The append built-in procedure appends elements to the end of a dynamic array
 // The append built-in procedure appends elements to the end of a dynamic array
 @builtin append :: proc{append_elem, append_elems, append_elem_string}
 @builtin append :: proc{append_elem, append_elems, append_elem_string}
+@builtin non_zero_append :: proc{non_zero_append_elem, non_zero_append_elems, non_zero_append_elem_string}
 
 
 
 
 @builtin
 @builtin
@@ -638,8 +685,7 @@ clear_dynamic_array :: proc "contextless" (array: ^$T/[dynamic]$E) {
 // `reserve_dynamic_array` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`).
 // `reserve_dynamic_array` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`).
 //
 //
 // Note: Prefer the procedure group `reserve`.
 // Note: Prefer the procedure group `reserve`.
-@builtin
-reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
+_reserve_dynamic_array :: #force_inline proc(array: ^$T/[dynamic]$E, capacity: int, should_zero: bool, loc := #caller_location) -> Allocator_Error {
 	if array == nil {
 	if array == nil {
 		return nil
 		return nil
 	}
 	}
@@ -658,7 +704,12 @@ reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #cal
 	new_size  := capacity * size_of(E)
 	new_size  := capacity * size_of(E)
 	allocator := a.allocator
 	allocator := a.allocator
 
 
-	new_data := mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return
+	new_data: []byte
+	if should_zero {
+		new_data = mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return
+	} else {
+		new_data = non_zero_mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return
+	}
 	if new_data == nil && new_size > 0 {
 	if new_data == nil && new_size > 0 {
 		return .Out_Of_Memory
 		return .Out_Of_Memory
 	}
 	}
@@ -668,11 +719,20 @@ reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #cal
 	return nil
 	return nil
 }
 }
 
 
+@builtin
+reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
+	return _reserve_dynamic_array(array, capacity, true, loc)
+}
+
+@builtin
+non_zero_reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
+	return _reserve_dynamic_array(array, capacity, false, loc)
+}
+
 // `resize_dynamic_array` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`).
 // `resize_dynamic_array` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`).
 //
 //
 // Note: Prefer the procedure group `resize`
 // Note: Prefer the procedure group `resize`
-@builtin
-resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error {
+_resize_dynamic_array :: #force_inline proc(array: ^$T/[dynamic]$E, length: int, should_zero: bool, loc := #caller_location) -> Allocator_Error {
 	if array == nil {
 	if array == nil {
 		return nil
 		return nil
 	}
 	}
@@ -692,7 +752,12 @@ resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller
 	new_size  := length * size_of(E)
 	new_size  := length * size_of(E)
 	allocator := a.allocator
 	allocator := a.allocator
 
 
-	new_data := mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return
+	new_data : []byte
+	if should_zero {
+		new_data = mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return
+	} else {
+		new_data = non_zero_mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return
+	}
 	if new_data == nil && new_size > 0 {
 	if new_data == nil && new_size > 0 {
 		return .Out_Of_Memory
 		return .Out_Of_Memory
 	}
 	}
@@ -703,6 +768,16 @@ resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller
 	return nil
 	return nil
 }
 }
 
 
+@builtin
+resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error {
+	return _resize_dynamic_array(array, length, true, loc=loc)
+}
+
+@builtin
+non_zero_resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error {
+	return _resize_dynamic_array(array, length, false, loc=loc)
+}
+
 /*
 /*
 	Shrinks the capacity of a dynamic array down to the current length, or the given capacity.
 	Shrinks the capacity of a dynamic array down to the current length, or the given capacity.
 
 

+ 1 - 1
core/runtime/default_allocators_arena.odin

@@ -195,7 +195,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
 		err = .Mode_Not_Implemented
 		err = .Mode_Not_Implemented
 	case .Free_All:
 	case .Free_All:
 		arena_free_all(arena, location)
 		arena_free_all(arena, location)
-	case .Resize:
+	case .Resize, .Resize_Non_Zeroed:
 		old_data := ([^]byte)(old_memory)
 		old_data := ([^]byte)(old_memory)
 
 
 		switch {
 		switch {

+ 5 - 1
core/runtime/default_allocators_nil.odin

@@ -10,7 +10,7 @@ nil_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
 		return nil, .None
 		return nil, .None
 	case .Free_All:
 	case .Free_All:
 		return nil, .Mode_Not_Implemented
 		return nil, .Mode_Not_Implemented
-	case .Resize:
+	case .Resize, .Resize_Non_Zeroed:
 		if size == 0 {
 		if size == 0 {
 			return nil, .None
 			return nil, .None
 		}
 		}
@@ -55,6 +55,10 @@ panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
 		if size > 0 {
 		if size > 0 {
 			panic("panic allocator, .Resize called", loc=loc)
 			panic("panic allocator, .Resize called", loc=loc)
 		}
 		}
+	case .Resize_Non_Zeroed:
+		if size > 0 {
+			panic("panic allocator, .Alloc_Non_Zeroed called", loc=loc)
+		}
 	case .Free:
 	case .Free:
 		if old_memory != nil {
 		if old_memory != nil {
 			panic("panic allocator, .Free called", loc=loc)
 			panic("panic allocator, .Free called", loc=loc)

+ 2 - 2
core/runtime/default_allocators_windows.odin

@@ -19,7 +19,7 @@ when ODIN_DEFAULT_TO_NIL_ALLOCATOR {
 		case .Free_All:
 		case .Free_All:
 			return nil, .Mode_Not_Implemented
 			return nil, .Mode_Not_Implemented
 
 
-		case .Resize:
+		case .Resize, .Resize_Non_Zeroed:
 			data, err = _windows_default_resize(old_memory, old_size, size, alignment)
 			data, err = _windows_default_resize(old_memory, old_size, size, alignment)
 
 
 		case .Query_Features:
 		case .Query_Features:
@@ -41,4 +41,4 @@ when ODIN_DEFAULT_TO_NIL_ALLOCATOR {
 			data = nil,
 			data = nil,
 		}
 		}
 	}
 	}
-}
+}

+ 23 - 4
core/runtime/internal.odin

@@ -187,7 +187,7 @@ mem_free_all :: #force_inline proc(allocator := context.allocator, loc := #calle
 	return
 	return
 }
 }
 
 
-mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
+_mem_resize :: #force_inline proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, should_zero: bool, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
 	if allocator.procedure == nil {
 	if allocator.procedure == nil {
 		return nil, nil
 		return nil, nil
 	}
 	}
@@ -198,15 +198,27 @@ mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAUL
 		}
 		}
 		return
 		return
 	} else if ptr == nil {
 	} else if ptr == nil {
-		return allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc)
+		if should_zero {
+			return allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc)
+		} else {
+			return allocator.procedure(allocator.data, .Alloc_Non_Zeroed, new_size, alignment, nil, 0, loc)
+		}
 	} else if old_size == new_size && uintptr(ptr) % uintptr(alignment) == 0 {
 	} else if old_size == new_size && uintptr(ptr) % uintptr(alignment) == 0 {
 		data = ([^]byte)(ptr)[:old_size]
 		data = ([^]byte)(ptr)[:old_size]
 		return
 		return
 	}
 	}
 
 
-	data, err = allocator.procedure(allocator.data, .Resize, new_size, alignment, ptr, old_size, loc)
+	if should_zero {
+		data, err = allocator.procedure(allocator.data, .Resize, new_size, alignment, ptr, old_size, loc)
+	} else {
+		data, err = allocator.procedure(allocator.data, .Resize_Non_Zeroed, new_size, alignment, ptr, old_size, loc)
+	}
 	if err == .Mode_Not_Implemented {
 	if err == .Mode_Not_Implemented {
-		data, err = allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc)
+		if should_zero {
+			data, err = allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc)
+		} else {
+			data, err = allocator.procedure(allocator.data, .Alloc_Non_Zeroed, new_size, alignment, nil, 0, loc)
+		}
 		if err != nil {
 		if err != nil {
 			return
 			return
 		}
 		}
@@ -216,6 +228,13 @@ mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAUL
 	return
 	return
 }
 }
 
 
+mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
+	return _mem_resize(ptr, old_size, new_size, alignment, allocator, true, loc)
+}
+non_zero_mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
+	return _mem_resize(ptr, old_size, new_size, alignment, allocator, false, loc)
+}
+
 memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool {
 memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool {
 	switch {
 	switch {
 	case n == 0: return true
 	case n == 0: return true

+ 1 - 1
vendor/commonmark/cmark.odin

@@ -511,7 +511,7 @@ cmark_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mod
 	case .Free_All:
 	case .Free_All:
 		return nil, .Mode_Not_Implemented
 		return nil, .Mode_Not_Implemented
 
 
-	case .Resize:
+	case .Resize, .Resize_Non_Zeroed:
 		new_ptr := cmark_alloc.realloc(old_memory, c.size_t(size))
 		new_ptr := cmark_alloc.realloc(old_memory, c.size_t(size))
 		res = transmute([]byte)runtime.Raw_Slice{new_ptr, size}
 		res = transmute([]byte)runtime.Raw_Slice{new_ptr, size}
 		if size > old_size {
 		if size > old_size {

+ 1 - 1
vendor/raylib/raylib.odin

@@ -1774,7 +1774,7 @@ MemAllocatorProc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
 		MemFree(old_memory)
 		MemFree(old_memory)
 		return nil, nil
 		return nil, nil
 	
 	
-	case .Resize:
+	case .Resize, .Resize_Non_Zeroed:
 		ptr := MemRealloc(old_memory, c.uint(size))
 		ptr := MemRealloc(old_memory, c.uint(size))
 		if ptr == nil {
 		if ptr == nil {
 			err = .Out_Of_Memory
 			err = .Out_Of_Memory