~maelkum/viuavm

299b15c52368ed459c6d7143e2c223cf8bafe687 — Marek Marecki 11 months ago 90ff10c
Access string table via a pointer

Pointers allow switching between different string tables at runtime.
While not particularly useful for normal execution it is crucial for
dynamic evaluation in REPL.

Without the ability to switch string tables it would be impossible to
dynamically evaluate STRING or FLOAT instructions, as they would access
the table at incorrect offsets (most likely). Why at incorrect offsets?
Because the dynamically evaluated code is compiled against its own
string table, not the table that is currently used by the process.
3 files changed, 27 insertions(+), 18 deletions(-)

M new/include/viua/vm/core.h
M new/src/tools/exec/repl.cpp
M new/src/vm/ins.cpp
M new/include/viua/vm/core.h => new/include/viua/vm/core.h +7 -1
@@ 432,13 432,19 @@ struct Process {
    pid_type const pid;

    Core* core{};

    Module const& module;
    Module::strtab_type const* strtab;

    using stack_type = Stack;
    stack_type stack;

    explicit inline Process(pid_type const p, Core* c, Module const& m)
            : pid{p}, core{c}, module{m}, stack{*this}
            : pid{p}
            , core{c}
            , module{m}
            , strtab{&m.strings_table}
            , stack{*this}
    {}

    inline auto push_frame(size_t const locals,

M new/src/tools/exec/repl.cpp => new/src/tools/exec/repl.cpp +5 -0
@@ 405,9 405,14 @@ auto evaluate_asm_expression(std::string const source_text) -> void
    }

    auto proc = REPL_STATE->core.find(*REPL_STATE->selected_pid);

    proc->strtab = &strings_table;

    for (auto const each : instructions) {
        viua::vm::ins::execute(proc->stack, &each);
    }

    proc->strtab = &proc->module.strings_table;
}

auto repl_eval(std::vector<std::string_view> const parts) -> bool

M new/src/vm/ins.cpp => new/src/vm/ins.cpp +15 -17
@@ 1198,19 1198,18 @@ auto execute(ATOM const op, Stack& stack, ip_type const ip) -> void
{
    auto target = get_proxy(stack, op.instruction.out, ip);

    auto const& mod        = stack.proc.module;
    auto const& strtab     = *stack.proc.strtab;
    auto const data_offset = cast_to<uint64_t>(target.view());
    auto const data_size   = [&mod, data_offset]() -> uint64_t {
    auto const data_size   = [&strtab, data_offset]() -> uint64_t {
        auto const size_offset = (data_offset - sizeof(uint64_t));
        auto tmp               = uint64_t{};
        memcpy(&tmp, &mod.strings_table[size_offset], sizeof(uint64_t));
        memcpy(&tmp, &strtab[size_offset], sizeof(uint64_t));
        return le64toh(tmp);
    }();

    auto s     = std::make_unique<viua::vm::types::Atom>();
    s->content = std::string{
        reinterpret_cast<char const*>(&mod.strings_table[0] + data_offset),
        data_size};
        reinterpret_cast<char const*>(&strtab[0] + data_offset), data_size};

    target = std::move(s);
}


@@ 1218,19 1217,18 @@ auto execute(STRING const op, Stack& stack, ip_type const ip) -> void
{
    auto target = get_proxy(stack, op.instruction.out, ip);

    auto const& mod        = stack.proc.module;
    auto const& strtab     = *stack.proc.strtab;
    auto const data_offset = cast_to<uint64_t>(target.view());
    auto const data_size   = [&mod, data_offset]() -> uint64_t {
    auto const data_size   = [&strtab, data_offset]() -> uint64_t {
        auto const size_offset = (data_offset - sizeof(uint64_t));
        auto tmp               = uint64_t{};
        memcpy(&tmp, &mod.strings_table[size_offset], sizeof(uint64_t));
        memcpy(&tmp, &strtab[size_offset], sizeof(uint64_t));
        return le64toh(tmp);
    }();

    auto s     = std::make_unique<viua::vm::types::String>();
    s->content = std::string{
        reinterpret_cast<char const*>(&mod.strings_table[0] + data_offset),
        data_size};
        reinterpret_cast<char const*>(&strtab[0] + data_offset), data_size};

    target = std::move(s);
}


@@ 1333,19 1331,20 @@ auto execute(FLOAT const op, Stack& stack, ip_type const) -> void

    auto& target = registers.at(op.instruction.out.index);

    auto const& strtab = *stack.proc.strtab;

    auto const data_offset = target.value.get<uint64_t>();
    auto const data_size   = [&stack, data_offset]() -> uint64_t {
    auto const data_size   = [&strtab, data_offset]() -> uint64_t {
        auto const size_offset = (data_offset - sizeof(uint64_t));
        auto tmp               = uint64_t{};
        memcpy(&tmp,
               &stack.proc.module.strings_table[size_offset],
               &strtab[size_offset],
               sizeof(uint64_t));
        return le64toh(tmp);
    }();

    auto tmp = uint32_t{};
    memcpy(
        &tmp, (&stack.proc.module.strings_table[0] + data_offset), data_size);
    memcpy(&tmp, (&strtab[0] + data_offset), data_size);
    tmp = le32toh(tmp);

    auto v = float{};


@@ 1364,14 1363,13 @@ auto execute(DOUBLE const op, Stack& stack, ip_type const) -> void
        auto const size_offset = (data_offset - sizeof(uint64_t));
        auto tmp               = uint64_t{};
        memcpy(&tmp,
               &stack.proc.module.strings_table[size_offset],
               &stack.proc.strtab->operator[](size_offset),
               sizeof(uint64_t));
        return le64toh(tmp);
    }();

    auto tmp = uint64_t{};
    memcpy(
        &tmp, (&stack.proc.module.strings_table[0] + data_offset), data_size);
    memcpy(&tmp, (&stack.proc.strtab->operator[](0) + data_offset), data_size);
    tmp = le64toh(tmp);

    auto v = double{};