Skip to content

Commit 8289177

Browse files
committed
Refactor unpacking of recursive types
Extracted from: #370 As initially implemented, we allocate a new stack whenever we encounter a child stack. This means acquiring a whole 4kiB chunk from the arena, which generally is overkill. Instead we can introduce a new type of stack item, that behave just like a Hash or Array.
1 parent 9bac145 commit 8289177

File tree

3 files changed

+11
-20
lines changed

3 files changed

+11
-20
lines changed

ext/msgpack/unpacker.c

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -108,25 +108,19 @@ static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack)
108108

109109
void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
110110
{
111-
msgpack_unpacker_stack_t *stack;
112-
while ((stack = uk->stack)) {
113-
uk->stack = stack->parent;
114-
_msgpack_unpacker_free_stack(stack);
115-
}
116-
111+
_msgpack_unpacker_free_stack(uk->stack);
117112
msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
118113
}
119114

120115
void msgpack_unpacker_mark_stack(msgpack_unpacker_stack_t* stack)
121116
{
122-
while (stack) {
117+
if (stack) {
123118
msgpack_unpacker_stack_entry_t* s = stack->data;
124119
msgpack_unpacker_stack_entry_t* send = stack->data + stack->depth;
125120
for(; s < send; s++) {
126121
rb_gc_mark(s->object);
127122
rb_gc_mark(s->key);
128123
}
129-
stack = stack->parent;
130124
}
131125
}
132126

@@ -343,14 +337,10 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
343337
reset_head_byte(uk);
344338
uk->reading_raw_remaining = 0;
345339

346-
msgpack_unpacker_stack_t* child_stack = _msgpack_unpacker_new_stack();
347-
child_stack->parent = uk->stack;
348-
uk->stack = child_stack;
349-
340+
_msgpack_unpacker_stack_push(uk, STACK_TYPE_RECURSIVE, 1, Qnil);
350341
int raised;
351342
obj = protected_proc_call(proc, 1, &uk->self, &raised);
352-
uk->stack = child_stack->parent;
353-
_msgpack_unpacker_free_stack(child_stack);
343+
msgpack_unpacker_stack_pop(uk);
354344

355345
if (raised) {
356346
uk->last_object = rb_errinfo();
@@ -783,6 +773,8 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
783773
}
784774
top->type = STACK_TYPE_MAP_KEY;
785775
break;
776+
case STACK_TYPE_RECURSIVE:
777+
return PRIMITIVE_OBJECT_COMPLETE;
786778
}
787779
size_t count = --top->count;
788780

ext/msgpack/unpacker.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ enum stack_type_t {
3131
STACK_TYPE_ARRAY,
3232
STACK_TYPE_MAP_KEY,
3333
STACK_TYPE_MAP_VALUE,
34+
STACK_TYPE_RECURSIVE,
3435
};
3536

3637
typedef struct {
@@ -44,7 +45,6 @@ struct msgpack_unpacker_stack_t {
4445
size_t depth;
4546
size_t capacity;
4647
msgpack_unpacker_stack_entry_t *data;
47-
msgpack_unpacker_stack_t *parent;
4848
};
4949

5050
struct msgpack_unpacker_t {

ext/msgpack/unpacker_class.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,16 @@ static void Unpacker_mark(void *ptr)
5858

5959
static size_t Unpacker_memsize(const void *ptr)
6060
{
61+
const msgpack_unpacker_t* uk = ptr;
62+
6163
size_t total_size = sizeof(msgpack_unpacker_t);
6264

63-
const msgpack_unpacker_t* uk = ptr;
6465
if (uk->ext_registry) {
6566
total_size += sizeof(msgpack_unpacker_ext_registry_t) / (uk->ext_registry->borrow_count + 1);
6667
}
6768

68-
msgpack_unpacker_stack_t *stack = uk->stack;
69-
while (stack) {
70-
total_size += (stack->depth + 1) * sizeof(msgpack_unpacker_stack_t);
71-
stack = stack->parent;
69+
if (uk->stack) {
70+
total_size += (uk->stack->depth + 1) * sizeof(msgpack_unpacker_stack_t);
7271
}
7372

7473
return total_size + msgpack_buffer_memsize(&uk->buffer);

0 commit comments

Comments
 (0)