mirror of
https://github.com/morluto/rea.git
synced 2026-10-29 10:55:57 +00:00
perf(javascript): reuse semantic member-mutation lookups (#2941)
The semantic member-mutation collector revisits the same nodes while it closes alias chains, and each visit re-derived results that cannot change within the phase: - resolveSemanticBindingState re-walked the scope chain for the same identifier node. Definition collection completes before this phase, and addBinding is reachable only from it, so a scope's bindings no longer change. - directInitializerPosition, directMutationPosition and referenceInitializerPosition are pure functions of a node and the analysis parent map, but were recomputed for every mutation and initializer. - markValue re-encoded the same capture tuple with JSON.stringify and built a fresh long key for every Set/Map lookup, so each lookup re-hashed the whole key. The capture key is now cached per binding, origin and owner, and the lifetime key is derived from it. On pdfjs-dist 5.3.93 wasm/openjpeg_nowasm_fallback.js (462316 bytes, sha256 53c228428a8861035a34738966af263fc9d4cee6df25a0ad942af947469a0bd9) the semantic phase takes 177.8 s instead of 272.9 s in-process, with a byte-identical semantic IR. With --max-heap-mb 3072 and the default heap the base revision exhausts the worker; with the default 300 s per-source deadline raised, the completed CLI run takes 240.6 s instead of 396.7 s and its output is identical apart from volatile identifiers. Refs #2498 Co-authored-by: gongfpp <22683417+gongfpp@users.noreply.github.com>
This commit is contained in:
1 parent
a9195c3a98
commit
0c6c571a01
2 files changed
+130
-20
No files matched your search
@@ -12,6 +12,37 @@ interface StatementPosition {
|
||||
readonly declaratorIndex: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializer positions depend only on a node and its parent map, which one
|
||||
* analysis builds once and never changes. Different mutations and initializers
|
||||
* re-derive the same positions along shared ancestry, so retain the first
|
||||
* result for as long as its parent map is reachable.
|
||||
*/
|
||||
interface InitializerPositionCache {
|
||||
readonly direct: WeakMap<t.Node, StatementPosition | null>;
|
||||
readonly mutation: WeakMap<t.Node, StatementPosition | null>;
|
||||
readonly reference: WeakMap<t.Node, StatementPosition | null>;
|
||||
}
|
||||
|
||||
const initializerPositionCaches = new WeakMap<
|
||||
WeakMap<t.Node, t.Node>,
|
||||
InitializerPositionCache
|
||||
>();
|
||||
|
||||
const initializerPositionCache = (
|
||||
parents: WeakMap<t.Node, t.Node>,
|
||||
): InitializerPositionCache => {
|
||||
const cached = initializerPositionCaches.get(parents);
|
||||
if (cached !== undefined) return cached;
|
||||
const created: InitializerPositionCache = {
|
||||
direct: new WeakMap(),
|
||||
mutation: new WeakMap(),
|
||||
reference: new WeakMap(),
|
||||
};
|
||||
initializerPositionCaches.set(parents, created);
|
||||
return created;
|
||||
};
|
||||
|
||||
const statementPosition = (
|
||||
statement: t.Statement,
|
||||
parents: WeakMap<t.Node, t.Node>,
|
||||
@@ -42,7 +73,7 @@ const positionPrecedes = (
|
||||
left.declaratorIndex >= 0 &&
|
||||
left.declaratorIndex < right.declaratorIndex));
|
||||
|
||||
const directInitializerPosition = (
|
||||
const computeDirectInitializerPosition = (
|
||||
node: t.Node,
|
||||
parents: WeakMap<t.Node, t.Node>,
|
||||
): StatementPosition | null => {
|
||||
@@ -67,7 +98,19 @@ const directInitializerPosition = (
|
||||
return null;
|
||||
};
|
||||
|
||||
const directMutationPosition = (
|
||||
const directInitializerPosition = (
|
||||
node: t.Node,
|
||||
parents: WeakMap<t.Node, t.Node>,
|
||||
): StatementPosition | null => {
|
||||
const cache = initializerPositionCache(parents);
|
||||
const cached = cache.direct.get(node);
|
||||
if (cached !== undefined) return cached;
|
||||
const computed = computeDirectInitializerPosition(node, parents);
|
||||
cache.direct.set(node, computed);
|
||||
return computed;
|
||||
};
|
||||
|
||||
const computeDirectMutationPosition = (
|
||||
node: t.Node,
|
||||
parents: WeakMap<t.Node, t.Node>,
|
||||
): StatementPosition | null => {
|
||||
@@ -115,7 +158,19 @@ const directMutationPosition = (
|
||||
}
|
||||
};
|
||||
|
||||
const referenceInitializerPosition = (
|
||||
const directMutationPosition = (
|
||||
node: t.Node,
|
||||
parents: WeakMap<t.Node, t.Node>,
|
||||
): StatementPosition | null => {
|
||||
const cache = initializerPositionCache(parents);
|
||||
const cached = cache.mutation.get(node);
|
||||
if (cached !== undefined) return cached;
|
||||
const computed = computeDirectMutationPosition(node, parents);
|
||||
cache.mutation.set(node, computed);
|
||||
return computed;
|
||||
};
|
||||
|
||||
const computeReferenceInitializerPosition = (
|
||||
node: t.Node,
|
||||
parents: WeakMap<t.Node, t.Node>,
|
||||
): StatementPosition | null => {
|
||||
@@ -137,6 +192,18 @@ const referenceInitializerPosition = (
|
||||
}
|
||||
};
|
||||
|
||||
const referenceInitializerPosition = (
|
||||
node: t.Node,
|
||||
parents: WeakMap<t.Node, t.Node>,
|
||||
): StatementPosition | null => {
|
||||
const cache = initializerPositionCache(parents);
|
||||
const cached = cache.reference.get(node);
|
||||
if (cached !== undefined) return cached;
|
||||
const computed = computeReferenceInitializerPosition(node, parents);
|
||||
cache.reference.set(node, computed);
|
||||
return computed;
|
||||
};
|
||||
|
||||
/** Resolve origins at their use or capture, never at a later transitive effect. */
|
||||
export const semanticMutationInitializers = (
|
||||
binding: JavaScriptSemanticBindingState,
|
||||
|
||||
Reference in new issue
Block a user