forked from Mirror/wren
Start moving embedding API towards "slot" register-API.
- wrenGetArgumentCount() -> wrenGetSlotCount() - wrenGetArgument___() -> wrenGetSlot___() Also, the get functions assert that the value is the right type instead of checking at runtime. This puts the onus on the caller to be safe, but maximizes performance.
This commit is contained in:
@ -120,7 +120,7 @@ typedef struct
|
|||||||
//
|
//
|
||||||
// If this is `NULL`, Wren discards any printed text.
|
// If this is `NULL`, Wren discards any printed text.
|
||||||
WrenWriteFn writeFn;
|
WrenWriteFn writeFn;
|
||||||
|
|
||||||
// The number of bytes Wren will allocate before triggering the first garbage
|
// The number of bytes Wren will allocate before triggering the first garbage
|
||||||
// collection.
|
// collection.
|
||||||
//
|
//
|
||||||
@ -237,8 +237,8 @@ void wrenReleaseValue(WrenVM* vm, WrenValue* value);
|
|||||||
// the foreign object's data.
|
// the foreign object's data.
|
||||||
void* wrenAllocateForeign(WrenVM* vm, size_t size);
|
void* wrenAllocateForeign(WrenVM* vm, size_t size);
|
||||||
|
|
||||||
// Returns the number of arguments available to the current foreign method.
|
// Returns the number of slots available to the current foreign method.
|
||||||
int wrenGetArgumentCount(WrenVM* vm);
|
int wrenGetSlotCount(WrenVM* vm);
|
||||||
|
|
||||||
// The following functions read one of the arguments passed to a foreign call.
|
// The following functions read one of the arguments passed to a foreign call.
|
||||||
// They may only be called while within a function provided to
|
// They may only be called while within a function provided to
|
||||||
@ -260,32 +260,37 @@ int wrenGetArgumentCount(WrenVM* vm);
|
|||||||
//
|
//
|
||||||
// It is an error to pass an invalid argument index.
|
// It is an error to pass an invalid argument index.
|
||||||
|
|
||||||
// Reads a boolean argument for a foreign call. Returns false if the argument
|
// Reads a boolean value from [slot].
|
||||||
// is not a boolean.
|
//
|
||||||
bool wrenGetArgumentBool(WrenVM* vm, int index);
|
// It is an error to call this if the slot does not contain a boolean value.
|
||||||
|
bool wrenGetSlotBool(WrenVM* vm, int slot);
|
||||||
|
|
||||||
// Reads a numeric argument for a foreign call. Returns 0 if the argument is not
|
// Reads a number from [slot].
|
||||||
// a number.
|
//
|
||||||
double wrenGetArgumentDouble(WrenVM* vm, int index);
|
// It is an error to call this if the slot does not contain a number.
|
||||||
|
double wrenGetSlotDouble(WrenVM* vm, int slot);
|
||||||
|
|
||||||
// Reads a foreign object argument for a foreign call and returns a pointer to
|
// Reads a foreign object from [slot] and returns a pointer to the foreign data
|
||||||
// the foreign data stored with it. Returns NULL if the argument is not a
|
// stored with it.
|
||||||
// foreign object.
|
//
|
||||||
void* wrenGetArgumentForeign(WrenVM* vm, int index);
|
// It is an error to call this if the slot does not contain an instance of a
|
||||||
|
// foreign class.
|
||||||
|
void* wrenGetSlotForeign(WrenVM* vm, int slot);
|
||||||
|
|
||||||
// Reads an string argument for a foreign call. Returns NULL if the argument is
|
// Reads a string from [slot].
|
||||||
// not a string.
|
|
||||||
//
|
//
|
||||||
// The memory for the returned string is owned by Wren. You can inspect it
|
// The memory for the returned string is owned by Wren. You can inspect it
|
||||||
// while in your foreign function, but cannot keep a pointer to it after the
|
// while in your foreign method, but cannot keep a pointer to it after the
|
||||||
// function returns, since the garbage collector may reclaim it.
|
// function returns, since the garbage collector may reclaim it.
|
||||||
const char* wrenGetArgumentString(WrenVM* vm, int index);
|
//
|
||||||
|
// It is an error to call this if the slot does not contain a string.
|
||||||
|
const char* wrenGetSlotString(WrenVM* vm, int slot);
|
||||||
|
|
||||||
// Creates a handle for the value passed as an argument to a foreign call.
|
// Creates a handle for the value stored in [slot].
|
||||||
//
|
//
|
||||||
// This will prevent the object that is referred to from being garbage collected
|
// This will prevent the object that is referred to from being garbage collected
|
||||||
// until the handle is released by calling [wrenReleaseValue()].
|
// until the handle is released by calling [wrenReleaseValue()].
|
||||||
WrenValue* wrenGetArgumentValue(WrenVM* vm, int index);
|
WrenValue* wrenGetSlotValue(WrenVM* vm, int slot);
|
||||||
|
|
||||||
// The following functions provide the return value for a foreign method back
|
// The following functions provide the return value for a foreign method back
|
||||||
// to Wren. Like above, they may only be called during a foreign call invoked
|
// to Wren. Like above, they may only be called during a foreign call invoked
|
||||||
|
|||||||
@ -33,7 +33,7 @@ static void shutdownStdin()
|
|||||||
free(stdinStream);
|
free(stdinStream);
|
||||||
stdinStream = NULL;
|
stdinStream = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stdinOnData != NULL)
|
if (stdinOnData != NULL)
|
||||||
{
|
{
|
||||||
wrenReleaseValue(getVM(), stdinOnData);
|
wrenReleaseValue(getVM(), stdinOnData);
|
||||||
@ -51,16 +51,16 @@ void fileAllocate(WrenVM* vm)
|
|||||||
// Store the file descriptor in the foreign data, so that we can get to it
|
// Store the file descriptor in the foreign data, so that we can get to it
|
||||||
// in the finalizer.
|
// in the finalizer.
|
||||||
int* fd = (int*)wrenAllocateForeign(vm, sizeof(int));
|
int* fd = (int*)wrenAllocateForeign(vm, sizeof(int));
|
||||||
*fd = (int)wrenGetArgumentDouble(vm, 1);
|
*fd = (int)wrenGetSlotDouble(vm, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fileFinalize(WrenVM* vm)
|
void fileFinalize(WrenVM* vm)
|
||||||
{
|
{
|
||||||
int fd = *(int*)wrenGetArgumentForeign(vm, 0);
|
int fd = *(int*)wrenGetSlotForeign(vm, 0);
|
||||||
|
|
||||||
// Already closed.
|
// Already closed.
|
||||||
if (fd == -1) return;
|
if (fd == -1) return;
|
||||||
|
|
||||||
uv_fs_t request;
|
uv_fs_t request;
|
||||||
uv_fs_close(getLoop(), &request, fd, NULL);
|
uv_fs_close(getLoop(), &request, fd, NULL);
|
||||||
uv_fs_req_cleanup(&request);
|
uv_fs_req_cleanup(&request);
|
||||||
@ -73,7 +73,7 @@ void fileFinalize(WrenVM* vm)
|
|||||||
static bool handleRequestError(uv_fs_t* request)
|
static bool handleRequestError(uv_fs_t* request)
|
||||||
{
|
{
|
||||||
if (request->result >= 0) return false;
|
if (request->result >= 0) return false;
|
||||||
|
|
||||||
FileRequestData* data = (FileRequestData*)request->data;
|
FileRequestData* data = (FileRequestData*)request->data;
|
||||||
WrenValue* fiber = (WrenValue*)data->fiber;
|
WrenValue* fiber = (WrenValue*)data->fiber;
|
||||||
|
|
||||||
@ -115,18 +115,18 @@ WrenValue* freeRequest(uv_fs_t* request)
|
|||||||
static void openCallback(uv_fs_t* request)
|
static void openCallback(uv_fs_t* request)
|
||||||
{
|
{
|
||||||
if (handleRequestError(request)) return;
|
if (handleRequestError(request)) return;
|
||||||
|
|
||||||
double fd = (double)request->result;
|
double fd = (double)request->result;
|
||||||
WrenValue* fiber = freeRequest(request);
|
WrenValue* fiber = freeRequest(request);
|
||||||
|
|
||||||
schedulerResumeDouble(fiber, fd);
|
schedulerResumeDouble(fiber, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fileOpen(WrenVM* vm)
|
void fileOpen(WrenVM* vm)
|
||||||
{
|
{
|
||||||
const char* path = wrenGetArgumentString(vm, 1);
|
const char* path = wrenGetSlotString(vm, 1);
|
||||||
uv_fs_t* request = createRequest(wrenGetArgumentValue(vm, 2));
|
uv_fs_t* request = createRequest(wrenGetSlotValue(vm, 2));
|
||||||
|
|
||||||
// TODO: Allow controlling flags and modes.
|
// TODO: Allow controlling flags and modes.
|
||||||
uv_fs_open(getLoop(), request, path, O_RDONLY, 0, openCallback);
|
uv_fs_open(getLoop(), request, path, O_RDONLY, 0, openCallback);
|
||||||
}
|
}
|
||||||
@ -135,51 +135,51 @@ void fileOpen(WrenVM* vm)
|
|||||||
static void sizeCallback(uv_fs_t* request)
|
static void sizeCallback(uv_fs_t* request)
|
||||||
{
|
{
|
||||||
if (handleRequestError(request)) return;
|
if (handleRequestError(request)) return;
|
||||||
|
|
||||||
double size = (double)request->statbuf.st_size;
|
double size = (double)request->statbuf.st_size;
|
||||||
WrenValue* fiber = freeRequest(request);
|
WrenValue* fiber = freeRequest(request);
|
||||||
|
|
||||||
schedulerResumeDouble(fiber, size);
|
schedulerResumeDouble(fiber, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fileSizePath(WrenVM* vm)
|
void fileSizePath(WrenVM* vm)
|
||||||
{
|
{
|
||||||
const char* path = wrenGetArgumentString(vm, 1);
|
const char* path = wrenGetSlotString(vm, 1);
|
||||||
uv_fs_t* request = createRequest(wrenGetArgumentValue(vm, 2));
|
uv_fs_t* request = createRequest(wrenGetSlotValue(vm, 2));
|
||||||
uv_fs_stat(getLoop(), request, path, sizeCallback);
|
uv_fs_stat(getLoop(), request, path, sizeCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void closeCallback(uv_fs_t* request)
|
static void closeCallback(uv_fs_t* request)
|
||||||
{
|
{
|
||||||
if (handleRequestError(request)) return;
|
if (handleRequestError(request)) return;
|
||||||
|
|
||||||
WrenValue* fiber = freeRequest(request);
|
WrenValue* fiber = freeRequest(request);
|
||||||
schedulerResume(fiber);
|
schedulerResume(fiber);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fileClose(WrenVM* vm)
|
void fileClose(WrenVM* vm)
|
||||||
{
|
{
|
||||||
int* foreign = (int*)wrenGetArgumentForeign(vm, 0);
|
int* foreign = (int*)wrenGetSlotForeign(vm, 0);
|
||||||
int fd = *foreign;
|
int fd = *foreign;
|
||||||
|
|
||||||
// If it's already closed, we're done.
|
// If it's already closed, we're done.
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
{
|
{
|
||||||
wrenReturnBool(vm, true);
|
wrenReturnBool(vm, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark it closed immediately.
|
// Mark it closed immediately.
|
||||||
*foreign = -1;
|
*foreign = -1;
|
||||||
|
|
||||||
uv_fs_t* request = createRequest(wrenGetArgumentValue(vm, 1));
|
uv_fs_t* request = createRequest(wrenGetSlotValue(vm, 1));
|
||||||
uv_fs_close(getLoop(), request, fd, closeCallback);
|
uv_fs_close(getLoop(), request, fd, closeCallback);
|
||||||
wrenReturnBool(vm, false);
|
wrenReturnBool(vm, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fileDescriptor(WrenVM* vm)
|
void fileDescriptor(WrenVM* vm)
|
||||||
{
|
{
|
||||||
int* foreign = (int*)wrenGetArgumentForeign(vm, 0);
|
int* foreign = (int*)wrenGetSlotForeign(vm, 0);
|
||||||
int fd = *foreign;
|
int fd = *foreign;
|
||||||
wrenReturnDouble(vm, fd);
|
wrenReturnDouble(vm, fd);
|
||||||
}
|
}
|
||||||
@ -197,35 +197,35 @@ static void fileReadBytesCallback(uv_fs_t* request)
|
|||||||
// embedding API supported a way to *give* it bytes that were previously
|
// embedding API supported a way to *give* it bytes that were previously
|
||||||
// allocated using Wren's own allocator.
|
// allocated using Wren's own allocator.
|
||||||
schedulerResumeBytes(fiber, buffer.base, buffer.len);
|
schedulerResumeBytes(fiber, buffer.base, buffer.len);
|
||||||
|
|
||||||
// TODO: Likewise, freeing this after we resume is lame.
|
// TODO: Likewise, freeing this after we resume is lame.
|
||||||
free(buffer.base);
|
free(buffer.base);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fileReadBytes(WrenVM* vm)
|
void fileReadBytes(WrenVM* vm)
|
||||||
{
|
{
|
||||||
uv_fs_t* request = createRequest(wrenGetArgumentValue(vm, 2));
|
uv_fs_t* request = createRequest(wrenGetSlotValue(vm, 2));
|
||||||
|
|
||||||
int fd = *(int*)wrenGetArgumentForeign(vm, 0);
|
int fd = *(int*)wrenGetSlotForeign(vm, 0);
|
||||||
// TODO: Assert fd != -1.
|
// TODO: Assert fd != -1.
|
||||||
|
|
||||||
FileRequestData* data = (FileRequestData*)request->data;
|
FileRequestData* data = (FileRequestData*)request->data;
|
||||||
size_t length = (size_t)wrenGetArgumentDouble(vm, 1);
|
size_t length = (size_t)wrenGetSlotDouble(vm, 1);
|
||||||
|
|
||||||
data->buffer.len = length;
|
data->buffer.len = length;
|
||||||
data->buffer.base = (char*)malloc(length);
|
data->buffer.base = (char*)malloc(length);
|
||||||
|
|
||||||
// TODO: Allow passing in offset.
|
// TODO: Allow passing in offset.
|
||||||
uv_fs_read(getLoop(), request, fd, &data->buffer, 1, 0, fileReadBytesCallback);
|
uv_fs_read(getLoop(), request, fd, &data->buffer, 1, 0, fileReadBytesCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fileSize(WrenVM* vm)
|
void fileSize(WrenVM* vm)
|
||||||
{
|
{
|
||||||
uv_fs_t* request = createRequest(wrenGetArgumentValue(vm, 1));
|
uv_fs_t* request = createRequest(wrenGetSlotValue(vm, 1));
|
||||||
|
|
||||||
int fd = *(int*)wrenGetArgumentForeign(vm, 0);
|
int fd = *(int*)wrenGetSlotForeign(vm, 0);
|
||||||
// TODO: Assert fd != -1.
|
// TODO: Assert fd != -1.
|
||||||
|
|
||||||
uv_fs_fstat(getLoop(), request, fd, sizeCallback);
|
uv_fs_fstat(getLoop(), request, fd, sizeCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,9 +247,9 @@ static void stdinReadCallback(uv_stream_t* stream, ssize_t numRead,
|
|||||||
shutdownStdin();
|
shutdownStdin();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Handle other errors.
|
// TODO: Handle other errors.
|
||||||
|
|
||||||
if (stdinOnData == NULL)
|
if (stdinOnData == NULL)
|
||||||
{
|
{
|
||||||
stdinOnData = wrenGetMethod(getVM(), "io", "Stdin", "onData_(_)");
|
stdinOnData = wrenGetMethod(getVM(), "io", "Stdin", "onData_(_)");
|
||||||
@ -259,7 +259,7 @@ static void stdinReadCallback(uv_stream_t* stream, ssize_t numRead,
|
|||||||
// embedding API supported a way to *give* it bytes that were previously
|
// embedding API supported a way to *give* it bytes that were previously
|
||||||
// allocated using Wren's own allocator.
|
// allocated using Wren's own allocator.
|
||||||
wrenCall(getVM(), stdinOnData, NULL, "a", buffer->base, numRead);
|
wrenCall(getVM(), stdinOnData, NULL, "a", buffer->base, numRead);
|
||||||
|
|
||||||
// TODO: Likewise, freeing this after we resume is lame.
|
// TODO: Likewise, freeing this after we resume is lame.
|
||||||
free(buffer->base);
|
free(buffer->base);
|
||||||
}
|
}
|
||||||
@ -284,7 +284,7 @@ void stdinReadStart(WrenVM* vm)
|
|||||||
stdinStream = (uv_stream_t*)handle;
|
stdinStream = (uv_stream_t*)handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uv_read_start(stdinStream, allocCallback, stdinReadCallback);
|
uv_read_start(stdinStream, allocCallback, stdinReadCallback);
|
||||||
// TODO: Check return.
|
// TODO: Check return.
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,8 +27,8 @@ static void timerCallback(uv_timer_t* handle)
|
|||||||
|
|
||||||
void timerStartTimer(WrenVM* vm)
|
void timerStartTimer(WrenVM* vm)
|
||||||
{
|
{
|
||||||
int milliseconds = (int)wrenGetArgumentDouble(vm, 1);
|
int milliseconds = (int)wrenGetSlotDouble(vm, 1);
|
||||||
WrenValue* fiber = wrenGetArgumentValue(vm, 2);
|
WrenValue* fiber = wrenGetSlotValue(vm, 2);
|
||||||
|
|
||||||
// Store the fiber to resume when the timer completes.
|
// Store the fiber to resume when the timer completes.
|
||||||
uv_timer_t* handle = (uv_timer_t*)malloc(sizeof(uv_timer_t));
|
uv_timer_t* handle = (uv_timer_t*)malloc(sizeof(uv_timer_t));
|
||||||
|
|||||||
@ -18,7 +18,7 @@ void metaCompile(WrenVM* vm)
|
|||||||
: AS_CLOSURE(callingFn)->fn->module;
|
: AS_CLOSURE(callingFn)->fn->module;
|
||||||
|
|
||||||
// Compile it.
|
// Compile it.
|
||||||
ObjFn* fn = wrenCompile(vm, module, wrenGetArgumentString(vm, 1), false);
|
ObjFn* fn = wrenCompile(vm, module, wrenGetSlotString(vm, 1), false);
|
||||||
if (fn == NULL) return;
|
if (fn == NULL) return;
|
||||||
|
|
||||||
// Return the result. We can't use the public API for this since we have a
|
// Return the result. We can't use the public API for this since we have a
|
||||||
|
|||||||
@ -45,7 +45,7 @@ static void randomAllocate(WrenVM* vm)
|
|||||||
|
|
||||||
static void randomSeed0(WrenVM* vm)
|
static void randomSeed0(WrenVM* vm)
|
||||||
{
|
{
|
||||||
Well512* well = (Well512*)wrenGetArgumentForeign(vm, 0);
|
Well512* well = (Well512*)wrenGetSlotForeign(vm, 0);
|
||||||
|
|
||||||
srand((uint32_t)time(NULL));
|
srand((uint32_t)time(NULL));
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
@ -56,9 +56,9 @@ static void randomSeed0(WrenVM* vm)
|
|||||||
|
|
||||||
static void randomSeed1(WrenVM* vm)
|
static void randomSeed1(WrenVM* vm)
|
||||||
{
|
{
|
||||||
Well512* well = (Well512*)wrenGetArgumentForeign(vm, 0);
|
Well512* well = (Well512*)wrenGetSlotForeign(vm, 0);
|
||||||
|
|
||||||
srand((uint32_t)wrenGetArgumentDouble(vm, 1));
|
srand((uint32_t)wrenGetSlotDouble(vm, 1));
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
well->state[i] = rand();
|
well->state[i] = rand();
|
||||||
@ -67,17 +67,17 @@ static void randomSeed1(WrenVM* vm)
|
|||||||
|
|
||||||
static void randomSeed16(WrenVM* vm)
|
static void randomSeed16(WrenVM* vm)
|
||||||
{
|
{
|
||||||
Well512* well = (Well512*)wrenGetArgumentForeign(vm, 0);
|
Well512* well = (Well512*)wrenGetSlotForeign(vm, 0);
|
||||||
|
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
well->state[i] = (uint32_t)wrenGetArgumentDouble(vm, i + 1);
|
well->state[i] = (uint32_t)wrenGetSlotDouble(vm, i + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void randomFloat(WrenVM* vm)
|
static void randomFloat(WrenVM* vm)
|
||||||
{
|
{
|
||||||
Well512* well = (Well512*)wrenGetArgumentForeign(vm, 0);
|
Well512* well = (Well512*)wrenGetSlotForeign(vm, 0);
|
||||||
|
|
||||||
// A double has 53 bits of precision in its mantissa, and we'd like to take
|
// A double has 53 bits of precision in its mantissa, and we'd like to take
|
||||||
// full advantage of that, so we need 53 bits of random source data.
|
// full advantage of that, so we need 53 bits of random source data.
|
||||||
@ -97,7 +97,7 @@ static void randomFloat(WrenVM* vm)
|
|||||||
|
|
||||||
static void randomInt0(WrenVM* vm)
|
static void randomInt0(WrenVM* vm)
|
||||||
{
|
{
|
||||||
Well512* well = (Well512*)wrenGetArgumentForeign(vm, 0);
|
Well512* well = (Well512*)wrenGetSlotForeign(vm, 0);
|
||||||
|
|
||||||
wrenReturnDouble(vm, (double)advanceState(well));
|
wrenReturnDouble(vm, (double)advanceState(well));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -74,6 +74,7 @@
|
|||||||
#define IS_FN(value) (wrenIsObjType(value, OBJ_FN)) // ObjFn
|
#define IS_FN(value) (wrenIsObjType(value, OBJ_FN)) // ObjFn
|
||||||
#define IS_FOREIGN(value) (wrenIsObjType(value, OBJ_FOREIGN)) // ObjForeign
|
#define IS_FOREIGN(value) (wrenIsObjType(value, OBJ_FOREIGN)) // ObjForeign
|
||||||
#define IS_INSTANCE(value) (wrenIsObjType(value, OBJ_INSTANCE)) // ObjInstance
|
#define IS_INSTANCE(value) (wrenIsObjType(value, OBJ_INSTANCE)) // ObjInstance
|
||||||
|
#define IS_LIST(value) (wrenIsObjType(value, OBJ_LIST)) // ObjList
|
||||||
#define IS_RANGE(value) (wrenIsObjType(value, OBJ_RANGE)) // ObjRange
|
#define IS_RANGE(value) (wrenIsObjType(value, OBJ_RANGE)) // ObjRange
|
||||||
#define IS_STRING(value) (wrenIsObjType(value, OBJ_STRING)) // ObjString
|
#define IS_STRING(value) (wrenIsObjType(value, OBJ_STRING)) // ObjString
|
||||||
|
|
||||||
|
|||||||
@ -439,21 +439,21 @@ static inline void callFunction(
|
|||||||
sizeof(CallFrame) * max);
|
sizeof(CallFrame) * max);
|
||||||
fiber->frameCapacity = max;
|
fiber->frameCapacity = max;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grow the stack if needed.
|
// Grow the stack if needed.
|
||||||
int stackSize = (int)(fiber->stackTop - fiber->stack);
|
int stackSize = (int)(fiber->stackTop - fiber->stack);
|
||||||
int needed = stackSize + wrenUpwrapClosure(function)->maxSlots;
|
int needed = stackSize + wrenUpwrapClosure(function)->maxSlots;
|
||||||
|
|
||||||
if (fiber->stackCapacity < needed)
|
if (fiber->stackCapacity < needed)
|
||||||
{
|
{
|
||||||
int capacity = wrenPowerOf2Ceil(needed);
|
int capacity = wrenPowerOf2Ceil(needed);
|
||||||
|
|
||||||
Value* oldStack = fiber->stack;
|
Value* oldStack = fiber->stack;
|
||||||
fiber->stack = (Value*)wrenReallocate(vm, fiber->stack,
|
fiber->stack = (Value*)wrenReallocate(vm, fiber->stack,
|
||||||
sizeof(Value) * fiber->stackCapacity,
|
sizeof(Value) * fiber->stackCapacity,
|
||||||
sizeof(Value) * capacity);
|
sizeof(Value) * capacity);
|
||||||
fiber->stackCapacity = capacity;
|
fiber->stackCapacity = capacity;
|
||||||
|
|
||||||
// If the reallocation moves the stack, then we need to shift every pointer
|
// If the reallocation moves the stack, then we need to shift every pointer
|
||||||
// into the stack to point to its new location.
|
// into the stack to point to its new location.
|
||||||
if (fiber->stack != oldStack)
|
if (fiber->stack != oldStack)
|
||||||
@ -461,13 +461,13 @@ static inline void callFunction(
|
|||||||
// Top of the stack.
|
// Top of the stack.
|
||||||
long offset = fiber->stack - oldStack;
|
long offset = fiber->stack - oldStack;
|
||||||
fiber->stackTop += offset;
|
fiber->stackTop += offset;
|
||||||
|
|
||||||
// Stack pointer for each call frame.
|
// Stack pointer for each call frame.
|
||||||
for (int i = 0; i < fiber->numFrames; i++)
|
for (int i = 0; i < fiber->numFrames; i++)
|
||||||
{
|
{
|
||||||
fiber->frames[i].stackStart += offset;
|
fiber->frames[i].stackStart += offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open upvalues.
|
// Open upvalues.
|
||||||
for (ObjUpvalue* upvalue = fiber->openUpvalues;
|
for (ObjUpvalue* upvalue = fiber->openUpvalues;
|
||||||
upvalue != NULL;
|
upvalue != NULL;
|
||||||
@ -1148,10 +1148,10 @@ static WrenInterpretResult runInterpreter(WrenVM* vm, register ObjFiber* fiber)
|
|||||||
// See if there's another fiber to return to.
|
// See if there's another fiber to return to.
|
||||||
ObjFiber* callingFiber = fiber->caller;
|
ObjFiber* callingFiber = fiber->caller;
|
||||||
fiber->caller = NULL;
|
fiber->caller = NULL;
|
||||||
|
|
||||||
fiber = callingFiber;
|
fiber = callingFiber;
|
||||||
vm->fiber = fiber;
|
vm->fiber = fiber;
|
||||||
|
|
||||||
// If not, we're done.
|
// If not, we're done.
|
||||||
if (fiber == NULL) return WREN_RESULT_SUCCESS;
|
if (fiber == NULL) return WREN_RESULT_SUCCESS;
|
||||||
|
|
||||||
@ -1624,10 +1624,10 @@ void wrenPopRoot(WrenVM* vm)
|
|||||||
vm->numTempRoots--;
|
vm->numTempRoots--;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wrenGetArgumentCount(WrenVM* vm)
|
int wrenGetSlotCount(WrenVM* vm)
|
||||||
{
|
{
|
||||||
ASSERT(vm->foreignStackStart != NULL, "Must be in foreign call.");
|
ASSERT(vm->foreignStackStart != NULL, "Must be in foreign call.");
|
||||||
|
|
||||||
// If no fiber is executing, we must be in a finalizer, in which case the
|
// If no fiber is executing, we must be in a finalizer, in which case the
|
||||||
// "stack" just has one object, the object being finalized.
|
// "stack" just has one object, the object being finalized.
|
||||||
if (vm->fiber == NULL) return 1;
|
if (vm->fiber == NULL) return 1;
|
||||||
@ -1635,54 +1635,52 @@ int wrenGetArgumentCount(WrenVM* vm)
|
|||||||
return (int)(vm->fiber->stackTop - vm->foreignStackStart);
|
return (int)(vm->fiber->stackTop - vm->foreignStackStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void validateForeignArgument(WrenVM* vm, int index)
|
// Ensures that [slot] is a valid index into a foreign method's stack of slots.
|
||||||
|
static void validateForeignSlot(WrenVM* vm, int slot)
|
||||||
{
|
{
|
||||||
ASSERT(vm->foreignStackStart != NULL, "Must be in foreign call.");
|
ASSERT(vm->foreignStackStart != NULL, "Must be in foreign call.");
|
||||||
ASSERT(index >= 0, "index cannot be negative.");
|
ASSERT(slot >= 0, "Slot cannot be negative.");
|
||||||
ASSERT(index < wrenGetArgumentCount(vm), "Not that many arguments.");
|
ASSERT(slot < wrenGetSlotCount(vm), "Not that many slots.");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wrenGetArgumentBool(WrenVM* vm, int index)
|
bool wrenGetSlotBool(WrenVM* vm, int slot)
|
||||||
{
|
{
|
||||||
validateForeignArgument(vm, index);
|
validateForeignSlot(vm, slot);
|
||||||
|
ASSERT(IS_BOOL(vm->foreignStackStart[slot]), "Slot must hold a bool.");
|
||||||
|
|
||||||
if (!IS_BOOL(vm->foreignStackStart[index])) return false;
|
return AS_BOOL(vm->foreignStackStart[slot]);
|
||||||
|
|
||||||
return AS_BOOL(vm->foreignStackStart[index]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double wrenGetArgumentDouble(WrenVM* vm, int index)
|
double wrenGetSlotDouble(WrenVM* vm, int slot)
|
||||||
{
|
{
|
||||||
validateForeignArgument(vm, index);
|
validateForeignSlot(vm, slot);
|
||||||
|
ASSERT(IS_NUM(vm->foreignStackStart[slot]), "Slot must hold a number.");
|
||||||
|
|
||||||
if (!IS_NUM(vm->foreignStackStart[index])) return 0.0;
|
return AS_NUM(vm->foreignStackStart[slot]);
|
||||||
|
|
||||||
return AS_NUM(vm->foreignStackStart[index]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void* wrenGetArgumentForeign(WrenVM* vm, int index)
|
void* wrenGetSlotForeign(WrenVM* vm, int slot)
|
||||||
{
|
{
|
||||||
validateForeignArgument(vm, index);
|
validateForeignSlot(vm, slot);
|
||||||
|
ASSERT(IS_FOREIGN(vm->foreignStackStart[slot]),
|
||||||
|
"Slot must hold a foreign instance.");
|
||||||
|
|
||||||
if (!IS_FOREIGN(vm->foreignStackStart[index])) return NULL;
|
return AS_FOREIGN(vm->foreignStackStart[slot])->data;
|
||||||
|
|
||||||
return AS_FOREIGN(vm->foreignStackStart[index])->data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* wrenGetArgumentString(WrenVM* vm, int index)
|
const char* wrenGetSlotString(WrenVM* vm, int slot)
|
||||||
{
|
{
|
||||||
validateForeignArgument(vm, index);
|
validateForeignSlot(vm, slot);
|
||||||
|
ASSERT(IS_STRING(vm->foreignStackStart[slot]), "Slot must hold a string.");
|
||||||
|
|
||||||
if (!IS_STRING(vm->foreignStackStart[index])) return NULL;
|
return AS_CSTRING(vm->foreignStackStart[slot]);
|
||||||
|
|
||||||
return AS_CSTRING(vm->foreignStackStart[index]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WrenValue* wrenGetArgumentValue(WrenVM* vm, int index)
|
WrenValue* wrenGetSlotValue(WrenVM* vm, int slot)
|
||||||
{
|
{
|
||||||
validateForeignArgument(vm, index);
|
validateForeignSlot(vm, slot);
|
||||||
|
|
||||||
return wrenCaptureValue(vm, vm->foreignStackStart[index]);
|
return wrenCaptureValue(vm, vm->foreignStackStart[slot]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wrenReturnBool(WrenVM* vm, bool value)
|
void wrenReturnBool(WrenVM* vm, bool value)
|
||||||
|
|||||||
@ -5,17 +5,18 @@
|
|||||||
static void arguments(WrenVM* vm)
|
static void arguments(WrenVM* vm)
|
||||||
{
|
{
|
||||||
double result = 0;
|
double result = 0;
|
||||||
result += wrenGetArgumentDouble(vm, 1);
|
|
||||||
result += wrenGetArgumentDouble(vm, 2);
|
result += wrenGetSlotDouble(vm, 1);
|
||||||
result += wrenGetArgumentDouble(vm, 3);
|
result += wrenGetSlotDouble(vm, 2);
|
||||||
result += wrenGetArgumentDouble(vm, 4);
|
result += wrenGetSlotDouble(vm, 3);
|
||||||
|
result += wrenGetSlotDouble(vm, 4);
|
||||||
|
|
||||||
wrenReturnDouble(vm, result);
|
wrenReturnDouble(vm, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
WrenForeignMethodFn benchmarkBindMethod(const char* signature)
|
WrenForeignMethodFn benchmarkBindMethod(const char* signature)
|
||||||
{
|
{
|
||||||
if (strcmp(signature, "static Benchmark.arguments(_,_,_,_)") == 0) return arguments;
|
if (strcmp(signature, "static Benchmark.arguments(_,_,_,_)") == 0) return arguments;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,15 +18,15 @@ static void counterAllocate(WrenVM* vm)
|
|||||||
|
|
||||||
static void counterIncrement(WrenVM* vm)
|
static void counterIncrement(WrenVM* vm)
|
||||||
{
|
{
|
||||||
double* value = (double*)wrenGetArgumentForeign(vm, 0);
|
double* value = (double*)wrenGetSlotForeign(vm, 0);
|
||||||
double increment = wrenGetArgumentDouble(vm, 1);
|
double increment = wrenGetSlotDouble(vm, 1);
|
||||||
|
|
||||||
*value += increment;
|
*value += increment;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void counterValue(WrenVM* vm)
|
static void counterValue(WrenVM* vm)
|
||||||
{
|
{
|
||||||
double value = *(double*)wrenGetArgumentForeign(vm, 0);
|
double value = *(double*)wrenGetSlotForeign(vm, 0);
|
||||||
wrenReturnDouble(vm, value);
|
wrenReturnDouble(vm, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,9 +34,9 @@ static void pointAllocate(WrenVM* vm)
|
|||||||
{
|
{
|
||||||
double* coordinates = (double*)wrenAllocateForeign(vm, sizeof(double[3]));
|
double* coordinates = (double*)wrenAllocateForeign(vm, sizeof(double[3]));
|
||||||
|
|
||||||
// This gets called by both constructors, so sniff the argument count to see
|
// This gets called by both constructors, so sniff the slot count to see
|
||||||
// which one was invoked.
|
// which one was invoked.
|
||||||
if (wrenGetArgumentCount(vm) == 1)
|
if (wrenGetSlotCount(vm) == 1)
|
||||||
{
|
{
|
||||||
coordinates[0] = 0.0;
|
coordinates[0] = 0.0;
|
||||||
coordinates[1] = 0.0;
|
coordinates[1] = 0.0;
|
||||||
@ -44,23 +44,23 @@ static void pointAllocate(WrenVM* vm)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
coordinates[0] = wrenGetArgumentDouble(vm, 1);
|
coordinates[0] = wrenGetSlotDouble(vm, 1);
|
||||||
coordinates[1] = wrenGetArgumentDouble(vm, 2);
|
coordinates[1] = wrenGetSlotDouble(vm, 2);
|
||||||
coordinates[2] = wrenGetArgumentDouble(vm, 3);
|
coordinates[2] = wrenGetSlotDouble(vm, 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pointTranslate(WrenVM* vm)
|
static void pointTranslate(WrenVM* vm)
|
||||||
{
|
{
|
||||||
double* coordinates = (double*)wrenGetArgumentForeign(vm, 0);
|
double* coordinates = (double*)wrenGetSlotForeign(vm, 0);
|
||||||
coordinates[0] += wrenGetArgumentDouble(vm, 1);
|
coordinates[0] += wrenGetSlotDouble(vm, 1);
|
||||||
coordinates[1] += wrenGetArgumentDouble(vm, 2);
|
coordinates[1] += wrenGetSlotDouble(vm, 2);
|
||||||
coordinates[2] += wrenGetArgumentDouble(vm, 3);
|
coordinates[2] += wrenGetSlotDouble(vm, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pointToString(WrenVM* vm)
|
static void pointToString(WrenVM* vm)
|
||||||
{
|
{
|
||||||
double* coordinates = (double*)wrenGetArgumentForeign(vm, 0);
|
double* coordinates = (double*)wrenGetSlotForeign(vm, 0);
|
||||||
char result[100];
|
char result[100];
|
||||||
sprintf(result, "(%g, %g, %g)",
|
sprintf(result, "(%g, %g, %g)",
|
||||||
coordinates[0], coordinates[1], coordinates[2]);
|
coordinates[0], coordinates[1], coordinates[2]);
|
||||||
|
|||||||
@ -6,7 +6,7 @@ static WrenValue* value;
|
|||||||
|
|
||||||
static void setValue(WrenVM* vm)
|
static void setValue(WrenVM* vm)
|
||||||
{
|
{
|
||||||
value = wrenGetArgumentValue(vm, 1);
|
value = wrenGetSlotValue(vm, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void getValue(WrenVM* vm)
|
static void getValue(WrenVM* vm)
|
||||||
|
|||||||
Reference in New Issue
Block a user