mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-06 17:34:25 +00:00
perf(ast): place NodeId field after Span in structs (#20584)
Alter the code in `ast_tools` which re-orders struct fields, to make `NodeId` always occupy a consistent "slot" in every AST node - at byte position 8, just after `Span`. This will be a sizeable gain once we start utilizing the `NodeId` fields more. Because, for example, every variant of `Expression` has its `NodeId` stored in same location as all the other variants, `Expression::node_id()` is just 1 operation - a pointer read - rather than a nest of branches, or a lookup table. Also alter the algorithm for ordering struct fields to fill in the 4-byte gap after `NodeId` field with other field(s), to avoid excess padding. The new algorithm also prioritizes keeping fields in definition order as much as possible, rather than sorting them strictly in order of size and alignment. This is mildly advantageous because field definition order is the order the AST is walked in, so it avoids bouncing between cache lines while iterating through the fields of a struct when visiting the AST. No types change size in the process. Fields remain packed to keep type sizes the minimum they can be - they just change order.
This commit is contained in:
1 parent
e98466632e
commit
c6ea0a068d
18 files changed
+5644
-5550
No files matched your search
@@ -54,22 +54,22 @@ export const PROGRAM_OFFSET = 0;
|
||||
/**
|
||||
* Byte offset of pointer to start of source text, relative to start of `Program`.
|
||||
*/
|
||||
export const SOURCE_START_OFFSET = 8;
|
||||
export const SOURCE_START_OFFSET = 16;
|
||||
|
||||
/**
|
||||
* Byte offset of length of source text, relative to start of `Program`.
|
||||
*/
|
||||
export const SOURCE_LEN_OFFSET = 16;
|
||||
export const SOURCE_LEN_OFFSET = 24;
|
||||
|
||||
/**
|
||||
* Byte offset of comments `Vec` pointer, relative to start of `Program`.
|
||||
*/
|
||||
export const COMMENTS_OFFSET = 24;
|
||||
export const COMMENTS_OFFSET = 32;
|
||||
|
||||
/**
|
||||
* Byte offset of comments `Vec` length, relative to start of `Program`.
|
||||
*/
|
||||
export const COMMENTS_LEN_OFFSET = 32;
|
||||
export const COMMENTS_LEN_OFFSET = 40;
|
||||
|
||||
/**
|
||||
* Size of `Comment` struct in bytes.
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -429,6 +429,7 @@ impl AstKind<'_> {
|
||||
}
|
||||
|
||||
/// Get [`NodeId`] of an [`AstKind`].
|
||||
// `node_id` field is in consistent position in all AST structs, so this boils down to 1 instruction.
|
||||
#[inline]
|
||||
pub fn node_id(&self) -> NodeId {
|
||||
match self {
|
||||
@@ -624,11 +625,8 @@ impl AstKind<'_> {
|
||||
}
|
||||
|
||||
/// Set [`NodeId`] of an [`AstKind`].
|
||||
#[expect(
|
||||
clippy::inline_always,
|
||||
reason = "enables compile-time match elimination in semantic builder"
|
||||
)]
|
||||
#[inline(always)]
|
||||
// `node_id` field is in consistent position in all AST structs, so this boils down to 1 instruction.
|
||||
#[inline]
|
||||
pub fn set_node_id(&self, node_id: NodeId) {
|
||||
match self {
|
||||
Self::Program(it) => it.set_node_id(node_id),
|
||||
|
||||
@@ -57,264 +57,264 @@ pub static STRUCTS: phf::Map<&'static str, StructDetails> = ::phf::Map {
|
||||
(0, 4),
|
||||
],
|
||||
entries: &[
|
||||
("JSXElement", StructDetails { field_order: Some(&[4, 0, 1, 2, 3]) }),
|
||||
("JSDocNullableType", StructDetails { field_order: Some(&[2, 0, 1, 3]) }),
|
||||
("WithClause", StructDetails { field_order: Some(&[2, 0, 3, 1]) }),
|
||||
("NewExpression", StructDetails { field_order: Some(&[4, 0, 1, 2, 3, 5]) }),
|
||||
("NumericLiteral", StructDetails { field_order: Some(&[3, 0, 1, 2, 4]) }),
|
||||
("JSXElement", StructDetails { field_order: Some(&[1, 0, 2, 3, 4]) }),
|
||||
("JSDocNullableType", StructDetails { field_order: Some(&[1, 0, 3, 2]) }),
|
||||
("WithClause", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("NewExpression", StructDetails { field_order: Some(&[1, 0, 3, 4, 5, 2]) }),
|
||||
("NumericLiteral", StructDetails { field_order: Some(&[1, 0, 4, 3, 2]) }),
|
||||
("TSUnknownKeyword", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("UnicodePropertyEscape", StructDetails { field_order: Some(&[0, 3, 4, 1, 2]) }),
|
||||
("TSInterfaceDeclaration", StructDetails { field_order: Some(&[5, 0, 1, 2, 3, 4, 7, 6]) }),
|
||||
("ObjectAssignmentTarget", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("SwitchCase", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("TSPropertySignature", StructDetails { field_order: Some(&[3, 0, 4, 5, 6, 1, 2]) }),
|
||||
("CatchClause", StructDetails { field_order: Some(&[3, 0, 1, 2, 4]) }),
|
||||
("ForInStatement", StructDetails { field_order: Some(&[4, 0, 1, 2, 3, 5]) }),
|
||||
("AssignmentExpression", StructDetails { field_order: Some(&[3, 0, 4, 1, 2]) }),
|
||||
("BlockStatement", StructDetails { field_order: Some(&[2, 0, 1, 3]) }),
|
||||
("StringLiteral", StructDetails { field_order: Some(&[3, 0, 1, 2, 4]) }),
|
||||
("TSInterfaceDeclaration", StructDetails { field_order: Some(&[1, 0, 3, 4, 5, 6, 7, 2]) }),
|
||||
("ObjectAssignmentTarget", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("SwitchCase", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("TSPropertySignature", StructDetails { field_order: Some(&[1, 0, 2, 3, 4, 5, 6]) }),
|
||||
("CatchClause", StructDetails { field_order: Some(&[1, 0, 3, 4, 2]) }),
|
||||
("ForInStatement", StructDetails { field_order: Some(&[1, 0, 3, 4, 5, 2]) }),
|
||||
("AssignmentExpression", StructDetails { field_order: Some(&[1, 0, 2, 3, 4]) }),
|
||||
("BlockStatement", StructDetails { field_order: Some(&[1, 0, 3, 2]) }),
|
||||
("StringLiteral", StructDetails { field_order: Some(&[1, 0, 3, 4, 2]) }),
|
||||
("TSNumberKeyword", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("ImportNamespaceSpecifier", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSTypeParameterInstantiation", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("ImportNamespaceSpecifier", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("TSTypeParameterInstantiation", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("ScopeId", StructDetails { field_order: None }),
|
||||
("ImportDeclaration", StructDetails { field_order: Some(&[4, 0, 1, 2, 5, 3, 6]) }),
|
||||
("ImportDeclaration", StructDetails { field_order: Some(&[1, 0, 4, 5, 2, 6, 3]) }),
|
||||
("SymbolId", StructDetails { field_order: None }),
|
||||
("PrivateIdentifier", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSModuleBlock", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("TSEnumDeclaration", StructDetails { field_order: Some(&[3, 0, 1, 2, 4, 5]) }),
|
||||
("JSXNamespacedName", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("PrivateIdentifier", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("TSModuleBlock", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("TSEnumDeclaration", StructDetails { field_order: Some(&[1, 0, 4, 5, 2, 3]) }),
|
||||
("JSXNamespacedName", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("TSIntrinsicKeyword", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("BindingRestElement", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSTypeQuery", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("SwitchStatement", StructDetails { field_order: Some(&[3, 0, 1, 2, 4]) }),
|
||||
("BindingRestElement", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("TSTypeQuery", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("SwitchStatement", StructDetails { field_order: Some(&[1, 0, 3, 4, 2]) }),
|
||||
("TSAnyKeyword", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("TSAsExpression", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("ReturnStatement", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("ArrayAssignmentTarget", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("TSAsExpression", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("ReturnStatement", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("ArrayAssignmentTarget", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("ThisExpression", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("IgnoreGroup", StructDetails { field_order: None }),
|
||||
("TSInterfaceBody", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("CatchParameter", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("TSInterfaceBody", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("CatchParameter", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("RawTransferData", StructDetails { field_order: None }),
|
||||
("RawTransferMetadata", StructDetails { field_order: Some(&[0, 3, 4, 5, 1, 2]) }),
|
||||
("ObjectProperty", StructDetails { field_order: Some(&[3, 0, 4, 1, 2, 5, 6, 7]) }),
|
||||
("ObjectProperty", StructDetails { field_order: Some(&[1, 0, 2, 6, 7, 3, 4, 5]) }),
|
||||
("DebuggerStatement", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("TSModuleDeclaration", StructDetails { field_order: Some(&[3, 0, 1, 2, 5, 6, 4]) }),
|
||||
("TSModuleDeclaration", StructDetails { field_order: Some(&[1, 0, 3, 4, 5, 6, 2]) }),
|
||||
(
|
||||
"MethodDefinition",
|
||||
StructDetails { field_order: Some(&[4, 0, 5, 1, 2, 3, 6, 7, 8, 9, 10, 11]) },
|
||||
StructDetails { field_order: Some(&[1, 0, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11]) },
|
||||
),
|
||||
("ExportEntry", StructDetails { field_order: Some(&[1, 0, 2, 3, 4, 5, 6]) }),
|
||||
("DoWhileStatement", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("FunctionBody", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("DoWhileStatement", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("FunctionBody", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("Dot", StructDetails { field_order: None }),
|
||||
("UnaryExpression", StructDetails { field_order: Some(&[2, 0, 3, 1]) }),
|
||||
("TSLiteralType", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("ObjectExpression", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSRestType", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TemplateElement", StructDetails { field_order: Some(&[2, 0, 1, 3, 4]) }),
|
||||
("JSXSpreadChild", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSOptionalType", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("IfStatement", StructDetails { field_order: Some(&[4, 0, 1, 2, 3]) }),
|
||||
("UnaryExpression", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("TSLiteralType", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("ObjectExpression", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("TSRestType", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("TemplateElement", StructDetails { field_order: Some(&[1, 0, 4, 2, 3]) }),
|
||||
("JSXSpreadChild", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("TSOptionalType", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("IfStatement", StructDetails { field_order: Some(&[1, 0, 2, 3, 4]) }),
|
||||
("Character", StructDetails { field_order: Some(&[0, 2, 1]) }),
|
||||
("LookAroundAssertion", StructDetails { field_order: Some(&[0, 2, 1]) }),
|
||||
("EcmaScriptModule", StructDetails { field_order: Some(&[4, 0, 1, 2, 3]) }),
|
||||
("RegExp", StructDetails { field_order: None }),
|
||||
("SpreadElement", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("SpreadElement", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("Span", StructDetails { field_order: None }),
|
||||
("Disjunction", StructDetails { field_order: None }),
|
||||
("AssignmentTargetPropertyIdentifier", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("ConditionalExpression", StructDetails { field_order: Some(&[4, 0, 1, 2, 3]) }),
|
||||
("AssignmentTargetPropertyIdentifier", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("ConditionalExpression", StructDetails { field_order: Some(&[1, 0, 2, 3, 4]) }),
|
||||
(
|
||||
"PropertyDefinition",
|
||||
StructDetails {
|
||||
field_order: Some(&[5, 0, 6, 1, 2, 3, 4, 7, 8, 9, 10, 11, 12, 13, 14]),
|
||||
field_order: Some(&[1, 0, 2, 6, 7, 8, 9, 3, 4, 5, 10, 11, 12, 13, 14]),
|
||||
},
|
||||
),
|
||||
("Comment", StructDetails { field_order: None }),
|
||||
("LabeledStatement", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("StaticMemberExpression", StructDetails { field_order: Some(&[3, 0, 1, 2, 4]) }),
|
||||
("LabeledStatement", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("StaticMemberExpression", StructDetails { field_order: Some(&[1, 0, 3, 4, 2]) }),
|
||||
("CharacterClassEscape", StructDetails { field_order: None }),
|
||||
("TSTupleType", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSTypeParameter", StructDetails { field_order: Some(&[4, 0, 1, 2, 3, 5, 6, 7]) }),
|
||||
("TSTupleType", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("TSTypeParameter", StructDetails { field_order: Some(&[1, 0, 5, 6, 7, 2, 3, 4]) }),
|
||||
("ErrorLabel", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("RawTransferMetadata2", StructDetails { field_order: Some(&[0, 3, 4, 5, 1, 2]) }),
|
||||
("ChainExpression", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("BindingProperty", StructDetails { field_order: Some(&[3, 0, 1, 2, 4, 5]) }),
|
||||
("ChainExpression", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("BindingProperty", StructDetails { field_order: Some(&[1, 0, 4, 5, 2, 3]) }),
|
||||
("NullLiteral", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("TSObjectKeyword", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("IdentifierName", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("IdentifierName", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("JSXOpeningFragment", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("AssignmentTargetRest", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSIndexedAccessType", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("AssignmentTargetRest", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("TSIndexedAccessType", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("Modifiers", StructDetails { field_order: None }),
|
||||
("CommentNewlines", StructDetails { field_order: None }),
|
||||
("JSXText", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("ExportAllDeclaration", StructDetails { field_order: Some(&[4, 0, 1, 2, 3, 5]) }),
|
||||
("TSMappedType", StructDetails { field_order: Some(&[5, 0, 1, 2, 3, 4, 7, 8, 6]) }),
|
||||
("JSXText", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("ExportAllDeclaration", StructDetails { field_order: Some(&[1, 0, 3, 4, 5, 2]) }),
|
||||
("TSMappedType", StructDetails { field_order: Some(&[1, 0, 3, 4, 5, 6, 7, 8, 2]) }),
|
||||
("TSStringKeyword", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("TSNamedTupleMember", StructDetails { field_order: Some(&[3, 0, 1, 2, 4]) }),
|
||||
("TSTypeLiteral", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSTemplateLiteralType", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("JSXAttribute", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("AssignmentTargetPropertyProperty", StructDetails { field_order: Some(&[3, 0, 1, 2, 4]) }),
|
||||
("TSNamedTupleMember", StructDetails { field_order: Some(&[1, 0, 3, 4, 2]) }),
|
||||
("TSTypeLiteral", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("TSTemplateLiteralType", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("JSXAttribute", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("AssignmentTargetPropertyProperty", StructDetails { field_order: Some(&[1, 0, 3, 4, 2]) }),
|
||||
("RegExpPattern", StructDetails { field_order: None }),
|
||||
("TSEnumBody", StructDetails { field_order: Some(&[2, 0, 1, 3]) }),
|
||||
("Decorator", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSEnumBody", StructDetails { field_order: Some(&[1, 0, 3, 2]) }),
|
||||
("Decorator", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("EmptyStatement", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("ForOfStatement", StructDetails { field_order: Some(&[4, 0, 6, 1, 2, 3, 5]) }),
|
||||
("ForOfStatement", StructDetails { field_order: Some(&[1, 0, 6, 3, 4, 5, 2]) }),
|
||||
("ReferenceId", StructDetails { field_order: None }),
|
||||
("V8IntrinsicExpression", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("WithStatement", StructDetails { field_order: Some(&[3, 0, 1, 2, 4]) }),
|
||||
("V8IntrinsicExpression", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("WithStatement", StructDetails { field_order: Some(&[1, 0, 3, 4, 2]) }),
|
||||
("SourceType", StructDetails { field_order: None }),
|
||||
("ThrowStatement", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("IdentifierReference", StructDetails { field_order: Some(&[2, 0, 1, 3]) }),
|
||||
("Program", StructDetails { field_order: Some(&[6, 0, 8, 1, 2, 3, 4, 5, 7]) }),
|
||||
("TaggedTemplateExpression", StructDetails { field_order: Some(&[4, 0, 1, 2, 3]) }),
|
||||
("ThrowStatement", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("IdentifierReference", StructDetails { field_order: Some(&[1, 0, 3, 2]) }),
|
||||
("Program", StructDetails { field_order: Some(&[1, 0, 8, 3, 4, 5, 6, 7, 2]) }),
|
||||
("TaggedTemplateExpression", StructDetails { field_order: Some(&[1, 0, 2, 3, 4]) }),
|
||||
("JSXEmptyExpression", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("JSXClosingFragment", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("TSTypePredicate", StructDetails { field_order: Some(&[3, 0, 1, 4, 2]) }),
|
||||
("AssignmentPattern", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("Class", StructDetails { field_order: Some(&[8, 0, 10, 1, 2, 3, 4, 5, 6, 7, 11, 12, 9]) }),
|
||||
("TSTypePredicate", StructDetails { field_order: Some(&[1, 0, 3, 2, 4]) }),
|
||||
("AssignmentPattern", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("Class", StructDetails { field_order: Some(&[1, 0, 10, 3, 4, 5, 6, 7, 8, 9, 11, 12, 2]) }),
|
||||
("StaticImport", StructDetails { field_order: None }),
|
||||
("TSThisType", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("NamedReference", StructDetails { field_order: None }),
|
||||
("JSDocUnknownType", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("BigIntLiteral", StructDetails { field_order: Some(&[3, 0, 1, 2, 4]) }),
|
||||
("ForStatement", StructDetails { field_order: Some(&[5, 0, 1, 2, 3, 4, 6]) }),
|
||||
("ParenthesizedExpression", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("ContinueStatement", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSQualifiedName", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("ArrayPattern", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("TSTypeOperator", StructDetails { field_order: Some(&[2, 0, 3, 1]) }),
|
||||
("UpdateExpression", StructDetails { field_order: Some(&[2, 0, 3, 4, 1]) }),
|
||||
("BigIntLiteral", StructDetails { field_order: Some(&[1, 0, 3, 4, 2]) }),
|
||||
("ForStatement", StructDetails { field_order: Some(&[1, 0, 3, 4, 5, 6, 2]) }),
|
||||
("ParenthesizedExpression", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("ContinueStatement", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("TSQualifiedName", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("ArrayPattern", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("TSTypeOperator", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("UpdateExpression", StructDetails { field_order: Some(&[1, 0, 2, 3, 4]) }),
|
||||
("CharacterClass", StructDetails { field_order: Some(&[0, 2, 3, 4, 1]) }),
|
||||
("ClassString", StructDetails { field_order: Some(&[0, 2, 1]) }),
|
||||
("ImportSpecifier", StructDetails { field_order: Some(&[3, 0, 1, 2, 4]) }),
|
||||
("TSIntersectionType", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("ImportAttribute", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("ImportSpecifier", StructDetails { field_order: Some(&[1, 0, 3, 4, 2]) }),
|
||||
("TSIntersectionType", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("ImportAttribute", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("TSNeverKeyword", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("JSXSpreadAttribute", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("CallExpression", StructDetails { field_order: Some(&[4, 0, 1, 2, 3, 5, 6]) }),
|
||||
("Hashbang", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSUnionType", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSTypeReference", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("JSXSpreadAttribute", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("CallExpression", StructDetails { field_order: Some(&[1, 0, 4, 5, 6, 2, 3]) }),
|
||||
("Hashbang", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("TSUnionType", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("TSTypeReference", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("Error", StructDetails { field_order: Some(&[4, 0, 1, 2, 3]) }),
|
||||
("ArrayExpression", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("ArrayExpression", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("IndexedReference", StructDetails { field_order: None }),
|
||||
("TSSymbolKeyword", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("TSInferType", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("AssignmentTargetWithDefault", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("TemplateLiteral", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("PrivateInExpression", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("JSXFragment", StructDetails { field_order: Some(&[4, 0, 1, 2, 3]) }),
|
||||
("TSInferType", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("AssignmentTargetWithDefault", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("TemplateLiteral", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("PrivateInExpression", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("JSXFragment", StructDetails { field_order: Some(&[1, 0, 2, 3, 4]) }),
|
||||
("ImportEntry", StructDetails { field_order: None }),
|
||||
("JSXExpressionContainer", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSTypeAssertion", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("JSXExpressionContainer", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("TSTypeAssertion", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
(
|
||||
"AccessorProperty",
|
||||
StructDetails { field_order: Some(&[5, 0, 6, 1, 2, 3, 4, 7, 8, 9, 10, 11]) },
|
||||
StructDetails { field_order: Some(&[1, 0, 2, 6, 7, 8, 9, 3, 4, 5, 10, 11]) },
|
||||
),
|
||||
("Modifier", StructDetails { field_order: None }),
|
||||
("LabelIdentifier", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSEnumMember", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("LabelIdentifier", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("TSEnumMember", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("TSUndefinedKeyword", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("TSImportTypeQualifiedName", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("TSImportTypeQualifiedName", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("BoundaryAssertion", StructDetails { field_order: None }),
|
||||
("TSClassImplements", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("BreakStatement", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSConstructorType", StructDetails { field_order: Some(&[4, 0, 6, 1, 2, 3, 5]) }),
|
||||
("TSCallSignatureDeclaration", StructDetails { field_order: Some(&[5, 0, 1, 2, 3, 4, 6]) }),
|
||||
("ExportDefaultDeclaration", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSGlobalDeclaration", StructDetails { field_order: Some(&[3, 0, 1, 2, 5, 4]) }),
|
||||
("TSFunctionType", StructDetails { field_order: Some(&[5, 0, 1, 2, 3, 4, 6]) }),
|
||||
("VariableDeclarator", StructDetails { field_order: Some(&[4, 0, 5, 1, 2, 3, 6]) }),
|
||||
("TSClassImplements", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("BreakStatement", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("TSConstructorType", StructDetails { field_order: Some(&[1, 0, 6, 3, 4, 5, 2]) }),
|
||||
("TSCallSignatureDeclaration", StructDetails { field_order: Some(&[1, 0, 3, 4, 5, 6, 2]) }),
|
||||
("ExportDefaultDeclaration", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("TSGlobalDeclaration", StructDetails { field_order: Some(&[1, 0, 3, 4, 5, 2]) }),
|
||||
("TSFunctionType", StructDetails { field_order: Some(&[1, 0, 3, 4, 5, 6, 2]) }),
|
||||
("VariableDeclarator", StructDetails { field_order: Some(&[1, 0, 2, 4, 5, 6, 3]) }),
|
||||
("StaticExport", StructDetails { field_order: None }),
|
||||
("MetaProperty", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("TSInterfaceHeritage", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("MetaProperty", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("TSInterfaceHeritage", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("CharacterClassRange", StructDetails { field_order: None }),
|
||||
("LogicalExpression", StructDetails { field_order: Some(&[3, 0, 1, 4, 2]) }),
|
||||
("LogicalExpression", StructDetails { field_order: Some(&[1, 0, 3, 2, 4]) }),
|
||||
("TSBigIntKeyword", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("TSConditionalType", StructDetails { field_order: Some(&[5, 0, 1, 2, 3, 4, 6]) }),
|
||||
("TSConditionalType", StructDetails { field_order: Some(&[1, 0, 3, 4, 5, 6, 2]) }),
|
||||
("CapturingGroup", StructDetails { field_order: None }),
|
||||
("JSXOpeningElement", StructDetails { field_order: Some(&[4, 0, 1, 2, 3]) }),
|
||||
("ImportExpression", StructDetails { field_order: Some(&[3, 0, 1, 2, 4]) }),
|
||||
("ImportDefaultSpecifier", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("JSXOpeningElement", StructDetails { field_order: Some(&[1, 0, 2, 3, 4]) }),
|
||||
("ImportExpression", StructDetails { field_order: Some(&[1, 0, 3, 4, 2]) }),
|
||||
("ImportDefaultSpecifier", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("Pattern", StructDetails { field_order: None }),
|
||||
("FormalParameterRest", StructDetails { field_order: Some(&[4, 0, 1, 2, 3]) }),
|
||||
("TSImportType", StructDetails { field_order: Some(&[5, 0, 1, 2, 3, 4]) }),
|
||||
("FormalParameter", StructDetails { field_order: Some(&[5, 0, 1, 2, 3, 4, 6, 7, 8, 9]) }),
|
||||
("FormalParameterRest", StructDetails { field_order: Some(&[1, 0, 2, 3, 4]) }),
|
||||
("TSImportType", StructDetails { field_order: Some(&[1, 0, 2, 3, 4, 5]) }),
|
||||
("FormalParameter", StructDetails { field_order: Some(&[1, 0, 6, 7, 8, 9, 2, 3, 4, 5]) }),
|
||||
("TemplateElementValue", StructDetails { field_order: None }),
|
||||
("TSThisParameter", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("RegExpLiteral", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("TSThisParameter", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("RegExpLiteral", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("RegExpFlags", StructDetails { field_order: None }),
|
||||
("TSSatisfiesExpression", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("ClassBody", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSSatisfiesExpression", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("ClassBody", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("ClassStringDisjunction", StructDetails { field_order: Some(&[0, 2, 1]) }),
|
||||
(
|
||||
"TSMethodSignature",
|
||||
StructDetails { field_order: Some(&[6, 0, 1, 8, 9, 10, 2, 3, 4, 5, 7]) },
|
||||
StructDetails { field_order: Some(&[1, 0, 3, 8, 9, 10, 4, 5, 6, 7, 2]) },
|
||||
),
|
||||
("WhileStatement", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("JSXIdentifier", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("WhileStatement", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("JSXIdentifier", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
(
|
||||
"ArrowFunctionExpression",
|
||||
StructDetails { field_order: Some(&[5, 0, 7, 8, 1, 2, 3, 4, 6, 9, 10]) },
|
||||
StructDetails { field_order: Some(&[1, 0, 7, 8, 3, 4, 5, 6, 2, 9, 10]) },
|
||||
),
|
||||
("Alternative", StructDetails { field_order: None }),
|
||||
("TSArrayType", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("PrivateFieldExpression", StructDetails { field_order: Some(&[3, 0, 1, 2, 4]) }),
|
||||
("ExportNamedDeclaration", StructDetails { field_order: Some(&[5, 0, 1, 2, 3, 6, 4]) }),
|
||||
("Directive", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("TryStatement", StructDetails { field_order: Some(&[4, 0, 1, 2, 3]) }),
|
||||
("AwaitExpression", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("StaticBlock", StructDetails { field_order: Some(&[2, 0, 1, 3]) }),
|
||||
("TSTypeAliasDeclaration", StructDetails { field_order: Some(&[4, 0, 1, 2, 3, 6, 5]) }),
|
||||
("VariableDeclaration", StructDetails { field_order: Some(&[2, 0, 3, 1, 4]) }),
|
||||
("TSExportAssignment", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("JSDocNonNullableType", StructDetails { field_order: Some(&[2, 0, 1, 3]) }),
|
||||
("TSArrayType", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("PrivateFieldExpression", StructDetails { field_order: Some(&[1, 0, 3, 4, 2]) }),
|
||||
("ExportNamedDeclaration", StructDetails { field_order: Some(&[1, 0, 3, 4, 5, 2, 6]) }),
|
||||
("Directive", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("TryStatement", StructDetails { field_order: Some(&[1, 0, 2, 3, 4]) }),
|
||||
("AwaitExpression", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("StaticBlock", StructDetails { field_order: Some(&[1, 0, 3, 2]) }),
|
||||
("TSTypeAliasDeclaration", StructDetails { field_order: Some(&[1, 0, 3, 4, 5, 6, 2]) }),
|
||||
("VariableDeclaration", StructDetails { field_order: Some(&[1, 0, 2, 4, 3]) }),
|
||||
("TSExportAssignment", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("JSDocNonNullableType", StructDetails { field_order: Some(&[1, 0, 3, 2]) }),
|
||||
("FixedSizeAllocatorMetadata", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("TSNonNullExpression", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("BinaryExpression", StructDetails { field_order: Some(&[3, 0, 1, 4, 2]) }),
|
||||
("TSNamespaceExportDeclaration", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSNonNullExpression", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("BinaryExpression", StructDetails { field_order: Some(&[1, 0, 3, 2, 4]) }),
|
||||
("TSNamespaceExportDeclaration", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("BooleanLiteral", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
(
|
||||
"TSConstructSignatureDeclaration",
|
||||
StructDetails { field_order: Some(&[4, 0, 1, 2, 3, 5]) },
|
||||
StructDetails { field_order: Some(&[1, 0, 3, 4, 5, 2]) },
|
||||
),
|
||||
("FormalParameters", StructDetails { field_order: Some(&[3, 0, 4, 1, 2]) }),
|
||||
("FormalParameters", StructDetails { field_order: Some(&[1, 0, 2, 3, 4]) }),
|
||||
(
|
||||
"Function",
|
||||
StructDetails {
|
||||
field_order: Some(&[7, 0, 9, 1, 10, 11, 12, 2, 3, 4, 5, 6, 8, 13, 14]),
|
||||
field_order: Some(&[1, 0, 9, 3, 10, 11, 12, 4, 5, 6, 7, 8, 2, 13, 14]),
|
||||
},
|
||||
),
|
||||
("TSNullKeyword", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("Elision", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("TSIndexSignature", StructDetails { field_order: Some(&[3, 0, 1, 2, 4, 5]) }),
|
||||
("TSIndexSignatureName", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("TSIndexSignature", StructDetails { field_order: Some(&[1, 0, 4, 5, 2, 3]) }),
|
||||
("TSIndexSignatureName", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("Super", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("Quantifier", StructDetails { field_order: Some(&[0, 1, 2, 4, 3]) }),
|
||||
("ObjectPattern", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("ObjectPattern", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("DynamicImport", StructDetails { field_order: None }),
|
||||
("TSBooleanKeyword", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("TSParenthesizedType", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSParenthesizedType", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("NameSpan", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("ComputedMemberExpression", StructDetails { field_order: Some(&[3, 0, 1, 2, 4]) }),
|
||||
("YieldExpression", StructDetails { field_order: Some(&[2, 0, 3, 1]) }),
|
||||
("TSTypeAnnotation", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("JSXMemberExpression", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("TSImportEqualsDeclaration", StructDetails { field_order: Some(&[3, 0, 1, 2, 4]) }),
|
||||
("ComputedMemberExpression", StructDetails { field_order: Some(&[1, 0, 3, 4, 2]) }),
|
||||
("YieldExpression", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("TSTypeAnnotation", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("JSXMemberExpression", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("TSImportEqualsDeclaration", StructDetails { field_order: Some(&[1, 0, 3, 4, 2]) }),
|
||||
("TSVoidKeyword", StructDetails { field_order: Some(&[1, 0]) }),
|
||||
("SequenceExpression", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("ExportSpecifier", StructDetails { field_order: Some(&[3, 0, 1, 2, 4]) }),
|
||||
("TSTypeParameterDeclaration", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("BindingIdentifier", StructDetails { field_order: Some(&[2, 0, 1, 3]) }),
|
||||
("JSXClosingElement", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("SequenceExpression", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("ExportSpecifier", StructDetails { field_order: Some(&[1, 0, 3, 4, 2]) }),
|
||||
("TSTypeParameterDeclaration", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("BindingIdentifier", StructDetails { field_order: Some(&[1, 0, 3, 2]) }),
|
||||
("JSXClosingElement", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("CommentNodeId", StructDetails { field_order: None }),
|
||||
("TSExternalModuleReference", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSInstantiationExpression", StructDetails { field_order: Some(&[3, 0, 1, 2]) }),
|
||||
("ExpressionStatement", StructDetails { field_order: Some(&[2, 0, 1]) }),
|
||||
("TSExternalModuleReference", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("TSInstantiationExpression", StructDetails { field_order: Some(&[1, 0, 2, 3]) }),
|
||||
("ExpressionStatement", StructDetails { field_order: Some(&[1, 0, 2]) }),
|
||||
("NonMaxU32", StructDetails { field_order: None }),
|
||||
],
|
||||
};
|
||||
@@ -54,22 +54,22 @@ export const PROGRAM_OFFSET = 0;
|
||||
/**
|
||||
* Byte offset of pointer to start of source text, relative to start of `Program`.
|
||||
*/
|
||||
export const SOURCE_START_OFFSET = 8;
|
||||
export const SOURCE_START_OFFSET = 16;
|
||||
|
||||
/**
|
||||
* Byte offset of length of source text, relative to start of `Program`.
|
||||
*/
|
||||
export const SOURCE_LEN_OFFSET = 16;
|
||||
export const SOURCE_LEN_OFFSET = 24;
|
||||
|
||||
/**
|
||||
* Byte offset of comments `Vec` pointer, relative to start of `Program`.
|
||||
*/
|
||||
export const COMMENTS_OFFSET = 24;
|
||||
export const COMMENTS_OFFSET = 32;
|
||||
|
||||
/**
|
||||
* Byte offset of comments `Vec` length, relative to start of `Program`.
|
||||
*/
|
||||
export const COMMENTS_LEN_OFFSET = 32;
|
||||
export const COMMENTS_LEN_OFFSET = 40;
|
||||
|
||||
/**
|
||||
* Size of `Comment` struct in bytes.
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -6,7 +6,7 @@
|
||||
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
cmp::{Ordering, max, min},
|
||||
cmp::{max, min},
|
||||
num,
|
||||
sync::atomic,
|
||||
};
|
||||
@@ -55,13 +55,17 @@ impl Generator for AssertLayouts {
|
||||
struct LayoutCalculator<'s> {
|
||||
schema: &'s mut Schema,
|
||||
span_type_id: TypeId,
|
||||
node_id_cell_type_id: TypeId,
|
||||
}
|
||||
|
||||
impl LayoutCalculator<'_> {
|
||||
/// Calculate layouts of all types.
|
||||
fn calculate(schema: &mut Schema) {
|
||||
let span_type_id = schema.type_names["Span"];
|
||||
let mut calculator = LayoutCalculator { schema, span_type_id };
|
||||
let node_id_cell_type_id =
|
||||
schema.type_by_name("NodeId").as_primitive().unwrap().containers.cell_id.unwrap();
|
||||
|
||||
let mut calculator = LayoutCalculator { schema, span_type_id, node_id_cell_type_id };
|
||||
|
||||
for type_id in calculator.schema.types.indices() {
|
||||
calculator.calculate_type(type_id);
|
||||
@@ -130,7 +134,103 @@ impl LayoutCalculator<'_> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct StructState<'s> {
|
||||
layout_64: PlatformLayout,
|
||||
layout_32: PlatformLayout,
|
||||
struct_def: &'s mut StructDef,
|
||||
current_align_64: u32,
|
||||
current_align_32: u32,
|
||||
}
|
||||
|
||||
struct FieldData {
|
||||
index: usize,
|
||||
layout: Layout,
|
||||
priority: u64,
|
||||
}
|
||||
|
||||
const MAX_ALIGN: u32 = 1 << 31;
|
||||
|
||||
impl<'s> StructState<'s> {
|
||||
fn new(struct_def: &'s mut StructDef) -> Self {
|
||||
Self {
|
||||
layout_64: PlatformLayout::from_size_align(0, 1),
|
||||
layout_32: PlatformLayout::from_size_align(0, 1),
|
||||
struct_def,
|
||||
current_align_64: MAX_ALIGN,
|
||||
current_align_32: MAX_ALIGN,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_field(&mut self, field_data: &FieldData) {
|
||||
let struct_name = self.struct_def.name();
|
||||
let offset_64 = Self::update(
|
||||
&mut self.layout_64,
|
||||
&field_data.layout.layout_64,
|
||||
&mut self.current_align_64,
|
||||
struct_name,
|
||||
);
|
||||
let offset_32 = Self::update(
|
||||
&mut self.layout_32,
|
||||
&field_data.layout.layout_32,
|
||||
&mut self.current_align_32,
|
||||
struct_name,
|
||||
);
|
||||
|
||||
// Store offset on `field`
|
||||
let field = &mut self.struct_def.fields[field_data.index];
|
||||
field.offset = Offset { offset_64, offset_32 };
|
||||
}
|
||||
|
||||
fn update(
|
||||
layout: &mut PlatformLayout,
|
||||
field_layout: &PlatformLayout,
|
||||
current_align: &mut u32,
|
||||
struct_name: &str,
|
||||
) -> u32 {
|
||||
// Check alignment is correct for this field
|
||||
let offset = layout.size;
|
||||
assert!(
|
||||
offset.is_multiple_of(field_layout.align),
|
||||
"Incorrect alignment for struct fields in `{struct_name}`"
|
||||
);
|
||||
|
||||
// Update alignment
|
||||
layout.align = max(layout.align, field_layout.align);
|
||||
|
||||
// Update niche.
|
||||
// Take the largest niche. Preference for (in order):
|
||||
// * Largest single range of niche values.
|
||||
// * Largest number of niche values at start of range.
|
||||
// * Earlier field (earlier after re-ordering).
|
||||
if let Some(field_niche) = &field_layout.niche
|
||||
&& layout.niche.as_ref().is_none_or(|niche| {
|
||||
field_niche.count_max() > niche.count_max()
|
||||
|| (field_niche.count_max() == niche.count_max()
|
||||
&& field_niche.count_start > niche.count_start)
|
||||
})
|
||||
{
|
||||
let mut niche = field_niche.clone();
|
||||
niche.offset += offset;
|
||||
layout.niche = Some(niche);
|
||||
}
|
||||
|
||||
// Next field starts after this one
|
||||
if field_layout.size > 0 {
|
||||
let next_offset = offset + field_layout.size;
|
||||
layout.size = next_offset;
|
||||
|
||||
// Get highest alignment next field can have
|
||||
*current_align = next_offset & next_offset.wrapping_neg();
|
||||
}
|
||||
|
||||
// Return offset of this field
|
||||
offset
|
||||
}
|
||||
}
|
||||
|
||||
impl LayoutCalculator<'_> {
|
||||
/// Calculate layout for a struct.
|
||||
///
|
||||
/// All structs in AST are `#[repr(C)]`. In a `#[repr(C)]` struct, compiler does not re-order the fields,
|
||||
@@ -152,11 +252,13 @@ impl LayoutCalculator<'_> {
|
||||
///
|
||||
/// Fields are ordered according to the following rules, in order:
|
||||
///
|
||||
/// 1. If field is `span: Span` it goes first.
|
||||
/// 2. If field is ZST, it goes last.
|
||||
/// 3. Fields with higher alignment on 64-bit systems go first.
|
||||
/// 4. Fields with higher alignment on 32-bit systems go first.
|
||||
/// 5. Otherwise, retain original field order.
|
||||
/// 1. `span: Span` goes first.
|
||||
/// 2. `node_id: Cell<NodeId>` goes next.
|
||||
/// 3. ZST fields go last.
|
||||
/// 4. Fields with higher alignment on 64-bit systems go first.
|
||||
/// 5. Fields with higher alignment on 32-bit systems go first.
|
||||
/// 6. If the highest-aligned field cannot go next, take the next field which has suitable alignment.
|
||||
/// 7. Otherwise, retain original field order.
|
||||
///
|
||||
/// This ordering scheme does not match `#[repr(Rust)]`, but is equally efficient in terms of packing
|
||||
/// structs into as few bytes as possible.
|
||||
@@ -167,6 +269,8 @@ impl LayoutCalculator<'_> {
|
||||
///
|
||||
/// `span: Span` is always first to make `Expression::get_span` etc branchless, because the `span` field
|
||||
/// is in the same position for all of `Expression`'s variants.
|
||||
/// `node_id: Cell<NodeId>` goes after `span: Span` for the same reason - so it has consistent position
|
||||
/// in all AST structs, which makes `AstKind::node_id` and `AstKind::set_node_id` branchless.
|
||||
///
|
||||
/// Ordering by 64-bit alignment first, then 32-alignment creates a layout that is optimally packed
|
||||
/// on both platforms. Fields will be ordered `u64`, `usize`, `u32`, so `usize` will have same alignment
|
||||
@@ -180,97 +284,91 @@ impl LayoutCalculator<'_> {
|
||||
/// If they did, this would screw up sorting the fields in `generate_struct_details`.
|
||||
fn calculate_struct(&mut self, type_id: TypeId) -> Layout {
|
||||
// Get layout of fields' types and calculate optimal field order
|
||||
struct FieldData {
|
||||
index: usize,
|
||||
layout: Layout,
|
||||
is_span: bool,
|
||||
is_zst: bool,
|
||||
}
|
||||
let mut zst_fields = vec![];
|
||||
|
||||
let mut field_order = self
|
||||
let mut fields = self
|
||||
.schema
|
||||
.struct_def(type_id)
|
||||
.field_indices()
|
||||
.map(|index| {
|
||||
.filter_map(|index| {
|
||||
let field = &self.schema.struct_def(type_id).fields[index];
|
||||
let is_span = field.type_id == self.span_type_id && field.name() == "span";
|
||||
let layout = self.calculate_type(field.type_id);
|
||||
let is_zst = layout.layout_64.size == 0 && layout.layout_32.size == 0;
|
||||
FieldData { index, layout: layout.clone(), is_span, is_zst }
|
||||
let layout = self.calculate_type(field.type_id).clone();
|
||||
|
||||
if layout.layout_64.size == 0 || layout.layout_32.size == 0 {
|
||||
assert!(
|
||||
layout.layout_64.size == 0 && layout.layout_32.size == 0,
|
||||
"ZST field must have 0 size on all platforms"
|
||||
);
|
||||
zst_fields.push(FieldData { index, layout, priority: 0 });
|
||||
return None;
|
||||
}
|
||||
|
||||
let field = &self.schema.struct_def(type_id).fields[index];
|
||||
let priority = if field.type_id == self.span_type_id && field.name() == "span" {
|
||||
// Highest priority
|
||||
u64::MAX
|
||||
} else if field.type_id == self.node_id_cell_type_id && field.name() == "node_id" {
|
||||
// 2nd highest priority
|
||||
u64::MAX - 1
|
||||
} else {
|
||||
// Prioritize fields with higher alignment on 64-bit systems, then 32-bit systems
|
||||
(u64::from(layout.layout_64.align) << 32) | u64::from(layout.layout_32.align)
|
||||
};
|
||||
|
||||
Some(FieldData { index, layout, priority })
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
field_order.sort_unstable_by(|f1, f2| {
|
||||
let mut order = f1.is_span.cmp(&f2.is_span).reverse();
|
||||
if order == Ordering::Equal {
|
||||
order = f1.is_zst.cmp(&f2.is_zst);
|
||||
if order == Ordering::Equal {
|
||||
order = f1.layout.layout_64.align.cmp(&f2.layout.layout_64.align).reverse();
|
||||
if order == Ordering::Equal {
|
||||
order = f1.layout.layout_32.align.cmp(&f2.layout.layout_32.align).reverse();
|
||||
if order == Ordering::Equal {
|
||||
order = f1.index.cmp(&f2.index);
|
||||
}
|
||||
}
|
||||
fields.sort_by(|f1, f2| f1.priority.cmp(&f2.priority).reverse());
|
||||
|
||||
// Add fields (except ZST fields)
|
||||
let mut state = StructState::new(self.schema.struct_def_mut(type_id));
|
||||
|
||||
while !fields.is_empty() {
|
||||
// Find next field with alignment <= current alignment for both 32 bit and 64 bit.
|
||||
// `other_fields` is sorted by alignment in descending order,
|
||||
// so this will pick the next field with largest alignment which can be placed at current offset.
|
||||
let index = fields.iter().position(|f| {
|
||||
f.layout.layout_64.align <= state.current_align_64
|
||||
&& f.layout.layout_32.align <= state.current_align_32
|
||||
});
|
||||
|
||||
if let Some(index) = index {
|
||||
// Found field with suitable alignment - add it to struct
|
||||
let field_data = fields.remove(index);
|
||||
state.add_field(&field_data);
|
||||
} else {
|
||||
// No field with suitable alignment found.
|
||||
// Double desired alignment, and add padding so it's aligned.
|
||||
// Go round loop again to find next field which satisfies new looser alignment requirements.
|
||||
let smallest_align_64 = fields.last().unwrap().layout.layout_64.align;
|
||||
if state.current_align_64 < smallest_align_64 {
|
||||
// No field meets alignment requirement for 64 bit
|
||||
state.current_align_64 *= 2;
|
||||
state.layout_64.size =
|
||||
state.layout_64.size.next_multiple_of(state.current_align_64);
|
||||
} else {
|
||||
// No field meets alignment requirement for 32 bit
|
||||
state.current_align_32 *= 2;
|
||||
state.layout_32.size =
|
||||
state.layout_32.size.next_multiple_of(state.current_align_32);
|
||||
}
|
||||
}
|
||||
order
|
||||
});
|
||||
}
|
||||
|
||||
// Calculate offset of each field, and size + alignment of struct
|
||||
let mut layout_64 = PlatformLayout::from_size_align(0, 1);
|
||||
let mut layout_32 = PlatformLayout::from_size_align(0, 1);
|
||||
// Add ZST fields last, in original order.
|
||||
// Order of ZSTs doesn't matter, but keeping in original order is relied on by `generate_struct_details`.
|
||||
let StructState { mut layout_64, mut layout_32, struct_def, .. } = state;
|
||||
|
||||
let struct_def = self.schema.struct_def_mut(type_id);
|
||||
for field_data in &field_order {
|
||||
fn update(
|
||||
layout: &mut PlatformLayout,
|
||||
field_layout: &PlatformLayout,
|
||||
struct_name: &str,
|
||||
) -> u32 {
|
||||
// Field should already be aligned as we've re-ordered fields to ensure they're tightly packed.
|
||||
// This shouldn't break as long as all fields are aligned on `< 16`.
|
||||
// If we introduce a `u128` into AST, we might need to change the field ordering algorithm
|
||||
// to fill in the gap between `span` and the `u128` field.
|
||||
let offset = layout.size;
|
||||
assert!(
|
||||
offset.is_multiple_of(field_layout.align),
|
||||
"Incorrect alignment for struct fields in `{struct_name}`"
|
||||
);
|
||||
|
||||
// Update alignment
|
||||
layout.align = max(layout.align, field_layout.align);
|
||||
|
||||
// Update niche.
|
||||
// Take the largest niche. Preference for (in order):
|
||||
// * Largest single range of niche values.
|
||||
// * Largest number of niche values at start of range.
|
||||
// * Earlier field (earlier after re-ordering).
|
||||
if let Some(field_niche) = &field_layout.niche
|
||||
&& layout.niche.as_ref().is_none_or(|niche| {
|
||||
field_niche.count_max() > niche.count_max()
|
||||
|| (field_niche.count_max() == niche.count_max()
|
||||
&& field_niche.count_start > niche.count_start)
|
||||
})
|
||||
{
|
||||
let mut niche = field_niche.clone();
|
||||
niche.offset += offset;
|
||||
layout.niche = Some(niche);
|
||||
}
|
||||
|
||||
// Next field starts after this one
|
||||
layout.size = offset + field_layout.size;
|
||||
|
||||
// Return offset of this field
|
||||
offset
|
||||
for field_data in &zst_fields {
|
||||
fn update(layout: &mut PlatformLayout, align: u32) -> u32 {
|
||||
layout.size = layout.size.next_multiple_of(align);
|
||||
layout.align = max(layout.align, align);
|
||||
layout.size
|
||||
}
|
||||
|
||||
let offset_64 = update(&mut layout_64, &field_data.layout.layout_64, struct_def.name());
|
||||
let offset_32 = update(&mut layout_32, &field_data.layout.layout_32, struct_def.name());
|
||||
|
||||
// Store offset on `field`
|
||||
let field = &mut struct_def.fields[field_data.index];
|
||||
field.offset = Offset { offset_64, offset_32 };
|
||||
let offset_64 = update(&mut layout_64, field_data.layout.layout_64.align);
|
||||
let offset_32 = update(&mut layout_32, field_data.layout.layout_32.align);
|
||||
struct_def.fields[field_data.index].offset = Offset { offset_64, offset_32 };
|
||||
}
|
||||
|
||||
// Round up size to alignment
|
||||
|
||||
@@ -190,6 +190,7 @@ impl Generator for AstKindGenerator {
|
||||
|
||||
///@@line_break
|
||||
/// Get [`NodeId`] of an [`AstKind`].
|
||||
///@ `node_id` field is in consistent position in all AST structs, so this boils down to 1 instruction.
|
||||
#[inline]
|
||||
pub fn node_id(&self) -> NodeId {
|
||||
match self {
|
||||
@@ -199,11 +200,8 @@ impl Generator for AstKindGenerator {
|
||||
|
||||
///@@line_break
|
||||
/// Set [`NodeId`] of an [`AstKind`].
|
||||
#[expect(
|
||||
clippy::inline_always,
|
||||
reason = "enables compile-time match elimination in semantic builder"
|
||||
)]
|
||||
#[inline(always)]
|
||||
///@ `node_id` field is in consistent position in all AST structs, so this boils down to 1 instruction.
|
||||
#[inline]
|
||||
pub fn set_node_id(&self, node_id: NodeId) {
|
||||
match self {
|
||||
#set_node_id_match_arms
|
||||
|
||||
Reference in new issue
Block a user