Skip to content

Commit 0815f34

Browse files
authored
Merge pull request #338 from Shopify/rb_proc_call
Use rb_proc_call* rather than rb_funcall
2 parents 6918512 + d33269d commit 0815f34

21 files changed

+169
-311
lines changed

ext/java/org/msgpack/jruby/ExtensionRegistry.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ public IRubyObject toInternalUnpackerRegistry(ThreadContext ctx) {
5454
return hash;
5555
}
5656

57-
public void put(RubyModule mod, int typeId, boolean recursive, IRubyObject packerProc, IRubyObject packerArg, IRubyObject unpackerProc, IRubyObject unpackerArg) {
58-
ExtensionEntry entry = new ExtensionEntry(mod, typeId, recursive, packerProc, packerArg, unpackerProc, unpackerArg);
57+
public void put(RubyModule mod, int typeId, boolean recursive, IRubyObject packerProc, IRubyObject unpackerProc) {
58+
ExtensionEntry entry = new ExtensionEntry(mod, typeId, recursive, packerProc, unpackerProc);
5959
extensionsByModule.put(mod, entry);
6060
extensionsByTypeId[typeId + 128] = entry;
6161
extensionsByAncestor.clear();
@@ -114,18 +114,14 @@ public static class ExtensionEntry {
114114
private final int typeId;
115115
private final boolean recursive;
116116
private final IRubyObject packerProc;
117-
private final IRubyObject packerArg;
118117
private final IRubyObject unpackerProc;
119-
private final IRubyObject unpackerArg;
120118

121-
public ExtensionEntry(RubyModule mod, int typeId, boolean recursive, IRubyObject packerProc, IRubyObject packerArg, IRubyObject unpackerProc, IRubyObject unpackerArg) {
119+
public ExtensionEntry(RubyModule mod, int typeId, boolean recursive, IRubyObject packerProc, IRubyObject unpackerProc) {
122120
this.mod = mod;
123121
this.typeId = typeId;
124122
this.recursive = recursive;
125123
this.packerProc = packerProc;
126-
this.packerArg = packerArg;
127124
this.unpackerProc = unpackerProc;
128-
this.unpackerArg = unpackerArg;
129125
}
130126

131127
public RubyModule getExtensionModule() {
@@ -157,11 +153,11 @@ public IRubyObject getUnpackerProc() {
157153
}
158154

159155
public RubyArray<?> toPackerTuple(ThreadContext ctx) {
160-
return ctx.runtime.newArray(new IRubyObject[] {ctx.runtime.newFixnum(typeId), packerProc, packerArg});
156+
return ctx.runtime.newArray(new IRubyObject[] {ctx.runtime.newFixnum(typeId), packerProc});
161157
}
162158

163159
public RubyArray<?> toUnpackerTuple(ThreadContext ctx) {
164-
return ctx.runtime.newArray(new IRubyObject[] {mod, unpackerProc, unpackerArg});
160+
return ctx.runtime.newArray(new IRubyObject[] {mod, unpackerProc});
165161
}
166162

167163
public IRubyObject[] toPackerProcTypeIdPair(ThreadContext ctx) {

ext/java/org/msgpack/jruby/Factory.java

Lines changed: 7 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -80,43 +80,15 @@ public IRubyObject registeredTypesInternal(ThreadContext ctx) {
8080
});
8181
}
8282

83-
@JRubyMethod(name = "register_type", required = 2, optional = 1)
84-
public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args) {
83+
@JRubyMethod(name = "register_type_internal", required = 3, visibility = PRIVATE)
84+
public IRubyObject registerTypeInternal(ThreadContext ctx, IRubyObject type, IRubyObject mod, IRubyObject opts) {
8585
testFrozen("MessagePack::Factory");
8686

8787
Ruby runtime = ctx.runtime;
88-
IRubyObject type = args[0];
89-
IRubyObject mod = args[1];
90-
91-
IRubyObject packerArg;
92-
IRubyObject unpackerArg;
93-
94-
RubyHash options = null;
95-
96-
if (args.length == 2) {
97-
packerArg = runtime.newSymbol("to_msgpack_ext");
98-
unpackerArg = runtime.newSymbol("from_msgpack_ext");
99-
} else if (args.length == 3) {
100-
if (args[args.length - 1] instanceof RubyHash) {
101-
options = (RubyHash) args[args.length - 1];
102-
packerArg = options.fastARef(runtime.newSymbol("packer"));
103-
if (packerArg != null && packerArg.isNil()) {
104-
packerArg = null;
105-
}
106-
unpackerArg = options.fastARef(runtime.newSymbol("unpacker"));
107-
if (unpackerArg != null && unpackerArg.isNil()) {
108-
unpackerArg = null;
109-
}
110-
IRubyObject optimizedSymbolsParsingArg = options.fastARef(runtime.newSymbol("optimized_symbols_parsing"));
111-
if (optimizedSymbolsParsingArg != null && optimizedSymbolsParsingArg.isTrue()) {
112-
throw runtime.newArgumentError("JRuby implementation does not support the optimized_symbols_parsing option");
113-
}
114-
} else {
115-
throw runtime.newArgumentError(String.format("expected Hash but found %s.", args[args.length - 1].getType().getName()));
116-
}
117-
} else {
118-
throw runtime.newArgumentError(String.format("wrong number of arguments (%d for 2..3)", 2 + args.length));
119-
}
88+
RubyHash options = (RubyHash) opts;
89+
90+
IRubyObject packerProc = options.fastARef(runtime.newSymbol("packer"));
91+
IRubyObject unpackerProc = options.fastARef(runtime.newSymbol("unpacker"));
12092

12193
long typeId = ((RubyFixnum) type).getLongValue();
12294
if (typeId < -128 || typeId > 127) {
@@ -128,21 +100,6 @@ public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args) {
128100
}
129101
RubyModule extModule = (RubyModule) mod;
130102

131-
IRubyObject packerProc = runtime.getNil();
132-
IRubyObject unpackerProc = runtime.getNil();
133-
if (packerArg != null) {
134-
packerProc = packerArg.callMethod(ctx, "to_proc");
135-
}
136-
if (unpackerArg != null) {
137-
if (unpackerArg instanceof RubyString || unpackerArg instanceof RubySymbol) {
138-
unpackerProc = extModule.method(unpackerArg.callMethod(ctx, "to_sym"));
139-
} else if (unpackerArg instanceof RubyProc || unpackerArg instanceof RubyMethod) {
140-
unpackerProc = unpackerArg;
141-
} else {
142-
unpackerProc = unpackerArg.callMethod(ctx, "method", runtime.newSymbol("call"));
143-
}
144-
}
145-
146103
boolean recursive = false;
147104
if (options != null) {
148105
IRubyObject recursiveExtensionArg = options.fastARef(runtime.newSymbol("recursive"));
@@ -151,7 +108,7 @@ public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args) {
151108
}
152109
}
153110

154-
extensionRegistry.put(extModule, (int) typeId, recursive, packerProc, packerArg, unpackerProc, unpackerArg);
111+
extensionRegistry.put(extModule, (int) typeId, recursive, packerProc, unpackerProc);
155112

156113
if (extModule == runtime.getSymbol() && !packerProc.isNil()) {
157114
hasSymbolExtType = true;

ext/java/org/msgpack/jruby/Packer.java

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -93,28 +93,11 @@ public IRubyObject registeredTypesInternal(ThreadContext ctx) {
9393
return registry.toInternalPackerRegistry(ctx);
9494
}
9595

96-
@JRubyMethod(name = "register_type", required = 2, optional = 1)
97-
public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args, final Block block) {
96+
@JRubyMethod(name = "register_type_internal", required = 3, visibility = PRIVATE)
97+
public IRubyObject registerType(ThreadContext ctx, IRubyObject type, IRubyObject mod, IRubyObject proc) {
9898
testFrozen("MessagePack::Packer");
9999

100100
Ruby runtime = ctx.runtime;
101-
IRubyObject type = args[0];
102-
IRubyObject mod = args[1];
103-
104-
IRubyObject arg;
105-
IRubyObject proc;
106-
if (args.length == 2) {
107-
if (! block.isGiven()) {
108-
throw runtime.newLocalJumpErrorNoBlock();
109-
}
110-
proc = block.getProcObject();
111-
arg = proc;
112-
} else if (args.length == 3) {
113-
arg = args[2];
114-
proc = arg.callMethod(ctx, "to_proc");
115-
} else {
116-
throw runtime.newArgumentError(String.format("wrong number of arguments (%d for 2..3)", 2 + args.length));
117-
}
118101

119102
long typeId = ((RubyFixnum) type).getLongValue();
120103
if (typeId < -128 || typeId > 127) {
@@ -126,7 +109,7 @@ public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args, final Blo
126109
}
127110
RubyModule extModule = (RubyModule) mod;
128111

129-
registry.put(extModule, (int) typeId, false, proc, arg, null, null);
112+
registry.put(extModule, (int) typeId, false, proc, null);
130113

131114
if (extModule == runtime.getSymbol() && !proc.isNil()) {
132115
encoder.hasSymbolExtType = true;

ext/java/org/msgpack/jruby/Unpacker.java

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -126,39 +126,23 @@ public IRubyObject registeredTypesInternal(ThreadContext ctx) {
126126
return registry.toInternalUnpackerRegistry(ctx);
127127
}
128128

129-
@JRubyMethod(name = "register_type", required = 1, optional = 2)
130-
public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args, final Block block) {
129+
@JRubyMethod(name = "register_type_internal", required = 3, visibility = PRIVATE)
130+
public IRubyObject registerTypeInternal(ThreadContext ctx, IRubyObject type, IRubyObject mod, IRubyObject proc) {
131131
testFrozen("MessagePack::Unpacker");
132132

133133
Ruby runtime = ctx.runtime;
134-
IRubyObject type = args[0];
135-
136-
RubyModule extModule;
137-
IRubyObject arg;
138-
IRubyObject proc;
139-
if (args.length == 1) {
140-
if (! block.isGiven()) {
141-
throw runtime.newLocalJumpErrorNoBlock();
142-
}
143-
proc = RubyProc.newProc(runtime, block, block.type);
144-
if (proc == null)
145-
System.err.println("proc from Block is null");
146-
arg = proc;
147-
extModule = null;
148-
} else if (args.length == 3) {
149-
extModule = (RubyModule) args[1];
150-
arg = args[2];
151-
proc = extModule.method(arg);
152-
} else {
153-
throw runtime.newArgumentError(String.format("wrong number of arguments (%d for 1 or 3)", 2 + args.length));
154-
}
155134

156135
long typeId = ((RubyFixnum) type).getLongValue();
157136
if (typeId < -128 || typeId > 127) {
158137
throw runtime.newRangeError(String.format("integer %d too big to convert to `signed char'", typeId));
159138
}
160139

161-
registry.put(extModule, (int) typeId, false, null, null, proc, arg);
140+
RubyModule extModule = null;
141+
if (mod != runtime.getNil()) {
142+
extModule = (RubyModule)mod;
143+
}
144+
145+
registry.put(extModule, (int) typeId, false, null, proc);
162146
return runtime.getNil();
163147
}
164148

ext/msgpack/extconf.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
have_header("st.h")
55
have_func("rb_enc_interned_str", "ruby.h") # Ruby 3.0+
66
have_func("rb_hash_new_capa", "ruby.h") # Ruby 3.2+
7+
have_func("rb_proc_call_with_block", "ruby.h") # CRuby (TruffleRuby doesn't have it)
78

89
append_cflags([
910
"-fvisibility=hidden",

ext/msgpack/factory_class.c

Lines changed: 18 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ static VALUE Factory_registered_types_internal(VALUE self)
187187
VALUE uk_mapping = rb_hash_new();
188188
if (fc->ukrg) {
189189
for(int i=0; i < 256; i++) {
190-
if(fc->ukrg->array[i] != Qnil) {
190+
if(!NIL_P(fc->ukrg->array[i])) {
191191
rb_hash_aset(uk_mapping, INT2FIX(i - 128), fc->ukrg->array[i]);
192192
}
193193
}
@@ -200,72 +200,35 @@ static VALUE Factory_registered_types_internal(VALUE self)
200200
);
201201
}
202202

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)
204204
{
205205
msgpack_factory_t *fc = Factory_get(self);
206206

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);
213208

214-
if (OBJ_FROZEN(self)) {
215-
rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::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));
216211
}
217212

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, unpacker: 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-
}
213+
int flags = 0;
230214

231-
packer_arg = rb_hash_aref(options, ID2SYM(rb_intern("packer")));
232-
unpacker_arg = rb_hash_aref(options, ID2SYM(rb_intern("unpacker")));
233-
break;
234-
default:
235-
rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..3)", argc);
215+
VALUE packer_proc = Qnil;
216+
VALUE unpacker_proc = Qnil;
217+
if(!NIL_P(options)) {
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")));
236221
}
237222

238-
if (options != Qnil) {
239-
Check_Type(options, T_HASH);
223+
if (OBJ_FROZEN(self)) {
224+
rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Factory");
240225
}
241226

242-
ext_type = NUM2INT(argv[0]);
227+
int ext_type = NUM2INT(rb_ext_type);
243228
if(ext_type < -128 || ext_type > 127) {
244229
rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
245230
}
246231

247-
ext_module = argv[1];
248-
if(rb_type(ext_module) != T_MODULE && rb_type(ext_module) != T_CLASS) {
249-
rb_raise(rb_eArgError, "expected Module/Class but found %s.", rb_obj_classname(ext_module));
250-
}
251-
252-
packer_proc = Qnil;
253-
unpacker_proc = Qnil;
254-
255-
if(packer_arg != Qnil) {
256-
packer_proc = rb_funcall(packer_arg, rb_intern("to_proc"), 0);
257-
}
258-
259-
if(unpacker_arg != Qnil) {
260-
if(rb_type(unpacker_arg) == T_SYMBOL || rb_type(unpacker_arg) == T_STRING) {
261-
unpacker_proc = rb_obj_method(ext_module, unpacker_arg);
262-
} else if (rb_respond_to(unpacker_arg, rb_intern("call"))) {
263-
unpacker_proc = unpacker_arg;
264-
} else {
265-
unpacker_proc = rb_funcall(unpacker_arg, rb_intern("method"), 1, ID2SYM(rb_intern("call")));
266-
}
267-
}
268-
269232
if(ext_module == rb_cSymbol) {
270233
if(NIL_P(options) || RTEST(rb_hash_aref(options, ID2SYM(rb_intern("packer"))))) {
271234
fc->has_symbol_ext_type = true;
@@ -289,8 +252,8 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
289252
}
290253
}
291254

292-
msgpack_packer_ext_registry_put(self, &fc->pkrg, ext_module, ext_type, flags, packer_proc, packer_arg);
293-
msgpack_unpacker_ext_registry_put(self, &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);
294257

295258
return Qnil;
296259
}
@@ -309,5 +272,5 @@ void MessagePack_Factory_module_init(VALUE mMessagePack)
309272
rb_define_method(cMessagePack_Factory, "unpacker", MessagePack_Factory_unpacker, -1);
310273

311274
rb_define_private_method(cMessagePack_Factory, "registered_types_internal", Factory_registered_types_internal, 0);
312-
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);
313276
}

ext/msgpack/packer.c

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,9 @@
1818

1919
#include "packer.h"
2020

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-
{ }
21+
#if !defined(HAVE_RB_PROC_CALL_WITH_BLOCK)
22+
#define rb_proc_call_with_block(recv, argc, argv, block) rb_funcallv(recv, rb_intern("call"), argc, argv)
23+
#endif
3024

3125
void msgpack_packer_init(msgpack_packer_t* pk)
3226
{
@@ -100,14 +94,13 @@ struct msgpack_call_proc_args_t;
10094
typedef struct msgpack_call_proc_args_t msgpack_call_proc_args_t;
10195
struct msgpack_call_proc_args_t {
10296
VALUE proc;
103-
VALUE arg;
104-
VALUE packer;
97+
VALUE args[2];
10598
};
10699

107100
VALUE msgpack_packer_try_calling_proc(VALUE value)
108101
{
109102
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);
103+
return rb_proc_call_with_block(args->proc, 2, args->args, Qnil);
111104
}
112105

113106
bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v)
@@ -125,7 +118,7 @@ bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v
125118
msgpack_buffer_init(PACKER_BUFFER_(pk));
126119

127120
int exception_occured = 0;
128-
msgpack_call_proc_args_t args = { proc, v, pk->to_msgpack_arg };
121+
msgpack_call_proc_args_t args = { proc, { v, pk->to_msgpack_arg } };
129122
rb_protect(msgpack_packer_try_calling_proc, (VALUE)&args, &exception_occured);
130123

131124
if (exception_occured) {
@@ -140,7 +133,7 @@ bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v
140133
msgpack_packer_write_ext(pk, ext_type, payload);
141134
}
142135
} else {
143-
VALUE payload = rb_funcall(proc, s_call, 1, v);
136+
VALUE payload = rb_proc_call_with_block(proc, 1, &v, Qnil);
144137
StringValue(payload);
145138
msgpack_packer_write_ext(pk, ext_type, payload);
146139
}

0 commit comments

Comments
 (0)