Skip to content

Commit 5d3ab2b

Browse files
committed
Switch core trampoline state back to arrays
1 parent fa430ae commit 5d3ab2b

File tree

3 files changed

+66
-63
lines changed

3 files changed

+66
-63
lines changed

src/compiler/binder.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1511,7 +1511,7 @@ namespace ts {
15111511
}
15121512
}
15131513

1514-
return createBinaryExpressionWalker(onEnter, onLeft, onOperator, onRight, onExit, identity);
1514+
return createBinaryExpressionTrampoline(onEnter, onLeft, onOperator, onRight, onExit, identity);
15151515

15161516
function onEnter(node: BinaryExpression, prev: BindBinaryExpressionState | undefined) {
15171517
let state: BindBinaryExpressionState;

src/compiler/emitter.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2531,7 +2531,7 @@ namespace ts {
25312531
sourceMapRange: SourceMapRange | undefined = undefined;
25322532
}
25332533

2534-
return createBinaryExpressionWalker(onEnter, maybeEmitExpression, onOperator, maybeEmitExpression, onExit, identity);
2534+
return createBinaryExpressionTrampoline(onEnter, maybeEmitExpression, onOperator, maybeEmitExpression, onExit, identity);
25352535

25362536
function onEnter(node: BinaryExpression, prev: EmitBinaryExpressionState | undefined) {
25372537
const state = new EmitBinaryExpressionState();
@@ -6666,7 +6666,7 @@ namespace ts {
66666666
) {}
66676667
}
66686668

6669-
return createBinaryExpressionWalker(onEnter, onLeft, onOperator, onRight, onExit, foldState);
6669+
return createBinaryExpressionTrampoline(onEnter, onLeft, onOperator, onRight, onExit, foldState);
66706670

66716671
function onEnter(node: BinaryExpression) {
66726672
return new PreprintBinaryExpressionState(node.left, node.operatorToken, node.right);

src/compiler/factory/utilities.ts

Lines changed: 63 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -930,7 +930,7 @@ namespace ts {
930930
return isBinaryOperator(node.kind);
931931
}
932932

933-
type BinaryExpressionState = <TState, TResult>(machine: BinaryExpressionStateMachine<TState, TResult>, frame: BinaryExpressionStateMachineFrame<TState, TResult>) => BinaryExpressionStateMachineFrame<TState, TResult>;
933+
type BinaryExpressionState = <TState, TResult>(machine: BinaryExpressionStateMachine<TState, TResult>, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], resultHolder: { value: TResult }) => number;
934934

935935
namespace BinaryExpressionState {
936936
/**
@@ -939,11 +939,12 @@ namespace ts {
939939
* @param frame The current frame
940940
* @returns The new frame
941941
*/
942-
export function enter<TState, TResult>(machine: BinaryExpressionStateMachine<TState, TResult>, frame: BinaryExpressionStateMachineFrame<TState, TResult>): BinaryExpressionStateMachineFrame<TState, TResult> {
943-
Debug.assertEqual(frame.state, enter);
944-
frame.userState = machine.onEnter(frame.node, frame.prev?.userState);
945-
frame.state = nextState(machine, enter);
946-
return frame;
942+
export function enter<TState, TResult>(machine: BinaryExpressionStateMachine<TState, TResult>, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], _resultHolder: { value: TResult }): number {
943+
const prevUserState = stackIndex > 0 ? userStateStack[stackIndex - 1] : undefined;
944+
Debug.assertEqual(stateStack[stackIndex], enter);
945+
userStateStack[stackIndex] = machine.onEnter(nodeStack[stackIndex], prevUserState);
946+
stateStack[stackIndex] = nextState(machine, enter);
947+
return stackIndex;
947948
}
948949

949950
/**
@@ -952,16 +953,16 @@ namespace ts {
952953
* @param frame The current frame
953954
* @returns The new frame
954955
*/
955-
export function left<TState, TResult>(machine: BinaryExpressionStateMachine<TState, TResult>, frame: BinaryExpressionStateMachineFrame<TState, TResult>): BinaryExpressionStateMachineFrame<TState, TResult> {
956-
Debug.assertEqual(frame.state, left);
956+
export function left<TState, TResult>(machine: BinaryExpressionStateMachine<TState, TResult>, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], _resultHolder: { value: TResult }): number {
957+
Debug.assertEqual(stateStack[stackIndex], left);
957958
Debug.assertIsDefined(machine.onLeft);
958-
frame.state = nextState(machine, left);
959-
const nextNode = machine.onLeft(frame.node.left, frame.userState, frame.node);
959+
stateStack[stackIndex] = nextState(machine, left);
960+
const nextNode = machine.onLeft(nodeStack[stackIndex].left, userStateStack[stackIndex], nodeStack[stackIndex]);
960961
if (nextNode) {
961-
checkCircularity(frame, nextNode);
962-
return new BinaryExpressionStateMachineFrame(frame, nextNode);
962+
checkCircularity(stackIndex, nodeStack, nextNode);
963+
return pushStack(stackIndex, stateStack, nodeStack, userStateStack, nextNode);
963964
}
964-
return frame;
965+
return stackIndex;
965966
}
966967

967968
/**
@@ -970,12 +971,12 @@ namespace ts {
970971
* @param frame The current frame
971972
* @returns The new frame
972973
*/
973-
export function operator<TState, TResult>(machine: BinaryExpressionStateMachine<TState, TResult>, frame: BinaryExpressionStateMachineFrame<TState, TResult>): BinaryExpressionStateMachineFrame<TState, TResult> {
974-
Debug.assertEqual(frame.state, operator);
974+
export function operator<TState, TResult>(machine: BinaryExpressionStateMachine<TState, TResult>, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], _resultHolder: { value: TResult }): number {
975+
Debug.assertEqual(stateStack[stackIndex], operator);
975976
Debug.assertIsDefined(machine.onOperator);
976-
frame.state = nextState(machine, operator);
977-
machine.onOperator(frame.node.operatorToken, frame.userState, frame.node);
978-
return frame;
977+
stateStack[stackIndex] = nextState(machine, operator);
978+
machine.onOperator(nodeStack[stackIndex].operatorToken, userStateStack[stackIndex], nodeStack[stackIndex]);
979+
return stackIndex;
979980
}
980981

981982
/**
@@ -984,16 +985,16 @@ namespace ts {
984985
* @param frame The current frame
985986
* @returns The new frame
986987
*/
987-
export function right<TState, TResult>(machine: BinaryExpressionStateMachine<TState, TResult>, frame: BinaryExpressionStateMachineFrame<TState, TResult>): BinaryExpressionStateMachineFrame<TState, TResult> {
988-
Debug.assertEqual(frame.state, right);
988+
export function right<TState, TResult>(machine: BinaryExpressionStateMachine<TState, TResult>, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], _resultHolder: { value: TResult }): number {
989+
Debug.assertEqual(stateStack[stackIndex], right);
989990
Debug.assertIsDefined(machine.onRight);
990-
frame.state = nextState(machine, right);
991-
const nextNode = machine.onRight(frame.node.right, frame.userState, frame.node);
991+
stateStack[stackIndex] = nextState(machine, right);
992+
const nextNode = machine.onRight(nodeStack[stackIndex].right, userStateStack[stackIndex], nodeStack[stackIndex]);
992993
if (nextNode) {
993-
checkCircularity(frame, nextNode);
994-
return new BinaryExpressionStateMachineFrame(frame, nextNode);
994+
checkCircularity(stackIndex, nodeStack, nextNode);
995+
return pushStack(stackIndex, stateStack, nodeStack, userStateStack, nextNode);
995996
}
996-
return frame;
997+
return stackIndex;
997998
}
998999

9991000
/**
@@ -1002,25 +1003,28 @@ namespace ts {
10021003
* @param frame The current frame
10031004
* @returns The new frame
10041005
*/
1005-
export function exit<TState, TResult>(machine: BinaryExpressionStateMachine<TState, TResult>, frame: BinaryExpressionStateMachineFrame<TState, TResult>): BinaryExpressionStateMachineFrame<TState, TResult> {
1006-
Debug.assertEqual(frame.state, exit);
1007-
frame.state = nextState(machine, exit);
1008-
frame.result = machine.onExit(frame.node, frame.userState);
1009-
if (frame.prev) {
1010-
const side = frame.prev.state === exit ? "right" : "left";
1011-
frame.prev.userState = machine.foldState(frame.prev.userState, frame.result, side);
1012-
return frame.prev;
1006+
export function exit<TState, TResult>(machine: BinaryExpressionStateMachine<TState, TResult>, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], resultHolder: { value: TResult }): number {
1007+
Debug.assertEqual(stateStack[stackIndex], exit);
1008+
stateStack[stackIndex] = nextState(machine, exit);
1009+
const result = machine.onExit(nodeStack[stackIndex], userStateStack[stackIndex]);
1010+
if (stackIndex > 0) {
1011+
stackIndex--;
1012+
const side = stateStack[stackIndex] === exit ? "right" : "left";
1013+
userStateStack[stackIndex] = machine.foldState(userStateStack[stackIndex], result, side);
10131014
}
1014-
return frame;
1015+
else {
1016+
resultHolder.value = result;
1017+
}
1018+
return stackIndex;
10151019
}
10161020

10171021
/**
10181022
* Handles a frame that is already done.
10191023
* @returns The `done` state.
10201024
*/
1021-
export function done<TState, TResult>(_machine: BinaryExpressionStateMachine<TState, TResult>, frame: BinaryExpressionStateMachineFrame<TState, TResult>): BinaryExpressionStateMachineFrame<TState, TResult> {
1022-
Debug.assertEqual(frame.state, done);
1023-
return frame;
1025+
export function done<TState, TResult>(_machine: BinaryExpressionStateMachine<TState, TResult>, stackIndex: number, stateStack: BinaryExpressionState[], _nodeStack: BinaryExpression[], _userStateStack: TState[], _resultHolder: { value: TResult }): number {
1026+
Debug.assertEqual(stateStack[stackIndex], done);
1027+
return stackIndex;
10241028
}
10251029

10261030
export function nextState<TState, TResult>(machine: BinaryExpressionStateMachine<TState, TResult>, currentState: BinaryExpressionState) {
@@ -1041,11 +1045,19 @@ namespace ts {
10411045
}
10421046
}
10431047

1044-
function checkCircularity<TState, TResult>(frame: BinaryExpressionStateMachineFrame<TState, TResult> | undefined, node: BinaryExpression) {
1048+
function pushStack<TState>(stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], node: BinaryExpression) {
1049+
stackIndex++;
1050+
stateStack[stackIndex] = BinaryExpressionState.enter;
1051+
nodeStack[stackIndex] = node;
1052+
userStateStack[stackIndex] = undefined!;
1053+
return stackIndex;
1054+
}
1055+
1056+
function checkCircularity(stackIndex: number, nodeStack: BinaryExpression[], node: BinaryExpression) {
10451057
if (Debug.shouldAssert(AssertionLevel.Aggressive)) {
1046-
while (frame) {
1047-
Debug.assert(frame.node !== node, "Circular traversal detected.");
1048-
frame = frame.prev;
1058+
while (stackIndex >= 0) {
1059+
Debug.assert(nodeStack[stackIndex] !== node, "Circular traversal detected.");
1060+
stackIndex--;
10491061
}
10501062
}
10511063
}
@@ -1066,20 +1078,6 @@ namespace ts {
10661078
}
10671079
}
10681080

1069-
/**
1070-
* Holds the current frame for the state machine
1071-
*/
1072-
class BinaryExpressionStateMachineFrame<TState, TResult> {
1073-
public state: BinaryExpressionState = BinaryExpressionState.enter;
1074-
public userState: TState = undefined!;
1075-
public result: TResult = undefined!;
1076-
constructor(
1077-
public prev: BinaryExpressionStateMachineFrame<TState, TResult> | undefined,
1078-
public node: BinaryExpression
1079-
) {
1080-
}
1081-
}
1082-
10831081
/**
10841082
* Creates a state machine that walks a `BinaryExpression` using the heap to reduce call-stack depth on a large tree.
10851083
* @param onEnter Callback evaluated when entering a `BinaryExpression`. Returns new user-defined state to associate with the node while walking.
@@ -1089,7 +1087,7 @@ namespace ts {
10891087
* @param foldState Callback evaluated when the result from a nested `onExit` should be folded into the state of that node's parent.
10901088
* @returns A function that walks a `BinaryExpression` node using the above callbacks, returning the result of the call to `onExit` from the outermost `BinaryExpression` node.
10911089
*/
1092-
export function createBinaryExpressionWalker<TState, TResult>(
1090+
export function createBinaryExpressionTrampoline<TState, TResult>(
10931091
onEnter: (node: BinaryExpression, prev: TState | undefined) => TState,
10941092
onLeft: ((left: Expression, userState: TState, node: BinaryExpression) => BinaryExpression | void) | undefined,
10951093
onOperator: ((operatorToken: BinaryOperatorToken, userState: TState, node: BinaryExpression) => void) | undefined,
@@ -1099,11 +1097,16 @@ namespace ts {
10991097
) {
11001098
const machine = new BinaryExpressionStateMachine(onEnter, onLeft, onOperator, onRight, onExit, foldState);
11011099
return (node: BinaryExpression) => {
1102-
let frame = new BinaryExpressionStateMachineFrame<TState, TResult>(/*prev*/ undefined, node);
1103-
while (frame.state !== BinaryExpressionState.done) {
1104-
frame = frame.state(machine, frame);
1100+
const resultHolder: { value: TResult } = { value: undefined! };
1101+
const stateStack: BinaryExpressionState[] = [BinaryExpressionState.enter];
1102+
const nodeStack: BinaryExpression[] = [node];
1103+
const userStateStack: TState[] = [undefined!];
1104+
let stackIndex = 0;
1105+
while (stateStack[stackIndex] !== BinaryExpressionState.done) {
1106+
stackIndex = stateStack[stackIndex](machine, stackIndex, stateStack, nodeStack, userStateStack, resultHolder);
11051107
}
1106-
return frame.result;
1108+
Debug.assertEqual(stackIndex, 0);
1109+
return resultHolder.value;
11071110
};
11081111
}
11091112
}

0 commit comments

Comments
 (0)