[gjs/ewlsh/allocate-nullptrs] Allocate nullptrs directly
- From: Evan Welsh <ewlsh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/ewlsh/allocate-nullptrs] Allocate nullptrs directly
- Date: Sat, 4 Sep 2021 04:40:38 +0000 (UTC)
commit 8f1369f829c3e0e4519943722ff88c391fe26d70
Author: Evan Welsh <contact evanwelsh com>
Date: Fri Sep 3 21:40:13 2021 -0700
Allocate nullptrs directly
gi/arg.cpp | 10 ++++++----
gi/boxed.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++----------
gi/boxed.h | 18 ++++++++++++++++--
3 files changed, 74 insertions(+), 16 deletions(-)
---
diff --git a/gi/arg.cpp b/gi/arg.cpp
index cff40e10..d7decad0 100644
--- a/gi/arg.cpp
+++ b/gi/arg.cpp
@@ -2749,10 +2749,12 @@ gjs_value_from_g_argument (JSContext *context,
return gjs_array_from_zero_terminated_c_array(
context, value_p, param_info, gjs_arg_get<void*>(arg));
} else {
- /* arrays with length are handled outside of this function */
- g_assert(((void) "Use gjs_value_from_explicit_array() for "
- "arrays with length param",
- g_type_info_get_array_length(type_info) == -1));
+ if (g_type_info_get_array_length(type_info) != -1) {
+ gjs_throw(context,
+ "Arrays with unknown length cannot be returned.");
+ return false;
+ }
+
return gjs_array_from_fixed_size_array(
context, value_p, type_info, gjs_arg_get<void*>(arg));
}
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index 7327c317..b038591a 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -25,6 +25,7 @@
#include <jsapi.h> // for IdVector, JS_AtomizeAndPinJSString
#include <mozilla/HashTable.h>
+#include "gi/arg-cache.h"
#include "gi/arg-inl.h"
#include "gi/arg.h"
#include "gi/boxed.h"
@@ -45,7 +46,8 @@ BoxedInstance::BoxedInstance(JSContext* cx, JS::HandleObject obj)
GJS_INC_COUNTER(boxed_instance);
}
-[[nodiscard]] static bool struct_is_simple(GIStructInfo* info);
+[[nodiscard]] static bool struct_is_simple(
+ GIStructInfo* info, Gjs::DirectAllocationPolicy allocation_policy);
// See GIWrapperBase::resolve().
bool BoxedPrototype::resolve_impl(JSContext* cx, JS::HandleObject obj,
@@ -366,7 +368,8 @@ bool BoxedInstance::constructor_impl(JSContext* context, JS::HandleObject obj,
debug_lifecycle("Boxed pointer created from zero-args constructor");
- } else if (proto->can_allocate_directly()) {
+ } else if (proto->can_allocate_directly(
+ Gjs::DirectAllocationPolicy::NO_POINTERS)) {
allocate_directly();
} else if (proto->has_default_constructor()) {
/* for simplicity, we simply delegate all the work to the actual JS
@@ -391,6 +394,8 @@ bool BoxedInstance::constructor_impl(JSContext* context, JS::HandleObject obj,
"boxed object discarded");
return true;
+ } else if (get_prototype()->can_allocate_directly()) {
+ allocate_directly();
} else {
gjs_throw(context,
"Unable to construct struct type %s since it has no default "
@@ -476,7 +481,8 @@ bool BoxedInstance::get_nested_interface_object(
GIBaseInfo* interface_info, JS::MutableHandleValue value) const {
int offset;
- if (!struct_is_simple ((GIStructInfo *)interface_info)) {
+ if (!struct_is_simple((GIStructInfo*)interface_info,
+ Gjs::DirectAllocationPolicy::ALLOCATE_POINTERS)) {
gjs_throw(context, "Reading field %s.%s is not supported", name(),
g_base_info_get_name(field_info));
@@ -552,6 +558,30 @@ bool BoxedInstance::field_getter_impl(JSContext* cx, JSObject* obj,
return false;
}
+ if (g_type_info_get_tag(type_info) == GI_TYPE_TAG_ARRAY &&
+ g_type_info_get_array_length(type_info) != -1) {
+ auto length_field_ix = g_type_info_get_array_length(type_info);
+ GjsAutoFieldInfo length_field_info =
+ this->get_field_info(cx, length_field_ix);
+ GjsAutoTypeInfo length_type_info =
+ g_field_info_get_type(length_field_info);
+ if (!length_field_info) {
+ gjs_throw(cx, "Reading field %s.%s is not supported", name(),
+ g_base_info_get_name(length_field_info));
+ return false;
+ }
+
+ GIArgument length_arg;
+ if (!g_field_info_get_field(length_field_info, m_ptr, &length_arg)) {
+ gjs_throw(cx, "Reading field %s.%s is not supported", name(),
+ g_base_info_get_name(length_field_info));
+ return false;
+ }
+ size_t length = gjs_g_argument_get_array_length(
+ g_type_info_get_tag(length_type_info), &length_arg);
+ return gjs_value_from_explicit_array(cx, rval, type_info, &arg, length);
+ }
+
return gjs_value_from_g_argument(cx, rval, type_info, &arg, true);
}
@@ -573,7 +603,8 @@ bool BoxedInstance::set_nested_interface_object(JSContext* context,
JS::HandleValue value) {
int offset;
- if (!struct_is_simple ((GIStructInfo *)interface_info)) {
+ if (!struct_is_simple((GIStructInfo*)interface_info,
+ Gjs::DirectAllocationPolicy::ALLOCATE_POINTERS)) {
gjs_throw(context, "Writing field %s.%s is not supported", name(),
g_base_info_get_name(field_info));
@@ -749,7 +780,7 @@ const struct JSClass BoxedBase::klass = {
// clang-format on
[[nodiscard]] static bool type_can_be_allocated_directly(
- GITypeInfo* type_info) {
+ GITypeInfo* type_info, Gjs::DirectAllocationPolicy allocation_policy) {
bool is_simple = true;
if (g_type_info_is_pointer(type_info)) {
@@ -757,9 +788,13 @@ 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);
+ 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;
}
@@ -771,7 +806,9 @@ 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((GIStructInfo *)interface))
+ if (!struct_is_simple(
+ (GIStructInfo*)interface,
+ Gjs::DirectAllocationPolicy::ALLOCATE_POINTERS))
is_simple = false;
break;
case GI_INFO_TYPE_UNION:
@@ -836,7 +873,8 @@ const struct JSClass BoxedBase::klass = {
* 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) {
+[[nodiscard]] static bool struct_is_simple(
+ GIStructInfo* info, Gjs::DirectAllocationPolicy allocation_policy) {
int n_fields = g_struct_info_get_n_fields(info);
bool is_simple = true;
int i;
@@ -849,7 +887,8 @@ 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);
+ is_simple =
+ type_can_be_allocated_directly(type_info, allocation_policy);
}
return is_simple;
@@ -860,7 +899,10 @@ BoxedPrototype::BoxedPrototype(GIStructInfo* info, GType gtype)
m_zero_args_constructor(-1),
m_default_constructor(-1),
m_default_constructor_name(JSID_VOID),
- m_can_allocate_directly(struct_is_simple(info)) {
+ 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)) {
GJS_INC_COUNTER(boxed_prototype);
}
diff --git a/gi/boxed.h b/gi/boxed.h
index 7c1cd49c..6287aea9 100644
--- a/gi/boxed.h
+++ b/gi/boxed.h
@@ -37,6 +37,13 @@ namespace js {
class SystemAllocPolicy;
}
+namespace Gjs {
+enum class DirectAllocationPolicy {
+ NO_POINTERS,
+ ALLOCATE_POINTERS,
+};
+};
+
/* To conserve memory, we have two different kinds of private data for GBoxed
* JS wrappers: BoxedInstance, and BoxedPrototype. Both inherit from BoxedBase
* for their common functionality. For more information, see the notes in
@@ -90,6 +97,7 @@ class BoxedPrototype : public GIWrapperPrototype<BoxedBase, BoxedPrototype,
JS::Heap<jsid> m_default_constructor_name;
std::unique_ptr<FieldMap> m_field_map;
bool m_can_allocate_directly : 1;
+ bool m_can_allocate_directly_with_pointers : 1;
explicit BoxedPrototype(GIStructInfo* info, GType gtype);
~BoxedPrototype(void);
@@ -101,8 +109,14 @@ class BoxedPrototype : public GIWrapperPrototype<BoxedBase, BoxedPrototype,
// Accessors
public:
- [[nodiscard]] bool can_allocate_directly() const {
- return m_can_allocate_directly;
+ [[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 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]