Reduce calls to getBlock

This commit is contained in:
griffpatch 2017-02-11 14:26:23 +00:00
parent 3f79712fb1
commit ea59f8cd66
3 changed files with 63 additions and 61 deletions
src/engine

View file

@ -16,38 +16,42 @@ var isPromise = function (value) {
* @param {!Thread} thread Thread which to read and execute.
*/
var execute = function (sequencer, thread) {
var runtime = sequencer.runtime;
var target = thread.target;
// Current block to execute is the one on the top of the stack.
var currentBlockId = thread.peekStack();
var currentStackFrame = thread.peekStackFrame();
// Check where the block lives: target blocks or flyout blocks.
var targetHasBlock = (
typeof target.blocks.getBlock(currentBlockId) !== 'undefined'
);
var flyoutHasBlock = (
typeof runtime.flyoutBlocks.getBlock(currentBlockId) !== 'undefined'
);
// Stop if block or target no longer exists.
if (!target || (!targetHasBlock && !flyoutHasBlock)) {
if (target == null) {
// No block found: stop the thread; script no longer exists.
sequencer.retireThread(thread);
return;
}
// Query info about the block.
var blockContainer = null;
if (targetHasBlock) {
blockContainer = target.blocks;
} else {
// Current block to execute is the one on the top of the stack.
var currentBlockId = thread.peekStack();
var currentStackFrame = thread.peekStackFrame();
var blockContainer = target.blocks;
var block = blockContainer.getBlock(currentBlockId);
if (block === undefined) {
blockContainer = runtime.flyoutBlocks;
block = blockContainer.getBlock(currentBlockId);
// Stop if block or target no longer exists.
if (block === undefined) {
// No block found: stop the thread; script no longer exists.
sequencer.retireThread(thread);
return;
}
}
var opcode = blockContainer.getOpcode(currentBlockId);
var fields = blockContainer.getFields(currentBlockId);
var inputs = blockContainer.getInputs(currentBlockId);
// if (eCount++ % 1000==0) { // 603,000 times!!
// console.log('Execute x' + eCount);
// }
// var block = blockContainer.getBlock(currentBlockId);
var opcode = block.opcode; // blockContainer.getOpcode(currentBlockId);
var fields = block.fields; // blockContainer.getFields(currentBlockId);
var inputs = blockContainer.getInputs(block);
var blockFunction = runtime.getOpcodeFunction(opcode);
var isHat = runtime.getIsHat(opcode);
@ -101,24 +105,20 @@ var execute = function (sequencer, thread) {
// it's treated as a predicate; if not, execution will proceed as a no-op.
// For single-field shadows: If the block has a single field, and no inputs,
// immediately return the value of the field.
if (!blockFunction) {
if (blockFunction == null) {
if (isHat) {
// Skip through the block (hat with no predicate).
return;
} else {
if (Object.keys(fields).length === 1 &&
Object.keys(inputs).length === 0) {
// One field and no inputs - treat as arg.
for (var fieldKey in fields) { // One iteration.
handleReport(fields[fieldKey].value);
}
} else {
log.warn('Could not get implementation for opcode: ' +
opcode);
}
thread.requestScriptGlowInFrame = true;
return;
}
var keys = Object.keys(fields);
if (keys.length === 1 && Object.keys(inputs).length === 0) {
// One field and no inputs - treat as arg.
handleReport(fields[keys[0]].value);
} else {
log.warn('Could not get implementation for opcode: ' + opcode);
}
thread.requestScriptGlowInFrame = true;
return;
}
// Generate values for arguments (inputs).
@ -134,8 +134,7 @@ var execute = function (sequencer, thread) {
var input = inputs[inputName];
var inputBlockId = input.block;
// Is there no value for this input waiting in the stack frame?
if (typeof currentStackFrame.reported[inputName] === 'undefined' &&
inputBlockId) {
if (inputBlockId != null && typeof currentStackFrame.reported[inputName] === 'undefined') {
// If there's not, we need to evaluate the block.
// Push to the stack to evaluate the reporter block.
thread.pushStack(inputBlockId);
@ -145,19 +144,19 @@ var execute = function (sequencer, thread) {
execute(sequencer, thread);
if (thread.status === Thread.STATUS_PROMISE_WAIT) {
return;
} else {
// Execution returned immediately,
// and presumably a value was reported, so pop the stack.
currentStackFrame.waitingReporter = null;
thread.popStack();
}
// Execution returned immediately,
// and presumably a value was reported, so pop the stack.
currentStackFrame.waitingReporter = null;
thread.popStack();
}
argValues[inputName] = currentStackFrame.reported[inputName];
}
// Add any mutation to args (e.g., for procedures).
var mutation = blockContainer.getMutation(currentBlockId);
if (mutation) {
var mutation = blockContainer.getMutation(block);
if (mutation !== null) {
argValues.mutation = mutation;
}