From 523586e3a617bdbf996e3a27a338289728001d13 Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Thu, 13 May 2021 00:43:44 +0200 Subject: [PATCH] mask vm loop always by opcode (fewer switch cases) --- src/cs_vm.cc | 257 +++++++++++++++++++-------------------------------- 1 file changed, 95 insertions(+), 162 deletions(-) diff --git a/src/cs_vm.cc b/src/cs_vm.cc index 94db756..515f758 100644 --- a/src/cs_vm.cc +++ b/src/cs_vm.cc @@ -254,39 +254,27 @@ std::uint32_t *vm_exec( } for (;;) { std::uint32_t op = *code++; - switch (op & 0xFF) { + switch (op & BC_INST_OP_MASK) { case BC_INST_START: case BC_INST_OFFSET: continue; - case BC_INST_NULL | BC_RET_NULL: - case BC_INST_NULL | BC_RET_STRING: - case BC_INST_NULL | BC_RET_INT: - case BC_INST_NULL | BC_RET_FLOAT: + case BC_INST_NULL: result.set_none(); force_arg(cs, result, op & BC_INST_RET_MASK); continue; - case BC_INST_FALSE | BC_RET_STRING: - case BC_INST_FALSE | BC_RET_NULL: - case BC_INST_FALSE | BC_RET_INT: - case BC_INST_FALSE | BC_RET_FLOAT: + case BC_INST_FALSE: result.set_integer(0); force_arg(cs, result, op & BC_INST_RET_MASK); continue; - case BC_INST_TRUE | BC_RET_STRING: - case BC_INST_TRUE | BC_RET_NULL: - case BC_INST_TRUE | BC_RET_INT: - case BC_INST_TRUE | BC_RET_FLOAT: + case BC_INST_TRUE: result.set_integer(1); force_arg(cs, result, op & BC_INST_RET_MASK); continue; - case BC_INST_NOT | BC_RET_STRING: - case BC_INST_NOT | BC_RET_NULL: - case BC_INST_NOT | BC_RET_INT: - case BC_INST_NOT | BC_RET_FLOAT: + case BC_INST_NOT: result.set_integer(!args.back().get_bool()); force_arg(cs, result, op & BC_INST_RET_MASK); args.pop_back(); @@ -302,40 +290,26 @@ std::uint32_t *vm_exec( code = vm_exec(ts, code, result); continue; - case BC_INST_EXIT | BC_RET_NULL: - case BC_INST_EXIT | BC_RET_STRING: - case BC_INST_EXIT | BC_RET_INT: - case BC_INST_EXIT | BC_RET_FLOAT: + case BC_INST_EXIT: force_arg(cs, result, op & BC_INST_RET_MASK); return code; - case BC_INST_RESULT | BC_RET_NULL: - case BC_INST_RESULT | BC_RET_STRING: - case BC_INST_RESULT | BC_RET_INT: - case BC_INST_RESULT | BC_RET_FLOAT: + case BC_INST_RESULT: result = std::move(args.back()); args.pop_back(); force_arg(cs, result, op & BC_INST_RET_MASK); continue; - case BC_INST_RESULT_ARG | BC_RET_NULL: - case BC_INST_RESULT_ARG | BC_RET_STRING: - case BC_INST_RESULT_ARG | BC_RET_INT: - case BC_INST_RESULT_ARG | BC_RET_FLOAT: + case BC_INST_RESULT_ARG: force_arg(cs, result, op & BC_INST_RET_MASK); args.emplace_back(std::move(result)); continue; - case BC_INST_FORCE | BC_RET_STRING: - case BC_INST_FORCE | BC_RET_INT: - case BC_INST_FORCE | BC_RET_FLOAT: + case BC_INST_FORCE: force_arg(cs, args.back(), op & BC_INST_RET_MASK); continue; - case BC_INST_DUP | BC_RET_NULL: - case BC_INST_DUP | BC_RET_INT: - case BC_INST_DUP | BC_RET_FLOAT: - case BC_INST_DUP | BC_RET_STRING: { + case BC_INST_DUP: { auto &v = args.back(); auto &nv = args.emplace_back(); nv = v; @@ -343,49 +317,60 @@ std::uint32_t *vm_exec( continue; } - case BC_INST_VAL | BC_RET_STRING: { - std::uint32_t len = op >> 8; - args.emplace_back().set_string(std::string_view{ - reinterpret_cast(code), len - }, cs); - code += len / sizeof(std::uint32_t) + 1; - continue; - } - case BC_INST_VAL_INT | BC_RET_STRING: { - char s[4] = { - char((op >> 8) & 0xFF), - char((op >> 16) & 0xFF), - char((op >> 24) & 0xFF), '\0' - }; - /* gotta cast or r.size() == potentially 3 */ - args.emplace_back().set_string( - static_cast(s), cs - ); - continue; - } - case BC_INST_VAL | BC_RET_NULL: - case BC_INST_VAL_INT | BC_RET_NULL: + case BC_INST_VAL: + switch (op & BC_INST_RET_MASK) { + case BC_RET_STRING: { + std::uint32_t len = op >> 8; + args.emplace_back().set_string(std::string_view{ + reinterpret_cast(code), len + }, cs); + code += len / sizeof(std::uint32_t) + 1; + continue; + } + case BC_RET_INT: + args.emplace_back().set_integer( + *reinterpret_cast(code) + ); + code += bc_store_size; + continue; + case BC_RET_FLOAT: + args.emplace_back().set_float( + *reinterpret_cast(code) + ); + code += bc_store_size; + continue; + default: + break; + } args.emplace_back().set_none(); continue; - case BC_INST_VAL | BC_RET_INT: - args.emplace_back().set_integer( - *reinterpret_cast(code) - ); - code += bc_store_size; - continue; - case BC_INST_VAL_INT | BC_RET_INT: - args.emplace_back().set_integer(integer_type(op) >> 8); - continue; - case BC_INST_VAL | BC_RET_FLOAT: - args.emplace_back().set_float( - *reinterpret_cast(code) - ); - code += bc_store_size; - continue; - case BC_INST_VAL_INT | BC_RET_FLOAT: - args.emplace_back().set_float( - float_type(integer_type(op) >> 8) - ); + + case BC_INST_VAL_INT: + switch (op & BC_INST_RET_MASK) { + case BC_RET_STRING: { + char s[4] = { + char((op >> 8) & 0xFF), + char((op >> 16) & 0xFF), + char((op >> 24) & 0xFF), '\0' + }; + /* gotta cast or r.size() == potentially 3 */ + args.emplace_back().set_string( + static_cast(s), cs + ); + continue; + } + case BC_RET_INT: + args.emplace_back().set_integer(integer_type(op) >> 8); + continue; + case BC_RET_FLOAT: + args.emplace_back().set_float( + float_type(integer_type(op) >> 8) + ); + continue; + default: + break; + } + args.emplace_back().set_none(); continue; case BC_INST_LOCAL: { @@ -414,10 +399,7 @@ std::uint32_t *vm_exec( return code; } - case BC_INST_DO_ARGS | BC_RET_NULL: - case BC_INST_DO_ARGS | BC_RET_STRING: - case BC_INST_DO_ARGS | BC_RET_INT: - case BC_INST_DO_ARGS | BC_RET_FLOAT: + case BC_INST_DO_ARGS: call_with_args(ts, [&]() { auto v = std::move(args.back()); args.pop_back(); @@ -425,11 +407,8 @@ std::uint32_t *vm_exec( force_arg(cs, result, op & BC_INST_RET_MASK); }); continue; - /* fallthrough */ - case BC_INST_DO | BC_RET_NULL: - case BC_INST_DO | BC_RET_STRING: - case BC_INST_DO | BC_RET_INT: - case BC_INST_DO | BC_RET_FLOAT: { + + case BC_INST_DO: { auto v = std::move(args.back()); args.pop_back(); result = v.get_code().call(cs); @@ -442,23 +421,18 @@ std::uint32_t *vm_exec( code += len; continue; } - case BC_INST_JUMP_B | BC_INST_FLAG_TRUE: { + + case BC_INST_JUMP_B: { std::uint32_t len = op >> 8; - if (args.back().get_bool()) { + /* BC_INST_FLAG_TRUE/FALSE */ + if (args.back().get_bool() == !!(op & BC_INST_RET_MASK)) { code += len; } args.pop_back(); continue; } - case BC_INST_JUMP_B | BC_INST_FLAG_FALSE: { - std::uint32_t len = op >> 8; - if (!args.back().get_bool()) { - code += len; - } - args.pop_back(); - continue; - } - case BC_INST_JUMP_RESULT | BC_INST_FLAG_TRUE: { + + case BC_INST_JUMP_RESULT: { std::uint32_t len = op >> 8; auto v = std::move(args.back()); args.pop_back(); @@ -467,37 +441,26 @@ std::uint32_t *vm_exec( } else { result = std::move(v); } - if (result.get_bool()) { + /* BC_INST_FLAG_TRUE/FALSE */ + if (result.get_bool() == !!(op & BC_INST_RET_MASK)) { code += len; } continue; } - case BC_INST_JUMP_RESULT | BC_INST_FLAG_FALSE: { - std::uint32_t len = op >> 8; - auto v = std::move(args.back()); - args.pop_back(); - if (v.type() == value_type::CODE) { - result = v.get_code().call(cs); - } else { - result = std::move(v); - } - if (!result.get_bool()) { - code += len; - } - continue; - } - case BC_INST_BREAK | BC_INST_FLAG_FALSE: + + case BC_INST_BREAK: if (ts.loop_level) { - throw break_exception(); + if (op & BC_INST_RET_MASK) { + throw continue_exception{}; + } else { + throw break_exception{}; + } } else { - throw error{cs, "no loop to break"}; - } - break; - case BC_INST_BREAK | BC_INST_FLAG_TRUE: - if (ts.loop_level) { - throw continue_exception(); - } else { - throw error{cs, "no loop to continue"}; + if (op & BC_INST_RET_MASK) { + throw error{cs, "no loop to continue"}; + } else { + throw error{cs, "no loop to break"}; + } } break; @@ -510,10 +473,7 @@ std::uint32_t *vm_exec( continue; } - case BC_INST_EMPTY | BC_RET_NULL: - case BC_INST_EMPTY | BC_RET_STRING: - case BC_INST_EMPTY | BC_RET_INT: - case BC_INST_EMPTY | BC_RET_FLOAT: + case BC_INST_EMPTY: args.emplace_back().set_code(bcode_p::make_ref( bcode_get_empty(ts.istate->empty, op & BC_INST_RET_MASK) )); @@ -588,18 +548,12 @@ std::uint32_t *vm_exec( continue; } - case BC_INST_LOOKUP_U | BC_RET_STRING: - case BC_INST_LOOKUP_U | BC_RET_INT: - case BC_INST_LOOKUP_U | BC_RET_FLOAT: - case BC_INST_LOOKUP_U | BC_RET_NULL: + case BC_INST_LOOKUP_U: args.back() = cs.lookup_value(args.back().get_string(cs)); force_arg(cs, args.back(), op & BC_INST_RET_MASK); continue; - case BC_INST_LOOKUP | BC_RET_STRING: - case BC_INST_LOOKUP | BC_RET_INT: - case BC_INST_LOOKUP | BC_RET_FLOAT: - case BC_INST_LOOKUP | BC_RET_NULL: { + case BC_INST_LOOKUP: { alias_stack *ast; auto &v = args.emplace_back(); if (get_lookup_id(ts, op, ast)) { @@ -609,14 +563,8 @@ std::uint32_t *vm_exec( continue; } - case BC_INST_CONC | BC_RET_NULL: - case BC_INST_CONC | BC_RET_STRING: - case BC_INST_CONC | BC_RET_FLOAT: - case BC_INST_CONC | BC_RET_INT: - case BC_INST_CONC_W | BC_RET_NULL: - case BC_INST_CONC_W | BC_RET_STRING: - case BC_INST_CONC_W | BC_RET_FLOAT: - case BC_INST_CONC_W | BC_RET_INT: { + case BC_INST_CONC: + case BC_INST_CONC_W: { std::size_t numconc = op >> 8; auto buf = concat_values( cs, span_type{ @@ -629,10 +577,7 @@ std::uint32_t *vm_exec( continue; } - case BC_INST_VAR | BC_RET_NULL: - case BC_INST_VAR | BC_RET_INT: - case BC_INST_VAR | BC_RET_FLOAT: - case BC_INST_VAR | BC_RET_STRING: + case BC_INST_VAR: args.emplace_back() = static_cast( ts.istate->identmap[op >> 8] )->value(); @@ -660,10 +605,7 @@ std::uint32_t *vm_exec( continue; } - case BC_INST_CALL | BC_RET_NULL: - case BC_INST_CALL | BC_RET_STRING: - case BC_INST_CALL | BC_RET_FLOAT: - case BC_INST_CALL | BC_RET_INT: { + case BC_INST_CALL: { result.force_none(); ident *id = ts.istate->identmap[op >> 8]; std::size_t callargs = *code++; @@ -685,10 +627,7 @@ std::uint32_t *vm_exec( continue; } - case BC_INST_CALL_U | BC_RET_NULL: - case BC_INST_CALL_U | BC_RET_STRING: - case BC_INST_CALL_U | BC_RET_FLOAT: - case BC_INST_CALL_U | BC_RET_INT: { + case BC_INST_CALL_U: { std::size_t callargs = op >> 8; std::size_t nnargs = args.size(); std::size_t offset = nnargs - callargs; @@ -795,10 +734,7 @@ noid: } } - case BC_INST_COM | BC_RET_NULL: - case BC_INST_COM | BC_RET_STRING: - case BC_INST_COM | BC_RET_FLOAT: - case BC_INST_COM | BC_RET_INT: { + case BC_INST_COM: { command_impl *id = static_cast( ts.istate->identmap[op >> 8] ); @@ -812,10 +748,7 @@ noid: continue; } - case BC_INST_COM_V | BC_RET_NULL: - case BC_INST_COM_V | BC_RET_STRING: - case BC_INST_COM_V | BC_RET_FLOAT: - case BC_INST_COM_V | BC_RET_INT: { + case BC_INST_COM_V: { command_impl *id = static_cast( ts.istate->identmap[op >> 8] );