Skip to content

Commit c6d5217

Browse files
committed
Reduce stack and heap allocations
1 parent d3290a6 commit c6d5217

File tree

5 files changed

+66
-57
lines changed

5 files changed

+66
-57
lines changed

src/bootstrap.zig

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,11 @@ fn mono_doorstop_bootstrap(mono_domain: *mono.Domain) void {
3838
}, 0) catch @panic("Out of memory");
3939
defer alloc.free(config_path);
4040

41-
const config_path_n = util.narrow(config_path);
41+
const config_path_n = util.narrow(true, true, config_path);
4242
defer config_path_n.deinit();
4343

4444
const folder_path = root.util.paths.getFolderName(os_char, app_path);
45-
defer alloc.free(folder_path);
46-
const folder_path_n = util.narrow(folder_path);
45+
const folder_path_n = util.narrow(false, true, folder_path);
4746
defer folder_path_n.deinit();
4847

4948
logger.debug("Setting config paths: base dir: {s}; config path: {s}", .{ folder_path_n.str, config_path_n.str });
@@ -52,17 +51,19 @@ fn mono_doorstop_bootstrap(mono_domain: *mono.Domain) void {
5251
}
5352

5453
const assembly_dir = std.mem.span(mono.addrs.assembly_getrootdir.?());
55-
const norm_assembly_dir = util.widen(assembly_dir);
56-
defer norm_assembly_dir.deinit();
5754

5855
mono.addrs.config_parse.?(null);
5956

6057
logger.debug("Assembly dir: {s}", .{assembly_dir});
61-
util.setEnv("DOORSTOP_MANAGED_FOLDER_DIR", norm_assembly_dir.str);
58+
{
59+
const norm_assembly_dir = util.widen(assembly_dir);
60+
defer norm_assembly_dir.deinit();
61+
util.setEnv("DOORSTOP_MANAGED_FOLDER_DIR", norm_assembly_dir.str);
62+
}
6263

6364
logger.debug("Opening assembly: {}", .{util.fmtString(config.target_assembly.?)});
6465

65-
const dll_path = util.narrow(config.target_assembly.?);
66+
const dll_path = util.narrow(true, true, config.target_assembly.?);
6667
defer dll_path.deinit();
6768
logger.debug("narrowed dll path", .{});
6869
const image = blk: {
@@ -127,7 +128,7 @@ pub fn init_mono(root_domain_name: [*:0]const u8, runtime_version: [*:0]const u8
127128
logger.debug("Overriding mono DLL search path", .{});
128129

129130
const mono_search_path_alloc = if (config.mono_dll_search_path_override) |paths| blk: {
130-
const mono_dll_search_path_override_n = util.narrow(paths);
131+
const mono_dll_search_path_override_n = util.narrow(true, false, paths);
131132
defer mono_dll_search_path_override_n.deinit();
132133
break :blk std.mem.concatWithSentinel(
133134
alloc,
@@ -193,15 +194,9 @@ fn il2cpp_doorstop_bootstrap() void {
193194

194195
var program_path_buf = util.paths.ProgramPathBuf{};
195196
const app_path = program_path_buf.get();
196-
const app_path_n = util.narrow(app_path);
197-
defer app_path_n.deinit();
198197

199198
const target_dir = util.paths.getFolderName(os_char, config.target_assembly.?);
200-
defer alloc.free(target_dir);
201199
const target_name = util.paths.getFileName(os_char, config.target_assembly.?, false);
202-
defer alloc.free(target_name);
203-
const target_name_n = util.narrow(target_name);
204-
defer target_name_n.deinit();
205200

206201
const app_paths_env = std.mem.concatWithSentinel(
207202
alloc,
@@ -211,7 +206,7 @@ fn il2cpp_doorstop_bootstrap() void {
211206
) catch @panic("Out of memory");
212207
defer alloc.free(app_paths_env);
213208

214-
const app_paths_env_n = util.narrow(app_paths_env);
209+
const app_paths_env_n = util.narrow(true, true, app_paths_env);
215210
defer app_paths_env_n.deinit();
216211

217212
logger.debug("App path: {}", .{util.fmtString(app_path)});
@@ -227,13 +222,18 @@ fn il2cpp_doorstop_bootstrap() void {
227222
util.setEnv("DOORSTOP_PROCESS_PATH", app_path);
228223
util.setEnv("DOORSTOP_DLL_SEARCH_DIRS", app_paths_env);
229224

225+
const app_path_n = util.narrow(true, true, app_path);
226+
defer app_path_n.deinit();
227+
230228
var host: ?*anyopaque = null;
231229
var domain_id: u32 = 0;
232230
var result = coreclr.addrs.initialize.?(app_path_n.str, "Doorstop Domain", 1, &.{props}, &.{app_paths_env_n.str}, &host, &domain_id);
233231
if (result != 0) {
234232
std.debug.panic("Failed to initialize CoreCLR: 0x{x:0>8}", .{result});
235233
}
236234

235+
const target_name_n = util.narrow(false, true, target_name);
236+
defer target_name_n.deinit();
237237
var startup: ?*const fn () callconv(.c) void = null;
238238
result = coreclr.addrs.create_delegate.?(host.?, domain_id, target_name_n.str, "Doorstop.Entrypoint", "Start", @ptrCast(&startup));
239239
if (result != 0) {
@@ -252,7 +252,7 @@ pub fn init_il2cpp(domain_name: [*:0]const u8) callconv(.c) i32 {
252252
}
253253

254254
pub fn hook_mono_jit_parse_options(argc: c_int, argv: [*][*:0]u8) callconv(.c) void {
255-
const debug_options_buf = if (@import("Config.zig").getEnvStrRef("DNSPY_UNITY_DBG2")) |s| util.narrow(s) else null;
255+
const debug_options_buf = if (@import("Config.zig").getEnvStrRef("DNSPY_UNITY_DBG2")) |s| util.narrow(true, true, s) else null;
256256
defer if (debug_options_buf) |buf| buf.deinit();
257257
var debug_options = if (debug_options_buf) |buf| buf.str else null;
258258
defer if (debug_options) |s| if (debug_options_buf == null) alloc.free(s);
@@ -269,15 +269,23 @@ pub fn hook_mono_jit_parse_options(argc: c_int, argv: [*][*:0]u8) callconv(.c) v
269269
@memcpy(new_argv[0..@intCast(argc)], argv);
270270

271271
if (debug_options == null) {
272-
const mono_debug_address_alloc = if (config.mono_debug_address) |s| util.narrow(s) else null;
273-
defer if (mono_debug_address_alloc) |s| s.deinit();
274-
const mono_debug_address: []const u8 = if (mono_debug_address_alloc) |s| s.str else "127.0.0.1:10000";
275-
276-
const MONO_DEBUG_NO_SUSPEND = ",suspend=n";
277-
const MONO_DEBUG_NO_SUSPEND_NET35 = ",suspend=n,defer=y";
278-
debug_options = std.fmt.allocPrintZ(alloc, "--debugger-agent=transport=dt_socket,server=y,address={s}{s}", .{
272+
const max_ipv6_addr_len = 5 * 8 - 1;
273+
const max_port_len = 5;
274+
var mono_debug_address_buf: if (builtin.os.tag == .windows) [max_ipv6_addr_len + 1 + max_port_len]u8 else void = undefined;
275+
const mono_debug_address: []const u8 = if (config.mono_debug_address) |s| switch (builtin.os.tag) {
276+
.windows => blk: {
277+
const n = std.unicode.utf16LeToUtf8(&mono_debug_address_buf, s) catch |e| {
278+
std.debug.panic("Invalid Mono debugger agent address: {}", .{e});
279+
};
280+
break :blk mono_debug_address_buf[0..n];
281+
},
282+
else => s,
283+
} else "127.0.0.1:10000";
284+
285+
debug_options = std.fmt.allocPrintZ(alloc, "--debugger-agent=transport=dt_socket,server=y,address={s}{s}{s}", .{
279286
mono_debug_address,
280-
if (config.mono_debug_suspend) "" else if (mono_is_net35) MONO_DEBUG_NO_SUSPEND_NET35 else MONO_DEBUG_NO_SUSPEND,
287+
if (config.mono_debug_suspend) "" else ",suspend=n",
288+
if (config.mono_debug_suspend or !mono_is_net35) "" else ",defer=y",
281289
}) catch @panic("Out of memory");
282290
}
283291

@@ -299,7 +307,7 @@ pub fn hook_mono_image_open_from_data_with_name(
299307
name: [*:0]const u8,
300308
) callconv(.c) ?*mono.Image {
301309
if (config.mono_dll_search_path_override) |mono_dll_search_path_override| {
302-
const name_file = root.util.paths.getFileNameRef(u8, std.mem.span(name), true);
310+
const name_file = root.util.paths.getFileName(u8, std.mem.span(name), true);
303311

304312
const name_file_len = std.unicode.calcWtf16LeLen(name_file) catch @panic("Invalid WTF-8");
305313
const new_full_path = alloc.allocSentinel(os_char, name_file_len + 1 + mono_dll_search_path_override.len, 0) catch @panic("Out of memory");

src/entrypoint.zig

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,19 @@ pub fn entrypoint(module: if (builtin.os.tag == .windows) std.os.windows.HMODULE
3535

3636
logger.debug("Doorstop started!", .{});
3737

38-
var program_path_buf = util.paths.ProgramPathBuf{};
39-
const app_path = program_path_buf.get();
40-
const app_dir = util.paths.getFolderName(util.os_char, app_path);
41-
logger.debug("Executable path: {}", .{util.fmtString(app_path)});
42-
logger.debug("Application dir: {}", .{util.fmtString(app_dir)});
43-
44-
const working_dir = util.paths.getWorkingDir();
45-
defer alloc.free(working_dir);
46-
logger.debug("Working dir: {}", .{util.fmtString(working_dir)});
38+
{
39+
var program_path_buf = util.paths.ProgramPathBuf{};
40+
const app_path = program_path_buf.get();
41+
const app_dir = util.paths.getFolderName(util.os_char, app_path);
42+
logger.debug("Executable path: {}", .{util.fmtString(app_path)});
43+
logger.debug("Application dir: {}", .{util.fmtString(app_dir)});
44+
}
45+
46+
{
47+
const working_dir = util.paths.getWorkingDir() catch |e| std.debug.panic("Failed to determine current working directory path: {}", .{e});
48+
defer alloc.free(working_dir);
49+
logger.debug("Working dir: {}", .{util.fmtString(working_dir)});
50+
}
4751

4852
var doorstop_path_buf = util.paths.ModulePathBuf{};
4953
const doorstop_path = doorstop_path_buf.get(switch (builtin.os.tag) {

src/hooks.zig

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ fn hookBootConfigCommon() ?[*:0]const os_char {
2323
.macos => blk: {
2424
var program_path_buf = util.paths.ProgramPathBuf{};
2525
const program_path = program_path_buf.get();
26-
const app_folder = util.paths.getFolderNameRef(u8, util.paths.getFolderNameRef(u8, program_path));
26+
const app_folder = util.paths.getFolderName(u8, util.paths.getFolderName(u8, program_path));
2727

2828
break :blk std.fmt.allocPrintZ(
2929
alloc,
@@ -32,15 +32,11 @@ fn hookBootConfigCommon() ?[*:0]const os_char {
3232
) catch @panic("Out of memory");
3333
},
3434
else => blk: {
35-
const working_dir = util.paths.getWorkingDir();
36-
defer alloc.free(working_dir);
3735
var program_path_buf = util.paths.ProgramPathBuf{};
3836
const program_path = program_path_buf.get();
39-
const file_name = util.paths.getFileNameRef(os_char, program_path, false);
37+
const file_name = util.paths.getFileName(os_char, program_path, false);
4038

4139
break :blk std.mem.concatWithSentinel(alloc, os_char, &.{
42-
working_dir,
43-
util.osStrLiteral(std.fs.path.sep_str),
4440
file_name,
4541
util.osStrLiteral("_Data" ++ std.fs.path.sep_str ++ "boot.config"),
4642
}, 0) catch @panic("Out of memory");

src/util.zig

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub fn fmtAddress(ptr: anytype) FmtAddress {
4545
}
4646

4747
pub const FmtString = struct {
48-
str: [:0]const os_char,
48+
str: []const os_char,
4949

5050
pub fn format(
5151
self: @This(),
@@ -65,15 +65,15 @@ pub const FmtString = struct {
6565
}
6666
};
6767

68-
pub fn fmtString(str: [:0]const os_char) FmtString {
68+
pub fn fmtString(str: []const os_char) FmtString {
6969
return .{ .str = str };
7070
}
7171

72-
pub fn narrow(str: [:0]const os_char) struct {
73-
str: [:0]const u8,
72+
pub fn narrow(comptime nt_in: bool, comptime nt_out: bool, str: if (nt_in) [:0]const os_char else []const os_char) struct {
73+
str: if (nt_out) [:0]const u8 else []const u8,
7474

7575
pub fn deinit(self: @This()) void {
76-
if (builtin.os.tag == .windows) {
76+
if (builtin.os.tag == .windows or (nt_out and !nt_in)) {
7777
alloc.free(@constCast(self.str));
7878
}
7979
}
@@ -83,7 +83,9 @@ pub fn narrow(str: [:0]const os_char) struct {
8383
error.OutOfMemory => @panic("Out of memory"),
8484
} };
8585
} else {
86-
return .{ .str = str };
86+
return .{ .str = if (nt_out and !nt_in) alloc.dupeZ(u8, str) catch |e| switch (e) {
87+
error.OutOfMemory => @panic("Out of memory"),
88+
} else str };
8789
}
8890
}
8991

src/util/paths.zig

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,11 @@ fn get_full_path(path: [*:0]const os_char) [*:0]os_char {
9999
}
100100
}
101101

102-
pub fn getWorkingDir() [:0]os_char {
102+
pub fn getWorkingDir() ![:0]os_char {
103103
var buf: [std.fs.max_path_bytes]u8 = undefined;
104104
const slice = switch (builtin.os.tag) {
105-
.windows => std.fs.cwd().realpathW(std.unicode.wtf8ToWtf16LeStringLiteral("."), &buf) catch |e| std.debug.panic("Failed to determine current working directory path: {}", .{e}),
106-
else => std.fs.cwd().realpathZ(".", &buf) catch |e| std.debug.panic("Failed to determine current working directory path: {}", .{e}),
105+
.windows => try std.fs.cwd().realpathW(std.unicode.wtf8ToWtf16LeStringLiteral("."), &buf),
106+
else => try std.fs.cwd().realpathZ(".", &buf),
107107
};
108108
return toOsString(slice);
109109
}
@@ -146,25 +146,24 @@ fn splitPath(comptime Char: type, path: []const Char) struct {
146146
}
147147
}
148148

149-
pub fn getFolderNameRef(comptime Char: type, path: []const Char) []const Char {
149+
/// The returned slice is a reference into `path`.
150+
pub fn getFolderName(comptime Char: type, path: []const Char) []const Char {
150151
const parts = splitPath(Char, path);
151152
return path[0 .. @max(parts.parent, 1) - 1];
152153
}
153154

154-
pub fn getFolderName(comptime Char: type, path: []const Char) [:0]Char {
155-
return alloc.dupeZ(Char, getFolderNameRef(Char, path)) catch @panic("Out of memory");
155+
/// Caller must free the returned slice.
156+
pub fn getFolderNameZ(comptime Char: type, path: []const Char) [:0]Char {
157+
return alloc.dupeZ(Char, getFolderName(Char, path)) catch @panic("Out of memory");
156158
}
157159

158-
pub fn getFileNameRef(comptime Char: type, path: []const Char, with_ext: bool) []const Char {
160+
/// The returned slice is a reference into `path`.
161+
pub fn getFileName(comptime Char: type, path: []const Char, with_ext: bool) []const Char {
159162
const parts = splitPath(Char, path);
160163
const end = if (with_ext) path.len else parts.ext;
161164
return path[parts.parent..end];
162165
}
163166

164-
pub fn getFileName(comptime Char: type, path: []const Char, with_ext: bool) [:0]Char {
165-
return alloc.dupeZ(Char, getFileNameRef(Char, path, with_ext)) catch @panic("Out of memory");
166-
}
167-
168167
fn toOsString(buf: []const u8) [:0]os_char {
169168
if (builtin.os.tag == .windows) {
170169
return std.unicode.wtf8ToWtf16LeAllocZ(alloc, buf) catch |e| switch (e) {

0 commit comments

Comments
 (0)