authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-12 02:27:02-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-12 02:44:31-05:00
log4a4ea92cf38372dc63184957e2936fa7989743fb
tree94866dbdde8065d23016ed23f2dc09af18ed85da
parent445b03384a5ffcace11927aa9dd5f21604527f5c

remove std.heap.IncrementingAllocator

Use std.heap.FixedBufferAllocator combined with std.heap.DirectAllocator instead. std.mem.FixedBufferAllocator is moved to std.heap.FixedBufferAllocator

7 files changed, 60 insertions(+), 140 deletions(-)

std/debug/index.zig+1-1
......@@ -1078,5 +1078,5 @@ fn readILeb128(in_stream: var) !i64 {
10781078}
10791079
10801080pub const global_allocator = &global_fixed_allocator.allocator;
1081var global_fixed_allocator = mem.FixedBufferAllocator.init(global_allocator_mem[0..]);
1081var global_fixed_allocator = std.heap.FixedBufferAllocator.init(global_allocator_mem[0..]);
10821082var global_allocator_mem: [100 * 1024]u8 = undefined;
std/heap.zig+52-87
......@@ -39,74 +39,6 @@ fn cFree(self: &Allocator, old_mem: []u8) void {
3939 c.free(old_ptr);
4040}
4141
42/// Use this allocator when you want to allocate completely up front and guarantee that individual
43/// allocations will never make syscalls.
44pub const IncrementingAllocator = struct {
45 allocator: Allocator,
46 bytes: []u8,
47 end_index: usize,
48 direct_allocator: DirectAllocator,
49
50 pub fn init(capacity: usize) !IncrementingAllocator {
51 var direct_allocator = DirectAllocator.init();
52 const bytes = try direct_allocator.allocator.alloc(u8, capacity);
53 errdefer direct_allocator.allocator.free(bytes);
54
55 return IncrementingAllocator {
56 .allocator = Allocator {
57 .allocFn = alloc,
58 .reallocFn = realloc,
59 .freeFn = free,
60 },
61 .bytes = bytes,
62 .direct_allocator = direct_allocator,
63 .end_index = 0,
64 };
65 }
66
67 pub fn deinit(self: &IncrementingAllocator) void {
68 self.direct_allocator.allocator.free(self.bytes);
69 self.direct_allocator.deinit();
70 }
71
72 fn reset(self: &IncrementingAllocator) void {
73 self.end_index = 0;
74 }
75
76 fn bytesLeft(self: &const IncrementingAllocator) usize {
77 return self.bytes.len - self.end_index;
78 }
79
80 fn alloc(allocator: &Allocator, n: usize, alignment: u29) ![]u8 {
81 const self = @fieldParentPtr(IncrementingAllocator, "allocator", allocator);
82 const addr = @ptrToInt(&self.bytes[self.end_index]);
83 const rem = @rem(addr, alignment);
84 const march_forward_bytes = if (rem == 0) 0 else (alignment - rem);
85 const adjusted_index = self.end_index + march_forward_bytes;
86 const new_end_index = adjusted_index + n;
87 if (new_end_index > self.bytes.len) {
88 return error.OutOfMemory;
89 }
90 const result = self.bytes[adjusted_index .. new_end_index];
91 self.end_index = new_end_index;
92 return result;
93 }
94
95 fn realloc(allocator: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {
96 if (new_size <= old_mem.len) {
97 return old_mem[0..new_size];
98 } else {
99 const result = try alloc(allocator, new_size, alignment);
100 mem.copy(u8, result, old_mem);
101 return result;
102 }
103 }
104
105 fn free(allocator: &Allocator, bytes: []u8) void {
106 // Do nothing. That's the point of an incrementing allocator.
107 }
108};
109
11042/// This allocator makes a syscall directly for every allocation and free.
11143pub const DirectAllocator = struct {
11244 allocator: Allocator,
......@@ -327,34 +259,60 @@ pub const ArenaAllocator = struct {
327259 fn free(allocator: &Allocator, bytes: []u8) void { }
328260};
329261
262pub const FixedBufferAllocator = struct {
263 allocator: Allocator,
264 end_index: usize,
265 buffer: []u8,
330266
331
332test "c_allocator" {
333 if (builtin.link_libc) {
334 var slice = c_allocator.alloc(u8, 50) catch return;
335 defer c_allocator.free(slice);
336 slice = c_allocator.realloc(u8, slice, 100) catch return;
267 pub fn init(buffer: []u8) FixedBufferAllocator {
268 return FixedBufferAllocator {
269 .allocator = Allocator {
270 .allocFn = alloc,
271 .reallocFn = realloc,
272 .freeFn = free,
273 },
274 .buffer = buffer,
275 .end_index = 0,
276 };
337277 }
338}
339278
340test "IncrementingAllocator" {
341 const total_bytes = 10 * 1024 * 1024;
342 var inc_allocator = try IncrementingAllocator.init(total_bytes);
343 defer inc_allocator.deinit();
279 fn alloc(allocator: &Allocator, n: usize, alignment: u29) ![]u8 {
280 const self = @fieldParentPtr(FixedBufferAllocator, "allocator", allocator);
281 const addr = @ptrToInt(&self.buffer[self.end_index]);
282 const rem = @rem(addr, alignment);
283 const march_forward_bytes = if (rem == 0) 0 else (alignment - rem);
284 const adjusted_index = self.end_index + march_forward_bytes;
285 const new_end_index = adjusted_index + n;
286 if (new_end_index > self.buffer.len) {
287 return error.OutOfMemory;
288 }
289 const result = self.buffer[adjusted_index .. new_end_index];
290 self.end_index = new_end_index;
344291
345 const allocator = &inc_allocator.allocator;
346 const slice = try allocator.alloc(&i32, 100);
292 return result;
293 }
347294
348 for (slice) |*item, i| {
349 *item = try allocator.create(i32);
350 **item = i32(i);
295 fn realloc(allocator: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {
296 if (new_size <= old_mem.len) {
297 return old_mem[0..new_size];
298 } else {
299 const result = try alloc(allocator, new_size, alignment);
300 mem.copy(u8, result, old_mem);
301 return result;
302 }
351303 }
352304
353 assert(inc_allocator.bytesLeft() == total_bytes - @sizeOf(i32) * 100 - @sizeOf(usize) * 100);
305 fn free(allocator: &Allocator, bytes: []u8) void { }
306};
307
354308
355 inc_allocator.reset();
356309
357 assert(inc_allocator.bytesLeft() == total_bytes);
310test "c_allocator" {
311 if (builtin.link_libc) {
312 var slice = c_allocator.alloc(u8, 50) catch return;
313 defer c_allocator.free(slice);
314 slice = c_allocator.realloc(u8, slice, 100) catch return;
315 }
358316}
359317
360318test "DirectAllocator" {
......@@ -375,6 +333,13 @@ test "ArenaAllocator" {
375333 try testAllocator(&arena_allocator.allocator);
376334}
377335
336var test_fixed_buffer_allocator_memory: [30000 * @sizeOf(usize)]u8 = undefined;
337test "FixedBufferAllocator" {
338 var fixed_buffer_allocator = FixedBufferAllocator.init(test_fixed_buffer_allocator_memory[0..]);
339
340 try testAllocator(&fixed_buffer_allocator.allocator);
341}
342
378343fn testAllocator(allocator: &mem.Allocator) !void {
379344 var slice = try allocator.alloc(&i32, 100);
380345
std/mem.zig-45
......@@ -111,51 +111,6 @@ pub const Allocator = struct {
111111 }
112112};
113113
114pub const FixedBufferAllocator = struct {
115 allocator: Allocator,
116 end_index: usize,
117 buffer: []u8,
118
119 pub fn init(buffer: []u8) FixedBufferAllocator {
120 return FixedBufferAllocator {
121 .allocator = Allocator {
122 .allocFn = alloc,
123 .reallocFn = realloc,
124 .freeFn = free,
125 },
126 .buffer = buffer,
127 .end_index = 0,
128 };
129 }
130
131 fn alloc(allocator: &Allocator, n: usize, alignment: u29) ![]u8 {
132 const self = @fieldParentPtr(FixedBufferAllocator, "allocator", allocator);
133 const addr = @ptrToInt(&self.buffer[self.end_index]);
134 const rem = @rem(addr, alignment);
135 const march_forward_bytes = if (rem == 0) 0 else (alignment - rem);
136 const adjusted_index = self.end_index + march_forward_bytes;
137 const new_end_index = adjusted_index + n;
138 if (new_end_index > self.buffer.len) {
139 return error.OutOfMemory;
140 }
141 const result = self.buffer[adjusted_index .. new_end_index];
142 self.end_index = new_end_index;
143 return result;
144 }
145
146 fn realloc(allocator: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {
147 if (new_size <= old_mem.len) {
148 return old_mem[0..new_size];
149 } else {
150 const result = try alloc(allocator, new_size, alignment);
151 copy(u8, result, old_mem);
152 return result;
153 }
154 }
155
156 fn free(allocator: &Allocator, bytes: []u8) void { }
157};
158
159114/// Copy all of source into dest at position 0.
160115/// dest.len must be >= source.len.
161116pub fn copy(comptime T: type, dest: []T, source: []const T) void {
std/os/child_process.zig+2-2
......@@ -363,7 +363,7 @@ pub const ChildProcess = struct {
363363 const dev_null_fd = if (any_ignore) blk: {
364364 const dev_null_path = "/dev/null";
365365 var fixed_buffer_mem: [dev_null_path.len + 1]u8 = undefined;
366 var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
366 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
367367 break :blk try os.posixOpen(&fixed_allocator.allocator, "/dev/null", posix.O_RDWR, 0);
368368 } else blk: {
369369 break :blk undefined;
......@@ -472,7 +472,7 @@ pub const ChildProcess = struct {
472472 const nul_handle = if (any_ignore) blk: {
473473 const nul_file_path = "NUL";
474474 var fixed_buffer_mem: [nul_file_path.len + 1]u8 = undefined;
475 var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
475 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
476476 break :blk try os.windowsOpen(&fixed_allocator.allocator, "NUL", windows.GENERIC_READ, windows.FILE_SHARE_READ,
477477 windows.OPEN_EXISTING, windows.FILE_ATTRIBUTE_NORMAL);
478478 } else blk: {
std/os/index.zig+2-2
......@@ -1702,12 +1702,12 @@ pub fn openSelfExe() !os.File {
17021702 Os.linux => {
17031703 const proc_file_path = "/proc/self/exe";
17041704 var fixed_buffer_mem: [proc_file_path.len + 1]u8 = undefined;
1705 var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
1705 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
17061706 return os.File.openRead(&fixed_allocator.allocator, proc_file_path);
17071707 },
17081708 Os.macosx, Os.ios => {
17091709 var fixed_buffer_mem: [darwin.PATH_MAX * 2]u8 = undefined;
1710 var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
1710 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
17111711 const self_exe_path = try selfExePath(&fixed_allocator.allocator);
17121712 return os.File.openRead(&fixed_allocator.allocator, self_exe_path);
17131713 },
std/sort.zig+1-1
......@@ -1094,7 +1094,7 @@ var fixed_buffer_mem: [100 * 1024]u8 = undefined;
10941094
10951095fn fuzzTest(rng: &std.rand.Rand) void {
10961096 const array_size = rng.range(usize, 0, 1000);
1097 var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
1097 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
10981098 var array = fixed_allocator.allocator.alloc(IdAndValue, array_size) catch unreachable;
10991099 // populate with random data
11001100 for (array) |*item, index| {
std/zig/parser.zig+2-2
......@@ -1060,7 +1060,7 @@ fn testParse(source: []const u8, allocator: &mem.Allocator) ![]u8 {
10601060fn testCanonical(source: []const u8) !void {
10611061 const needed_alloc_count = x: {
10621062 // Try it once with unlimited memory, make sure it works
1063 var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
1063 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
10641064 var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, @maxValue(usize));
10651065 const result_source = try testParse(source, &failing_allocator.allocator);
10661066 if (!mem.eql(u8, result_source, source)) {
......@@ -1077,7 +1077,7 @@ fn testCanonical(source: []const u8) !void {
10771077
10781078 var fail_index: usize = 0;
10791079 while (fail_index < needed_alloc_count) : (fail_index += 1) {
1080 var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
1080 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
10811081 var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, fail_index);
10821082 if (testParse(source, &failing_allocator.allocator)) |_| {
10831083 return error.NondeterministicMemoryUsage;