stage2 parser: arrays and structs directly in memory after the node

Slightly reduced memory usage. Roughly the same API and perf.
master
Andrew Kelley 2020-05-21 22:52:45 -04:00
parent 9377af934f
commit 19de259936
3 changed files with 134 additions and 26 deletions

View File

@ -2067,11 +2067,23 @@ pub const Node = struct {
}
};
/// Elements occur directly in memory after ArrayInitializer.
pub const ArrayInitializer = struct {
base: Node = Node{ .id = .ArrayInitializer },
rtoken: TokenIndex,
list_len: NodeIndex,
lhs: *Node,
list: []*Node,
/// After this the caller must initialize the fields_and_decls list.
pub fn alloc(allocator: *mem.Allocator, list_len: NodeIndex) !*ArrayInitializer {
const bytes = try allocator.alignedAlloc(u8, @alignOf(ArrayInitializer), sizeInBytes(list_len));
return @ptrCast(*ArrayInitializer, bytes.ptr);
}
pub fn free(self: *ArrayInitializer, allocator: *mem.Allocator) void {
const bytes = @ptrCast([*]u8, self)[0..sizeInBytes(self.list_len)];
allocator.free(bytes);
}
pub fn iterate(self: *const ArrayInitializer) Node.Iterator {
return .{ .parent_node = &self.base, .index = 0, .node = null };
@ -2084,8 +2096,8 @@ pub const Node = struct {
if (i < 1) return self.lhs;
i -= 1;
if (i < self.list.len) return self.list[i];
i -= self.list.len;
if (i < self.list_len) return self.listConst()[i];
i -= self.list_len;
return null;
}
@ -2097,13 +2109,39 @@ pub const Node = struct {
pub fn lastToken(self: *const ArrayInitializer) TokenIndex {
return self.rtoken;
}
pub fn list(self: *ArrayInitializer) []*Node {
const decls_start = @ptrCast([*]u8, self) + @sizeOf(ArrayInitializer);
return @ptrCast([*]*Node, decls_start)[0..self.list_len];
}
pub fn listConst(self: *const ArrayInitializer) []const *Node {
const decls_start = @ptrCast([*]const u8, self) + @sizeOf(ArrayInitializer);
return @ptrCast([*]const *Node, decls_start)[0..self.list_len];
}
fn sizeInBytes(list_len: NodeIndex) usize {
return @sizeOf(ArrayInitializer) + @sizeOf(*Node) * @as(usize, list_len);
}
};
/// Elements occur directly in memory after ArrayInitializerDot.
pub const ArrayInitializerDot = struct {
base: Node = Node{ .id = .ArrayInitializerDot },
dot: TokenIndex,
rtoken: TokenIndex,
list: []*Node,
list_len: NodeIndex,
/// After this the caller must initialize the fields_and_decls list.
pub fn alloc(allocator: *mem.Allocator, list_len: NodeIndex) !*ArrayInitializerDot {
const bytes = try allocator.alignedAlloc(u8, @alignOf(ArrayInitializerDot), sizeInBytes(list_len));
return @ptrCast(*ArrayInitializerDot, bytes.ptr);
}
pub fn free(self: *ArrayInitializerDot, allocator: *mem.Allocator) void {
const bytes = @ptrCast([*]u8, self)[0..sizeInBytes(self.list_len)];
allocator.free(bytes);
}
pub fn iterate(self: *const ArrayInitializerDot) Node.Iterator {
return .{ .parent_node = &self.base, .index = 0, .node = null };
@ -2113,8 +2151,8 @@ pub const Node = struct {
var i = it.index;
it.index += 1;
if (i < self.list.len) return self.list[i];
i -= self.list.len;
if (i < self.list_len) return self.listConst()[i];
i -= self.list_len;
return null;
}
@ -2126,13 +2164,39 @@ pub const Node = struct {
pub fn lastToken(self: *const ArrayInitializerDot) TokenIndex {
return self.rtoken;
}
pub fn list(self: *ArrayInitializerDot) []*Node {
const decls_start = @ptrCast([*]u8, self) + @sizeOf(ArrayInitializerDot);
return @ptrCast([*]*Node, decls_start)[0..self.list_len];
}
pub fn listConst(self: *const ArrayInitializerDot) []const *Node {
const decls_start = @ptrCast([*]const u8, self) + @sizeOf(ArrayInitializerDot);
return @ptrCast([*]const *Node, decls_start)[0..self.list_len];
}
fn sizeInBytes(list_len: NodeIndex) usize {
return @sizeOf(ArrayInitializerDot) + @sizeOf(*Node) * @as(usize, list_len);
}
};
/// Elements occur directly in memory after StructInitializer.
pub const StructInitializer = struct {
base: Node = Node{ .id = .StructInitializer },
rtoken: TokenIndex,
list_len: NodeIndex,
lhs: *Node,
list: []*Node,
/// After this the caller must initialize the fields_and_decls list.
pub fn alloc(allocator: *mem.Allocator, list_len: NodeIndex) !*StructInitializer {
const bytes = try allocator.alignedAlloc(u8, @alignOf(StructInitializer), sizeInBytes(list_len));
return @ptrCast(*StructInitializer, bytes.ptr);
}
pub fn free(self: *StructInitializer, allocator: *mem.Allocator) void {
const bytes = @ptrCast([*]u8, self)[0..sizeInBytes(self.list_len)];
allocator.free(bytes);
}
pub fn iterate(self: *const StructInitializer) Node.Iterator {
return .{ .parent_node = &self.base, .index = 0, .node = null };
@ -2145,8 +2209,8 @@ pub const Node = struct {
if (i < 1) return self.lhs;
i -= 1;
if (i < self.list.len) return self.list[i];
i -= self.list.len;
if (i < self.list_len) return self.listConst()[i];
i -= self.list_len;
return null;
}
@ -2158,13 +2222,39 @@ pub const Node = struct {
pub fn lastToken(self: *const StructInitializer) TokenIndex {
return self.rtoken;
}
pub fn list(self: *StructInitializer) []*Node {
const decls_start = @ptrCast([*]u8, self) + @sizeOf(StructInitializer);
return @ptrCast([*]*Node, decls_start)[0..self.list_len];
}
pub fn listConst(self: *const StructInitializer) []const *Node {
const decls_start = @ptrCast([*]const u8, self) + @sizeOf(StructInitializer);
return @ptrCast([*]const *Node, decls_start)[0..self.list_len];
}
fn sizeInBytes(list_len: NodeIndex) usize {
return @sizeOf(StructInitializer) + @sizeOf(*Node) * @as(usize, list_len);
}
};
/// Elements occur directly in memory after StructInitializerDot.
pub const StructInitializerDot = struct {
base: Node = Node{ .id = .StructInitializerDot },
dot: TokenIndex,
rtoken: TokenIndex,
list: []*Node,
list_len: NodeIndex,
/// After this the caller must initialize the fields_and_decls list.
pub fn alloc(allocator: *mem.Allocator, list_len: NodeIndex) !*StructInitializerDot {
const bytes = try allocator.alignedAlloc(u8, @alignOf(StructInitializerDot), sizeInBytes(list_len));
return @ptrCast(*StructInitializerDot, bytes.ptr);
}
pub fn free(self: *StructInitializerDot, allocator: *mem.Allocator) void {
const bytes = @ptrCast([*]u8, self)[0..sizeInBytes(self.list_len)];
allocator.free(bytes);
}
pub fn iterate(self: *const StructInitializerDot) Node.Iterator {
return .{ .parent_node = &self.base, .index = 0, .node = null };
@ -2174,8 +2264,8 @@ pub const Node = struct {
var i = it.index;
it.index += 1;
if (i < self.list.len) return self.list[i];
i -= self.list.len;
if (i < self.list_len) return self.listConst()[i];
i -= self.list_len;
return null;
}
@ -2187,6 +2277,20 @@ pub const Node = struct {
pub fn lastToken(self: *const StructInitializerDot) TokenIndex {
return self.rtoken;
}
pub fn list(self: *StructInitializerDot) []*Node {
const decls_start = @ptrCast([*]u8, self) + @sizeOf(StructInitializerDot);
return @ptrCast([*]*Node, decls_start)[0..self.list_len];
}
pub fn listConst(self: *const StructInitializerDot) []const *Node {
const decls_start = @ptrCast([*]const u8, self) + @sizeOf(StructInitializerDot);
return @ptrCast([*]const *Node, decls_start)[0..self.list_len];
}
fn sizeInBytes(list_len: NodeIndex) usize {
return @sizeOf(StructInitializerDot) + @sizeOf(*Node) * @as(usize, list_len);
}
};
/// Parameter nodes directly follow Call in memory.

View File

@ -1318,12 +1318,13 @@ const Parser = struct {
const next = (try p.parseFieldInit()) orelse break;
try init_list.append(next);
}
const node = try p.arena.allocator.create(Node.StructInitializer);
const node = try Node.StructInitializer.alloc(&p.arena.allocator, init_list.items.len);
node.* = .{
.lhs = lhs,
.rtoken = try p.expectToken(.RBrace),
.list = try p.arena.allocator.dupe(*Node, init_list.items),
.list_len = init_list.items.len,
};
std.mem.copy(*Node, node.list(), init_list.items);
return &node.base;
}
@ -1333,12 +1334,13 @@ const Parser = struct {
const next = (try p.parseExpr()) orelse break;
try init_list.append(next);
}
const node = try p.arena.allocator.create(Node.ArrayInitializer);
const node = try Node.ArrayInitializer.alloc(&p.arena.allocator, init_list.items.len);
node.* = .{
.lhs = lhs,
.rtoken = try p.expectToken(.RBrace),
.list = try p.arena.allocator.dupe(*Node, init_list.items),
.list_len = init_list.items.len,
};
std.mem.copy(*Node, node.list(), init_list.items);
return &node.base;
}
@ -1346,7 +1348,7 @@ const Parser = struct {
node.* = .{
.lhs = lhs,
.rtoken = try p.expectToken(.RBrace),
.list = &[0]*Node{},
.list_len = 0,
};
return &node.base;
}
@ -1366,12 +1368,13 @@ const Parser = struct {
const next = (try p.parseFieldInit()) orelse break;
try init_list.append(next);
}
const node = try p.arena.allocator.create(Node.StructInitializerDot);
const node = try Node.StructInitializerDot.alloc(&p.arena.allocator, init_list.items.len);
node.* = .{
.dot = dot,
.rtoken = try p.expectToken(.RBrace),
.list = try p.arena.allocator.dupe(*Node, init_list.items),
.list_len = init_list.items.len,
};
std.mem.copy(*Node, node.list(), init_list.items);
return &node.base;
}
@ -1381,12 +1384,13 @@ const Parser = struct {
const next = (try p.parseExpr()) orelse break;
try init_list.append(next);
}
const node = try p.arena.allocator.create(Node.ArrayInitializerDot);
const node = try Node.ArrayInitializerDot.alloc(&p.arena.allocator, init_list.items.len);
node.* = .{
.dot = dot,
.rtoken = try p.expectToken(.RBrace),
.list = try p.arena.allocator.dupe(*Node, init_list.items),
.list_len = init_list.items.len,
};
std.mem.copy(*Node, node.list(), init_list.items);
return &node.base;
}
@ -1394,7 +1398,7 @@ const Parser = struct {
node.* = .{
.dot = dot,
.rtoken = try p.expectToken(.RBrace),
.list = &[0]*Node{},
.list_len = 0,
};
return &node.base;
}

View File

@ -620,13 +620,13 @@ fn renderExpression(
.ArrayInitializerDot => blk: {
const casted = @fieldParentPtr(ast.Node.ArrayInitializerDot, "base", base);
rtoken = casted.rtoken;
exprs = casted.list;
exprs = casted.list();
break :blk .{ .dot = casted.dot };
},
.ArrayInitializer => blk: {
const casted = @fieldParentPtr(ast.Node.ArrayInitializer, "base", base);
rtoken = casted.rtoken;
exprs = casted.list;
exprs = casted.list();
break :blk .{ .node = casted.lhs };
},
else => unreachable,
@ -784,13 +784,13 @@ fn renderExpression(
.StructInitializerDot => blk: {
const casted = @fieldParentPtr(ast.Node.StructInitializerDot, "base", base);
rtoken = casted.rtoken;
field_inits = casted.list;
field_inits = casted.list();
break :blk .{ .dot = casted.dot };
},
.StructInitializer => blk: {
const casted = @fieldParentPtr(ast.Node.StructInitializer, "base", base);
rtoken = casted.rtoken;
field_inits = casted.list;
field_inits = casted.list();
break :blk .{ .node = casted.lhs };
},
else => unreachable,