Skip to content

Commit d291b56

Browse files
Fixes #19475 (#19495)
Co-authored-by: Dylan Conway <[email protected]> Co-authored-by: Dylan Conway <[email protected]>
1 parent 920b3dc commit d291b56

File tree

7 files changed

+112
-61
lines changed

7 files changed

+112
-61
lines changed

src/Watcher.zig

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,13 @@ pub const WatchEvent = struct {
164164
};
165165
}
166166

167-
pub const Op = packed struct {
167+
pub const Op = packed struct(u8) {
168168
delete: bool = false,
169169
metadata: bool = false,
170170
rename: bool = false,
171171
write: bool = false,
172172
move_to: bool = false,
173+
_padding: u3 = 0,
173174

174175
pub fn merge(before: Op, after: Op) Op {
175176
return .{
@@ -185,6 +186,7 @@ pub const WatchEvent = struct {
185186
try w.writeAll("{");
186187
var first = true;
187188
inline for (comptime std.meta.fieldNames(Op)) |name| {
189+
if (comptime std.mem.eql(u8, name, "_padding")) continue;
188190
if (@field(op, name)) {
189191
if (!first) {
190192
try w.writeAll(",");

src/bake/DevServer.zig

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,9 +1917,8 @@ fn startAsyncBundle(
19171917
errdefer heap.deinit();
19181918
const allocator = heap.allocator();
19191919
const ast_memory_allocator = try allocator.create(bun.JSAst.ASTMemoryAllocator);
1920-
ast_memory_allocator.* = .{ .allocator = allocator };
1921-
ast_memory_allocator.reset();
1922-
ast_memory_allocator.push();
1920+
var ast_scope = ast_memory_allocator.enter(allocator);
1921+
defer ast_scope.exit();
19231922

19241923
const bv2 = try BundleV2.init(
19251924
&dev.server_transpiler,

src/bake/bake.zig

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -595,14 +595,15 @@ pub const Framework = struct {
595595
bundler_options: *const BuildConfigSubset,
596596
) !void {
597597
const JSAst = bun.JSAst;
598-
const prev_alloc_stmt = JSAst.Stmt.Data.Store.memory_allocator;
599-
const prev_alloc_expr = JSAst.Expr.Data.Store.memory_allocator;
600-
defer JSAst.Stmt.Data.Store.memory_allocator = prev_alloc_stmt;
601-
defer JSAst.Expr.Data.Store.memory_allocator = prev_alloc_expr;
598+
602599
var ast_memory_allocator: JSAst.ASTMemoryAllocator = undefined;
603600
ast_memory_allocator.initWithoutStack(arena);
604-
JSAst.Stmt.Data.Store.memory_allocator = &ast_memory_allocator;
605-
JSAst.Expr.Data.Store.memory_allocator = &ast_memory_allocator;
601+
var ast_scope = JSAst.ASTMemoryAllocator.Scope{
602+
.previous = JSAst.Stmt.Data.Store.memory_allocator,
603+
.current = &ast_memory_allocator,
604+
};
605+
ast_scope.enter();
606+
defer ast_scope.exit();
606607

607608
out.* = try bun.Transpiler.init(
608609
arena,

src/bun.js/ModuleLoader.zig

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,11 @@ pub fn transpileSourceCode(
845845

846846
switch (loader) {
847847
.js, .jsx, .ts, .tsx, .json, .jsonc, .toml, .text => {
848+
// Ensure that if there was an ASTMemoryAllocator in use, it's not used anymore.
849+
var ast_scope = js_ast.ASTMemoryAllocator.Scope{};
850+
ast_scope.enter();
851+
defer ast_scope.exit();
852+
848853
jsc_vm.transpiled_count += 1;
849854
jsc_vm.transpiler.resetStore();
850855
const hash = bun.Watcher.getHash(path.text);
@@ -2320,9 +2325,8 @@ pub const RuntimeTranspilerStore = struct {
23202325
};
23212326
}
23222327

2323-
ast_memory_store.?.allocator = allocator;
2324-
ast_memory_store.?.reset();
2325-
ast_memory_store.?.push();
2328+
var ast_scope = ast_memory_store.?.enter(allocator);
2329+
defer ast_scope.exit();
23262330

23272331
const path = this.path;
23282332
const specifier = this.path.text;

src/bun.js/api/JSTranspiler.zig

Lines changed: 22 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -117,30 +117,13 @@ pub const TransformTask = struct {
117117
const name = this.loader.stdinName();
118118
const source = logger.Source.initPathString(name, this.input_code.slice());
119119

120-
const prev_memory_allocators = .{ JSAst.Stmt.Data.Store.memory_allocator, JSAst.Expr.Data.Store.memory_allocator };
121-
defer {
122-
JSAst.Stmt.Data.Store.memory_allocator = prev_memory_allocators[0];
123-
JSAst.Expr.Data.Store.memory_allocator = prev_memory_allocators[1];
124-
}
125-
126120
var arena = Mimalloc.Arena.init() catch unreachable;
121+
defer arena.deinit();
127122

128123
const allocator = arena.allocator();
129-
130124
var ast_memory_allocator = allocator.create(JSAst.ASTMemoryAllocator) catch bun.outOfMemory();
131-
ast_memory_allocator.* = .{
132-
.allocator = allocator,
133-
};
134-
ast_memory_allocator.reset();
135-
136-
JSAst.Stmt.Data.Store.memory_allocator = ast_memory_allocator;
137-
JSAst.Expr.Data.Store.memory_allocator = ast_memory_allocator;
138-
139-
defer {
140-
JSAst.Stmt.Data.Store.reset();
141-
JSAst.Expr.Data.Store.reset();
142-
arena.deinit();
143-
}
125+
var ast_scope = ast_memory_allocator.enter(allocator);
126+
defer ast_scope.exit();
144127

145128
this.transpiler.setAllocator(allocator);
146129
this.transpiler.setLog(&this.log);
@@ -847,7 +830,8 @@ pub fn scan(this: *JSTranspiler, globalThis: *JSC.JSGlobalObject, callframe: *JS
847830

848831
var arena = Mimalloc.Arena.init() catch unreachable;
849832
const prev_allocator = this.transpiler.allocator;
850-
this.transpiler.setAllocator(arena.allocator());
833+
const allocator = arena.allocator();
834+
this.transpiler.setAllocator(allocator);
851835
var log = logger.Log.init(arena.backingAllocator());
852836
defer log.deinit();
853837
this.transpiler.setLog(&log);
@@ -856,13 +840,11 @@ pub fn scan(this: *JSTranspiler, globalThis: *JSC.JSGlobalObject, callframe: *JS
856840
this.transpiler.setAllocator(prev_allocator);
857841
arena.deinit();
858842
}
843+
var ast_memory_allocator = allocator.create(JSAst.ASTMemoryAllocator) catch bun.outOfMemory();
844+
var ast_scope = ast_memory_allocator.enter(allocator);
845+
defer ast_scope.exit();
859846

860-
defer {
861-
JSAst.Stmt.Data.Store.reset();
862-
JSAst.Expr.Data.Store.reset();
863-
}
864-
865-
var parse_result = getParseResult(this, arena.allocator(), code, loader, Transpiler.MacroJSValueType.zero) orelse {
847+
var parse_result = getParseResult(this, allocator, code, loader, Transpiler.MacroJSValueType.zero) orelse {
866848
if ((this.transpiler.log.warnings + this.transpiler.log.errors) > 0) {
867849
return globalThis.throwValue(try this.transpiler.log.toJS(globalThis, globalThis.allocator(), "Parse error"));
868850
}
@@ -991,15 +973,14 @@ pub fn transformSync(
991973
}
992974
}
993975

994-
JSAst.Stmt.Data.Store.reset();
995-
JSAst.Expr.Data.Store.reset();
996-
defer {
997-
JSAst.Stmt.Data.Store.reset();
998-
JSAst.Expr.Data.Store.reset();
999-
}
976+
const allocator = arena.allocator();
977+
978+
var ast_memory_allocator = allocator.create(JSAst.ASTMemoryAllocator) catch bun.outOfMemory();
979+
var ast_scope = ast_memory_allocator.enter(allocator);
980+
defer ast_scope.exit();
1000981

1001982
const prev_bundler = this.transpiler;
1002-
this.transpiler.setAllocator(arena.allocator());
983+
this.transpiler.setAllocator(allocator);
1003984
this.transpiler.macro_context = null;
1004985
var log = logger.Log.init(arena.backingAllocator());
1005986
log.level = this.transpiler_options.log.level;
@@ -1010,7 +991,7 @@ pub fn transformSync(
1010991
}
1011992
const parse_result = getParseResult(
1012993
this,
1013-
arena.allocator(),
994+
allocator,
1014995
code,
1015996
loader,
1016997
js_ctx_value,
@@ -1132,7 +1113,12 @@ pub fn scanImports(this: *JSTranspiler, globalThis: *JSC.JSGlobalObject, callfra
11321113

11331114
var arena = Mimalloc.Arena.init() catch unreachable;
11341115
const prev_allocator = this.transpiler.allocator;
1135-
this.transpiler.setAllocator(arena.allocator());
1116+
const allocator = arena.allocator();
1117+
var ast_memory_allocator = allocator.create(JSAst.ASTMemoryAllocator) catch bun.outOfMemory();
1118+
var ast_scope = ast_memory_allocator.enter(allocator);
1119+
defer ast_scope.exit();
1120+
1121+
this.transpiler.setAllocator(allocator);
11361122
var log = logger.Log.init(arena.backingAllocator());
11371123
defer log.deinit();
11381124
this.transpiler.setLog(&log);
@@ -1155,14 +1141,6 @@ pub fn scanImports(this: *JSTranspiler, globalThis: *JSC.JSGlobalObject, callfra
11551141
}
11561142
opts.macro_context = &this.transpiler.macro_context.?;
11571143

1158-
JSAst.Stmt.Data.Store.reset();
1159-
JSAst.Expr.Data.Store.reset();
1160-
1161-
defer {
1162-
JSAst.Stmt.Data.Store.reset();
1163-
JSAst.Expr.Data.Store.reset();
1164-
}
1165-
11661144
transpiler.resolver.caches.js.scan(
11671145
transpiler.allocator,
11681146
&this.scan_pass_result,

src/js_ast.zig

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ pub fn NewStore(comptime types: []const type, comptime count: usize) type {
119119
log("deinit", .{});
120120
var it = store.firstBlock().next; // do not free `store.head`
121121
while (it) |next| {
122-
if (Environment.isDebug)
122+
if (Environment.isDebug or Environment.enable_asan)
123123
@memset(next.buffer, undefined);
124124
it = next.next;
125125
backing_allocator.destroy(next);
@@ -133,7 +133,7 @@ pub fn NewStore(comptime types: []const type, comptime count: usize) type {
133133
pub fn reset(store: *Store) void {
134134
log("reset", .{});
135135

136-
if (Environment.isDebug) {
136+
if (Environment.isDebug or Environment.enable_asan) {
137137
var it: ?*Block = store.firstBlock();
138138
while (it) |next| : (it = next.next) {
139139
next.bytes_used = undefined;
@@ -3214,6 +3214,18 @@ pub const Stmt = struct {
32143214
instance = StoreType.init();
32153215
}
32163216

3217+
/// create || reset
3218+
pub fn begin() void {
3219+
if (memory_allocator != null) return;
3220+
if (instance == null) {
3221+
create();
3222+
return;
3223+
}
3224+
3225+
if (!disable_reset)
3226+
instance.?.reset();
3227+
}
3228+
32173229
pub fn reset() void {
32183230
if (disable_reset or memory_allocator != null) return;
32193231
instance.?.reset();
@@ -6322,12 +6334,24 @@ pub const Expr = struct {
63226334
}
63236335

63246336
pub inline fn assert() void {
6325-
if (comptime Environment.allow_assert) {
6337+
if (comptime Environment.isDebug or Environment.enable_asan) {
63266338
if (instance == null and memory_allocator == null)
63276339
bun.unreachablePanic("Store must be init'd", .{});
63286340
}
63296341
}
63306342

6343+
/// create || reset
6344+
pub fn begin() void {
6345+
if (memory_allocator != null) return;
6346+
if (instance == null) {
6347+
create();
6348+
return;
6349+
}
6350+
6351+
if (!disable_reset)
6352+
instance.?.reset();
6353+
}
6354+
63316355
pub fn append(comptime T: type, value: T) *T {
63326356
if (memory_allocator) |allocator| {
63336357
return allocator.append(T, value);
@@ -8554,6 +8578,48 @@ pub const ASTMemoryAllocator = struct {
85548578
allocator: std.mem.Allocator,
85558579
previous: ?*ASTMemoryAllocator = null,
85568580

8581+
pub fn enter(this: *ASTMemoryAllocator, allocator: std.mem.Allocator) ASTMemoryAllocator.Scope {
8582+
this.allocator = allocator;
8583+
this.stack_allocator = SFA{
8584+
.buffer = undefined,
8585+
.fallback_allocator = allocator,
8586+
.fixed_buffer_allocator = undefined,
8587+
};
8588+
this.bump_allocator = this.stack_allocator.get();
8589+
this.previous = null;
8590+
var ast_scope = ASTMemoryAllocator.Scope{
8591+
.current = this,
8592+
.previous = Stmt.Data.Store.memory_allocator,
8593+
};
8594+
ast_scope.enter();
8595+
return ast_scope;
8596+
}
8597+
pub const Scope = struct {
8598+
current: ?*ASTMemoryAllocator = null,
8599+
previous: ?*ASTMemoryAllocator = null,
8600+
8601+
pub fn enter(this: *@This()) void {
8602+
bun.debugAssert(Expr.Data.Store.memory_allocator == Stmt.Data.Store.memory_allocator);
8603+
8604+
this.previous = Expr.Data.Store.memory_allocator;
8605+
8606+
const current = this.current;
8607+
8608+
Expr.Data.Store.memory_allocator = current;
8609+
Stmt.Data.Store.memory_allocator = current;
8610+
8611+
if (current == null) {
8612+
Stmt.Data.Store.begin();
8613+
Expr.Data.Store.begin();
8614+
}
8615+
}
8616+
8617+
pub fn exit(this: *const @This()) void {
8618+
Expr.Data.Store.memory_allocator = this.previous;
8619+
Stmt.Data.Store.memory_allocator = this.previous;
8620+
}
8621+
};
8622+
85578623
pub fn reset(this: *ASTMemoryAllocator) void {
85588624
this.stack_allocator = SFA{
85598625
.buffer = undefined,

src/watcher/INotifyWatcher.zig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,8 @@ pub fn watchLoopCycle(this: *bun.Watcher) bun.JSC.Maybe(void) {
292292
this.mutex.lock();
293293
defer this.mutex.unlock();
294294
if (this.running) {
295-
this.onFileUpdate(this.ctx, all_events[0 .. last_event_index + 1], this.changed_filepaths[0 .. name_off + 1], this.watchlist);
295+
// all_events.len == 0 is checked above, so last_event_index + 1 is safe
296+
this.onFileUpdate(this.ctx, all_events[0 .. last_event_index + 1], this.changed_filepaths[0..name_off], this.watchlist);
296297
} else {
297298
break;
298299
}

0 commit comments

Comments
 (0)