From 97c557eb04ab94ff8aa837722b7750aa8e54dcf4 Mon Sep 17 00:00:00 2001 From: Benedikt Meurer Date: Mon, 4 Feb 2019 14:39:29 +0100 Subject: [PATCH] Make modifierFlagsCache mandatory for Node objects The `modifierFlagsCache` property is among the top properties that cause megamorphic stub cache misses when having `tsc` build itself. This is because it's added sort of randomly to a whole lot of different objects, at arbitrary points after their initialization. This also means that `modifierFlagsCache` is often not present on the instances, which means that when missing on the megamorphic stub cache, Node/V8 has to compute `NonExistent` handlers for the relevant inline caches. It's a lot cheaper to just make sure that the property is always existent on the instance, and ideally also at the same offset. This change ensures exactly that. Drive-by-fix: Also make sure that `transformFlags` (and `parent`) is always at the same offset for `Node` objects. --- src/compiler/types.ts | 2 +- src/services/services.ts | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ff5ce74d31d..030926d969a 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -609,7 +609,7 @@ namespace ts { export interface Node extends TextRange { kind: SyntaxKind; flags: NodeFlags; - /* @internal */ modifierFlagsCache?: ModifierFlags; + /* @internal */ modifierFlagsCache: ModifierFlags; /* @internal */ transformFlags: TransformFlags; // Flags for transforms, possibly undefined decorators?: NodeArray; // Array of decorators (in document order) modifiers?: ModifiersArray; // Array of modifiers diff --git a/src/services/services.ts b/src/services/services.ts index 6a63497d7e6..7f8e2aa45d3 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -16,17 +16,19 @@ namespace ts { public pos: number; public end: number; public flags: NodeFlags; + public modifierFlagsCache: ModifierFlags; + public transformFlags: TransformFlags; public parent: Node; public symbol!: Symbol; // Actually optional, but it was too annoying to access `node.symbol!` everywhere since in many cases we know it must be defined public jsDoc?: JSDoc[]; public original?: Node; - public transformFlags: TransformFlags; private _children: Node[] | undefined; constructor(kind: SyntaxKind, pos: number, end: number) { this.pos = pos; this.end = end; this.flags = NodeFlags.None; + this.modifierFlagsCache = ModifierFlags.None; this.transformFlags = undefined!; // TODO: GH#18217 this.parent = undefined!; this.kind = kind; @@ -200,16 +202,19 @@ namespace ts { public pos: number; public end: number; public flags: NodeFlags; + public modifierFlagsCache: ModifierFlags; + public transformFlags: TransformFlags; public parent: Node; public symbol!: Symbol; public jsDocComments?: JSDoc[]; - public transformFlags!: TransformFlags; constructor(pos: number, end: number) { // Set properties in same order as NodeObject this.pos = pos; this.end = end; this.flags = NodeFlags.None; + this.modifierFlagsCache = ModifierFlags.None; + this.transformFlags = undefined!; // TODO: GH#18217 this.parent = undefined!; }