[gjs/ewlsh/allocate-nullptrs] Proposal; squash if acceptable
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/ewlsh/allocate-nullptrs] Proposal; squash if acceptable
- Date: Sun, 19 Sep 2021 22:17:47 +0000 (UTC)
commit aa4ec1ba3646921fc72194caea336a768651cf8b
Author: Philip Chimento <philip chimento gmail com>
Date: Sun Sep 19 14:31:33 2021 -0700
Proposal; squash if acceptable
gi/boxed.cpp | 90 +++++++++++++++++++++++++++++++++++++++---------------------
gi/boxed.h | 15 ++++------
2 files changed, 65 insertions(+), 40 deletions(-)
---
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index 6d1fb400..8f150145 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -46,8 +46,7 @@ BoxedInstance::BoxedInstance(JSContext* cx, JS::HandleObject obj)
GJS_INC_COUNTER(boxed_instance);
}
-[[nodiscard]] static bool struct_is_simple(
- GIStructInfo* info, Gjs::DirectAllocationPolicy allocation_policy);
+[[nodiscard]] static bool struct_is_simple(GIStructInfo* info);
// See GIWrapperBase::resolve().
bool BoxedPrototype::resolve_impl(JSContext* cx, JS::HandleObject obj,
@@ -368,8 +367,7 @@ bool BoxedInstance::constructor_impl(JSContext* context, JS::HandleObject obj,
debug_lifecycle("Boxed pointer created from zero-args constructor");
- } else if (proto->can_allocate_directly(
- Gjs::DirectAllocationPolicy::NO_POINTERS)) {
+ } else if (proto->can_allocate_directly_without_pointers()) {
allocate_directly();
} else if (proto->has_default_constructor()) {
/* for simplicity, we simply delegate all the work to the actual JS
@@ -481,8 +479,7 @@ bool BoxedInstance::get_nested_interface_object(
GIBaseInfo* interface_info, JS::MutableHandleValue value) const {
int offset;
- if (!struct_is_simple(reinterpret_cast<GIStructInfo*>(interface_info),
- Gjs::DirectAllocationPolicy::ALLOCATE_POINTERS)) {
+ if (!struct_is_simple ((GIStructInfo *)interface_info)) {
gjs_throw(context, "Reading field %s.%s is not supported", name(),
g_base_info_get_name(field_info));
@@ -604,8 +601,7 @@ bool BoxedInstance::set_nested_interface_object(JSContext* context,
JS::HandleValue value) {
int offset;
- if (!struct_is_simple(reinterpret_cast<GIStructInfo*>(interface_info),
- Gjs::DirectAllocationPolicy::ALLOCATE_POINTERS)) {
+ if (!struct_is_simple ((GIStructInfo *)interface_info)) {
gjs_throw(context, "Writing field %s.%s is not supported", name(),
g_base_info_get_name(field_info));
@@ -781,7 +777,7 @@ const struct JSClass BoxedBase::klass = {
// clang-format on
[[nodiscard]] static bool type_can_be_allocated_directly(
- GITypeInfo* type_info, Gjs::DirectAllocationPolicy allocation_policy) {
+ GITypeInfo* type_info) {
bool is_simple = true;
if (g_type_info_is_pointer(type_info)) {
@@ -789,16 +785,9 @@ const struct JSClass BoxedBase::klass = {
g_type_info_get_array_type(type_info) == GI_ARRAY_TYPE_C) {
GjsAutoBaseInfo param_info =
g_type_info_get_param_type(type_info, 0);
- is_simple =
- type_can_be_allocated_directly(param_info, allocation_policy);
- } else if (g_type_info_get_tag(type_info) == GI_TYPE_TAG_VOID) {
- return true;
- } else if (allocation_policy ==
- Gjs::DirectAllocationPolicy::ALLOCATE_POINTERS) {
- return true;
- } else {
- is_simple = false;
+ return type_can_be_allocated_directly(param_info);
}
+ return true;
} else {
switch (g_type_info_get_tag(type_info)) {
case GI_TYPE_TAG_INTERFACE:
@@ -807,11 +796,7 @@ const struct JSClass BoxedBase::klass = {
switch (g_base_info_get_type(interface)) {
case GI_INFO_TYPE_BOXED:
case GI_INFO_TYPE_STRUCT:
- if (!struct_is_simple(
- interface.as<GIStructInfo>(),
- Gjs::DirectAllocationPolicy::ALLOCATE_POINTERS))
- is_simple = false;
- break;
+ return struct_is_simple(interface.as<GIStructInfo>());
case GI_INFO_TYPE_UNION:
/* FIXME: Need to implement */
is_simple = false;
@@ -870,12 +855,37 @@ const struct JSClass BoxedBase::klass = {
return is_simple;
}
+[[nodiscard]] static bool simple_struct_has_pointers(GIStructInfo*);
+
+[[nodiscard]] static bool direct_allocation_has_pointers(
+ GITypeInfo* type_info) {
+ if (g_type_info_is_pointer(type_info)) {
+ if (g_type_info_get_tag(type_info) == GI_TYPE_TAG_ARRAY &&
+ g_type_info_get_array_type(type_info) == GI_ARRAY_TYPE_C) {
+ GjsAutoBaseInfo param_info =
+ g_type_info_get_param_type(type_info, 0);
+ return direct_allocation_has_pointers(param_info);
+ }
+
+ return g_type_info_get_tag(type_info) != GI_TYPE_TAG_VOID;
+ }
+
+ if (g_type_info_get_tag(type_info) != GI_TYPE_TAG_INTERFACE)
+ return false;
+
+ GjsAutoBaseInfo interface = g_type_info_get_interface(type_info);
+ if (interface.type() == GI_INFO_TYPE_BOXED ||
+ interface.type() == GI_INFO_TYPE_STRUCT)
+ return simple_struct_has_pointers(interface.as<GIStructInfo>());
+
+ return false;
+}
+
/* Check if the type of the boxed is "simple" - every field is a non-pointer
* type that we know how to assign to. If so, then we can allocate and free
* instances without needing a constructor.
*/
-[[nodiscard]] static bool struct_is_simple(
- GIStructInfo* info, Gjs::DirectAllocationPolicy allocation_policy) {
+[[nodiscard]] static bool struct_is_simple(GIStructInfo* info) {
int n_fields = g_struct_info_get_n_fields(info);
bool is_simple = true;
int i;
@@ -888,22 +898,40 @@ const struct JSClass BoxedBase::klass = {
GjsAutoBaseInfo field_info = g_struct_info_get_field(info, i);
GjsAutoBaseInfo type_info = g_field_info_get_type(field_info);
- is_simple =
- type_can_be_allocated_directly(type_info, allocation_policy);
+ is_simple = type_can_be_allocated_directly(type_info);
}
return is_simple;
}
+[[nodiscard]] static bool simple_struct_has_pointers(GIStructInfo* info) {
+ g_assert(struct_is_simple(info) &&
+ "Don't call simple_struct_has_pointers() on a non-simple struct");
+
+ int n_fields = g_struct_info_get_n_fields(info);
+ g_assert(n_fields > 0);
+
+ for (int i = 0; i < n_fields; i++) {
+ GjsAutoBaseInfo field_info = g_struct_info_get_field(info, i);
+ GjsAutoBaseInfo type_info = g_field_info_get_type(field_info);
+ if (direct_allocation_has_pointers(type_info))
+ return true;
+ }
+ return false;
+}
+
BoxedPrototype::BoxedPrototype(GIStructInfo* info, GType gtype)
: GIWrapperPrototype(info, gtype),
m_zero_args_constructor(-1),
m_default_constructor(-1),
m_default_constructor_name(JSID_VOID),
- m_can_allocate_directly(
- struct_is_simple(info, Gjs::DirectAllocationPolicy::NO_POINTERS)),
- m_can_allocate_directly_with_pointers(struct_is_simple(
- info, Gjs::DirectAllocationPolicy::ALLOCATE_POINTERS)) {
+ m_can_allocate_directly(struct_is_simple(info)) {
+ if (!m_can_allocate_directly) {
+ m_can_allocate_directly_without_pointers = false;
+ } else {
+ m_can_allocate_directly_without_pointers =
+ !simple_struct_has_pointers(info);
+ }
GJS_INC_COUNTER(boxed_prototype);
}
diff --git a/gi/boxed.h b/gi/boxed.h
index 6287aea9..faaec5e9 100644
--- a/gi/boxed.h
+++ b/gi/boxed.h
@@ -96,8 +96,8 @@ class BoxedPrototype : public GIWrapperPrototype<BoxedBase, BoxedPrototype,
int m_default_constructor; // -1 if none
JS::Heap<jsid> m_default_constructor_name;
std::unique_ptr<FieldMap> m_field_map;
+ bool m_can_allocate_directly_without_pointers : 1;
bool m_can_allocate_directly : 1;
- bool m_can_allocate_directly_with_pointers : 1;
explicit BoxedPrototype(GIStructInfo* info, GType gtype);
~BoxedPrototype(void);
@@ -109,14 +109,11 @@ class BoxedPrototype : public GIWrapperPrototype<BoxedBase, BoxedPrototype,
// Accessors
public:
- [[nodiscard]] bool can_allocate_directly(
- Gjs::DirectAllocationPolicy allocation_policy =
- Gjs::DirectAllocationPolicy::ALLOCATE_POINTERS) const {
- if (allocation_policy == Gjs::DirectAllocationPolicy::NO_POINTERS) {
- return m_can_allocate_directly;
- }
-
- return m_can_allocate_directly_with_pointers;
+ [[nodiscard]] bool can_allocate_directly_without_pointers() const {
+ return m_can_allocate_directly_without_pointers;
+ }
+ [[nodiscard]] bool can_allocate_directly() const {
+ return m_can_allocate_directly;
}
[[nodiscard]] bool has_zero_args_constructor() const {
return m_zero_args_constructor >= 0;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]