refactor(library/vm): use global indices for declarations and cases
This commit is contained in:
parent
4c01cb503c
commit
41e8a1712e
2 changed files with 137 additions and 124 deletions
|
|
@ -16,6 +16,7 @@ Author: Leonardo de Moura
|
||||||
#include "util/sstream.h"
|
#include "util/sstream.h"
|
||||||
#include "util/small_object_allocator.h"
|
#include "util/small_object_allocator.h"
|
||||||
#include "util/sexpr/option_declarations.h"
|
#include "util/sexpr/option_declarations.h"
|
||||||
|
#include "util/shared_mutex.h"
|
||||||
#include "library/constants.h"
|
#include "library/constants.h"
|
||||||
#include "library/kernel_serializer.h"
|
#include "library/kernel_serializer.h"
|
||||||
#include "library/trace.h"
|
#include "library/trace.h"
|
||||||
|
|
@ -272,14 +273,14 @@ void vm_obj_cell::dealloc() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void display(std::ostream & out, vm_obj const & o, std::function<optional<name>(unsigned)> const & idx2name) {
|
void display(std::ostream & out, vm_obj const & o) {
|
||||||
if (is_simple(o)) {
|
if (is_simple(o)) {
|
||||||
out << cidx(o);
|
out << cidx(o);
|
||||||
} else if (is_constructor(o)) {
|
} else if (is_constructor(o)) {
|
||||||
out << "(#" << cidx(o);
|
out << "(#" << cidx(o);
|
||||||
for (unsigned i = 0; i < csize(o); i++) {
|
for (unsigned i = 0; i < csize(o); i++) {
|
||||||
out << " ";
|
out << " ";
|
||||||
display(out, cfield(o, i), idx2name);
|
display(out, cfield(o, i));
|
||||||
}
|
}
|
||||||
out << ")";
|
out << ")";
|
||||||
} else if (is_mpz(o)) {
|
} else if (is_mpz(o)) {
|
||||||
|
|
@ -287,14 +288,14 @@ void display(std::ostream & out, vm_obj const & o, std::function<optional<name>(
|
||||||
} else if (is_external(o)) {
|
} else if (is_external(o)) {
|
||||||
out << "[external]";
|
out << "[external]";
|
||||||
} else if (is_closure(o)) {
|
} else if (is_closure(o)) {
|
||||||
if (auto n = idx2name(cfn_idx(o))) {
|
if (auto n = find_vm_name(cfn_idx(o))) {
|
||||||
out << "(" << *n;
|
out << "(" << *n;
|
||||||
} else {
|
} else {
|
||||||
out << "(fn#" << cfn_idx(o);
|
out << "(fn#" << cfn_idx(o);
|
||||||
}
|
}
|
||||||
for (unsigned i = 0; i < csize(o); i++) {
|
for (unsigned i = 0; i < csize(o); i++) {
|
||||||
out << " ";
|
out << " ";
|
||||||
display(out, cfield(o, i), idx2name);
|
display(out, cfield(o, i));
|
||||||
}
|
}
|
||||||
out << ")";
|
out << ")";
|
||||||
} else if (is_native_closure(o)) {
|
} else if (is_native_closure(o)) {
|
||||||
|
|
@ -302,7 +303,7 @@ void display(std::ostream & out, vm_obj const & o, std::function<optional<name>(
|
||||||
vm_obj const * args = to_native_closure(o)->get_args();
|
vm_obj const * args = to_native_closure(o)->get_args();
|
||||||
for (unsigned i = 0; i < to_native_closure(o)->get_num_args(); i++) {
|
for (unsigned i = 0; i < to_native_closure(o)->get_num_args(); i++) {
|
||||||
out << " ";
|
out << " ";
|
||||||
display(out, args[i], idx2name);
|
display(out, args[i]);
|
||||||
}
|
}
|
||||||
out << ")";
|
out << ")";
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -310,24 +311,18 @@ void display(std::ostream & out, vm_obj const & o, std::function<optional<name>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void display(std::ostream & out, vm_obj const & o) {
|
static void display_fn(std::ostream & out, unsigned fn_idx) {
|
||||||
display(out, o, [](unsigned) { return optional<name>(); });
|
if (auto r = find_vm_name(fn_idx))
|
||||||
}
|
|
||||||
|
|
||||||
static void display_fn(std::ostream & out, std::function<optional<name>(unsigned)> const & idx2name, unsigned fn_idx) {
|
|
||||||
if (auto r = idx2name(fn_idx))
|
|
||||||
out << *r;
|
out << *r;
|
||||||
else
|
else
|
||||||
out << fn_idx;
|
out << fn_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void display_builtin_cases(std::ostream & out, std::function<optional<name>(unsigned)> const & idx2name, unsigned cases_idx) {
|
static void display_builtin_cases(std::ostream & out, unsigned cases_idx) {
|
||||||
display_fn(out, idx2name, cases_idx);
|
display_fn(out, cases_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_instr::display(std::ostream & out,
|
void vm_instr::display(std::ostream & out) const {
|
||||||
std::function<optional<name>(unsigned)> const & idx2name,
|
|
||||||
std::function<optional<name>(unsigned)> const & cases_idx2name) const {
|
|
||||||
switch (m_op) {
|
switch (m_op) {
|
||||||
case opcode::Push: out << "push " << m_idx; break;
|
case opcode::Push: out << "push " << m_idx; break;
|
||||||
case opcode::Ret: out << "ret"; break;
|
case opcode::Ret: out << "ret"; break;
|
||||||
|
|
@ -346,7 +341,7 @@ void vm_instr::display(std::ostream & out,
|
||||||
break;
|
break;
|
||||||
case opcode::BuiltinCases:
|
case opcode::BuiltinCases:
|
||||||
out << "builtin_cases ";
|
out << "builtin_cases ";
|
||||||
display_builtin_cases(out, cases_idx2name, get_cases_idx());
|
display_builtin_cases(out, get_cases_idx());
|
||||||
out << ",";
|
out << ",";
|
||||||
for (unsigned i = 0; i < get_casesn_size(); i++)
|
for (unsigned i = 0; i < get_casesn_size(); i++)
|
||||||
out << " " << get_casesn_pc(i);
|
out << " " << get_casesn_pc(i);
|
||||||
|
|
@ -356,19 +351,19 @@ void vm_instr::display(std::ostream & out,
|
||||||
case opcode::Apply: out << "apply"; break;
|
case opcode::Apply: out << "apply"; break;
|
||||||
case opcode::InvokeGlobal:
|
case opcode::InvokeGlobal:
|
||||||
out << "ginvoke ";
|
out << "ginvoke ";
|
||||||
display_fn(out, idx2name, m_fn_idx);
|
display_fn(out, m_fn_idx);
|
||||||
break;
|
break;
|
||||||
case opcode::InvokeBuiltin:
|
case opcode::InvokeBuiltin:
|
||||||
out << "builtin ";
|
out << "builtin ";
|
||||||
display_fn(out, idx2name, m_fn_idx);
|
display_fn(out, m_fn_idx);
|
||||||
break;
|
break;
|
||||||
case opcode::InvokeCFun:
|
case opcode::InvokeCFun:
|
||||||
out << "cfun ";
|
out << "cfun ";
|
||||||
display_fn(out, idx2name, m_fn_idx);
|
display_fn(out, m_fn_idx);
|
||||||
break;
|
break;
|
||||||
case opcode::Closure:
|
case opcode::Closure:
|
||||||
out << "closure ";
|
out << "closure ";
|
||||||
display_fn(out, idx2name, m_fn_idx);
|
display_fn(out, m_fn_idx);
|
||||||
out << " " << m_nargs;
|
out << " " << m_nargs;
|
||||||
break;
|
break;
|
||||||
case opcode::Pexpr:
|
case opcode::Pexpr:
|
||||||
|
|
@ -378,10 +373,6 @@ void vm_instr::display(std::ostream & out,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_instr::display(std::ostream & out) const {
|
|
||||||
display(out, [](unsigned) { return optional<name>(); }, [](unsigned) { return optional<name>(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned vm_instr::get_num_pcs() const {
|
unsigned vm_instr::get_num_pcs() const {
|
||||||
switch (m_op) {
|
switch (m_op) {
|
||||||
case opcode::Goto:
|
case opcode::Goto:
|
||||||
|
|
@ -723,13 +714,10 @@ void vm_instr::serialize(serializer & s, std::function<name(unsigned)> const & i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned read_fn_idx(deserializer & d, name_map<unsigned> const & name2idx) {
|
static unsigned read_fn_idx(deserializer & d) {
|
||||||
name n;
|
name n;
|
||||||
d >> n;
|
d >> n;
|
||||||
if (auto r = name2idx.find(n))
|
return get_vm_index(n);
|
||||||
return *r;
|
|
||||||
else
|
|
||||||
throw corrupted_stream_exception();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void read_cases_pcs(deserializer & d, buffer<unsigned> & pcs) {
|
static void read_cases_pcs(deserializer & d, buffer<unsigned> & pcs) {
|
||||||
|
|
@ -738,18 +726,18 @@ static void read_cases_pcs(deserializer & d, buffer<unsigned> & pcs) {
|
||||||
pcs.push_back(d.read_unsigned());
|
pcs.push_back(d.read_unsigned());
|
||||||
}
|
}
|
||||||
|
|
||||||
static vm_instr read_vm_instr(deserializer & d, name_map<unsigned> const & name2idx) {
|
static vm_instr read_vm_instr(deserializer & d) {
|
||||||
opcode op = static_cast<opcode>(d.read_char());
|
opcode op = static_cast<opcode>(d.read_char());
|
||||||
unsigned pc, idx;
|
unsigned pc, idx;
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case opcode::InvokeGlobal:
|
case opcode::InvokeGlobal:
|
||||||
return mk_invoke_global_instr(read_fn_idx(d, name2idx));
|
return mk_invoke_global_instr(read_fn_idx(d));
|
||||||
case opcode::InvokeBuiltin:
|
case opcode::InvokeBuiltin:
|
||||||
return mk_invoke_builtin_instr(read_fn_idx(d, name2idx));
|
return mk_invoke_builtin_instr(read_fn_idx(d));
|
||||||
case opcode::InvokeCFun:
|
case opcode::InvokeCFun:
|
||||||
return mk_invoke_cfun_instr(read_fn_idx(d, name2idx));
|
return mk_invoke_cfun_instr(read_fn_idx(d));
|
||||||
case opcode::Closure:
|
case opcode::Closure:
|
||||||
idx = read_fn_idx(d, name2idx);
|
idx = read_fn_idx(d);
|
||||||
return mk_closure_instr(idx, d.read_unsigned());
|
return mk_closure_instr(idx, d.read_unsigned());
|
||||||
case opcode::Push:
|
case opcode::Push:
|
||||||
return mk_push_instr(d.read_unsigned());
|
return mk_push_instr(d.read_unsigned());
|
||||||
|
|
@ -906,58 +894,40 @@ void declare_vm_cases_builtin(name const & n, char const * i, vm_cases_function
|
||||||
|
|
||||||
/** \brief VM function/constant declarations are stored in an environment extension. */
|
/** \brief VM function/constant declarations are stored in an environment extension. */
|
||||||
struct vm_decls : public environment_extension {
|
struct vm_decls : public environment_extension {
|
||||||
name_map<unsigned> m_name2idx;
|
unsigned_map<vm_decl> m_decls;
|
||||||
unsigned_map<vm_decl> m_decls;
|
|
||||||
unsigned m_next_decl_idx{0};
|
|
||||||
|
|
||||||
name_map<unsigned> m_cases2idx;
|
|
||||||
unsigned_map<vm_cases_function> m_cases;
|
unsigned_map<vm_cases_function> m_cases;
|
||||||
unsigned_map<name> m_cases_names;
|
|
||||||
unsigned m_next_cases_idx{0};
|
|
||||||
|
|
||||||
name m_monitor;
|
name m_monitor;
|
||||||
|
|
||||||
vm_decls() {
|
vm_decls() {
|
||||||
g_vm_builtins->for_each([&](name const & n, std::tuple<unsigned, char const *, vm_function> const & p) {
|
g_vm_builtins->for_each([&](name const & n, std::tuple<unsigned, char const *, vm_function> const & p) {
|
||||||
add_core(vm_decl(n, m_next_decl_idx, std::get<0>(p), std::get<2>(p)));
|
add_core(vm_decl(n, get_vm_index(n), std::get<0>(p), std::get<2>(p)));
|
||||||
m_next_decl_idx++;
|
|
||||||
});
|
});
|
||||||
g_vm_cbuiltins->for_each([&](name const & n, std::tuple<unsigned, char const *, vm_cfunction> const & p) {
|
g_vm_cbuiltins->for_each([&](name const & n, std::tuple<unsigned, char const *, vm_cfunction> const & p) {
|
||||||
add_core(vm_decl(n, m_next_decl_idx, std::get<0>(p), std::get<2>(p)));
|
add_core(vm_decl(n, get_vm_index(n), std::get<0>(p), std::get<2>(p)));
|
||||||
m_next_decl_idx++;
|
|
||||||
});
|
});
|
||||||
g_vm_cases_builtins->for_each([&](name const & n, std::tuple<char const *, vm_cases_function> const & p) {
|
g_vm_cases_builtins->for_each([&](name const & n, std::tuple<char const *, vm_cases_function> const & p) {
|
||||||
unsigned idx = m_next_cases_idx;
|
unsigned idx = get_vm_index(n);
|
||||||
m_cases2idx.insert(n, idx);
|
|
||||||
m_cases.insert(idx, std::get<1>(p));
|
m_cases.insert(idx, std::get<1>(p));
|
||||||
m_cases_names.insert(idx, n);
|
|
||||||
m_next_cases_idx++;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_core(vm_decl const & d) {
|
void add_core(vm_decl const & d) {
|
||||||
if (m_name2idx.contains(d.get_name()))
|
if (m_decls.contains(d.get_idx()))
|
||||||
throw exception(sstream() << "VM already contains code for '" << d.get_name() << "'");
|
throw exception(sstream() << "VM already contains code for '" << d.get_name() << "'");
|
||||||
m_name2idx.insert(d.get_name(), d.get_idx());
|
|
||||||
m_decls.insert(d.get_idx(), d);
|
m_decls.insert(d.get_idx(), d);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_native(name const & n, unsigned arity, vm_cfunction fn) {
|
void add_native(name const & n, unsigned arity, vm_cfunction fn) {
|
||||||
if (auto idx = m_name2idx.find(n)) {
|
auto idx = get_vm_index(n);
|
||||||
lean_assert(m_decls.find(*idx)->get_arity() == arity);
|
DEBUG_CODE(if (auto decl = m_decls.find(idx)) lean_assert(decl->get_arity() == arity);)
|
||||||
m_decls.insert(*idx, vm_decl(n, *idx, arity, fn));
|
m_decls.insert(idx, vm_decl(n, idx, arity, fn));
|
||||||
} else {
|
|
||||||
add_core(vm_decl(n, m_next_decl_idx, arity, fn));
|
|
||||||
m_next_decl_idx++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned reserve(name const & n, expr const & e) {
|
unsigned reserve(name const & n, expr const & e) {
|
||||||
if (m_name2idx.contains(n))
|
unsigned idx = get_vm_index(n);
|
||||||
|
if (m_decls.contains(idx))
|
||||||
throw exception(sstream() << "VM already contains code for '" << n << "'");
|
throw exception(sstream() << "VM already contains code for '" << n << "'");
|
||||||
unsigned idx = m_next_decl_idx;
|
|
||||||
m_next_decl_idx++;
|
|
||||||
m_name2idx.insert(n, idx);
|
|
||||||
m_decls.insert(idx, vm_decl(n, idx, e, 0, nullptr, list<vm_local_info>(), optional<pos_info>()));
|
m_decls.insert(idx, vm_decl(n, idx, e, 0, nullptr, list<vm_local_info>(), optional<pos_info>()));
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
@ -965,9 +935,9 @@ struct vm_decls : public environment_extension {
|
||||||
void update(name const & n, unsigned code_sz, vm_instr const * code,
|
void update(name const & n, unsigned code_sz, vm_instr const * code,
|
||||||
list<vm_local_info> const & args_info, optional<pos_info> const & pos,
|
list<vm_local_info> const & args_info, optional<pos_info> const & pos,
|
||||||
optional<std::string> const & olean = optional<std::string>()) {
|
optional<std::string> const & olean = optional<std::string>()) {
|
||||||
lean_assert(m_name2idx.contains(n));
|
unsigned idx = get_vm_index(n);
|
||||||
unsigned idx = *m_name2idx.find(n);
|
|
||||||
vm_decl const * d = m_decls.find(idx);
|
vm_decl const * d = m_decls.find(idx);
|
||||||
|
lean_assert(d);
|
||||||
m_decls.insert(idx, vm_decl(n, idx, d->get_expr(), code_sz, code, args_info, pos, olean));
|
m_decls.insert(idx, vm_decl(n, idx, d->get_expr(), code_sz, code, args_info, pos, olean));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1037,21 +1007,23 @@ environment add_native(environment const & env, name const & n, unsigned arity,
|
||||||
|
|
||||||
bool is_vm_function(environment const & env, name const & fn) {
|
bool is_vm_function(environment const & env, name const & fn) {
|
||||||
auto const & ext = get_extension(env);
|
auto const & ext = get_extension(env);
|
||||||
return ext.m_name2idx.contains(fn) || g_vm_builtins->contains(fn);
|
return ext.m_decls.contains(get_vm_index(fn)) || g_vm_builtins->contains(fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<unsigned> get_vm_constant_idx(environment const & env, name const & n) {
|
optional<unsigned> get_vm_constant_idx(environment const & env, name const & n) {
|
||||||
auto const & ext = get_extension(env);
|
auto const & ext = get_extension(env);
|
||||||
if (auto r = ext.m_name2idx.find(n))
|
auto idx = get_vm_index(n);
|
||||||
return optional<unsigned>(*r);
|
if (ext.m_decls.contains(idx))
|
||||||
|
return optional<unsigned>(idx);
|
||||||
else
|
else
|
||||||
return optional<unsigned>();
|
return optional<unsigned>();
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<unsigned> get_vm_builtin_idx(name const & n) {
|
optional<unsigned> get_vm_builtin_idx(name const & n) {
|
||||||
lean_assert(g_ext);
|
lean_assert(g_ext);
|
||||||
if (auto r = g_ext->m_init_decls->m_name2idx.find(n))
|
auto idx = get_vm_index(n);
|
||||||
return optional<unsigned>(*r);
|
if (g_ext->m_init_decls->m_decls.contains(idx))
|
||||||
|
return optional<unsigned>(idx);
|
||||||
else
|
else
|
||||||
return optional<unsigned>();
|
return optional<unsigned>();
|
||||||
}
|
}
|
||||||
|
|
@ -1094,7 +1066,7 @@ static void code_reader(deserializer & d, environment & env) {
|
||||||
vm_decls ext = get_extension(env);
|
vm_decls ext = get_extension(env);
|
||||||
buffer<vm_instr> code;
|
buffer<vm_instr> code;
|
||||||
for (unsigned i = 0; i < code_sz; i++) {
|
for (unsigned i = 0; i < code_sz; i++) {
|
||||||
code.push_back(read_vm_instr(d, ext.m_name2idx));
|
code.push_back(read_vm_instr(d));
|
||||||
}
|
}
|
||||||
ext.update(fn, code_sz, code.data(), args_info, pos, d.get_fname());
|
ext.update(fn, code_sz, code.data(), args_info, pos, d.get_fname());
|
||||||
env = update(env, ext);
|
env = update(env, ext);
|
||||||
|
|
@ -1105,7 +1077,7 @@ environment update_vm_code(environment const & env, name const & fn, unsigned co
|
||||||
vm_decls ext = get_extension(env);
|
vm_decls ext = get_extension(env);
|
||||||
ext.update(fn, code_sz, code, args_info, pos);
|
ext.update(fn, code_sz, code, args_info, pos);
|
||||||
environment new_env = update(env, ext);
|
environment new_env = update(env, ext);
|
||||||
unsigned fidx = *ext.m_name2idx.find(fn);
|
unsigned fidx = get_vm_index(fn);
|
||||||
return module::add(new_env, *g_vm_code_key, [=](environment const & env, serializer & s) {
|
return module::add(new_env, *g_vm_code_key, [=](environment const & env, serializer & s) {
|
||||||
serialize_code(s, fidx, get_extension(env).m_decls);
|
serialize_code(s, fidx, get_extension(env).m_decls);
|
||||||
});
|
});
|
||||||
|
|
@ -1119,16 +1091,17 @@ environment add_vm_code(environment const & env, name const & fn, expr const & e
|
||||||
|
|
||||||
optional<vm_decl> get_vm_decl(environment const & env, name const & n) {
|
optional<vm_decl> get_vm_decl(environment const & env, name const & n) {
|
||||||
vm_decls const & ext = get_extension(env);
|
vm_decls const & ext = get_extension(env);
|
||||||
if (auto idx = ext.m_name2idx.find(n))
|
if (auto decl = ext.m_decls.find(get_vm_index(n)))
|
||||||
return optional<vm_decl>(*ext.m_decls.find(*idx));
|
return optional<vm_decl>(*decl);
|
||||||
else
|
else
|
||||||
return optional<vm_decl>();
|
return optional<vm_decl>();
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<unsigned> get_vm_builtin_cases_idx(environment const & env, name const & n) {
|
optional<unsigned> get_vm_builtin_cases_idx(environment const & env, name const & n) {
|
||||||
vm_decls const & ext = get_extension(env);
|
vm_decls const & ext = get_extension(env);
|
||||||
if (auto idx = ext.m_cases2idx.find(n))
|
auto idx = get_vm_index(n);
|
||||||
return optional<unsigned>(*idx);
|
if (ext.m_cases.contains(idx))
|
||||||
|
return optional<unsigned>(idx);
|
||||||
else
|
else
|
||||||
return optional<unsigned>();
|
return optional<unsigned>();
|
||||||
}
|
}
|
||||||
|
|
@ -1149,11 +1122,9 @@ vm_state::vm_state(environment const & env, options const & opts):
|
||||||
m_env(env),
|
m_env(env),
|
||||||
m_options(opts),
|
m_options(opts),
|
||||||
m_decl_map(get_extension(m_env).m_decls),
|
m_decl_map(get_extension(m_env).m_decls),
|
||||||
m_decl_vector(get_extension(m_env).m_next_decl_idx),
|
m_decl_vector(get_vm_index_bound()),
|
||||||
m_builtin_cases_map(get_extension(m_env).m_cases),
|
m_builtin_cases_map(get_extension(m_env).m_cases),
|
||||||
m_builtin_cases_vector(get_extension(m_env).m_next_cases_idx),
|
m_builtin_cases_vector(get_vm_index_bound()),
|
||||||
m_builtin_cases_names(get_extension(m_env).m_cases_names),
|
|
||||||
m_fn_name2idx(get_extension(m_env).m_name2idx),
|
|
||||||
m_code(nullptr),
|
m_code(nullptr),
|
||||||
m_fn_idx(g_null_fn_idx),
|
m_fn_idx(g_null_fn_idx),
|
||||||
m_bp(0) {
|
m_bp(0) {
|
||||||
|
|
@ -1220,9 +1191,7 @@ void vm_state::update_env(environment const & env) {
|
||||||
m_env = env;
|
m_env = env;
|
||||||
auto ext = get_extension(env);
|
auto ext = get_extension(env);
|
||||||
m_decl_map = ext.m_decls;
|
m_decl_map = ext.m_decls;
|
||||||
lean_assert(ext.m_next_decl_idx >= m_decl_vector.size());
|
m_decl_vector.resize(get_vm_index_bound());
|
||||||
m_decl_vector.resize(ext.m_next_decl_idx);
|
|
||||||
m_fn_name2idx = ext.m_name2idx;
|
|
||||||
lean_assert(is_eqp(m_builtin_cases_map, ext.m_cases));
|
lean_assert(is_eqp(m_builtin_cases_map, ext.m_cases));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1404,8 +1373,9 @@ vm_obj vm_state::invoke(unsigned fn_idx, unsigned nargs, vm_obj const * as) {
|
||||||
}
|
}
|
||||||
|
|
||||||
vm_obj vm_state::invoke(name const & fn, unsigned nargs, vm_obj const * as) {
|
vm_obj vm_state::invoke(name const & fn, unsigned nargs, vm_obj const * as) {
|
||||||
if (auto r = m_fn_name2idx.find(fn)) {
|
auto idx = get_vm_index(fn);
|
||||||
return invoke(*r, nargs, as);
|
if (m_decl_map.contains(idx)) {
|
||||||
|
return invoke(idx, nargs, as);
|
||||||
} else {
|
} else {
|
||||||
throw exception(sstream() << "VM does not have code for '" << fn << "'");
|
throw exception(sstream() << "VM does not have code for '" << fn << "'");
|
||||||
}
|
}
|
||||||
|
|
@ -2524,13 +2494,7 @@ void vm_state::run() {
|
||||||
/* We only trace VM in debug mode */
|
/* We only trace VM in debug mode */
|
||||||
lean_trace(name({"vm", "run"}),
|
lean_trace(name({"vm", "run"}),
|
||||||
tout() << m_pc << ": ";
|
tout() << m_pc << ": ";
|
||||||
instr.display(tout().get_stream(),
|
instr.display(tout().get_stream());
|
||||||
[&](unsigned idx) {
|
|
||||||
return optional<name>(get_decl(idx).get_name());
|
|
||||||
},
|
|
||||||
[&](unsigned idx) {
|
|
||||||
return optional<name>(*m_builtin_cases_names.find(idx));
|
|
||||||
});
|
|
||||||
tout() << "\n";
|
tout() << "\n";
|
||||||
display_stack(tout().get_stream());
|
display_stack(tout().get_stream());
|
||||||
tout() << "\n";)
|
tout() << "\n";)
|
||||||
|
|
@ -2965,8 +2929,9 @@ void vm_state::run() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_state::invoke_fn(name const & fn) {
|
void vm_state::invoke_fn(name const & fn) {
|
||||||
if (auto r = m_fn_name2idx.find(fn)) {
|
auto idx = get_vm_index(fn);
|
||||||
invoke_fn(*r);
|
if (m_decl_map.contains(idx)) {
|
||||||
|
invoke_fn(idx);
|
||||||
} else {
|
} else {
|
||||||
throw exception(sstream() << "VM does not have code for '" << fn << "'");
|
throw exception(sstream() << "VM does not have code for '" << fn << "'");
|
||||||
}
|
}
|
||||||
|
|
@ -2982,8 +2947,9 @@ void vm_state::invoke_fn(unsigned fn_idx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
vm_obj vm_state::get_constant(name const & cname) {
|
vm_obj vm_state::get_constant(name const & cname) {
|
||||||
if (auto fn_idx = m_fn_name2idx.find(cname)) {
|
auto fn_idx = get_vm_index(cname);
|
||||||
vm_decl d = get_decl(*fn_idx);
|
if (m_decl_map.contains(fn_idx)) {
|
||||||
|
vm_decl d = get_decl(fn_idx);
|
||||||
if (d.get_arity() == 0) {
|
if (d.get_arity() == 0) {
|
||||||
DEBUG_CODE(unsigned stack_sz = m_stack.size(););
|
DEBUG_CODE(unsigned stack_sz = m_stack.size(););
|
||||||
unsigned saved_pc = m_pc;
|
unsigned saved_pc = m_pc;
|
||||||
|
|
@ -2995,7 +2961,7 @@ vm_obj vm_state::get_constant(name const & cname) {
|
||||||
lean_assert(m_stack.size() == stack_sz);
|
lean_assert(m_stack.size() == stack_sz);
|
||||||
return r;
|
return r;
|
||||||
} else {
|
} else {
|
||||||
return mk_vm_closure(*fn_idx, 0, nullptr);
|
return mk_vm_closure(fn_idx, 0, nullptr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw exception(sstream() << "VM does not have code for '" << cname << "'");
|
throw exception(sstream() << "VM does not have code for '" << cname << "'");
|
||||||
|
|
@ -3019,13 +2985,13 @@ void vm_state::apply(unsigned n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_state::display(std::ostream & out, vm_obj const & o) const {
|
void vm_state::display(std::ostream & out, vm_obj const & o) const {
|
||||||
::lean::display(out, o,
|
::lean::display(out, o);
|
||||||
[&](unsigned idx) { return optional<name>(get_decl(idx).get_name()); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<vm_decl> vm_state::get_decl(name const & n) const {
|
optional<vm_decl> vm_state::get_decl(name const & n) const {
|
||||||
if (auto idx = m_fn_name2idx.find(n))
|
auto idx = get_vm_index(n);
|
||||||
return optional<vm_decl>(get_decl(*idx));
|
if (m_decl_map.contains(idx))
|
||||||
|
return optional<vm_decl>(get_decl(idx));
|
||||||
else
|
else
|
||||||
return optional<vm_decl>();
|
return optional<vm_decl>();
|
||||||
}
|
}
|
||||||
|
|
@ -3177,25 +3143,9 @@ void vm_state::profiler::snapshots::display(std::ostream & out) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void display_vm_code(std::ostream & out, environment const & env, unsigned code_sz, vm_instr const * code) {
|
void display_vm_code(std::ostream & out, environment const & env, unsigned code_sz, vm_instr const * code) {
|
||||||
vm_decls const & ext = get_extension(env);
|
|
||||||
auto idx2name = [&](unsigned idx) {
|
|
||||||
if (idx < ext.m_decls.size()) {
|
|
||||||
return optional<name>(ext.m_decls.find(idx)->get_name());
|
|
||||||
} else {
|
|
||||||
return optional<name>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
auto cases2name = [&](unsigned idx) {
|
|
||||||
if (idx < ext.m_cases_names.size()) {
|
|
||||||
return optional<name>(*ext.m_cases_names.find(idx));
|
|
||||||
} else {
|
|
||||||
return optional<name>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < code_sz; i++) {
|
for (unsigned i = 0; i < code_sz; i++) {
|
||||||
out << i << ": ";
|
out << i << ": ";
|
||||||
code[i].display(out, idx2name, cases2name);
|
code[i].display(out);
|
||||||
out << "\n";
|
out << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3295,7 +3245,70 @@ static void vm_monitor_reader(deserializer & d, environment & env) {
|
||||||
env = update(env, ext);
|
env = update(env, ext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class vm_index_manager {
|
||||||
|
shared_mutex m_mutex;
|
||||||
|
std::unordered_map<name, unsigned, name_hash> m_name2idx;
|
||||||
|
std::vector<name> m_idx2name;
|
||||||
|
|
||||||
|
public:
|
||||||
|
unsigned get_index(name const & n) {
|
||||||
|
{
|
||||||
|
shared_lock lock(m_mutex);
|
||||||
|
auto it = m_name2idx.find(n);
|
||||||
|
if (it != m_name2idx.end())
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
exclusive_lock lock(m_mutex);
|
||||||
|
auto it = m_name2idx.find(n);
|
||||||
|
if (it != m_name2idx.end()) {
|
||||||
|
return it->second;
|
||||||
|
} else {
|
||||||
|
auto i = static_cast<unsigned>(m_idx2name.size());
|
||||||
|
m_idx2name.push_back(n);
|
||||||
|
m_name2idx[n] = i;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_index_bound() {
|
||||||
|
shared_lock _(m_mutex);
|
||||||
|
return static_cast<unsigned>(m_idx2name.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
name const & get_name(unsigned idx) {
|
||||||
|
shared_lock lock(m_mutex);
|
||||||
|
lean_assert(idx < m_idx2name.size());
|
||||||
|
return m_idx2name.at(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<name> find_name(unsigned idx) {
|
||||||
|
shared_lock lock(m_mutex);
|
||||||
|
if (idx < m_idx2name.size()) {
|
||||||
|
return optional<name>(m_idx2name.at(idx));
|
||||||
|
} else {
|
||||||
|
return optional<name>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static vm_index_manager * g_vm_index_manager = nullptr;
|
||||||
|
|
||||||
|
unsigned get_vm_index(name const & n) {
|
||||||
|
return g_vm_index_manager->get_index(n);
|
||||||
|
}
|
||||||
|
unsigned get_vm_index_bound() {
|
||||||
|
return g_vm_index_manager->get_index_bound();
|
||||||
|
}
|
||||||
|
name const & get_vm_name(unsigned idx) {
|
||||||
|
return g_vm_index_manager->get_name(idx);
|
||||||
|
}
|
||||||
|
optional<name> find_vm_name(unsigned idx) {
|
||||||
|
return g_vm_index_manager->find_name(idx);
|
||||||
|
}
|
||||||
|
|
||||||
void initialize_vm_core() {
|
void initialize_vm_core() {
|
||||||
|
g_vm_index_manager = new vm_index_manager;
|
||||||
g_vm_builtins = new name_map<std::tuple<unsigned, char const *, vm_function>>();
|
g_vm_builtins = new name_map<std::tuple<unsigned, char const *, vm_function>>();
|
||||||
g_vm_cbuiltins = new name_map<std::tuple<unsigned, char const *, vm_cfunction>>();
|
g_vm_cbuiltins = new name_map<std::tuple<unsigned, char const *, vm_cfunction>>();
|
||||||
g_vm_cases_builtins = new name_map<std::tuple<char const *, vm_cases_function>>();
|
g_vm_cases_builtins = new name_map<std::tuple<char const *, vm_cases_function>>();
|
||||||
|
|
@ -3311,6 +3324,7 @@ void finalize_vm_core() {
|
||||||
delete g_vm_builtins;
|
delete g_vm_builtins;
|
||||||
delete g_vm_cbuiltins;
|
delete g_vm_cbuiltins;
|
||||||
delete g_vm_cases_builtins;
|
delete g_vm_cases_builtins;
|
||||||
|
delete g_vm_index_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize_vm() {
|
void initialize_vm() {
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,6 @@ public:
|
||||||
#define LEAN_VM_BOX(num) (reinterpret_cast<vm_obj_cell*>((num << 1) | 1))
|
#define LEAN_VM_BOX(num) (reinterpret_cast<vm_obj_cell*>((num << 1) | 1))
|
||||||
#define LEAN_VM_UNBOX(obj) (reinterpret_cast<size_t>(obj) >> 1)
|
#define LEAN_VM_UNBOX(obj) (reinterpret_cast<size_t>(obj) >> 1)
|
||||||
|
|
||||||
void display(std::ostream & out, vm_obj const & o, std::function<optional<name>(unsigned)> const & idx2name);
|
|
||||||
void display(std::ostream & out, vm_obj const & o);
|
void display(std::ostream & out, vm_obj const & o);
|
||||||
|
|
||||||
/** \brief VM object */
|
/** \brief VM object */
|
||||||
|
|
@ -454,9 +453,6 @@ public:
|
||||||
unsigned get_pc(unsigned i) const;
|
unsigned get_pc(unsigned i) const;
|
||||||
void set_pc(unsigned i, unsigned pc);
|
void set_pc(unsigned i, unsigned pc);
|
||||||
|
|
||||||
void display(std::ostream & out,
|
|
||||||
std::function<optional<name>(unsigned)> const & idx2name,
|
|
||||||
std::function<optional<name>(unsigned)> const & cases_idx2name) const;
|
|
||||||
void display(std::ostream & out) const;
|
void display(std::ostream & out) const;
|
||||||
|
|
||||||
void serialize(serializer & s, std::function<name(unsigned)> const & idx2name) const;
|
void serialize(serializer & s, std::function<name(unsigned)> const & idx2name) const;
|
||||||
|
|
@ -573,8 +569,6 @@ class vm_state {
|
||||||
cache_vector m_cache_vector; /* for 0-ary declarations */
|
cache_vector m_cache_vector; /* for 0-ary declarations */
|
||||||
builtin_cases_map m_builtin_cases_map;
|
builtin_cases_map m_builtin_cases_map;
|
||||||
builtin_cases_vector m_builtin_cases_vector;
|
builtin_cases_vector m_builtin_cases_vector;
|
||||||
unsigned_map<name> m_builtin_cases_names;
|
|
||||||
name_map<unsigned> m_fn_name2idx;
|
|
||||||
vm_instr const * m_code; /* code of the current function being executed */
|
vm_instr const * m_code; /* code of the current function being executed */
|
||||||
unsigned m_fn_idx; /* function idx being executed */
|
unsigned m_fn_idx; /* function idx being executed */
|
||||||
unsigned m_pc; /* program counter */
|
unsigned m_pc; /* program counter */
|
||||||
|
|
@ -832,6 +826,11 @@ environment add_native(environment const & env, name const & n, vm_cfunction_7 f
|
||||||
environment add_native(environment const & env, name const & n, vm_cfunction_8 fn);
|
environment add_native(environment const & env, name const & n, vm_cfunction_8 fn);
|
||||||
environment add_native(environment const & env, name const & n, unsigned arity, vm_cfunction_N fn);
|
environment add_native(environment const & env, name const & n, unsigned arity, vm_cfunction_N fn);
|
||||||
|
|
||||||
|
unsigned get_vm_index(name const & n);
|
||||||
|
unsigned get_vm_index_bound();
|
||||||
|
name const & get_vm_name(unsigned idx);
|
||||||
|
optional<name> find_vm_name(unsigned idx);
|
||||||
|
|
||||||
/** \brief Reserve an index for the given function in the VM, the expression
|
/** \brief Reserve an index for the given function in the VM, the expression
|
||||||
\c e is the value of \c fn after preprocessing.
|
\c e is the value of \c fn after preprocessing.
|
||||||
See library/compiler/pre_proprocess_rec.cpp for details. */
|
See library/compiler/pre_proprocess_rec.cpp for details. */
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue