Skip to content

Commit 914b447

Browse files
committed
Implementation with a preallocated list
The idea turned out to be very closely related to HPyTracker, so I blatantly stole some code there.
1 parent de2e78a commit 914b447

File tree

13 files changed

+172
-103
lines changed

13 files changed

+172
-103
lines changed

Diff for: hpy/debug/src/autogen_debug_ctx_init.h

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: hpy/debug/src/autogen_debug_wrappers.c

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: hpy/devel/include/common/runtime/ctx_unicodebuilder.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
#include "common/hpytype.h"
77

88

9-
_HPy_HIDDEN HPyUnicodeBuilder ctx_UnicodeBuilder_New(HPyContext *ctx);
10-
_HPy_HIDDEN void ctx_UnicodeBuilder_Append(HPyContext *ctx, HPyUnicodeBuilder builder,
11-
HPy h_item);
9+
_HPy_HIDDEN HPyUnicodeBuilder ctx_UnicodeBuilder_New(HPyContext *ctx, HPy_ssize_t capacity);
10+
_HPy_HIDDEN int ctx_UnicodeBuilder_Add(HPyContext *ctx, HPyUnicodeBuilder builder,
11+
HPy h_item);
1212
_HPy_HIDDEN HPy ctx_UnicodeBuilder_Build(HPyContext *ctx, HPyUnicodeBuilder builder);
1313
_HPy_HIDDEN void ctx_UnicodeBuilder_Cancel(HPyContext *ctx, HPyUnicodeBuilder builder);
1414

Diff for: hpy/devel/include/cpython/hpy.h

+25-26
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@
3131

3232
typedef struct { PyObject *_o; } HPy;
3333
typedef struct { Py_ssize_t _lst; } HPyListBuilder;
34-
typedef struct { Py_ssize_t _lst; } HPyUnicodeBuilder;
3534
typedef struct { Py_ssize_t _tup; } HPyTupleBuilder;
3635
typedef struct { void *_o; } HPyTracker;
36+
typedef struct { void *_o; } HPyUnicodeBuilder;
3737
typedef Py_ssize_t HPy_ssize_t;
3838
typedef Py_hash_t HPy_hash_t;
3939

@@ -380,31 +380,6 @@ HPyListBuilder_Cancel(HPyContext *ctx, HPyListBuilder builder)
380380
ctx_ListBuilder_Cancel(ctx, builder);
381381
}
382382

383-
HPyAPI_FUNC(HPyUnicodeBuilder)
384-
HPyUnicodeBuilder_New(HPyContext *ctx)
385-
{
386-
return ctx_UnicodeBuilder_New(ctx);
387-
}
388-
389-
HPyAPI_FUNC(void)
390-
HPyUnicodeBuilder_Append(HPyContext *ctx, HPyUnicodeBuilder builder,
391-
HPy h_item)
392-
{
393-
ctx_UnicodeBuilder_Append(ctx, builder, h_item);
394-
}
395-
396-
HPyAPI_FUNC(HPy)
397-
HPyUnicodeBuilder_Build(HPyContext *ctx, HPyUnicodeBuilder builder)
398-
{
399-
return ctx_UnicodeBuilder_Build(ctx, builder);
400-
}
401-
402-
HPyAPI_FUNC(void)
403-
HPyUnicodeBuilder_Cancel(HPyContext *ctx, HPyUnicodeBuilder builder)
404-
{
405-
ctx_UnicodeBuilder_Cancel(ctx, builder);
406-
}
407-
408383
HPyAPI_FUNC(HPyTupleBuilder)
409384
HPyTupleBuilder_New(HPyContext *ctx, HPy_ssize_t initial_size)
410385
{
@@ -460,4 +435,28 @@ HPyTracker_Close(HPyContext *ctx, HPyTracker ht)
460435
ctx_Tracker_Close(ctx, ht);
461436
}
462437

438+
HPyAPI_FUNC(HPyUnicodeBuilder)
439+
HPyUnicodeBuilder_New(HPyContext *ctx, HPy_ssize_t size)
440+
{
441+
return ctx_UnicodeBuilder_New(ctx, size);
442+
}
443+
444+
HPyAPI_FUNC(int)
445+
HPyUnicodeBuilder_Add(HPyContext *ctx, HPyUnicodeBuilder builder, HPy h_item)
446+
{
447+
return ctx_UnicodeBuilder_Add(ctx, builder, h_item);
448+
}
449+
450+
HPyAPI_FUNC(HPy)
451+
HPyUnicodeBuilder_Build(HPyContext *ctx, HPyUnicodeBuilder builder)
452+
{
453+
return ctx_UnicodeBuilder_Build(ctx, builder);
454+
}
455+
456+
HPyAPI_FUNC(void)
457+
HPyUnicodeBuilder_Cancel(HPyContext *ctx, HPyUnicodeBuilder builder)
458+
{
459+
ctx_UnicodeBuilder_Cancel(ctx, builder);
460+
}
461+
463462
#endif /* !HPy_CPYTHON_H */

Diff for: hpy/devel/include/universal/autogen_ctx.h

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: hpy/devel/include/universal/autogen_trampolines.h

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: hpy/devel/include/universal/hpy.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ typedef intptr_t HPy_hash_t;
3434
the HPy structure contains an index in a global array. */
3535
typedef struct _HPy_s { HPy_ssize_t _i; } HPy;
3636
typedef struct { HPy_ssize_t _lst; } HPyListBuilder;
37-
typedef struct { HPy_ssize_t _lst; } HPyUnicodeBuilder;
3837
typedef struct { HPy_ssize_t _tup; } HPyTupleBuilder;
3938
typedef struct { HPy_ssize_t _i; } HPyTracker;
39+
typedef struct { HPy_ssize_t _i; } HPyUnicodeBuilder;
4040

4141
typedef struct _HPyContext_s HPyContext;
4242

Diff for: hpy/devel/src/runtime/ctx_unicodebuilder.c

+73-29
Original file line numberDiff line numberDiff line change
@@ -7,57 +7,101 @@
77
# include "handles.h"
88
#endif
99

10-
#include <stdio.h>
10+
static const Py_ssize_t HPYUNICODEBUILDER_INITIAL_CAPACITY = 5;
11+
12+
typedef struct {
13+
Py_ssize_t capacity; // allocated handles
14+
Py_ssize_t length; // used handles
15+
PyObject *list;
16+
} _PyUnicodeBuilder_s;
17+
18+
#ifdef HPY_UNIVERSAL_ABI
19+
static inline _PyUnicodeBuilder_s *_hb2pb(HPyUnicodeBuilder ht) {
20+
return (_PyUnicodeBuilder_s *) (ht)._i;
21+
}
22+
static inline HPyUnicodeBuilder _pb2hb(_PyUnicodeBuilder_s *bp) {
23+
return (HPyUnicodeBuilder) {(HPy_ssize_t) (bp)};
24+
}
25+
#else
26+
static inline _PyUnicodeBuilder_s *_hb2pb(HPyUnicodeBuilder ht) {
27+
return (_PyUnicodeBuilder_s *) (ht)._o;
28+
}
29+
static inline HPyUnicodeBuilder _pb2hb(_PyUnicodeBuilder_s *bp) {
30+
return (HPyUnicodeBuilder) {(void *) (bp)};
31+
}
32+
#endif
1133

1234
_HPy_HIDDEN HPyUnicodeBuilder
13-
ctx_UnicodeBuilder_New(HPyContext *ctx)
35+
ctx_UnicodeBuilder_New(HPyContext *ctx, HPy_ssize_t capacity)
1436
{
15-
PyObject *lst = PyList_New(0);
16-
if (lst == NULL)
17-
PyErr_Clear(); /* delay the MemoryError */
18-
return (HPyUnicodeBuilder){(HPy_ssize_t)lst };
37+
_PyUnicodeBuilder_s *bp;
38+
if (capacity == 0) {
39+
capacity = HPYUNICODEBUILDER_INITIAL_CAPACITY;
40+
}
41+
capacity++; // always reserve space for an extra handle, see the docs, analogue to HPyTracker
42+
43+
bp = malloc(sizeof(_PyUnicodeBuilder_s));
44+
if (bp == NULL) {
45+
HPyErr_NoMemory(ctx);
46+
return _pb2hb(0);
47+
}
48+
49+
bp->list = PyList_New(capacity);
50+
if (bp->list == NULL) {
51+
free(bp);
52+
HPyErr_NoMemory(ctx);
53+
return _pb2hb(0);
54+
}
55+
bp->capacity = capacity;
56+
bp->length = 0;
57+
return _pb2hb(bp);
1958
}
2059

21-
_HPy_HIDDEN void
22-
ctx_UnicodeBuilder_Append(HPyContext *ctx, HPyUnicodeBuilder builder, HPy h_item)
60+
_HPy_HIDDEN int
61+
ctx_UnicodeBuilder_Add(HPyContext *ctx, HPyUnicodeBuilder builder, HPy h_item)
2362
{
24-
PyObject *lst = (PyObject *)builder._lst;
25-
if (lst != NULL) {
26-
PyObject *item = _h2py(h_item);
27-
PyList_Append(lst, item);
63+
if(!HPyUnicode_Check(ctx, h_item)) {
64+
HPyErr_SetString(ctx, ctx->h_TypeError, "Argument must be of type HPyUnicode");
65+
return -1;
66+
}
67+
68+
_PyUnicodeBuilder_s *bp = _hb2pb(builder);
69+
PyObject *item = _h2py(h_item);
70+
71+
// XXX: For the initial PoC we don't care about reallocation
72+
if (bp->capacity <= bp->length) {
73+
return -1;
2874
}
75+
Py_INCREF(item);
76+
PyList_SET_ITEM(bp->list, bp->length++, item);
77+
return 0;
2978
}
3079

3180
_HPy_HIDDEN HPy
3281
ctx_UnicodeBuilder_Build(HPyContext *ctx, HPyUnicodeBuilder builder)
3382
{
34-
PyObject *lst = (PyObject *)builder._lst;
35-
if (lst == NULL) {
36-
PyErr_NoMemory();
37-
return HPy_NULL;
38-
}
39-
builder._lst = 0;
83+
_PyUnicodeBuilder_s *bp = _hb2pb(builder);
84+
PyObject *list = PyList_GetSlice(bp->list, 0, bp->length);
85+
4086
PyObject *sep = PyUnicode_FromString("");
41-
PyObject *str = PyUnicode_Join(sep, lst);
87+
PyObject *str = PyUnicode_Join(sep, list);
4288
Py_XDECREF(sep);
89+
4390
if(str == NULL) {
4491
PyErr_NoMemory();
4592
return HPy_NULL;
4693
}
47-
Py_XDECREF(lst);
94+
95+
Py_XDECREF(bp->list);
96+
Py_XDECREF(list);
97+
free(bp);
4898
return _py2h(str);
4999
}
50100

51101
_HPy_HIDDEN void
52102
ctx_UnicodeBuilder_Cancel(HPyContext *ctx, HPyUnicodeBuilder builder)
53103
{
54-
PyObject *lst = (PyObject *)builder._lst;
55-
if (lst == NULL) {
56-
// we don't report the memory error here: the builder
57-
// is being cancelled (so the result of the builder is not being used)
58-
// and likely it's being cancelled during the handling of another error
59-
return;
60-
}
61-
builder._lst = 0;
62-
Py_XDECREF(lst);
104+
_PyUnicodeBuilder_s *bp = _hb2pb(builder);
105+
Py_XDECREF(bp->list);
106+
free(bp);
63107
}

Diff for: hpy/tools/autogen/parse.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,6 @@ def _visit_hpyslot_slot(self, node):
210210
'HPyListBuilder_Set': None,
211211
'HPyListBuilder_Build': None,
212212
'HPyListBuilder_Cancel': None,
213-
'HPyUnicodeBuilder_New': None,
214-
'HPyUnicodeBuilder_Append': None,
215-
'HPyUnicodeBuilder_Build': None,
216-
'HPyUnicodeBuilder_Cancel': None,
217213
'HPyTuple_FromArray': None,
218214
'HPyTupleBuilder_New': None,
219215
'HPyTupleBuilder_Set': None,
@@ -223,6 +219,10 @@ def _visit_hpyslot_slot(self, node):
223219
'HPyTracker_Add': None,
224220
'HPyTracker_ForgetAll': None,
225221
'HPyTracker_Close': None,
222+
'HPyUnicodeBuilder_New': None,
223+
'HPyUnicodeBuilder_Add': None,
224+
'HPyUnicodeBuilder_Build': None,
225+
'HPyUnicodeBuilder_Cancel': None,
226226
'_HPy_Dump': None,
227227
'HPy_Type': 'PyObject_Type',
228228
'HPy_TypeCheck': None,

Diff for: hpy/tools/autogen/public_api.h

+2-3
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,8 @@ void HPyListBuilder_Set(HPyContext *ctx, HPyListBuilder builder,
283283
HPy HPyListBuilder_Build(HPyContext *ctx, HPyListBuilder builder);
284284
void HPyListBuilder_Cancel(HPyContext *ctx, HPyListBuilder builder);
285285

286-
HPyUnicodeBuilder HPyUnicodeBuilder_New(HPyContext *ctx);
287-
void HPyUnicodeBuilder_Append(HPyContext *ctx, HPyUnicodeBuilder builder,
288-
HPy h_item);
286+
HPyUnicodeBuilder HPyUnicodeBuilder_New(HPyContext *ctx, HPy_ssize_t size);
287+
int HPyUnicodeBuilder_Add(HPyContext *ctx, HPyUnicodeBuilder builder, HPy h_item);
289288
HPy HPyUnicodeBuilder_Build(HPyContext *ctx, HPyUnicodeBuilder builder);
290289
void HPyUnicodeBuilder_Cancel(HPyContext *ctx, HPyUnicodeBuilder builder);
291290

Diff for: hpy/universal/src/autogen_ctx_def.h

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: test/test_hpystringbuilder.py

-23
This file was deleted.

0 commit comments

Comments
 (0)