Skip to content

Commit

Permalink
Implementation with a preallocated list
Browse files Browse the repository at this point in the history
The idea turned out to be very closely related to HPyTracker,
so I blatantly stole some code there.
  • Loading branch information
cklein committed Apr 11, 2021
1 parent de2e78a commit cd4c539
Show file tree
Hide file tree
Showing 13 changed files with 173 additions and 103 deletions.
6 changes: 3 additions & 3 deletions hpy/debug/src/autogen_debug_ctx_init.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions hpy/debug/src/autogen_debug_wrappers.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions hpy/devel/include/common/runtime/ctx_unicodebuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
#include "common/hpytype.h"


_HPy_HIDDEN HPyUnicodeBuilder ctx_UnicodeBuilder_New(HPyContext *ctx);
_HPy_HIDDEN void ctx_UnicodeBuilder_Append(HPyContext *ctx, HPyUnicodeBuilder builder,
HPy h_item);
_HPy_HIDDEN HPyUnicodeBuilder ctx_UnicodeBuilder_New(HPyContext *ctx, HPy_ssize_t capacity);
_HPy_HIDDEN int ctx_UnicodeBuilder_Add(HPyContext *ctx, HPyUnicodeBuilder builder,
HPy h_item);
_HPy_HIDDEN HPy ctx_UnicodeBuilder_Build(HPyContext *ctx, HPyUnicodeBuilder builder);
_HPy_HIDDEN void ctx_UnicodeBuilder_Cancel(HPyContext *ctx, HPyUnicodeBuilder builder);

Expand Down
51 changes: 25 additions & 26 deletions hpy/devel/include/cpython/hpy.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@

typedef struct { PyObject *_o; } HPy;
typedef struct { Py_ssize_t _lst; } HPyListBuilder;
typedef struct { Py_ssize_t _lst; } HPyUnicodeBuilder;
typedef struct { Py_ssize_t _tup; } HPyTupleBuilder;
typedef struct { void *_o; } HPyTracker;
typedef struct { void *_o; } HPyUnicodeBuilder;
typedef Py_ssize_t HPy_ssize_t;
typedef Py_hash_t HPy_hash_t;

Expand Down Expand Up @@ -380,31 +380,6 @@ HPyListBuilder_Cancel(HPyContext *ctx, HPyListBuilder builder)
ctx_ListBuilder_Cancel(ctx, builder);
}

HPyAPI_FUNC(HPyUnicodeBuilder)
HPyUnicodeBuilder_New(HPyContext *ctx)
{
return ctx_UnicodeBuilder_New(ctx);
}

HPyAPI_FUNC(void)
HPyUnicodeBuilder_Append(HPyContext *ctx, HPyUnicodeBuilder builder,
HPy h_item)
{
ctx_UnicodeBuilder_Append(ctx, builder, h_item);
}

HPyAPI_FUNC(HPy)
HPyUnicodeBuilder_Build(HPyContext *ctx, HPyUnicodeBuilder builder)
{
return ctx_UnicodeBuilder_Build(ctx, builder);
}

HPyAPI_FUNC(void)
HPyUnicodeBuilder_Cancel(HPyContext *ctx, HPyUnicodeBuilder builder)
{
ctx_UnicodeBuilder_Cancel(ctx, builder);
}

HPyAPI_FUNC(HPyTupleBuilder)
HPyTupleBuilder_New(HPyContext *ctx, HPy_ssize_t initial_size)
{
Expand Down Expand Up @@ -460,4 +435,28 @@ HPyTracker_Close(HPyContext *ctx, HPyTracker ht)
ctx_Tracker_Close(ctx, ht);
}

HPyAPI_FUNC(HPyUnicodeBuilder)
HPyUnicodeBuilder_New(HPyContext *ctx, HPy_ssize_t size)
{
return ctx_UnicodeBuilder_New(ctx, size);
}

HPyAPI_FUNC(int)
HPyUnicodeBuilder_Add(HPyContext *ctx, HPyUnicodeBuilder builder, HPy h_item)
{
return ctx_UnicodeBuilder_Add(ctx, builder, h_item);
}

HPyAPI_FUNC(HPy)
HPyUnicodeBuilder_Build(HPyContext *ctx, HPyUnicodeBuilder builder)
{
return ctx_UnicodeBuilder_Build(ctx, builder);
}

HPyAPI_FUNC(void)
HPyUnicodeBuilder_Cancel(HPyContext *ctx, HPyUnicodeBuilder builder)
{
ctx_UnicodeBuilder_Cancel(ctx, builder);
}

#endif /* !HPy_CPYTHON_H */
4 changes: 2 additions & 2 deletions hpy/devel/include/universal/autogen_ctx.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions hpy/devel/include/universal/autogen_trampolines.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion hpy/devel/include/universal/hpy.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ typedef intptr_t HPy_hash_t;
the HPy structure contains an index in a global array. */
typedef struct _HPy_s { HPy_ssize_t _i; } HPy;
typedef struct { HPy_ssize_t _lst; } HPyListBuilder;
typedef struct { HPy_ssize_t _lst; } HPyUnicodeBuilder;
typedef struct { HPy_ssize_t _tup; } HPyTupleBuilder;
typedef struct { HPy_ssize_t _i; } HPyTracker;
typedef struct { HPy_ssize_t _i; } HPyUnicodeBuilder;

typedef struct _HPyContext_s HPyContext;

Expand Down
102 changes: 73 additions & 29 deletions hpy/devel/src/runtime/ctx_unicodebuilder.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,57 +7,101 @@
# include "handles.h"
#endif

#include <stdio.h>
static const Py_ssize_t HPYUNICODEBUILDER_INITIAL_CAPACITY = 5;

typedef struct {
Py_ssize_t capacity; // allocated handles
Py_ssize_t length; // used handles
PyObject *list;
} _PyUnicodeBuilder_s;

#ifdef HPY_UNIVERSAL_ABI
static inline _PyUnicodeBuilder_s *_hb2pb(HPyUnicodeBuilder ht) {
return (_PyUnicodeBuilder_s *) (ht)._i;
}
static inline HPyUnicodeBuilder _pb2hb(_PyUnicodeBuilder_s *bp) {
return (HPyUnicodeBuilder) {(HPy_ssize_t) (bp)};
}
#else
static inline _PyUnicodeBuilder_s *_hb2pb(HPyUnicodeBuilder ht) {
return (_PyUnicodeBuilder_s *) (ht)._o;
}
static inline HPyUnicodeBuilder _pb2hb(_PyUnicodeBuilder_s *bp) {
return (HPyUnicodeBuilder) {(void *) (bp)};
}
#endif

_HPy_HIDDEN HPyUnicodeBuilder
ctx_UnicodeBuilder_New(HPyContext *ctx)
ctx_UnicodeBuilder_New(HPyContext *ctx, HPy_ssize_t capacity)
{
PyObject *lst = PyList_New(0);
if (lst == NULL)
PyErr_Clear(); /* delay the MemoryError */
return (HPyUnicodeBuilder){(HPy_ssize_t)lst };
_PyUnicodeBuilder_s *bp;
if (capacity == 0) {
capacity = HPYUNICODEBUILDER_INITIAL_CAPACITY;
}
capacity++; // always reserve space for an extra handle, see the docs, analogue to HPyTracker

bp = malloc(sizeof(_PyUnicodeBuilder_s));
if (bp == NULL) {
HPyErr_NoMemory(ctx);
return _pb2hb(0);
}

bp->list = PyList_New(capacity);
if (bp->list == NULL) {
free(bp);
HPyErr_NoMemory(ctx);
return _pb2hb(0);
}
bp->capacity = capacity;
bp->length = 0;
return _pb2hb(bp);
}

_HPy_HIDDEN void
ctx_UnicodeBuilder_Append(HPyContext *ctx, HPyUnicodeBuilder builder, HPy h_item)
_HPy_HIDDEN int
ctx_UnicodeBuilder_Add(HPyContext *ctx, HPyUnicodeBuilder builder, HPy h_item)
{
PyObject *lst = (PyObject *)builder._lst;
if (lst != NULL) {
PyObject *item = _h2py(h_item);
PyList_Append(lst, item);
if(!HPyUnicode_Check(ctx, h_item)) {
HPyErr_SetString(ctx, ctx->h_TypeError, "Argument must be of type HPyUnicode");
return -1;
}

_PyUnicodeBuilder_s *bp = _hb2pb(builder);
PyObject *item = _h2py(h_item);

// XXX: For the initial PoC we don't care about reallocation
if (bp->capacity <= bp->length) {
return -1;
}
Py_INCREF(item);
PyList_SET_ITEM(bp->list, bp->length++, item);
return 0;
}

_HPy_HIDDEN HPy
ctx_UnicodeBuilder_Build(HPyContext *ctx, HPyUnicodeBuilder builder)
{
PyObject *lst = (PyObject *)builder._lst;
if (lst == NULL) {
PyErr_NoMemory();
return HPy_NULL;
}
builder._lst = 0;
_PyUnicodeBuilder_s *bp = _hb2pb(builder);
PyObject *list = PyList_GetSlice(bp->list, 0, bp->length);

PyObject *sep = PyUnicode_FromString("");
PyObject *str = PyUnicode_Join(sep, lst);
PyObject *str = PyUnicode_Join(sep, list);
Py_XDECREF(sep);

if(str == NULL) {
PyErr_NoMemory();
return HPy_NULL;
}
Py_XDECREF(lst);

Py_XDECREF(bp->list);
Py_XDECREF(list);
free(bp);
return _py2h(str);
}

_HPy_HIDDEN void
ctx_UnicodeBuilder_Cancel(HPyContext *ctx, HPyUnicodeBuilder builder)
{
PyObject *lst = (PyObject *)builder._lst;
if (lst == NULL) {
// we don't report the memory error here: the builder
// is being cancelled (so the result of the builder is not being used)
// and likely it's being cancelled during the handling of another error
return;
}
builder._lst = 0;
Py_XDECREF(lst);
_PyUnicodeBuilder_s *bp = _hb2pb(builder);
Py_XDECREF(bp->list);
free(bp);
}
8 changes: 4 additions & 4 deletions hpy/tools/autogen/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,6 @@ def _visit_hpyslot_slot(self, node):
'HPyListBuilder_Set': None,
'HPyListBuilder_Build': None,
'HPyListBuilder_Cancel': None,
'HPyUnicodeBuilder_New': None,
'HPyUnicodeBuilder_Append': None,
'HPyUnicodeBuilder_Build': None,
'HPyUnicodeBuilder_Cancel': None,
'HPyTuple_FromArray': None,
'HPyTupleBuilder_New': None,
'HPyTupleBuilder_Set': None,
Expand All @@ -223,6 +219,10 @@ def _visit_hpyslot_slot(self, node):
'HPyTracker_Add': None,
'HPyTracker_ForgetAll': None,
'HPyTracker_Close': None,
'HPyUnicodeBuilder_New': None,
'HPyUnicodeBuilder_Add': None,
'HPyUnicodeBuilder_Build': None,
'HPyUnicodeBuilder_Cancel': None,
'_HPy_Dump': None,
'HPy_Type': 'PyObject_Type',
'HPy_TypeCheck': None,
Expand Down
5 changes: 2 additions & 3 deletions hpy/tools/autogen/public_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,8 @@ void HPyListBuilder_Set(HPyContext *ctx, HPyListBuilder builder,
HPy HPyListBuilder_Build(HPyContext *ctx, HPyListBuilder builder);
void HPyListBuilder_Cancel(HPyContext *ctx, HPyListBuilder builder);

HPyUnicodeBuilder HPyUnicodeBuilder_New(HPyContext *ctx);
void HPyUnicodeBuilder_Append(HPyContext *ctx, HPyUnicodeBuilder builder,
HPy h_item);
HPyUnicodeBuilder HPyUnicodeBuilder_New(HPyContext *ctx, HPy_ssize_t size);
int HPyUnicodeBuilder_Add(HPyContext *ctx, HPyUnicodeBuilder builder, HPy h_item);
HPy HPyUnicodeBuilder_Build(HPyContext *ctx, HPyUnicodeBuilder builder);
void HPyUnicodeBuilder_Cancel(HPyContext *ctx, HPyUnicodeBuilder builder);

Expand Down
2 changes: 1 addition & 1 deletion hpy/universal/src/autogen_ctx_def.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 0 additions & 23 deletions test/test_hpystringbuilder.py

This file was deleted.

Loading

0 comments on commit cd4c539

Please sign in to comment.