Skip to content

Commit 3be640b

Browse files
committed
Update HPy inlined files: 5ddcbc8d
1 parent 3dab01e commit 3be640b

File tree

14 files changed

+3748
-4
lines changed

14 files changed

+3748
-4
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11

22
// automatically generated by setup.py:get_scm_config()
3-
#define HPY_VERSION "0.0.5.dev86+g7a576ef1"
4-
#define HPY_GIT_REVISION "7a576ef1"
3+
#define HPY_VERSION "0.9.0rc2"
4+
#define HPY_GIT_REVISION "5ddcbc8d"
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
// Python-level interface for the _trace module. Written in HPy itself, the
2+
// idea is that it should be reusable by other implementations
3+
4+
// NOTE: hpy.trace._trace is loaded using the UNIVERSAL ctx. To make it
5+
// clearer, we will use "uctx" and "tctx" to distinguish them.
6+
7+
#include "hpy.h"
8+
#include "trace_internal.h"
9+
10+
#ifndef _WIN32
11+
#include <limits.h>
12+
#define MAX_SEC (LLONG_MAX / FREQ_NSEC)
13+
#endif
14+
15+
HPY_MOD_EMBEDDABLE(_trace)
16+
17+
static inline int is_empty(const char *s)
18+
{
19+
return s[0] == '\0';
20+
}
21+
22+
#ifdef _WIN32
23+
static inline HPy win_time_to_ns(HPyContext *uctx, const LONGLONG to_ns, _HPyTime_t t)
24+
{
25+
return HPyLong_FromLongLong(uctx, t.QuadPart * to_ns);
26+
}
27+
28+
#else
29+
static inline HPy posix_time_to_ns(HPyContext *uctx, HPy *s_to_ns, _HPyTime_t t)
30+
{
31+
/* Fast-path: If we can fit into a signed 64-bit integer, then do the
32+
computation in C. This is the case if we can do 't.tv_sec * FREQ_SEC'
33+
(i.e. converting seconds to nanoseconds) and add 'tv.tv_nsec' without
34+
overflowing. */
35+
if (t.tv_sec < MAX_SEC) {
36+
return HPyLong_FromLongLong(uctx, (long long)t.tv_sec * FREQ_NSEC +
37+
(long long)t.tv_nsec);
38+
} else {
39+
/* Slow-path: do the computation with an (unbound) Python long */
40+
if (HPy_IsNull(*s_to_ns)) {
41+
*s_to_ns = HPyLong_FromLongLong(uctx, FREQ_NSEC);
42+
}
43+
44+
HPy h_tv_sec = HPyLong_FromLongLong(uctx, t.tv_sec);
45+
HPy h_tv_sec_as_ns = HPy_Multiply(uctx, h_tv_sec, *s_to_ns);
46+
HPy_Close(uctx, h_tv_sec);
47+
48+
HPy tv_nsec = HPyLong_FromLong(uctx, t.tv_nsec);
49+
HPy res = HPy_Add(uctx, h_tv_sec_as_ns, tv_nsec);
50+
HPy_Close(uctx, h_tv_sec_as_ns);
51+
HPy_Close(uctx, tv_nsec);
52+
53+
return res;
54+
}
55+
}
56+
#endif
57+
58+
HPyDef_METH(get_durations, "get_durations", HPyFunc_NOARGS)
59+
static HPy get_durations_impl(HPyContext *uctx, HPy self)
60+
{
61+
HPyContext *tctx = hpy_trace_get_ctx(uctx);
62+
HPyTraceInfo *info = get_info(tctx);
63+
HPyTracker ht = HPyTracker_New(uctx, hpy_trace_get_nfunc());
64+
65+
#ifdef _WIN32
66+
const LONGLONG to_ns = FREQ_NSEC / info->counter_freq.QuadPart;
67+
#else
68+
HPy s_to_ns = HPy_NULL;
69+
#endif
70+
HPy res = HPyDict_New(uctx);
71+
const char *func_name;
72+
for (int i=0; (func_name = hpy_trace_get_func_name(i)); i++)
73+
{
74+
/* skip empty names; those indices denote a context handle */
75+
if (!is_empty(func_name))
76+
{
77+
#ifdef _WIN32
78+
HPy value = win_time_to_ns(uctx, to_ns, info->durations[i]);
79+
#else
80+
HPy value = posix_time_to_ns(uctx, &s_to_ns, info->durations[i]);
81+
#endif
82+
HPyTracker_Add(uctx, ht, value);
83+
if (HPy_IsNull(value))
84+
goto fail;
85+
if (HPy_SetItem_s(uctx, res, func_name, value) < 0)
86+
goto fail;
87+
}
88+
}
89+
#ifndef _WIN32
90+
HPy_Close(uctx, s_to_ns);
91+
#endif
92+
HPyTracker_Close(uctx, ht);
93+
return res;
94+
fail:
95+
HPy_Close(uctx, res);
96+
HPyTracker_Close(uctx, ht);
97+
return HPy_NULL;
98+
}
99+
100+
HPyDef_METH(get_call_counts, "get_call_counts", HPyFunc_NOARGS)
101+
static HPy get_call_counts_impl(HPyContext *uctx, HPy self)
102+
{
103+
HPyContext *tctx = hpy_trace_get_ctx(uctx);
104+
HPyTraceInfo *info = get_info(tctx);
105+
HPyTracker ht = HPyTracker_New(uctx, hpy_trace_get_nfunc());
106+
HPy res = HPyDict_New(uctx);
107+
const char *func_name;
108+
for (int i=0; (func_name = hpy_trace_get_func_name(i)); i++)
109+
{
110+
/* skip empty names; those indices denote a context handle */
111+
if (!is_empty(func_name))
112+
{
113+
HPy value = HPyLong_FromUnsignedLongLong(uctx,
114+
(unsigned long long)info->call_counts[i]);
115+
HPyTracker_Add(uctx, ht, value);
116+
if (HPy_IsNull(value))
117+
goto fail;
118+
if (HPy_SetItem_s(uctx, res, func_name, value) < 0)
119+
goto fail;
120+
}
121+
}
122+
HPyTracker_Close(uctx, ht);
123+
return res;
124+
fail:
125+
HPy_Close(uctx, res);
126+
HPyTracker_Close(uctx, ht);
127+
return HPy_NULL;
128+
}
129+
130+
static int check_and_set_func(HPyContext *uctx, HPy arg, HPy *out)
131+
{
132+
if (HPy_IsNull(arg)) {
133+
// not provided -> do not change value
134+
return 0;
135+
} else if (HPy_Is(uctx, arg, uctx->h_None)) {
136+
// None -> clear function
137+
*out = HPy_NULL;
138+
return 0;
139+
} else if (!HPyCallable_Check(uctx, arg)) {
140+
// not null, not None, not callable -> error
141+
HPyErr_SetString(uctx, uctx->h_TypeError, "Expected a callable object or None");
142+
return -1;
143+
}
144+
// a callable -> set function
145+
*out = HPy_Dup(uctx, arg);
146+
return 0;
147+
}
148+
149+
HPyDef_METH(set_trace_functions, "set_trace_functions", HPyFunc_KEYWORDS,
150+
.doc="Set the functions to call if an HPy API is entered/exited.")
151+
static HPy set_trace_functions_impl(HPyContext *uctx, HPy self, const HPy *args,
152+
size_t nargs, HPy kwnames)
153+
{
154+
HPy h_on_enter = HPy_NULL;
155+
HPy h_on_exit = HPy_NULL;
156+
HPyContext *dctx = hpy_trace_get_ctx(uctx);
157+
HPyTraceInfo *info = get_info(dctx);
158+
HPyTracker ht;
159+
160+
static const char *kwlist[] = { "on_enter", "on_exit", NULL };
161+
if (!HPyArg_ParseKeywords(uctx, &ht, args, nargs, kwnames, "|OO", kwlist,
162+
&h_on_enter, &h_on_exit)) {
163+
return HPy_NULL;
164+
}
165+
166+
int r = check_and_set_func(uctx, h_on_enter, &info->on_enter_func) < 0 ||
167+
check_and_set_func(uctx, h_on_exit, &info->on_exit_func) < 0;
168+
HPyTracker_Close(uctx, ht);
169+
if (r) {
170+
return HPy_NULL;
171+
}
172+
return HPy_Dup(uctx, uctx->h_None);
173+
}
174+
175+
HPyDef_METH(get_frequency, "get_frequency", HPyFunc_NOARGS,
176+
.doc="Resolution of the used clock in Hertz.")
177+
static HPy get_frequency_impl(HPyContext *uctx, HPy self)
178+
{
179+
HPyContext *tctx = hpy_trace_get_ctx(uctx);
180+
HPyTraceInfo *info = get_info(tctx);
181+
#ifdef _WIN32
182+
long long f = (long long) info->counter_freq.QuadPart;
183+
#else
184+
long long f = (long long) info->counter_freq.tv_sec +
185+
(long long)info->counter_freq.tv_nsec * FREQ_NSEC;
186+
#endif
187+
return HPyLong_FromLongLong(uctx, f);
188+
}
189+
190+
191+
/* ~~~~~~ definition of the module hpy.trace._trace ~~~~~~~ */
192+
193+
static HPyDef *module_defines[] = {
194+
&get_durations,
195+
&get_call_counts,
196+
&set_trace_functions,
197+
&get_frequency,
198+
NULL
199+
};
200+
201+
static HPyModuleDef moduledef = {
202+
.doc = "HPy trace mode",
203+
.size = 0,
204+
.defines = module_defines
205+
};
206+
207+
HPy_MODINIT(_trace, moduledef)

0 commit comments

Comments
 (0)