Convert Compiler and ObjList to both use ValueBuffer for their arrays.

This commit is contained in:
Bob Nystrom
2015-03-22 12:22:47 -07:00
parent 2dfec85506
commit dd4691649a
4 changed files with 67 additions and 98 deletions

View File

@ -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);
}

View File

@ -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]);
}

View File

@ -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:

View File

@ -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);