mirror of
https://github.com/janet-lang/janet
synced 2024-06-16 10:19:55 +00:00
Reintroduce a separate Thread objects for threads instead of using arrays.
This commit is contained in:
parent
d28a7174af
commit
8cdc0610e3
47
datatypes.h
47
datatypes.h
|
@ -4,10 +4,6 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
|
|
||||||
#define THREAD_STATUS_ALIVE 0
|
|
||||||
#define THREAD_STATUS_DEAD 1
|
|
||||||
#define THREAD_STATUS_PENDING 2
|
|
||||||
|
|
||||||
typedef enum Type {
|
typedef enum Type {
|
||||||
TYPE_NIL = 0,
|
TYPE_NIL = 0,
|
||||||
TYPE_NUMBER,
|
TYPE_NUMBER,
|
||||||
|
@ -39,6 +35,7 @@ typedef struct Parser Parser;
|
||||||
typedef struct ParseState ParseState;
|
typedef struct ParseState ParseState;
|
||||||
typedef struct Scope Scope;
|
typedef struct Scope Scope;
|
||||||
typedef struct Compiler Compiler;
|
typedef struct Compiler Compiler;
|
||||||
|
typedef struct Thread Thread;
|
||||||
typedef struct StackFrame StackFrame;
|
typedef struct StackFrame StackFrame;
|
||||||
|
|
||||||
union ValueData {
|
union ValueData {
|
||||||
|
@ -49,28 +46,49 @@ union ValueData {
|
||||||
Buffer * buffer;
|
Buffer * buffer;
|
||||||
Dictionary * dict;
|
Dictionary * dict;
|
||||||
Func * func;
|
Func * func;
|
||||||
|
Thread * thread;
|
||||||
void * pointer;
|
void * pointer;
|
||||||
CFunction cfunction;
|
CFunction cfunction;
|
||||||
uint16_t u16[4];
|
uint16_t u16[4];
|
||||||
uint8_t u8[8];
|
uint8_t u8[8];
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
|
struct Value {
|
||||||
|
Type type;
|
||||||
|
ValueData data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Thread {
|
||||||
|
uint32_t count;
|
||||||
|
uint32_t capacity;
|
||||||
|
Value * data;
|
||||||
|
enum {
|
||||||
|
THREAD_PENDING = 0,
|
||||||
|
THREAD_ALIVE,
|
||||||
|
TRHEAD_DEAD
|
||||||
|
} status;
|
||||||
|
};
|
||||||
|
|
||||||
struct Array {
|
struct Array {
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
uint32_t capacity;
|
uint32_t capacity;
|
||||||
Value * data;
|
Value * data;
|
||||||
|
uint32_t flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Buffer {
|
struct Buffer {
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
uint32_t capacity;
|
uint32_t capacity;
|
||||||
uint8_t * data;
|
uint8_t * data;
|
||||||
|
uint32_t flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Dictionary {
|
struct Dictionary {
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
uint32_t capacity;
|
uint32_t capacity;
|
||||||
DictBucket ** buckets;
|
DictBucket ** buckets;
|
||||||
|
uint32_t flags;
|
||||||
|
Value meta;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DictionaryIterator {
|
struct DictionaryIterator {
|
||||||
|
@ -89,7 +107,7 @@ struct FuncDef {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FuncEnv {
|
struct FuncEnv {
|
||||||
Array * thread; /* When nil, index the local values */
|
Thread * thread; /* When nil, index the local values */
|
||||||
uint32_t stackOffset; /* Used as environment size when off stack */
|
uint32_t stackOffset; /* Used as environment size when off stack */
|
||||||
Value * values;
|
Value * values;
|
||||||
};
|
};
|
||||||
|
@ -100,11 +118,6 @@ struct Func {
|
||||||
Func * parent;
|
Func * parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Value {
|
|
||||||
Type type;
|
|
||||||
ValueData data;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DictBucket {
|
struct DictBucket {
|
||||||
Value key;
|
Value key;
|
||||||
Value value;
|
Value value;
|
||||||
|
@ -129,21 +142,19 @@ struct VM {
|
||||||
uint32_t lock : 31;
|
uint32_t lock : 31;
|
||||||
/* Thread */
|
/* Thread */
|
||||||
uint16_t * pc;
|
uint16_t * pc;
|
||||||
Array * thread;
|
Thread * thread;
|
||||||
Value * base;
|
Value * base;
|
||||||
StackFrame * frame;
|
StackFrame * frame;
|
||||||
/* Return state */
|
/* Return state */
|
||||||
const char * error;
|
const char * error;
|
||||||
jmp_buf jump;
|
jmp_buf jump;
|
||||||
Value ret; /* Returned value from VMStart */
|
Value ret; /* Returned value from VMStart */
|
||||||
|
/* Object definitions */
|
||||||
|
Value metas[TYPE_DICTIONARY];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Parsing */
|
/* Parsing */
|
||||||
|
|
||||||
#define PARSER_PENDING 0
|
|
||||||
#define PARSER_FULL 1
|
|
||||||
#define PARSER_ERROR -1
|
|
||||||
|
|
||||||
struct Parser {
|
struct Parser {
|
||||||
VM * vm;
|
VM * vm;
|
||||||
const char * error;
|
const char * error;
|
||||||
|
@ -152,7 +163,11 @@ struct Parser {
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
uint32_t cap;
|
uint32_t cap;
|
||||||
uint32_t index;
|
uint32_t index;
|
||||||
uint32_t status;
|
enum {
|
||||||
|
PARSER_PENDING = 0,
|
||||||
|
PARSER_FULL,
|
||||||
|
PARSER_ERROR
|
||||||
|
} status;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Compiling */
|
/* Compiling */
|
||||||
|
|
3
ds.c
3
ds.c
|
@ -14,6 +14,7 @@ Buffer * BufferNew(VM * vm, uint32_t capacity) {
|
||||||
buffer->data = data;
|
buffer->data = data;
|
||||||
buffer->count = 0;
|
buffer->count = 0;
|
||||||
buffer->capacity = capacity;
|
buffer->capacity = capacity;
|
||||||
|
buffer->flags = 0;
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +76,7 @@ Array * ArrayNew(VM * vm, uint32_t capacity) {
|
||||||
array->data = data;
|
array->data = data;
|
||||||
array->count = 0;
|
array->count = 0;
|
||||||
array->capacity = capacity;
|
array->capacity = capacity;
|
||||||
|
array->flags = 0;
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,6 +156,7 @@ Dictionary * DictNew(VM * vm, uint32_t capacity) {
|
||||||
dict->buckets = buckets;
|
dict->buckets = buckets;
|
||||||
dict->capacity = capacity;
|
dict->capacity = capacity;
|
||||||
dict->count = 0;
|
dict->count = 0;
|
||||||
|
dict->flags = 0;
|
||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
5
ds.h
5
ds.h
|
@ -3,6 +3,11 @@
|
||||||
|
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Data type flags
|
||||||
|
*/
|
||||||
|
#define DS_LOCKED 0x01
|
||||||
|
|
||||||
/****/
|
/****/
|
||||||
/* Buffer functions */
|
/* Buffer functions */
|
||||||
/****/
|
/****/
|
||||||
|
|
43
vm.c
43
vm.c
|
@ -15,7 +15,7 @@ static const char VMS_EXPECTED_NUMBER_LOP[] = "Expected left operand to be numbe
|
||||||
#define FRAME_SIZE ((sizeof(StackFrame) + sizeof(Value) - 1) / sizeof(Value))
|
#define FRAME_SIZE ((sizeof(StackFrame) + sizeof(Value) - 1) / sizeof(Value))
|
||||||
|
|
||||||
/* Get the stack frame pointer for a thread */
|
/* Get the stack frame pointer for a thread */
|
||||||
static StackFrame * ThreadFrame(Array * thread) {
|
static StackFrame * ThreadFrame(Thread * thread) {
|
||||||
return (StackFrame *)(thread->data + thread->count - FRAME_SIZE);
|
return (StackFrame *)(thread->data + thread->count - FRAME_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ static void VMMarkFuncEnv(VM * vm, FuncEnv * env) {
|
||||||
GCHeader(env)->color = vm->black;
|
GCHeader(env)->color = vm->black;
|
||||||
if (env->thread) {
|
if (env->thread) {
|
||||||
temp.type = TYPE_THREAD;
|
temp.type = TYPE_THREAD;
|
||||||
temp.data.array = env->thread;
|
temp.data.thread = env->thread;
|
||||||
VMMark(vm, &temp);
|
VMMark(vm, &temp);
|
||||||
}
|
}
|
||||||
if (env->values) {
|
if (env->values) {
|
||||||
|
@ -117,8 +117,8 @@ static void VMMark(VM * vm, Value * x) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TYPE_THREAD:
|
case TYPE_THREAD:
|
||||||
if (GCHeader(x->data.array)->color != vm->black) {
|
if (GCHeader(x->data.thread)->color != vm->black) {
|
||||||
Array * thread = x->data.array;
|
Thread * thread = x->data.thread;
|
||||||
StackFrame * frame = (StackFrame *)thread->data;
|
StackFrame * frame = (StackFrame *)thread->data;
|
||||||
StackFrame * end = ThreadFrame(thread);
|
StackFrame * end = ThreadFrame(thread);
|
||||||
GCHeader(thread)->color = vm->black;
|
GCHeader(thread)->color = vm->black;
|
||||||
|
@ -220,7 +220,7 @@ void VMCollect(VM * vm) {
|
||||||
if (vm->thread) {
|
if (vm->thread) {
|
||||||
Value thread;
|
Value thread;
|
||||||
thread.type = TYPE_THREAD;
|
thread.type = TYPE_THREAD;
|
||||||
thread.data.array = vm->thread;
|
thread.data.thread = vm->thread;
|
||||||
VMMark(vm, &thread);
|
VMMark(vm, &thread);
|
||||||
}
|
}
|
||||||
VMMark(vm, &vm->ret);
|
VMMark(vm, &vm->ret);
|
||||||
|
@ -234,8 +234,19 @@ void VMMaybeCollect(VM * vm) {
|
||||||
VMCollect(vm);
|
VMCollect(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ensure that a thread has enough space in it */
|
||||||
|
static void ThreadEnsure(VM * vm, Thread * thread, uint32_t size) {
|
||||||
|
if (size > thread->capacity) {
|
||||||
|
uint32_t newCap = size * 2;
|
||||||
|
Value * newData = VMAlloc(vm, sizeof(Value) * newCap);
|
||||||
|
memcpy(newData, thread->data, thread->capacity * sizeof(Value));
|
||||||
|
thread->data = newData;
|
||||||
|
thread->capacity = newCap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Push a stack frame onto a thread */
|
/* Push a stack frame onto a thread */
|
||||||
static void VMThreadPush(VM * vm, Array * thread, Value callee, uint32_t size) {
|
static void VMThreadPush(VM * vm, Thread * thread, Value callee, uint32_t size) {
|
||||||
uint16_t oldSize;
|
uint16_t oldSize;
|
||||||
uint32_t nextCount, i;
|
uint32_t nextCount, i;
|
||||||
StackFrame * frame;
|
StackFrame * frame;
|
||||||
|
@ -246,7 +257,7 @@ static void VMThreadPush(VM * vm, Array * thread, Value callee, uint32_t size) {
|
||||||
oldSize = 0;
|
oldSize = 0;
|
||||||
}
|
}
|
||||||
nextCount = thread->count + oldSize + FRAME_SIZE;
|
nextCount = thread->count + oldSize + FRAME_SIZE;
|
||||||
ArrayEnsure(vm, thread, nextCount + size);
|
ThreadEnsure(vm, thread, nextCount + size);
|
||||||
thread->count = nextCount;
|
thread->count = nextCount;
|
||||||
/* Ensure values start out as nil so as to not confuse
|
/* Ensure values start out as nil so as to not confuse
|
||||||
* the garabage collector */
|
* the garabage collector */
|
||||||
|
@ -268,7 +279,7 @@ static void VMThreadSplitStack(VM * vm) {
|
||||||
FuncEnv * env = frame->env;
|
FuncEnv * env = frame->env;
|
||||||
/* Check for closures */
|
/* Check for closures */
|
||||||
if (env) {
|
if (env) {
|
||||||
Array * thread = vm->thread;
|
Thread * thread = vm->thread;
|
||||||
uint32_t size = frame->size;
|
uint32_t size = frame->size;
|
||||||
env->thread = NULL;
|
env->thread = NULL;
|
||||||
env->stackOffset = size;
|
env->stackOffset = size;
|
||||||
|
@ -279,7 +290,7 @@ static void VMThreadSplitStack(VM * vm) {
|
||||||
|
|
||||||
/* Pop the top-most stack frame from stack */
|
/* Pop the top-most stack frame from stack */
|
||||||
static void VMThreadPop(VM * vm) {
|
static void VMThreadPop(VM * vm) {
|
||||||
Array * thread = vm->thread;
|
Thread * thread = vm->thread;
|
||||||
StackFrame * frame = vm->frame;
|
StackFrame * frame = vm->frame;
|
||||||
uint32_t delta = FRAME_SIZE + frame->prevSize;
|
uint32_t delta = FRAME_SIZE + frame->prevSize;
|
||||||
if (thread->count) {
|
if (thread->count) {
|
||||||
|
@ -335,7 +346,7 @@ static void VMReturn(VM * vm, Value ret) {
|
||||||
|
|
||||||
/* Implementation of the opcode for function calls */
|
/* Implementation of the opcode for function calls */
|
||||||
static void VMCallOp(VM * vm) {
|
static void VMCallOp(VM * vm) {
|
||||||
Array * thread = vm->thread;
|
Thread * thread = vm->thread;
|
||||||
Value callee = vm->base[vm->pc[1]];
|
Value callee = vm->base[vm->pc[1]];
|
||||||
uint32_t arity = vm->pc[3];
|
uint32_t arity = vm->pc[3];
|
||||||
uint32_t oldCount = thread->count;
|
uint32_t oldCount = thread->count;
|
||||||
|
@ -371,7 +382,7 @@ static void VMCallOp(VM * vm) {
|
||||||
|
|
||||||
/* Implementation of the opcode for tail calls */
|
/* Implementation of the opcode for tail calls */
|
||||||
static void VMTailCallOp(VM * vm) {
|
static void VMTailCallOp(VM * vm) {
|
||||||
Array * thread = vm->thread;
|
Thread * thread = vm->thread;
|
||||||
Value callee = vm->base[vm->pc[1]];
|
Value callee = vm->base[vm->pc[1]];
|
||||||
uint32_t arity = vm->pc[2];
|
uint32_t arity = vm->pc[2];
|
||||||
uint16_t newFrameSize, currentFrameSize;
|
uint16_t newFrameSize, currentFrameSize;
|
||||||
|
@ -388,7 +399,7 @@ static void VMTailCallOp(VM * vm) {
|
||||||
}
|
}
|
||||||
/* Ensure stack has enough space for copies of arguments */
|
/* Ensure stack has enough space for copies of arguments */
|
||||||
currentFrameSize = vm->frame->size;
|
currentFrameSize = vm->frame->size;
|
||||||
ArrayEnsure(vm, thread, thread->count + currentFrameSize + arity);
|
ThreadEnsure(vm, thread, thread->count + currentFrameSize + arity);
|
||||||
vm->base = thread->data + thread->count;
|
vm->base = thread->data + thread->count;
|
||||||
/* Copy the arguments into the extra space */
|
/* Copy the arguments into the extra space */
|
||||||
for (i = 0; i < arity; ++i) {
|
for (i = 0; i < arity; ++i) {
|
||||||
|
@ -416,7 +427,7 @@ static void VMTailCallOp(VM * vm) {
|
||||||
|
|
||||||
/* Instantiate a closure */
|
/* Instantiate a closure */
|
||||||
static Value VMMakeClosure(VM * vm, uint16_t literal) {
|
static Value VMMakeClosure(VM * vm, uint16_t literal) {
|
||||||
Array * thread = vm->thread;
|
Thread * thread = vm->thread;
|
||||||
if (vm->frame->callee.type != TYPE_FUNCTION) {
|
if (vm->frame->callee.type != TYPE_FUNCTION) {
|
||||||
VMError(vm, EXPECTED_FUNCTION);
|
VMError(vm, EXPECTED_FUNCTION);
|
||||||
} else {
|
} else {
|
||||||
|
@ -767,7 +778,11 @@ void VMInit(VM * vm) {
|
||||||
/* Load a function into the VM. The function will be called with
|
/* Load a function into the VM. The function will be called with
|
||||||
* no arguments when run */
|
* no arguments when run */
|
||||||
void VMLoad(VM * vm, Value func) {
|
void VMLoad(VM * vm, Value func) {
|
||||||
Array * thread = ArrayNew(vm, 100);
|
uint32_t startCapacity = 100;
|
||||||
|
Thread * thread = VMAlloc(vm, sizeof(Thread));
|
||||||
|
thread->data = VMAlloc(vm, sizeof(Value) * startCapacity);
|
||||||
|
thread->capacity = startCapacity;
|
||||||
|
thread->count = 0;
|
||||||
vm->thread = thread;
|
vm->thread = thread;
|
||||||
if (func.type == TYPE_FUNCTION) {
|
if (func.type == TYPE_FUNCTION) {
|
||||||
Func * fn = func.data.func;
|
Func * fn = func.data.func;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user