Branch data Line data Source code
1 : : /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2 : : // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
3 : : // SPDX-FileCopyrightText: 2008 litl, LLC
4 : :
5 : : #include <config.h>
6 : :
7 : : #include <inttypes.h>
8 : :
9 : : #include <girepository/girepository.h>
10 : : #include <glib-object.h>
11 : : #include <glib.h>
12 : :
13 : : #include <mozilla/CheckedInt.h>
14 : : #include <mozilla/Maybe.h>
15 : : #include <mozilla/Result.h>
16 : : #include <mozilla/Span.h>
17 : :
18 : : #include "gi/arg-inl.h"
19 : : #include "gi/info.h"
20 : : #include "gjs/mem-private.h" // IWYU pragma: associated
21 : : #include "gjs/mem.h"
22 : : #include "util/log.h"
23 : :
24 : : namespace Gjs::Memory::Counters {
25 : : #define GJS_DEFINE_COUNTER(name, ix) Counter name(#name);
26 : :
27 : : GJS_DEFINE_COUNTER(everything, -1)
28 : : GJS_FOR_EACH_COUNTER(GJS_DEFINE_COUNTER)
29 : : } // namespace Gjs::Memory::Counters
30 : :
31 : : #define GJS_LIST_COUNTER(name, ix) &Gjs::Memory::Counters::name,
32 : :
33 : : static Gjs::Memory::Counter* counters[] = {
34 : : GJS_FOR_EACH_COUNTER(GJS_LIST_COUNTER)};
35 : :
36 : 100 : void gjs_memory_report(const char* where, bool die_if_leaks) {
37 : 100 : gjs_debug(GJS_DEBUG_MEMORY,
38 : : "Memory report: %s",
39 : : where);
40 : :
41 : 100 : size_t n_counters = G_N_ELEMENTS(counters);
42 : :
43 : 100 : int64_t total_objects = 0;
44 [ + + ]: 1700 : for (size_t i = 0; i < n_counters; ++i) {
45 : 1600 : total_objects += counters[i]->value;
46 : : }
47 : :
48 [ - + ]: 100 : if (total_objects != GJS_GET_COUNTER(everything)) {
49 : 0 : gjs_debug(GJS_DEBUG_MEMORY,
50 : : "Object counts don't add up!");
51 : : }
52 : :
53 : 100 : gjs_debug(GJS_DEBUG_MEMORY, " %" PRId64 " objects currently alive",
54 : : GJS_GET_COUNTER(everything));
55 : :
56 [ + + ]: 100 : if (GJS_GET_COUNTER(everything) != 0) {
57 [ + + ]: 850 : for (size_t i = 0; i < n_counters; ++i) {
58 : 1600 : gjs_debug(GJS_DEBUG_MEMORY, " %24s = %" PRId64,
59 : 1600 : counters[i]->name, counters[i]->value.load());
60 : : }
61 : :
62 [ - + ]: 50 : if (die_if_leaks)
63 : 0 : g_error("%s: JavaScript objects were leaked.", where);
64 : : }
65 : 100 : }
66 : :
67 : 1 : int32_t estimate_size_of_gdkpixbuf(GObject* wrapped) {
68 : 1 : GI::Repository repo;
69 : 1 : GI::AutoObjectInfo gdkpixbuf_info{
70 : 2 : repo.find_by_name<GI::InfoTag::OBJECT>("GdkPixbuf", "Pixbuf")
71 : 1 : .value()};
72 : 1 : GI::AutoFunctionInfo get_width_func{
73 : 1 : gdkpixbuf_info.method("get_width").value()};
74 : 1 : GI::AutoFunctionInfo get_height_func{
75 : 1 : gdkpixbuf_info.method("get_height").value()};
76 : 1 : GI::AutoFunctionInfo get_bits_per_sample_func{
77 : 1 : gdkpixbuf_info.method("get_bits_per_sample").value()};
78 : : GIArgument args;
79 : 1 : gjs_arg_set(&args, wrapped);
80 : : GIArgument width, height, bits_per_sample;
81 : 1 : auto result_width = get_width_func.invoke({{args}}, {}, &width);
82 : 1 : auto result_height = get_height_func.invoke({{args}}, {}, &height);
83 : 1 : auto result_bits_per_sample =
84 : 1 : get_bits_per_sample_func.invoke({{args}}, {}, &bits_per_sample);
85 [ + - + - : 2 : if (result_width.isErr() || result_height.isErr() ||
- + - + ]
86 : 1 : result_bits_per_sample.isErr()) {
87 : 0 : gjs_debug(GJS_DEBUG_MEMORY, "Failed to estimate GdkPixbuf size");
88 : 0 : return 0;
89 : : }
90 : 1 : int width_int = gjs_arg_get<int>(&width);
91 : 1 : int height_int = gjs_arg_get<int>(&height);
92 : 1 : int bits_per_sample_int = gjs_arg_get<int>(&bits_per_sample);
93 : 1 : mozilla::CheckedInt32 estimated_size =
94 : 1 : mozilla::CheckedInt32{width_int} * height_int * bits_per_sample_int;
95 [ - + ]: 1 : if (!estimated_size.isValid())
96 : 0 : return INT32_MAX;
97 : 1 : return estimated_size.value();
98 : 1 : }
|