We use small_object_allocator to allocate vm_obj's. However small_object_allocator is not thread safe. So, we need to copy vm_obj's between threads. Moreover, in our experiments, we observed that JEMALLOC is actually faster than the small_object_allocator. Here are numbers for the reduced corelib. small_object_allocator: 15.62 secs gcc 4.9 allocator: 16.19 secs jemalloc: 13.83 secs
119 lines
4.3 KiB
C++
119 lines
4.3 KiB
C++
/*
|
|
Copyright (c) 2016 Microsoft Corporation. All rights reserved.
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
Author: Leonardo de Moura
|
|
*/
|
|
#include "library/vm/vm_name.h"
|
|
#include "library/vm/vm_nat.h"
|
|
#include "library/vm/vm_level.h"
|
|
#include "library/vm/vm_expr.h"
|
|
#include "library/vm/vm_list.h"
|
|
|
|
namespace lean {
|
|
template<typename A>
|
|
struct vm_list : public vm_external {
|
|
list<A> m_val;
|
|
vm_list(list<A> const & v):m_val(v) {}
|
|
virtual ~vm_list() {}
|
|
virtual void dealloc() override { delete this; }
|
|
virtual vm_external * ts_clone(vm_clone_fn const &) override { return new vm_list<A>(m_val); }
|
|
virtual vm_external * clone(vm_clone_fn const &) override { return new vm_list<A>(m_val); }
|
|
};
|
|
|
|
template<typename A>
|
|
vm_obj list_to_obj(list<A> const & l) {
|
|
return mk_vm_external(new vm_list<A>(l));
|
|
}
|
|
|
|
vm_obj to_obj(list<name> const & ls) { return list_to_obj(ls); }
|
|
vm_obj to_obj(list<level> const & ls) { return list_to_obj(ls); }
|
|
vm_obj to_obj(list<expr> const & ls) { return list_to_obj(ls); }
|
|
|
|
vm_obj to_obj(list<list<expr>> const & ls) { return list_to_obj(ls); }
|
|
|
|
vm_obj to_obj(buffer<name> const & ls) { return to_obj(to_list(ls)); }
|
|
vm_obj to_obj(buffer<level> const & ls) { return to_obj(to_list(ls)); }
|
|
vm_obj to_obj(buffer<expr> const & ls) { return to_obj(to_list(ls)); }
|
|
|
|
#define MK_TO_LIST(A, ToA) \
|
|
list<A> to_list_ ## A(vm_obj const & o) { \
|
|
if (is_simple(o)) { \
|
|
return list<A>(); \
|
|
} else if (is_constructor(o)) { \
|
|
return list<A>(ToA(cfield(o, 0)), to_list_ ## A(cfield(o, 1))); \
|
|
} else { \
|
|
lean_vm_check(dynamic_cast<vm_list<A>*>(to_external(o))); \
|
|
return static_cast<vm_list<A>*>(to_external(o))->m_val; \
|
|
} \
|
|
}
|
|
|
|
MK_TO_LIST(name, to_name)
|
|
MK_TO_LIST(level, to_level)
|
|
MK_TO_LIST(expr, to_expr)
|
|
|
|
#define MK_TO_BUFFER(A, ToA) \
|
|
void to_buffer_ ## A(vm_obj const & o, buffer<A> & r) { \
|
|
if (is_simple(o)) { \
|
|
return; \
|
|
} else if (is_constructor(o)) { \
|
|
r.push_back(ToA(cfield(o, 0))); \
|
|
to_buffer_ ## A(cfield(o, 1), r); \
|
|
} else { \
|
|
lean_vm_check(dynamic_cast<vm_list<A>*>(to_external(o))); \
|
|
to_buffer(static_cast<vm_list<A>*>(to_external(o))->m_val, r); \
|
|
} \
|
|
}
|
|
|
|
MK_TO_BUFFER(name, to_name)
|
|
MK_TO_BUFFER(level, to_level)
|
|
MK_TO_BUFFER(expr, to_expr)
|
|
|
|
template<typename A>
|
|
unsigned list_cases_on_core(list<A> const & l, buffer<vm_obj> & data) {
|
|
if (empty(l)) {
|
|
return 0;
|
|
} else {
|
|
data.push_back(to_obj(head(l)));
|
|
data.push_back(list_to_obj(tail(l)));
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
unsigned list_cases_on(vm_obj const & o, buffer<vm_obj> & data) {
|
|
if (is_simple(o)) {
|
|
return 0;
|
|
} else if (is_constructor(o)) {
|
|
data.append(csize(o), cfields(o));
|
|
return 1;
|
|
} else {
|
|
if (auto l = dynamic_cast<vm_list<name>*>(to_external(o))) {
|
|
return list_cases_on_core(l->m_val, data);
|
|
} else if (auto l = dynamic_cast<vm_list<expr>*>(to_external(o))) {
|
|
return list_cases_on_core(l->m_val, data);
|
|
} else if (auto l = dynamic_cast<vm_list<level>*>(to_external(o))) {
|
|
return list_cases_on_core(l->m_val, data);
|
|
} else {
|
|
lean_unreachable();
|
|
}
|
|
}
|
|
}
|
|
|
|
vm_obj to_obj(list<unsigned> const & ls) {
|
|
return to_vm_list(ls, [&](unsigned n) { return mk_vm_nat(n); });
|
|
}
|
|
|
|
vm_obj to_obj(buffer<vm_obj> const & ls) {
|
|
vm_obj obj = mk_vm_nil();
|
|
for (unsigned i = ls.size(); i > 0; i--)
|
|
obj = mk_vm_cons(ls[i - 1], obj);
|
|
return obj;
|
|
}
|
|
|
|
void initialize_vm_list() {
|
|
DECLARE_VM_CASES_BUILTIN(name({"list", "cases_on"}), list_cases_on);
|
|
}
|
|
|
|
void finalize_vm_list() {
|
|
}
|
|
}
|