mirror of
https://github.com/aphrody-labs/oxc.git
synced 2026-10-17 12:56:09 +00:00
perf(packages/codegen): reduce megamorphic property accesses for BinaryExpressions (#27459)
Perf optimization. Continuation of #27458. The branch of `printExpression` for `BinaryExpression` (common path) reads the `type` of the left-hand node in order to check if it's a `PrivateInExpression`. This is a costly megamorphic access. In the common case where it's _not_ a `PrivateInExpression`, it then calls `printBinaryish` which then accesses `node.left.type` again. This incurs the megamorphic load cost twice. Instead, pass the extracted value of `node.left.type` into `printBinaryish` so it can avoid the 2nd lookup.
This commit is contained in:
1 parent
675ec5e879
commit
3d2f93f87c
2 files changed
+14
-7
No files matched your search
@@ -1,6 +1,6 @@
|
||||
// Binary/logical expressions (port of `binary_expr_visitor.rs`).
|
||||
|
||||
import { typeAssertIs } from "../asserts.ts";
|
||||
import { debugAssert, typeAssertIs } from "../asserts.ts";
|
||||
import { CAT_CLOSE_BRACKET, CAT_OTHER } from "./categories.ts";
|
||||
import { write } from "./write.ts";
|
||||
import { printPrivateInExpression, printExpression } from "./expression.ts";
|
||||
@@ -17,7 +17,6 @@ import type {
|
||||
LogicalExpression,
|
||||
LogicalOperator,
|
||||
ParenthesizedExpression,
|
||||
PrivateIdentifier,
|
||||
PrivateInExpression,
|
||||
} from "../../../../npm/oxc-types/types.d.ts";
|
||||
|
||||
@@ -49,12 +48,14 @@ interface BinaryVisitor {
|
||||
* @param state - Printer state
|
||||
* @param precedence - Precedence of the position this expression sits in, deciding parenthesisation
|
||||
* @param ctx - Context flags, carrying whether `in` is forbidden and calls are
|
||||
* @param leftType - `node.left.type`, which the caller has already read
|
||||
*/
|
||||
export function printBinaryish(
|
||||
node: BinaryExpression | LogicalExpression,
|
||||
state: State,
|
||||
precedence: number,
|
||||
ctx: number,
|
||||
leftType: string,
|
||||
): void {
|
||||
// The pending outer levels are threaded through `parent` rather than a separate stack array
|
||||
let v: BinaryVisitor | null = {
|
||||
@@ -70,8 +71,9 @@ export function printBinaryish(
|
||||
|
||||
// An operand can be any expression, so reading its `type` is a megamorphic load.
|
||||
// Each left operand's `type` is read once, and carried down the left spine to the next level.
|
||||
// The root's is read by the caller, for its private-in check, and passed in as `leftType`.
|
||||
let { left } = node;
|
||||
let leftType: (Expression | PrivateIdentifier)["type"] = left.type;
|
||||
debugAssert(leftType === left.type, "`leftType` must be the `type` of `node.left`");
|
||||
|
||||
// At the top of each iteration, `left` is `v.e.left`, and `leftType` is its `type`
|
||||
for (;;) {
|
||||
|
||||
@@ -110,17 +110,22 @@ export function printExpression(
|
||||
case "Literal":
|
||||
printLiteral(node, state, precedence, ctx);
|
||||
break;
|
||||
case "BinaryExpression":
|
||||
if (node.left.type === "PrivateIdentifier") {
|
||||
case "BinaryExpression": {
|
||||
// `node.left` can be any expression, so reading its `type` is a megamorphic load.
|
||||
// Read it once here, for both the private-in check and `printBinaryish`.
|
||||
const leftType = node.left.type;
|
||||
if (leftType === "PrivateIdentifier") {
|
||||
typeAssertIs<ESTree.PrivateInExpression>(node);
|
||||
printPrivateInExpression(node, state, precedence);
|
||||
} else {
|
||||
typeAssertIs<ESTree.BinaryExpression>(node);
|
||||
printBinaryish(node, state, precedence, ctx);
|
||||
printBinaryish(node, state, precedence, ctx, leftType);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "LogicalExpression":
|
||||
printBinaryish(node, state, precedence, ctx);
|
||||
// The left operand of a logical expression can't be a private name, so no private-in check
|
||||
printBinaryish(node, state, precedence, ctx, node.left.type);
|
||||
break;
|
||||
case "ObjectExpression":
|
||||
printObjectExpression(node, state);
|
||||
|
||||
Reference in new issue
Block a user