#include "CPUCount.h"
#include "Interpreter.h"
#include <assert.h>
#include <cstddef>
#include <cstdlib>
#include <errno.h>
#include <fcntl.h>
#include <string>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <vector>
#include "mbmalloc.h"
Interpreter::Interpreter(const char* fileName, bool shouldFreeAllObjects)
: m_shouldFreeAllObjects(shouldFreeAllObjects)
{
m_fd = open(fileName, O_RDWR, S_IRUSR | S_IWUSR);
if (m_fd == -1)
fprintf(stderr, "failed to open\n");
struct stat buf;
fstat(m_fd, &buf);
m_opCount = buf.st_size / sizeof(Op);
assert(m_opCount * sizeof(Op) == buf.st_size);
size_t maxSlot = 0;
std::vector<Op> ops(1024);
size_t remaining = m_opCount * sizeof(Op);
while (remaining) {
size_t bytes = std::min(remaining, ops.size() * sizeof(Op));
remaining -= bytes;
read(m_fd, ops.data(), bytes);
size_t opCount = bytes / sizeof(Op);
for (size_t i = 0; i < opCount; ++i) {
Op op = ops[i];
if (op.slot > maxSlot)
maxSlot = op.slot;
}
}
m_objects.resize(maxSlot + 1);
}
Interpreter::~Interpreter()
{
int result = close(m_fd);
if (result == -1)
fprintf(stderr, "failed to close\n");
}
void Interpreter::run()
{
std::vector<Op> ops(1024);
lseek(m_fd, 0, SEEK_SET);
size_t remaining = m_opCount * sizeof(Op);
while (remaining) {
size_t bytes = std::min(remaining, ops.size() * sizeof(Op));
remaining -= bytes;
read(m_fd, ops.data(), bytes);
size_t opCount = bytes / sizeof(Op);
for (size_t i = 0; i < opCount; ++i) {
Op op = ops[i];
switch (op.opcode) {
case op_malloc: {
m_objects[op.slot] = { mbmalloc(op.size), op.size };
assert(m_objects[op.slot].object);
bzero(m_objects[op.slot].object, op.size);
break;
}
case op_free: {
if (!m_objects[op.slot].object)
continue;
mbfree(m_objects[op.slot].object, m_objects[op.slot].size);
m_objects[op.slot] = { 0, 0 };
break;
}
case op_realloc: {
if (!m_objects[op.slot].object)
continue;
m_objects[op.slot] = { mbrealloc(m_objects[op.slot].object, m_objects[op.slot].size, op.size), op.size };
break;
}
default: {
fprintf(stderr, "bad opcode: %d\n", op.opcode);
abort();
break;
}
}
}
}
if (!m_shouldFreeAllObjects)
return;
for (size_t i = 0; i < m_objects.size(); ++i) {
if (!m_objects[i].object)
continue;
mbfree(m_objects[i].object, m_objects[i].size);
m_objects[i] = { 0, 0 };
}
}