diff options
author | 2021-05-05 13:12:19 -0700 | |
---|---|---|
committer | 2021-05-05 13:12:19 -0700 | |
commit | 7a4084a23fc5045b479ed4fc08853e251e904d77 (patch) | |
tree | 3863baac41f44299c317f2d3d4255fdae3f83768 /src/js_parser/js_parser.zig | |
parent | 6be0a4653fa62ba8c9ae1c62ba4c56f46f00d7b6 (diff) | |
download | bun-7a4084a23fc5045b479ed4fc08853e251e904d77.tar.gz bun-7a4084a23fc5045b479ed4fc08853e251e904d77.tar.zst bun-7a4084a23fc5045b479ed4fc08853e251e904d77.zip |
alright
Former-commit-id: e0d01a9a9169bc0593b040b58c6260da18e6e717
Diffstat (limited to 'src/js_parser/js_parser.zig')
-rw-r--r-- | src/js_parser/js_parser.zig | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig index 5afdade21..3321d0ed3 100644 --- a/src/js_parser/js_parser.zig +++ b/src/js_parser/js_parser.zig @@ -993,8 +993,9 @@ const ExprOut = struct { const Tup = std.meta.Tuple; // This function exists to tie all of these checks together in one place +// This can sometimes show up on benchmarks as a small thing. fn isEvalOrArguments(name: string) bool { - return strings.eql(name, "eval") or strings.eql(name, "arguments"); + return strings.eqlComptime(name, "eval") or strings.eqlComptime(name, "arguments"); } const PrependTempRefsOpts = struct { @@ -1649,7 +1650,7 @@ pub const P = struct { // symbols must be separate from the pass that binds identifiers to declared // symbols to handle declaring a hoisted "var" symbol in a nested scope and // binding a name to it in a parent or sibling scope. - scopes_in_order: List(ScopeOrder), + scopes_in_order: std.ArrayListUnmanaged(ScopeOrder), // These properties are for the visit pass, which runs after the parse pass. // The visit pass binds identifiers to declared symbols, does constant @@ -2240,12 +2241,18 @@ pub const P = struct { } pub fn pushScopeForVisitPass(p: *P, comptime kind: js_ast.Scope.Kind, loc: logger.Loc) !void { + assert(p.scopes_in_order.items.len > 0); const order = p.scopes_in_order.items[0]; - p.scopes_in_order.items = p.scopes_in_order.items[1..p.scopes_in_order.items.len]; + if (p.scopes_in_order.items.len > 1) { + p.scopes_in_order.items = p.scopes_in_order.items[1..p.scopes_in_order.items.len]; + } else { + p.scopes_in_order.items = &([_]ScopeOrder{}); + } // Sanity-check that the scopes generated by the first and second passes match if (order.loc.start != loc.start or order.scope.kind != kind) { - p.panic("Expected scope ({s}, {d}) in {s}, found scope ({s}, {d})", .{ kind, loc.start, p.source.path.pretty, order.scope.kind, order.loc.start }); + std.debug.print("Expected scope ({s}, {d}) in {s}, found scope ({s}, {d})", .{ kind, loc.start, p.source.path.pretty, order.scope.kind, order.loc.start }); + p.panic("", .{}); } p.current_scope = order.scope; @@ -2284,7 +2291,7 @@ pub const P = struct { // errors if a statement in the function body tries to re-declare any of the // arguments. if (kind == js_ast.Scope.Kind.function_body) { - assert(parent.kind != js_ast.Scope.Kind.function_args); + assert(parent.kind == js_ast.Scope.Kind.function_args); var iter = scope.parent.?.members.iterator(); while (iter.next()) |entry| { @@ -2299,7 +2306,7 @@ pub const P = struct { // Remember the length in case we call popAndDiscardScope() later const scope_index = p.scopes_in_order.items.len; - try p.scopes_in_order.append(ScopeOrder{ .loc = loc, .scope = scope }); + try p.scopes_in_order.append(p.allocator, ScopeOrder{ .loc = loc, .scope = scope }); return scope_index; } @@ -4057,7 +4064,7 @@ pub const P = struct { } // Truncate the scope order where we started to pretend we never saw this scope - p.scopes_in_order.shrinkAndFree(scope_index); + p.scopes_in_order.shrinkRetainingCapacity(scope_index); } pub fn skipTypescriptTypeStmt(p: *P, opts: *ParseStatementOptions) void { @@ -4122,7 +4129,7 @@ pub const P = struct { if (p.lexer.isContextualKeyword("as")) { p.lexer.next(); original_name = p.lexer.identifier; - name = LocRef{ .loc = alias_loc, .ref = try p.storeNameInRef(alias) }; + name = LocRef{ .loc = alias_loc, .ref = try p.storeNameInRef(original_name) }; p.lexer.expect(.t_identifier); } else if (!isIdentifier) { // An import where the name is a keyword must have an alias @@ -10690,21 +10697,25 @@ pub const P = struct { p.panic("", .{}); } + // This code is tricky. + // - Doing it incorrectly will cause segfaults. + // - Doing it correctly drastically affects runtime performance while parsing larger files + // The key is in how we remove scopes from the list + // If we do an orderedRemove, it gets very slow. + // swapRemove is fast. But a little more dangerous. pub fn popAndFlattenScope(p: *P, scope_index: usize) void { // Move up to the parent scope var to_flatten = p.current_scope; var parent = to_flatten.parent.?; p.current_scope = parent; - var scopes_in_order_end = p.scopes_in_order.capacity; - var _scopes_in_order = p.scopes_in_order.allocatedSlice(); - var scopes_in_order = _scopes_in_order[0..scopes_in_order_end]; + // Erase this scope from the order. This will shift over the indices of all // the scopes that were created after us. However, we shouldn't have to // worry about other code with outstanding scope indices for these scopes. // These scopes were all created in between this scope's push and pop // operations, so they should all be child scopes and should all be popped // by the time we get here. - std.mem.copyBackwards(ScopeOrder, scopes_in_order[scope_index..scopes_in_order.len], scopes_in_order[scope_index + 1 .. scopes_in_order.len]); + _ = p.scopes_in_order.swapRemove(scope_index); // Remove the last child from the parent scope const last = parent.children.items.len - 1; @@ -10895,7 +10906,7 @@ pub const P = struct { .named_exports = @TypeOf(_parser.named_exports).init(allocator), .top_level_symbol_to_parts = @TypeOf(_parser.top_level_symbol_to_parts).init(allocator), .import_namespace_cc_map = @TypeOf(_parser.import_namespace_cc_map).init(allocator), - .scopes_in_order = std.ArrayList(ScopeOrder).init(allocator), + .scopes_in_order = try std.ArrayListUnmanaged(ScopeOrder).initCapacity(allocator, 1), .temp_refs_to_declare = @TypeOf(_parser.temp_refs_to_declare).init(allocator), .relocated_top_level_vars = @TypeOf(_parser.relocated_top_level_vars).init(allocator), .log = log, |