feat(runtime): thunk serialization
This commit is contained in:
parent
8a96fde229
commit
bcb37ef862
5 changed files with 55 additions and 7 deletions
|
|
@ -103,7 +103,7 @@ void del(object * o) {
|
|||
case object_kind::MPZ:
|
||||
dealloc_mpz(o); break;
|
||||
case object_kind::Thunk:
|
||||
dec(to_thunk(o)->m_closure, todo);
|
||||
if (object * c = to_thunk(o)->m_closure) dec(c, todo);
|
||||
if (object * v = to_thunk(o)->m_value) dec(v, todo);
|
||||
free(o);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ struct mpz_object : public object {
|
|||
struct thunk_object : public object {
|
||||
object * m_closure;
|
||||
atomic<object *> m_value;
|
||||
thunk_object(object * c);
|
||||
thunk_object(object * c, bool is_value = false);
|
||||
};
|
||||
|
||||
/* Base class for wrapping external_object data.
|
||||
|
|
@ -330,15 +330,26 @@ inline mpz const & mpz_value(object * o) { return to_mpz(o)->m_value; }
|
|||
|
||||
/* Thunks */
|
||||
|
||||
inline thunk_object::thunk_object(object * c):
|
||||
object(object_kind::Thunk), m_closure(c), m_value(nullptr) {
|
||||
/* Remark: the implementation relies on the fact that nullptr is not a valid lean object. */
|
||||
lean_assert(is_closure(c));
|
||||
inline thunk_object::thunk_object(object * c, bool is_value):
|
||||
object(object_kind::Thunk) {
|
||||
if (is_value) {
|
||||
m_closure = nullptr;
|
||||
m_value = c;
|
||||
} else {
|
||||
lean_assert(is_closure(c));
|
||||
m_closure = c;
|
||||
m_value = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remark: `c`'s RC is not modified. Result object has RC == 1. */
|
||||
inline object * mk_thunk(object * c) {
|
||||
return new (malloc(sizeof(thunk_object))) thunk_object(c); // NOLINT
|
||||
return new (malloc(sizeof(thunk_object))) thunk_object(c, false); // NOLINT
|
||||
}
|
||||
|
||||
/* Remark: `v`'s RC is not modified. Result object has RC == 1. */
|
||||
inline object * mk_thunk_from_value(object * v) {
|
||||
return new (malloc(sizeof(thunk_object))) thunk_object(v, true); // NOLINT
|
||||
}
|
||||
|
||||
object * apply_1(object * f, object * a1);
|
||||
|
|
|
|||
|
|
@ -100,6 +100,11 @@ void serializer::write_closure(object *) { // NOLINT
|
|||
throw exception("serializer for closures has not been implemented yet");
|
||||
}
|
||||
|
||||
void serializer::write_thunk(object * o) {
|
||||
object * r = thunk_get(o);
|
||||
write_object(r);
|
||||
}
|
||||
|
||||
void serializer::write_array(object * o) {
|
||||
lean_assert(is_array(o));
|
||||
size_t sz = sarray_size(o);
|
||||
|
|
@ -162,6 +167,7 @@ void serializer::write_object(object * o) {
|
|||
switch (k) {
|
||||
case object_kind::Constructor: write_constructor(o); break;
|
||||
case object_kind::Closure: write_closure(o); break;
|
||||
case object_kind::Thunk: write_thunk(o); break;
|
||||
case object_kind::Array: write_array(o); break;
|
||||
case object_kind::ScalarArray: write_scalar_array(o); break;
|
||||
case object_kind::String: write_string_object(o); break;
|
||||
|
|
@ -282,6 +288,12 @@ object * deserializer::read_closure() {
|
|||
throw exception("serializer for closures has not been implemented yet");
|
||||
}
|
||||
|
||||
object * deserializer::read_thunk() {
|
||||
object * v = read_object();
|
||||
inc(v);
|
||||
return mk_thunk_from_value(v);
|
||||
}
|
||||
|
||||
object * deserializer::read_array() {
|
||||
size_t sz = read_size_t();
|
||||
object * r = alloc_array(sz, sz);
|
||||
|
|
@ -334,6 +346,7 @@ object * deserializer::read_object() {
|
|||
switch (k) {
|
||||
case object_kind::Constructor: r = read_constructor(); break;
|
||||
case object_kind::Closure: r = read_closure(); break;
|
||||
case object_kind::Thunk: r = read_thunk(); break;
|
||||
case object_kind::Array: r = read_array(); break;
|
||||
case object_kind::ScalarArray: r = read_scalar_array(); break;
|
||||
case object_kind::String: r = read_string_object(); break;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ class serializer {
|
|||
std::unordered_map<object*, unsigned, std::hash<object*>, std::equal_to<object*>> m_obj_table;
|
||||
void write_constructor(object * o);
|
||||
void write_closure(object * o);
|
||||
void write_thunk(object * o);
|
||||
void write_array(object * o);
|
||||
void write_scalar_array(object * o);
|
||||
void write_string_object(object * o);
|
||||
|
|
@ -62,6 +63,7 @@ class deserializer {
|
|||
unsigned read_unsigned_ext();
|
||||
object * read_constructor();
|
||||
object * read_closure();
|
||||
object * read_thunk();
|
||||
object * read_array();
|
||||
object * read_scalar_array();
|
||||
object * read_string_object();
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
|
|||
Author: Leonardo de Moura
|
||||
*/
|
||||
#include <iostream>
|
||||
#include "runtime/serializer.h"
|
||||
#include "util/test.h"
|
||||
#include "util/object_ref.h"
|
||||
#include "util/init_module.h"
|
||||
|
|
@ -85,6 +86,26 @@ static void tst4() {
|
|||
lean_assert(string_eq(r4, "hello world"));
|
||||
}
|
||||
|
||||
static void tst5() {
|
||||
object_ref c(alloc_closure(r, 1, 0));
|
||||
object_ref t = mk_thunk_ref(c);
|
||||
std::ostringstream out;
|
||||
serializer s(out);
|
||||
object_ref o(mk_string("bla bla"));
|
||||
s.write_object(o.raw());
|
||||
s.write_object(t.raw());
|
||||
s.write_object(t.raw());
|
||||
std::istringstream in(out.str());
|
||||
deserializer d(in);
|
||||
d.read_object();
|
||||
object * r1 = d.read_object();
|
||||
object * r2 = d.read_object();
|
||||
lean_assert(r1 == r2);
|
||||
lean_assert(is_thunk(r1));
|
||||
object * str = thunk_get(r1);
|
||||
lean_assert(strcmp(string_data(str), "hello world") == 0);
|
||||
}
|
||||
|
||||
int main() {
|
||||
save_stack_info();
|
||||
initialize_util_module();
|
||||
|
|
@ -92,6 +113,7 @@ int main() {
|
|||
tst2();
|
||||
tst3();
|
||||
tst4();
|
||||
tst5();
|
||||
finalize_util_module();
|
||||
return has_violations() ? 1 : 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue