mirror of
https://github.com/wren-lang/wren.git
synced 2026-01-11 22:28:45 +01:00
Convert Compiler and ObjList to both use ValueBuffer for their arrays.
This commit is contained in:
@ -235,7 +235,7 @@ struct sCompiler
|
||||
struct sCompiler* parent;
|
||||
|
||||
// The constants that have been defined in this function so far.
|
||||
ObjList* constants;
|
||||
ValueBuffer constants;
|
||||
|
||||
// The currently in scope local variables.
|
||||
Local locals[MAX_LOCALS];
|
||||
@ -334,9 +334,11 @@ static void error(Compiler* compiler, const char* format, ...)
|
||||
// Adds [constant] to the constant pool and returns its index.
|
||||
static int addConstant(Compiler* compiler, Value constant)
|
||||
{
|
||||
if (compiler->constants->count < MAX_CONSTANTS)
|
||||
if (compiler->constants.count < MAX_CONSTANTS)
|
||||
{
|
||||
wrenListAdd(compiler->parser->vm, compiler->constants, constant);
|
||||
if (IS_OBJ(constant)) wrenPushRoot(compiler->parser->vm, AS_OBJ(constant));
|
||||
wrenValueBufferWrite(compiler->parser->vm, &compiler->constants, constant);
|
||||
if (IS_OBJ(constant)) wrenPopRoot(compiler->parser->vm);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -344,7 +346,7 @@ static int addConstant(Compiler* compiler, Value constant)
|
||||
MAX_CONSTANTS);
|
||||
}
|
||||
|
||||
return compiler->constants->count - 1;
|
||||
return compiler->constants.count - 1;
|
||||
}
|
||||
|
||||
// Initializes [compiler].
|
||||
@ -356,7 +358,7 @@ static void initCompiler(Compiler* compiler, Parser* parser, Compiler* parent,
|
||||
|
||||
// Initialize this to NULL before allocating in case a GC gets triggered in
|
||||
// the middle of initializing the compiler.
|
||||
compiler->constants = NULL;
|
||||
wrenValueBufferInit(parser->vm, &compiler->constants);
|
||||
|
||||
compiler->numUpvalues = 0;
|
||||
compiler->numParams = 0;
|
||||
@ -365,9 +367,6 @@ static void initCompiler(Compiler* compiler, Parser* parser, Compiler* parent,
|
||||
|
||||
wrenSetCompiler(parser->vm, compiler);
|
||||
|
||||
// Create a growable list for the constants used by this function.
|
||||
compiler->constants = wrenNewList(parser->vm, 0);
|
||||
|
||||
if (parent == NULL)
|
||||
{
|
||||
compiler->numLocals = 0;
|
||||
@ -1305,8 +1304,8 @@ static ObjFn* endCompiler(Compiler* compiler,
|
||||
// Create a function object for the code we just compiled.
|
||||
ObjFn* fn = wrenNewFunction(compiler->parser->vm,
|
||||
compiler->parser->module,
|
||||
compiler->constants->elements,
|
||||
compiler->constants->count,
|
||||
compiler->constants.data,
|
||||
compiler->constants.count,
|
||||
compiler->numUpvalues,
|
||||
compiler->numParams,
|
||||
compiler->bytecode.data,
|
||||
@ -2686,7 +2685,7 @@ static void endLoop(Compiler* compiler)
|
||||
{
|
||||
// Skip this instruction and its arguments.
|
||||
i += 1 + getNumArguments(compiler->bytecode.data,
|
||||
compiler->constants->elements, i);
|
||||
compiler->constants.data, i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3234,13 +3233,10 @@ void wrenMarkCompiler(WrenVM* vm, Compiler* compiler)
|
||||
|
||||
// Walk up the parent chain to mark the outer compilers too. The VM only
|
||||
// tracks the innermost one.
|
||||
while (compiler != NULL)
|
||||
do
|
||||
{
|
||||
if (compiler->constants != NULL)
|
||||
{
|
||||
wrenMarkObj(vm, (Obj*)compiler->constants);
|
||||
}
|
||||
|
||||
wrenMarkBuffer(vm, &compiler->constants);
|
||||
compiler = compiler->parent;
|
||||
}
|
||||
while (compiler != NULL);
|
||||
}
|
||||
|
||||
@ -666,23 +666,19 @@ DEF_PRIMITIVE(list_instantiate)
|
||||
|
||||
DEF_PRIMITIVE(list_add)
|
||||
{
|
||||
wrenListAdd(vm, AS_LIST(args[0]), args[1]);
|
||||
wrenValueBufferWrite(vm, &AS_LIST(args[0])->elements, args[1]);
|
||||
RETURN_VAL(args[1]);
|
||||
}
|
||||
|
||||
DEF_PRIMITIVE(list_clear)
|
||||
{
|
||||
ObjList* list = AS_LIST(args[0]);
|
||||
DEALLOCATE(vm, list->elements);
|
||||
list->elements = NULL;
|
||||
list->capacity = 0;
|
||||
list->count = 0;
|
||||
wrenValueBufferClear(vm, &AS_LIST(args[0])->elements);
|
||||
RETURN_NULL;
|
||||
}
|
||||
|
||||
DEF_PRIMITIVE(list_count)
|
||||
{
|
||||
RETURN_NUM(AS_LIST(args[0])->count);
|
||||
RETURN_NUM(AS_LIST(args[0])->elements.count);
|
||||
}
|
||||
|
||||
DEF_PRIMITIVE(list_insert)
|
||||
@ -690,7 +686,8 @@ DEF_PRIMITIVE(list_insert)
|
||||
ObjList* list = AS_LIST(args[0]);
|
||||
|
||||
// count + 1 here so you can "insert" at the very end.
|
||||
uint32_t index = validateIndex(vm, args, list->count + 1, 1, "Index");
|
||||
uint32_t index = validateIndex(vm, args, list->elements.count + 1, 1,
|
||||
"Index");
|
||||
if (index == UINT32_MAX) return PRIM_ERROR;
|
||||
|
||||
wrenListInsert(vm, list, args[2], index);
|
||||
@ -704,7 +701,7 @@ DEF_PRIMITIVE(list_iterate)
|
||||
// If we're starting the iteration, return the first index.
|
||||
if (IS_NULL(args[1]))
|
||||
{
|
||||
if (list->count == 0) RETURN_FALSE;
|
||||
if (list->elements.count == 0) RETURN_FALSE;
|
||||
RETURN_NUM(0);
|
||||
}
|
||||
|
||||
@ -712,7 +709,7 @@ DEF_PRIMITIVE(list_iterate)
|
||||
|
||||
// Stop if we're out of bounds.
|
||||
double index = AS_NUM(args[1]);
|
||||
if (index < 0 || index >= list->count - 1) RETURN_FALSE;
|
||||
if (index < 0 || index >= list->elements.count - 1) RETURN_FALSE;
|
||||
|
||||
// Otherwise, move to the next index.
|
||||
RETURN_NUM(index + 1);
|
||||
@ -721,16 +718,16 @@ DEF_PRIMITIVE(list_iterate)
|
||||
DEF_PRIMITIVE(list_iteratorValue)
|
||||
{
|
||||
ObjList* list = AS_LIST(args[0]);
|
||||
uint32_t index = validateIndex(vm, args, list->count, 1, "Iterator");
|
||||
uint32_t index = validateIndex(vm, args, list->elements.count, 1, "Iterator");
|
||||
if (index == UINT32_MAX) return PRIM_ERROR;
|
||||
|
||||
RETURN_VAL(list->elements[index]);
|
||||
RETURN_VAL(list->elements.data[index]);
|
||||
}
|
||||
|
||||
DEF_PRIMITIVE(list_removeAt)
|
||||
{
|
||||
ObjList* list = AS_LIST(args[0]);
|
||||
uint32_t index = validateIndex(vm, args, list->count, 1, "Index");
|
||||
uint32_t index = validateIndex(vm, args, list->elements.count, 1, "Index");
|
||||
if (index == UINT32_MAX) return PRIM_ERROR;
|
||||
|
||||
RETURN_VAL(wrenListRemoveAt(vm, list, index));
|
||||
@ -742,10 +739,11 @@ DEF_PRIMITIVE(list_subscript)
|
||||
|
||||
if (IS_NUM(args[1]))
|
||||
{
|
||||
uint32_t index = validateIndex(vm, args, list->count, 1, "Subscript");
|
||||
uint32_t index = validateIndex(vm, args, list->elements.count, 1,
|
||||
"Subscript");
|
||||
if (index == UINT32_MAX) return PRIM_ERROR;
|
||||
|
||||
RETURN_VAL(list->elements[index]);
|
||||
RETURN_VAL(list->elements.data[index]);
|
||||
}
|
||||
|
||||
if (!IS_RANGE(args[1]))
|
||||
@ -754,14 +752,14 @@ DEF_PRIMITIVE(list_subscript)
|
||||
}
|
||||
|
||||
int step;
|
||||
uint32_t count = list->count;
|
||||
uint32_t count = list->elements.count;
|
||||
uint32_t start = calculateRange(vm, args, AS_RANGE(args[1]), &count, &step);
|
||||
if (start == UINT32_MAX) return PRIM_ERROR;
|
||||
|
||||
ObjList* result = wrenNewList(vm, count);
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
{
|
||||
result->elements[i] = list->elements[start + (i * step)];
|
||||
result->elements.data[i] = list->elements.data[start + (i * step)];
|
||||
}
|
||||
|
||||
RETURN_OBJ(result);
|
||||
@ -770,10 +768,11 @@ DEF_PRIMITIVE(list_subscript)
|
||||
DEF_PRIMITIVE(list_subscriptSetter)
|
||||
{
|
||||
ObjList* list = AS_LIST(args[0]);
|
||||
uint32_t index = validateIndex(vm, args, list->count, 1, "Subscript");
|
||||
uint32_t index = validateIndex(vm, args, list->elements.count, 1,
|
||||
"Subscript");
|
||||
if (index == UINT32_MAX) return PRIM_ERROR;
|
||||
|
||||
list->elements[index] = args[2];
|
||||
list->elements.data[index] = args[2];
|
||||
RETURN_VAL(args[2]);
|
||||
}
|
||||
|
||||
|
||||
@ -245,80 +245,55 @@ ObjList* wrenNewList(WrenVM* vm, uint32_t numElements)
|
||||
|
||||
ObjList* list = ALLOCATE(vm, ObjList);
|
||||
initObj(vm, &list->obj, OBJ_LIST, vm->listClass);
|
||||
list->capacity = numElements;
|
||||
list->count = numElements;
|
||||
list->elements = elements;
|
||||
list->elements.capacity = numElements;
|
||||
list->elements.count = numElements;
|
||||
list->elements.data = elements;
|
||||
return list;
|
||||
}
|
||||
|
||||
// Grows [list] if needed to ensure it can hold one more element.
|
||||
static void ensureListCapacity(WrenVM* vm, ObjList* list)
|
||||
{
|
||||
if (list->capacity >= list->count + 1) return;
|
||||
|
||||
uint32_t capacity = list->capacity * GROW_FACTOR;
|
||||
if (capacity < MIN_CAPACITY) capacity = MIN_CAPACITY;
|
||||
|
||||
list->capacity = capacity;
|
||||
list->elements = (Value*)wrenReallocate(vm, list->elements,
|
||||
list->capacity * sizeof(Value), capacity * sizeof(Value));
|
||||
// TODO: Handle allocation failure.
|
||||
list->capacity = capacity;
|
||||
}
|
||||
|
||||
void wrenListAdd(WrenVM* vm, ObjList* list, Value value)
|
||||
{
|
||||
if (IS_OBJ(value)) wrenPushRoot(vm, AS_OBJ(value));
|
||||
|
||||
ensureListCapacity(vm, list);
|
||||
|
||||
if (IS_OBJ(value)) wrenPopRoot(vm);
|
||||
|
||||
list->elements[list->count++] = value;
|
||||
}
|
||||
|
||||
void wrenListInsert(WrenVM* vm, ObjList* list, Value value, uint32_t index)
|
||||
{
|
||||
if (IS_OBJ(value)) wrenPushRoot(vm, AS_OBJ(value));
|
||||
|
||||
ensureListCapacity(vm, list);
|
||||
// Add a slot at the end of the list.
|
||||
wrenValueBufferWrite(vm, &list->elements, NULL_VAL);
|
||||
|
||||
if (IS_OBJ(value)) wrenPopRoot(vm);
|
||||
|
||||
// Shift items down.
|
||||
for (uint32_t i = list->count; i > index; i--)
|
||||
// Shift the existing elements down.
|
||||
for (uint32_t i = list->elements.count - 1; i > index; i--)
|
||||
{
|
||||
list->elements[i] = list->elements[i - 1];
|
||||
list->elements.data[i] = list->elements.data[i - 1];
|
||||
}
|
||||
|
||||
list->elements[index] = value;
|
||||
list->count++;
|
||||
// Store the new element.
|
||||
list->elements.data[index] = value;
|
||||
}
|
||||
|
||||
Value wrenListRemoveAt(WrenVM* vm, ObjList* list, uint32_t index)
|
||||
{
|
||||
Value removed = list->elements[index];
|
||||
Value removed = list->elements.data[index];
|
||||
|
||||
if (IS_OBJ(removed)) wrenPushRoot(vm, AS_OBJ(removed));
|
||||
|
||||
// Shift items up.
|
||||
for (uint32_t i = index; i < list->count - 1; i++)
|
||||
for (int i = index; i < list->elements.count - 1; i++)
|
||||
{
|
||||
list->elements[i] = list->elements[i + 1];
|
||||
list->elements.data[i] = list->elements.data[i + 1];
|
||||
}
|
||||
|
||||
// If we have too much excess capacity, shrink it.
|
||||
if (list->capacity / GROW_FACTOR >= list->count)
|
||||
if (list->elements.capacity / GROW_FACTOR >= list->elements.count)
|
||||
{
|
||||
list->elements = (Value*)wrenReallocate(vm, list->elements,
|
||||
sizeof(Value) * list->capacity,
|
||||
sizeof(Value) * (list->capacity / GROW_FACTOR));
|
||||
list->capacity /= GROW_FACTOR;
|
||||
list->elements.data = (Value*)wrenReallocate(vm, list->elements.data,
|
||||
sizeof(Value) * list->elements.capacity,
|
||||
sizeof(Value) * (list->elements.capacity / GROW_FACTOR));
|
||||
list->elements.capacity /= GROW_FACTOR;
|
||||
}
|
||||
|
||||
if (IS_OBJ(removed)) wrenPopRoot(vm);
|
||||
|
||||
list->count--;
|
||||
list->elements.count--;
|
||||
return removed;
|
||||
}
|
||||
|
||||
@ -940,15 +915,11 @@ static void markInstance(WrenVM* vm, ObjInstance* instance)
|
||||
static void markList(WrenVM* vm, ObjList* list)
|
||||
{
|
||||
// Mark the elements.
|
||||
Value* elements = list->elements;
|
||||
for (uint32_t i = 0; i < list->count; i++)
|
||||
{
|
||||
wrenMarkValue(vm, elements[i]);
|
||||
}
|
||||
wrenMarkBuffer(vm, &list->elements);
|
||||
|
||||
// Keep track of how much memory is still in use.
|
||||
vm->bytesAllocated += sizeof(ObjList);
|
||||
vm->bytesAllocated += sizeof(Value) * list->capacity;
|
||||
vm->bytesAllocated += sizeof(Value) * list->elements.capacity;
|
||||
}
|
||||
|
||||
static void markMap(WrenVM* vm, ObjMap* map)
|
||||
@ -1048,6 +1019,14 @@ void wrenMarkValue(WrenVM* vm, Value value)
|
||||
wrenMarkObj(vm, AS_OBJ(value));
|
||||
}
|
||||
|
||||
void wrenMarkBuffer(WrenVM* vm, ValueBuffer* buffer)
|
||||
{
|
||||
for (int i = 0; i < buffer->count; i++)
|
||||
{
|
||||
wrenMarkValue(vm, buffer->data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void wrenFreeObj(WrenVM* vm, Obj* obj)
|
||||
{
|
||||
#if WREN_DEBUG_TRACE_MEMORY
|
||||
@ -1074,7 +1053,7 @@ void wrenFreeObj(WrenVM* vm, Obj* obj)
|
||||
}
|
||||
|
||||
case OBJ_LIST:
|
||||
DEALLOCATE(vm, ((ObjList*)obj)->elements);
|
||||
wrenValueBufferClear(vm, &((ObjList*)obj)->elements);
|
||||
break;
|
||||
|
||||
case OBJ_MAP:
|
||||
|
||||
@ -393,14 +393,8 @@ typedef struct
|
||||
{
|
||||
Obj obj;
|
||||
|
||||
// The number of elements allocated.
|
||||
uint32_t capacity;
|
||||
|
||||
// The number of items in the list.
|
||||
uint32_t count;
|
||||
|
||||
// Pointer to a contiguous array of [capacity] elements.
|
||||
Value* elements;
|
||||
// The elements in the list.
|
||||
ValueBuffer elements;
|
||||
} ObjList;
|
||||
|
||||
typedef struct
|
||||
@ -639,9 +633,6 @@ Value wrenNewInstance(WrenVM* vm, ObjClass* classObj);
|
||||
// uninitialized.)
|
||||
ObjList* wrenNewList(WrenVM* vm, uint32_t numElements);
|
||||
|
||||
// Adds [value] to [list], reallocating and growing its storage if needed.
|
||||
void wrenListAdd(WrenVM* vm, ObjList* list, Value value);
|
||||
|
||||
// Inserts [value] in [list] at [index], shifting down the other elements.
|
||||
void wrenListInsert(WrenVM* vm, ObjList* list, Value value, uint32_t index);
|
||||
|
||||
@ -710,6 +701,10 @@ void wrenMarkValue(WrenVM* vm, Value value);
|
||||
// during the sweep phase of a garbage collection.
|
||||
void wrenMarkObj(WrenVM* vm, Obj* obj);
|
||||
|
||||
// Mark the values in [buffer] as reachable and still in use. This should only
|
||||
// be called during the sweep phase of a garbage collection.
|
||||
void wrenMarkBuffer(WrenVM* vm, ValueBuffer* buffer);
|
||||
|
||||
// Releases all memory owned by [obj], including [obj] itself.
|
||||
void wrenFreeObj(WrenVM* vm, Obj* obj);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user