2828
2929static int RAW_TYPE_STRING = 256 ;
3030static int RAW_TYPE_BINARY = 257 ;
31- static int16_t INITIAL_BUFFER_CAPACITY_MAX = SHRT_MAX ;
3231
3332static msgpack_rmem_t s_stack_rmem ;
3433
@@ -39,9 +38,98 @@ static inline VALUE rb_hash_new_capa(long capa)
3938}
4039#endif
4140
42- static inline int16_t initial_buffer_size (long size )
41+ /* rvalue_stack functions */
42+
43+ static inline void _msgpack_unpacker_rvalue_stack_free (msgpack_rvalue_stack_t * value_stack ) {
44+ switch (value_stack -> type ) {
45+ case STACK_TYPE_UNALLOCATED :
46+ break ;
47+ case STACK_TYPE_RMEM :
48+ if (!msgpack_rmem_free (& s_stack_rmem , value_stack -> data )) {
49+ rb_bug ("Failed to free an rmem pointer, memory leak?" );
50+ }
51+ break ;
52+ case STACK_TYPE_HEAP :
53+ xfree (value_stack -> data );
54+ break ;
55+ }
56+ memset (value_stack , 0 , sizeof (msgpack_rvalue_stack_t ));
57+ }
58+
59+ static void _msgpack_unpacker_rvalue_stack_grow (msgpack_rvalue_stack_t * value_stack ) {
60+ switch (value_stack -> type ) {
61+ case STACK_TYPE_UNALLOCATED : {
62+ value_stack -> data = msgpack_rmem_alloc (& s_stack_rmem );
63+ value_stack -> capacity = MSGPACK_RMEM_PAGE_SIZE / sizeof (VALUE );
64+ value_stack -> type = STACK_TYPE_RMEM ;
65+ break ;
66+ }
67+ case STACK_TYPE_RMEM : {
68+ size_t new_capacity = value_stack -> capacity * 2 ;
69+ VALUE * new_ptr = ALLOC_N (VALUE , new_capacity );
70+ MEMCPY (new_ptr , value_stack -> data , VALUE , value_stack -> depth );
71+ if (!msgpack_rmem_free (& s_stack_rmem , value_stack -> data )) {
72+ rb_bug ("Failed to free an rmem pointer, memory leak?" );
73+ }
74+ value_stack -> type = STACK_TYPE_HEAP ;
75+ value_stack -> data = new_ptr ;
76+ value_stack -> capacity = new_capacity ;
77+ break ;
78+ }
79+ case STACK_TYPE_HEAP : {
80+ size_t new_capacity = value_stack -> capacity * 2 ;
81+ REALLOC_N (value_stack -> data , VALUE , new_capacity );
82+ value_stack -> capacity = new_capacity ;
83+ break ;
84+ }
85+ }
86+ }
87+
88+ static inline void _msgpack_unpacker_rvalue_stack_push (msgpack_unpacker_t * uk , VALUE value ) {
89+ size_t free_slots = uk -> value_stack .capacity - uk -> value_stack .depth ;
90+
91+ if (RB_UNLIKELY (free_slots == 0 )) {
92+ _msgpack_unpacker_rvalue_stack_grow (& uk -> value_stack );
93+ free_slots = uk -> value_stack .capacity - uk -> value_stack .depth ;
94+ }
95+
96+ RB_OBJ_WRITE (uk -> self , & uk -> value_stack .data [uk -> value_stack .depth ++ ], value );
97+ }
98+
99+ // static inline VALUE _msgpack_unpacker_rvalue_stack_top(msgpack_unpacker_t* uk)
100+ // {
101+ // return uk->value_stack.data[uk->value_stack.depth - 1];
102+ // }
103+
104+ static inline VALUE _msgpack_unpacker_rvalue_stack_create_array (msgpack_unpacker_t * uk , size_t length ) {
105+ VALUE * data = & uk -> value_stack .data [uk -> value_stack .depth - length ];
106+
107+ VALUE array = rb_ary_new_from_values (length , data );
108+
109+ RB_OBJ_WRITE (uk -> self , data , array );
110+ uk -> value_stack .depth -= (length - 1 );
111+
112+ return RB_GC_GUARD (array );
113+ }
114+
115+ static inline VALUE _msgpack_unpacker_rvalue_stack_create_hash (msgpack_unpacker_t * uk , size_t items_count ) {
116+ size_t length = items_count / 2 ;
117+ VALUE * data = & uk -> value_stack .data [uk -> value_stack .depth - items_count ];
118+
119+ VALUE hash = rb_hash_new_capa (length );
120+ rb_hash_bulk_insert (items_count , data , hash );
121+
122+ RB_OBJ_WRITE (uk -> self , data , hash );
123+ uk -> value_stack .depth -= (items_count - 1 );
124+
125+ return RB_GC_GUARD (hash );
126+ }
127+
128+ void msgpack_unpacker_mark_rvalue_stack (msgpack_rvalue_stack_t * value_stack )
43129{
44- return (size > INITIAL_BUFFER_CAPACITY_MAX ) ? INITIAL_BUFFER_CAPACITY_MAX : size ;
130+ if (value_stack -> data ) {
131+ rb_gc_mark_locations (value_stack -> data , value_stack -> data + value_stack -> depth );
132+ }
45133}
46134
47135void msgpack_unpacker_static_init (void )
@@ -88,27 +176,15 @@ static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack)
88176void _msgpack_unpacker_destroy (msgpack_unpacker_t * uk )
89177{
90178 _msgpack_unpacker_free_stack (uk -> stack );
179+ _msgpack_unpacker_rvalue_stack_free (& uk -> value_stack );
91180 msgpack_buffer_destroy (UNPACKER_BUFFER_ (uk ));
92181}
93182
94- void msgpack_unpacker_mark_stack (msgpack_unpacker_stack_t * stack )
95- {
96- while (stack ) {
97- msgpack_unpacker_stack_entry_t * s = stack -> data ;
98- msgpack_unpacker_stack_entry_t * send = stack -> data + stack -> depth ;
99- for (; s < send ; s ++ ) {
100- rb_gc_mark (s -> object );
101- rb_gc_mark (s -> key );
102- }
103- stack = stack -> parent ;
104- }
105- }
106-
107183void msgpack_unpacker_mark (msgpack_unpacker_t * uk )
108184{
109185 rb_gc_mark (uk -> last_object );
110186 rb_gc_mark (uk -> reading_raw );
111- msgpack_unpacker_mark_stack ( uk -> stack );
187+ msgpack_unpacker_mark_rvalue_stack ( & uk -> value_stack );
112188 /* See MessagePack_Buffer_wrap */
113189 /* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
114190 rb_gc_mark (uk -> buffer_ref );
@@ -160,13 +236,15 @@ static inline int object_complete(msgpack_unpacker_t* uk, VALUE object)
160236 }
161237
162238 uk -> last_object = object ;
239+ _msgpack_unpacker_rvalue_stack_push (uk , object );
163240 reset_head_byte (uk );
164241 return PRIMITIVE_OBJECT_COMPLETE ;
165242}
166243
167244static inline int object_complete_symbol (msgpack_unpacker_t * uk , VALUE object )
168245{
169246 uk -> last_object = object ;
247+ _msgpack_unpacker_rvalue_stack_push (uk , object );
170248 reset_head_byte (uk );
171249 return PRIMITIVE_OBJECT_COMPLETE ;
172250}
@@ -204,7 +282,7 @@ static inline msgpack_unpacker_stack_entry_t* _msgpack_unpacker_stack_entry_top(
204282 return & uk -> stack -> data [uk -> stack -> depth - 1 ];
205283}
206284
207- static inline int _msgpack_unpacker_stack_push (msgpack_unpacker_t * uk , enum stack_type_t type , size_t count , VALUE object )
285+ static inline int _msgpack_unpacker_stack_push (msgpack_unpacker_t * uk , enum stack_type_t type , size_t count )
208286{
209287 reset_head_byte (uk );
210288
@@ -214,22 +292,20 @@ static inline int _msgpack_unpacker_stack_push(msgpack_unpacker_t* uk, enum stac
214292
215293 msgpack_unpacker_stack_entry_t * next = & uk -> stack -> data [uk -> stack -> depth ];
216294 next -> count = count ;
295+ next -> size = count ;
217296 next -> type = type ;
218- next -> object = object ;
219- next -> key = Qnil ;
220-
221297 uk -> stack -> depth ++ ;
222298 return PRIMITIVE_CONTAINER_START ;
223299}
224300
225- static inline VALUE msgpack_unpacker_stack_pop (msgpack_unpacker_t * uk )
301+ static inline size_t msgpack_unpacker_stack_pop (msgpack_unpacker_t * uk )
226302{
227303 return -- uk -> stack -> depth ;
228304}
229305
230306static inline bool msgpack_unpacker_stack_is_empty (msgpack_unpacker_t * uk )
231307{
232- return uk -> stack -> depth == 0 ;
308+ return uk -> stack -> depth == 0 || _msgpack_unpacker_stack_entry_top ( uk ) -> type == STACK_TYPE_RECURSIVE ;
233309}
234310
235311#ifdef USE_CASE_RANGE
@@ -259,9 +335,7 @@ static inline bool is_reading_map_key(msgpack_unpacker_t* uk)
259335{
260336 if (uk -> stack -> depth > 0 ) {
261337 msgpack_unpacker_stack_entry_t * top = _msgpack_unpacker_stack_entry_top (uk );
262- if (top -> type == STACK_TYPE_MAP_KEY ) {
263- return true;
264- }
338+ return top -> type == STACK_TYPE_MAP && (top -> count % 2 == 0 );
265339 }
266340 return false;
267341}
@@ -312,14 +386,9 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
312386 reset_head_byte (uk );
313387 uk -> reading_raw_remaining = 0 ;
314388
315- msgpack_unpacker_stack_t * child_stack = _msgpack_unpacker_new_stack ();
316- child_stack -> parent = uk -> stack ;
317- uk -> stack = child_stack ;
318-
389+ _msgpack_unpacker_stack_push (uk , STACK_TYPE_RECURSIVE , 1 );
319390 obj = rb_proc_call_with_block (proc , 1 , & uk -> self , Qnil );
320-
321- uk -> stack = child_stack -> parent ;
322- _msgpack_unpacker_free_stack (child_stack );
391+ msgpack_unpacker_stack_pop (uk );
323392
324393 return object_complete (uk , obj );
325394 }
@@ -382,14 +451,14 @@ static int read_primitive(msgpack_unpacker_t* uk)
382451 if (count == 0 ) {
383452 return object_complete (uk , rb_ary_new ());
384453 }
385- return _msgpack_unpacker_stack_push (uk , STACK_TYPE_ARRAY , count , rb_ary_new2 ( initial_buffer_size ( count )) );
454+ return _msgpack_unpacker_stack_push (uk , STACK_TYPE_ARRAY , count );
386455
387456 SWITCH_RANGE (b , 0x80 , 0x8f ) // FixMap
388457 int count = b & 0x0f ;
389458 if (count == 0 ) {
390459 return object_complete (uk , rb_hash_new ());
391460 }
392- return _msgpack_unpacker_stack_push (uk , STACK_TYPE_MAP_KEY , count * 2 , rb_hash_new_capa ( initial_buffer_size ( count )) );
461+ return _msgpack_unpacker_stack_push (uk , STACK_TYPE_MAP , count * 2 );
393462
394463 SWITCH_RANGE (b , 0xc0 , 0xdf ) // Variable
395464 switch (b ) {
@@ -612,7 +681,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
612681 if (count == 0 ) {
613682 return object_complete (uk , rb_ary_new ());
614683 }
615- return _msgpack_unpacker_stack_push (uk , STACK_TYPE_ARRAY , count , rb_ary_new2 ( initial_buffer_size ( count )) );
684+ return _msgpack_unpacker_stack_push (uk , STACK_TYPE_ARRAY , count );
616685 }
617686
618687 case 0xdd : // array 32
@@ -622,7 +691,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
622691 if (count == 0 ) {
623692 return object_complete (uk , rb_ary_new ());
624693 }
625- return _msgpack_unpacker_stack_push (uk , STACK_TYPE_ARRAY , count , rb_ary_new2 ( initial_buffer_size ( count )) );
694+ return _msgpack_unpacker_stack_push (uk , STACK_TYPE_ARRAY , count );
626695 }
627696
628697 case 0xde : // map 16
@@ -632,7 +701,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
632701 if (count == 0 ) {
633702 return object_complete (uk , rb_hash_new ());
634703 }
635- return _msgpack_unpacker_stack_push (uk , STACK_TYPE_MAP_KEY , count * 2 , rb_hash_new_capa ( initial_buffer_size ( count )) );
704+ return _msgpack_unpacker_stack_push (uk , STACK_TYPE_MAP , count * 2 );
636705 }
637706
638707 case 0xdf : // map 32
@@ -642,7 +711,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
642711 if (count == 0 ) {
643712 return object_complete (uk , rb_hash_new ());
644713 }
645- return _msgpack_unpacker_stack_push (uk , STACK_TYPE_MAP_KEY , count * 2 , rb_hash_new_capa ( initial_buffer_size ( count )) );
714+ return _msgpack_unpacker_stack_push (uk , STACK_TYPE_MAP , count * 2 );
646715 }
647716
648717 default :
@@ -730,28 +799,23 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
730799 container_completed :
731800 {
732801 msgpack_unpacker_stack_entry_t * top = _msgpack_unpacker_stack_entry_top (uk );
733- switch (top -> type ) {
734- case STACK_TYPE_ARRAY :
735- rb_ary_push (top -> object , uk -> last_object );
736- break ;
737- case STACK_TYPE_MAP_KEY :
738- top -> key = uk -> last_object ;
739- top -> type = STACK_TYPE_MAP_VALUE ;
740- break ;
741- case STACK_TYPE_MAP_VALUE :
742- if (uk -> symbolize_keys && rb_type (top -> key ) == T_STRING ) {
743- /* here uses rb_str_intern instead of rb_intern so that Ruby VM can GC unused symbols */
744- rb_hash_aset (top -> object , rb_str_intern (top -> key ), uk -> last_object );
745- } else {
746- rb_hash_aset (top -> object , top -> key , uk -> last_object );
747- }
748- top -> type = STACK_TYPE_MAP_KEY ;
749- break ;
750- }
751802 size_t count = -- top -> count ;
752803
753804 if (count == 0 ) {
754- object_complete (uk , top -> object );
805+ switch (top -> type ) {
806+ case STACK_TYPE_ARRAY :
807+ _msgpack_unpacker_rvalue_stack_create_array (uk , top -> size );
808+ break ;
809+ case STACK_TYPE_MAP :
810+ _msgpack_unpacker_rvalue_stack_create_hash (uk , top -> size );
811+ break ;
812+ case STACK_TYPE_RECURSIVE :
813+ object_complete (uk , _msgpack_unpacker_rvalue_stack_pop (uk ));
814+ return PRIMITIVE_OBJECT_COMPLETE ;
815+ break ;
816+ }
817+
818+ object_complete (uk , _msgpack_unpacker_rvalue_stack_pop (uk ));
755819 if (msgpack_unpacker_stack_pop (uk ) <= target_stack_depth ) {
756820 return PRIMITIVE_OBJECT_COMPLETE ;
757821 }
0 commit comments