Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
jll63 committed Aug 19, 2024
1 parent 934b083 commit 21048c8
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 110 deletions.
158 changes: 88 additions & 70 deletions include/yorel/yomm2/detail.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -986,7 +986,7 @@ void decode_dispatch_data(Data& init) {
// definitions are in reverse order, because of how 'chain' works. While
// building the array of array of defintions, we put them back in the order
// in which the compiler saw them.
auto packed_slots_iter = init.packed.slots;
auto packed_slots_iter = init.encoded.slots;
auto methods = (method_info**)alloca(method_count * pointer_size);
auto methods_iter = methods;
auto method_defs = (uintptr_t**)alloca(method_count * pointer_size);
Expand All @@ -996,85 +996,96 @@ void decode_dispatch_data(Data& init) {
auto multi_method_to_method =
(std::size_t*)alloca(multi_method_count * sizeof(std::size_t));
auto multi_method_to_method_iter = multi_method_to_method;
auto method_index = 0;

for (auto& method : Policy::methods) {
++trace << "method " << method.name << "\n";
indent _(trace);
{
auto method_index = 0;

*methods_iter++ = &method;
for (auto& method : Policy::methods) {
++trace << "method " << method.name << "\n";
indent _(trace);

++trace << "specializations:\n";
*methods_iter++ = &method;

for (auto& spec : method.specs) {
indent _(trace);
++trace << spec.pf << " " << type_name(spec.type) << "\n";
}
++trace << "specializations:\n";

auto slots_strides_count = 2 * method.arity() - 1;

// copy slots and strides into the method's static
++trace << "installing " << slots_strides_count
<< " slots and strides\n";
std::copy_n(
packed_slots_iter, slots_strides_count, method.slots_strides_ptr);
packed_slots_iter += slots_strides_count;

auto specs =
(uintptr_t*)alloca((method.specs.size() + 2) * pointer_size);
*method_defs_iter++ = specs;
++trace << "specs index: " << specs << "\n";
specs = std::transform(
method.specs.begin(), method.specs.end(), specs,
[](auto& spec) { return (uintptr_t)spec.pf; });
*specs++ = (uintptr_t)method.ambiguous;
*specs++ = (uintptr_t)method.not_implemented;
for (auto& spec : method.specs) {
indent _(trace);
++trace << spec.pf << " " << type_name(spec.type) << "\n";
}

if (method.arity() >= 2) {
++trace << "m-method "
<< (multi_method_to_method_iter - multi_method_to_method)
<< " is method " << method_index << "\n";
*multi_method_to_method_iter++ = method_index;
auto slots_strides_count = 2 * method.arity() - 1;

// copy slots and strides into the method's static
++trace << "installing " << slots_strides_count
<< " slots and strides\n";
std::copy_n(
packed_slots_iter, slots_strides_count,
method.slots_strides_ptr);
packed_slots_iter += slots_strides_count;

auto specs =
(uintptr_t*)alloca((method.specs.size() + 2) * pointer_size);
*method_defs_iter++ = specs;
++trace << "specs index: " << specs << "\n";
specs = std::transform(
method.specs.begin(), method.specs.end(), specs,
[](auto& spec) { return (uintptr_t)spec.pf; });
*specs++ = (uintptr_t)method.ambiguous;
*specs++ = (uintptr_t)method.not_implemented;
++method_index;
}

++method_index;
}

// Build a table of pointers to dispatch tables, for multi-methods only.

// decode the dispatch tables for multi-methods, and keep track of them in
// an array. We will use it when we fill the vtables. The packed dispatch
// tables are in compiler order.

auto packed_iter = init.packed.dispatch;
auto decode_iter = init.decode;
// Decode dispatch tables for multi-methods, in place, and keep track of
// them in an array. We will use it when we fill the vtables.

++trace << "decoding multi-method dispatch tables\n";
{
std::size_t method_index = 0;
auto dtbl_iter = init.dtbls;

for (auto& method : Policy::methods) {
// Resist the temptation to use 'continue' to skip uni-methods, as
// 'method_index' needs to be incremented.
if (method.arity() > 1) {
indent _(trace);

for (auto i = 0; i < multi_method_count; ++i) {
assert((char*)decode_iter < (char*)packed_iter);
indent _(trace);
dispatch_tables[method_index] = dtbl_iter;
++trace << "multi-method " << method_index
<< " dispatch table at " << dtbl_iter << "\n";

dispatch_tables[i] = decode_iter;
++trace << "multi-method " << i << " dispatch table at " << decode_iter
<< "\n";
indent __(trace);
++trace << "specs:";

indent __(trace);
++trace << "specs:";
auto defs = method_defs[method_index];
bool more = true;

auto defs = method_defs[multi_method_to_method[i]];
while (more) {
more = !(*dtbl_iter & stop_bit);
auto spec_index = *dtbl_iter & ~stop_bit;
trace << " " << spec_index;
*dtbl_iter = defs[spec_index];
};

do {
auto spec_index = *packed_iter & ~stop_bit;
trace << " " << spec_index;
*decode_iter++ = defs[spec_index];
} while (!(*packed_iter++ & stop_bit));
trace << "\n";
}

trace << "\n";
++method_index;
}
}

++trace << "decoding v-tables\n";
auto vtbl_iter = init.packed.vtbl;

auto encode_iter = init.encoded.vtbls;
auto decode_iter = init.vtbls;

auto emit = [&](std::uintptr_t value) {
assert((char*)(decode_iter + 1) <= (char*)encode_iter);
assert(
(char*)(decode_iter + 1) <=
(char*)(decode_iter + sizeof(init.dtbls) / sizeof(*init.dtbls)));
*decode_iter++ = value;
};

for (auto& cls : Policy::classes) {
if (*cls.static_vptr != nullptr) {
Expand All @@ -1086,42 +1097,49 @@ void decode_dispatch_data(Data& init) {

indent _2(trace);

auto first_slot = *vtbl_iter++;
auto first_slot = *encode_iter++;
++trace << "first slot: " << first_slot << "\n";

*cls.static_vptr = decode_iter - first_slot;

do {
auto entry = *vtbl_iter & ~stop_bit;
auto entry = *encode_iter & ~stop_bit;

if (entry & index_bit) {
auto index = *vtbl_iter & ~index_bit;
auto index = *encode_iter & ~index_bit;
++trace << "multi-method group " << index << "\n";
*decode_iter++ = index;
emit(index);
} else {
auto method_index = entry;
auto method = methods[method_index];
auto group_index = *++vtbl_iter & ~stop_bit; // spec or group
auto group_index = *++encode_iter & ~stop_bit; // spec or group

if (method->arity() == 1) {
++trace << "uni-method " << method_index << " spec "
<< group_index;
*decode_iter++ = method_defs[method_index][group_index];
emit(method_defs[method_index][group_index]);
} else {
++trace << "multi-method " << method_index << " group "
<< group_index;
indent _(trace);
trace << type_name(method->method_type) << "\n";
*decode_iter++ =
(std::uintptr_t)(dispatch_tables[method_index] +
group_index);
emit((std::uintptr_t)(dispatch_tables[method_index] +
group_index));
}

trace << "\n";
indent _(trace);
++trace << type_name(method->method_type) << "\n";
}
} while (!(*vtbl_iter++ & stop_bit));
} while (!(*encode_iter++ & stop_bit));
}

++trace << decode_iter << " " << encode_iter << "\n";

auto waste = sizeof(init.encoded) - sizeof(init.vtbls);

if (waste > 0) {
++trace << waste << " bytes wasted\n";
}

using namespace policy;
Expand Down
99 changes: 59 additions & 40 deletions include/yorel/yomm2/generator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,11 @@ void generator::encode_dispatch_data(
auto dispatch_tables_size = std::accumulate(
compiler.methods.begin(), compiler.methods.end(), size_t(0),
[](auto sum, auto& method) {
return sum + method.dispatch_table.size();
if (method.arity() == 1) {
return sum;
} else {
return sum + method.dispatch_table.size();
}
});

size_t encode_vtbl_size = 0, decode_vtbl_size = 0;
Expand Down Expand Up @@ -324,28 +328,43 @@ void generator::encode_dispatch_data(
// Write data structure declaration and open initializer.

char prelude_format[] = R"(
static union {
struct {
uint16_t headroom[%d];
uint16_t slots[%d];
uint16_t dispatch[%d];
uint16_t vtbl[%d];
} packed;
std::uintptr_t decode[%d];
} yomm2_dispatch_data = { { {}, {
static struct {
union {
struct {
uint16_t headroom[%d];
uint16_t slots[%d];
uint16_t vtbls[%d];
} encoded;
std::uintptr_t vtbls[%d];
};
std::uintptr_t dtbls[%d];
} yomm2_dispatch_data = { { { {}, {
)";

const auto decode_bytes = sizeof(uintptr_t);
const auto encode_bytes = sizeof(uint16_t);

const auto total_decode_size = dispatch_tables_size + decode_vtbl_size;
const auto total_encode_size =
slots_and_strides_size + dispatch_tables_size + encode_vtbl_size;

const auto headroom = total_decode_size * sizeof(uintptr_t) -
auto headroom = total_decode_size * sizeof(uintptr_t) -
total_encode_size * sizeof(uint16_t);

const auto dispatch_and_vtbl_bytes =
(dispatch_tables_size + encode_vtbl_size) * encode_bytes;
const auto total_decode_bytes = total_decode_size * decode_bytes;

if (dispatch_and_vtbl_bytes < total_decode_bytes) {
headroom +=
(total_decode_bytes - dispatch_and_vtbl_bytes) / encode_bytes;
}

char prelude[sizeof(prelude_format) + 5 * 6];
std::snprintf(
prelude, sizeof(prelude), prelude_format, headroom / sizeof(uint16_t),
slots_and_strides_size, dispatch_tables_size, encode_vtbl_size,
total_decode_size);
slots_and_strides_size, encode_vtbl_size, decode_vtbl_size,
dispatch_tables_size);
os << prelude;

std::vector<const generic_compiler::method*> methods;
Expand Down Expand Up @@ -378,37 +397,12 @@ void generator::encode_dispatch_data(

os << " }, {\n";

// -------------------------------------------------------------------------
// Write multi-methods dispatch tables.

os << indent << "// multi-methods dispatch tables\n";

for (auto& method :
range(compiler.methods.begin(), compiler.methods.end())) {
if (method.arity() < 2) {
continue;
}

os << indent << "// " << boost::core::demangle(method.info->name.data())
<< "\n";
os << indent;
auto dt_iter = std::transform(
method.dispatch_table.begin(), method.dispatch_table.end() - 1,
std::ostream_iterator<uint16_t>(os, ", "),
[&method](auto entry) { return uint16_t(entry->spec_index); });
auto& last = method.dispatch_table.back();
*dt_iter = (uint16_t)last->spec_index | stop_bit;
os << "\n";
}

os << " }, {\n";

// -------------------------------------------------------------------------
// Write v-tables.

os << indent << "// v-tables\n";

for (auto& cls : range(compiler.classes.begin(), compiler.classes.end())) {
for (auto& cls : compiler.classes) {
os << indent << "// "
<< boost::core::demangle(
reinterpret_cast<const std::type_info*>(cls.type_ids[0])
Expand Down Expand Up @@ -449,10 +443,35 @@ void generator::encode_dispatch_data(
}
}

os << " } } }, {\n";

// -------------------------------------------------------------------------
// Write multi-methods dispatch tables.

os << indent << "// multi-methods dispatch tables\n";

for (auto& method :
range(compiler.methods.begin(), compiler.methods.end())) {
if (method.arity() < 2) {
continue;
}

os << indent << "// " << boost::core::demangle(method.info->name.data())
<< "\n";
os << indent;
auto dt_iter = std::transform(
method.dispatch_table.begin(), method.dispatch_table.end() - 1,
std::ostream_iterator<uint16_t>(os, ", "),
[&method](auto entry) { return uint16_t(entry->spec_index); });
auto& last = method.dispatch_table.back();
*dt_iter = (uint16_t)last->spec_index | stop_bit;
os << "\n";
}

// -------------------------------------------------------------------------
// Close braces.

os << " } } };\n\n";
os << " } };\n\n";

// -------------------------------------------------------------------------
// Write call to decoder.
Expand Down

0 comments on commit 21048c8

Please sign in to comment.