@@ -49,7 +49,6 @@ static VALUE protected_proc_call(VALUE proc, int argc, VALUE *argv, int *raised)
49
49
50
50
static int RAW_TYPE_STRING = 256 ;
51
51
static int RAW_TYPE_BINARY = 257 ;
52
- static int16_t INITIAL_BUFFER_CAPACITY_MAX = SHRT_MAX ;
53
52
54
53
static msgpack_rmem_t s_stack_rmem ;
55
54
@@ -60,9 +59,106 @@ static inline VALUE rb_hash_new_capa(long capa)
60
59
}
61
60
#endif
62
61
63
- static inline int16_t initial_buffer_size (long size )
62
+ #ifndef HAVE_RB_HASH_BULK_INSERT
63
+ void rb_hash_bulk_insert (long count , const VALUE * pairs , VALUE hash )
64
64
{
65
- return (size > INITIAL_BUFFER_CAPACITY_MAX ) ? INITIAL_BUFFER_CAPACITY_MAX : size ;
65
+ long index = 0 ;
66
+ while (index < count ) {
67
+ VALUE name = pairs [index ++ ];
68
+ VALUE value = pairs [index ++ ];
69
+ rb_hash_aset (hash , name , value );
70
+ }
71
+ RB_GC_GUARD (hash );
72
+ }
73
+ #endif
74
+
75
+ /* rvalue_stack functions */
76
+
77
+ static inline void _msgpack_unpacker_rvalue_stack_free (msgpack_rvalue_stack_t * value_stack ) {
78
+ switch (value_stack -> type ) {
79
+ case STACK_TYPE_UNALLOCATED :
80
+ break ;
81
+ case STACK_TYPE_RMEM :
82
+ if (!msgpack_rmem_free (& s_stack_rmem , value_stack -> data )) {
83
+ rb_bug ("Failed to free an rmem pointer, memory leak?" );
84
+ }
85
+ break ;
86
+ case STACK_TYPE_HEAP :
87
+ xfree (value_stack -> data );
88
+ break ;
89
+ }
90
+ memset (value_stack , 0 , sizeof (msgpack_rvalue_stack_t ));
91
+ }
92
+
93
+ static void _msgpack_unpacker_rvalue_stack_grow (msgpack_rvalue_stack_t * value_stack ) {
94
+ switch (value_stack -> type ) {
95
+ case STACK_TYPE_UNALLOCATED : {
96
+ value_stack -> data = msgpack_rmem_alloc (& s_stack_rmem );
97
+ value_stack -> capacity = MSGPACK_RMEM_PAGE_SIZE / sizeof (VALUE );
98
+ value_stack -> type = STACK_TYPE_RMEM ;
99
+ break ;
100
+ }
101
+ case STACK_TYPE_RMEM : {
102
+ size_t new_capacity = value_stack -> capacity * 2 ;
103
+ VALUE * new_ptr = ALLOC_N (VALUE , new_capacity );
104
+ MEMCPY (new_ptr , value_stack -> data , VALUE , value_stack -> depth );
105
+ if (!msgpack_rmem_free (& s_stack_rmem , value_stack -> data )) {
106
+ rb_bug ("Failed to free an rmem pointer, memory leak?" );
107
+ }
108
+ value_stack -> type = STACK_TYPE_HEAP ;
109
+ value_stack -> data = new_ptr ;
110
+ value_stack -> capacity = new_capacity ;
111
+ break ;
112
+ }
113
+ case STACK_TYPE_HEAP : {
114
+ size_t new_capacity = value_stack -> capacity * 2 ;
115
+ REALLOC_N (value_stack -> data , VALUE , new_capacity );
116
+ value_stack -> capacity = new_capacity ;
117
+ break ;
118
+ }
119
+ }
120
+ }
121
+
122
+ static inline void _msgpack_unpacker_rvalue_stack_push (msgpack_unpacker_t * uk , VALUE value ) {
123
+ size_t free_slots = uk -> value_stack .capacity - uk -> value_stack .depth ;
124
+
125
+ if (RB_UNLIKELY (free_slots == 0 )) {
126
+ _msgpack_unpacker_rvalue_stack_grow (& uk -> value_stack );
127
+ free_slots = uk -> value_stack .capacity - uk -> value_stack .depth ;
128
+ }
129
+
130
+ RB_OBJ_WRITE (uk -> self , & uk -> value_stack .data [uk -> value_stack .depth ++ ], value );
131
+ }
132
+
133
+ static inline VALUE _msgpack_unpacker_rvalue_stack_create_array (msgpack_unpacker_t * uk , size_t length ) {
134
+ VALUE * data = & uk -> value_stack .data [uk -> value_stack .depth - length ];
135
+
136
+ VALUE array = rb_ary_new_from_values (length , data );
137
+
138
+ RB_OBJ_WRITE (uk -> self , data , array );
139
+ uk -> value_stack .depth -= (length - 1 );
140
+
141
+ return RB_GC_GUARD (array );
142
+ }
143
+
144
+ static inline VALUE _msgpack_unpacker_rvalue_stack_create_hash (msgpack_unpacker_t * uk , size_t items_count ) {
145
+ size_t length = items_count / 2 ;
146
+ VALUE * data = & uk -> value_stack .data [uk -> value_stack .depth - items_count ];
147
+
148
+ VALUE hash = rb_hash_new_capa (length );
149
+ rb_hash_bulk_insert (items_count , data , hash );
150
+
151
+ RB_OBJ_WRITE (uk -> self , data , hash );
152
+ uk -> value_stack .depth -= (items_count - 1 );
153
+
154
+ return RB_GC_GUARD (hash );
155
+ }
156
+
157
+ void msgpack_unpacker_mark_rvalue_stack (msgpack_rvalue_stack_t * value_stack )
158
+ {
159
+ if (value_stack -> data ) {
160
+ rb_gc_mark_locations (value_stack -> data , value_stack -> data + value_stack -> depth );
161
+ }
66
162
}
67
163
68
164
void msgpack_unpacker_static_init (void )
@@ -108,33 +204,16 @@ static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack)
108
204
109
205
void _msgpack_unpacker_destroy (msgpack_unpacker_t * uk )
110
206
{
111
- msgpack_unpacker_stack_t * stack ;
112
- while ((stack = uk -> stack )) {
113
- uk -> stack = stack -> parent ;
114
- _msgpack_unpacker_free_stack (stack );
115
- }
116
-
207
+ _msgpack_unpacker_free_stack (uk -> stack );
208
+ _msgpack_unpacker_rvalue_stack_free (& uk -> value_stack );
117
209
msgpack_buffer_destroy (UNPACKER_BUFFER_ (uk ));
118
210
}
119
211
120
- void msgpack_unpacker_mark_stack (msgpack_unpacker_stack_t * stack )
121
- {
122
- while (stack ) {
123
- msgpack_unpacker_stack_entry_t * s = stack -> data ;
124
- msgpack_unpacker_stack_entry_t * send = stack -> data + stack -> depth ;
125
- for (; s < send ; s ++ ) {
126
- rb_gc_mark (s -> object );
127
- rb_gc_mark (s -> key );
128
- }
129
- stack = stack -> parent ;
130
- }
131
- }
132
-
133
212
void msgpack_unpacker_mark (msgpack_unpacker_t * uk )
134
213
{
135
214
rb_gc_mark (uk -> last_object );
136
215
rb_gc_mark (uk -> reading_raw );
137
- msgpack_unpacker_mark_stack ( uk -> stack );
216
+ msgpack_unpacker_mark_rvalue_stack ( & uk -> value_stack );
138
217
/* See MessagePack_Buffer_wrap */
139
218
/* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
140
219
rb_gc_mark (uk -> buffer_ref );
@@ -149,6 +228,7 @@ void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
149
228
150
229
/*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack->depth);*/
151
230
uk -> stack -> depth = 0 ;
231
+ uk -> value_stack .depth = 0 ;
152
232
uk -> last_object = Qnil ;
153
233
uk -> reading_raw = Qnil ;
154
234
uk -> reading_raw_remaining = 0 ;
@@ -186,13 +266,15 @@ static inline int object_complete(msgpack_unpacker_t* uk, VALUE object)
186
266
}
187
267
188
268
uk -> last_object = object ;
269
+ _msgpack_unpacker_rvalue_stack_push (uk , object );
189
270
reset_head_byte (uk );
190
271
return PRIMITIVE_OBJECT_COMPLETE ;
191
272
}
192
273
193
274
static inline int object_complete_symbol (msgpack_unpacker_t * uk , VALUE object )
194
275
{
195
276
uk -> last_object = object ;
277
+ _msgpack_unpacker_rvalue_stack_push (uk , object );
196
278
reset_head_byte (uk );
197
279
return PRIMITIVE_OBJECT_COMPLETE ;
198
280
}
@@ -212,12 +294,14 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
212
294
if (proc != Qnil ) {
213
295
VALUE obj ;
214
296
VALUE arg = (str == Qnil ? rb_str_buf_new (0 ) : str );
297
+
215
298
int raised ;
216
299
obj = protected_proc_call (proc , 1 , & arg , & raised );
217
300
if (raised ) {
218
301
uk -> last_object = rb_errinfo ();
219
302
return PRIMITIVE_RECURSIVE_RAISED ;
220
303
}
304
+
221
305
return object_complete (uk , obj );
222
306
}
223
307
@@ -235,7 +319,7 @@ static inline msgpack_unpacker_stack_entry_t* _msgpack_unpacker_stack_entry_top(
235
319
return & uk -> stack -> data [uk -> stack -> depth - 1 ];
236
320
}
237
321
238
- static inline int _msgpack_unpacker_stack_push (msgpack_unpacker_t * uk , enum stack_type_t type , size_t count , VALUE object )
322
+ static inline int _msgpack_unpacker_stack_push (msgpack_unpacker_t * uk , enum stack_type_t type , size_t count )
239
323
{
240
324
reset_head_byte (uk );
241
325
@@ -245,22 +329,20 @@ static inline int _msgpack_unpacker_stack_push(msgpack_unpacker_t* uk, enum stac
245
329
246
330
msgpack_unpacker_stack_entry_t * next = & uk -> stack -> data [uk -> stack -> depth ];
247
331
next -> count = count ;
332
+ next -> size = count ;
248
333
next -> type = type ;
249
- next -> object = object ;
250
- next -> key = Qnil ;
251
-
252
334
uk -> stack -> depth ++ ;
253
335
return PRIMITIVE_CONTAINER_START ;
254
336
}
255
337
256
- static inline VALUE msgpack_unpacker_stack_pop (msgpack_unpacker_t * uk )
338
+ static inline size_t msgpack_unpacker_stack_pop (msgpack_unpacker_t * uk )
257
339
{
258
340
return -- uk -> stack -> depth ;
259
341
}
260
342
261
343
static inline bool msgpack_unpacker_stack_is_empty (msgpack_unpacker_t * uk )
262
344
{
263
- return uk -> stack -> depth == 0 ;
345
+ return uk -> stack -> depth == 0 || _msgpack_unpacker_stack_entry_top ( uk ) -> type == STACK_TYPE_RECURSIVE ;
264
346
}
265
347
266
348
#ifdef USE_CASE_RANGE
@@ -290,9 +372,7 @@ static inline bool is_reading_map_key(msgpack_unpacker_t* uk)
290
372
{
291
373
if (uk -> stack -> depth > 0 ) {
292
374
msgpack_unpacker_stack_entry_t * top = _msgpack_unpacker_stack_entry_top (uk );
293
- if (top -> type == STACK_TYPE_MAP_KEY ) {
294
- return true;
295
- }
375
+ return top -> type == STACK_TYPE_MAP && (top -> count % 2 == 0 );
296
376
}
297
377
return false;
298
378
}
@@ -343,17 +423,17 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
343
423
reset_head_byte (uk );
344
424
uk -> reading_raw_remaining = 0 ;
345
425
346
- msgpack_unpacker_stack_t * child_stack = _msgpack_unpacker_new_stack ();
347
- child_stack -> parent = uk -> stack ;
348
- uk -> stack = child_stack ;
349
426
427
+ _msgpack_unpacker_stack_push (uk , STACK_TYPE_RECURSIVE , 1 );
428
+ size_t value_stack_depth = uk -> value_stack .depth ;
350
429
int raised ;
351
430
obj = protected_proc_call (proc , 1 , & uk -> self , & raised );
352
- uk -> stack = child_stack -> parent ;
353
- _msgpack_unpacker_free_stack ( child_stack );
431
+ uk -> value_stack . depth = value_stack_depth ;
432
+ msgpack_unpacker_stack_pop ( uk );
354
433
355
434
if (raised ) {
356
435
uk -> last_object = rb_errinfo ();
436
+ _msgpack_unpacker_rvalue_stack_push (uk , Qnil );
357
437
return PRIMITIVE_RECURSIVE_RAISED ;
358
438
}
359
439
@@ -418,14 +498,14 @@ static int read_primitive(msgpack_unpacker_t* uk)
418
498
if (count == 0 ) {
419
499
return object_complete (uk , rb_ary_new ());
420
500
}
421
- return _msgpack_unpacker_stack_push (uk , STACK_TYPE_ARRAY , count , rb_ary_new2 ( initial_buffer_size ( count )) );
501
+ return _msgpack_unpacker_stack_push (uk , STACK_TYPE_ARRAY , count );
422
502
423
503
SWITCH_RANGE (b , 0x80 , 0x8f ) // FixMap
424
504
int count = b & 0x0f ;
425
505
if (count == 0 ) {
426
506
return object_complete (uk , rb_hash_new ());
427
507
}
428
- return _msgpack_unpacker_stack_push (uk , STACK_TYPE_MAP_KEY , count * 2 , rb_hash_new_capa ( initial_buffer_size ( count )) );
508
+ return _msgpack_unpacker_stack_push (uk , STACK_TYPE_MAP , count * 2 );
429
509
430
510
SWITCH_RANGE (b , 0xc0 , 0xdf ) // Variable
431
511
switch (b ) {
@@ -648,7 +728,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
648
728
if (count == 0 ) {
649
729
return object_complete (uk , rb_ary_new ());
650
730
}
651
- return _msgpack_unpacker_stack_push (uk , STACK_TYPE_ARRAY , count , rb_ary_new2 ( initial_buffer_size ( count )) );
731
+ return _msgpack_unpacker_stack_push (uk , STACK_TYPE_ARRAY , count );
652
732
}
653
733
654
734
case 0xdd : // array 32
@@ -658,7 +738,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
658
738
if (count == 0 ) {
659
739
return object_complete (uk , rb_ary_new ());
660
740
}
661
- return _msgpack_unpacker_stack_push (uk , STACK_TYPE_ARRAY , count , rb_ary_new2 ( initial_buffer_size ( count )) );
741
+ return _msgpack_unpacker_stack_push (uk , STACK_TYPE_ARRAY , count );
662
742
}
663
743
664
744
case 0xde : // map 16
@@ -668,7 +748,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
668
748
if (count == 0 ) {
669
749
return object_complete (uk , rb_hash_new ());
670
750
}
671
- return _msgpack_unpacker_stack_push (uk , STACK_TYPE_MAP_KEY , count * 2 , rb_hash_new_capa ( initial_buffer_size ( count )) );
751
+ return _msgpack_unpacker_stack_push (uk , STACK_TYPE_MAP , count * 2 );
672
752
}
673
753
674
754
case 0xdf : // map 32
@@ -678,7 +758,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
678
758
if (count == 0 ) {
679
759
return object_complete (uk , rb_hash_new ());
680
760
}
681
- return _msgpack_unpacker_stack_push (uk , STACK_TYPE_MAP_KEY , count * 2 , rb_hash_new_capa ( initial_buffer_size ( count )) );
761
+ return _msgpack_unpacker_stack_push (uk , STACK_TYPE_MAP , count * 2 );
682
762
}
683
763
684
764
default :
@@ -766,28 +846,23 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
766
846
container_completed :
767
847
{
768
848
msgpack_unpacker_stack_entry_t * top = _msgpack_unpacker_stack_entry_top (uk );
769
- switch (top -> type ) {
770
- case STACK_TYPE_ARRAY :
771
- rb_ary_push (top -> object , uk -> last_object );
772
- break ;
773
- case STACK_TYPE_MAP_KEY :
774
- top -> key = uk -> last_object ;
775
- top -> type = STACK_TYPE_MAP_VALUE ;
776
- break ;
777
- case STACK_TYPE_MAP_VALUE :
778
- if (uk -> symbolize_keys && rb_type (top -> key ) == T_STRING ) {
779
- /* here uses rb_str_intern instead of rb_intern so that Ruby VM can GC unused symbols */
780
- rb_hash_aset (top -> object , rb_str_intern (top -> key ), uk -> last_object );
781
- } else {
782
- rb_hash_aset (top -> object , top -> key , uk -> last_object );
783
- }
784
- top -> type = STACK_TYPE_MAP_KEY ;
785
- break ;
786
- }
787
849
size_t count = -- top -> count ;
788
850
789
851
if (count == 0 ) {
790
- object_complete (uk , top -> object );
852
+ switch (top -> type ) {
853
+ case STACK_TYPE_ARRAY :
854
+ _msgpack_unpacker_rvalue_stack_create_array (uk , top -> size );
855
+ break ;
856
+ case STACK_TYPE_MAP :
857
+ _msgpack_unpacker_rvalue_stack_create_hash (uk , top -> size );
858
+ break ;
859
+ case STACK_TYPE_RECURSIVE :
860
+ object_complete (uk , _msgpack_unpacker_rvalue_stack_pop (uk ));
861
+ return PRIMITIVE_OBJECT_COMPLETE ;
862
+ break ;
863
+ }
864
+
865
+ object_complete (uk , _msgpack_unpacker_rvalue_stack_pop (uk ));
791
866
if (msgpack_unpacker_stack_pop (uk ) <= target_stack_depth ) {
792
867
return PRIMITIVE_OBJECT_COMPLETE ;
793
868
}
0 commit comments