Add specialized instructions for loading some locals.

Not having to decode a separate arg byte improves some benchmarks:

binary_trees - wren           ..........  3094  0.32s  101.95% relative to baseline
delta_blue - wren             ..........  6555  0.15s  101.05% relative to baseline
fib - wren                    ..........  2326  0.43s  107.32% relative to baseline
for - wren                    ..........  6183  0.16s  102.81% relative to baseline
method_call - wren            ..........  4746  0.21s  105.97% relative to baseline
This commit is contained in:
Bob Nystrom
2014-12-06 19:59:11 -08:00
parent a94dfdac10
commit ac67386208
5 changed files with 174 additions and 34 deletions
+38 -7
View File
@@ -1168,6 +1168,17 @@ static int resolveName(Compiler* compiler, const char* name, int length,
&compiler->parser->vm->globalNames, name, length);
}
static void loadLocal(Compiler* compiler, int slot)
{
if (slot <= 8)
{
emit(compiler, CODE_LOAD_LOCAL_0 + slot);
return;
}
emitByte(compiler, CODE_LOAD_LOCAL, slot);
}
// Copies the identifier from the previously consumed `TOKEN_NAME` into [name],
// which should point to a buffer large enough to contain it. Returns the
// length of the name.
@@ -1363,7 +1374,7 @@ static void finishBody(Compiler* compiler, bool isConstructor)
if (!isStatementBody) emit(compiler, CODE_POP);
// The receiver is always stored in the first local slot.
emitByte(compiler, CODE_LOAD_LOCAL, 0);
emit(compiler, CODE_LOAD_LOCAL_0);
}
else if (isStatementBody)
{
@@ -1511,7 +1522,14 @@ static void loadThis(Compiler* compiler)
int index = resolveName(compiler, "this", 4, &loadInstruction);
ASSERT(index == -1 || loadInstruction != CODE_LOAD_GLOBAL,
"'this' should not be global.");
emitByte(compiler, loadInstruction, index);
if (loadInstruction == CODE_LOAD_LOCAL)
{
loadLocal(compiler, index);
}
else
{
emitByte(compiler, loadInstruction, index);
}
}
static void grouping(Compiler* compiler, bool allowAssignment)
@@ -1671,6 +1689,10 @@ static void variable(Compiler* compiler, bool allowAssignment, int index,
{
emitShort(compiler, loadInstruction, index);
}
else if (loadInstruction == CODE_LOAD_LOCAL)
{
loadLocal(compiler, index);
}
else
{
emitByte(compiler, loadInstruction, index);
@@ -2187,6 +2209,15 @@ static int getNumArguments(const uint8_t* bytecode, const Value* constants,
case CODE_CLOSE_UPVALUE:
case CODE_RETURN:
case CODE_END:
case CODE_LOAD_LOCAL_0:
case CODE_LOAD_LOCAL_1:
case CODE_LOAD_LOCAL_2:
case CODE_LOAD_LOCAL_3:
case CODE_LOAD_LOCAL_4:
case CODE_LOAD_LOCAL_5:
case CODE_LOAD_LOCAL_6:
case CODE_LOAD_LOCAL_7:
case CODE_LOAD_LOCAL_8:
return 0;
case CODE_LOAD_LOCAL:
@@ -2379,8 +2410,8 @@ static void forStatement(Compiler* compiler)
startLoop(compiler, &loop);
// Advance the iterator by calling the ".iterate" method on the sequence.
emitByte(compiler, CODE_LOAD_LOCAL, seqSlot);
emitByte(compiler, CODE_LOAD_LOCAL, iterSlot);
loadLocal(compiler, seqSlot);
loadLocal(compiler, iterSlot);
emitShort(compiler, CODE_CALL_1, methodSymbol(compiler, "iterate ", 8));
@@ -2391,8 +2422,8 @@ static void forStatement(Compiler* compiler)
testExitLoop(compiler);
// Get the current value in the sequence by calling ".iteratorValue".
emitByte(compiler, CODE_LOAD_LOCAL, seqSlot);
emitByte(compiler, CODE_LOAD_LOCAL, iterSlot);
loadLocal(compiler, seqSlot);
loadLocal(compiler, iterSlot);
emitShort(compiler, CODE_CALL_1,
methodSymbol(compiler, "iteratorValue ", 14));
@@ -2630,7 +2661,7 @@ static void classDefinition(Compiler* compiler)
}
else
{
emitByte(compiler, CODE_LOAD_LOCAL, symbol);
loadLocal(compiler, symbol);
}
// Define the method.