mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2025-07-28 23:19:03 -04:00
Reduce calls to getBlock
This commit is contained in:
parent
3f79712fb1
commit
ea59f8cd66
3 changed files with 63 additions and 61 deletions
src/engine
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue