diff options
author | 2021-05-29 17:40:00 -0700 | |
---|---|---|
committer | 2021-05-29 17:40:00 -0700 | |
commit | b5612b303b934b668c35c1a70d64f498b7c62856 (patch) | |
tree | 422c9f2d9f3239036296335f0593a9e78434cb7a /src | |
parent | 3436ee9deddf21594a0b4fb3640a7596ea078093 (diff) | |
download | bun-b5612b303b934b668c35c1a70d64f498b7c62856.tar.gz bun-b5612b303b934b668c35c1a70d64f498b7c62856.tar.zst bun-b5612b303b934b668c35c1a70d64f498b7c62856.zip |
WIP
Former-commit-id: 55dcde581df46b425733508c3923e073ccdf880f
Diffstat (limited to 'src')
-rw-r--r-- | src/allocators.zig | 381 | ||||
-rw-r--r-- | src/bundler.zig | 63 | ||||
-rw-r--r-- | src/cli.zig | 5 | ||||
-rw-r--r-- | src/hash_map.zig | 2 | ||||
-rw-r--r-- | src/js_ast.zig | 679 | ||||
-rw-r--r-- | src/js_lexer.zig | 2 | ||||
-rw-r--r-- | src/js_parser/js_parser.zig | 17 | ||||
-rw-r--r-- | src/thread_safe_hash_map.zig | 2 |
8 files changed, 498 insertions, 653 deletions
diff --git a/src/allocators.zig b/src/allocators.zig index 8ebde9150..c9371426a 100644 --- a/src/allocators.zig +++ b/src/allocators.zig @@ -1,5 +1,8 @@ const std = @import("std"); +const hash_map = @import("hash_map.zig"); + +const HashMapUnmanaged = hash_map.HashMapUnmanaged; const Wyhash = std.hash.Wyhash; const FixedBufferAllocator = std.heap.FixedBufferAllocator; @@ -70,7 +73,7 @@ pub const IndexType = packed struct { }; const HashKeyType = u64; -const IndexMap = std.HashMapUnmanaged(HashKeyType, IndexType, hash_hashFn, hash_eqlFn, 80); +const IndexMap = HashMapUnmanaged(HashKeyType, IndexType, hash_hashFn, hash_eqlFn, 80); pub const Result = struct { hash: HashKeyType, index: IndexType, @@ -88,7 +91,7 @@ pub const Result = struct { return if (r.isOverflowing(count)) @intCast(IndexType, r.index - max_index) else r.index; } }; -const Seed = 999; +const Seed = 0; pub const NotFound = IndexType{ .index = std.math.maxInt(u31), @@ -233,246 +236,227 @@ pub fn BSSList(comptime ValueType: type, comptime count: anytype) type { } }; } -pub fn BSSStringList(comptime count: usize, comptime item_length: usize) type { - const max_index = count - 1; - const ValueType = []const u8; - return struct { - pub var slice_buf: [count][]const u8 = undefined; - pub var slice_buf_used: u16 = 0; - pub var backing_buf: [count * item_length]u8 = undefined; - pub var backing_buf_used: u64 = undefined; - const Allocator = std.mem.Allocator; - const Self = @This(); - pub const ListIndex = packed struct { - index: u31, - is_overflowing: bool = false, - }; - overflow_list: std.ArrayListUnmanaged(ValueType), - allocator: *Allocator, +// Like an ArrayList except: +// - It only grows +// - Pointer never invalidates +pub const ByteBuffer = struct { + allocator: *std.mem.Allocator, + ptr: [*]u8, + len: usize, - pub var instance: Self = undefined; + items: []u8, - pub fn init(allocator: *std.mem.Allocator) *Self { - instance = Self{ - .allocator = allocator, - .overflow_list = std.ArrayListUnmanaged(ValueType){}, - }; + pub fn init(allocator: *std.mem.Allocator, comptime min_length: usize) !ByteBuffer { + var items = if (min_length > 0) try allocator.alloc(u8, min_length) else &([_]u8{}); - return &instance; + return ByteBuffer{ .allocator = allocator, .items = items, .ptr = undefined, .len = min_length }; + } + + pub fn growIfNeeded(this: *ByteBuffer, min_length: usize) !void { + const len = std.math.ceilPowerOfTwo(usize, this.items.len + min_length) catch unreachable; + if (this.len >= len) { + return; } - pub fn isOverflowing() bool { - return slice_buf_used >= @as(u16, count); + if (this.len == 0) { + const items = try this.allocator.alloc(u8, len); + this.ptr = items.ptr; + this.len = items.len; + } else { + const items = try this.allocator.realloc(this.ptr[0..this.len], len); + this.ptr = items.ptr; + this.len = items.len; } - pub fn at(self: *const Self, index: IndexType) ?ValueType { - if (index.index == NotFound.index or index.index == Unassigned.index) return null; + this.items = this.ptr[0 .. this.items.len + min_length]; + } - if (index.is_overflowing) { - return &self.overflow_list.items[index.index]; - } else { - return &slice_buf[index.index]; - } - } + pub fn reset(this: *ByteBuffer) void { + this.items = this.items[0..0]; + } - pub fn exists(self: *Self, value: ValueType) bool { - return isSliceInBuffer(value, slice_buf); - } + pub fn slice(this: *ByteBuffer, len: usize) ![]u8 { + try this.growIfNeeded(len); - pub fn editableSlice(slice: []const u8) []u8 { - return constStrToU8(slice); + return this.items[this.items.len - len ..]; + } + + pub fn append(this: *ByteBuffer, items: anytype) ![]u8 { + var writable = try this.slice(items.len); + @memcpy(writable.ptr, items.ptr, items.len); + return writable; + } +}; + +// Like an ArrayList except: +// - It only grows +// - Pointer never invalidates + +pub fn OverflowList(comptime ValueType: type) type { + return struct { + const Self = @This(); + allocator: *std.mem.Allocator, + ptr: [*]ValueType, + len: usize, + + items: []ValueType, + + pub fn init(allocator: *std.mem.Allocator, comptime min_length: usize) !Self { + var items = if (min_length > 0) try allocator.alloc(ValueType, min_length) else &([_]ValueType{}); + + return Self{ .allocator = allocator, .items = items, .ptr = undefined, .len = min_length }; } - pub fn append(self: *Self, _value: anytype) ![]const u8 { - var value = _value; - if (value.len + backing_buf_used < backing_buf.len - 1) { - const start = backing_buf_used; - backing_buf_used += value.len; - std.mem.copy(u8, backing_buf[start..backing_buf_used], _value); - value = backing_buf[start..backing_buf_used]; - } else { - value = try self.allocator.dupe(u8, _value); + pub fn growIfNeeded(this: *Self, min_length: usize) !void { + const len = std.math.ceilPowerOfTwo(usize, this.items.len + min_length) catch unreachable; + if (this.len >= len) { + return; } - var result = ListIndex{ .index = std.math.maxInt(u31), .is_overflowing = slice_buf_used > max_index }; - - if (result.is_overflowing) { - result.index = @intCast(u31, self.overflow_list.items.len); + if (this.len == 0) { + const items = try this.allocator.alloc(ValueType, len); + this.ptr = items.ptr; + this.len = items.len; } else { - result.index = slice_buf_used; - slice_buf_used += 1; - if (slice_buf_used >= max_index) { - self.overflow_list = try @TypeOf(self.overflow_list).initCapacity(self.allocator, count); - } + const items = try this.allocator.realloc(this.ptr[0..this.len], len); + this.ptr = items.ptr; + this.len = items.len; } - if (result.is_overflowing) { - if (self.overflow_list.items.len == result.index) { - const real_index = self.overflow_list.items.len; - try self.overflow_list.append(self.allocator, value); - } else { - self.overflow_list.items[result.index] = value; - } + this.items = this.ptr[0 .. this.items.len + min_length]; + } - return self.overflow_list.items[result.index]; - } else { - slice_buf[result.index] = value; + pub fn reset(this: *Self) void { + this.items = this.items[0..0]; + } - return slice_buf[result.index]; - } + pub fn slice(this: *Self, len: usize) ![]ValueType { + try this.growIfNeeded(len); + + return this.items[this.items.len - len ..]; } - pub fn remove(self: *Self, index: ListIndex) void { - @compileError("Not implemented yet."); - // switch (index) { - // Unassigned.index => { - // self.index.remove(_key); - // }, - // NotFound.index => { - // self.index.remove(_key); - // }, - // 0...max_index => { - // if (hasDeinit(ValueType)) { - // slice_buf[index].deinit(); - // } - // slice_buf[index] = undefined; - // }, - // else => { - // const i = index - count; - // if (hasDeinit(ValueType)) { - // self.overflow_list.items[i].deinit(); - // } - // self.overflow_list.items[index - count] = undefined; - // }, - // } + pub fn append(this: *Self, value: ValueType) !*ValueType { + try this.growIfNeeded(1); + const index = this.items.len - 1; + this.items[index] = value; + return &this.items[index]; + } - // return index; + pub fn appendGetIndex(this: *Self, value: ValueType) !usize { + try this.growIfNeeded(1); + const index = this.items.len - 1; + this.items[index] = value; + return index; } }; } -pub fn TBSSStringList(comptime count: usize, comptime item_length: usize) type { +// Growable array of variable-length strings +// Copies the strings +pub const StringList = struct { + const DataType = [][]u8; + buffer: ByteBuffer, + ptr: [*][]u8, + len: usize = 0, + allocator: *std.mem.Allocator, + + items: DataType, + + pub fn init(allocator: *std.mem.Allocator) StringList { + return StringList{ + .ptr = undefined, + .allocator = allocator, + .len = 0, + .buffer = ByteBuffer.init(allocator, 0) catch unreachable, + .items = std.mem.zeroes(DataType), + }; + } + + pub fn reset(self: *StringList) void { + self.buffer.reset(); + self.items = self.ptr[0..0]; + } + + pub fn appendCopy(self: *StringList, str: anytype, comptime copy: bool) ![]const u8 { + const index = try self.appendCopyIndex(str, copy); + return self.items[index]; + } + + pub fn appendCopyIndex(self: *StringList, str: anytype, comptime copy: bool) !usize { + if (self.len == 0) { + var items = try self.allocator.alloc([]u8, 8); + self.ptr = items.ptr; + self.len = items.len; + self.items = items[0..1]; + } else if (self.items.len >= self.len) { + const end = self.len + 1; + const len = std.math.ceilPowerOfTwo(usize, self.len + 1) catch unreachable; + var items = try self.allocator.realloc(self.ptr[0..self.len], len); + self.ptr = items.ptr; + self.len = items.len; + self.items = self.ptr[0..end]; + } + + const index = self.items.len - 1; + self.items[index] = if (copy) try self.buffer.append(str) else str; + return index; + } + + pub fn append(self: *StringList, str: anytype) ![]const u8 { + return try self.appendCopy(str, true); + } +}; + +pub fn BSSStringList(comptime count: usize, comptime item_length: usize) type { const max_index = count - 1; const ValueType = []const u8; return struct { + pub var backing_buf: [count * item_length]u8 = undefined; + pub var backing_buf_used: u64 = undefined; + const Allocator = std.mem.Allocator; const Self = @This(); - - pub threadlocal var slice_buf: [count][]const u8 = undefined; - pub threadlocal var slice_buf_used: u16 = 0; - pub threadlocal var backing_buf: [count * item_length]u8 = undefined; - pub threadlocal var backing_buf_used: u64 = undefined; - pub threadlocal var instance: Self = undefined; pub const ListIndex = packed struct { index: u31, is_overflowing: bool = false, }; - overflow_list: std.ArrayListUnmanaged(ValueType), + list: StringList, allocator: *Allocator, + pub var instance: Self = undefined; + pub fn init(allocator: *std.mem.Allocator) *Self { instance = Self{ .allocator = allocator, - .overflow_list = std.ArrayListUnmanaged(ValueType){}, + .list = StringList.init(allocator), }; return &instance; } - pub fn isOverflowing() bool { - return slice_buf_used >= @as(u16, count); - } - - pub fn at(self: *const Self, index: IndexType) ?ValueType { - if (index.index == NotFound.index or index.index == Unassigned.index) return null; - - if (index.is_overflowing) { - return &self.overflow_list.items[index.index]; - } else { - return &slice_buf[index.index]; - } - } - - pub fn exists(self: *Self, value: ValueType) bool { - return isSliceInBuffer(value, slice_buf); - } - pub fn editableSlice(slice: []const u8) []u8 { return constStrToU8(slice); } - pub fn append(self: *Self, _value: anytype) ![]const u8 { - var value = _value; + pub fn append(self: *Self, value: anytype) ![]const u8 { if (value.len + backing_buf_used < backing_buf.len - 1) { const start = backing_buf_used; backing_buf_used += value.len; - std.mem.copy(u8, backing_buf[start..backing_buf_used], _value); - value = backing_buf[start..backing_buf_used]; - } else { - value = try self.allocator.dupe(u8, _value); + std.mem.copy(u8, backing_buf[start..backing_buf_used], value); + return try self.list.appendCopy(backing_buf[start..backing_buf_used], false); } - var result = ListIndex{ .index = std.math.maxInt(u31), .is_overflowing = slice_buf_used > max_index }; - - if (result.is_overflowing) { - result.index = @intCast(u31, self.overflow_list.items.len); - } else { - result.index = slice_buf_used; - slice_buf_used += 1; - if (slice_buf_used >= max_index) { - self.overflow_list = try @TypeOf(self.overflow_list).initCapacity(self.allocator, count); - } - } - - if (result.is_overflowing) { - if (self.overflow_list.items.len == result.index) { - const real_index = self.overflow_list.items.len; - try self.overflow_list.append(self.allocator, value); - } else { - self.overflow_list.items[result.index] = value; - } - - return self.overflow_list.items[result.index]; - } else { - slice_buf[result.index] = value; - - return slice_buf[result.index]; - } - } - - pub fn remove(self: *Self, index: ListIndex) void { - @compileError("Not implemented yet."); - // switch (index) { - // Unassigned.index => { - // self.index.remove(_key); - // }, - // NotFound.index => { - // self.index.remove(_key); - // }, - // 0...max_index => { - // if (hasDeinit(ValueType)) { - // slice_buf[index].deinit(); - // } - // slice_buf[index] = undefined; - // }, - // else => { - // const i = index - count; - // if (hasDeinit(ValueType)) { - // self.overflow_list.items[i].deinit(); - // } - // self.overflow_list.items[index - count] = undefined; - // }, - // } - - // return index; + return try self.list.appendCopy(value, true); } }; } pub fn BSSMap(comptime ValueType: type, comptime count: anytype, store_keys: bool, estimated_key_length: usize) type { const max_index = count - 1; + const OverflowListType = OverflowList(ValueType); const BSSMapType = struct { pub var backing_buf: [count]ValueType = undefined; pub var backing_buf_used: u16 = 0; @@ -480,7 +464,7 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, store_keys: boo const Self = @This(); index: IndexMap, - overflow_list: std.ArrayListUnmanaged(ValueType), + overflow_list: OverflowListType, allocator: *Allocator, pub var instance: Self = undefined; @@ -489,7 +473,7 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, store_keys: boo instance = Self{ .index = IndexMap{}, .allocator = allocator, - .overflow_list = std.ArrayListUnmanaged(ValueType){}, + .overflow_list = OverflowListType.init(allocator, 0) catch unreachable, }; return &instance; @@ -501,7 +485,7 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, store_keys: boo pub fn getOrPut(self: *Self, key: []const u8) !Result { const _key = Wyhash.hash(Seed, key); - var index = try self.index.getOrPut(self.allocator, _key); + var index = try self.index.getOrPutWithHash(self.allocator, _key, _key); if (index.found_existing) { return Result{ @@ -525,12 +509,12 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, store_keys: boo pub fn get(self: *const Self, key: []const u8) ?*ValueType { const _key = Wyhash.hash(Seed, key); - const index = self.index.get(_key) orelse return null; + const index = self.index.getWithHash(_key, _key) orelse return null; return self.atIndex(index); } pub fn markNotFound(self: *Self, result: Result) void { - self.index.put(self.allocator, result.hash, NotFound) catch unreachable; + self.index.putWithHash(self.allocator, result.hash, result.hash, NotFound) catch unreachable; } pub fn atIndex(self: *const Self, index: IndexType) ?*ValueType { @@ -551,23 +535,13 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, store_keys: boo } else { result.index.index = backing_buf_used; backing_buf_used += 1; - if (backing_buf_used >= max_index) { - self.overflow_list = try @TypeOf(self.overflow_list).initCapacity(self.allocator, count); - } } } - try self.index.put(self.allocator, result.hash, result.index); + try self.index.putWithHash(self.allocator, result.hash, result.hash, result.index); if (result.index.is_overflow) { - if (self.overflow_list.items.len == result.index.index) { - const real_index = self.overflow_list.items.len; - try self.overflow_list.append(self.allocator, value); - } else { - self.overflow_list.items[result.index.index] = value; - } - - return &self.overflow_list.items[result.index.index]; + return try self.overflow_list.append(value); } else { backing_buf[result.index.index] = value; @@ -577,7 +551,7 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, store_keys: boo pub fn remove(self: *Self, key: string) IndexType { const _key = Wyhash.hash(Seed, key); - const index = self.index.get(_key) orelse return; + const index = self.index.getWithHash(_key, _key) orelse return; switch (index) { Unassigned.index => { self.index.remove(_key); @@ -614,13 +588,13 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, store_keys: boo var key_list_buffer: [count * estimated_key_length]u8 = undefined; var key_list_buffer_used: usize = 0; var key_list_slices: [count][]u8 = undefined; - var key_list_overflow: std.ArrayListUnmanaged([]u8) = undefined; + var key_list_overflow: StringList = undefined; pub fn init(allocator: *std.mem.Allocator) *Self { instance = Self{ .map = BSSMapType.init(allocator), }; - + key_list_overflow = key_list_overflow.init(allocator); return &instance; } @@ -677,9 +651,10 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, store_keys: boo const start = key_list_buffer_used; key_list_buffer_used += key.len; slice = key_list_buffer[start..key_list_buffer_used]; - std.mem.copy(u8, slice, key); + @memcpy(slice.ptr, key.ptr, key.len); } else { - slice = try self.map.allocator.dupe(u8, key); + result.index = try key_list_overflow.appendCopyIndex(key, true); + return; } if (!result.index.is_overflow) { @@ -692,7 +667,7 @@ pub fn BSSMap(comptime ValueType: type, comptime count: anytype, store_keys: boo } key_list_overflow.items[result.index.index] = slice; } else { - try key_list_overflow.append(self.map.allocator, slice); + try key_list_overflow.appendCopy(self.map.allocator, slice, false); } } } diff --git a/src/bundler.zig b/src/bundler.zig index 42b515678..aa7bfaec9 100644 --- a/src/bundler.zig +++ b/src/bundler.zig @@ -80,6 +80,9 @@ pub const Bundler = struct { log: *logger.Log, opts: Api.TransformOptions, ) !Bundler { + js_ast.Expr.Data.Store.create(allocator); + js_ast.Stmt.Data.Store.create(allocator); + var fs = try Fs.FileSystem.init1(allocator, opts.absolute_working_dir, opts.serve orelse false); const bundle_options = try options.BundleOptions.fromApi(allocator, fs, log, opts); @@ -168,35 +171,36 @@ pub const Bundler = struct { bundler.needs_runtime = true; } + import_record.path = try bundler.generateImportPath(source_dir, resolve_result.path_pair.primary.text); + // lazy means: // Run the resolver // Don't parse/print automatically. if (bundler.options.resolve_mode != .lazy) { - try bundler.enqueueResolveResult(&resolve_result); + try bundler.enqueueResolveResult(resolve_result); } - - import_record.path = try bundler.generateImportPath(source_dir, resolve_result.path_pair.primary.text); } - pub fn resolveResultHashKey(bundler: *Bundler, resolve_result: *Resolver.Resolver.Result) string { - var hash_key = resolve_result.path_pair.primary.text; + pub fn resolveResultHashKey(bundler: *Bundler, path: string) string { + var hash_key = path; // Shorter hash key is faster to hash - if (strings.startsWith(resolve_result.path_pair.primary.text, bundler.fs.top_level_dir)) { - hash_key = resolve_result.path_pair.primary.text[bundler.fs.top_level_dir.len..]; + if (strings.startsWith(path, bundler.fs.top_level_dir)) { + hash_key = path[bundler.fs.top_level_dir.len..]; } return hash_key; } - pub fn enqueueResolveResult(bundler: *Bundler, resolve_result: *Resolver.Resolver.Result) !void { - const hash_key = bundler.resolveResultHashKey(resolve_result); + pub fn enqueueResolveResult(bundler: *Bundler, resolve_result: Resolver.Resolver.Result) !void { + const hash_key = bundler.resolveResultHashKey(resolve_result.path_pair.primary.text); const get_or_put_entry = try bundler.resolve_results.backing.getOrPut(hash_key); + get_or_put_entry.entry.value = resolve_result; + if (!get_or_put_entry.found_existing) { - get_or_put_entry.entry.value = resolve_result.*; - try bundler.resolve_queue.writeItem(resolve_result.*); + try bundler.resolve_queue.writeItem(resolve_result); } } @@ -510,22 +514,17 @@ pub const Bundler = struct { }; } - pub fn bundle( - allocator: *std.mem.Allocator, - log: *logger.Log, - opts: Api.TransformOptions, - ) !options.TransformResult { - var bundler = try Bundler.init(allocator, log, opts); - + pub fn run(bundler: *Bundler) !options.TransformResult { + const allocator = bundler.allocator; // 100.00 µs std.fifo.LinearFifo(resolver.resolver.Result,std.fifo.LinearFifoBufferType { .Dynamic = {}}).writeItemAssumeCapacity - if (bundler.options.resolve_mode != .lazy) { - try bundler.resolve_queue.ensureUnusedCapacity(1000); - } + // if (bundler.options.resolve_mode != .lazy) { + // try bundler.resolve_queue.ensureUnusedCapacity(1000); + // } var entry_points = try allocator.alloc(Resolver.Resolver.Result, bundler.options.entry_points.len); if (isDebug) { - log.level = .verbose; + bundler.log.level = .verbose; bundler.resolver.debug_logs = try Resolver.Resolver.DebugLogs.init(allocator); } @@ -596,6 +595,10 @@ pub const Bundler = struct { bundler.resolve_queue.writeItem(result) catch unreachable; } + // The resolver may use the AST store when parsing package.json / tsconfig.json + js_ast.Stmt.Data.Store.reset(); + js_ast.Expr.Data.Store.reset(); + switch (bundler.options.resolve_mode) { .lazy, .dev, .bundle => { while (bundler.resolve_queue.readItem()) |item| { @@ -628,7 +631,21 @@ pub const Bundler = struct { ); } - return try options.TransformResult.init(try allocator.dupe(u8, bundler.result.outbase), bundler.output_files.toOwnedSlice(), log, allocator); + return try options.TransformResult.init( + try allocator.dupe(u8, bundler.result.outbase), + bundler.output_files.toOwnedSlice(), + bundler.log, + bundler.allocator, + ); + } + + pub fn bundle( + allocator: *std.mem.Allocator, + log: *logger.Log, + opts: Api.TransformOptions, + ) !options.TransformResult { + var bundler = try Bundler.init(allocator, log, opts); + return try bundler.run(); } }; diff --git a/src/cli.zig b/src/cli.zig index 6e44d5e08..f20529875 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -392,8 +392,9 @@ pub const Cli = struct { } if (isDebug) { - Output.println("Expr count: {d}", .{js_ast.Expr.icount}); - Output.println("Stmt count: {d}", .{js_ast.Stmt.icount}); + Output.println("Expr count: {d}", .{js_ast.Expr.icount}); + Output.println("Stmt count: {d}", .{js_ast.Stmt.icount}); + Output.println("Binding count: {d}", .{js_ast.Binding.binding_count}); Output.println("File Descriptors: {d} / {d}", .{ fs.FileSystem.max_fd, diff --git a/src/hash_map.zig b/src/hash_map.zig index 69c56997c..7153795f2 100644 --- a/src/hash_map.zig +++ b/src/hash_map.zig @@ -688,7 +688,7 @@ pub fn HashMapUnmanaged( } pub fn getOrPutAssumeCapacity(self: *Self, key: K) GetOrPutResult { - return @call(.{ .modifier = .always_inline }, Self.getOrPutAssumeCapacityWithHash, .{ self, key, hashFn(key) }); + return self.getOrPutAssumeCapacityWithHash(key, hashFn(key)); } pub fn getOrPutAssumeCapacityWithHash(self: *Self, key: K, hash: u64) GetOrPutResult { diff --git a/src/js_ast.zig b/src/js_ast.zig index 5b3f1a7c1..701abd474 100644 --- a/src/js_ast.zig +++ b/src/js_ast.zig @@ -12,6 +12,132 @@ const _hash_map = @import("hash_map.zig"); const StringHashMap = _hash_map.StringHashMap; const AutoHashMap = _hash_map.AutoHashMap; +pub fn NewBaseStore(comptime Union: anytype, count: usize) type { + var max_size: usize = 0; + var max_align: usize = 1; + for (Union) |kind| { + max_size = std.math.max(@sizeOf(kind), max_size); + max_align = if (@sizeOf(kind) == 0) max_align else std.math.max(@alignOf(kind), max_align); + } + + max_size = std.mem.alignForward(max_size, max_align); + const element_size = max_size; + const total_byte_count = count * max_size; + + return struct { + const Self = @This(); + const OverflowList = std.ArrayListUnmanaged(u8); + pub threadlocal var byte_buffer: [total_byte_count]u8 align(max_align) = undefined; + pub threadlocal var bytes_used: usize = undefined; + pub threadlocal var bytes_element_count: usize = undefined; + pub threadlocal var instance: Self = undefined; + pub threadlocal var self: *Self = undefined; + pub threadlocal var has_loaded: bool = false; + allocator: *std.mem.Allocator, + overflow_list: []u8, + overflow_list_ptr: [*]u8 = undefined, + overflow_list_ptr_len: usize = 0, + overflow_element_count: usize = 0, + + pub fn init(allocator: *std.mem.Allocator) *Self { + if (has_loaded) { + return self; + } + + instance = Self{ + .allocator = allocator, + .overflow_list = &([_]u8{}), + }; + bytes_used = 0; + bytes_element_count = 0; + self = &instance; + has_loaded = true; + return self; + } + + pub fn reset() void { + std.debug.assert(has_loaded); + self.overflow_list = &([_]u8{}); + self.overflow_element_count = 0; + bytes_used = 0; + bytes_element_count = 0; + } + + pub fn growOverflowListIfNeeded(store: *Self, to: usize) void { + if (store.overflow_list_ptr_len >= to) { + return; + } + + const is_new = store.overflow_list_ptr_len == 0; + store.overflow_list_ptr_len = to + (max_size * 100); + + if (!is_new) { + _ = store.allocator.resize(store.overflow_list_ptr[0..store.overflow_list_ptr_len], store.overflow_list_ptr_len) catch unreachable; + } else { + store.overflow_list_ptr = (store.allocator.alloc(u8, store.overflow_list_ptr_len) catch unreachable).ptr; + } + } + + pub fn append(comptime ValueType: type, value: ValueType) ListIndex { + std.debug.assert(has_loaded); + + if (bytes_used < max_size - 1) { + const index = bytes_element_count; + const offset = bytes_used; + bytes_element_count += 1; + bytes_used += max_size; + std.mem.copy(u8, byte_buffer[offset..bytes_used], std.mem.asBytes(&value)); + return ListIndex{ .is_overflowing = false, .index = @intCast(u31, index) }; + } else { + const index = self.overflow_element_count; + const offset = self.overflow_list.len; + self.overflow_element_count += 1; + const end_length = offset + max_size; + self.growOverflowListIfNeeded(end_length); + std.mem.copy(u8, self.overflow_list_ptr[offset..end_length], std.mem.asBytes(&value)); + self.overflow_list = self.overflow_list_ptr[0..end_length]; + return ListIndex{ .is_overflowing = true, .index = @intCast(u31, index) }; + } + } + + pub fn at(index: ListIndex, comptime ValueType: type) *ValueType { + std.debug.assert(index.index != allocators.NotFound.index and index.index != allocators.Unassigned.index); + @setRuntimeSafety(false); + + const slice_begin = index.index * element_size; + const slice_end = slice_begin + element_size; + + var slice: []u8 = undefined; + if (index.is_overflowing) { + slice = self.overflow_list_ptr[slice_begin..slice_end]; + @setRuntimeSafety(false); + } else { + slice = byte_buffer[slice_begin..]; + @setRuntimeSafety(false); + } + + var aligned_slice = @alignCast(@alignOf(ValueType), slice.ptr); + + return @ptrCast( + *ValueType, + aligned_slice, + ); + } + }; +} + +pub fn NewStore(comptime BaseStore: type, comptime ValueType: type) type { + return struct { + pub fn at(index: ListIndex) *ValueType { + return BaseStore.at(index, ValueType); + } + + pub fn append(value: ValueType) ListIndex { + return BaseStore.append(ValueType, value); + } + }; +} + pub const ListIndex = packed struct { index: u31, is_overflowing: bool = false, @@ -197,7 +323,9 @@ pub const Binding = struct { b_missing, }; + pub var binding_count: usize = 0; pub fn init(t: anytype, loc: logger.Loc) Binding { + binding_count += 1; switch (@TypeOf(t)) { *B.Identifier => { return Binding{ .loc = loc, .data = B{ .b_identifier = t } }; @@ -221,6 +349,7 @@ pub const Binding = struct { } pub fn alloc(allocator: *std.mem.Allocator, t: anytype, loc: logger.Loc) Binding { + binding_count += 1; switch (@TypeOf(t)) { B.Identifier => { var data = allocator.create(B.Identifier) catch unreachable; @@ -690,7 +819,7 @@ pub const E = struct { op: Op.Code, }; - pub const Boolean = packed struct { value: bool }; + pub const Boolean = struct { value: bool }; pub const Super = struct {}; pub const Null = struct {}; pub const This = struct {}; @@ -777,7 +906,7 @@ pub const E = struct { pub const Function = struct { func: G.Fn }; - pub const Identifier = packed struct { + pub const Identifier = struct { ref: Ref = Ref.None, // If we're inside a "with" statement, this identifier may be a property @@ -1459,10 +1588,8 @@ pub const Stmt = struct { s_class: ListIndex, s_comment: ListIndex, s_continue: ListIndex, - s_debugger: S.Debugger, s_directive: ListIndex, s_do_while: ListIndex, - s_empty: S.Empty, // special case, its a zero value type s_enum: ListIndex, s_export_clause: ListIndex, s_export_default: ListIndex, @@ -1484,113 +1611,85 @@ pub const Stmt = struct { s_switch: ListIndex, s_throw: ListIndex, s_try: ListIndex, - s_type_script: S.TypeScript, s_while: ListIndex, s_with: ListIndex, + s_type_script: S.TypeScript, + s_empty: S.Empty, // special case, its a zero value type + s_debugger: S.Debugger, + pub const Store = struct { - pub const Block = NewStore(S.Block); - pub const Break = NewStore(S.Break); - pub const Class = NewStore(S.Class); - pub const Comment = NewStore(S.Comment); - pub const Continue = NewStore(S.Continue); - pub const Directive = NewStore(S.Directive); - pub const DoWhile = NewStore(S.DoWhile); - pub const Enum = NewStore(S.Enum); - pub const ExportClause = NewStore(S.ExportClause); - pub const ExportDefault = NewStore(S.ExportDefault); - pub const ExportEquals = NewStore(S.ExportEquals); - pub const ExportFrom = NewStore(S.ExportFrom); - pub const ExportStar = NewStore(S.ExportStar); - pub const SExpr = NewStore(S.SExpr); - pub const ForIn = NewStore(S.ForIn); - pub const ForOf = NewStore(S.ForOf); - pub const For = NewStore(S.For); - pub const Function = NewStore(S.Function); - pub const If = NewStore(S.If); - pub const Import = NewStore(S.Import); - pub const Label = NewStore(S.Label); - pub const LazyExport = NewStore(S.LazyExport); - pub const Local = NewStore(S.Local); - pub const Namespace = NewStore(S.Namespace); - pub const Return = NewStore(S.Return); - pub const Switch = NewStore(S.Switch); - pub const Throw = NewStore(S.Throw); - pub const Try = NewStore(S.Try); - pub const TypeScript = NewStore(S.TypeScript); - pub const While = NewStore(S.While); - pub const With = NewStore(S.With); + const Union = [_]type{ + S.Block, + S.Break, + S.Class, + S.Comment, + S.Continue, + S.Directive, + S.DoWhile, + S.Enum, + S.ExportClause, + S.ExportDefault, + S.ExportEquals, + S.ExportFrom, + S.ExportStar, + S.SExpr, + S.ForIn, + S.ForOf, + S.For, + S.Function, + S.If, + S.Import, + S.Label, + S.LazyExport, + S.Local, + S.Namespace, + S.Return, + S.Switch, + S.Throw, + S.Try, + S.While, + S.With, + }; + pub const BaseStore = NewBaseStore(&Union, 512); + pub const Block = NewStore(BaseStore, S.Block); + pub const Break = NewStore(BaseStore, S.Break); + pub const Class = NewStore(BaseStore, S.Class); + pub const Comment = NewStore(BaseStore, S.Comment); + pub const Continue = NewStore(BaseStore, S.Continue); + pub const Directive = NewStore(BaseStore, S.Directive); + pub const DoWhile = NewStore(BaseStore, S.DoWhile); + pub const Enum = NewStore(BaseStore, S.Enum); + pub const ExportClause = NewStore(BaseStore, S.ExportClause); + pub const ExportDefault = NewStore(BaseStore, S.ExportDefault); + pub const ExportEquals = NewStore(BaseStore, S.ExportEquals); + pub const ExportFrom = NewStore(BaseStore, S.ExportFrom); + pub const ExportStar = NewStore(BaseStore, S.ExportStar); + pub const SExpr = NewStore(BaseStore, S.SExpr); + pub const ForIn = NewStore(BaseStore, S.ForIn); + pub const ForOf = NewStore(BaseStore, S.ForOf); + pub const For = NewStore(BaseStore, S.For); + pub const Function = NewStore(BaseStore, S.Function); + pub const If = NewStore(BaseStore, S.If); + pub const Import = NewStore(BaseStore, S.Import); + pub const Label = NewStore(BaseStore, S.Label); + pub const LazyExport = NewStore(BaseStore, S.LazyExport); + pub const Local = NewStore(BaseStore, S.Local); + pub const Namespace = NewStore(BaseStore, S.Namespace); + pub const Return = NewStore(BaseStore, S.Return); + pub const Switch = NewStore(BaseStore, S.Switch); + pub const Throw = NewStore(BaseStore, S.Throw); + pub const Try = NewStore(BaseStore, S.Try); + pub const While = NewStore(BaseStore, S.While); + pub const With = NewStore(BaseStore, S.With); threadlocal var has_inited = false; pub fn create(allocator: *std.mem.Allocator) void { - if (has_inited) { - return; - } - - has_inited = true; - _ = Block.init(allocator); - _ = Break.init(allocator); - _ = Class.init(allocator); - _ = Comment.init(allocator); - _ = Continue.init(allocator); - _ = Directive.init(allocator); - _ = DoWhile.init(allocator); - _ = Enum.init(allocator); - _ = ExportClause.init(allocator); - _ = ExportDefault.init(allocator); - _ = ExportEquals.init(allocator); - _ = ExportFrom.init(allocator); - _ = ExportStar.init(allocator); - _ = SExpr.init(allocator); - _ = ForIn.init(allocator); - _ = ForOf.init(allocator); - _ = For.init(allocator); - _ = Function.init(allocator); - _ = If.init(allocator); - _ = Import.init(allocator); - _ = Label.init(allocator); - _ = LazyExport.init(allocator); - _ = Local.init(allocator); - _ = Namespace.init(allocator); - _ = Return.init(allocator); - _ = Switch.init(allocator); - _ = Throw.init(allocator); - _ = Try.init(allocator); - _ = While.init(allocator); - _ = With.init(allocator); + _ = BaseStore.init(allocator); } pub fn reset() void { - Block.reset(); - Break.reset(); - Class.reset(); - Comment.reset(); - Continue.reset(); - Directive.reset(); - DoWhile.reset(); - Enum.reset(); - ExportClause.reset(); - ExportDefault.reset(); - ExportEquals.reset(); - ExportFrom.reset(); - ExportStar.reset(); - SExpr.reset(); - ForIn.reset(); - ForOf.reset(); - For.reset(); - Function.reset(); - If.reset(); - Import.reset(); - Label.reset(); - LazyExport.reset(); - Local.reset(); - Namespace.reset(); - Return.reset(); - Switch.reset(); - Throw.reset(); - Try.reset(); - While.reset(); - With.reset(); + BaseStore.reset(); } pub fn append(comptime ValueType: type, value: anytype) ListIndex { @@ -1695,76 +1794,6 @@ pub const Stmt = struct { }, } } - - pub fn NewStore(comptime ValueType: type) type { - const count = 8096; - const max_index = count - 1; - const list_count = count; - return struct { - pub threadlocal var backing_buf: [count]ValueType = undefined; - pub threadlocal var backing_buf_used: u16 = 0; - const Allocator = std.mem.Allocator; - const Self = @This(); - const NotFound = allocators.NotFound; - const Unassigned = allocators.Unassigned; - - overflow_list: std.ArrayListUnmanaged(ValueType), - allocator: *Allocator, - - pub threadlocal var instance: Self = undefined; - pub threadlocal var self: *Self = undefined; - - pub fn reset() void { - backing_buf_used = 0; - self.overflow_list.items.len = 0; - } - - pub fn init(allocator: *std.mem.Allocator) *Self { - instance = Self{ - .allocator = allocator, - .overflow_list = std.ArrayListUnmanaged(ValueType){}, - }; - - self = &instance; - return self; - } - - pub fn isOverflowing() bool { - return backing_buf_used >= @as(u16, count); - } - - pub fn at(index: ListIndex) *ValueType { - std.debug.assert(index.index != NotFound.index and index.index != Unassigned.index); - - if (index.is_overflowing) { - return &self.overflow_list.items[index.index]; - } else { - return &backing_buf[index.index]; - } - } - - pub fn exists(value: ValueType) bool { - return isSliceInBuffer(value, backing_buf); - } - - pub fn append(value: ValueType) ListIndex { - var result = ListIndex{ .index = std.math.maxInt(u31), .is_overflowing = backing_buf_used > max_index }; - if (result.is_overflowing) { - result.index = @intCast(u31, self.overflow_list.items.len); - self.overflow_list.append(self.allocator, value) catch unreachable; - } else { - result.index = backing_buf_used; - backing_buf[result.index] = value; - backing_buf_used += 1; - if (backing_buf_used >= max_index and self.overflow_list.capacity == 0) { - self.overflow_list = @TypeOf(self.overflow_list).initCapacity(self.allocator, 1) catch unreachable; - } - } - - return result; - } - }; - } }; pub inline fn set(data: *Data, value: anytype) void { @@ -3263,11 +3292,12 @@ pub const Expr = struct { e_null: E.Null, e_undefined: E.Undefined, e_new_target: E.NewTarget, + e_import_meta: E.ImportMeta, e_new: ListIndex, e_function: ListIndex, - e_import_meta: E.ImportMeta, + e_call: ListIndex, e_dot: ListIndex, e_index: ListIndex, @@ -3293,41 +3323,67 @@ pub const Expr = struct { e_import: ListIndex, pub const Store = struct { - pub const Array = NewStore(E.Array); - pub const Unary = NewStore(E.Unary); - pub const Binary = NewStore(E.Binary); - pub const This = NewStore(E.This); - pub const Class = NewStore(E.Class); - pub const Boolean = NewStore(E.Boolean); - pub const Super = NewStore(E.Super); - pub const Null = NewStore(E.Null); - pub const Undefined = NewStore(E.Undefined); - pub const New = NewStore(E.New); - pub const Function = NewStore(E.Function); - pub const ImportMeta = NewStore(E.ImportMeta); - pub const Call = NewStore(E.Call); - pub const Dot = NewStore(E.Dot); - pub const Index = NewStore(E.Index); - pub const Arrow = NewStore(E.Arrow); - pub const Identifier = NewStore(E.Identifier); - pub const ImportIdentifier = NewStore(E.ImportIdentifier); - pub const PrivateIdentifier = NewStore(E.PrivateIdentifier); - pub const JSXElement = NewStore(E.JSXElement); - pub const Missing = NewStore(E.Missing); - pub const Number = NewStore(E.Number); - pub const BigInt = NewStore(E.BigInt); - pub const Object = NewStore(E.Object); - pub const Spread = NewStore(E.Spread); - pub const String = NewStore(E.String); - pub const TemplatePart = NewStore(E.TemplatePart); - pub const Template = NewStore(E.Template); - pub const RegExp = NewStore(E.RegExp); - pub const Await = NewStore(E.Await); - pub const Yield = NewStore(E.Yield); - pub const If = NewStore(E.If); - pub const Require = NewStore(E.Require); - pub const RequireOrRequireResolve = NewStore(E.RequireOrRequireResolve); - pub const Import = NewStore(E.Import); + const Union = [_]type{ + E.Array, + E.Unary, + E.Binary, + E.Class, + E.Boolean, + E.New, + E.Function, + E.Call, + E.Dot, + E.Index, + E.Arrow, + E.Identifier, + E.ImportIdentifier, + E.PrivateIdentifier, + E.JSXElement, + E.Number, + E.BigInt, + E.Object, + E.Spread, + E.String, + E.TemplatePart, + E.Template, + E.RegExp, + E.Await, + E.Yield, + E.If, + E.Require, + E.RequireOrRequireResolve, + E.Import, + }; + pub const BaseStore = NewBaseStore(&Union, 2048); + pub const Array = NewStore(BaseStore, E.Array); + pub const Unary = NewStore(BaseStore, E.Unary); + pub const Binary = NewStore(BaseStore, E.Binary); + pub const Class = NewStore(BaseStore, E.Class); + pub const Boolean = NewStore(BaseStore, E.Boolean); + pub const New = NewStore(BaseStore, E.New); + pub const Function = NewStore(BaseStore, E.Function); + pub const Call = NewStore(BaseStore, E.Call); + pub const Dot = NewStore(BaseStore, E.Dot); + pub const Index = NewStore(BaseStore, E.Index); + pub const Arrow = NewStore(BaseStore, E.Arrow); + pub const Identifier = NewStore(BaseStore, E.Identifier); + pub const ImportIdentifier = NewStore(BaseStore, E.ImportIdentifier); + pub const PrivateIdentifier = NewStore(BaseStore, E.PrivateIdentifier); + pub const JSXElement = NewStore(BaseStore, E.JSXElement); + pub const Number = NewStore(BaseStore, E.Number); + pub const BigInt = NewStore(BaseStore, E.BigInt); + pub const Object = NewStore(BaseStore, E.Object); + pub const Spread = NewStore(BaseStore, E.Spread); + pub const String = NewStore(BaseStore, E.String); + pub const TemplatePart = NewStore(BaseStore, E.TemplatePart); + pub const Template = NewStore(BaseStore, E.Template); + pub const RegExp = NewStore(BaseStore, E.RegExp); + pub const Await = NewStore(BaseStore, E.Await); + pub const Yield = NewStore(BaseStore, E.Yield); + pub const If = NewStore(BaseStore, E.If); + pub const Require = NewStore(BaseStore, E.Require); + pub const RequireOrRequireResolve = NewStore(BaseStore, E.RequireOrRequireResolve); + pub const Import = NewStore(BaseStore, E.Import); threadlocal var has_inited = false; pub fn create(allocator: *std.mem.Allocator) void { @@ -3336,73 +3392,11 @@ pub const Expr = struct { } has_inited = true; - _ = Array.init(allocator); - _ = Unary.init(allocator); - _ = Binary.init(allocator); - _ = This.init(allocator); - _ = Class.init(allocator); - _ = Boolean.init(allocator); - _ = New.init(allocator); - _ = Function.init(allocator); - _ = ImportMeta.init(allocator); - _ = Call.init(allocator); - _ = Dot.init(allocator); - _ = Index.init(allocator); - _ = Arrow.init(allocator); - _ = Identifier.init(allocator); - _ = ImportIdentifier.init(allocator); - _ = PrivateIdentifier.init(allocator); - _ = JSXElement.init(allocator); - _ = Missing.init(allocator); - _ = Number.init(allocator); - _ = BigInt.init(allocator); - _ = Object.init(allocator); - _ = Spread.init(allocator); - _ = String.init(allocator); - _ = TemplatePart.init(allocator); - _ = Template.init(allocator); - _ = RegExp.init(allocator); - _ = Await.init(allocator); - _ = Yield.init(allocator); - _ = If.init(allocator); - _ = Require.init(allocator); - _ = RequireOrRequireResolve.init(allocator); - _ = Import.init(allocator); + _ = BaseStore.init(allocator); } pub fn reset() void { - Array.reset(); - Unary.reset(); - Binary.reset(); - This.reset(); - Class.reset(); - Boolean.reset(); - New.reset(); - Function.reset(); - ImportMeta.reset(); - Call.reset(); - Dot.reset(); - Index.reset(); - Arrow.reset(); - Identifier.reset(); - ImportIdentifier.reset(); - PrivateIdentifier.reset(); - JSXElement.reset(); - Missing.reset(); - Number.reset(); - BigInt.reset(); - Object.reset(); - Spread.reset(); - String.reset(); - TemplatePart.reset(); - Template.reset(); - RegExp.reset(); - Await.reset(); - Yield.reset(); - If.reset(); - Require.reset(); - RequireOrRequireResolve.reset(); - Import.reset(); + BaseStore.reset(); } pub fn append(comptime ValueType: type, value: anytype) ListIndex { @@ -3520,77 +3514,6 @@ pub const Expr = struct { }, } } - - pub fn NewStore(comptime ValueType: type) type { - const count = 8096; - const max_index = count - 1; - const list_count = count; - return struct { - pub threadlocal var backing_buf: [count]ValueType = undefined; - pub threadlocal var backing_buf_used: u16 = 0; - const Allocator = std.mem.Allocator; - const Self = @This(); - const NotFound = allocators.NotFound; - const Unassigned = allocators.Unassigned; - - overflow_list: std.ArrayListUnmanaged(ValueType), - allocator: *Allocator, - - pub threadlocal var instance: Self = undefined; - pub threadlocal var self: *Self = undefined; - - pub fn reset() void { - backing_buf_used = 0; - self.overflow_list.shrinkRetainingCapacity(0); - } - - pub fn init(allocator: *std.mem.Allocator) *Self { - instance = Self{ - .allocator = allocator, - .overflow_list = std.ArrayListUnmanaged(ValueType){}, - }; - - self = &instance; - return self; - } - - pub fn isOverflowing() bool { - return backing_buf_used >= @as(u16, count); - } - - pub fn at(index: ListIndex) *ValueType { - std.debug.assert(index.index != NotFound.index and index.index != Unassigned.index); - - if (index.is_overflowing) { - return &self.overflow_list.items[index.index]; - } else { - return &backing_buf[index.index]; - } - } - - pub fn exists(value: ValueType) bool { - return isSliceInBuffer(value, backing_buf); - } - - pub fn append(value: ValueType) ListIndex { - var result = ListIndex{ .index = std.math.maxInt(u31), .is_overflowing = backing_buf_used > max_index }; - if (result.is_overflowing) { - result.index = @intCast(u31, self.overflow_list.items.len); - self.overflow_list.append(self.allocator, value) catch unreachable; - } else { - result.index = backing_buf_used; - backing_buf[result.index] = value; - backing_buf_used += 1; - - if (backing_buf_used >= max_index and self.overflow_list.capacity == 0) { - self.overflow_list = @TypeOf(self.overflow_list).initCapacity(self.allocator, 1) catch unreachable; - } - } - - return result; - } - }; - } }; pub fn isBooleanValue(self: *Expr) bool { @@ -4148,78 +4071,6 @@ pub const Dependency = packed struct { pub const ExprList = std.ArrayList(Expr); pub const StmtList = std.ArrayList(Stmt); pub const BindingList = std.ArrayList(Binding); -pub const AstData = struct { - expr_list: ExprList, - stmt_list: StmtList, - binding_list: BindingList, - - pub fn init(allocator: *std.mem.Allocator) AstData { - return AstData{ - .expr_list = ExprList.init(allocator), - .stmt_list = StmtList.init(allocator), - .binding_list = BindingList.init(allocator), - }; - } - - pub fn deinit(self: *AstData) void { - self.expr_list.deinit(); - self.stmt_list.deinit(); - self.binding_list.deinit(); - } - - pub fn expr(self: *AstData, index: ExprNodeIndex) Expr { - return self.expr_list.items[index]; - } - - pub fn stmt(self: *AstData, index: StmtNodeIndex) Stmt { - return self.stmt_list.items[index]; - } - - pub fn binding(self: *AstData, index: BindingNodeIndex) Binding { - return self.binding_list.items[index]; - } - - pub fn add_(self: *AstData, t: anytype) !void { - return switch (@TypeOf(t)) { - Stmt => { - try self.stmt_list.append(t); - }, - Expr => { - try self.expr_list.append(t); - }, - Binding => { - try self.binding_list.append(t); - }, - else => { - @compileError("Invalid type passed to AstData.add. Expected Stmt, Expr, or Binding."); - }, - }; - } - - pub fn add(self: *AstData, t: anytype) !NodeIndex { - return &t; - // return switch (@TypeOf(t)) { - // Stmt => { - // var len = self.stmt_list.items.len; - // try self.stmt_list.append(t); - // return @intCast(StmtNodeIndex, len); - // }, - // Expr => { - // var len = self.expr_list.items.len; - // try self.expr_list.append(t); - // return @intCast(ExprNodeIndex, len); - // }, - // Binding => { - // var len = self.binding_list.items.len; - // try self.binding_list.append(t); - // return @intCast(BindingNodeIndex, len); - // }, - // else => { - // @compileError("Invalid type passed to AstData.add. Expected Stmt, Expr, or Binding."); - // }, - // }; - } -}; // Each file is made up of multiple parts, and each part consists of one or // more top-level statements. Parts are used for tree shaking and code diff --git a/src/js_lexer.zig b/src/js_lexer.zig index fef12bf47..e725a3a24 100644 --- a/src/js_lexer.zig +++ b/src/js_lexer.zig @@ -491,7 +491,7 @@ pub const Lexer = struct { } } - pub const InnerStringLiteral = packed struct { suffix_len: u3, needs_slow_path: bool }; + pub const InnerStringLiteral = struct { suffix_len: u3, needs_slow_path: bool }; fn parseStringLiteralInnter(lexer: *LexerType, comptime quote: CodePoint) !InnerStringLiteral { var needs_slow_path = false; var suffix_len: u3 = 1; diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig index ffa401bb7..fd8121f43 100644 --- a/src/js_parser/js_parser.zig +++ b/src/js_parser/js_parser.zig @@ -501,7 +501,7 @@ pub const SideEffects = enum(u2) { could_have_side_effects, no_side_effects, - pub const Result = packed struct { + pub const Result = struct { side_effects: SideEffects, ok: bool = false, value: bool = false, @@ -707,7 +707,7 @@ pub const SideEffects = enum(u2) { } } - pub const Equality = packed struct { equal: bool = false, ok: bool = false }; + pub const Equality = struct { equal: bool = false, ok: bool = false }; // Returns "equal, ok". If "ok" is false, then nothing is known about the two // values. If "ok" is true, the equality or inequality of the two values is @@ -1102,7 +1102,7 @@ const AsyncPrefixExpression = enum(u4) { } }; -const IdentifierOpts = packed struct { +const IdentifierOpts = struct { assign_target: js_ast.AssignTarget = js_ast.AssignTarget.none, is_delete_target: bool = false, was_originally_identifier: bool = false, @@ -1140,7 +1140,7 @@ fn statementCaresAboutScope(stmt: Stmt) bool { } } -const ExprIn = packed struct { +const ExprIn = struct { // This tells us if there are optional chain expressions (EDot, EIndex, or // ECall) that are chained on to this expression. Because of the way the AST // works, chaining expressions on to this expression means they are our @@ -1297,7 +1297,7 @@ const ScopeOrder = struct { scope: *js_ast.Scope, }; -const ParenExprOpts = packed struct { +const ParenExprOpts = struct { async_range: logger.Range = logger.Range.None, is_async: bool = false, force_arrow_fn: bool = false, @@ -1771,7 +1771,6 @@ pub const P = struct { promise_ref: ?js_ast.Ref = null, scopes_in_order_visitor_index: usize = 0, has_classic_runtime_warned: bool = false, - data: js_ast.AstData, injected_define_symbols: List(Ref), symbol_uses: SymbolUseMap, @@ -10258,7 +10257,10 @@ pub const P = struct { var has_spread = false; var has_proto = false; - for (e_.properties) |*property, i| { + for (e_.properties) |_, i| { + var property = e_.properties[i]; + defer e_.properties[i] = property; + if (property.kind != .spread) { property.key = p.visitExpr(property.key orelse Global.panic("Expected property key", .{})); const key = property.key.?; @@ -12822,7 +12824,6 @@ pub const P = struct { .require_transposer = @TypeOf(_parser.require_transposer).init(_parser), .require_resolve_transposer = @TypeOf(_parser.require_resolve_transposer).init(_parser), .lexer = lexer, - .data = js_ast.AstData.init(allocator), }; return _parser; diff --git a/src/thread_safe_hash_map.zig b/src/thread_safe_hash_map.zig index 5c3a8cf51..df6dc07c2 100644 --- a/src/thread_safe_hash_map.zig +++ b/src/thread_safe_hash_map.zig @@ -13,7 +13,7 @@ pub fn ThreadSafeStringHashMap(comptime Value: type) type { pub fn init(allocator: *std.mem.Allocator) !*HashMap { var self = try allocator.create(HashMap); self.* = HashMap{ .backing = HashMapType.init(allocator), .lock = sync.RwLock.init() }; - + try self.backing.ensureCapacity(10); return self; } |