| author | |
| committer | |
| log | 6d4dbf05effa3afeb650aeea17683d5de4e6429c |
| tree | 29458c85d0cb2cd28a48c2c7f0c47d07222f978b |
| parent | 3e77317261e3da50ac55be0c14bc00192ee93166 |
| signature |
And delete DeprecatedLinearFifo from the source tree.3 files changed, 22 insertions(+), 192 deletions(-)
lib/std/deque.zig+1-1| ... | ... | @@ -143,7 +143,7 @@ pub fn Deque(comptime T: type) type { |
| 143 | 143 | deque.len += 1; |
| 144 | 144 | } |
| 145 | 145 | |
| 146 | /// Add one item to the front of the deque. | |
| 146 | /// Add one item to the back of the deque. | |
| 147 | 147 | /// |
| 148 | 148 | /// Invalidates element pointers if additional memory is needed. |
| 149 | 149 | pub fn pushBack(deque: *Self, gpa: Allocator, item: T) error{OutOfMemory}!void { |
src/Compilation.zig+21-22| ... | ... | @@ -45,8 +45,6 @@ const Builtin = @import("Builtin.zig"); |
| 45 | 45 | const LlvmObject = @import("codegen/llvm.zig").Object; |
| 46 | 46 | const dev = @import("dev.zig"); |
| 47 | 47 | |
| 48 | const DeprecatedLinearFifo = @import("deprecated.zig").LinearFifo; | |
| 49 | ||
| 50 | 48 | pub const Config = @import("Compilation/Config.zig"); |
| 51 | 49 | |
| 52 | 50 | /// General-purpose allocator. Used for both temporary and long-term storage. |
| ... | ... | @@ -124,20 +122,21 @@ work_queues: [ |
| 124 | 122 | } |
| 125 | 123 | break :len len; |
| 126 | 124 | } |
| 127 | ]DeprecatedLinearFifo(Job), | |
| 125 | ]std.Deque(Job), | |
| 128 | 126 | |
| 129 | 127 | /// These jobs are to invoke the Clang compiler to create an object file, which |
| 130 | 128 | /// gets linked with the Compilation. |
| 131 | c_object_work_queue: DeprecatedLinearFifo(*CObject), | |
| 129 | c_object_work_queue: std.Deque(*CObject), | |
| 132 | 130 | |
| 133 | 131 | /// These jobs are to invoke the RC compiler to create a compiled resource file (.res), which |
| 134 | 132 | /// gets linked with the Compilation. |
| 135 | win32_resource_work_queue: if (dev.env.supports(.win32_resource)) DeprecatedLinearFifo(*Win32Resource) else struct { | |
| 136 | pub fn ensureUnusedCapacity(_: @This(), _: u0) error{}!void {} | |
| 137 | pub fn readItem(_: @This()) ?noreturn { | |
| 133 | win32_resource_work_queue: if (dev.env.supports(.win32_resource)) std.Deque(*Win32Resource) else struct { | |
| 134 | pub const empty: @This() = .{}; | |
| 135 | pub fn ensureUnusedCapacity(_: @This(), _: Allocator, _: u0) error{}!void {} | |
| 136 | pub fn popFront(_: @This()) ?noreturn { | |
| 138 | 137 | return null; |
| 139 | 138 | } |
| 140 | pub fn deinit(_: @This()) void {} | |
| 139 | pub fn deinit(_: @This(), _: Allocator) void {} | |
| 141 | 140 | }, |
| 142 | 141 | |
| 143 | 142 | /// The ErrorMsg memory is owned by the `CObject`, using Compilation's general purpose allocator. |
| ... | ... | @@ -2231,9 +2230,9 @@ pub fn create(gpa: Allocator, arena: Allocator, diag: *CreateDiagnostic, options |
| 2231 | 2230 | .root_mod = options.root_mod, |
| 2232 | 2231 | .config = options.config, |
| 2233 | 2232 | .dirs = options.dirs, |
| 2234 | .work_queues = @splat(.init(gpa)), | |
| 2235 | .c_object_work_queue = .init(gpa), | |
| 2236 | .win32_resource_work_queue = if (dev.env.supports(.win32_resource)) .init(gpa) else .{}, | |
| 2233 | .work_queues = @splat(.empty), | |
| 2234 | .c_object_work_queue = .empty, | |
| 2235 | .win32_resource_work_queue = .empty, | |
| 2237 | 2236 | .c_source_files = options.c_source_files, |
| 2238 | 2237 | .rc_source_files = options.rc_source_files, |
| 2239 | 2238 | .cache_parent = cache, |
| ... | ... | @@ -2699,9 +2698,9 @@ pub fn destroy(comp: *Compilation) void { |
| 2699 | 2698 | if (comp.zcu) |zcu| zcu.deinit(); |
| 2700 | 2699 | comp.cache_use.deinit(); |
| 2701 | 2700 | |
| 2702 | for (&comp.work_queues) |*work_queue| work_queue.deinit(); | |
| 2703 | comp.c_object_work_queue.deinit(); | |
| 2704 | comp.win32_resource_work_queue.deinit(); | |
| 2701 | for (&comp.work_queues) |*work_queue| work_queue.deinit(gpa); | |
| 2702 | comp.c_object_work_queue.deinit(gpa); | |
| 2703 | comp.win32_resource_work_queue.deinit(gpa); | |
| 2705 | 2704 | |
| 2706 | 2705 | for (comp.windows_libs.keys()) |windows_lib| gpa.free(windows_lib); |
| 2707 | 2706 | comp.windows_libs.deinit(gpa); |
| ... | ... | @@ -3016,17 +3015,17 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE |
| 3016 | 3015 | |
| 3017 | 3016 | // For compiling C objects, we rely on the cache hash system to avoid duplicating work. |
| 3018 | 3017 | // Add a Job for each C object. |
| 3019 | try comp.c_object_work_queue.ensureUnusedCapacity(comp.c_object_table.count()); | |
| 3018 | try comp.c_object_work_queue.ensureUnusedCapacity(gpa, comp.c_object_table.count()); | |
| 3020 | 3019 | for (comp.c_object_table.keys()) |c_object| { |
| 3021 | comp.c_object_work_queue.writeItemAssumeCapacity(c_object); | |
| 3020 | comp.c_object_work_queue.pushBackAssumeCapacity(c_object); | |
| 3022 | 3021 | try comp.appendFileSystemInput(try .fromUnresolved(arena, comp.dirs, &.{c_object.src.src_path})); |
| 3023 | 3022 | } |
| 3024 | 3023 | |
| 3025 | 3024 | // For compiling Win32 resources, we rely on the cache hash system to avoid duplicating work. |
| 3026 | 3025 | // Add a Job for each Win32 resource file. |
| 3027 | try comp.win32_resource_work_queue.ensureUnusedCapacity(comp.win32_resource_table.count()); | |
| 3026 | try comp.win32_resource_work_queue.ensureUnusedCapacity(gpa, comp.win32_resource_table.count()); | |
| 3028 | 3027 | for (comp.win32_resource_table.keys()) |win32_resource| { |
| 3029 | comp.win32_resource_work_queue.writeItemAssumeCapacity(win32_resource); | |
| 3028 | comp.win32_resource_work_queue.pushBackAssumeCapacity(win32_resource); | |
| 3030 | 3029 | switch (win32_resource.src) { |
| 3031 | 3030 | .rc => |f| { |
| 3032 | 3031 | try comp.appendFileSystemInput(try .fromUnresolved(arena, comp.dirs, &.{f.src_path})); |
| ... | ... | @@ -4869,14 +4868,14 @@ fn performAllTheWork( |
| 4869 | 4868 | } |
| 4870 | 4869 | } |
| 4871 | 4870 | |
| 4872 | while (comp.c_object_work_queue.readItem()) |c_object| { | |
| 4871 | while (comp.c_object_work_queue.popFront()) |c_object| { | |
| 4873 | 4872 | comp.link_task_queue.startPrelinkItem(); |
| 4874 | 4873 | comp.thread_pool.spawnWg(&comp.link_task_wait_group, workerUpdateCObject, .{ |
| 4875 | 4874 | comp, c_object, main_progress_node, |
| 4876 | 4875 | }); |
| 4877 | 4876 | } |
| 4878 | 4877 | |
| 4879 | while (comp.win32_resource_work_queue.readItem()) |win32_resource| { | |
| 4878 | while (comp.win32_resource_work_queue.popFront()) |win32_resource| { | |
| 4880 | 4879 | comp.link_task_queue.startPrelinkItem(); |
| 4881 | 4880 | comp.thread_pool.spawnWg(&comp.link_task_wait_group, workerUpdateWin32Resource, .{ |
| 4882 | 4881 | comp, win32_resource, main_progress_node, |
| ... | ... | @@ -4996,7 +4995,7 @@ fn performAllTheWork( |
| 4996 | 4995 | } |
| 4997 | 4996 | |
| 4998 | 4997 | work: while (true) { |
| 4999 | for (&comp.work_queues) |*work_queue| if (work_queue.readItem()) |job| { | |
| 4998 | for (&comp.work_queues) |*work_queue| if (work_queue.popFront()) |job| { | |
| 5000 | 4999 | try processOneJob(@intFromEnum(Zcu.PerThread.Id.main), comp, job); |
| 5001 | 5000 | continue :work; |
| 5002 | 5001 | }; |
| ... | ... | @@ -5025,7 +5024,7 @@ fn performAllTheWork( |
| 5025 | 5024 | const JobError = Allocator.Error; |
| 5026 | 5025 | |
| 5027 | 5026 | pub fn queueJob(comp: *Compilation, job: Job) !void { |
| 5028 | try comp.work_queues[Job.stage(job)].writeItem(job); | |
| 5027 | try comp.work_queues[Job.stage(job)].pushBack(comp.gpa, job); | |
| 5029 | 5028 | } |
| 5030 | 5029 | |
| 5031 | 5030 | pub fn queueJobs(comp: *Compilation, jobs: []const Job) !void { |
src/deprecated.zig deleted-169| ... | ... | @@ -1,169 +0,0 @@ |
| 1 | //! Deprecated. Stop using this API | |
| 2 | ||
| 3 | const std = @import("std"); | |
| 4 | const math = std.math; | |
| 5 | const mem = std.mem; | |
| 6 | const Allocator = mem.Allocator; | |
| 7 | const assert = std.debug.assert; | |
| 8 | const testing = std.testing; | |
| 9 | ||
| 10 | pub fn LinearFifo(comptime T: type) type { | |
| 11 | return struct { | |
| 12 | allocator: Allocator, | |
| 13 | buf: []T, | |
| 14 | head: usize, | |
| 15 | count: usize, | |
| 16 | ||
| 17 | const Self = @This(); | |
| 18 | ||
| 19 | pub fn init(allocator: Allocator) Self { | |
| 20 | return .{ | |
| 21 | .allocator = allocator, | |
| 22 | .buf = &.{}, | |
| 23 | .head = 0, | |
| 24 | .count = 0, | |
| 25 | }; | |
| 26 | } | |
| 27 | ||
| 28 | pub fn deinit(self: *Self) void { | |
| 29 | self.allocator.free(self.buf); | |
| 30 | self.* = undefined; | |
| 31 | } | |
| 32 | ||
| 33 | pub fn realign(self: *Self) void { | |
| 34 | if (self.buf.len - self.head >= self.count) { | |
| 35 | mem.copyForwards(T, self.buf[0..self.count], self.buf[self.head..][0..self.count]); | |
| 36 | self.head = 0; | |
| 37 | } else { | |
| 38 | var tmp: [4096 / 2 / @sizeOf(T)]T = undefined; | |
| 39 | ||
| 40 | while (self.head != 0) { | |
| 41 | const n = @min(self.head, tmp.len); | |
| 42 | const m = self.buf.len - n; | |
| 43 | @memcpy(tmp[0..n], self.buf[0..n]); | |
| 44 | mem.copyForwards(T, self.buf[0..m], self.buf[n..][0..m]); | |
| 45 | @memcpy(self.buf[m..][0..n], tmp[0..n]); | |
| 46 | self.head -= n; | |
| 47 | } | |
| 48 | } | |
| 49 | { // set unused area to undefined | |
| 50 | const unused = mem.sliceAsBytes(self.buf[self.count..]); | |
| 51 | @memset(unused, undefined); | |
| 52 | } | |
| 53 | } | |
| 54 | ||
| 55 | /// Ensure that the buffer can fit at least `size` items | |
| 56 | pub fn ensureTotalCapacity(self: *Self, size: usize) !void { | |
| 57 | if (self.buf.len >= size) return; | |
| 58 | self.realign(); | |
| 59 | const new_size = math.ceilPowerOfTwo(usize, size) catch return error.OutOfMemory; | |
| 60 | self.buf = try self.allocator.realloc(self.buf, new_size); | |
| 61 | } | |
| 62 | ||
| 63 | /// Makes sure at least `size` items are unused | |
| 64 | pub fn ensureUnusedCapacity(self: *Self, size: usize) error{OutOfMemory}!void { | |
| 65 | if (self.writableLength() >= size) return; | |
| 66 | ||
| 67 | return try self.ensureTotalCapacity(math.add(usize, self.count, size) catch return error.OutOfMemory); | |
| 68 | } | |
| 69 | ||
| 70 | /// Returns a writable slice from the 'read' end of the fifo | |
| 71 | fn readableSliceMut(self: Self, offset: usize) []T { | |
| 72 | if (offset > self.count) return &[_]T{}; | |
| 73 | ||
| 74 | var start = self.head + offset; | |
| 75 | if (start >= self.buf.len) { | |
| 76 | start -= self.buf.len; | |
| 77 | return self.buf[start .. start + (self.count - offset)]; | |
| 78 | } else { | |
| 79 | const end = @min(self.head + self.count, self.buf.len); | |
| 80 | return self.buf[start..end]; | |
| 81 | } | |
| 82 | } | |
| 83 | ||
| 84 | /// Discard first `count` items in the fifo | |
| 85 | pub fn discard(self: *Self, count: usize) void { | |
| 86 | assert(count <= self.count); | |
| 87 | { // set old range to undefined. Note: may be wrapped around | |
| 88 | const slice = self.readableSliceMut(0); | |
| 89 | if (slice.len >= count) { | |
| 90 | const unused = mem.sliceAsBytes(slice[0..count]); | |
| 91 | @memset(unused, undefined); | |
| 92 | } else { | |
| 93 | const unused = mem.sliceAsBytes(slice[0..]); | |
| 94 | @memset(unused, undefined); | |
| 95 | const unused2 = mem.sliceAsBytes(self.readableSliceMut(slice.len)[0 .. count - slice.len]); | |
| 96 | @memset(unused2, undefined); | |
| 97 | } | |
| 98 | } | |
| 99 | var head = self.head + count; | |
| 100 | // Note it is safe to do a wrapping subtract as | |
| 101 | // bitwise & with all 1s is a noop | |
| 102 | head &= self.buf.len -% 1; | |
| 103 | self.head = head; | |
| 104 | self.count -= count; | |
| 105 | } | |
| 106 | ||
| 107 | /// Read the next item from the fifo | |
| 108 | pub fn readItem(self: *Self) ?T { | |
| 109 | if (self.count == 0) return null; | |
| 110 | ||
| 111 | const c = self.buf[self.head]; | |
| 112 | self.discard(1); | |
| 113 | return c; | |
| 114 | } | |
| 115 | ||
| 116 | /// Returns number of items available in fifo | |
| 117 | pub fn writableLength(self: Self) usize { | |
| 118 | return self.buf.len - self.count; | |
| 119 | } | |
| 120 | ||
| 121 | /// Returns the first section of writable buffer. | |
| 122 | /// Note that this may be of length 0 | |
| 123 | pub fn writableSlice(self: Self, offset: usize) []T { | |
| 124 | if (offset > self.buf.len) return &[_]T{}; | |
| 125 | ||
| 126 | const tail = self.head + offset + self.count; | |
| 127 | if (tail < self.buf.len) { | |
| 128 | return self.buf[tail..]; | |
| 129 | } else { | |
| 130 | return self.buf[tail - self.buf.len ..][0 .. self.writableLength() - offset]; | |
| 131 | } | |
| 132 | } | |
| 133 | ||
| 134 | /// Update the tail location of the buffer (usually follows use of writable/writableWithSize) | |
| 135 | pub fn update(self: *Self, count: usize) void { | |
| 136 | assert(self.count + count <= self.buf.len); | |
| 137 | self.count += count; | |
| 138 | } | |
| 139 | ||
| 140 | /// Appends the data in `src` to the fifo. | |
| 141 | /// You must have ensured there is enough space. | |
| 142 | pub fn writeAssumeCapacity(self: *Self, src: []const T) void { | |
| 143 | assert(self.writableLength() >= src.len); | |
| 144 | ||
| 145 | var src_left = src; | |
| 146 | while (src_left.len > 0) { | |
| 147 | const writable_slice = self.writableSlice(0); | |
| 148 | assert(writable_slice.len != 0); | |
| 149 | const n = @min(writable_slice.len, src_left.len); | |
| 150 | @memcpy(writable_slice[0..n], src_left[0..n]); | |
| 151 | self.update(n); | |
| 152 | src_left = src_left[n..]; | |
| 153 | } | |
| 154 | } | |
| 155 | ||
| 156 | /// Write a single item to the fifo | |
| 157 | pub fn writeItem(self: *Self, item: T) !void { | |
| 158 | try self.ensureUnusedCapacity(1); | |
| 159 | return self.writeItemAssumeCapacity(item); | |
| 160 | } | |
| 161 | ||
| 162 | pub fn writeItemAssumeCapacity(self: *Self, item: T) void { | |
| 163 | var tail = self.head + self.count; | |
| 164 | tail &= self.buf.len - 1; | |
| 165 | self.buf[tail] = item; | |
| 166 | self.update(1); | |
| 167 | } | |
| 168 | }; | |
| 169 | } |