Reset API stack a fiber is aborted from wrenCall().

This commit is contained in:
Bob Nystrom
2016-11-01 08:40:16 -07:00
parent 51e50e6cc4
commit b9f53f71fb
8 changed files with 68 additions and 7 deletions

View File

@ -400,6 +400,7 @@ static void runtimeError(WrenVM* vm)
// If we got here, nothing caught the error, so show the stack trace.
wrenDebugPrintStackTrace(vm);
vm->fiber = NULL;
vm->apiStack = NULL;
}
// Aborts the current fiber with an appropriate method not found error for a

View File

@ -12,6 +12,7 @@
#include "handle.h"
#include "lists.h"
#include "new_vm.h"
#include "reset_stack_after_call_abort.h"
#include "reset_stack_after_foreign_construct.h"
#include "slots.h"
@ -87,8 +88,15 @@ static WrenForeignClassMethods bindForeignClass(
}
static void afterLoad(WrenVM* vm) {
if (strstr(testName, "/call.wren") != NULL) callRunTests(vm);
if (strstr(testName, "/reset_stack_after_foreign_construct.wren") != NULL)
if (strstr(testName, "/call.wren") != NULL)
{
callRunTests(vm);
}
else if (strstr(testName, "/reset_stack_after_call_abort.wren") != NULL)
{
resetStackAfterCallAbortRunTests(vm);
}
else if (strstr(testName, "/reset_stack_after_foreign_construct.wren") != NULL)
{
resetStackAfterForeignConstructRunTests(vm);
}

View File

@ -0,0 +1,28 @@
#include <stdio.h>
#include <string.h>
#include "wren.h"
void resetStackAfterCallAbortRunTests(WrenVM* vm)
{
wrenEnsureSlots(vm, 1);
wrenGetVariable(vm, "main", "Test", 0);
WrenHandle* testClass = wrenGetSlotHandle(vm, 0);
WrenHandle* abortFiber = wrenMakeCallHandle(vm, "abortFiber()");
WrenHandle* afterConstruct = wrenMakeCallHandle(vm, "afterAbort(_,_)");
wrenEnsureSlots(vm, 1);
wrenSetSlotHandle(vm, 0, testClass);
wrenCall(vm, abortFiber);
wrenEnsureSlots(vm, 3);
wrenSetSlotHandle(vm, 0, testClass);
wrenSetSlotDouble(vm, 1, 1.0);
wrenSetSlotDouble(vm, 2, 2.0);
wrenCall(vm, afterConstruct);
wrenReleaseHandle(vm, testClass);
wrenReleaseHandle(vm, abortFiber);
wrenReleaseHandle(vm, afterConstruct);
}

View File

@ -0,0 +1,3 @@
#include "wren.h"
void resetStackAfterCallAbortRunTests(WrenVM* vm);

View File

@ -0,0 +1,14 @@
// Regression test.
//
// If you invoked some code with wrenCall() and that code aborted the current
// fiber, it did not reset the API stack. If you tried to immediately reuse the
// API stack by calling wrenCall(), it would be in a broken state.
class Test {
static abortFiber() {
Fiber.abort("Abort!") // expect handled runtime error: Abort!
}
static afterAbort(a, b) {
System.print(a + b) // expect: 3
}
}

View File

@ -1,7 +1,7 @@
#include <stdio.h>
#include <string.h>
#include "foreign_class.h"
#include "wren.h"
static void counterAllocate(WrenVM* vm)
{

View File

@ -18,7 +18,7 @@ TEST_APP = join(WREN_DIR, 'build', 'debug', 'test', 'wrend')
EXPECT_PATTERN = re.compile(r'// expect: ?(.*)')
EXPECT_ERROR_PATTERN = re.compile(r'// expect error(?! line)')
EXPECT_ERROR_LINE_PATTERN = re.compile(r'// expect error line (\d+)')
EXPECT_RUNTIME_ERROR_PATTERN = re.compile(r'// expect runtime error: (.+)')
EXPECT_RUNTIME_ERROR_PATTERN = re.compile(r'// expect (handled )?runtime error: (.+)')
ERROR_PATTERN = re.compile(r'\[.* line (\d+)\] Error')
STACK_TRACE_PATTERN = re.compile(r'\[main line (\d+)\] in')
STDIN_PATTERN = re.compile(r'// stdin: (.*)')
@ -77,9 +77,10 @@ class Test:
match = EXPECT_RUNTIME_ERROR_PATTERN.search(line)
if match:
self.runtime_error_line = line_num
self.runtime_error_message = match.group(1)
# If we expect a runtime error, it should exit with EX_SOFTWARE.
self.exit_code = 70
self.runtime_error_message = match.group(2)
# If the runtime error isn't handled, it should exit with EX_SOFTWARE.
if match.group(1) != "handled ":
self.exit_code = 70
expectations += 1
match = STDIN_PATTERN.search(line)

View File

@ -48,6 +48,7 @@
29D025E41C19CD1000A3BB28 /* os.c in Sources */ = {isa = PBXBuildFile; fileRef = 29D025E01C19CD1000A3BB28 /* os.c */; };
29D025E51C19CD1000A3BB28 /* os.wren.inc in Sources */ = {isa = PBXBuildFile; fileRef = 29D025E21C19CD1000A3BB28 /* os.wren.inc */; };
29D025E61C19CD1000A3BB28 /* os.wren.inc in Sources */ = {isa = PBXBuildFile; fileRef = 29D025E21C19CD1000A3BB28 /* os.wren.inc */; };
29D880661DC8ECF600025364 /* reset_stack_after_call_abort.c in Sources */ = {isa = PBXBuildFile; fileRef = 29D880641DC8ECF600025364 /* reset_stack_after_call_abort.c */; };
29DC149F1BBA2FCC008A8274 /* vm.c in Sources */ = {isa = PBXBuildFile; fileRef = 29C8A9311AB71FFF00DEC81D /* vm.c */; };
29DC14A01BBA2FD6008A8274 /* timer.c in Sources */ = {isa = PBXBuildFile; fileRef = 2901D7621B74F4050083A2C8 /* timer.c */; };
29DC14A11BBA2FEC008A8274 /* scheduler.c in Sources */ = {isa = PBXBuildFile; fileRef = 291647C21BA5EA45006142EE /* scheduler.c */; };
@ -151,6 +152,8 @@
29D025E01C19CD1000A3BB28 /* os.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = os.c; path = ../../src/module/os.c; sourceTree = "<group>"; };
29D025E11C19CD1000A3BB28 /* os.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = os.h; path = ../../src/module/os.h; sourceTree = "<group>"; };
29D025E21C19CD1000A3BB28 /* os.wren.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = os.wren.inc; path = ../../src/module/os.wren.inc; sourceTree = "<group>"; };
29D880641DC8ECF600025364 /* reset_stack_after_call_abort.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = reset_stack_after_call_abort.c; path = ../../test/api/reset_stack_after_call_abort.c; sourceTree = "<group>"; };
29D880651DC8ECF600025364 /* reset_stack_after_call_abort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = reset_stack_after_call_abort.h; path = ../../test/api/reset_stack_after_call_abort.h; sourceTree = "<group>"; };
29F384111BD19706002F84E0 /* io.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = io.h; path = ../../src/module/io.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -294,6 +297,8 @@
29932D531C210F8D00099DEE /* lists.h */,
29C946961C88F14F00B4A4F3 /* new_vm.c */,
29C946971C88F14F00B4A4F3 /* new_vm.h */,
29D880641DC8ECF600025364 /* reset_stack_after_call_abort.c */,
29D880651DC8ECF600025364 /* reset_stack_after_call_abort.h */,
29C80D581D73332A00493837 /* reset_stack_after_foreign_construct.c */,
29C80D591D73332A00493837 /* reset_stack_after_foreign_construct.h */,
29D009AA1B7E39A8000CE58C /* slots.c */,
@ -415,6 +420,7 @@
29DC14A11BBA2FEC008A8274 /* scheduler.c in Sources */,
29A427391BDBE435001E6E22 /* wren_opt_random.c in Sources */,
293B255A1CEFD8C7005D9537 /* repl.wren.inc in Sources */,
29D880661DC8ECF600025364 /* reset_stack_after_call_abort.c in Sources */,
29932D511C20D8C900099DEE /* benchmark.c in Sources */,
29DC14A01BBA2FD6008A8274 /* timer.c in Sources */,
29DC149F1BBA2FCC008A8274 /* vm.c in Sources */,