Skip to content

Commit

Permalink
Propagate runtime config options about stack size
Browse files Browse the repository at this point in the history
Deep stacks, at least on the lazy impl, seem to be working as long as the
runtime correctly gets the options about stack size.

Eager is still failing with call stack size exceeded with these changes.

The runtimeOpts given to stopifyLocally were not used to configure any starting
stack sizes, this does that configuration on the init() method. I'm not sure
that's the right place, but it's where the estimator and some other config
happen based on the opts field, so it seems reasonable.

Separately, this also adds (optional) params to newRTS to configure stack size
(since those are the parameters the constructors of the various runtimes take).
With just this change (e.g. without the new configuration in init() that sets
fields on rts), you can get deep/lazy working by using e.g.

stopify.newRTS('lazy', 1000, 10)

before calling .run(). But since stopifyLocally takes the runtimeOpts, it seems
right to use them somewhere.
  • Loading branch information
jpolitz committed Jul 30, 2024
1 parent 275d950 commit 355a50d
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 8 deletions.
10 changes: 5 additions & 5 deletions stopify-continuations/src/runtime/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ import { FudgeRuntime } from './fudgeRuntime';
export * from './abstractRuntime';

let savedRTS: RuntimeImpl | undefined;
export function newRTS(transform: string): RuntimeImpl {
export function newRTS(transform: string, stackSize: number = Infinity, restoreFrames: number = Infinity): RuntimeImpl {
if (!savedRTS || savedRTS.kind !== transform) {
switch (transform) {
// Default to shallow runtime.
case 'catch':
savedRTS = new LazyRuntime(Infinity, Infinity);
savedRTS = new LazyRuntime(stackSize, restoreFrames);
savedRTS.kind = 'catch'; // TODO(arjun): Sloppy
break;
case 'lazy': savedRTS = new LazyRuntime(Infinity, Infinity); break;
case 'eager': savedRTS = new EagerRuntime(Infinity, Infinity); break;
case 'retval': savedRTS = new RetvalRuntime(Infinity, Infinity); break;
case 'lazy': savedRTS = new LazyRuntime(stackSize, restoreFrames); break;
case 'eager': savedRTS = new EagerRuntime(stackSize, restoreFrames); break;
case 'retval': savedRTS = new RetvalRuntime(stackSize, restoreFrames); break;
case 'fudge': savedRTS = new FudgeRuntime(); break;
default: throw new Error(`bad runtime: ${transform}`);
}
Expand Down
5 changes: 5 additions & 0 deletions stopify/src/runtime/abstractRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ export abstract class AbstractRunner implements AsyncRun {
*/
init(rts: Runtime) {
this.continuationsRTS = rts;

this.continuationsRTS.stackSize = this.opts.stackSize;
this.continuationsRTS.restoreFrames = this.opts.restoreFrames;
this.continuationsRTS.remainingStack = this.opts.stackSize;

const estimator = makeEstimator(this.opts);
this.suspendRTS = new RuntimeWithSuspend(this.continuationsRTS, this.opts.yieldInterval, estimator, () => {
switch (this.mayYieldFlag.kind) {
Expand Down
6 changes: 3 additions & 3 deletions stopify/test/semantics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ describe('Test cases that require deep stacks',() => {
yieldInterval: 25
};

test.skip('non-tail recursive function (deep, lazy)', onDone => {
test('non-tail recursive function (deep, lazy)', onDone => {
const runner = harness(`
function sum(x) {
if (x <= 1) {
Expand All @@ -299,7 +299,7 @@ describe('Test cases that require deep stacks',() => {
return x + sum(x-1);
}
}
assert.equal(sum(200), 1250025000);
assert.equal(sum(100000), 5000050000);
`, { captureMethod: 'lazy' }, runtimeOpts);
runner.run(result => {
expect(result).toEqual({ type: 'normal' });
Expand All @@ -316,7 +316,7 @@ describe('Test cases that require deep stacks',() => {
return x + sum(x-1);
}
}
assert.equal(sum(200), 1250025000);
assert.equal(sum(100000), 5000050000);
`, { captureMethod: 'eager' }, runtimeOpts);
runner.run(result => {
expect(result).toEqual({ type: 'normal' });
Expand Down

0 comments on commit 355a50d

Please sign in to comment.