mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
emergency update
This commit is contained in:
parent
5d846e0aaf
commit
9f351fc29f
87 changed files with 2486 additions and 655 deletions
|
@ -789,7 +789,7 @@ void register_shift_logic_ops(OpcodeTable& cp0) {
|
|||
|
||||
int exec_minmax(VmState* st, int mode) {
|
||||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute MINMAXOP " << mode;
|
||||
VM_LOG(st) << "execute " << (mode & 1 ? "Q" : "") << (mode & 2 ? "MIN" : "") << (mode & 4 ? "MAX" : "");
|
||||
stack.check_underflow(2);
|
||||
auto x = stack.pop_int();
|
||||
auto y = stack.pop_int();
|
||||
|
@ -811,7 +811,7 @@ int exec_minmax(VmState* st, int mode) {
|
|||
|
||||
int exec_abs(VmState* st, bool quiet) {
|
||||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute ABS";
|
||||
VM_LOG(st) << "execute " << (quiet ? "QABS" : "ABS");
|
||||
stack.check_underflow(1);
|
||||
auto x = stack.pop_int();
|
||||
if (x->is_valid() && x->sgn() < 0) {
|
||||
|
|
|
@ -58,14 +58,27 @@ std::string dump_push_ref(CellSlice& cs, unsigned args, int pfx_bits, std::strin
|
|||
return "";
|
||||
}
|
||||
cs.advance(pfx_bits);
|
||||
cs.advance_refs(1);
|
||||
return name;
|
||||
auto cell = cs.fetch_ref();
|
||||
return name + " (" + cell->get_hash().to_hex() + ")";
|
||||
}
|
||||
|
||||
int compute_len_push_ref(const CellSlice& cs, unsigned args, int pfx_bits) {
|
||||
return cs.have_refs(1) ? (0x10000 + pfx_bits) : 0;
|
||||
}
|
||||
|
||||
std::string dump_push_ref2(CellSlice& cs, unsigned args, int pfx_bits, std::string name) {
|
||||
if (!cs.have_refs(2)) {
|
||||
return "";
|
||||
}
|
||||
cs.advance(pfx_bits);
|
||||
auto cell1 = cs.fetch_ref(), cell2 = cs.fetch_ref();
|
||||
return name + " (" + cell1->get_hash().to_hex() + ") (" + cell2->get_hash().to_hex() + ")";
|
||||
}
|
||||
|
||||
int compute_len_push_ref2(const CellSlice& cs, unsigned args, int pfx_bits) {
|
||||
return cs.have_refs(2) ? (0x20000 + pfx_bits) : 0;
|
||||
}
|
||||
|
||||
int exec_push_slice_common(VmState* st, CellSlice& cs, unsigned data_bits, unsigned refs, int pfx_bits) {
|
||||
if (!cs.have(pfx_bits + data_bits)) {
|
||||
throw VmError{Excno::inv_opcode, "not enough data bits for a PUSHSLICE instruction"};
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
#include "vm/cellslice.h"
|
||||
|
@ -28,4 +28,7 @@ void register_cell_ops(OpcodeTable &cp0);
|
|||
std::string dump_push_ref(CellSlice &cs, unsigned args, int pfx_bits, std::string name);
|
||||
int compute_len_push_ref(const CellSlice &cs, unsigned args, int pfx_bits);
|
||||
|
||||
std::string dump_push_ref2(CellSlice &cs, unsigned args, int pfx_bits, std::string name);
|
||||
int compute_len_push_ref2(const CellSlice &cs, unsigned args, int pfx_bits);
|
||||
|
||||
} // namespace vm
|
||||
|
|
|
@ -26,10 +26,12 @@
|
|||
#include "vm/excno.hpp"
|
||||
#include "vm/vm.h"
|
||||
|
||||
using namespace std::literals::string_literals;
|
||||
|
||||
namespace vm {
|
||||
|
||||
int exec_execute(VmState* st) {
|
||||
VM_LOG(st) << "execute EXECUTE\n";
|
||||
VM_LOG(st) << "execute EXECUTE";
|
||||
auto cont = st->get_stack().pop_cont();
|
||||
return st->call(std::move(cont));
|
||||
}
|
||||
|
@ -150,12 +152,58 @@ int exec_callcc_varargs(VmState* st) {
|
|||
int exec_do_with_ref(VmState* st, CellSlice& cs, int pfx_bits, const std::function<int(VmState*, Ref<OrdCont>)>& func,
|
||||
const char* name) {
|
||||
if (!cs.have_refs(1)) {
|
||||
throw VmError{Excno::inv_opcode, "no references left for a CALLREF instruction"};
|
||||
throw VmError{Excno::inv_opcode, "no references left for a "s + name + " instruction"};
|
||||
}
|
||||
cs.advance(pfx_bits);
|
||||
auto cell = cs.fetch_ref();
|
||||
VM_LOG(st) << "execute " << name << " (" << cell->get_hash().to_hex() << ")";
|
||||
return func(st, Ref<OrdCont>{true, load_cell_slice_ref(std::move(cell)), st->get_cp()});
|
||||
return func(st, st->ref_to_cont(std::move(cell)));
|
||||
}
|
||||
|
||||
int exec_do_with_cell(VmState* st, CellSlice& cs, int pfx_bits, const std::function<int(VmState*, Ref<Cell>)>& func,
|
||||
const char* name) {
|
||||
if (!cs.have_refs(1)) {
|
||||
throw VmError{Excno::inv_opcode, "no references left for a "s + name + " instruction"};
|
||||
}
|
||||
cs.advance(pfx_bits);
|
||||
auto cell = cs.fetch_ref();
|
||||
VM_LOG(st) << "execute " << name << " (" << cell->get_hash().to_hex() << ")";
|
||||
return func(st, std::move(cell));
|
||||
}
|
||||
|
||||
int exec_ifelse_ref(VmState* st, CellSlice& cs, int pfx_bits, bool mode) {
|
||||
const char* name = mode ? "IFREFELSE" : "IFELSEREF";
|
||||
if (!cs.have_refs(1)) {
|
||||
throw VmError{Excno::inv_opcode, "no references left for a "s + name + " instruction"};
|
||||
}
|
||||
cs.advance(pfx_bits);
|
||||
auto cell = cs.fetch_ref();
|
||||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute " << name << " (" << cell->get_hash().to_hex() << ")";
|
||||
stack.check_underflow(2);
|
||||
auto cont = stack.pop_cont();
|
||||
if (stack.pop_bool() == mode) {
|
||||
cont = st->ref_to_cont(std::move(cell));
|
||||
} else {
|
||||
cell.clear();
|
||||
}
|
||||
return st->call(std::move(cont));
|
||||
}
|
||||
|
||||
int exec_ifref_elseref(VmState* st, CellSlice& cs, unsigned args, int pfx_bits) {
|
||||
if (!cs.have_refs(2)) {
|
||||
throw VmError{Excno::inv_opcode, "no references left for a IFREFELSEREF instruction"};
|
||||
}
|
||||
cs.advance(pfx_bits);
|
||||
auto cell1 = cs.fetch_ref(), cell2 = cs.fetch_ref();
|
||||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute IFREFELSEREF (" << cell1->get_hash().to_hex() << ") (" << cell2->get_hash().to_hex() << ")";
|
||||
if (!stack.pop_bool()) {
|
||||
cell1 = std::move(cell2);
|
||||
} else {
|
||||
cell2.clear();
|
||||
}
|
||||
return st->call(st->ref_to_cont(std::move(cell1)));
|
||||
}
|
||||
|
||||
int exec_ret_data(VmState* st) {
|
||||
|
@ -349,7 +397,7 @@ int exec_if_bit_jmpref(VmState* st, CellSlice& cs, unsigned args, int pfx_bits)
|
|||
bool val = x->get_bit(bit);
|
||||
stack.push_int(std::move(x));
|
||||
if (val ^ negate) {
|
||||
return st->jump(Ref<OrdCont>{true, load_cell_slice_ref(std::move(cell)), st->get_cp()});
|
||||
return st->jump(st->ref_to_cont(std::move(cell)));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -365,66 +413,72 @@ std::string dump_if_bit_jmpref(CellSlice& cs, unsigned args, int pfx_bits) {
|
|||
return os.str();
|
||||
}
|
||||
|
||||
int exec_repeat(VmState* st) {
|
||||
int exec_repeat(VmState* st, bool brk) {
|
||||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute REPEAT\n";
|
||||
VM_LOG(st) << "execute REPEAT" << (brk ? "BRK" : "");
|
||||
stack.check_underflow(2);
|
||||
auto cont = stack.pop_cont();
|
||||
int c = stack.pop_smallint_range(0x7fffffff, 0x80000000);
|
||||
if (c <= 0) {
|
||||
return 0;
|
||||
}
|
||||
return st->repeat(std::move(cont), st->extract_cc(1), c);
|
||||
return st->repeat(std::move(cont), st->c1_envelope_if(brk, st->extract_cc(1)), c);
|
||||
}
|
||||
|
||||
int exec_repeat_end(VmState* st) {
|
||||
int exec_repeat_end(VmState* st, bool brk) {
|
||||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute REPEATEND\n";
|
||||
VM_LOG(st) << "execute REPEATEND" << (brk ? "BRK" : "");
|
||||
stack.check_underflow(1);
|
||||
int c = stack.pop_smallint_range(0x7fffffff, 0x80000000);
|
||||
if (c <= 0) {
|
||||
return st->ret();
|
||||
}
|
||||
auto cont = st->extract_cc(0);
|
||||
return st->repeat(std::move(cont), st->get_c0(), c);
|
||||
return st->repeat(std::move(cont), st->c1_envelope_if(brk, st->get_c0()), c);
|
||||
}
|
||||
|
||||
int exec_until(VmState* st) {
|
||||
int exec_until(VmState* st, bool brk) {
|
||||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute UNTIL\n";
|
||||
VM_LOG(st) << "execute UNTIL" << (brk ? "BRK" : "");
|
||||
auto cont = stack.pop_cont();
|
||||
return st->until(std::move(cont), st->extract_cc(1));
|
||||
return st->until(std::move(cont), st->c1_envelope_if(brk, st->extract_cc(1)));
|
||||
}
|
||||
|
||||
int exec_until_end(VmState* st) {
|
||||
VM_LOG(st) << "execute UNTILEND\n";
|
||||
int exec_until_end(VmState* st, bool brk) {
|
||||
VM_LOG(st) << "execute UNTILEND" << (brk ? "BRK" : "");
|
||||
auto cont = st->extract_cc(0);
|
||||
return st->until(std::move(cont), st->get_c0());
|
||||
return st->until(std::move(cont), st->c1_envelope_if(brk, st->get_c0()));
|
||||
}
|
||||
|
||||
int exec_while(VmState* st) {
|
||||
int exec_while(VmState* st, bool brk) {
|
||||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute WHILE\n";
|
||||
VM_LOG(st) << "execute WHILE" << (brk ? "BRK" : "");
|
||||
stack.check_underflow(2);
|
||||
auto body = stack.pop_cont();
|
||||
auto cond = stack.pop_cont();
|
||||
return st->loop_while(std::move(cond), std::move(body), st->extract_cc(1));
|
||||
return st->loop_while(std::move(cond), std::move(body), st->c1_envelope_if(brk, st->extract_cc(1)));
|
||||
}
|
||||
|
||||
int exec_while_end(VmState* st) {
|
||||
VM_LOG(st) << "execute WHILEEND\n";
|
||||
int exec_while_end(VmState* st, bool brk) {
|
||||
VM_LOG(st) << "execute WHILEEND" << (brk ? "BRK" : "");
|
||||
auto cond = st->get_stack().pop_cont();
|
||||
auto body = st->extract_cc(0);
|
||||
return st->loop_while(std::move(cond), std::move(body), st->get_c0());
|
||||
return st->loop_while(std::move(cond), std::move(body), st->c1_envelope_if(brk, st->get_c0()));
|
||||
}
|
||||
|
||||
int exec_again(VmState* st) {
|
||||
VM_LOG(st) << "execute AGAIN\n";
|
||||
int exec_again(VmState* st, bool brk) {
|
||||
VM_LOG(st) << "execute AGAIN" << (brk ? "BRK" : "");
|
||||
if (brk) {
|
||||
st->set_c1(st->extract_cc(3));
|
||||
}
|
||||
return st->again(st->get_stack().pop_cont());
|
||||
}
|
||||
|
||||
int exec_again_end(VmState* st) {
|
||||
VM_LOG(st) << "execute AGAINEND\n";
|
||||
int exec_again_end(VmState* st, bool brk) {
|
||||
VM_LOG(st) << "execute AGAINEND" << (brk ? "BRK" : "");
|
||||
if (brk) {
|
||||
st->c1_save_set();
|
||||
}
|
||||
return st->again(st->extract_cc(0));
|
||||
}
|
||||
|
||||
|
@ -437,44 +491,70 @@ void register_continuation_cond_loop_ops(OpcodeTable& cp0) {
|
|||
.insert(OpcodeInstr::mksimple(0xe0, 8, "IFJMP", exec_if_jmp))
|
||||
.insert(OpcodeInstr::mksimple(0xe1, 8, "IFNOTJMP", exec_ifnot_jmp))
|
||||
.insert(OpcodeInstr::mksimple(0xe2, 8, "IFELSE", exec_if_else))
|
||||
.insert(OpcodeInstr::mkext(
|
||||
0xe300, 16, 0, std::bind(dump_push_ref, _1, _2, _3, "IFREF"),
|
||||
std::bind(exec_do_with_ref, _1, _2, _4,
|
||||
[](auto st, auto cont) { return st->get_stack().pop_bool() ? st->call(std::move(cont)) : 0; },
|
||||
"IFREF"),
|
||||
compute_len_push_ref))
|
||||
.insert(OpcodeInstr::mkext(
|
||||
0xe301, 16, 0, std::bind(dump_push_ref, _1, _2, _3, "IFNOTREF"),
|
||||
std::bind(exec_do_with_ref, _1, _2, _4,
|
||||
[](auto st, auto cont) { return st->get_stack().pop_bool() ? 0 : st->call(std::move(cont)); },
|
||||
"IFNOTREF"),
|
||||
compute_len_push_ref))
|
||||
.insert(OpcodeInstr::mkext(
|
||||
0xe302, 16, 0, std::bind(dump_push_ref, _1, _2, _3, "IFJMPREF"),
|
||||
std::bind(exec_do_with_ref, _1, _2, _4,
|
||||
[](auto st, auto cont) { return st->get_stack().pop_bool() ? st->jump(std::move(cont)) : 0; },
|
||||
"IFJMPREF"),
|
||||
compute_len_push_ref))
|
||||
.insert(OpcodeInstr::mkext(
|
||||
0xe303, 16, 0, std::bind(dump_push_ref, _1, _2, _3, "IFNOTJMPREF"),
|
||||
std::bind(exec_do_with_ref, _1, _2, _4,
|
||||
[](auto st, auto cont) { return st->get_stack().pop_bool() ? 0 : st->jump(std::move(cont)); },
|
||||
"IFNOTJMPREF"),
|
||||
compute_len_push_ref))
|
||||
.insert(OpcodeInstr::mkext(0xe300, 16, 0, std::bind(dump_push_ref, _1, _2, _3, "IFREF"),
|
||||
std::bind(exec_do_with_cell, _1, _2, _4,
|
||||
[](auto st, auto cell) {
|
||||
return st->get_stack().pop_bool()
|
||||
? st->call(st->ref_to_cont(std::move(cell)))
|
||||
: 0;
|
||||
},
|
||||
"IFREF"),
|
||||
compute_len_push_ref))
|
||||
.insert(OpcodeInstr::mkext(0xe301, 16, 0, std::bind(dump_push_ref, _1, _2, _3, "IFNOTREF"),
|
||||
std::bind(exec_do_with_cell, _1, _2, _4,
|
||||
[](auto st, auto cell) {
|
||||
return st->get_stack().pop_bool()
|
||||
? 0
|
||||
: st->call(st->ref_to_cont(std::move(cell)));
|
||||
},
|
||||
"IFNOTREF"),
|
||||
compute_len_push_ref))
|
||||
.insert(OpcodeInstr::mkext(0xe302, 16, 0, std::bind(dump_push_ref, _1, _2, _3, "IFJMPREF"),
|
||||
std::bind(exec_do_with_cell, _1, _2, _4,
|
||||
[](auto st, auto cell) {
|
||||
return st->get_stack().pop_bool()
|
||||
? st->jump(st->ref_to_cont(std::move(cell)))
|
||||
: 0;
|
||||
},
|
||||
"IFJMPREF"),
|
||||
compute_len_push_ref))
|
||||
.insert(OpcodeInstr::mkext(0xe303, 16, 0, std::bind(dump_push_ref, _1, _2, _3, "IFNOTJMPREF"),
|
||||
std::bind(exec_do_with_cell, _1, _2, _4,
|
||||
[](auto st, auto cell) {
|
||||
return st->get_stack().pop_bool()
|
||||
? 0
|
||||
: st->jump(st->ref_to_cont(std::move(cell)));
|
||||
},
|
||||
"IFNOTJMPREF"),
|
||||
compute_len_push_ref))
|
||||
.insert(OpcodeInstr::mksimple(0xe304, 16, "CONDSEL", exec_condsel))
|
||||
.insert(OpcodeInstr::mksimple(0xe305, 16, "CONDSELCHK", exec_condsel_chk))
|
||||
.insert(OpcodeInstr::mksimple(0xe308, 16, "IFRETALT", exec_ifretalt))
|
||||
.insert(OpcodeInstr::mksimple(0xe309, 16, "IFNOTRETALT", exec_ifnotretalt))
|
||||
.insert(OpcodeInstr::mkext(0xe30d, 16, 0, std::bind(dump_push_ref, _1, _2, _3, "IFREFELSE"),
|
||||
std::bind(exec_ifelse_ref, _1, _2, _4, true), compute_len_push_ref))
|
||||
.insert(OpcodeInstr::mkext(0xe30e, 16, 0, std::bind(dump_push_ref, _1, _2, _3, "IFELSEREF"),
|
||||
std::bind(exec_ifelse_ref, _1, _2, _4, false), compute_len_push_ref))
|
||||
.insert(OpcodeInstr::mkext(0xe30f, 16, 0, std::bind(dump_push_ref2, _1, _2, _3, "IFREFELSEREF"),
|
||||
exec_ifref_elseref, compute_len_push_ref2))
|
||||
.insert(OpcodeInstr::mkfixed(0xe380 >> 6, 10, 6, dump_if_bit_jmp, exec_if_bit_jmp))
|
||||
.insert(OpcodeInstr::mkext(0xe3c0 >> 6, 10, 6, dump_if_bit_jmpref, exec_if_bit_jmpref, compute_len_push_ref))
|
||||
.insert(OpcodeInstr::mksimple(0xe4, 8, "REPEAT", exec_repeat))
|
||||
.insert(OpcodeInstr::mksimple(0xe5, 8, "REPEATEND", exec_repeat_end))
|
||||
.insert(OpcodeInstr::mksimple(0xe6, 8, "UNTIL", exec_until))
|
||||
.insert(OpcodeInstr::mksimple(0xe7, 8, "UNTILEND", exec_until_end))
|
||||
.insert(OpcodeInstr::mksimple(0xe8, 8, "WHILE", exec_while))
|
||||
.insert(OpcodeInstr::mksimple(0xe9, 8, "WHILEEND", exec_while_end))
|
||||
.insert(OpcodeInstr::mksimple(0xea, 8, "AGAIN", exec_again))
|
||||
.insert(OpcodeInstr::mksimple(0xeb, 8, "AGAINEND", exec_again_end));
|
||||
.insert(OpcodeInstr::mksimple(0xe4, 8, "REPEAT", std::bind(exec_repeat, _1, false)))
|
||||
.insert(OpcodeInstr::mksimple(0xe5, 8, "REPEATEND", std::bind(exec_repeat_end, _1, false)))
|
||||
.insert(OpcodeInstr::mksimple(0xe6, 8, "UNTIL", std::bind(exec_until, _1, false)))
|
||||
.insert(OpcodeInstr::mksimple(0xe7, 8, "UNTILEND", std::bind(exec_until_end, _1, false)))
|
||||
.insert(OpcodeInstr::mksimple(0xe8, 8, "WHILE", std::bind(exec_while, _1, false)))
|
||||
.insert(OpcodeInstr::mksimple(0xe9, 8, "WHILEEND", std::bind(exec_while_end, _1, false)))
|
||||
.insert(OpcodeInstr::mksimple(0xea, 8, "AGAIN", std::bind(exec_again, _1, false)))
|
||||
.insert(OpcodeInstr::mksimple(0xeb, 8, "AGAINEND", std::bind(exec_again_end, _1, false)))
|
||||
.insert(OpcodeInstr::mksimple(0xe314, 16, "REPEATBRK", std::bind(exec_repeat, _1, true)))
|
||||
.insert(OpcodeInstr::mksimple(0xe315, 16, "REPEATENDBRK", std::bind(exec_repeat_end, _1, true)))
|
||||
.insert(OpcodeInstr::mksimple(0xe316, 16, "UNTILBRK", std::bind(exec_until, _1, true)))
|
||||
.insert(OpcodeInstr::mksimple(0xe317, 16, "UNTILENDBRK", std::bind(exec_until_end, _1, true)))
|
||||
.insert(OpcodeInstr::mksimple(0xe318, 16, "WHILEBRK", std::bind(exec_while, _1, true)))
|
||||
.insert(OpcodeInstr::mksimple(0xe319, 16, "WHILEENDBRK", std::bind(exec_while_end, _1, true)))
|
||||
.insert(OpcodeInstr::mksimple(0xe31a, 16, "AGAINBRK", std::bind(exec_again, _1, true)))
|
||||
.insert(OpcodeInstr::mksimple(0xe31b, 16, "AGAINENDBRK", std::bind(exec_again_end, _1, true)));
|
||||
}
|
||||
|
||||
int exec_setcontargs_common(VmState* st, int copy, int more) {
|
||||
|
@ -706,6 +786,17 @@ int exec_save_ctr(VmState* st, unsigned args) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int exec_samealt(VmState* st, bool save) {
|
||||
VM_LOG(st) << "execute SAMEALT" << (save ? "SAVE" : "");
|
||||
auto c0 = st->get_c0();
|
||||
if (save) {
|
||||
force_cregs(c0)->define_c1(st->get_c1());
|
||||
st->set_c0(c0);
|
||||
}
|
||||
st->set_c1(std::move(c0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int exec_savealt_ctr(VmState* st, unsigned args) {
|
||||
unsigned idx = args & 15;
|
||||
VM_LOG(st) << "execute SAVEALTCTR c" << idx;
|
||||
|
@ -883,6 +974,8 @@ void register_continuation_change_ops(OpcodeTable& cp0) {
|
|||
.insert(OpcodeInstr::mksimple(0xedf7, 16, "THENRETALT", exec_thenret_alt))
|
||||
.insert(OpcodeInstr::mksimple(0xedf8, 16, "INVERT", exec_invert))
|
||||
.insert(OpcodeInstr::mksimple(0xedf9, 16, "BOOLEVAL", exec_booleval))
|
||||
.insert(OpcodeInstr::mksimple(0xedfa, 16, "SAMEALT", std::bind(exec_samealt, _1, false)))
|
||||
.insert(OpcodeInstr::mksimple(0xedfb, 16, "SAMEALTSAVE", std::bind(exec_samealt, _1, true)))
|
||||
.insert(OpcodeInstr::mkfixed(0xee, 8, 8, std::bind(dump_setcontargs, _1, _2, "BLESSARGS"), exec_bless_args));
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -45,6 +45,7 @@ const char* get_exception_msg(Excno exc_no);
|
|||
|
||||
class VmError {
|
||||
Excno exc_no;
|
||||
bool msg_alloc = false;
|
||||
const char* msg;
|
||||
long long arg;
|
||||
|
||||
|
@ -55,6 +56,18 @@ class VmError {
|
|||
}
|
||||
VmError(Excno _excno, const char* _msg, long long _arg) : exc_no(_excno), msg(_msg), arg(_arg) {
|
||||
}
|
||||
VmError(Excno _excno, std::string _msg, long long _arg = 0) : exc_no(_excno), msg_alloc(true), arg(_arg) {
|
||||
msg_alloc = true;
|
||||
char* p = (char*)malloc(_msg.size() + 1);
|
||||
memcpy(p, _msg.data(), _msg.size());
|
||||
p[_msg.size()] = 0;
|
||||
msg = p;
|
||||
}
|
||||
~VmError() {
|
||||
if (msg_alloc) {
|
||||
free(const_cast<char*>(msg));
|
||||
}
|
||||
}
|
||||
int get_errno() const {
|
||||
return static_cast<int>(exc_no);
|
||||
}
|
||||
|
|
|
@ -333,6 +333,22 @@ int VmState::ret_alt(int ret_args) {
|
|||
return jump(std::move(cont), ret_args);
|
||||
}
|
||||
|
||||
Ref<Continuation> VmState::c1_envelope(Ref<Continuation> cont, bool save) {
|
||||
if (save) {
|
||||
force_cregs(cont)->define_c1(cr.c[1]);
|
||||
force_cregs(cont)->define_c0(cr.c[0]);
|
||||
}
|
||||
set_c1(cont);
|
||||
return cont;
|
||||
}
|
||||
|
||||
void VmState::c1_save_set(bool save) {
|
||||
if (save) {
|
||||
force_cregs(cr.c[0])->define_c1(cr.c[1]);
|
||||
}
|
||||
set_c1(cr.c[0]);
|
||||
}
|
||||
|
||||
Ref<OrdCont> VmState::extract_cc(int save_cr, int stack_copy, int cc_args) {
|
||||
Ref<Stack> new_stk;
|
||||
if (stack_copy < 0 || stack_copy == stack->depth()) {
|
||||
|
|
|
@ -297,6 +297,11 @@ class VmState final : public VmStateInterface {
|
|||
int throw_exception(int excno, StackEntry&& arg);
|
||||
int throw_exception(int excno);
|
||||
Ref<OrdCont> extract_cc(int save_cr = 1, int stack_copy = -1, int cc_args = -1);
|
||||
Ref<Continuation> c1_envelope(Ref<Continuation> cont, bool save = true);
|
||||
Ref<Continuation> c1_envelope_if(bool cond, Ref<Continuation> cont, bool save = true) {
|
||||
return cond ? c1_envelope(std::move(cont), save) : std::move(cont);
|
||||
}
|
||||
void c1_save_set(bool save = true);
|
||||
void fatal(void) const {
|
||||
throw VmFatal{};
|
||||
}
|
||||
|
@ -313,6 +318,9 @@ class VmState final : public VmStateInterface {
|
|||
bool get_chksig_always_succeed() const {
|
||||
return chksig_always_succeed;
|
||||
}
|
||||
Ref<OrdCont> ref_to_cont(Ref<Cell> cell) const {
|
||||
return td::make_ref<OrdCont>(load_cell_slice_ref(std::move(cell)), get_cp());
|
||||
}
|
||||
|
||||
private:
|
||||
void init_cregs(bool same_c3 = false, bool push_0 = true);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue