Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions _scripts/generate-go-ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,15 @@ function generateNodeFactoryStruct(w: CodeWriter) {
w.pop();
w.write("}");
w.write("");

w.write("func (f *NodeFactory) ReleaseArenas() {")
w.push();
for (const { fieldName } of arenaFields) {
w.write(`f.${fieldName}.Release()`);
}
w.pop();
w.write("}");
w.write("");
}

function generateHeader(w: CodeWriter) {
Expand Down
51 changes: 51 additions & 0 deletions internal/ast/ast_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions internal/checker/nodebuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,12 +285,15 @@ func NewNodeBuilderEx(ch *Checker, e *printer.EmitContext, idToSymbol map[*ast.I
return &NodeBuilder{impl: impl, ctxStack: make([]*NodeBuilderContext, 0, 1), host: ch.program}
}

func (c *Checker) getNodeBuilder() *NodeBuilder {
func (c *Checker) getNodeBuilder() (*NodeBuilder, func()) {
releaseNodes := func() {
c.typeToStringNodebuilder.EmitContext().Factory.ReleaseArenas() // Allow any allocated nodes to be freed if they're no longer in a cache
}
if c.typeToStringNodebuilder != nil {
return c.typeToStringNodebuilder
return c.typeToStringNodebuilder, releaseNodes
}
c.typeToStringNodebuilder = c.getNodeBuilderEx(nil /*idToSymbol*/)
return c.typeToStringNodebuilder
return c.typeToStringNodebuilder, releaseNodes
}

func (c *Checker) getNodeBuilderEx(idToSymbol map[*ast.IdentifierNode]*ast.Symbol) *NodeBuilder {
Expand Down
25 changes: 18 additions & 7 deletions internal/checker/printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ func (c *Checker) typeToStringEx(t *Type, enclosingDeclaration *ast.Node, flags
if noTruncation {
combinedFlags = combinedFlags | nodebuilder.FlagsNoTruncation
}
nodeBuilder := c.getNodeBuilder()
nodeBuilder, release := c.getNodeBuilder()
defer release()
if vc != nil {
nodeBuilder.verbosity = vc
}
Comment on lines 202 to 204
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gabritto @RyanCavanaugh I'm pretty sure this copilot comment just picked up on the fix for #4010 (unrelated to this PR though)

Expand Down Expand Up @@ -270,7 +271,8 @@ func (c *Checker) symbolToStringEx(symbol *ast.Symbol, enclosingDeclaration *ast
internalNodeFlags |= nodebuilder.InternalFlagsWriteComputedProps
}

nodeBuilder := c.getNodeBuilder()
nodeBuilder, release := c.getNodeBuilder()
defer release()
var sourceFile *ast.SourceFile
if enclosingDeclaration != nil {
sourceFile = ast.GetSourceFileOfNode(enclosingDeclaration)
Expand Down Expand Up @@ -319,7 +321,8 @@ func (c *Checker) signatureToStringEx(signature *Signature, enclosingDeclaration
}
}

nodeBuilder := c.getNodeBuilder()
nodeBuilder, release := c.getNodeBuilder()
defer release()
if vc != nil {
nodeBuilder.verbosity = vc
}
Comment on lines 326 to 328
Expand Down Expand Up @@ -348,7 +351,8 @@ func (c *Checker) typePredicateToString(typePredicate *TypePredicate) string {
func (c *Checker) typePredicateToStringEx(typePredicate *TypePredicate, enclosingDeclaration *ast.Node, flags TypeFormatFlags) string {
writer, putWriter := printer.GetSingleLineStringWriter()
defer putWriter()
nodeBuilder := c.getNodeBuilder()
nodeBuilder, release := c.getNodeBuilder()
defer release()
combinedFlags := toNodeBuilderFlags(flags) | nodebuilder.FlagsIgnoreErrors | nodebuilder.FlagsWriteTypeParametersInQualifiedName
predicate := nodeBuilder.TypePredicateToTypePredicateNode(typePredicate, enclosingDeclaration, combinedFlags, nodebuilder.InternalFlagsNone, nil) // TODO: GH#18217
printer_ := createPrinterWithRemoveComments(nodeBuilder.EmitContext())
Expand Down Expand Up @@ -405,13 +409,17 @@ func (c *Checker) TypeToTypeNode(t *Type, enclosingDeclaration *ast.Node, flags
}

func (c *Checker) SignatureToSignatureDeclaration(signature *Signature, kind ast.Kind, enclosingDeclaration *ast.Node, flags nodebuilder.Flags) *ast.Node {
nodeBuilder := c.getNodeBuilder()
nodeBuilder, release := c.getNodeBuilder()
defer release()
return nodeBuilder.SignatureToSignatureDeclaration(signature, kind, enclosingDeclaration, flags, nodebuilder.InternalFlagsNone, nil)
}

// ExpandSymbolForHover produces declaration strings for a symbol with verbosity support for expandable hover.
func (c *Checker) ExpandSymbolForHover(symbol *ast.Symbol, meaning ast.SymbolFlags, vc *VerbosityContext) string {
nodeBuilder := c.getNodeBuilder()
nodeBuilder, release := c.getNodeBuilder()
defer release()
oldVerbosity := nodeBuilder.verbosity
defer func() { nodeBuilder.verbosity = oldVerbosity }()
nodeBuilder.verbosity = vc
nodes := nodeBuilder.ExpandSymbolForHover(symbol, meaning)
if len(nodes) == 0 {
Expand All @@ -434,7 +442,10 @@ func (c *Checker) ExpandSymbolForHover(symbol *ast.Symbol, meaning ast.SymbolFla

// TypeParameterToStringEx renders a type parameter declaration (e.g. "T extends Foo") with optional verbosity support.
func (c *Checker) TypeParameterToStringEx(t *Type, enclosingDeclaration *ast.Node, vc *VerbosityContext) string {
nodeBuilder := c.getNodeBuilder()
nodeBuilder, release := c.getNodeBuilder()
defer release()
oldVerbosity := nodeBuilder.verbosity
defer func() { nodeBuilder.verbosity = oldVerbosity }()
nodeBuilder.verbosity = vc
typeParamNode := nodeBuilder.TypeParameterToDeclaration(t, enclosingDeclaration, nodebuilder.FlagsIgnoreErrors, nodebuilder.InternalFlagsNone, nil)
if typeParamNode == nil {
Expand Down
5 changes: 5 additions & 0 deletions internal/core/arena.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ func (a *Arena[T]) Clone(t []T) []T {
return slice
}

// Reset arena back to zero, removing GC refs between the arena and any objects in the arena, allowing them to be freed
func (a *Arena[T]) Release() {
a.data = nil
}

func nextArenaSize(size int) int {
// This compiles down branch-free.
size = max(size, 1)
Expand Down
Loading