| author | |
| committer | |
| log | e97feb96e4daf7d53538c9c8773d50459a59e5ee |
| tree | 33474da46590a20370d970d033a3123b620b2f81 |
| parent | d03e9d0b8347a74d674bdafadb71e7ddd8fdfad1 |
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 { |
| 551 | 551 | |
| 552 | 552 | /// Caller must free returned memory. |
| 553 | 553 | pub fn utf16leToUtf8Alloc(allocator: *mem.Allocator, utf16le: []const u16) ![]u8 { |
| 554 | var result = std.ArrayList(u8).init(allocator); | |
| 555 | errdefer result.deinit(); | |
| 556 | 554 | // 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(); | |
| 558 | 557 | var out_index: usize = 0; |
| 559 | 558 | var it = Utf16LeIterator.init(utf16le); |
| 560 | 559 | while (try it.nextCodepoint()) |codepoint| { |
| ... | ... | @@ -569,10 +568,9 @@ pub fn utf16leToUtf8Alloc(allocator: *mem.Allocator, utf16le: []const u16) ![]u8 |
| 569 | 568 | |
| 570 | 569 | /// Caller must free returned memory. |
| 571 | 570 | pub fn utf16leToUtf8AllocZ(allocator: *mem.Allocator, utf16le: []const u16) ![:0]u8 { |
| 572 | var result = std.ArrayList(u8).init(allocator); | |
| 573 | errdefer result.deinit(); | |
| 574 | 571 | // 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(); | |
| 576 | 574 | var out_index: usize = 0; |
| 577 | 575 | var it = Utf16LeIterator.init(utf16le); |
| 578 | 576 | while (try it.nextCodepoint()) |codepoint| { |
| ... | ... | @@ -664,10 +662,9 @@ test "utf16leToUtf8" { |
| 664 | 662 | } |
| 665 | 663 | |
| 666 | 664 | pub fn utf8ToUtf16LeWithNull(allocator: *mem.Allocator, utf8: []const u8) ![:0]u16 { |
| 667 | var result = std.ArrayList(u16).init(allocator); | |
| 668 | errdefer result.deinit(); | |
| 669 | 665 | // 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(); | |
| 671 | 668 | |
| 672 | 669 | const view = try Utf8View.init(utf8); |
| 673 | 670 | var it = view.iterator(); |
src/Compilation.zig+1-2| ... | ... | @@ -3812,8 +3812,7 @@ fn detectLibCIncludeDirs( |
| 3812 | 3812 | } |
| 3813 | 3813 | |
| 3814 | 3814 | fn 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); | |
| 3817 | 3816 | |
| 3818 | 3817 | list.appendAssumeCapacity(lci.include_dir.?); |
| 3819 | 3818 |
src/Sema.zig+3-4| ... | ... | @@ -6219,12 +6219,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 6219 | 6219 | |
| 6220 | 6220 | try sema.requireRuntimeBlock(block, src); |
| 6221 | 6221 | |
| 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); | |
| 6223 | 6225 | defer cases_extra.deinit(gpa); |
| 6224 | 6226 | |
| 6225 | try cases_extra.ensureTotalCapacity(gpa, (scalar_cases_len + multi_cases_len) * | |
| 6226 | @typeInfo(Air.SwitchBr.Case).Struct.fields.len + 2); | |
| 6227 | ||
| 6228 | 6227 | var case_block = child_block.makeSubBlock(); |
| 6229 | 6228 | case_block.runtime_loop = null; |
| 6230 | 6229 | case_block.runtime_cond = operand_src; |
src/codegen/llvm.zig+2-4| ... | ... | @@ -849,8 +849,7 @@ pub const DeclGen = struct { |
| 849 | 849 | |
| 850 | 850 | assert(struct_obj.haveFieldTypes()); |
| 851 | 851 | |
| 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()); | |
| 854 | 853 | defer llvm_field_types.deinit(gpa); |
| 855 | 854 | |
| 856 | 855 | for (struct_obj.fields.values()) |field| { |
| ... | ... | @@ -1251,8 +1250,7 @@ pub const DeclGen = struct { |
| 1251 | 1250 | const field_vals = tv.val.castTag(.@"struct").?.data; |
| 1252 | 1251 | const gpa = self.gpa; |
| 1253 | 1252 | |
| 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); | |
| 1256 | 1254 | defer llvm_fields.deinit(gpa); |
| 1257 | 1255 | |
| 1258 | 1256 | for (field_vals) |field_val, i| { |
src/libcxx.zig+2-4| ... | ... | @@ -109,8 +109,7 @@ pub fn buildLibCXX(comp: *Compilation) !void { |
| 109 | 109 | |
| 110 | 110 | const cxxabi_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", "include" }); |
| 111 | 111 | 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); | |
| 114 | 113 | |
| 115 | 114 | for (libcxx_files) |cxx_src| { |
| 116 | 115 | var cflags = std.ArrayList([]const u8).init(arena); |
| ... | ... | @@ -256,8 +255,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void { |
| 256 | 255 | |
| 257 | 256 | const cxxabi_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", "include" }); |
| 258 | 257 | 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); | |
| 261 | 259 | |
| 262 | 260 | for (libcxxabi_files) |cxxabi_src| { |
| 263 | 261 | var cflags = std.ArrayList([]const u8).init(arena); |
src/link.zig+2-2| ... | ... | @@ -650,10 +650,10 @@ pub const File = struct { |
| 650 | 650 | }; |
| 651 | 651 | } |
| 652 | 652 | |
| 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); | |
| 654 | 655 | defer object_files.deinit(); |
| 655 | 656 | |
| 656 | try object_files.ensureTotalCapacity(base.options.objects.len + comp.c_object_table.count() + 2); | |
| 657 | 657 | for (base.options.objects) |obj_path| { |
| 658 | 658 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, obj_path)); |
| 659 | 659 | } |
src/link/C.zig+2-3| ... | ... | @@ -397,11 +397,10 @@ pub fn flushEmitH(module: *Module) !void { |
| 397 | 397 | const emit_h = module.emit_h orelse return; |
| 398 | 398 | |
| 399 | 399 | // 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); | |
| 401 | 402 | defer all_buffers.deinit(); |
| 402 | 403 | |
| 403 | try all_buffers.ensureTotalCapacity(emit_h.decl_table.count() + 1); | |
| 404 | ||
| 405 | 404 | var file_size: u64 = zig_h.len; |
| 406 | 405 | all_buffers.appendAssumeCapacity(.{ |
| 407 | 406 | .iov_base = zig_h, |
src/link/Elf.zig+10-16| ... | ... | @@ -851,12 +851,11 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { |
| 851 | 851 | const last_dbg_info_decl = self.dbg_info_decl_last.?; |
| 852 | 852 | const debug_info_sect = &self.sections.items[self.debug_info_section_index.?]; |
| 853 | 853 | |
| 854 | var di_buf = std.ArrayList(u8).init(self.base.allocator); | |
| 855 | defer di_buf.deinit(); | |
| 856 | ||
| 857 | 854 | // We have a function to compute the upper bound size, because it's needed |
| 858 | 855 | // 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(); | |
| 860 | 859 | |
| 861 | 860 | // initial length - length of the .debug_info contribution for this compilation unit, |
| 862 | 861 | // not including the initial length itself. |
| ... | ... | @@ -920,12 +919,10 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { |
| 920 | 919 | if (self.debug_aranges_section_dirty) { |
| 921 | 920 | const debug_aranges_sect = &self.sections.items[self.debug_aranges_section_index.?]; |
| 922 | 921 | |
| 923 | var di_buf = std.ArrayList(u8).init(self.base.allocator); | |
| 924 | defer di_buf.deinit(); | |
| 925 | ||
| 926 | 922 | // Enough for all the data without resizing. When support for more compilation units |
| 927 | 923 | // 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(); | |
| 929 | 926 | |
| 930 | 927 | // initial length - length of the .debug_aranges contribution for this compilation unit, |
| 931 | 928 | // not including the initial length itself. |
| ... | ... | @@ -998,13 +995,12 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { |
| 998 | 995 | |
| 999 | 996 | const debug_line_sect = &self.sections.items[self.debug_line_section_index.?]; |
| 1000 | 997 | |
| 1001 | var di_buf = std.ArrayList(u8).init(self.base.allocator); | |
| 1002 | defer di_buf.deinit(); | |
| 1003 | ||
| 1004 | 998 | // The size of this header is variable, depending on the number of directories, |
| 1005 | 999 | // files, and padding. We have a function to compute the upper bound size, however, |
| 1006 | 1000 | // 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(); | |
| 1008 | 1004 | |
| 1009 | 1005 | // initial length - length of the .debug_line contribution for this compilation unit, |
| 1010 | 1006 | // not including the initial length itself. |
| ... | ... | @@ -2300,7 +2296,8 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven |
| 2300 | 2296 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 2301 | 2297 | defer code_buffer.deinit(); |
| 2302 | 2298 | |
| 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); | |
| 2304 | 2301 | defer dbg_line_buffer.deinit(); |
| 2305 | 2302 | |
| 2306 | 2303 | 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 |
| 2309 | 2306 | var dbg_info_type_relocs: File.DbgInfoTypeRelocsTable = .{}; |
| 2310 | 2307 | defer deinitRelocs(self.base.allocator, &dbg_info_type_relocs); |
| 2311 | 2308 | |
| 2312 | // For functions we need to add a prologue to the debug line program. | |
| 2313 | try dbg_line_buffer.ensureTotalCapacity(26); | |
| 2314 | ||
| 2315 | 2309 | const decl = func.owner_decl; |
| 2316 | 2310 | const line_off = @intCast(u28, decl.src_line + func.lbrace_line); |
| 2317 | 2311 |
src/link/MachO.zig+1-2| ... | ... | @@ -5323,8 +5323,7 @@ fn snapshotState(self: *MachO) !void { |
| 5323 | 5323 | node.payload.aliases = aliases.toOwnedSlice(); |
| 5324 | 5324 | try nodes.append(node); |
| 5325 | 5325 | |
| 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); | |
| 5328 | 5327 | for (atom.relocs.items) |rel| { |
| 5329 | 5328 | const arch = self.base.options.target.cpu.arch; |
| 5330 | 5329 | 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 |
| 348 | 348 | const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment; |
| 349 | 349 | const debug_info_sect = &dwarf_segment.sections.items[self.debug_info_section_index.?]; |
| 350 | 350 | |
| 351 | var di_buf = std.ArrayList(u8).init(allocator); | |
| 352 | defer di_buf.deinit(); | |
| 353 | ||
| 354 | 351 | // We have a function to compute the upper bound size, because it's needed |
| 355 | 352 | // 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(); | |
| 357 | 356 | |
| 358 | 357 | // initial length - length of the .debug_info contribution for this compilation unit, |
| 359 | 358 | // not including the initial length itself. |
| ... | ... | @@ -403,12 +402,10 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt |
| 403 | 402 | const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment; |
| 404 | 403 | const debug_aranges_sect = &dwarf_segment.sections.items[self.debug_aranges_section_index.?]; |
| 405 | 404 | |
| 406 | var di_buf = std.ArrayList(u8).init(allocator); | |
| 407 | defer di_buf.deinit(); | |
| 408 | ||
| 409 | 405 | // Enough for all the data without resizing. When support for more compilation units |
| 410 | 406 | // 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(); | |
| 412 | 409 | |
| 413 | 410 | // initial length - length of the .debug_aranges contribution for this compilation unit, |
| 414 | 411 | // not including the initial length itself. |
| ... | ... | @@ -473,13 +470,12 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt |
| 473 | 470 | const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment; |
| 474 | 471 | const debug_line_sect = &dwarf_segment.sections.items[self.debug_line_section_index.?]; |
| 475 | 472 | |
| 476 | var di_buf = std.ArrayList(u8).init(allocator); | |
| 477 | defer di_buf.deinit(); | |
| 478 | ||
| 479 | 473 | // The size of this header is variable, depending on the number of directories, |
| 480 | 474 | // files, and padding. We have a function to compute the upper bound size, however, |
| 481 | 475 | // 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(); | |
| 483 | 479 | |
| 484 | 480 | // initial length - length of the .debug_line contribution for this compilation unit, |
| 485 | 481 | // 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) |
| 393 | 393 | // local < extern defined < undefined. Unfortunately, this is not guaranteed! For instance, |
| 394 | 394 | // the GO compiler does not necessarily respect that therefore we sort immediately by type |
| 395 | 395 | // 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); | |
| 397 | 397 | defer sorted_all_nlists.deinit(); |
| 398 | try sorted_all_nlists.ensureTotalCapacity(self.symtab.items.len); | |
| 399 | 398 | |
| 400 | 399 | for (self.symtab.items) |nlist, index| { |
| 401 | 400 | sorted_all_nlists.appendAssumeCapacity(.{ |
src/main.zig+1-2| ... | ... | @@ -2866,8 +2866,7 @@ pub fn cmdInit( |
| 2866 | 2866 | const build_zig_contents = template_dir.readFileAlloc(arena, "build.zig", max_bytes) catch |err| { |
| 2867 | 2867 | fatal("unable to read template file 'build.zig': {s}", .{@errorName(err)}); |
| 2868 | 2868 | }; |
| 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); | |
| 2871 | 2870 | for (build_zig_contents) |c| { |
| 2872 | 2871 | if (c == '$') { |
| 2873 | 2872 | try modified_build_zig_contents.appendSlice(cwd_basename); |
src/translate_c.zig+2-3| ... | ... | @@ -4901,10 +4901,9 @@ fn finishTransFnProto( |
| 4901 | 4901 | |
| 4902 | 4902 | // TODO check for align attribute |
| 4903 | 4903 | |
| 4904 | var fn_params = std.ArrayList(ast.Payload.Param).init(c.gpa); | |
| 4905 | defer fn_params.deinit(); | |
| 4906 | 4904 | 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(); | |
| 4908 | 4907 | |
| 4909 | 4908 | var i: usize = 0; |
| 4910 | 4909 | while (i < param_count) : (i += 1) { |
src/translate_c/ast.zig+1-2| ... | ... | @@ -2787,9 +2787,8 @@ fn renderMacroFunc(c: *Context, node: Node) !NodeIndex { |
| 2787 | 2787 | |
| 2788 | 2788 | fn renderParams(c: *Context, params: []Payload.Param, is_var_args: bool) !std.ArrayList(NodeIndex) { |
| 2789 | 2789 | _ = 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)); | |
| 2791 | 2791 | errdefer rendered.deinit(); |
| 2792 | try rendered.ensureTotalCapacity(std.math.max(params.len, 1)); | |
| 2793 | 2792 | |
| 2794 | 2793 | for (params) |param, i| { |
| 2795 | 2794 | if (i != 0) _ = try c.addToken(.comma, ","); |