Skip to content

Commit

Permalink
hash_factors_in_method
Browse files Browse the repository at this point in the history
  • Loading branch information
jll63 committed Jul 12, 2023
1 parent 39d7fcb commit 15ca786
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 148 deletions.
3 changes: 1 addition & 2 deletions dev/bmutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
axes = dict(
dispatch=(
"virtual_function",
"hash_factors_in_globals",
"hash_factors_in_method",
"basic_policy",
"direct_intrusive",
"indirect_intrusive",
"direct_virtual_ptr",
Expand Down
173 changes: 99 additions & 74 deletions include/yorel/yomm2/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,39 +31,6 @@
namespace yorel {
namespace yomm2 {

namespace detail {

union word {
void* pf;
const word* pw;
size_t i;
const void* ti;
};

using ti_ptr = const std::type_info*;

struct hash_function {
std::uintptr_t mult;
std::size_t shift;

std::size_t operator()(const void* p) const {
return static_cast<std::size_t>(
(mult * reinterpret_cast<std::uintptr_t>(const_cast<void*>(p))) >>
shift);
}
};

template<class Class, class Policy>
struct virtual_ptr_traits;

} // namespace detail

template<typename T>
struct virtual_;

template<typename... Types>
struct types;

struct resolution_error {
enum status_type { no_definition = 1, ambiguous } status;
const std::type_info* method;
Expand Down Expand Up @@ -94,24 +61,79 @@ using error_handler_type = void (*)(const error_type& error);

yOMM2_API error_handler_type set_error_handler(error_handler_type handler);

namespace detail {

#ifdef NDEBUG
constexpr bool debug = false;
#else
constexpr bool debug = true;
#endif

union word {
void* pf;
const word* pw;
size_t i;
const void* ti;
};

using ti_ptr = const std::type_info*;

extern yOMM2_API error_handler_type error_handler;

struct hash_function {
std::uintptr_t mult;
std::size_t shift;
std::vector<detail::ti_ptr> control;

auto unchecked_hash(ti_ptr tip) const {
return static_cast<std::size_t>(
(mult * reinterpret_cast<std::uintptr_t>(tip)) >> shift);
}

auto operator()(ti_ptr tip) const {
auto index = unchecked_hash(tip);

if constexpr (debug) {
auto control_tip = control[index];

if (control_tip != tip) {
error_handler(
unknown_class_error{unknown_class_error::call, tip});
}
}

return index;
}
};

template<class Class, class Policy>
struct virtual_ptr_traits;

} // namespace detail

template<typename T>
struct virtual_;

template<typename... Types>
struct types;

struct catalog;

struct context {
std::vector<detail::word> gv;
std::vector<detail::word*> mptrs;
std::vector<detail::ti_ptr> control;
std::vector<detail::word**> indirect_mptrs;
detail::hash_function hash;
};

namespace policy {

struct abstract_policy;
struct hash_factors_in_globals;
struct basic_policy;

} // namespace policy

using default_policy = policy::hash_factors_in_globals;
using default_policy = policy::basic_policy;

template<typename Class, typename... Rest>
struct class_declaration;
Expand Down Expand Up @@ -201,25 +223,8 @@ static detail::mptr_type method_table;
template<typename>
static detail::mptr_type* indirect_method_table;

struct hash_factors_in_globals : global_catalog, global_context {
struct basic_policy : global_catalog, global_context {
using method_info_type = detail::method_info;

template<typename>
static auto hash() {
return context.hash;
}
};

struct hash_factors_in_method : global_catalog, global_context {
struct yOMM2_API method_info_type : detail::method_info {
detail::hash_function hash;
void install_hash_factors(detail::runtime& rt) override;
};

template<typename Method>
static auto hash() {
return Method::fn.hash;
}
};

} // namespace policy
Expand Down Expand Up @@ -595,49 +600,61 @@ class virtual_ptr_aux {
virtual_ptr_aux(Class& obj, mptr_type mptr) : obj(obj), mptr(mptr) {
}

static auto final(Class& obj) {
template<class OtherClass>
static auto final(OtherClass& obj) {
using namespace detail;

mptr_type mptr;

if constexpr (Policy::use_indirect_method_pointers) {
mptr = detail::indirect_method_table<
typename detail::virtual_traits<Class&>::polymorphic_type,
Policy>;
} else {
mptr = detail::method_table<
typename detail::virtual_traits<Class&>::polymorphic_type,
Policy>;
}

if constexpr (debug) {
auto key = virtual_traits<Class&>::key(obj);
// check that dynamic type == static type
auto key = virtual_traits<OtherClass&>::key(obj);
auto final_key =
&typeid(typename virtual_traits<Class&>::polymorphic_type);
&typeid(typename virtual_traits<OtherClass&>::polymorphic_type);

if (key != final_key) {
error_handler(method_table_error{key});
}
}

if constexpr (Policy::use_indirect_method_pointers) {
return virtual_ptr<Class, Policy>(
obj,
detail::indirect_method_table<
typename detail::virtual_traits<Class&>::polymorphic_type,
Policy>);
} else {
return virtual_ptr<Class, Policy>(
obj,
detail::method_table<
typename detail::virtual_traits<Class&>::polymorphic_type,
Policy>);
// check that OtherClass is registered
if constexpr (Policy::use_indirect_method_pointers) {
check_method_pointer<Policy>(*mptr, key);
} else {
check_method_pointer<Policy>(mptr, key);
}
}

return virtual_ptr<Class, Policy>(obj, mptr);
}

template<class OtherClass>
static auto dynamic_method_table(OtherClass& obj) {
using namespace detail;

mptr_type mptr;

auto key = virtual_traits<OtherClass&>::key(obj);
auto final_key =
&typeid(typename virtual_traits<OtherClass&>::polymorphic_type);

if (key == final_key) {
if constexpr (Policy::use_indirect_method_pointers) {
return detail::indirect_method_table<
mptr = detail::indirect_method_table<
typename detail::virtual_traits<
OtherClass&>::polymorphic_type,
Policy>;
} else {
return detail::method_table<
mptr = detail::method_table<
typename detail::virtual_traits<
OtherClass&>::polymorphic_type,
Policy>;
Expand All @@ -646,11 +663,19 @@ class virtual_ptr_aux {
auto index = Policy::context.hash(key);

if constexpr (Policy::use_indirect_method_pointers) {
return Policy::context.indirect_mptrs[index];
mptr = Policy::context.indirect_mptrs[index];
} else {
return Policy::context.mptrs[index];
mptr = Policy::context.mptrs[index];
}
}

if constexpr (Policy::use_indirect_method_pointers) {
check_method_pointer<Policy>(*mptr, final_key);
} else {
check_method_pointer<Policy>(mptr, final_key);
}

return mptr;
}

auto& box() const noexcept {
Expand Down
19 changes: 7 additions & 12 deletions include/yorel/yomm2/detail.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,6 @@ yOMM2_API void update_methods(catalog& cat, context& ht);

namespace mp11 = boost::mp11;

extern yOMM2_API error_handler_type error_handler;

#ifdef NDEBUG
constexpr bool debug = false;
#else
constexpr bool debug = true;
#endif

enum { TRACE_RUNTIME = 1, TRACE_CALLS = 2 };
yOMM2_API extern std::ostream* logs;
yOMM2_API extern unsigned trace_flags;
Expand Down Expand Up @@ -200,8 +192,6 @@ struct yOMM2_API method_info : static_chain<method_info>::static_link {
const std::type_info* hash_factors_placement;
size_t* slots_strides_p;

virtual void install_hash_factors(runtime&);

auto arity() const {
return std::distance(vp_begin, vp_end);
}
Expand Down Expand Up @@ -649,10 +639,15 @@ inline auto get_tip(const T& arg) {

template<class Policy>
inline auto check_method_pointer(const word* mptr, ti_ptr key) {
auto& ctx = Policy::context;
if constexpr (Policy::enable_runtime_checks) {
auto& ctx = Policy::context;
auto p = reinterpret_cast<const char*>(mptr);

if (p == 0 && ctx.gv.empty()) {
// no declared methods
return mptr;
}

if (p < reinterpret_cast<const char*>(ctx.gv.data()) ||
p >= reinterpret_cast<const char*>(ctx.gv.data() + ctx.gv.size())) {
error_handler(method_table_error{key});
Expand Down Expand Up @@ -687,7 +682,7 @@ inline auto get_mptr(resolver_type<ArgType> arg) {
call_trace << " key = " << key;
}

mptr = policy::context.mptrs[policy::template hash<Method>()(key)];
mptr = policy::context.mptrs[policy::context.hash(key)];
}

if constexpr (bool(trace_enabled & TRACE_CALLS)) {
Expand Down
9 changes: 0 additions & 9 deletions reference.in/virtual_ptr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,6 @@ pointer to its associated method table.

`Class` - The type of the object.

### Specializations

```
template<class Class, typename = unspecified>
class virtual_ptr<std::shared_ptr<Class>>;
```

This specialization uses a `std::shared_ptr<Class>`, instead of a `Class*`, to store the address of the object.

## Member functions

| | |
Expand Down
9 changes: 0 additions & 9 deletions reference/virtual_ptr.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,6 @@ pointer to its associated method table.
`Class` - The type of the object.
### Specializations
```
template<class Class, typename = unspecified>
class virtual_ptr<std::shared_ptr<Class>>;
```
This specialization uses a `std::shared_ptr<Class>`, instead of a `Class*`, to store the address of the object.
## Member functions
| | |
Expand Down
Loading

0 comments on commit 15ca786

Please sign in to comment.