authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-08 13:22:48+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-08 13:22:48+01:00
logdcb7f5791a206d7713bea153a8d94f22dfb155a9
treee4b0e3196d2d1a50ed990d6b05c75bd6e8909342
parent102846315c1be4518ce7783717dc1ceb133b66cf

macho: alloc improvement for relocatable


2 files changed, 60 insertions(+), 46 deletions(-)

src/link/MachO.zig+49-37
...@@ -3202,20 +3202,22 @@ fn detectAllocCollision(self: *MachO, start: u64, size: u64) ?u64 {...@@ -3202,20 +3202,22 @@ fn detectAllocCollision(self: *MachO, start: u64, size: u64) ?u64 {
32023202
3203 const end = start + padToIdeal(size);3203 const end = start + padToIdeal(size);
32043204
3205 for (self.sections.items(.header)) |header| {3205 if (self.base.isRelocatable()) {
3206 if (header.isZerofill()) continue;3206 for (self.sections.items(.header)) |header| {
3207 const increased_size = padToIdeal(header.size);3207 if (header.isZerofill()) continue;
3208 const test_end = header.offset +| increased_size;3208 const increased_size = padToIdeal(header.size);
3209 if (end > header.offset and start < test_end) {3209 const test_end = header.offset +| increased_size;
3210 return test_end;3210 if (end > header.offset and start < test_end) {
3211 return test_end;
3212 }
3211 }3213 }
3212 }3214 } else {
32133215 for (self.segments.items) |seg| {
3214 for (self.segments.items) |seg| {3216 const increased_size = padToIdeal(seg.filesize);
3215 const increased_size = padToIdeal(seg.filesize);3217 const test_end = seg.fileoff +| increased_size;
3216 const test_end = seg.fileoff +| increased_size;3218 if (end > seg.fileoff and start < test_end) {
3217 if (end > seg.fileoff and start < test_end) {3219 return test_end;
3218 return test_end;3220 }
3219 }3221 }
3220 }3222 }
32213223
...@@ -3223,27 +3225,29 @@ fn detectAllocCollision(self: *MachO, start: u64, size: u64) ?u64 {...@@ -3223,27 +3225,29 @@ fn detectAllocCollision(self: *MachO, start: u64, size: u64) ?u64 {
3223}3225}
32243226
3225fn detectAllocCollisionVirtual(self: *MachO, start: u64, size: u64) ?u64 {3227fn detectAllocCollisionVirtual(self: *MachO, start: u64, size: u64) ?u64 {
3226 // Conservatively commit one page size as reserved space for the headers as we
3227 // expect it to grow and everything else be moved in flush anyhow.
3228 const header_size = self.getPageSize();
3229 if (start < header_size)
3230 return header_size;
3231
3232 const end = start + padToIdeal(size);3228 const end = start + padToIdeal(size);
32333229
3234 for (self.sections.items(.header)) |header| {3230 if (self.base.isRelocatable()) {
3235 const increased_size = padToIdeal(header.size);3231 for (self.sections.items(.header)) |header| {
3236 const test_end = header.addr +| increased_size;3232 const increased_size = padToIdeal(header.size);
3237 if (end > header.addr and start < test_end) {3233 const test_end = header.addr +| increased_size;
3238 return test_end;3234 if (end > header.addr and start < test_end) {
3235 return test_end;
3236 }
3239 }3237 }
3240 }3238 } else {
3239 // Conservatively commit one page size as reserved space for the headers as we
3240 // expect it to grow and everything else be moved in flush anyhow.
3241 const header_size = self.getPageSize();
3242 if (start < header_size)
3243 return header_size;
32413244
3242 for (self.segments.items) |seg| {3245 for (self.segments.items) |seg| {
3243 const increased_size = padToIdeal(seg.vmsize);3246 const increased_size = padToIdeal(seg.vmsize);
3244 const test_end = seg.vmaddr +| increased_size;3247 const test_end = seg.vmaddr +| increased_size;
3245 if (end > seg.vmaddr and start < test_end) {3248 if (end > seg.vmaddr and start < test_end) {
3246 return test_end;3249 return test_end;
3250 }
3247 }3251 }
3248 }3252 }
32493253
...@@ -3252,21 +3256,29 @@ fn detectAllocCollisionVirtual(self: *MachO, start: u64, size: u64) ?u64 {...@@ -3252,21 +3256,29 @@ fn detectAllocCollisionVirtual(self: *MachO, start: u64, size: u64) ?u64 {
32523256
3253pub fn allocatedSize(self: *MachO, start: u64) u64 {3257pub fn allocatedSize(self: *MachO, start: u64) u64 {
3254 if (start == 0) return 0;3258 if (start == 0) return 0;
3259
3255 var min_pos: u64 = std.math.maxInt(u64);3260 var min_pos: u64 = std.math.maxInt(u64);
3256 for (self.sections.items(.header)) |header| {3261
3257 if (header.offset <= start) continue;3262 if (self.base.isRelocatable()) {
3258 if (header.offset < min_pos) min_pos = header.offset;3263 for (self.sections.items(.header)) |header| {
3259 }3264 if (header.offset <= start) continue;
3260 for (self.segments.items) |seg| {3265 if (header.offset < min_pos) min_pos = header.offset;
3261 if (seg.fileoff <= start) continue;3266 }
3262 if (seg.fileoff < min_pos) min_pos = seg.fileoff;3267 } else {
3268 for (self.segments.items) |seg| {
3269 if (seg.fileoff <= start) continue;
3270 if (seg.fileoff < min_pos) min_pos = seg.fileoff;
3271 }
3263 }3272 }
3273
3264 return min_pos - start;3274 return min_pos - start;
3265}3275}
32663276
3267pub fn allocatedSizeVirtual(self: *MachO, start: u64) u64 {3277pub fn allocatedSizeVirtual(self: *MachO, start: u64) u64 {
3268 if (start == 0) return 0;3278 if (start == 0) return 0;
3279
3269 var min_pos: u64 = std.math.maxInt(u64);3280 var min_pos: u64 = std.math.maxInt(u64);
3281
3270 if (self.base.isRelocatable()) {3282 if (self.base.isRelocatable()) {
3271 for (self.sections.items(.header)) |header| {3283 for (self.sections.items(.header)) |header| {
3272 if (header.addr <= start) continue;3284 if (header.addr <= start) continue;
src/link/MachO/relocatable.zig+11-9
...@@ -437,18 +437,20 @@ fn calcCompactUnwindSize(macho_file: *MachO, sect_index: u8) void {...@@ -437,18 +437,20 @@ fn calcCompactUnwindSize(macho_file: *MachO, sect_index: u8) void {
437437
438fn allocateSections(macho_file: *MachO) !void {438fn allocateSections(macho_file: *MachO) !void {
439 const slice = macho_file.sections.slice();439 const slice = macho_file.sections.slice();
440440 for (slice.items(.header)) |*header| {
441 const last_index = for (0..slice.items(.header).len) |i| {441 const needed_size = header.size;
442 if (macho_file.isZigSection(@intCast(i))) break i;442 header.size = 0;
443 } else slice.items(.header).len;
444
445 for (slice.items(.header)[0..last_index]) |*header| {
446 const alignment = try math.powi(u32, 2, header.@"align");443 const alignment = try math.powi(u32, 2, header.@"align");
447 if (!header.isZerofill()) {444 if (!header.isZerofill()) {
448 header.offset = math.cast(u32, macho_file.findFreeSpace(header.size, alignment)) orelse445 if (needed_size > macho_file.allocatedSize(header.offset)) {
449 return error.Overflow;446 header.offset = math.cast(u32, macho_file.findFreeSpace(needed_size, alignment)) orelse
447 return error.Overflow;
448 }
449 }
450 if (needed_size > macho_file.allocatedSizeVirtual(header.addr)) {
451 header.addr = macho_file.findFreeSpaceVirtual(needed_size, alignment);
450 }452 }
451 header.addr = macho_file.findFreeSpaceVirtual(header.size, alignment);453 header.size = needed_size;
452 }454 }
453}455}
454456