diff --git a/src/engine/sequencer.js b/src/engine/sequencer.js index 7d40dd85a..5b3fcf005 100644 --- a/src/engine/sequencer.js +++ b/src/engine/sequencer.js @@ -74,7 +74,7 @@ class Sequencer { let numActiveThreads = Infinity; // Whether `stepThreads` has run through a full single tick. let ranFirstTick = false; - const doneThreads = this.runtime.threads.map(() => null); + const doneThreads = []; // Conditions for continuing to stepping threads: // 1. We must have threads in the list, and some must be active. // 2. Time elapsed must be less than WORK_TIME. @@ -91,19 +91,17 @@ class Sequencer { } numActiveThreads = 0; + let stoppedThread = false; // Attempt to run each thread one time. for (let i = 0; i < this.runtime.threads.length; i++) { const activeThread = this.runtime.threads[i]; + // Check if the thread is done so it is not executed. if (activeThread.stack.length === 0 || activeThread.status === Thread.STATUS_DONE) { // Finished with this thread. - doneThreads[i] = activeThread; + stoppedThread = true; continue; } - // A thread was removed, added or this thread was restarted. - if (doneThreads[i] !== null) { - doneThreads[i] = null; - } if (activeThread.status === Thread.STATUS_YIELD_TICK && !ranFirstTick) { // Clear single-tick yield from the last call of `stepThreads`. @@ -130,6 +128,13 @@ class Sequencer { if (activeThread.status === Thread.STATUS_RUNNING) { numActiveThreads++; } + // Check if the thread completed while it just stepped to make + // sure we remove it before the next iteration of all threads. + if (activeThread.stack.length === 0 || + activeThread.status === Thread.STATUS_DONE) { + // Finished with this thread. + stoppedThread = true; + } } // We successfully ticked once. Prevents running STATUS_YIELD_TICK // threads on the next tick. @@ -138,28 +143,23 @@ class Sequencer { if (this.runtime.profiler !== null) { this.runtime.profiler.stop(); } - } - // Filter inactive threads from `this.runtime.threads`. - numActiveThreads = 0; - for (let i = 0; i < this.runtime.threads.length; i++) { - const thread = this.runtime.threads[i]; - if (doneThreads[i] === null) { - this.runtime.threads[numActiveThreads] = thread; - numActiveThreads++; - } - } - this.runtime.threads.length = numActiveThreads; - // Filter undefined and null values from `doneThreads`. - let numDoneThreads = 0; - for (let i = 0; i < doneThreads.length; i++) { - const maybeThread = doneThreads[i]; - if (maybeThread !== null) { - doneThreads[numDoneThreads] = maybeThread; - numDoneThreads++; + // Filter inactive threads from `this.runtime.threads`. + if (stoppedThread) { + let nextActiveThread = 0; + for (let i = 0; i < this.runtime.threads.length; i++) { + const thread = this.runtime.threads[i]; + if (thread.stack.length !== 0 && + thread.status !== Thread.STATUS_DONE) { + this.runtime.threads[nextActiveThread] = thread; + nextActiveThread++; + } else { + doneThreads.push(thread); + } + } + this.runtime.threads.length = nextActiveThread; } } - doneThreads.length = numDoneThreads; return doneThreads; }