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.
This commit is contained in:
Benedikt Meurer 2019-02-04 14:39:29 +01:00
parent 4d85acb387
commit 97c557eb04
2 changed files with 8 additions and 3 deletions

View file

@ -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<Decorator>; // Array of decorators (in document order)
modifiers?: ModifiersArray; // Array of modifiers

View file

@ -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!;
}