diff options
| author | jmoenig <jens@moenig.org> | 2014-11-25 12:24:20 +0100 |
|---|---|---|
| committer | jmoenig <jens@moenig.org> | 2014-11-25 12:24:20 +0100 |
| commit | 75849a59a2ac594c2c78a7cf6ef1e8be6c1eec57 (patch) | |
| tree | fb13a87c2b95ae03a266778b136b8077bb92d6f5 | |
| parent | 4be96bb240ea8518fa95218cba7111846af93baa (diff) | |
| download | snap-byow-75849a59a2ac594c2c78a7cf6ef1e8be6c1eec57.tar.gz snap-byow-75849a59a2ac594c2c78a7cf6ef1e8be6c1eec57.zip | |
Evaluator optimizations
reducing the stack size for reporters
| -rwxr-xr-x | history.txt | 6 | ||||
| -rw-r--r-- | threads.js | 127 |
2 files changed, 67 insertions, 66 deletions
diff --git a/history.txt b/history.txt index 964686e..22215e9 100755 --- a/history.txt +++ b/history.txt @@ -2342,7 +2342,7 @@ ______ ------- * Threads: Fix “stop this block” primitive for tail-call-elimination -1411214 +1411224 ------- * Threads: Fixed #318 * Objects: Fixed #416 @@ -2353,3 +2353,7 @@ ______ * snap.html, favicon.ico: new Favicon, thanks, Michael! * Threads: improved whitespace detection for “split” primitive, thanks, Michael! * Threads: tail-call-elimination for reporters experiment (commented out, under construction) + +1411225 +------- +* Threads: Evaluator optimizations (reducing the stack size for reporters) @@ -83,7 +83,7 @@ ArgLabelMorph, localize, XML_Element, hex_sha512*/ // Global stuff //////////////////////////////////////////////////////// -modules.threads = '2014-November-24'; +modules.threads = '2014-November-25'; var ThreadManager; var Process; @@ -218,11 +218,10 @@ ThreadManager.prototype.resumeAll = function (stage) { }; ThreadManager.prototype.step = function () { -/* - run each process until it gives up control, skipping processes - for sprites that are currently picked up, then filter out any - processes that have been terminated -*/ + // run each process until it gives up control, skipping processes + // for sprites that are currently picked up, then filter out any + // processes that have been terminated + this.processes.forEach(function (proc) { if (!proc.homeContext.receiver.isPickedUp() && !proc.isDead) { proc.runStep(); @@ -384,13 +383,13 @@ Process.prototype.isRunning = function () { // Process entry points Process.prototype.runStep = function () { -/* - a step is an an uninterruptable 'atom', it can consist - of several contexts, even of several blocks -*/ + // a step is an an uninterruptable 'atom', it can consist + // of several contexts, even of several blocks + if (this.isPaused) { // allow pausing in between atomic steps: return this.pauseStep(); } + this.readyToYield = false; while (!this.readyToYield && this.context @@ -459,6 +458,9 @@ Process.prototype.pauseStep = function () { Process.prototype.evaluateContext = function () { var exp = this.context.expression; this.frameCount += 1; + if (this.context.tag === 'exit') { + this.expectReport(); + } if (exp instanceof Array) { return this.evaluateSequence(exp); } @@ -482,7 +484,7 @@ Process.prototype.evaluateContext = function () { Process.prototype.evaluateBlock = function (block, argCount) { // check for special forms - if (contains(['reportOr', 'reportAnd'], block.selector)) { + if (contains(['reportOr', 'reportAnd', 'doReport'], block.selector)) { return this[block.selector](block); } @@ -548,33 +550,29 @@ Process.prototype.reportAnd = function (block) { } }; -/* - tail-call-elimination for reporters - ----------------------------------- - currently under construction, commented out for now - to activate add 'doReport' to the list of special forms - selectors in evaluateBlock() and comment out / remove - the current 'doReport' primitive in the "return" - section of the code - Process.prototype.doReport = function (block) { - -// if (this.context.expression.partOfCustomCommand) { -// return this.doStopCustomBlock(); -// } - + if (this.context.expression.partOfCustomCommand) { + this.doStopCustomBlock(); + this.popContext(); + return; + } var outer = this.context.outerContext; - while (this.context && this.context.expression !== 'exitReporter') { + while (this.context && this.context.tag !== 'exit') { if (this.context.expression === 'doStopWarping') { this.doStopWarping(); } else { this.popContext(); } } - this.popContext(); + if (this.context.expression === 'expectReport') { + // pop off inserted top-level exit context + this.popContext(); + } else { + // un-tag and preserve original caller + this.context.tag = null; + } this.pushContext(block.inputs()[0], outer); }; -*/ // Process: Non-Block evaluation @@ -724,9 +722,8 @@ Process.prototype.doYield = function () { } }; -Process.prototype.exitReporter = function () { - // catch-tag for REPORT and STOP BLOCK primitives - this.handleError(new Error("missing 'report' statement in reporter")); +Process.prototype.expectReport = function () { + this.handleError(new Error("reporter didn't report")); }; // Process Exception Handling @@ -831,9 +828,10 @@ Process.prototype.evaluate = function ( } var outer = new Context(null, null, context.outerContext), + caller = this.context.parentContext, + exit, runnable, extra, - exit, parms = args.asArray(), i, value; @@ -904,17 +902,22 @@ Process.prototype.evaluate = function ( if (runnable.expression instanceof CommandBlockMorph) { runnable.expression = runnable.expression.blockSequence(); - - // insert a reporter exit tag for the - // CALL SCRIPT primitive variant if (!isCommand) { - exit = new Context( - runnable.parentContext, - 'exitReporter', - outer, - outer.receiver - ); - runnable.parentContext = exit; + if (caller) { + // tag caller, so "report" can catch it later + caller.tag = 'exit'; + } else { + // top-level context, insert a tagged exit context + // which "report" can catch later + exit = new Context( + runnable.parentContext, + 'expectReport', + outer, + outer.receiver + ); + exit.tag = 'exit'; + runnable.parentContext = exit; + } } } }; @@ -993,21 +996,7 @@ Process.prototype.fork = function (context, args) { stage.threads.processes.push(proc); }; -// Process "return" primitives - -Process.prototype.doReport = function (value) { - if (this.context.expression.partOfCustomCommand) { - return this.doStopCustomBlock(); - } - while (this.context && this.context.expression !== 'exitReporter') { - if (this.context.expression === 'doStopWarping') { - this.doStopWarping(); - } else { - this.popContext(); - } - } - return value; -}; +// Process stopping blocks primitives Process.prototype.doStopBlock = function () { var target = this.context.expression.exitTag; @@ -1119,13 +1108,21 @@ Process.prototype.evaluateCustomBlock = function () { // insert a reporter exit tag for the // CALL SCRIPT primitive variant if (this.context.expression.definition.type !== 'command') { - exit = new Context( - runnable.parentContext, - 'exitReporter', - outer, - outer.receiver - ); - runnable.parentContext = exit; + if (caller) { + // tag caller, so "report" can catch it later + caller.tag = 'exit'; + } else { + // top-level context, insert a tagged exit context + // which "report" can catch later + exit = new Context( + runnable.parentContext, + 'expectReport', + outer, + outer.receiver + ); + exit.tag = 'exit'; + runnable.parentContext = exit; + } } else { // tag all "stop this block" blocks with the current // procedureCount as exitTag, and mark all "report" blocks @@ -2925,7 +2922,7 @@ Context.prototype.continuation = function () { } else { return new Context(null, 'doStop'); } - if (cont.expression === 'exitReporter') { + if (cont.expression === 'expectReport') { return cont.continuation(); } cont = cont.copyForContinuation(); |
