authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-03 23:08:33+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-12 10:20:57+02:00
log35403d41ce7845628d608ffd6fe16aa334f017ef
tree186c924c4dfe215457f621f96dbc7519ea6a1789
parentda57d6df320cb6bd9ce09bef192f201d59a50b28

macho: use array hashmaps for quick lookups

as containers for unresolved and tentative definitions when resolving symbols.

1 files changed, 24 insertions(+), 45 deletions(-)

src/link/MachO.zig+24-45
...@@ -2094,8 +2094,8 @@ fn writeStubHelperCommon(self: *MachO) !void {...@@ -2094,8 +2094,8 @@ fn writeStubHelperCommon(self: *MachO) !void {
2094fn resolveSymbolsInObject(2094fn resolveSymbolsInObject(
2095 self: *MachO,2095 self: *MachO,
2096 object_id: u16,2096 object_id: u16,
2097 tentatives: *std.ArrayList(u32),2097 tentatives: *std.AutoArrayHashMap(u32, void),
2098 unresolved: *std.ArrayList(u32),2098 unresolved: *std.AutoArrayHashMap(u32, void),
2099) !void {2099) !void {
2100 const object = &self.objects.items[object_id];2100 const object = &self.objects.items[object_id];
21012101
...@@ -2176,14 +2176,9 @@ fn resolveSymbolsInObject(...@@ -2176,14 +2176,9 @@ fn resolveSymbolsInObject(
2176 return error.MultipleSymbolDefinitions;2176 return error.MultipleSymbolDefinitions;
2177 }2177 }
2178 if (symbolIsWeakDef(sym) or symbolIsPext(sym)) continue; // Current symbol is weak, so skip it.2178 if (symbolIsWeakDef(sym) or symbolIsPext(sym)) continue; // Current symbol is weak, so skip it.
2179
2179 if (symbolIsTentative(global.*)) {2180 if (symbolIsTentative(global.*)) {
2180 var i: usize = 0;2181 _ = tentatives.fetchSwapRemove(resolv.where_index);
2181 while (i < tentatives.items.len) : (i += 1) {
2182 if (tentatives.items[i] == resolv.where_index) {
2183 _ = tentatives.swapRemove(i);
2184 break;
2185 }
2186 }
2187 }2182 }
21882183
2189 // Otherwise, update the resolver and the global symbol.2184 // Otherwise, update the resolver and the global symbol.
...@@ -2202,14 +2197,7 @@ fn resolveSymbolsInObject(...@@ -2202,14 +2197,7 @@ fn resolveSymbolsInObject(
2202 .n_desc = 0,2197 .n_desc = 0,
2203 .n_value = 0,2198 .n_value = 0,
2204 };2199 };
22052200 _ = unresolved.fetchSwapRemove(resolv.where_index);
2206 var i: usize = 0;
2207 while (i < unresolved.items.len) : (i += 1) {
2208 if (unresolved.items[i] == resolv.where_index) {
2209 _ = unresolved.swapRemove(i);
2210 break;
2211 }
2212 }
2213 },2201 },
2214 }2202 }
22152203
...@@ -2243,7 +2231,7 @@ fn resolveSymbolsInObject(...@@ -2243,7 +2231,7 @@ fn resolveSymbolsInObject(
2243 .where_index = global_sym_index,2231 .where_index = global_sym_index,
2244 .file = object_id,2232 .file = object_id,
2245 });2233 });
2246 try tentatives.append(global_sym_index);2234 _ = try tentatives.getOrPut(global_sym_index);
2247 continue;2235 continue;
2248 };2236 };
22492237
...@@ -2267,7 +2255,7 @@ fn resolveSymbolsInObject(...@@ -2267,7 +2255,7 @@ fn resolveSymbolsInObject(
2267 .n_desc = sym.n_desc,2255 .n_desc = sym.n_desc,
2268 .n_value = sym.n_value,2256 .n_value = sym.n_value,
2269 });2257 });
2270 try tentatives.append(global_sym_index);2258 _ = try tentatives.getOrPut(global_sym_index);
2271 resolv.* = .{2259 resolv.* = .{
2272 .where = .global,2260 .where = .global,
2273 .where_index = global_sym_index,2261 .where_index = global_sym_index,
...@@ -2280,13 +2268,7 @@ fn resolveSymbolsInObject(...@@ -2280,13 +2268,7 @@ fn resolveSymbolsInObject(
2280 .n_desc = 0,2268 .n_desc = 0,
2281 .n_value = 0,2269 .n_value = 0,
2282 };2270 };
2283 var i: usize = 0;2271 _ = unresolved.fetchSwapRemove(resolv.where_index);
2284 while (i < unresolved.items.len) : (i += 1) {
2285 if (unresolved.items[i] == resolv.where_index) {
2286 _ = unresolved.swapRemove(i);
2287 break;
2288 }
2289 }
2290 },2272 },
2291 }2273 }
2292 } else {2274 } else {
...@@ -2306,16 +2288,16 @@ fn resolveSymbolsInObject(...@@ -2306,16 +2288,16 @@ fn resolveSymbolsInObject(
2306 .where_index = undef_sym_index,2288 .where_index = undef_sym_index,
2307 .file = object_id,2289 .file = object_id,
2308 });2290 });
2309 try unresolved.append(undef_sym_index);2291 _ = try unresolved.getOrPut(undef_sym_index);
2310 }2292 }
2311 }2293 }
2312}2294}
23132295
2314fn resolveSymbols(self: *MachO) !void {2296fn resolveSymbols(self: *MachO) !void {
2315 var tentatives = std.ArrayList(u32).init(self.base.allocator);2297 var tentatives = std.AutoArrayHashMap(u32, void).init(self.base.allocator);
2316 defer tentatives.deinit();2298 defer tentatives.deinit();
23172299
2318 var unresolved = std.ArrayList(u32).init(self.base.allocator);2300 var unresolved = std.AutoArrayHashMap(u32, void).init(self.base.allocator);
2319 defer unresolved.deinit();2301 defer unresolved.deinit();
23202302
2321 // First pass, resolve symbols in provided objects.2303 // First pass, resolve symbols in provided objects.
...@@ -2325,8 +2307,8 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2325,8 +2307,8 @@ fn resolveSymbols(self: *MachO) !void {
23252307
2326 // Second pass, resolve symbols in static libraries.2308 // Second pass, resolve symbols in static libraries.
2327 var next_sym: usize = 0;2309 var next_sym: usize = 0;
2328 loop: while (next_sym < unresolved.items.len) {2310 loop: while (next_sym < unresolved.count()) {
2329 const sym = self.undefs.items[unresolved.items[next_sym]];2311 const sym = self.undefs.items[unresolved.keys()[next_sym]];
2330 const sym_name = self.getString(sym.n_strx);2312 const sym_name = self.getString(sym.n_strx);
23312313
2332 for (self.archives.items) |archive| {2314 for (self.archives.items) |archive| {
...@@ -2350,7 +2332,10 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2350,7 +2332,10 @@ fn resolveSymbols(self: *MachO) !void {
23502332
2351 // Convert any tentative definition into a regular symbol and allocate2333 // Convert any tentative definition into a regular symbol and allocate
2352 // text blocks for each tentative defintion.2334 // text blocks for each tentative defintion.
2353 while (tentatives.popOrNull()) |index| {2335 var tentatives_count: usize = 0;
2336 const ntentatives = tentatives.count();
2337 while (tentatives_count < ntentatives) : (tentatives_count += 1) {
2338 const index = tentatives.pop().key;
2354 const sym = &self.globals.items[index];2339 const sym = &self.globals.items[index];
2355 const match: MatchingSection = blk: {2340 const match: MatchingSection = blk: {
2356 if (self.common_section_index == null) {2341 if (self.common_section_index == null) {
...@@ -2430,12 +2415,12 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2430,12 +2415,12 @@ fn resolveSymbols(self: *MachO) !void {
2430 .where = .undef,2415 .where = .undef,
2431 .where_index = undef_sym_index,2416 .where_index = undef_sym_index,
2432 });2417 });
2433 try unresolved.append(undef_sym_index);2418 _ = try unresolved.getOrPut(undef_sym_index);
2434 }2419 }
24352420
2436 next_sym = 0;2421 next_sym = 0;
2437 loop: while (next_sym < unresolved.items.len) {2422 loop: while (next_sym < unresolved.count()) {
2438 const sym = self.undefs.items[unresolved.items[next_sym]];2423 const sym = self.undefs.items[unresolved.keys()[next_sym]];
2439 const sym_name = self.getString(sym.n_strx);2424 const sym_name = self.getString(sym.n_strx);
24402425
2441 for (self.dylibs.items) |dylib, id| {2426 for (self.dylibs.items) |dylib, id| {
...@@ -2452,7 +2437,7 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2452,7 +2437,7 @@ fn resolveSymbols(self: *MachO) !void {
2452 undef.n_type |= macho.N_EXT;2437 undef.n_type |= macho.N_EXT;
2453 undef.n_desc = @intCast(u16, ordinal + 1) * macho.N_SYMBOL_RESOLVER;2438 undef.n_desc = @intCast(u16, ordinal + 1) * macho.N_SYMBOL_RESOLVER;
24542439
2455 _ = unresolved.swapRemove(next_sym);2440 _ = unresolved.fetchSwapRemove(resolv.where_index);
24562441
2457 continue :loop;2442 continue :loop;
2458 }2443 }
...@@ -2486,13 +2471,7 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2486,13 +2471,7 @@ fn resolveSymbols(self: *MachO) !void {
2486 nlist.n_desc = macho.N_WEAK_DEF;2471 nlist.n_desc = macho.N_WEAK_DEF;
2487 try self.globals.append(self.base.allocator, nlist);2472 try self.globals.append(self.base.allocator, nlist);
24882473
2489 var i: usize = 0;2474 _ = unresolved.fetchSwapRemove(resolv.where_index);
2490 while (i < unresolved.items.len) : (i += 1) {
2491 if (unresolved.items[i] == resolv.where_index) {
2492 _ = unresolved.swapRemove(i);
2493 break;
2494 }
2495 }
24962475
2497 undef.* = .{2476 undef.* = .{
2498 .n_strx = 0,2477 .n_strx = 0,
...@@ -2526,7 +2505,7 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2526,7 +2505,7 @@ fn resolveSymbols(self: *MachO) !void {
2526 }2505 }
2527 }2506 }
25282507
2529 for (unresolved.items) |index| {2508 for (unresolved.keys()) |index| {
2530 const sym = self.undefs.items[index];2509 const sym = self.undefs.items[index];
2531 const sym_name = self.getString(sym.n_strx);2510 const sym_name = self.getString(sym.n_strx);
2532 const resolv = self.symbol_resolver.get(sym.n_strx) orelse unreachable;2511 const resolv = self.symbol_resolver.get(sym.n_strx) orelse unreachable;
...@@ -2535,7 +2514,7 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2535,7 +2514,7 @@ fn resolveSymbols(self: *MachO) !void {
2535 log.err(" first referenced in '{s}'", .{self.objects.items[resolv.file].name});2514 log.err(" first referenced in '{s}'", .{self.objects.items[resolv.file].name});
2536 }2515 }
25372516
2538 if (unresolved.items.len > 0)2517 if (unresolved.count() > 0)
2539 return error.UndefinedSymbolReference;2518 return error.UndefinedSymbolReference;
2540}2519}
25412520