msgpack 1.6.1 → 1.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,19 +1,23 @@
1
1
  require 'mkmf'
2
2
 
3
- have_header("ruby/st.h")
4
- have_header("st.h")
5
3
  have_func("rb_enc_interned_str", "ruby.h") # Ruby 3.0+
6
4
  have_func("rb_hash_new_capa", "ruby.h") # Ruby 3.2+
5
+ have_func("rb_proc_call_with_block", "ruby.h") # CRuby (TruffleRuby doesn't have it)
7
6
 
8
- $CFLAGS << " -fvisibility=hidden "
7
+ append_cflags([
8
+ "-fvisibility=hidden",
9
+ "-I..",
10
+ "-Wall",
11
+ "-O3",
12
+ "-std=gnu99"
13
+ ])
14
+ append_cflags(RbConfig::CONFIG["debugflags"]) if RbConfig::CONFIG["debugflags"]
9
15
 
10
- unless RUBY_PLATFORM.include? 'mswin'
11
- $CFLAGS << %[ -I.. -Wall -O3 #{RbConfig::CONFIG["debugflags"]} -std=gnu99]
12
- end
16
+ append_cflags("-DRUBY_DEBUG=1") if ENV["MSGPACK_DEBUG"]
13
17
 
14
18
  if RUBY_VERSION.start_with?('3.0.') && RUBY_VERSION <= '3.0.5'
15
19
  # https://bugs.ruby-lang.org/issues/18772
16
- $CFLAGS << ' -DRB_ENC_INTERNED_STR_NULL_CHECK=1 '
20
+ append_cflags("-DRB_ENC_INTERNED_STR_NULL_CHECK=1")
17
21
  end
18
22
 
19
23
  # checking if Hash#[]= (rb_hash_aset) dedupes string keys (Ruby 2.6+)
@@ -23,35 +27,21 @@ r = rand.to_s
23
27
  h[%W(#{r}).join('')] = :foo
24
28
  x[%W(#{r}).join('')] = :foo
25
29
  if x.keys[0].equal?(h.keys[0])
26
- $CFLAGS << ' -DHASH_ASET_DEDUPE=1 '
30
+ append_cflags("-DHASH_ASET_DEDUPE=1")
27
31
  else
28
- $CFLAGS << ' -DHASH_ASET_DEDUPE=0 '
29
- end
30
-
31
-
32
- # checking if String#-@ (str_uminus) dedupes... ' (Ruby 2.5+)
33
- begin
34
- a = -(%w(t e s t).join)
35
- b = -(%w(t e s t).join)
36
- if a.equal?(b)
37
- $CFLAGS << ' -DSTR_UMINUS_DEDUPE=1 '
38
- else
39
- $CFLAGS += ' -DSTR_UMINUS_DEDUPE=0 '
40
- end
41
- rescue NoMethodError
42
- $CFLAGS << ' -DSTR_UMINUS_DEDUPE=0 '
32
+ append_cflags("-DHASH_ASET_DEDUPE=0")
43
33
  end
44
34
 
45
35
  # checking if String#-@ (str_uminus) directly interns frozen strings... ' (Ruby 3.0+)
46
36
  begin
47
37
  s = rand.to_s.freeze
48
38
  if (-s).equal?(s) && (-s.dup).equal?(s)
49
- $CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=1 '
39
+ append_cflags("-DSTR_UMINUS_DEDUPE_FROZEN=1")
50
40
  else
51
- $CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=0 '
41
+ append_cflags("-DSTR_UMINUS_DEDUPE_FROZEN=0")
52
42
  end
53
43
  rescue NoMethodError
54
- $CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=0 '
44
+ append_cflags("-DSTR_UMINUS_DEDUPE_FROZEN=0")
55
45
  end
56
46
 
57
47
  if warnflags = CONFIG['warnflags']
@@ -75,7 +75,7 @@ static const rb_data_type_t factory_data_type = {
75
75
  .dfree = Factory_free,
76
76
  .dsize = Factory_memsize,
77
77
  },
78
- .flags = RUBY_TYPED_FREE_IMMEDIATELY
78
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
79
79
  };
80
80
 
81
81
  static inline msgpack_factory_t *Factory_get(VALUE object)
@@ -98,7 +98,7 @@ static VALUE Factory_initialize(int argc, VALUE* argv, VALUE self)
98
98
  {
99
99
  msgpack_factory_t *fc = Factory_get(self);
100
100
 
101
- msgpack_packer_ext_registry_init(&fc->pkrg);
101
+ msgpack_packer_ext_registry_init(self, &fc->pkrg);
102
102
  // fc->ukrg is lazily initialized
103
103
 
104
104
  fc->has_symbol_ext_type = false;
@@ -124,7 +124,7 @@ static VALUE Factory_dup(VALUE self)
124
124
  cloned_fc->has_symbol_ext_type = fc->has_symbol_ext_type;
125
125
  cloned_fc->pkrg = fc->pkrg;
126
126
  msgpack_unpacker_ext_registry_borrow(fc->ukrg, &cloned_fc->ukrg);
127
- msgpack_packer_ext_registry_dup(&fc->pkrg, &cloned_fc->pkrg);
127
+ msgpack_packer_ext_registry_dup(clone, &fc->pkrg, &cloned_fc->pkrg);
128
128
 
129
129
  return clone;
130
130
  }
@@ -139,7 +139,7 @@ static VALUE Factory_freeze(VALUE self) {
139
139
  // If the factory is frozen, we can safely share the packer cache between
140
140
  // all packers. So we eagerly create it now so it's available when #packer
141
141
  // is called.
142
- fc->pkrg.cache = rb_hash_new();
142
+ RB_OBJ_WRITE(self, &fc->pkrg.cache, rb_hash_new());
143
143
  }
144
144
  }
145
145
 
@@ -158,7 +158,7 @@ VALUE MessagePack_Factory_packer(int argc, VALUE* argv, VALUE self)
158
158
 
159
159
  msgpack_packer_t* pk = MessagePack_Packer_get(packer);
160
160
  msgpack_packer_ext_registry_destroy(&pk->ext_registry);
161
- msgpack_packer_ext_registry_dup(&fc->pkrg, &pk->ext_registry);
161
+ msgpack_packer_ext_registry_borrow(packer, &fc->pkrg, &pk->ext_registry);
162
162
  pk->has_bigint_ext_type = fc->has_bigint_ext_type;
163
163
  pk->has_symbol_ext_type = fc->has_symbol_ext_type;
164
164
 
@@ -187,7 +187,7 @@ static VALUE Factory_registered_types_internal(VALUE self)
187
187
  VALUE uk_mapping = rb_hash_new();
188
188
  if (fc->ukrg) {
189
189
  for(int i=0; i < 256; i++) {
190
- if(fc->ukrg->array[i] != Qnil) {
190
+ if(!NIL_P(fc->ukrg->array[i])) {
191
191
  rb_hash_aset(uk_mapping, INT2FIX(i - 128), fc->ukrg->array[i]);
192
192
  }
193
193
  }
@@ -200,73 +200,39 @@ static VALUE Factory_registered_types_internal(VALUE self)
200
200
  );
201
201
  }
202
202
 
203
- static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
203
+ static VALUE Factory_register_type_internal(VALUE self, VALUE rb_ext_type, VALUE ext_module, VALUE options)
204
204
  {
205
205
  msgpack_factory_t *fc = Factory_get(self);
206
206
 
207
- int ext_type;
208
- int flags = 0;
209
- VALUE ext_module;
210
- VALUE options = Qnil;
211
- VALUE packer_arg, unpacker_arg;
212
- VALUE packer_proc, unpacker_proc;
207
+ Check_Type(rb_ext_type, T_FIXNUM);
213
208
 
214
- if (OBJ_FROZEN(self)) {
215
- rb_raise(rb_eRuntimeError, "can't modify frozen Factory");
209
+ if(rb_type(ext_module) != T_MODULE && rb_type(ext_module) != T_CLASS) {
210
+ rb_raise(rb_eArgError, "expected Module/Class but found %s.", rb_obj_classname(ext_module));
216
211
  }
217
212
 
218
- switch (argc) {
219
- case 2:
220
- /* register_type(0x7f, Time) */
221
- packer_arg = ID2SYM(rb_intern("to_msgpack_ext"));
222
- unpacker_arg = ID2SYM(rb_intern("from_msgpack_ext"));
223
- break;
224
- case 3:
225
- /* register_type(0x7f, Time, packer: proc-like, unapcker: proc-like) */
226
- options = argv[2];
227
- if(rb_type(options) != T_HASH) {
228
- rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
229
- }
230
- packer_arg = rb_hash_aref(options, ID2SYM(rb_intern("packer")));
231
- unpacker_arg = rb_hash_aref(options, ID2SYM(rb_intern("unpacker")));
232
- break;
233
- default:
234
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..3)", argc);
235
- }
213
+ int flags = 0;
236
214
 
237
- if (options != Qnil) {
215
+ VALUE packer_proc = Qnil;
216
+ VALUE unpacker_proc = Qnil;
217
+ if(!NIL_P(options)) {
238
218
  Check_Type(options, T_HASH);
219
+ packer_proc = rb_hash_aref(options, ID2SYM(rb_intern("packer")));
220
+ unpacker_proc = rb_hash_aref(options, ID2SYM(rb_intern("unpacker")));
239
221
  }
240
222
 
241
- ext_type = NUM2INT(argv[0]);
242
- if(ext_type < -128 || ext_type > 127) {
243
- rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
244
- }
245
-
246
- ext_module = argv[1];
247
- if(rb_type(ext_module) != T_MODULE && rb_type(ext_module) != T_CLASS) {
248
- rb_raise(rb_eArgError, "expected Module/Class but found %s.", rb_obj_classname(ext_module));
249
- }
250
-
251
- packer_proc = Qnil;
252
- unpacker_proc = Qnil;
253
-
254
- if(packer_arg != Qnil) {
255
- packer_proc = rb_funcall(packer_arg, rb_intern("to_proc"), 0);
223
+ if (OBJ_FROZEN(self)) {
224
+ rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Factory");
256
225
  }
257
226
 
258
- if(unpacker_arg != Qnil) {
259
- if(rb_type(unpacker_arg) == T_SYMBOL || rb_type(unpacker_arg) == T_STRING) {
260
- unpacker_proc = rb_obj_method(ext_module, unpacker_arg);
261
- } else if (rb_respond_to(unpacker_arg, rb_intern("call"))) {
262
- unpacker_proc = unpacker_arg;
263
- } else {
264
- unpacker_proc = rb_funcall(unpacker_arg, rb_intern("method"), 1, ID2SYM(rb_intern("call")));
265
- }
227
+ int ext_type = NUM2INT(rb_ext_type);
228
+ if(ext_type < -128 || ext_type > 127) {
229
+ rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
266
230
  }
267
231
 
268
232
  if(ext_module == rb_cSymbol) {
269
- fc->has_symbol_ext_type = true;
233
+ if(NIL_P(options) || RTEST(rb_hash_aref(options, ID2SYM(rb_intern("packer"))))) {
234
+ fc->has_symbol_ext_type = true;
235
+ }
270
236
  if(RTEST(options) && RTEST(rb_hash_aref(options, ID2SYM(rb_intern("optimized_symbols_parsing"))))) {
271
237
  fc->optimized_symbol_ext_type = true;
272
238
  }
@@ -286,8 +252,8 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
286
252
  }
287
253
  }
288
254
 
289
- msgpack_packer_ext_registry_put(&fc->pkrg, ext_module, ext_type, flags, packer_proc, packer_arg);
290
- msgpack_unpacker_ext_registry_put(&fc->ukrg, ext_module, ext_type, flags, unpacker_proc, unpacker_arg);
255
+ msgpack_packer_ext_registry_put(self, &fc->pkrg, ext_module, ext_type, flags, packer_proc);
256
+ msgpack_unpacker_ext_registry_put(self, &fc->ukrg, ext_module, ext_type, flags, unpacker_proc);
291
257
 
292
258
  return Qnil;
293
259
  }
@@ -306,5 +272,5 @@ void MessagePack_Factory_module_init(VALUE mMessagePack)
306
272
  rb_define_method(cMessagePack_Factory, "unpacker", MessagePack_Factory_unpacker, -1);
307
273
 
308
274
  rb_define_private_method(cMessagePack_Factory, "registered_types_internal", Factory_registered_types_internal, 0);
309
- rb_define_method(cMessagePack_Factory, "register_type", Factory_register_type, -1);
275
+ rb_define_private_method(cMessagePack_Factory, "register_type_internal", Factory_register_type_internal, 3);
310
276
  }
data/ext/msgpack/packer.c CHANGED
@@ -17,16 +17,11 @@
17
17
  */
18
18
 
19
19
  #include "packer.h"
20
+ #include "buffer_class.h"
20
21
 
21
- static ID s_call;
22
-
23
- void msgpack_packer_static_init(void)
24
- {
25
- s_call = rb_intern("call");
26
- }
27
-
28
- void msgpack_packer_static_destroy(void)
29
- { }
22
+ #if !defined(HAVE_RB_PROC_CALL_WITH_BLOCK)
23
+ #define rb_proc_call_with_block(recv, argc, argv, block) rb_funcallv(recv, rb_intern("call"), argc, argv)
24
+ #endif
30
25
 
31
26
  void msgpack_packer_init(msgpack_packer_t* pk)
32
27
  {
@@ -100,14 +95,13 @@ struct msgpack_call_proc_args_t;
100
95
  typedef struct msgpack_call_proc_args_t msgpack_call_proc_args_t;
101
96
  struct msgpack_call_proc_args_t {
102
97
  VALUE proc;
103
- VALUE arg;
104
- VALUE packer;
98
+ VALUE args[2];
105
99
  };
106
100
 
107
101
  VALUE msgpack_packer_try_calling_proc(VALUE value)
108
102
  {
109
103
  msgpack_call_proc_args_t *args = (msgpack_call_proc_args_t *)value;
110
- return rb_funcall(args->proc, s_call, 2, args->arg, args->packer);
104
+ return rb_proc_call_with_block(args->proc, 2, args->args, Qnil);
111
105
  }
112
106
 
113
107
  bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v)
@@ -121,11 +115,13 @@ bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v
121
115
  }
122
116
 
123
117
  if(ext_flags & MSGPACK_EXT_RECURSIVE) {
118
+ VALUE held_buffer = MessagePack_Buffer_hold(&pk->buffer);
119
+
124
120
  msgpack_buffer_t parent_buffer = pk->buffer;
125
121
  msgpack_buffer_init(PACKER_BUFFER_(pk));
126
122
 
127
123
  int exception_occured = 0;
128
- msgpack_call_proc_args_t args = { proc, v, pk->to_msgpack_arg };
124
+ msgpack_call_proc_args_t args = { proc, { v, pk->to_msgpack_arg } };
129
125
  rb_protect(msgpack_packer_try_calling_proc, (VALUE)&args, &exception_occured);
130
126
 
131
127
  if (exception_occured) {
@@ -139,8 +135,10 @@ bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v
139
135
  pk->buffer = parent_buffer;
140
136
  msgpack_packer_write_ext(pk, ext_type, payload);
141
137
  }
138
+
139
+ RB_GC_GUARD(held_buffer);
142
140
  } else {
143
- VALUE payload = rb_funcall(proc, s_call, 1, v);
141
+ VALUE payload = rb_proc_call_with_block(proc, 1, &v, Qnil);
144
142
  StringValue(payload);
145
143
  msgpack_packer_write_ext(pk, ext_type, payload);
146
144
  }
data/ext/msgpack/packer.h CHANGED
@@ -47,10 +47,6 @@ struct msgpack_packer_t {
47
47
 
48
48
  #define PACKER_BUFFER_(pk) (&(pk)->buffer)
49
49
 
50
- void msgpack_packer_static_init(void);
51
-
52
- void msgpack_packer_static_destroy(void);
53
-
54
50
  void msgpack_packer_init(msgpack_packer_t* pk);
55
51
 
56
52
  void msgpack_packer_destroy(msgpack_packer_t* pk);
@@ -106,8 +106,8 @@ VALUE MessagePack_Packer_initialize(int argc, VALUE* argv, VALUE self)
106
106
 
107
107
  msgpack_packer_t *pk = MessagePack_Packer_get(self);
108
108
 
109
- msgpack_packer_ext_registry_init(&pk->ext_registry);
110
- pk->buffer_ref = Qnil;
109
+ msgpack_packer_ext_registry_init(self, &pk->ext_registry);
110
+ pk->buffer_ref = MessagePack_Buffer_wrap(PACKER_BUFFER_(pk), self);
111
111
 
112
112
  MessagePack_Buffer_set_options(PACKER_BUFFER_(pk), io, options);
113
113
 
@@ -233,7 +233,12 @@ static VALUE Packer_write_extension(VALUE self, VALUE obj)
233
233
  msgpack_packer_t *pk = MessagePack_Packer_get(self);
234
234
  Check_Type(obj, T_STRUCT);
235
235
 
236
- int ext_type = FIX2INT(RSTRUCT_GET(obj, 0));
236
+ VALUE rb_ext_type = RSTRUCT_GET(obj, 0);
237
+ if(!RB_TYPE_P(rb_ext_type, T_FIXNUM)) {
238
+ rb_raise(rb_eRangeError, "integer %s too big to convert to `signed char'", RSTRING_PTR(rb_String(rb_ext_type)));
239
+ }
240
+
241
+ int ext_type = FIX2INT(rb_ext_type);
237
242
  if(ext_type < -128 || ext_type > 127) {
238
243
  rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
239
244
  }
@@ -347,42 +352,20 @@ static VALUE Packer_registered_types_internal(VALUE self)
347
352
  return rb_hash_new();
348
353
  }
349
354
 
350
- static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
355
+ static VALUE Packer_register_type_internal(VALUE self, VALUE rb_ext_type, VALUE ext_module, VALUE proc)
351
356
  {
352
- msgpack_packer_t *pk = MessagePack_Packer_get(self);
353
-
354
- int ext_type;
355
- VALUE ext_module;
356
- VALUE proc;
357
- VALUE arg;
358
-
359
- switch (argc) {
360
- case 2:
361
- /* register_type(0x7f, Time) {|obj| block... } */
362
- rb_need_block();
363
- proc = rb_block_lambda();
364
- arg = proc;
365
- break;
366
- case 3:
367
- /* register_type(0x7f, Time, :to_msgpack_ext) */
368
- arg = argv[2];
369
- proc = rb_funcall(arg, rb_intern("to_proc"), 0);
370
- break;
371
- default:
372
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..3)", argc);
357
+ if (OBJ_FROZEN(self)) {
358
+ rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Packer");
373
359
  }
374
360
 
375
- ext_type = NUM2INT(argv[0]);
361
+ msgpack_packer_t *pk = MessagePack_Packer_get(self);
362
+
363
+ int ext_type = NUM2INT(rb_ext_type);
376
364
  if(ext_type < -128 || ext_type > 127) {
377
365
  rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
378
366
  }
379
367
 
380
- ext_module = argv[1];
381
- if(rb_type(ext_module) != T_MODULE && rb_type(ext_module) != T_CLASS) {
382
- rb_raise(rb_eArgError, "expected Module/Class but found %s.", rb_obj_classname(ext_module));
383
- }
384
-
385
- msgpack_packer_ext_registry_put(&pk->ext_registry, ext_module, ext_type, 0, proc, arg);
368
+ msgpack_packer_ext_registry_put(self, &pk->ext_registry, ext_module, ext_type, 0, proc);
386
369
 
387
370
  if (ext_module == rb_cSymbol) {
388
371
  pk->has_symbol_ext_type = true;
@@ -415,10 +398,6 @@ void MessagePack_Packer_module_init(VALUE mMessagePack)
415
398
  s_write = rb_intern("write");
416
399
 
417
400
  sym_compatibility_mode = ID2SYM(rb_intern("compatibility_mode"));
418
-
419
- msgpack_packer_static_init();
420
- msgpack_packer_ext_registry_static_init();
421
-
422
401
  cMessagePack_Packer = rb_define_class_under(mMessagePack, "Packer", rb_cObject);
423
402
 
424
403
  rb_define_alloc_func(cMessagePack_Packer, MessagePack_Packer_alloc);
@@ -457,7 +436,7 @@ void MessagePack_Packer_module_init(VALUE mMessagePack)
457
436
  rb_define_method(cMessagePack_Packer, "to_a", Packer_to_a, 0);
458
437
 
459
438
  rb_define_private_method(cMessagePack_Packer, "registered_types_internal", Packer_registered_types_internal, 0);
460
- rb_define_method(cMessagePack_Packer, "register_type", Packer_register_type, -1);
439
+ rb_define_method(cMessagePack_Packer, "register_type_internal", Packer_register_type_internal, 3);
461
440
 
462
441
  rb_define_method(cMessagePack_Packer, "full_pack", Packer_full_pack, 0);
463
442
  }
@@ -18,20 +18,10 @@
18
18
 
19
19
  #include "packer_ext_registry.h"
20
20
 
21
- static ID s_call;
22
-
23
- void msgpack_packer_ext_registry_static_init(void)
24
- {
25
- s_call = rb_intern("call");
26
- }
27
-
28
- void msgpack_packer_ext_registry_static_destroy(void)
29
- { }
30
-
31
- void msgpack_packer_ext_registry_init(msgpack_packer_ext_registry_t* pkrg)
21
+ void msgpack_packer_ext_registry_init(VALUE owner, msgpack_packer_ext_registry_t* pkrg)
32
22
  {
33
- pkrg->hash = Qnil;
34
- pkrg->cache = Qnil;
23
+ RB_OBJ_WRITE(owner, &pkrg->hash, Qnil);
24
+ RB_OBJ_WRITE(owner, &pkrg->cache, Qnil);
35
25
  }
36
26
 
37
27
  void msgpack_packer_ext_registry_mark(msgpack_packer_ext_registry_t* pkrg)
@@ -40,32 +30,45 @@ void msgpack_packer_ext_registry_mark(msgpack_packer_ext_registry_t* pkrg)
40
30
  rb_gc_mark(pkrg->cache);
41
31
  }
42
32
 
43
- void msgpack_packer_ext_registry_dup(msgpack_packer_ext_registry_t* src,
33
+ void msgpack_packer_ext_registry_borrow(VALUE owner, msgpack_packer_ext_registry_t* src,
44
34
  msgpack_packer_ext_registry_t* dst)
45
35
  {
46
- if(RTEST(src->hash) && !rb_obj_frozen_p(src->hash)) {
47
- dst->hash = rb_hash_dup(src->hash);
48
- dst->cache = RTEST(src->cache) ? rb_hash_dup(src->cache) : Qnil;
36
+ if(RTEST(src->hash)) {
37
+ if(rb_obj_frozen_p(src->hash)) {
38
+ // If the type registry is frozen we can safely share it, and share the cache as well.
39
+ RB_OBJ_WRITE(owner, &dst->hash, src->hash);
40
+ RB_OBJ_WRITE(owner, &dst->cache, src->cache);
41
+ } else {
42
+ RB_OBJ_WRITE(owner, &dst->hash, rb_hash_dup(src->hash));
43
+ RB_OBJ_WRITE(owner, &dst->cache, NIL_P(src->cache) ? Qnil : rb_hash_dup(src->cache));
44
+ }
49
45
  } else {
50
- // If the type registry is frozen we can safely share it, and share the cache as well.
51
- dst->hash = src->hash;
52
- dst->cache = src->cache;
46
+ RB_OBJ_WRITE(owner, &dst->hash, Qnil);
47
+ RB_OBJ_WRITE(owner, &dst->cache, Qnil);
53
48
  }
54
49
  }
55
50
 
56
- VALUE msgpack_packer_ext_registry_put(msgpack_packer_ext_registry_t* pkrg,
57
- VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg)
51
+ void msgpack_packer_ext_registry_dup(VALUE owner, msgpack_packer_ext_registry_t* src,
52
+ msgpack_packer_ext_registry_t* dst)
58
53
  {
59
- if (!RTEST(pkrg->hash)) {
60
- pkrg->hash = rb_hash_new();
54
+ RB_OBJ_WRITE(owner, &dst->hash, NIL_P(src->hash) ? Qnil : rb_hash_dup(src->hash));
55
+ RB_OBJ_WRITE(owner, &dst->cache, NIL_P(src->cache) ? Qnil : rb_hash_dup(src->cache));
56
+ }
57
+
58
+ void msgpack_packer_ext_registry_put(VALUE owner, msgpack_packer_ext_registry_t* pkrg,
59
+ VALUE ext_module, int ext_type, int flags, VALUE proc)
60
+ {
61
+ if(NIL_P(pkrg->hash)) {
62
+ RB_OBJ_WRITE(owner, &pkrg->hash, rb_hash_new());
61
63
  }
62
64
 
63
- if (RTEST(pkrg->cache)) {
65
+ if(NIL_P(pkrg->cache)) {
66
+ RB_OBJ_WRITE(owner, &pkrg->cache, rb_hash_new());
67
+ } else {
64
68
  /* clear lookup cache not to miss added type */
65
69
  rb_hash_clear(pkrg->cache);
66
70
  }
67
71
 
68
- // TODO: Ruby embeded array limit is 3, merging `proc` and `arg` would be good.
69
- VALUE entry = rb_ary_new3(4, INT2FIX(ext_type), proc, arg, INT2FIX(flags));
70
- return rb_hash_aset(pkrg->hash, ext_module, entry);
72
+ VALUE entry = rb_ary_new3(3, INT2FIX(ext_type), proc, INT2FIX(flags));
73
+ rb_hash_aset(pkrg->hash, ext_module, entry);
71
74
  }
@@ -31,22 +31,21 @@ struct msgpack_packer_ext_registry_t {
31
31
  VALUE cache; // lookup cache for ext types inherited from a super class
32
32
  };
33
33
 
34
- void msgpack_packer_ext_registry_static_init(void);
35
-
36
- void msgpack_packer_ext_registry_static_destroy(void);
37
-
38
- void msgpack_packer_ext_registry_init(msgpack_packer_ext_registry_t* pkrg);
34
+ void msgpack_packer_ext_registry_init(VALUE owner, msgpack_packer_ext_registry_t* pkrg);
39
35
 
40
36
  static inline void msgpack_packer_ext_registry_destroy(msgpack_packer_ext_registry_t* pkrg)
41
37
  { }
42
38
 
43
39
  void msgpack_packer_ext_registry_mark(msgpack_packer_ext_registry_t* pkrg);
44
40
 
45
- void msgpack_packer_ext_registry_dup(msgpack_packer_ext_registry_t* src,
41
+ void msgpack_packer_ext_registry_borrow(VALUE owner, msgpack_packer_ext_registry_t* src,
46
42
  msgpack_packer_ext_registry_t* dst);
47
43
 
48
- VALUE msgpack_packer_ext_registry_put(msgpack_packer_ext_registry_t* pkrg,
49
- VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg);
44
+ void msgpack_packer_ext_registry_dup(VALUE owner, msgpack_packer_ext_registry_t* src,
45
+ msgpack_packer_ext_registry_t* dst);
46
+
47
+ void msgpack_packer_ext_registry_put(VALUE owner, msgpack_packer_ext_registry_t* pkrg,
48
+ VALUE ext_module, int ext_type, int flags, VALUE proc);
50
49
 
51
50
  static int msgpack_packer_ext_find_superclass(VALUE key, VALUE value, VALUE arg)
52
51
  {
@@ -68,7 +67,7 @@ static inline VALUE msgpack_packer_ext_registry_fetch(msgpack_packer_ext_registr
68
67
  VALUE type = rb_hash_lookup(pkrg->hash, lookup_class);
69
68
  if(type != Qnil) {
70
69
  *ext_type_result = FIX2INT(rb_ary_entry(type, 0));
71
- *ext_flags_result = FIX2INT(rb_ary_entry(type, 3));
70
+ *ext_flags_result = FIX2INT(rb_ary_entry(type, 2));
72
71
  return rb_ary_entry(type, 1);
73
72
  }
74
73
 
@@ -77,7 +76,7 @@ static inline VALUE msgpack_packer_ext_registry_fetch(msgpack_packer_ext_registr
77
76
  VALUE type_inht = rb_hash_lookup(pkrg->cache, lookup_class);
78
77
  if(type_inht != Qnil) {
79
78
  *ext_type_result = FIX2INT(rb_ary_entry(type_inht, 0));
80
- *ext_flags_result = FIX2INT(rb_ary_entry(type_inht, 3));
79
+ *ext_flags_result = FIX2INT(rb_ary_entry(type_inht, 2));
81
80
  return rb_ary_entry(type_inht, 1);
82
81
  }
83
82
  }
@@ -129,12 +128,9 @@ static inline VALUE msgpack_packer_ext_registry_lookup(msgpack_packer_ext_regist
129
128
  VALUE superclass = args[1];
130
129
  if(superclass != Qnil) {
131
130
  VALUE superclass_type = rb_hash_lookup(pkrg->hash, superclass);
132
- if (!RTEST(pkrg->cache)) {
133
- pkrg->cache = rb_hash_new();
134
- }
135
131
  rb_hash_aset(pkrg->cache, lookup_class, superclass_type);
136
132
  *ext_type_result = FIX2INT(rb_ary_entry(superclass_type, 0));
137
- *ext_flags_result = FIX2INT(rb_ary_entry(superclass_type, 3));
133
+ *ext_flags_result = FIX2INT(rb_ary_entry(superclass_type, 2));
138
134
  return rb_ary_entry(superclass_type, 1);
139
135
  }
140
136
 
data/ext/msgpack/rmem.c CHANGED
@@ -65,11 +65,10 @@ void* _msgpack_rmem_alloc2(msgpack_rmem_t* pm)
65
65
  /* allocate new chunk */
66
66
  c = pm->array_last++;
67
67
 
68
- /* move to head */
69
- msgpack_rmem_chunk_t tmp = pm->head;
70
- pm->head = *c;
71
- *c = tmp;
68
+ /* move head to array */
69
+ *c = pm->head;
72
70
 
71
+ pm->head.pages = NULL; /* make sure we don't point to another chunk's pages in case xmalloc triggers GC */
73
72
  pm->head.mask = 0xffffffff & (~1); /* "& (~1)" means first chunk is already allocated */
74
73
  pm->head.pages = xmalloc(MSGPACK_RMEM_PAGE_SIZE * 32);
75
74
 
@@ -19,20 +19,16 @@
19
19
  #include "unpacker.h"
20
20
  #include "rmem.h"
21
21
  #include "extension_value_class.h"
22
+ #include <assert.h>
22
23
 
23
- #if !defined(DISABLE_UNPACKER_STACK_RMEM) && \
24
- MSGPACK_UNPACKER_STACK_CAPACITY * MSGPACK_UNPACKER_STACK_SIZE <= MSGPACK_RMEM_PAGE_SIZE
25
- #define UNPACKER_STACK_RMEM
24
+ #if !defined(HAVE_RB_PROC_CALL_WITH_BLOCK)
25
+ #define rb_proc_call_with_block(recv, argc, argv, block) rb_funcallv(recv, rb_intern("call"), argc, argv)
26
26
  #endif
27
27
 
28
28
  static int RAW_TYPE_STRING = 256;
29
29
  static int RAW_TYPE_BINARY = 257;
30
30
 
31
- static ID s_call;
32
-
33
- #ifdef UNPACKER_STACK_RMEM
34
31
  static msgpack_rmem_t s_stack_rmem;
35
- #endif
36
32
 
37
33
  #if !defined(HAVE_RB_HASH_NEW_CAPA)
38
34
  static inline VALUE rb_hash_new_capa(long capa)
@@ -43,18 +39,14 @@ static inline VALUE rb_hash_new_capa(long capa)
43
39
 
44
40
  void msgpack_unpacker_static_init(void)
45
41
  {
46
- #ifdef UNPACKER_STACK_RMEM
47
- msgpack_rmem_init(&s_stack_rmem);
48
- #endif
42
+ assert(sizeof(msgpack_unpacker_stack_entry_t) * MSGPACK_UNPACKER_STACK_CAPACITY <= MSGPACK_RMEM_PAGE_SIZE);
49
43
 
50
- s_call = rb_intern("call");
44
+ msgpack_rmem_init(&s_stack_rmem);
51
45
  }
52
46
 
53
47
  void msgpack_unpacker_static_destroy(void)
54
48
  {
55
- #ifdef UNPACKER_STACK_RMEM
56
49
  msgpack_rmem_destroy(&s_stack_rmem);
57
- #endif
58
50
  }
59
51
 
60
52
  #define HEAD_BYTE_REQUIRED 0xc1
@@ -62,13 +54,8 @@ void msgpack_unpacker_static_destroy(void)
62
54
  static inline msgpack_unpacker_stack_t* _msgpack_unpacker_new_stack(void) {
63
55
  msgpack_unpacker_stack_t *stack = ZALLOC(msgpack_unpacker_stack_t);
64
56
  stack->capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
65
- #ifdef UNPACKER_STACK_RMEM
66
57
  stack->data = msgpack_rmem_alloc(&s_stack_rmem);
67
58
  /*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
68
- #else
69
- /*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_entry_t));*/
70
- stack->data = xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_entry_t));
71
- #endif
72
59
  return stack;
73
60
  }
74
61
 
@@ -85,11 +72,9 @@ void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
85
72
  }
86
73
 
87
74
  static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
88
- #ifdef UNPACKER_STACK_RMEM
89
- msgpack_rmem_free(&s_stack_rmem, stack->data);
90
- #else
91
- xfree(stack->data);
92
- #endif
75
+ if (!msgpack_rmem_free(&s_stack_rmem, stack->data)) {
76
+ rb_bug("Failed to free an rmem pointer, memory leak?");
77
+ }
93
78
  xfree(stack);
94
79
  }
95
80
 
@@ -193,7 +178,8 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
193
178
 
194
179
  if(proc != Qnil) {
195
180
  VALUE obj;
196
- obj = rb_funcall(proc, s_call, 1, str == Qnil ? rb_str_buf_new(0) : str);
181
+ VALUE arg = (str == Qnil ? rb_str_buf_new(0) : str);
182
+ obj = rb_proc_call_with_block(proc, 1, &arg, Qnil);
197
183
  return object_complete(uk, obj);
198
184
  }
199
185
 
@@ -323,7 +309,7 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
323
309
  child_stack->parent = uk->stack;
324
310
  uk->stack = child_stack;
325
311
 
326
- obj = rb_funcall(proc, s_call, 1, uk->self);
312
+ obj = rb_proc_call_with_block(proc, 1, &uk->self, Qnil);
327
313
 
328
314
  uk->stack = child_stack->parent;
329
315
  _msgpack_unpacker_free_stack(child_stack);