Skip to content

Commit d87d782

Browse files
authored
Merge pull request #1137 from lightpanda-io/profiler
Expose v8 CpuProfiler + add fast properties for some window properties
2 parents 99f8fe1 + c381e41 commit d87d782

File tree

6 files changed

+64
-40
lines changed

6 files changed

+64
-40
lines changed

build.zig.zon

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
.fingerprint = 0xda130f3af836cea0,
66
.dependencies = .{
77
.v8 = .{
8-
.url = "https://github.com/lightpanda-io/zig-v8-fork/archive/5ce9ade6c6d7f7ab9ab4582a6b1b36fdc8e246e2.tar.gz",
9-
.hash = "v8-0.0.0-xddH6yTGAwA__kfiDozsVXL2_jnycrtDUfR8kIADQFUz",
8+
.url = "https://github.com/lightpanda-io/zig-v8-fork/archive/305bb3706716d32d59b2ffa674731556caa1002b.tar.gz",
9+
.hash = "v8-0.0.0-xddH63bVAwBSEobaUok9J0er1FqsvEujCDDVy6ItqKQ5",
1010
},
1111
//.v8 = .{ .path = "../zig-v8-fork" }
1212
},

src/browser/html/window.zig

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,6 @@ pub const Window = struct {
136136
self.onload_callback = null;
137137
}
138138

139-
pub fn get_window(self: *Window) *Window {
140-
return self;
141-
}
142-
143-
pub fn get_navigator(self: *Window) *Navigator {
144-
return &self.navigator;
145-
}
146-
147139
pub fn get_location(self: *Window) *Location {
148140
return &self.location;
149141
}
@@ -152,22 +144,6 @@ pub const Window = struct {
152144
return page.navigateFromWebAPI(url, .{ .reason = .script });
153145
}
154146

155-
pub fn get_console(self: *Window) *Console {
156-
return &self.console;
157-
}
158-
159-
pub fn get_crypto(self: *Window) *Crypto {
160-
return &self.crypto;
161-
}
162-
163-
pub fn get_self(self: *Window) *Window {
164-
return self;
165-
}
166-
167-
pub fn get_parent(self: *Window) *Window {
168-
return self;
169-
}
170-
171147
// frames return the window itself, but accessing it via a pseudo
172148
// array returns the Window object corresponding to the given frame or
173149
// iframe.
@@ -205,10 +181,6 @@ pub const Window = struct {
205181
return frames.get_length();
206182
}
207183

208-
pub fn get_top(self: *Window) *Window {
209-
return self;
210-
}
211-
212184
pub fn get_document(self: *Window) ?*parser.DocumentHTML {
213185
return self.document;
214186
}
@@ -243,14 +215,6 @@ pub const Window = struct {
243215
return &self.storage_shelf.?.bucket.session;
244216
}
245217

246-
pub fn get_performance(self: *Window) *Performance {
247-
return &self.performance;
248-
}
249-
250-
pub fn get_screen(self: *Window) *Screen {
251-
return &self.screen;
252-
}
253-
254218
pub fn get_CSS(self: *Window) *Css {
255219
return &self.css;
256220
}
@@ -463,6 +427,18 @@ pub const Window = struct {
463427
// and thus the target has already been set to the document.
464428
return self.base.redispatchEvent(evt);
465429
}
430+
431+
pub fn postAttach(self: *Window, js_this: js.This) !void {
432+
try js_this.set("top", self, .{});
433+
try js_this.set("self", self, .{});
434+
try js_this.set("parent", self, .{});
435+
try js_this.set("window", self, .{});
436+
try js_this.set("crypto", &self.crypto, .{});
437+
try js_this.set("screen", &self.screen, .{});
438+
try js_this.set("console", &self.console, .{});
439+
try js_this.set("navigator", &self.navigator, .{});
440+
try js_this.set("performance", &self.performance, .{});
441+
}
466442
};
467443

468444
const TimerCallback = struct {

src/browser/js/Context.zig

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ isolate: v8.Isolate,
2929
v8_context: v8.Context,
3030
handle_scope: ?v8.HandleScope,
3131

32+
cpu_profiler: ?v8.CpuProfiler = null,
33+
3234
// references Env.templates
3335
templates: []v8.FunctionTemplate,
3436

@@ -1815,6 +1817,11 @@ fn zigJsonToJs(isolate: v8.Isolate, v8_context: v8.Context, value: std.json.Valu
18151817
}
18161818
}
18171819

1820+
pub fn getGlobalThis(self: *Context) js.This {
1821+
const js_global = self.v8_context.getGlobal();
1822+
return .{ .obj = .{ .js_obj = js_global, .context = self } };
1823+
}
1824+
18181825
// == Misc ==
18191826
// An interface for types that want to have their jsDeinit function to be
18201827
// called when the call context ends
@@ -1843,3 +1850,26 @@ const DestructorCallback = struct {
18431850
self.destructorFn(self.ptr);
18441851
}
18451852
};
1853+
1854+
// == Profiler ==
1855+
pub fn startCpuProfiler(self: *Context) void {
1856+
if (builtin.mode != .Debug) {
1857+
// Still testing this out, don't have it properly exposed, so add this
1858+
// guard for the time being to prevent any accidental/weird prod issues.
1859+
@compileError("CPU Profiling is only available in debug builds");
1860+
}
1861+
1862+
std.debug.assert(self.cpu_profiler == null);
1863+
v8.CpuProfiler.useDetailedSourcePositionsForProfiling(self.isolate);
1864+
const cpu_profiler = v8.CpuProfiler.init(self.isolate);
1865+
const title = self.isolate.initStringUtf8("v8_cpu_profile");
1866+
cpu_profiler.startProfiling(title);
1867+
self.cpu_profiler = cpu_profiler;
1868+
}
1869+
1870+
pub fn stopCpuProfiler(self: *Context) ![]const u8 {
1871+
const title = self.isolate.initStringUtf8("v8_cpu_profile");
1872+
const profile = self.cpu_profiler.?.stopProfiling(title) orelse unreachable;
1873+
const serialized = profile.serialize(self.isolate).?;
1874+
return self.jsStringToZig(serialized, .{});
1875+
}

src/browser/js/Object.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub fn setIndex(self: Object, index: u32, value: anytype, opts: SetOpts) !void {
2727
return self.set(key, value, opts);
2828
}
2929

30-
pub fn set(self: Object, key: []const u8, value: anytype, opts: SetOpts) !void {
30+
pub fn set(self: Object, key: []const u8, value: anytype, opts: SetOpts) error{ FailedToSet, OutOfMemory }!void {
3131
const context = self.context;
3232

3333
const js_key = v8.String.initUtf8(context.isolate, key);

src/browser/page.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,7 @@ pub const Page = struct {
849849
_ = self.session.browser.transfer_arena.reset(.{ .retain_with_limit = 4 * 1024 });
850850
}
851851

852-
// extracted because this sis called from tests to set things up.
852+
// extracted because this is called from tests to set things up.
853853
pub fn setDocument(self: *Page, html_doc: *parser.DocumentHTML) !void {
854854
const doc = parser.documentHTMLToDocument(html_doc);
855855
try parser.documentSetDocumentURI(doc, self.url.raw);

src/main.zig

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,24 @@ fn run(alloc: Allocator) !void {
165165
// page
166166
const page = try session.createPage();
167167

168+
// // Comment this out to get a profile of the JS code in v8/profile.json.
169+
// // You can open this in Chrome's profiler.
170+
// // I've seen it generate invalid JSON, but I'm not sure why. It only
171+
// // happens rarely, and I manually fix the file.
172+
// page.js.startCpuProfiler();
173+
// defer {
174+
// if (page.js.stopCpuProfiler()) |profile| {
175+
// std.fs.cwd().writeFile(.{
176+
// .sub_path = "v8/profile.json",
177+
// .data = profile,
178+
// }) catch |err| {
179+
// log.err(.app, "profile write error", .{ .err = err });
180+
// };
181+
// } else |err| {
182+
// log.err(.app, "profile error", .{ .err = err });
183+
// }
184+
// }
185+
168186
_ = page.navigate(url, .{}) catch |err| switch (err) {
169187
error.UnsupportedUriScheme, error.UriMissingHost => {
170188
log.fatal(.app, "invalid fetch URL", .{ .err = err, .url = url });

0 commit comments

Comments
 (0)