Merge pull request #9348 from danez/perf

Parser Performance Collection
This commit is contained in:
Daniel Tschinder
2019-01-21 02:27:42 -08:00
committed by GitHub
24 changed files with 456 additions and 346 deletions

View File

@@ -1124,7 +1124,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node.types = [];
this.expect(tt.bracketL);
// We allow trailing commas
while (this.state.pos < this.input.length && !this.match(tt.bracketR)) {
while (this.state.pos < this.state.length && !this.match(tt.bracketR)) {
node.types.push(this.flowParseType());
if (this.match(tt.bracketR)) break;
this.expect(tt.comma);
@@ -1190,9 +1190,6 @@ export default (superClass: Class<Parser>): Class<Parser> =>
case "any":
return this.finishNode(node, "AnyTypeAnnotation");
case "void":
return this.finishNode(node, "VoidTypeAnnotation");
case "bool":
case "boolean":
return this.finishNode(node, "BooleanTypeAnnotation");
@@ -1369,6 +1366,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
"NumberLiteralTypeAnnotation",
);
case tt._void:
this.next();
return this.finishNode(node, "VoidTypeAnnotation");
case tt._null:
this.next();
return this.finishNode(node, "NullLiteralTypeAnnotation");
@@ -1398,7 +1399,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
const startPos = this.state.start,
startLoc = this.state.startLoc;
let type = this.flowParsePrimaryType();
while (!this.canInsertSemicolon() && this.match(tt.bracketL)) {
while (this.match(tt.bracketL) && !this.canInsertSemicolon()) {
const node = this.startNodeAt(startPos, startLoc);
node.elementType = type;
this.expect(tt.bracketL);
@@ -1630,7 +1631,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
this.match(tt.name) &&
(this.state.value === "type" ||
this.state.value === "interface" ||
this.state.value == "opaque")
this.state.value === "opaque")
) {
return false;
}
@@ -1922,20 +1923,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
}
// don't consider `void` to be a keyword as then it'll use the void token type
// and set startExpr
isKeyword(name: string): boolean {
if (this.state.inType && name === "void") {
return false;
} else {
return super.isKeyword(name);
}
}
// ensure that inside flow types, we bypass the jsx parser plugin
readToken(code: number): void {
const next = this.input.charCodeAt(this.state.pos + 1);
if (
getTokenFromCode(code: number): void {
const next = this.state.input.charCodeAt(this.state.pos + 1);
if (code === charCodes.leftCurlyBrace && next === charCodes.verticalBar) {
return this.finishOp(tt.braceBarL, 2);
} else if (
this.state.inType &&
(code === charCodes.greaterThan || code === charCodes.lessThan)
) {
@@ -1944,7 +1937,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
this.state.isIterator = true;
return super.readWord();
} else {
return super.readToken(code);
return super.getTokenFromCode(code);
}
}
@@ -2686,7 +2679,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
readToken_mult_modulo(code: number): void {
const next = this.input.charCodeAt(this.state.pos + 1);
const next = this.state.input.charCodeAt(this.state.pos + 1);
if (
code === charCodes.asterisk &&
next === charCodes.slash &&
@@ -2701,6 +2694,20 @@ export default (superClass: Class<Parser>): Class<Parser> =>
super.readToken_mult_modulo(code);
}
readToken_pipe_amp(code: number): void {
const next = this.state.input.charCodeAt(this.state.pos + 1);
if (
code === charCodes.verticalBar &&
next === charCodes.rightCurlyBrace
) {
// '|}'
this.finishOp(tt.braceBarR, 2);
return;
}
super.readToken_pipe_amp(code);
}
parseTopLevel(file: N.File, program: N.Program): N.File {
const fileNode = super.parseTopLevel(file, program);
if (this.state.hasFlowComment) {
@@ -2710,11 +2717,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
skipBlockComment(): void {
if (
this.hasPlugin("flow") &&
this.hasPlugin("flowComments") &&
this.skipFlowComment()
) {
if (this.hasPlugin("flowComments") && this.skipFlowComment()) {
if (this.state.hasFlowComment) {
this.unexpected(
null,
@@ -2727,8 +2730,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return;
}
if (this.hasPlugin("flow") && this.state.hasFlowComment) {
const end = this.input.indexOf("*-/", (this.state.pos += 2));
if (this.state.hasFlowComment) {
const end = this.state.input.indexOf("*-/", (this.state.pos += 2));
if (end === -1) this.raise(this.state.pos - 2, "Unterminated comment");
this.state.pos = end + 3;
return;
@@ -2742,20 +2745,22 @@ export default (superClass: Class<Parser>): Class<Parser> =>
let shiftToFirstNonWhiteSpace = 2;
while (
[charCodes.space, charCodes.tab].includes(
this.input.charCodeAt(pos + shiftToFirstNonWhiteSpace),
this.state.input.charCodeAt(pos + shiftToFirstNonWhiteSpace),
)
) {
shiftToFirstNonWhiteSpace++;
}
const ch2 = this.input.charCodeAt(shiftToFirstNonWhiteSpace + pos);
const ch3 = this.input.charCodeAt(shiftToFirstNonWhiteSpace + pos + 1);
const ch2 = this.state.input.charCodeAt(shiftToFirstNonWhiteSpace + pos);
const ch3 = this.state.input.charCodeAt(
shiftToFirstNonWhiteSpace + pos + 1,
);
if (ch2 === charCodes.colon && ch3 === charCodes.colon) {
return shiftToFirstNonWhiteSpace + 2; // check for /*::
}
if (
this.input.slice(
this.state.input.slice(
shiftToFirstNonWhiteSpace + pos,
shiftToFirstNonWhiteSpace + pos + 12,
) === "flow-include"
@@ -2769,7 +2774,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
hasFlowCommentCompletion(): void {
const end = this.input.indexOf("*/", this.state.pos);
const end = this.state.input.indexOf("*/", this.state.pos);
if (end === -1) {
this.raise(this.state.pos, "Unterminated comment");
}

View File

@@ -79,11 +79,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
let out = "";
let chunkStart = this.state.pos;
for (;;) {
if (this.state.pos >= this.input.length) {
if (this.state.pos >= this.state.length) {
this.raise(this.state.start, "Unterminated JSX contents");
}
const ch = this.input.charCodeAt(this.state.pos);
const ch = this.state.input.charCodeAt(this.state.pos);
switch (ch) {
case charCodes.lessThan:
@@ -93,20 +93,20 @@ export default (superClass: Class<Parser>): Class<Parser> =>
++this.state.pos;
return this.finishToken(tt.jsxTagStart);
}
return this.getTokenFromCode(ch);
return super.getTokenFromCode(ch);
}
out += this.input.slice(chunkStart, this.state.pos);
out += this.state.input.slice(chunkStart, this.state.pos);
return this.finishToken(tt.jsxText, out);
case charCodes.ampersand:
out += this.input.slice(chunkStart, this.state.pos);
out += this.state.input.slice(chunkStart, this.state.pos);
out += this.jsxReadEntity();
chunkStart = this.state.pos;
break;
default:
if (isNewLine(ch)) {
out += this.input.slice(chunkStart, this.state.pos);
out += this.state.input.slice(chunkStart, this.state.pos);
out += this.jsxReadNewLine(true);
chunkStart = this.state.pos;
} else {
@@ -117,12 +117,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
jsxReadNewLine(normalizeCRLF: boolean): string {
const ch = this.input.charCodeAt(this.state.pos);
const ch = this.state.input.charCodeAt(this.state.pos);
let out;
++this.state.pos;
if (
ch === charCodes.carriageReturn &&
this.input.charCodeAt(this.state.pos) === charCodes.lineFeed
this.state.input.charCodeAt(this.state.pos) === charCodes.lineFeed
) {
++this.state.pos;
out = normalizeCRLF ? "\n" : "\r\n";
@@ -139,25 +139,25 @@ export default (superClass: Class<Parser>): Class<Parser> =>
let out = "";
let chunkStart = ++this.state.pos;
for (;;) {
if (this.state.pos >= this.input.length) {
if (this.state.pos >= this.state.length) {
this.raise(this.state.start, "Unterminated string constant");
}
const ch = this.input.charCodeAt(this.state.pos);
const ch = this.state.input.charCodeAt(this.state.pos);
if (ch === quote) break;
if (ch === charCodes.ampersand) {
out += this.input.slice(chunkStart, this.state.pos);
out += this.state.input.slice(chunkStart, this.state.pos);
out += this.jsxReadEntity();
chunkStart = this.state.pos;
} else if (isNewLine(ch)) {
out += this.input.slice(chunkStart, this.state.pos);
out += this.state.input.slice(chunkStart, this.state.pos);
out += this.jsxReadNewLine(false);
chunkStart = this.state.pos;
} else {
++this.state.pos;
}
}
out += this.input.slice(chunkStart, this.state.pos++);
out += this.state.input.slice(chunkStart, this.state.pos++);
return this.finishToken(tt.string, out);
}
@@ -165,11 +165,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
let str = "";
let count = 0;
let entity;
let ch = this.input[this.state.pos];
let ch = this.state.input[this.state.pos];
const startPos = ++this.state.pos;
while (this.state.pos < this.input.length && count++ < 10) {
ch = this.input[this.state.pos++];
while (this.state.pos < this.state.length && count++ < 10) {
ch = this.state.input[this.state.pos++];
if (ch === ";") {
if (str[0] === "#") {
if (str[1] === "x") {
@@ -208,11 +208,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
let ch;
const start = this.state.pos;
do {
ch = this.input.charCodeAt(++this.state.pos);
ch = this.state.input.charCodeAt(++this.state.pos);
} while (isIdentifierChar(ch) || ch === charCodes.dash);
return this.finishToken(
tt.jsxName,
this.input.slice(start, this.state.pos),
this.state.input.slice(start, this.state.pos),
);
}
@@ -520,8 +520,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
}
readToken(code: number): void {
if (this.state.inPropertyName) return super.readToken(code);
getTokenFromCode(code: number): void {
if (this.state.inPropertyName) return super.getTokenFromCode(code);
const context = this.curContext();
@@ -557,7 +557,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return this.finishToken(tt.jsxTagStart);
}
return super.readToken(code);
return super.getTokenFromCode(code);
}
updateContext(prevType: TokenType): void {

View File

@@ -1324,7 +1324,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
tsCheckLineTerminatorAndMatch(tokenType: TokenType, next: boolean) {
return !this.isLineTerminator() && (next || this.match(tokenType));
return (next || this.match(tokenType)) && !this.isLineTerminator();
}
tsTryParseGenericAsyncArrowFunction(
@@ -2218,11 +2218,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
// ensure that inside types, we bypass the jsx parser plugin
readToken(code: number): void {
getTokenFromCode(code: number): void {
if (this.state.inType && (code === 62 || code === 60)) {
return this.finishOp(tt.relational, 1);
} else {
return super.readToken(code);
return super.getTokenFromCode(code);
}
}