Revamp wrenCall to work with slots.

Now, you call wrenEnsureSlots() and then wrenSetSlot___() to set up the
receiver and arguments before the call. Then wrenCall() is passed a
handle to the stub function that makes the call. After that, you can
get the result using wrenGetSlot___().

This is a little more verbose to use, but it's more flexible, simpler,
and much faster in the VM. The call benchmark is 185% of the previous
speed.
This commit is contained in:
Bob Nystrom
2015-12-29 07:58:47 -08:00
parent ed6fad6153
commit e0ac88c22a
10 changed files with 239 additions and 283 deletions

View File

@ -32,21 +32,32 @@ static void call(WrenVM* vm)
wrenInterpret(otherVM, testScript);
WrenValue* method = wrenGetMethod(otherVM, "main", "Test", "method(_,_,_,_)");
WrenValue* method = wrenMakeCallHandle(otherVM, "method(_,_,_,_)");
wrenEnsureSlots(otherVM, 1);
wrenGetVariable(otherVM, "main", "Test", 0);
WrenValue* testClass = wrenGetSlotValue(otherVM, 0);
double startTime = (double)clock() / CLOCKS_PER_SEC;
double result = 0;
for (int i = 0; i < iterations; i++)
{
WrenValue* resultValue;
wrenCall(otherVM, method, &resultValue, "dddd", 1.0, 2.0, 3.0, 4.0);
result += wrenGetValueDouble(otherVM, resultValue);
wrenReleaseValue(otherVM, resultValue);
wrenEnsureSlots(otherVM, 5);
wrenSetSlotValue(otherVM, 0, testClass);
wrenSetSlotDouble(otherVM, 1, 1.0);
wrenSetSlotDouble(otherVM, 2, 2.0);
wrenSetSlotDouble(otherVM, 3, 3.0);
wrenSetSlotDouble(otherVM, 4, 4.0);
wrenCall(otherVM, method);
result += wrenGetSlotDouble(otherVM, 0);
}
double elapsed = (double)clock() / CLOCKS_PER_SEC - startTime;
wrenReleaseValue(otherVM, testClass);
wrenReleaseValue(otherVM, method);
wrenFreeVM(otherVM);

View File

@ -5,33 +5,75 @@
void callRunTests(WrenVM* vm)
{
WrenValue* noParams = wrenGetMethod(vm, "main", "Call", "noParams");
WrenValue* zero = wrenGetMethod(vm, "main", "Call", "zero()");
WrenValue* one = wrenGetMethod(vm, "main", "Call", "one(_)");
WrenValue* two = wrenGetMethod(vm, "main", "Call", "two(_,_)");
wrenEnsureSlots(vm, 1);
wrenGetVariable(vm, "main", "Call", 0);
WrenValue* callClass = wrenGetSlotValue(vm, 0);
WrenValue* noParams = wrenMakeCallHandle(vm, "noParams");
WrenValue* zero = wrenMakeCallHandle(vm, "zero()");
WrenValue* one = wrenMakeCallHandle(vm, "one(_)");
WrenValue* two = wrenMakeCallHandle(vm, "two(_,_)");
// Different arity.
wrenCall(vm, noParams, NULL, "");
wrenCall(vm, zero, NULL, "");
wrenCall(vm, one, NULL, "i", 1);
wrenCall(vm, two, NULL, "ii", 1, 2);
WrenValue* getValue = wrenGetMethod(vm, "main", "Call", "getValue(_)");
wrenEnsureSlots(vm, 1);
wrenSetSlotValue(vm, 0, callClass);
wrenCall(vm, noParams);
wrenEnsureSlots(vm, 1);
wrenSetSlotValue(vm, 0, callClass);
wrenCall(vm, zero);
wrenEnsureSlots(vm, 2);
wrenSetSlotValue(vm, 0, callClass);
wrenSetSlotDouble(vm, 1, 1.0);
wrenCall(vm, one);
wrenEnsureSlots(vm, 3);
wrenSetSlotValue(vm, 0, callClass);
wrenSetSlotDouble(vm, 1, 1.0);
wrenSetSlotDouble(vm, 2, 2.0);
wrenCall(vm, two);
// Returning a value.
WrenValue* value = NULL;
wrenCall(vm, getValue, &value, "v", NULL);
WrenValue* getValue = wrenMakeCallHandle(vm, "getValue()");
wrenEnsureSlots(vm, 1);
wrenSetSlotValue(vm, 0, callClass);
wrenCall(vm, getValue);
WrenValue* value = wrenGetSlotValue(vm, 0);
// Different argument types.
wrenCall(vm, two, NULL, "bb", true, false);
wrenCall(vm, two, NULL, "dd", 1.2, 3.4);
wrenCall(vm, two, NULL, "ii", 3, 4);
wrenCall(vm, two, NULL, "ss", "string", "another");
wrenCall(vm, two, NULL, "vv", NULL, value);
wrenEnsureSlots(vm, 3);
wrenSetSlotValue(vm, 0, callClass);
wrenSetSlotBool(vm, 1, true);
wrenSetSlotBool(vm, 2, false);
wrenCall(vm, two);
wrenEnsureSlots(vm, 3);
wrenSetSlotValue(vm, 0, callClass);
wrenSetSlotDouble(vm, 1, 1.2);
wrenSetSlotDouble(vm, 2, 3.4);
wrenCall(vm, two);
wrenEnsureSlots(vm, 3);
wrenSetSlotValue(vm, 0, callClass);
wrenSetSlotString(vm, 1, "string");
wrenSetSlotString(vm, 2, "another");
wrenCall(vm, two);
wrenEnsureSlots(vm, 3);
wrenSetSlotValue(vm, 0, callClass);
wrenSetSlotNull(vm, 1);
wrenSetSlotValue(vm, 2, value);
wrenCall(vm, two);
// Truncate a string, or allow null bytes.
wrenCall(vm, two, NULL, "aa", "string", 3, "b\0y\0t\0e", 7);
wrenEnsureSlots(vm, 3);
wrenSetSlotValue(vm, 0, callClass);
wrenSetSlotBytes(vm, 1, "string", 3);
wrenSetSlotBytes(vm, 2, "b\0y\0t\0e", 7);
wrenCall(vm, two);
wrenReleaseValue(vm, callClass);
wrenReleaseValue(vm, noParams);
wrenReleaseValue(vm, zero);
wrenReleaseValue(vm, one);

View File

@ -20,13 +20,7 @@ class Call {
System.print("two %(one) %(two)")
}
static getValue(value) {
// Return a new value if we aren't given one.
if (value == null) return ["a", "b"]
// Otherwise print it.
System.print(value)
}
static getValue() { ["a", "b"] }
}
// expect: noParams
@ -36,7 +30,6 @@ class Call {
// expect: two true false
// expect: two 1.2 3.4
// expect: two 3 4
// expect: two string another
// expect: two null [a, b]
// expect: two str [98, 0, 121, 0, 116, 0, 101]