Skip to content

Commit e19a74f

Browse files
committed
Still import all HPy runtime sources; duplicate ctx_tacker.c for JNI backend
1 parent e2eafe1 commit e19a74f

File tree

3 files changed

+202
-9
lines changed

3 files changed

+202
-9
lines changed
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
/* MIT License
2+
*
3+
* Copyright (c) 2021, Oracle and/or its affiliates.
4+
* Copyright (c) 2019 pyhandle
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
/**
26+
* A manager for HPy handles, allowing handles to be tracked
27+
* and closed as a group.
28+
*
29+
* Note::
30+
* Calling HPyTracker_New(ctx, n) will ensure that at least n handles
31+
* can be tracked without a call to HPyTracker_Add failing.
32+
*
33+
* If a call to HPyTracker_Add fails, the tracker still guarantees that
34+
* the handle passed to it has been tracked (internally it does this by
35+
* maintaining space for one more handle).
36+
*
37+
* After HPyTracker_Add fails, HPyTracker_Close should be called without
38+
* any further calls to HPyTracker_Add. Calling HPyTracker_Close will close
39+
* all the tracked handles, including the handled passed to the failed call
40+
* to HPyTracker_Add.
41+
*
42+
* Example usage (inside an HPyDef_METH function)::
43+
*
44+
* long i;
45+
* HPy key, value;
46+
* HPyTracker ht;
47+
*
48+
* ht = HPyTracker_New(ctx, 0); // track the key-value pairs
49+
* if (HPy_IsNull(ht))
50+
* return HPy_NULL;
51+
*
52+
* HPy dict = HPyDict_New(ctx);
53+
* if (HPy_IsNull(dict))
54+
* goto error;
55+
*
56+
* for (i=0; i<5; i++) {
57+
* key = HPyLong_FromLong(ctx, i);
58+
* if (HPy_IsNull(key))
59+
* goto error;
60+
* if (HPyTracker_Add(ctx, ht, key) < 0)
61+
* goto error;
62+
* value = HPyLong_FromLong(ctx, i * i);
63+
* if (HPy_IsNull(value)) {
64+
* goto error;
65+
* }
66+
* if (HPyTracker_Add(ctx, ht, value) < 0)
67+
* goto error;
68+
* result = HPy_SetItem(ctx, dict, key, value);
69+
* if (result < 0)
70+
* goto error;
71+
* }
72+
*
73+
* success:
74+
* HPyTracker_Close(ctx, ht);
75+
* return dict;
76+
*
77+
* error:
78+
* HPyTracker_Close(ctx, ht);
79+
* HPy_Close(ctx, dict);
80+
* // HPyErr will already have been set by the error that occurred.
81+
* return HPy_NULL;
82+
*/
83+
84+
#include "hpy.h"
85+
86+
static const HPy_ssize_t HPYTRACKER_INITIAL_CAPACITY = 5;
87+
88+
typedef struct {
89+
HPy_ssize_t capacity; // allocated handles
90+
HPy_ssize_t length; // used handles
91+
HPy *handles;
92+
} _HPyTracker_s;
93+
94+
95+
#ifdef HPY_UNIVERSAL_ABI
96+
static inline _HPyTracker_s *_ht2hp(HPyTracker ht) {
97+
return (_HPyTracker_s *) (ht)._i;
98+
}
99+
static inline HPyTracker _hp2ht(_HPyTracker_s *hp) {
100+
return (HPyTracker) {(HPy_ssize_t) (hp)};
101+
}
102+
#else
103+
static inline _HPyTracker_s *_ht2hp(HPyTracker ht) {
104+
return (_HPyTracker_s *) (ht)._o;
105+
}
106+
static inline HPyTracker _hp2ht(_HPyTracker_s *hp) {
107+
return (HPyTracker) {(void *) (hp)};
108+
}
109+
#endif
110+
111+
112+
_HPy_HIDDEN HPyTracker
113+
ctx_Tracker_New(HPyContext ctx, HPy_ssize_t capacity)
114+
{
115+
_HPyTracker_s *hp;
116+
if (capacity == 0) {
117+
capacity = HPYTRACKER_INITIAL_CAPACITY;
118+
}
119+
capacity++; // always reserve space for an extra handle, see the docs
120+
121+
hp = malloc(sizeof(_HPyTracker_s));
122+
if (hp == NULL) {
123+
HPyErr_NoMemory(ctx);
124+
return _hp2ht(0);
125+
}
126+
hp->handles = calloc(capacity, sizeof(HPy));
127+
if (hp->handles == NULL) {
128+
free(hp);
129+
HPyErr_NoMemory(ctx);
130+
return _hp2ht(0);
131+
}
132+
hp->capacity = capacity;
133+
hp->length = 0;
134+
// cppcheck thinks that hp->handles is a memory leak because we cast the
135+
// pointer to an int (and thus the pointer is "lost" from its POV, I
136+
// suppose). But it's not a real leak because we free it in
137+
// ctx_Tracker_Close:
138+
// cppcheck-suppress memleak
139+
return _hp2ht(hp);
140+
}
141+
142+
static int
143+
tracker_resize(HPyContext ctx, _HPyTracker_s *hp, HPy_ssize_t capacity)
144+
{
145+
HPy *new_handles;
146+
capacity++;
147+
148+
if (capacity <= hp->length) {
149+
// refuse a resize that would either 1) lose handles or 2) not leave
150+
// space for one new handle
151+
HPyErr_SetString(ctx, ctx->h_ValueError, "HPyTracker resize would lose handles");
152+
return -1;
153+
}
154+
new_handles = realloc(hp->handles, capacity * sizeof(HPy));
155+
if (new_handles == NULL) {
156+
HPyErr_NoMemory(ctx);
157+
return -1;
158+
}
159+
hp->capacity = capacity;
160+
hp->handles = new_handles;
161+
return 0;
162+
}
163+
164+
_HPy_HIDDEN int
165+
ctx_Tracker_Add(HPyContext ctx, HPyTracker ht, HPy h)
166+
{
167+
_HPyTracker_s *hp = _ht2hp(ht);
168+
hp->handles[hp->length++] = h;
169+
if (hp->capacity <= hp->length) {
170+
if (tracker_resize(ctx, hp, hp->capacity * 2 - 1) < 0)
171+
return -1;
172+
}
173+
return 0;
174+
}
175+
176+
_HPy_HIDDEN void
177+
ctx_Tracker_ForgetAll(HPyContext ctx, HPyTracker ht)
178+
{
179+
_HPyTracker_s *hp = _ht2hp(ht);
180+
hp->length = 0;
181+
}
182+
183+
_HPy_HIDDEN void
184+
ctx_Tracker_Close(HPyContext ctx, HPyTracker ht)
185+
{
186+
_HPyTracker_s *hp = _ht2hp(ht);
187+
HPy_ssize_t i;
188+
for (i=0; i<hp->length; i++) {
189+
HPy_Close(ctx, hp->handles[i]);
190+
}
191+
free(hp->handles);
192+
free(hp);
193+
}

mx.graalpython/copyrights/overrides

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,7 @@ graalpython/lib-graalpython/modules/hpy/devel/src/runtime/ctx_call.c,hpy.copyrig
574574
graalpython/lib-graalpython/modules/hpy/devel/src/runtime/ctx_listbuilder.c,hpy.copyright
575575
graalpython/lib-graalpython/modules/hpy/devel/src/runtime/ctx_module.c,hpy.copyright
576576
graalpython/lib-graalpython/modules/hpy/devel/src/runtime/ctx_object.c,hpy.copyright
577+
graalpython/lib-graalpython/modules/hpy/devel/src/runtime/ctx_tracker.c,hpy.copyright
577578
graalpython/lib-graalpython/modules/hpy/devel/src/runtime/ctx_tuple.c,hpy.copyright
578579
graalpython/lib-graalpython/modules/hpy/devel/src/runtime/ctx_tuplebuilder.c,hpy.copyright
579580
graalpython/lib-graalpython/modules/hpy/devel/src/runtime/ctx_type.c,hpy.copyright

mx.graalpython/mx_graalpython.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2148,14 +2148,13 @@ def exclude_subdir(subdir):
21482148
import_files(hpy_repo_include_dir, header_dest)
21492149
remove_inexistent_files(hpy_repo_include_dir, header_dest)
21502150

2151-
# argparse sources go into 'lib-graalpython/module/hpy/devel/src'
2152-
argparse_file_src = join(hpy_repo_runtime_dir, "argparse.c")
2153-
if not os.path.exists(argparse_file_src):
2154-
mx.abort("File '{}' is missing but required.".format(argparse_file_src))
2155-
argparse_file_dest = join(_get_core_home(), "modules", "hpy", "devel", "src", "argparse.c")
2156-
import_file(argparse_file_src, argparse_file_dest)
2157-
2158-
# 'ctx_tracker.c' goes to 'com.oracle.graal.python.jni/src/ctx_tracker.c'
2151+
2152+
# runtime sources go into 'lib-graalpython/module/hpy/devel/src'
2153+
runtime_files_dest = join(_get_core_home(), "modules", "hpy", "devel", "src")
2154+
import_files(hpy_repo_runtime_dir, runtime_files_dest)
2155+
remove_inexistent_files(hpy_repo_runtime_dir, runtime_files_dest)
2156+
2157+
# 'ctx_tracker.c' also goes to 'com.oracle.graal.python.jni/src/ctx_tracker.c'
21592158
tracker_file_src = join(hpy_repo_runtime_dir, "ctx_tracker.c")
21602159
if not os.path.exists(tracker_file_src):
21612160
mx.abort("File '{}' is missing but required.".format(tracker_file_src))
@@ -2179,7 +2178,7 @@ def exclude_subdir(subdir):
21792178
spec.loader.exec_module(version_module)
21802179
imported_version = version_module.__version__
21812180

2182-
SUITE.vc.git_command(SUITE.dir, ["add", header_dest, test_files_dest, argparse_file_dest, tracker_file_dest])
2181+
SUITE.vc.git_command(SUITE.dir, ["add", header_dest, test_files_dest, runtime_files_dest, tracker_file_dest])
21832182
input("Check that the updated files look as intended, then press RETURN...")
21842183
SUITE.vc.commit(SUITE.dir, "Update HPy inlined files: %s" % import_version)
21852184
SUITE.vc.git_command(SUITE.dir, ["checkout", "-"])

0 commit comments

Comments
 (0)