fastruby 0.0.14 → 0.0.15
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.
- data/CHANGELOG +12 -0
- data/README +0 -2
- data/Rakefile +1 -1
- data/benchmarks/benchmark.rb +1 -0
- data/benchmarks/benchmark5.rb +3 -1
- data/ext/fastruby_base/fastruby_base.inl +2 -0
- data/lib/fastruby/builder.rb +18 -42
- data/lib/fastruby/exceptions.rb +8 -0
- data/lib/fastruby/getlocals.rb +17 -0
- data/lib/fastruby/object.rb +1 -31
- data/lib/fastruby/translator/modules/block.rb +44 -22
- data/lib/fastruby/translator/modules/call.rb +25 -1
- data/lib/fastruby/translator/modules/defn.rb +85 -57
- data/lib/fastruby/translator/modules/iter.rb +159 -46
- data/lib/fastruby/translator/modules/method_group.rb +7 -0
- data/lib/fastruby/translator/translator.rb +224 -245
- data/lib/fastruby.rb +1 -1
- data/lib/targetted +84 -0
- data/spec/block/arguments_spec.rb +214 -0
- data/spec/block/block_as_proc_spec.rb +98 -0
- data/spec/block/callcc_spec.rb +233 -0
- data/spec/block/proc_as_block_spec.rb +111 -0
- data/spec/call/base_call_spec.rb +3 -2
- data/spec/defn/default_args_spec.rb +303 -0
- data/spec/defn/multiple_args_spec.rb +35 -0
- data/spec/exception/base_spec.rb +26 -0
- metadata +10 -4
@@ -38,7 +38,6 @@ module FastRuby
|
|
38
38
|
attr_reader :no_cache
|
39
39
|
attr_reader :init_extra
|
40
40
|
attr_reader :extra_code
|
41
|
-
attr_reader :yield_signature
|
42
41
|
|
43
42
|
TranslatorModules.instance.load_under(FastRuby.fastruby_load_path + "/fastruby/translator/modules/")
|
44
43
|
TranslatorModules.instance.modls.each do |modl|
|
@@ -68,6 +67,12 @@ module FastRuby
|
|
68
67
|
void* block_function_param;
|
69
68
|
}"
|
70
69
|
|
70
|
+
extra_code << "
|
71
|
+
static void frb_jump_tag(int state) {
|
72
|
+
VALUE exception = rb_funcall(#{literal_value FastRuby::JumpTagException}, #{intern_num :new},1,INT2FIX(state));
|
73
|
+
rb_exc_raise(exception);
|
74
|
+
}
|
75
|
+
"
|
71
76
|
|
72
77
|
extra_code << "
|
73
78
|
#include \"node.h\"
|
@@ -98,11 +103,13 @@ module FastRuby
|
|
98
103
|
@lambda_node_gvar = add_global_name("NODE*", 0);
|
99
104
|
@proc_node_gvar = add_global_name("NODE*", 0);
|
100
105
|
@procnew_node_gvar = add_global_name("NODE*", 0);
|
106
|
+
@callcc_node_gvar = add_global_name("NODE*", 0);
|
101
107
|
|
102
108
|
init_extra << "
|
103
109
|
#{@lambda_node_gvar} = rb_method_node(rb_cObject, #{intern_num :lambda});
|
104
110
|
#{@proc_node_gvar} = rb_method_node(rb_cObject, #{intern_num :proc});
|
105
111
|
#{@procnew_node_gvar} = rb_method_node(CLASS_OF(rb_cProc), #{intern_num :new});
|
112
|
+
#{@callcc_node_gvar} = rb_method_node(rb_mKernel, #{intern_num :callcc});
|
106
113
|
"
|
107
114
|
|
108
115
|
@common_func = common_func
|
@@ -145,6 +152,7 @@ module FastRuby
|
|
145
152
|
*/
|
146
153
|
|
147
154
|
"
|
155
|
+
|
148
156
|
end
|
149
157
|
end
|
150
158
|
|
@@ -161,7 +169,7 @@ module FastRuby
|
|
161
169
|
name
|
162
170
|
end
|
163
171
|
|
164
|
-
def frame_call(inner_code)
|
172
|
+
def frame_call(inner_code, precode = "", postcode = "")
|
165
173
|
inline_block "
|
166
174
|
|
167
175
|
|
@@ -181,24 +189,33 @@ module FastRuby
|
|
181
189
|
VALUE old_call_frame = plocals->call_frame;
|
182
190
|
plocals->call_frame = LONG2FIX(&call_frame);
|
183
191
|
|
192
|
+
#{precode}
|
193
|
+
|
184
194
|
int aux = setjmp(call_frame.jmp);
|
185
195
|
if (aux != 0) {
|
186
196
|
if (call_frame.targetted == 0) {
|
197
|
+
#{postcode}
|
187
198
|
longjmp(old_pframe->jmp,aux);
|
188
199
|
}
|
189
200
|
|
190
201
|
if (aux == FASTRUBY_TAG_BREAK) {
|
191
202
|
plocals->call_frame = old_call_frame;
|
203
|
+
#{postcode}
|
192
204
|
return call_frame.return_value;
|
193
205
|
} else if (aux == FASTRUBY_TAG_RETRY ) {
|
194
206
|
// do nothing and let the call execute again
|
195
207
|
} else {
|
196
208
|
plocals->call_frame = old_call_frame;
|
209
|
+
#{postcode}
|
197
210
|
return call_frame.return_value;
|
198
211
|
}
|
199
212
|
}
|
213
|
+
|
200
214
|
|
201
215
|
VALUE ret = #{inner_code};
|
216
|
+
|
217
|
+
#{postcode}
|
218
|
+
|
202
219
|
plocals->call_frame = old_call_frame;
|
203
220
|
return ret;
|
204
221
|
"
|
@@ -207,6 +224,7 @@ module FastRuby
|
|
207
224
|
def initialize_method_structs(args_tree)
|
208
225
|
@locals_struct = "struct {
|
209
226
|
VALUE return_value;
|
227
|
+
VALUE parent_locals;
|
210
228
|
VALUE pframe;
|
211
229
|
VALUE block_function_address;
|
212
230
|
VALUE block_function_param;
|
@@ -214,94 +232,10 @@ module FastRuby
|
|
214
232
|
VALUE active;
|
215
233
|
VALUE targetted;
|
216
234
|
#{@locals.map{|l| "VALUE #{l};\n"}.join}
|
217
|
-
#{args_tree[1..-1].map{|arg| "VALUE #{arg.to_s.gsub("*","")};\n"}.join};
|
218
235
|
}"
|
219
236
|
|
220
237
|
end
|
221
238
|
|
222
|
-
def to_c_method_defs(tree)
|
223
|
-
|
224
|
-
method_name = tree[2]
|
225
|
-
args_tree = tree[3]
|
226
|
-
|
227
|
-
impl_tree = tree[4][1]
|
228
|
-
|
229
|
-
initialize_method_structs(args_tree)
|
230
|
-
|
231
|
-
strargs = if args_tree.size > 1
|
232
|
-
|
233
|
-
"VALUE self, void* block_address, VALUE block_param, void* _parent_frame, #{args_tree[1..-1].map{|arg| "VALUE #{arg.to_s.gsub("*","")}" }.join(",") }"
|
234
|
-
else
|
235
|
-
"VALUE self, void* block_address, VALUE block_param, void* _parent_frame"
|
236
|
-
end
|
237
|
-
|
238
|
-
extra_code << "static VALUE #{@alt_method_name + "_real"}(#{strargs}) {
|
239
|
-
#{func_frame}
|
240
|
-
|
241
|
-
#{args_tree[1..-1].map { |arg|
|
242
|
-
arg = arg.to_s
|
243
|
-
arg.gsub!("*","")
|
244
|
-
"plocals->#{arg} = #{arg};\n"
|
245
|
-
}.join("") }
|
246
|
-
|
247
|
-
plocals->block_function_address = LONG2FIX(block_address);
|
248
|
-
plocals->block_function_param = LONG2FIX(block_param);
|
249
|
-
|
250
|
-
return #{to_c impl_tree};
|
251
|
-
}"
|
252
|
-
|
253
|
-
strargs2 = if args_tree.size > 1
|
254
|
-
"VALUE self, #{args_tree[1..-1].map{|arg| "VALUE #{arg}" }.join(",") }"
|
255
|
-
else
|
256
|
-
"VALUE self"
|
257
|
-
end
|
258
|
-
|
259
|
-
value_cast = ( ["VALUE"]*(args_tree.size+1) ).join(",")
|
260
|
-
strmethodargs = ""
|
261
|
-
|
262
|
-
if args_tree.size > 1
|
263
|
-
strmethodargs = "self,block_address,block_param,&frame,#{args_tree[1..-1].map(&:to_s).join(",") }"
|
264
|
-
else
|
265
|
-
strmethodargs = "self,block_address,block_param,&frame"
|
266
|
-
end
|
267
|
-
|
268
|
-
"
|
269
|
-
VALUE #{@alt_method_name}(#{strargs2}) {
|
270
|
-
#{@frame_struct} frame;
|
271
|
-
int argc = #{args_tree.size};
|
272
|
-
void* block_address = 0;
|
273
|
-
VALUE block_param = Qnil;
|
274
|
-
|
275
|
-
frame.plocals = 0;
|
276
|
-
frame.parent_frame = 0;
|
277
|
-
frame.return_value = Qnil;
|
278
|
-
frame.rescue = 0;
|
279
|
-
frame.targetted = 0;
|
280
|
-
frame.thread_data = rb_current_thread_data();
|
281
|
-
|
282
|
-
if (rb_block_given_p()) {
|
283
|
-
block_address = #{
|
284
|
-
anonymous_function{|name|
|
285
|
-
"static VALUE #{name}(int argc, VALUE* argv, VALUE param) {
|
286
|
-
return rb_yield_splat(rb_ary_new4(argc,argv));
|
287
|
-
}"
|
288
|
-
}
|
289
|
-
};
|
290
|
-
|
291
|
-
block_param = 0;
|
292
|
-
}
|
293
|
-
|
294
|
-
int aux = setjmp(frame.jmp);
|
295
|
-
if (aux != 0) {
|
296
|
-
rb_funcall(self, #{intern_num :raise}, 1, frame.thread_data->exception);
|
297
|
-
}
|
298
|
-
|
299
|
-
|
300
|
-
return #{@alt_method_name + "_real"}(#{strmethodargs});
|
301
|
-
}
|
302
|
-
"
|
303
|
-
end
|
304
|
-
|
305
239
|
def add_main
|
306
240
|
if options[:main]
|
307
241
|
|
@@ -374,20 +308,31 @@ module FastRuby
|
|
374
308
|
end
|
375
309
|
|
376
310
|
def to_c_method(tree, signature = nil)
|
377
|
-
|
378
|
-
|
379
|
-
|
311
|
+
|
312
|
+
if tree[0] == :defn
|
313
|
+
method_name = tree[1]
|
314
|
+
original_args_tree = tree[2]
|
315
|
+
block_argument = tree[2].find{|x| x.to_s[0] == ?&}
|
316
|
+
impl_tree = tree[3][1]
|
317
|
+
elsif tree[0] == :defs
|
318
|
+
method_name = tree[2]
|
319
|
+
original_args_tree = tree[3]
|
320
|
+
block_argument = tree[3].find{|x| x.to_s[0] == ?&}
|
321
|
+
impl_tree = tree[4][1]
|
322
|
+
end
|
323
|
+
|
324
|
+
args_tree = original_args_tree.select{|x| x.to_s[0] != ?&}
|
380
325
|
|
381
326
|
if (options[:main])
|
382
|
-
initialize_method_structs(
|
327
|
+
initialize_method_structs(original_args_tree)
|
383
328
|
|
384
329
|
strargs = if args_tree.size > 1
|
385
|
-
"VALUE block, VALUE _parent_frame, #{(0..signature.size-1).map{|x| "VALUE arg#{x}"}.join(",")}"
|
330
|
+
"VALUE self, VALUE block, VALUE _parent_frame, #{(0..signature.size-1).map{|x| "VALUE arg#{x}"}.join(",")}"
|
386
331
|
else
|
387
|
-
"VALUE block, VALUE _parent_frame"
|
332
|
+
"VALUE self, VALUE block, VALUE _parent_frame"
|
388
333
|
end
|
389
334
|
|
390
|
-
ret = "VALUE #{@alt_method_name || method_name}() {
|
335
|
+
ret = "VALUE #{@alt_method_name || method_name}(VALUE self) {
|
391
336
|
|
392
337
|
#{@locals_struct} *plocals;
|
393
338
|
#{@frame_struct} frame;
|
@@ -404,7 +349,7 @@ module FastRuby
|
|
404
349
|
VALUE rb_previous_stack_chunk = Qnil;
|
405
350
|
VALUE rb_stack_chunk = frame.thread_data->rb_stack_chunk;
|
406
351
|
struct STACKCHUNK* stack_chunk = 0;
|
407
|
-
|
352
|
+
|
408
353
|
if (rb_stack_chunk != Qnil) {
|
409
354
|
Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
|
410
355
|
}
|
@@ -425,6 +370,11 @@ module FastRuby
|
|
425
370
|
int previous_stack_position = stack_chunk_get_current_position(stack_chunk);
|
426
371
|
|
427
372
|
plocals = (typeof(plocals))stack_chunk_alloc(stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
|
373
|
+
|
374
|
+
plocals->parent_locals = LONG2FIX(frame.thread_data->last_plocals);
|
375
|
+
void* old_parent_locals = frame.thread_data->last_plocals;
|
376
|
+
frame.thread_data->last_plocals = plocals;
|
377
|
+
|
428
378
|
plocals->active = Qtrue;
|
429
379
|
plocals->targetted = Qfalse;
|
430
380
|
plocals->pframe = LONG2FIX(&frame);
|
@@ -444,6 +394,7 @@ module FastRuby
|
|
444
394
|
}
|
445
395
|
|
446
396
|
plocals->active = Qfalse;
|
397
|
+
frame.thread_data->last_plocals = old_parent_locals;
|
447
398
|
return plocals->return_value;
|
448
399
|
}
|
449
400
|
|
@@ -468,72 +419,131 @@ module FastRuby
|
|
468
419
|
}
|
469
420
|
|
470
421
|
plocals->active = Qfalse;
|
422
|
+
|
423
|
+
frame.thread_data->last_plocals = old_parent_locals;
|
471
424
|
return ret;
|
472
425
|
|
473
426
|
}"
|
474
427
|
|
475
428
|
add_main
|
476
|
-
ret
|
429
|
+
extra_code << ret
|
477
430
|
else
|
478
431
|
|
479
|
-
initialize_method_structs(
|
480
|
-
|
481
|
-
strargs = if args_tree.size > 1
|
482
|
-
"VALUE block, VALUE _parent_frame, #{(0..signature.size-1).map{|x| "VALUE arg#{x}"}.join(",")}"
|
483
|
-
else
|
484
|
-
"VALUE block, VALUE _parent_frame"
|
485
|
-
end
|
432
|
+
initialize_method_structs(original_args_tree)
|
486
433
|
|
487
|
-
|
434
|
+
strargs = "VALUE self, VALUE block, VALUE _parent_frame, int argc, VALUE* argv"
|
488
435
|
|
489
|
-
|
436
|
+
splat_arg = args_tree[1..-1].find{|x| x.to_s.match(/\*/) }
|
437
|
+
|
438
|
+
maxargnum = args_tree[1..-1].count{ |x|
|
439
|
+
if x.instance_of? Symbol
|
440
|
+
not x.to_s.match(/\*/) and not x.to_s.match(/\&/)
|
441
|
+
else
|
442
|
+
false
|
443
|
+
end
|
444
|
+
}
|
490
445
|
|
491
|
-
|
446
|
+
minargnum = maxargnum
|
492
447
|
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
448
|
+
args_tree[1..-1].each do |subtree|
|
449
|
+
unless subtree.instance_of? Symbol
|
450
|
+
if subtree[0] == :block
|
451
|
+
minargnum = minargnum - (subtree.size-1)
|
452
|
+
end
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
if args_tree[1..-1].find{|x| x.to_s.match(/\*/)}
|
457
|
+
maxargnum = 2147483647
|
458
|
+
end
|
459
|
+
|
460
|
+
read_arguments_code = ""
|
461
|
+
|
506
462
|
|
507
|
-
|
463
|
+
validate_arguments_code = if signature.size-1 < minargnum
|
508
464
|
"
|
465
|
+
rb_raise(rb_eArgError, \"wrong number of arguments (#{signature.size-1} for #{minargnum})\");
|
509
466
|
"
|
510
|
-
|
467
|
+
elsif signature.size-1 > maxargnum
|
511
468
|
"
|
512
|
-
rb_raise(rb_eArgError, \"wrong number of arguments (#{signature.size} for #{
|
469
|
+
rb_raise(rb_eArgError, \"wrong number of arguments (#{signature.size-1} for #{maxargnum})\");
|
513
470
|
"
|
514
|
-
end
|
515
|
-
|
516
471
|
else
|
472
|
+
|
473
|
+
default_block_tree = args_tree[1..-1].find{|subtree|
|
474
|
+
unless subtree.instance_of? Symbol
|
475
|
+
if subtree[0] == :block
|
476
|
+
next true
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
false
|
481
|
+
}
|
482
|
+
|
483
|
+
i = -1
|
484
|
+
|
485
|
+
normalargsnum = args_tree[1..-1].count{|subtree|
|
486
|
+
if subtree.instance_of? Symbol
|
487
|
+
unless subtree.to_s.match(/\*/) or subtree.to_s.match(/\&/)
|
488
|
+
next true
|
489
|
+
end
|
490
|
+
end
|
491
|
+
|
492
|
+
false
|
493
|
+
}
|
494
|
+
|
495
|
+
read_arguments_code = args_tree[1..-1].map { |arg_|
|
496
|
+
arg = arg_.to_s
|
497
|
+
i = i + 1
|
498
|
+
|
499
|
+
if i < normalargsnum
|
500
|
+
if i < signature.size-1
|
501
|
+
"plocals->#{arg} = argv[#{i}];\n"
|
502
|
+
else
|
503
|
+
|
504
|
+
if default_block_tree
|
505
|
+
initialize_tree = default_block_tree[1..-1].find{|subtree| subtree[1] == arg_}
|
506
|
+
if initialize_tree
|
507
|
+
to_c(initialize_tree) + ";\n"
|
508
|
+
else
|
509
|
+
""
|
510
|
+
end
|
511
|
+
else
|
512
|
+
";\n"
|
513
|
+
end
|
514
|
+
end
|
515
|
+
else
|
516
|
+
""
|
517
|
+
end
|
518
|
+
}.join("")
|
519
|
+
|
520
|
+
if splat_arg
|
521
|
+
if signature.size-1 < normalargsnum then
|
522
|
+
read_arguments_code << "
|
523
|
+
plocals->#{splat_arg.to_s.gsub("*","")} = rb_ary_new3(0);
|
524
|
+
"
|
525
|
+
else
|
526
|
+
read_arguments_code << "
|
527
|
+
plocals->#{splat_arg.to_s.gsub("*","")} = rb_ary_new4(
|
528
|
+
#{(signature.size-1) - (normalargsnum)}, argv+#{normalargsnum}
|
529
|
+
);
|
530
|
+
"
|
531
|
+
end
|
532
|
+
|
533
|
+
end
|
517
534
|
|
518
|
-
i = -1
|
519
535
|
|
520
|
-
|
521
|
-
|
522
|
-
i = i + 1
|
523
|
-
"plocals->#{arg} = arg#{i};\n"
|
524
|
-
}.join("")
|
536
|
+
""
|
537
|
+
end
|
525
538
|
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
end
|
534
|
-
|
539
|
+
if block_argument
|
540
|
+
|
541
|
+
proc_reyield_block_tree = s(:iter, s(:call, nil, :proc, s(:arglist)), s(:masgn, s(:array, s(:splat, s(:lasgn, :__xproc_arguments)))), s(:yield, s(:splat, s(:lvar, :__xproc_arguments))))
|
542
|
+
|
543
|
+
read_arguments_code << "
|
544
|
+
plocals->#{block_argument.to_s.gsub("&","")} = #{to_c proc_reyield_block_tree.to_fastruby_sexp};
|
545
|
+
"
|
535
546
|
end
|
536
|
-
|
537
547
|
|
538
548
|
ret = "VALUE #{@alt_method_name || method_name}(#{strargs}) {
|
539
549
|
#{validate_arguments_code}
|
@@ -576,6 +586,11 @@ module FastRuby
|
|
576
586
|
int previous_stack_position = stack_chunk_get_current_position(stack_chunk);
|
577
587
|
|
578
588
|
plocals = (typeof(plocals))stack_chunk_alloc(stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
|
589
|
+
|
590
|
+
plocals->parent_locals = LONG2FIX(frame.thread_data->last_plocals);
|
591
|
+
void* old_parent_locals = frame.thread_data->last_plocals;
|
592
|
+
frame.thread_data->last_plocals = plocals;
|
593
|
+
|
579
594
|
frame.plocals = plocals;
|
580
595
|
plocals->active = Qtrue;
|
581
596
|
plocals->targetted = Qfalse;
|
@@ -598,10 +613,14 @@ module FastRuby
|
|
598
613
|
frame.thread_data->rb_stack_chunk = rb_previous_stack_chunk;
|
599
614
|
}
|
600
615
|
|
601
|
-
if (plocals->targetted == Qfalse) {
|
616
|
+
if (plocals->targetted == Qfalse || aux != FASTRUBY_TAG_RETURN) {
|
617
|
+
frame.thread_data->last_plocals = old_parent_locals;
|
618
|
+
|
602
619
|
longjmp(((typeof(pframe))_parent_frame)->jmp,aux);
|
603
620
|
}
|
604
621
|
|
622
|
+
frame.thread_data->last_plocals = old_parent_locals;
|
623
|
+
|
605
624
|
return plocals->return_value;
|
606
625
|
}
|
607
626
|
|
@@ -627,12 +646,21 @@ module FastRuby
|
|
627
646
|
}
|
628
647
|
|
629
648
|
plocals->active = Qfalse;
|
649
|
+
|
650
|
+
frame.thread_data->last_plocals = old_parent_locals;
|
651
|
+
|
630
652
|
return __ret;
|
631
653
|
}"
|
632
654
|
|
633
655
|
add_main
|
634
|
-
ret
|
656
|
+
extra_code << ret
|
635
657
|
end
|
658
|
+
|
659
|
+
"
|
660
|
+
static VALUE dummy_#{method_name}_#{alt_method_name}_#{rand(1000000000000000000000000000000000)}(VALUE a) {
|
661
|
+
return Qnil;
|
662
|
+
}
|
663
|
+
"
|
636
664
|
end
|
637
665
|
|
638
666
|
def locals_accessor
|
@@ -646,6 +674,7 @@ module FastRuby
|
|
646
674
|
@locals = locals
|
647
675
|
@locals_struct = "struct {
|
648
676
|
VALUE return_value;
|
677
|
+
VALUE parent_locals;
|
649
678
|
VALUE pframe;
|
650
679
|
VALUE block_function_address;
|
651
680
|
VALUE block_function_param;
|
@@ -687,16 +716,6 @@ module FastRuby
|
|
687
716
|
@on_block = old_on_block
|
688
717
|
end
|
689
718
|
|
690
|
-
def with_extra_inference(extra_inference)
|
691
|
-
previous_infer_lvar_map = @infer_lvar_map
|
692
|
-
begin
|
693
|
-
@infer_lvar_map = @infer_lvar_map.merge(extra_inference)
|
694
|
-
yield
|
695
|
-
ensure
|
696
|
-
@infer_lvar_map = previous_infer_lvar_map
|
697
|
-
end
|
698
|
-
end
|
699
|
-
|
700
719
|
def directive(tree)
|
701
720
|
recv = tree[1]
|
702
721
|
mname = tree[2]
|
@@ -779,14 +798,20 @@ module FastRuby
|
|
779
798
|
def protected_block(inner_code, always_rescue = false,repass_var = nil, nolocals = false)
|
780
799
|
body = nil
|
781
800
|
rescue_args = nil
|
782
|
-
|
801
|
+
|
783
802
|
body = anonymous_function{ |name| "
|
784
803
|
static VALUE #{name}(VALUE param) {
|
785
804
|
|
786
805
|
#{@frame_struct} frame;
|
787
806
|
|
788
807
|
typeof(frame)* pframe;
|
789
|
-
|
808
|
+
|
809
|
+
#{if repass_var
|
810
|
+
"typeof(frame)* parent_frame = ((typeof(pframe))((void**)param)[0]);"
|
811
|
+
else
|
812
|
+
"typeof(frame)* parent_frame = (typeof(pframe))param;"
|
813
|
+
end
|
814
|
+
}
|
790
815
|
|
791
816
|
frame.parent_frame = 0;
|
792
817
|
frame.return_value = Qnil;
|
@@ -794,6 +819,7 @@ module FastRuby
|
|
794
819
|
frame.last_error = Qnil;
|
795
820
|
frame.targetted = 0;
|
796
821
|
frame.thread_data = parent_frame->thread_data;
|
822
|
+
frame.next_recv = parent_frame->next_recv;
|
797
823
|
if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
|
798
824
|
|
799
825
|
pframe = &frame;
|
@@ -810,84 +836,69 @@ module FastRuby
|
|
810
836
|
if (frame.targetted == 1) {
|
811
837
|
return frame.return_value;
|
812
838
|
} else {
|
813
|
-
|
839
|
+
frb_jump_tag(aux);
|
814
840
|
}
|
815
841
|
}
|
816
842
|
|
817
|
-
|
843
|
+
#{if repass_var
|
844
|
+
"VALUE #{repass_var} = (VALUE)((void**)param)[1];"
|
845
|
+
end
|
846
|
+
}
|
818
847
|
return #{inner_code};
|
819
848
|
}
|
820
849
|
"
|
821
850
|
}
|
822
851
|
|
852
|
+
if repass_var
|
823
853
|
rescue_args = ""
|
824
854
|
rescue_args = "(VALUE)(VALUE[]){(VALUE)pframe,(VALUE)#{repass_var}}"
|
825
855
|
else
|
856
|
+
rescue_args = "(VALUE)pframe"
|
857
|
+
end
|
826
858
|
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
frame.rescue = 0;
|
837
|
-
frame.last_error = Qnil;
|
838
|
-
frame.targetted = 0;
|
839
|
-
frame.thread_data = parent_frame->thread_data;
|
840
|
-
if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
|
841
|
-
|
842
|
-
pframe = &frame;
|
843
|
-
|
844
|
-
#{
|
845
|
-
nolocals ? "frame.plocals = 0;" : "#{@locals_struct}* plocals = parent_frame->plocals;
|
846
|
-
frame.plocals = plocals;
|
847
|
-
"
|
848
|
-
}
|
849
|
-
|
850
|
-
int aux = setjmp(frame.jmp);
|
851
|
-
if (aux != 0) {
|
852
|
-
|
853
|
-
if (frame.targetted == 1) {
|
854
|
-
return frame.return_value;
|
855
|
-
} else {
|
856
|
-
rb_jump_tag(aux);
|
859
|
+
wrapper_code = "
|
860
|
+
if (str.state >= 0x80) {
|
861
|
+
longjmp(pframe->jmp, str.state);
|
862
|
+
} else {
|
863
|
+
if (str.last_error != Qnil) {
|
864
|
+
// raise emulation
|
865
|
+
pframe->thread_data->exception = str.last_error;
|
866
|
+
longjmp(pframe->jmp, FASTRUBY_TAG_RAISE);
|
867
|
+
return Qnil;
|
857
868
|
}
|
858
869
|
}
|
859
|
-
|
860
|
-
|
861
|
-
|
870
|
+
"
|
871
|
+
|
872
|
+
return_err_struct = "struct {
|
873
|
+
VALUE last_error;
|
874
|
+
int state;
|
875
|
+
}
|
862
876
|
"
|
863
|
-
}
|
864
|
-
|
865
|
-
rescue_args = "(VALUE)pframe"
|
866
|
-
end
|
867
|
-
|
868
|
-
wrapper_code = " if (state != 0) {
|
869
|
-
if (state < 0x80) {
|
870
877
|
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
878
|
+
rescue_body = anonymous_function{ |name| "
|
879
|
+
static VALUE #{name}(VALUE param, VALUE err) {
|
880
|
+
#{return_err_struct} *pstr = (void*)param;
|
881
|
+
|
882
|
+
if (rb_obj_is_instance_of(err, #{literal_value FastRuby::JumpTagException})) {
|
883
|
+
pstr->state = FIX2INT(rb_funcall(err, #{intern_num :state}, 0));
|
876
884
|
} else {
|
877
|
-
|
885
|
+
pstr->last_error = err;
|
878
886
|
}
|
879
|
-
|
880
|
-
|
887
|
+
|
888
|
+
return Qnil;
|
881
889
|
}
|
882
|
-
|
883
|
-
}
|
884
890
|
"
|
891
|
+
}
|
885
892
|
|
886
|
-
rescue_code = "
|
893
|
+
rescue_code = "rb_rescue2(#{body}, #{rescue_args}, #{rescue_body}, (VALUE)&str, rb_eException, (VALUE)0)"
|
887
894
|
|
888
895
|
if always_rescue
|
889
896
|
inline_block "
|
890
|
-
|
897
|
+
#{return_err_struct} str;
|
898
|
+
|
899
|
+
str.state = 0;
|
900
|
+
str.last_error = Qnil;
|
901
|
+
|
891
902
|
pframe->last_error = Qnil;
|
892
903
|
VALUE result = #{rescue_code};
|
893
904
|
|
@@ -898,7 +909,11 @@ module FastRuby
|
|
898
909
|
else
|
899
910
|
inline_block "
|
900
911
|
VALUE result;
|
901
|
-
|
912
|
+
#{return_err_struct} str;
|
913
|
+
|
914
|
+
str.state = 0;
|
915
|
+
str.last_error = Qnil;
|
916
|
+
|
902
917
|
pframe->last_error = Qnil;
|
903
918
|
|
904
919
|
if (pframe->rescue) {
|
@@ -913,42 +928,6 @@ module FastRuby
|
|
913
928
|
end
|
914
929
|
end
|
915
930
|
|
916
|
-
def func_frame
|
917
|
-
"
|
918
|
-
#{@locals_struct} *plocals = malloc(sizeof(typeof(*plocals)));
|
919
|
-
#{@frame_struct} frame;
|
920
|
-
#{@frame_struct} *pframe;
|
921
|
-
|
922
|
-
frame.plocals = plocals;
|
923
|
-
frame.parent_frame = (void*)_parent_frame;
|
924
|
-
frame.return_value = Qnil;
|
925
|
-
frame.rescue = 0;
|
926
|
-
frame.targetted = 0;
|
927
|
-
frame.thread_data = ((typeof(pframe))_parent_frame)->thread_data;
|
928
|
-
if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
|
929
|
-
|
930
|
-
plocals->pframe = LONG2FIX(&frame);
|
931
|
-
plocals->targetted = Qfalse;
|
932
|
-
|
933
|
-
pframe = (void*)&frame;
|
934
|
-
|
935
|
-
#{@block_struct} *pblock;
|
936
|
-
VALUE last_expression = Qnil;
|
937
|
-
|
938
|
-
int aux = setjmp(pframe->jmp);
|
939
|
-
if (aux != 0) {
|
940
|
-
|
941
|
-
if (plocals->targetted == Qfalse) {
|
942
|
-
longjmp(((typeof(pframe))_parent_frame)->jmp,aux);
|
943
|
-
}
|
944
|
-
|
945
|
-
return plocals->return_value;
|
946
|
-
}
|
947
|
-
|
948
|
-
plocals->self = self;
|
949
|
-
"
|
950
|
-
end
|
951
|
-
|
952
931
|
def c_escape(str)
|
953
932
|
str.inspect
|
954
933
|
end
|
@@ -1102,7 +1081,7 @@ module FastRuby
|
|
1102
1081
|
protected_block "rb_funcall(((VALUE*)method_arguments)[0], #{intern_num mname.to_sym}, #{args_tree.size-1}#{inprocstrargs});", false, "method_arguments"
|
1103
1082
|
};
|
1104
1083
|
} else {
|
1105
|
-
return ( (VALUE(*)(
|
1084
|
+
return ( (VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*)) (fptr) )(self,(VALUE)block,(VALUE)frame,#{args_tree.size-1},method_arguments+1);
|
1106
1085
|
}
|
1107
1086
|
}
|
1108
1087
|
"
|