Skip to content

Commit

Permalink
macho: redo deduping literals yet again
Browse files Browse the repository at this point in the history
This time we can completely get rid of the mutex in Symbol.
  • Loading branch information
kubkon committed Jul 1, 2024
1 parent c62e005 commit 5334972
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 59 deletions.
2 changes: 1 addition & 1 deletion src/MachO.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1595,7 +1595,7 @@ fn calcSectionSizeWorker(self: *MachO, sect_id: u8) void {
) !void {
for (atoms) |ref| {
const atom = ref.getAtom(macho_file).?;
const p2align = atom.alignment.load(.seq_cst);
const p2align = atom.alignment;
const atom_alignment = try math.powi(u32, 2, p2align);
const offset = mem.alignForward(u64, header.size, atom_alignment);
const padding = offset - header.size;
Expand Down
6 changes: 3 additions & 3 deletions src/MachO/Atom.zig
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ file: File.Index = 0,
size: u64 = 0,

/// Alignment of this atom as a power of two.
alignment: std.atomic.Value(u32) = std.atomic.Value(u32).init(0),
alignment: u32 = 0,

/// Index of the input section.
n_sect: u32 = 0,
Expand Down Expand Up @@ -861,8 +861,8 @@ fn format2(
const macho_file = ctx.macho_file;
const file = atom.getFile(macho_file);
try writer.print("atom({d}) : {s} : @{x} : sect({d}) : align({x}) : size({x}) : thunk({d})", .{
atom.atom_index, atom.getName(macho_file), atom.getAddress(macho_file),
atom.out_n_sect, atom.alignment.load(.seq_cst), atom.size,
atom.atom_index, atom.getName(macho_file), atom.getAddress(macho_file),
atom.out_n_sect, atom.alignment, atom.size,
atom.getExtra(macho_file).thunk,
});
if (!atom.alive.load(.seq_cst)) try writer.writeAll(" : [*]");
Expand Down
56 changes: 25 additions & 31 deletions src/MachO/InternalObject.zig
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ fn addObjcMethnameSection(self: *InternalObject, methname: []const u8, macho_fil
try self.atoms_indexes.append(gpa, atom_index);
const atom = self.getAtom(atom_index).?;
atom.size = methname.len + 1;
atom.alignment.store(0, .seq_cst);
atom.alignment = 0;

const n_sect = try self.addSection(gpa, "__TEXT", "__objc_methname");
const sect = &self.sections.items(.header)[n_sect];
Expand Down Expand Up @@ -291,7 +291,7 @@ fn addObjcSelrefsSection(self: *InternalObject, methname_sym_index: Symbol.Index
try self.atoms_indexes.append(gpa, atom_index);
const atom = self.getAtom(atom_index).?;
atom.size = @sizeOf(u64);
atom.alignment.store(3, .seq_cst);
atom.alignment = 3;

const n_sect = try self.addSection(gpa, "__DATA", "__objc_selrefs");
const sect = &self.sections.items(.header)[n_sect];
Expand Down Expand Up @@ -422,6 +422,11 @@ pub fn resolveLiterals(self: *InternalObject, lp: *MachO.LiteralPool, macho_file
buffer.clearRetainingCapacity();
if (!res.found_existing) {
res.ref.* = .{ .index = atom.getExtra(macho_file).literal_symbol_index, .file = self.index };
} else {
const lp_sym = lp.getSymbol(res.index, macho_file);
const lp_atom = lp_sym.getAtom(macho_file).?;
lp_atom.alignment = @max(lp_atom.alignment, atom.alignment);
_ = atom.alive.swap(false, .seq_cst);
}
atom.addExtra(.{ .literal_pool_index = res.index }, macho_file);
}
Expand All @@ -443,22 +448,16 @@ pub fn dedupLiterals(self: *InternalObject, lp: MachO.LiteralPool, macho_file: *
for (relocs) |*rel| {
if (rel.tag != .@"extern") continue;
const target_sym_ref = rel.getTargetSymbolRef(atom.*, macho_file);
if (target_sym_ref.getFile(macho_file) != null) {
const target_sym = target_sym_ref.getSymbol(macho_file).?;
if (target_sym.getAtom(macho_file)) |target_atom| {
if (!Object.isPtrLiteral(target_atom.getInputSection(macho_file))) continue;
const lp_index = target_atom.getExtra(macho_file).literal_pool_index;
const lp_sym = lp.getSymbol(lp_index, macho_file);
const lp_atom_ref = lp_sym.atom_ref;
if (target_atom.atom_index != lp_atom_ref.index or target_atom.file != lp_atom_ref.file) {
const lp_atom = lp_sym.getAtom(macho_file).?;
_ = lp_atom.alignment.fetchMax(target_atom.alignment.load(.seq_cst), .seq_cst);
_ = target_atom.alive.swap(false, .seq_cst);
target_sym.mutex.lock();
defer target_sym.mutex.unlock();
target_sym.atom_ref = lp_atom_ref;
}
}
const file = target_sym_ref.getFile(macho_file) orelse continue;
if (file.getIndex() != self.index) continue;
const target_sym = target_sym_ref.getSymbol(macho_file).?;
const target_atom = target_sym.getAtom(macho_file) orelse continue;
if (!Object.isPtrLiteral(target_atom.getInputSection(macho_file))) continue;
const lp_index = target_atom.getExtra(macho_file).literal_pool_index;
const lp_sym = lp.getSymbol(lp_index, macho_file);
const lp_atom_ref = lp_sym.atom_ref;
if (target_atom.atom_index != lp_atom_ref.index or target_atom.file != lp_atom_ref.file) {
target_sym.atom_ref = lp_atom_ref;
}
}
}
Expand All @@ -467,23 +466,18 @@ pub fn dedupLiterals(self: *InternalObject, lp: MachO.LiteralPool, macho_file: *
if (!sym.getSectionFlags().objc_stubs) continue;
const extra = sym.getExtra(macho_file);
const file = sym.getFile(macho_file).?;
if (file.getIndex() != self.index) continue;
const tsym = switch (file) {
.dylib => unreachable,
inline else => |x| &x.symbols.items[extra.objc_selrefs],
};
if (tsym.getAtom(macho_file)) |atom| {
if (!Object.isPtrLiteral(atom.getInputSection(macho_file))) continue;
const lp_index = atom.getExtra(macho_file).literal_pool_index;
const lp_sym = lp.getSymbol(lp_index, macho_file);
const lp_atom_ref = lp_sym.atom_ref;
if (atom.atom_index != lp_atom_ref.index or atom.file != lp_atom_ref.file) {
const lp_atom = lp_sym.getAtom(macho_file).?;
_ = lp_atom.alignment.fetchMax(atom.alignment.load(.seq_cst), .seq_cst);
_ = atom.alive.swap(false, .seq_cst);
tsym.mutex.lock();
defer tsym.mutex.unlock();
tsym.atom_ref = lp_atom_ref;
}
const atom = tsym.getAtom(macho_file) orelse continue;
if (!Object.isPtrLiteral(atom.getInputSection(macho_file))) continue;
const lp_index = atom.getExtra(macho_file).literal_pool_index;
const lp_sym = lp.getSymbol(lp_index, macho_file);
const lp_atom_ref = lp_sym.atom_ref;
if (atom.atom_index != lp_atom_ref.index or atom.file != lp_atom_ref.file) {
tsym.atom_ref = lp_atom_ref;
}
}
}
Expand Down
53 changes: 34 additions & 19 deletions src/MachO/Object.zig
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,11 @@ pub fn resolveLiterals(self: *Object, lp: *MachO.LiteralPool, macho_file: *MachO
const res = try lp.insert(gpa, header.type(), atom_data);
if (!res.found_existing) {
res.ref.* = .{ .index = atom.getExtra(macho_file).literal_symbol_index, .file = self.index };
} else {
const lp_sym = lp.getSymbol(res.index, macho_file);
const lp_atom = lp_sym.getAtom(macho_file).?;
lp_atom.alignment = @max(lp_atom.alignment, atom.alignment);
_ = atom.alive.swap(false, .seq_cst);
}
atom.addExtra(.{ .literal_pool_index = res.index }, macho_file);
}
Expand Down Expand Up @@ -666,6 +671,11 @@ pub fn resolveLiterals(self: *Object, lp: *MachO.LiteralPool, macho_file: *MachO
buffer.clearRetainingCapacity();
if (!res.found_existing) {
res.ref.* = .{ .index = atom.getExtra(macho_file).literal_symbol_index, .file = self.index };
} else {
const lp_sym = lp.getSymbol(res.index, macho_file);
const lp_atom = lp_sym.getAtom(macho_file).?;
lp_atom.alignment = @max(lp_atom.alignment, atom.alignment);
_ = atom.alive.swap(false, .seq_cst);
}
atom.addExtra(.{ .literal_pool_index = res.index }, macho_file);
}
Expand All @@ -689,27 +699,32 @@ pub fn dedupLiterals(self: *Object, lp: MachO.LiteralPool, macho_file: *MachO) v
for (relocs) |*rel| {
if (rel.tag != .@"extern") continue;
const target_sym_ref = rel.getTargetSymbolRef(atom.*, macho_file);
if (target_sym_ref.getFile(macho_file) != null) {
const target_sym = target_sym_ref.getSymbol(macho_file).?;
if (target_sym.getAtom(macho_file)) |target_atom| {
const isec = target_atom.getInputSection(macho_file);
if (Object.isCstringLiteral(isec) or Object.isFixedSizeLiteral(isec) or Object.isPtrLiteral(isec)) {
const lp_index = target_atom.getExtra(macho_file).literal_pool_index;
const lp_sym = lp.getSymbol(lp_index, macho_file);
const lp_atom_ref = lp_sym.atom_ref;
if (target_atom.atom_index != lp_atom_ref.index or target_atom.file != lp_atom_ref.file) {
const lp_atom = lp_sym.getAtom(macho_file).?;
_ = lp_atom.alignment.fetchMax(target_atom.alignment.load(.seq_cst), .seq_cst);
_ = target_atom.alive.swap(false, .seq_cst);
target_sym.mutex.lock();
defer target_sym.mutex.unlock();
target_sym.atom_ref = lp_atom_ref;
}
}
}
const file = target_sym_ref.getFile(macho_file) orelse continue;
if (file.getIndex() != self.index) continue;
const target_sym = target_sym_ref.getSymbol(macho_file).?;
const target_atom = target_sym.getAtom(macho_file) orelse continue;
const isec = target_atom.getInputSection(macho_file);
if (!Object.isCstringLiteral(isec) and !Object.isFixedSizeLiteral(isec) and !Object.isPtrLiteral(isec)) continue;
const lp_index = target_atom.getExtra(macho_file).literal_pool_index;
const lp_sym = lp.getSymbol(lp_index, macho_file);
const lp_atom_ref = lp_sym.atom_ref;
if (target_atom.atom_index != lp_atom_ref.index or target_atom.file != lp_atom_ref.file) {
target_sym.atom_ref = lp_atom_ref;
}
}
}

for (self.symbols.items) |*sym| {
const atom = sym.getAtom(macho_file) orelse continue;
const isec = atom.getInputSection(macho_file);
if (!Object.isCstringLiteral(isec) and !Object.isFixedSizeLiteral(isec) and !Object.isPtrLiteral(isec)) continue;
const lp_index = atom.getExtra(macho_file).literal_pool_index;
const lp_sym = lp.getSymbol(lp_index, macho_file);
const lp_atom_ref = lp_sym.atom_ref;
if (atom.atom_index != lp_atom_ref.index or self.index != lp_atom_ref.file) {
sym.atom_ref = lp_atom_ref;
}
}
}

pub fn findAtom(self: Object, addr: u64) ?Atom.Index {
Expand Down Expand Up @@ -2258,8 +2273,8 @@ fn addAtom(self: *Object, allocator: Allocator, args: AddAtomArgs) !Atom.Index {
.size = args.size,
.off = args.off,
.extra = try self.addAtomExtra(allocator, .{}),
.alignment = args.alignment,
};
atom.alignment.store(args.alignment, .seq_cst);
return atom_index;
}

Expand Down
2 changes: 0 additions & 2 deletions src/MachO/Symbol.zig
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ visibility: Visibility = .local,

extra: u32 = 0,

mutex: std.Thread.Mutex = .{},

pub fn isLocal(symbol: Symbol) bool {
return !(symbol.flags.import or symbol.flags.@"export");
}
Expand Down
2 changes: 1 addition & 1 deletion src/MachO/relocatable.zig
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ fn calcSectionSizeWorker(macho_file: *MachO, sect_id: u8) void {
fn doWork(mfile: *MachO, header: *macho.section_64, atoms: []const MachO.Ref) !void {
for (atoms) |ref| {
const atom = ref.getAtom(mfile).?;
const p2align = atom.alignment.load(.seq_cst);
const p2align = atom.alignment;
const atom_alignment = try math.powi(u32, 2, p2align);
const offset = mem.alignForward(u64, header.size, atom_alignment);
const padding = offset - header.size;
Expand Down
4 changes: 2 additions & 2 deletions src/MachO/thunks.zig
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ pub fn createThunks(sect_id: u8, macho_file: *MachO) !void {
const start = i;
const start_atom = atoms[start].getAtom(macho_file).?;
assert(start_atom.alive.load(.seq_cst));
start_atom.value = try advance(header, start_atom.size, start_atom.alignment.load(.seq_cst));
start_atom.value = try advance(header, start_atom.size, start_atom.alignment);
i += 1;

while (i < atoms.len and
header.size - start_atom.value < max_allowed_distance) : (i += 1)
{
const atom = atoms[i].getAtom(macho_file).?;
assert(atom.alive.load(.seq_cst));
atom.value = try advance(header, atom.size, atom.alignment.load(.seq_cst));
atom.value = try advance(header, atom.size, atom.alignment);
}

// Insert a thunk at the group end
Expand Down

0 comments on commit 5334972

Please sign in to comment.