authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2021-11-01 00:54:04-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-11-04 14:54:25-04:00
loge97feb96e4daf7d53538c9c8773d50459a59e5ee
tree33474da46590a20370d970d033a3123b620b2f81
parentd03e9d0b8347a74d674bdafadb71e7ddd8fdfad1

Replace ArrayList.init/ensureTotalCapacity pairs with initCapacity

Because ArrayList.initCapacity uses 'precise' capacity allocation, this should save memory on average, and definitely will save memory in cases where ArrayList is used where a regular allocated slice could have also be used.

14 files changed, 42 insertions(+), 67 deletions(-)

lib/std/unicode.zig+6-9
......@@ -551,10 +551,9 @@ fn testDecode(bytes: []const u8) !u21 {
551551
552552/// Caller must free returned memory.
553553pub fn utf16leToUtf8Alloc(allocator: *mem.Allocator, utf16le: []const u16) ![]u8 {
554 var result = std.ArrayList(u8).init(allocator);
555 errdefer result.deinit();
556554 // optimistically guess that it will all be ascii.
557 try result.ensureTotalCapacity(utf16le.len);
555 var result = try std.ArrayList(u8).initCapacity(allocator, utf16le.len);
556 errdefer result.deinit();
558557 var out_index: usize = 0;
559558 var it = Utf16LeIterator.init(utf16le);
560559 while (try it.nextCodepoint()) |codepoint| {
......@@ -569,10 +568,9 @@ pub fn utf16leToUtf8Alloc(allocator: *mem.Allocator, utf16le: []const u16) ![]u8
569568
570569/// Caller must free returned memory.
571570pub fn utf16leToUtf8AllocZ(allocator: *mem.Allocator, utf16le: []const u16) ![:0]u8 {
572 var result = std.ArrayList(u8).init(allocator);
573 errdefer result.deinit();
574571 // optimistically guess that it will all be ascii.
575 try result.ensureTotalCapacity(utf16le.len);
572 var result = try std.ArrayList(u8).initCapacity(allocator, utf16le.len);
573 errdefer result.deinit();
576574 var out_index: usize = 0;
577575 var it = Utf16LeIterator.init(utf16le);
578576 while (try it.nextCodepoint()) |codepoint| {
......@@ -664,10 +662,9 @@ test "utf16leToUtf8" {
664662}
665663
666664pub fn utf8ToUtf16LeWithNull(allocator: *mem.Allocator, utf8: []const u8) ![:0]u16 {
667 var result = std.ArrayList(u16).init(allocator);
668 errdefer result.deinit();
669665 // optimistically guess that it will not require surrogate pairs
670 try result.ensureTotalCapacity(utf8.len + 1);
666 var result = try std.ArrayList(u16).initCapacity(allocator, utf8.len + 1);
667 errdefer result.deinit();
671668
672669 const view = try Utf8View.init(utf8);
673670 var it = view.iterator();
src/Compilation.zig+1-2
......@@ -3812,8 +3812,7 @@ fn detectLibCIncludeDirs(
38123812}
38133813
38143814fn detectLibCFromLibCInstallation(arena: *Allocator, target: Target, lci: *const LibCInstallation) !LibCDirs {
3815 var list = std.ArrayList([]const u8).init(arena);
3816 try list.ensureTotalCapacity(4);
3815 var list = try std.ArrayList([]const u8).initCapacity(arena, 4);
38173816
38183817 list.appendAssumeCapacity(lci.include_dir.?);
38193818
src/Sema.zig+3-4
......@@ -6219,12 +6219,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
62196219
62206220 try sema.requireRuntimeBlock(block, src);
62216221
6222 var cases_extra: std.ArrayListUnmanaged(u32) = .{};
6222 const estimated_cases_extra = (scalar_cases_len + multi_cases_len) *
6223 @typeInfo(Air.SwitchBr.Case).Struct.fields.len + 2;
6224 var cases_extra = try std.ArrayListUnmanaged(u32).initCapacity(gpa, estimated_cases_extra);
62236225 defer cases_extra.deinit(gpa);
62246226
6225 try cases_extra.ensureTotalCapacity(gpa, (scalar_cases_len + multi_cases_len) *
6226 @typeInfo(Air.SwitchBr.Case).Struct.fields.len + 2);
6227
62286227 var case_block = child_block.makeSubBlock();
62296228 case_block.runtime_loop = null;
62306229 case_block.runtime_cond = operand_src;
src/codegen/llvm.zig+2-4
......@@ -849,8 +849,7 @@ pub const DeclGen = struct {
849849
850850 assert(struct_obj.haveFieldTypes());
851851
852 var llvm_field_types: std.ArrayListUnmanaged(*const llvm.Type) = .{};
853 try llvm_field_types.ensureTotalCapacity(gpa, struct_obj.fields.count());
852 var llvm_field_types = try std.ArrayListUnmanaged(*const llvm.Type).initCapacity(gpa, struct_obj.fields.count());
854853 defer llvm_field_types.deinit(gpa);
855854
856855 for (struct_obj.fields.values()) |field| {
......@@ -1251,8 +1250,7 @@ pub const DeclGen = struct {
12511250 const field_vals = tv.val.castTag(.@"struct").?.data;
12521251 const gpa = self.gpa;
12531252
1254 var llvm_fields: std.ArrayListUnmanaged(*const llvm.Value) = .{};
1255 try llvm_fields.ensureTotalCapacity(gpa, field_vals.len);
1253 var llvm_fields = try std.ArrayListUnmanaged(*const llvm.Value).initCapacity(gpa, field_vals.len);
12561254 defer llvm_fields.deinit(gpa);
12571255
12581256 for (field_vals) |field_val, i| {
src/libcxx.zig+2-4
......@@ -109,8 +109,7 @@ pub fn buildLibCXX(comp: *Compilation) !void {
109109
110110 const cxxabi_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", "include" });
111111 const cxx_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxx", "include" });
112 var c_source_files = std.ArrayList(Compilation.CSourceFile).init(arena);
113 try c_source_files.ensureTotalCapacity(libcxx_files.len);
112 var c_source_files = try std.ArrayList(Compilation.CSourceFile).initCapacity(arena, libcxx_files.len);
114113
115114 for (libcxx_files) |cxx_src| {
116115 var cflags = std.ArrayList([]const u8).init(arena);
......@@ -256,8 +255,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {
256255
257256 const cxxabi_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", "include" });
258257 const cxx_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxx", "include" });
259 var c_source_files = std.ArrayList(Compilation.CSourceFile).init(arena);
260 try c_source_files.ensureTotalCapacity(libcxxabi_files.len);
258 var c_source_files = try std.ArrayList(Compilation.CSourceFile).initCapacity(arena, libcxxabi_files.len);
261259
262260 for (libcxxabi_files) |cxxabi_src| {
263261 var cflags = std.ArrayList([]const u8).init(arena);
src/link.zig+2-2
......@@ -650,10 +650,10 @@ pub const File = struct {
650650 };
651651 }
652652
653 var object_files = std.ArrayList([*:0]const u8).init(base.allocator);
653 const num_object_files = base.options.objects.len + comp.c_object_table.count() + 2;
654 var object_files = try std.ArrayList([*:0]const u8).initCapacity(base.allocator, num_object_files);
654655 defer object_files.deinit();
655656
656 try object_files.ensureTotalCapacity(base.options.objects.len + comp.c_object_table.count() + 2);
657657 for (base.options.objects) |obj_path| {
658658 object_files.appendAssumeCapacity(try arena.dupeZ(u8, obj_path));
659659 }
src/link/C.zig+2-3
......@@ -397,11 +397,10 @@ pub fn flushEmitH(module: *Module) !void {
397397 const emit_h = module.emit_h orelse return;
398398
399399 // We collect a list of buffers to write, and write them all at once with pwritev 😎
400 var all_buffers = std.ArrayList(std.os.iovec_const).init(module.gpa);
400 const num_buffers = emit_h.decl_table.count() + 1;
401 var all_buffers = try std.ArrayList(std.os.iovec_const).initCapacity(module.gpa, num_buffers);
401402 defer all_buffers.deinit();
402403
403 try all_buffers.ensureTotalCapacity(emit_h.decl_table.count() + 1);
404
405404 var file_size: u64 = zig_h.len;
406405 all_buffers.appendAssumeCapacity(.{
407406 .iov_base = zig_h,
src/link/Elf.zig+10-16
......@@ -851,12 +851,11 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
851851 const last_dbg_info_decl = self.dbg_info_decl_last.?;
852852 const debug_info_sect = &self.sections.items[self.debug_info_section_index.?];
853853
854 var di_buf = std.ArrayList(u8).init(self.base.allocator);
855 defer di_buf.deinit();
856
857854 // We have a function to compute the upper bound size, because it's needed
858855 // for determining where to put the offset of the first `LinkBlock`.
859 try di_buf.ensureTotalCapacity(self.dbgInfoNeededHeaderBytes());
856 const needed_bytes = self.dbgInfoNeededHeaderBytes();
857 var di_buf = try std.ArrayList(u8).initCapacity(self.base.allocator, needed_bytes);
858 defer di_buf.deinit();
860859
861860 // initial length - length of the .debug_info contribution for this compilation unit,
862861 // not including the initial length itself.
......@@ -920,12 +919,10 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
920919 if (self.debug_aranges_section_dirty) {
921920 const debug_aranges_sect = &self.sections.items[self.debug_aranges_section_index.?];
922921
923 var di_buf = std.ArrayList(u8).init(self.base.allocator);
924 defer di_buf.deinit();
925
926922 // Enough for all the data without resizing. When support for more compilation units
927923 // is added, the size of this section will become more variable.
928 try di_buf.ensureTotalCapacity(100);
924 var di_buf = try std.ArrayList(u8).initCapacity(self.base.allocator, 100);
925 defer di_buf.deinit();
929926
930927 // initial length - length of the .debug_aranges contribution for this compilation unit,
931928 // not including the initial length itself.
......@@ -998,13 +995,12 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
998995
999996 const debug_line_sect = &self.sections.items[self.debug_line_section_index.?];
1000997
1001 var di_buf = std.ArrayList(u8).init(self.base.allocator);
1002 defer di_buf.deinit();
1003
1004998 // The size of this header is variable, depending on the number of directories,
1005999 // files, and padding. We have a function to compute the upper bound size, however,
10061000 // because it's needed for determining where to put the offset of the first `SrcFn`.
1007 try di_buf.ensureTotalCapacity(self.dbgLineNeededHeaderBytes());
1001 const needed_bytes = self.dbgLineNeededHeaderBytes();
1002 var di_buf = try std.ArrayList(u8).initCapacity(self.base.allocator, needed_bytes);
1003 defer di_buf.deinit();
10081004
10091005 // initial length - length of the .debug_line contribution for this compilation unit,
10101006 // not including the initial length itself.
......@@ -2300,7 +2296,8 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven
23002296 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
23012297 defer code_buffer.deinit();
23022298
2303 var dbg_line_buffer = std.ArrayList(u8).init(self.base.allocator);
2299 // For functions we need to add a prologue to the debug line program.
2300 var dbg_line_buffer = try std.ArrayList(u8).initCapacity(self.base.allocator, 26);
23042301 defer dbg_line_buffer.deinit();
23052302
23062303 var dbg_info_buffer = std.ArrayList(u8).init(self.base.allocator);
......@@ -2309,9 +2306,6 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven
23092306 var dbg_info_type_relocs: File.DbgInfoTypeRelocsTable = .{};
23102307 defer deinitRelocs(self.base.allocator, &dbg_info_type_relocs);
23112308
2312 // For functions we need to add a prologue to the debug line program.
2313 try dbg_line_buffer.ensureTotalCapacity(26);
2314
23152309 const decl = func.owner_decl;
23162310 const line_off = @intCast(u28, decl.src_line + func.lbrace_line);
23172311
src/link/MachO.zig+1-2
......@@ -5323,8 +5323,7 @@ fn snapshotState(self: *MachO) !void {
53235323 node.payload.aliases = aliases.toOwnedSlice();
53245324 try nodes.append(node);
53255325
5326 var relocs = std.ArrayList(Snapshot.Node).init(arena);
5327 try relocs.ensureTotalCapacity(atom.relocs.items.len);
5326 var relocs = try std.ArrayList(Snapshot.Node).initCapacity(arena, atom.relocs.items.len);
53285327 for (atom.relocs.items) |rel| {
53295328 const arch = self.base.options.target.cpu.arch;
53305329 const source_addr = blk: {
src/link/MachO/DebugSymbols.zig+8-12
......@@ -348,12 +348,11 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt
348348 const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
349349 const debug_info_sect = &dwarf_segment.sections.items[self.debug_info_section_index.?];
350350
351 var di_buf = std.ArrayList(u8).init(allocator);
352 defer di_buf.deinit();
353
354351 // We have a function to compute the upper bound size, because it's needed
355352 // for determining where to put the offset of the first `LinkBlock`.
356 try di_buf.ensureTotalCapacity(self.dbgInfoNeededHeaderBytes());
353 const needed_bytes = self.dbgInfoNeededHeaderBytes();
354 var di_buf = try std.ArrayList(u8).initCapacity(allocator, needed_bytes);
355 defer di_buf.deinit();
357356
358357 // initial length - length of the .debug_info contribution for this compilation unit,
359358 // not including the initial length itself.
......@@ -403,12 +402,10 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt
403402 const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
404403 const debug_aranges_sect = &dwarf_segment.sections.items[self.debug_aranges_section_index.?];
405404
406 var di_buf = std.ArrayList(u8).init(allocator);
407 defer di_buf.deinit();
408
409405 // Enough for all the data without resizing. When support for more compilation units
410406 // is added, the size of this section will become more variable.
411 try di_buf.ensureTotalCapacity(100);
407 var di_buf = try std.ArrayList(u8).initCapacity(allocator, 100);
408 defer di_buf.deinit();
412409
413410 // initial length - length of the .debug_aranges contribution for this compilation unit,
414411 // not including the initial length itself.
......@@ -473,13 +470,12 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt
473470 const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
474471 const debug_line_sect = &dwarf_segment.sections.items[self.debug_line_section_index.?];
475472
476 var di_buf = std.ArrayList(u8).init(allocator);
477 defer di_buf.deinit();
478
479473 // The size of this header is variable, depending on the number of directories,
480474 // files, and padding. We have a function to compute the upper bound size, however,
481475 // because it's needed for determining where to put the offset of the first `SrcFn`.
482 try di_buf.ensureTotalCapacity(self.dbgLineNeededHeaderBytes(module));
476 const needed_bytes = self.dbgLineNeededHeaderBytes(module);
477 var di_buf = try std.ArrayList(u8).initCapacity(allocator, needed_bytes);
478 defer di_buf.deinit();
483479
484480 // initial length - length of the .debug_line contribution for this compilation unit,
485481 // not including the initial length itself.
src/link/MachO/Object.zig+1-2
......@@ -393,9 +393,8 @@ pub fn parseIntoAtoms(self: *Object, allocator: *Allocator, macho_file: *MachO)
393393 // local < extern defined < undefined. Unfortunately, this is not guaranteed! For instance,
394394 // the GO compiler does not necessarily respect that therefore we sort immediately by type
395395 // and address within.
396 var sorted_all_nlists = std.ArrayList(NlistWithIndex).init(allocator);
396 var sorted_all_nlists = try std.ArrayList(NlistWithIndex).initCapacity(allocator, self.symtab.items.len);
397397 defer sorted_all_nlists.deinit();
398 try sorted_all_nlists.ensureTotalCapacity(self.symtab.items.len);
399398
400399 for (self.symtab.items) |nlist, index| {
401400 sorted_all_nlists.appendAssumeCapacity(.{
src/main.zig+1-2
......@@ -2866,8 +2866,7 @@ pub fn cmdInit(
28662866 const build_zig_contents = template_dir.readFileAlloc(arena, "build.zig", max_bytes) catch |err| {
28672867 fatal("unable to read template file 'build.zig': {s}", .{@errorName(err)});
28682868 };
2869 var modified_build_zig_contents = std.ArrayList(u8).init(arena);
2870 try modified_build_zig_contents.ensureTotalCapacity(build_zig_contents.len);
2869 var modified_build_zig_contents = try std.ArrayList(u8).initCapacity(arena, build_zig_contents.len);
28712870 for (build_zig_contents) |c| {
28722871 if (c == '$') {
28732872 try modified_build_zig_contents.appendSlice(cwd_basename);
src/translate_c.zig+2-3
......@@ -4901,10 +4901,9 @@ fn finishTransFnProto(
49014901
49024902 // TODO check for align attribute
49034903
4904 var fn_params = std.ArrayList(ast.Payload.Param).init(c.gpa);
4905 defer fn_params.deinit();
49064904 const param_count: usize = if (fn_proto_ty != null) fn_proto_ty.?.getNumParams() else 0;
4907 try fn_params.ensureTotalCapacity(param_count);
4905 var fn_params = try std.ArrayList(ast.Payload.Param).initCapacity(c.gpa, param_count);
4906 defer fn_params.deinit();
49084907
49094908 var i: usize = 0;
49104909 while (i < param_count) : (i += 1) {
src/translate_c/ast.zig+1-2
......@@ -2787,9 +2787,8 @@ fn renderMacroFunc(c: *Context, node: Node) !NodeIndex {
27872787
27882788fn renderParams(c: *Context, params: []Payload.Param, is_var_args: bool) !std.ArrayList(NodeIndex) {
27892789 _ = try c.addToken(.l_paren, "(");
2790 var rendered = std.ArrayList(NodeIndex).init(c.gpa);
2790 var rendered = try std.ArrayList(NodeIndex).initCapacity(c.gpa, std.math.max(params.len, 1));
27912791 errdefer rendered.deinit();
2792 try rendered.ensureTotalCapacity(std.math.max(params.len, 1));
27932792
27942793 for (params) |param, i| {
27952794 if (i != 0) _ = try c.addToken(.comma, ",");