fastruby 0.0.20 → 0.0.21

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.
Files changed (42) hide show
  1. data/Rakefile +1 -1
  2. data/lib/fastruby/builder.rb~ +5 -1
  3. data/lib/fastruby/corelib/fixnum.rb +1 -1
  4. data/lib/fastruby/corelib/fixnum.rb~ +0 -71
  5. data/lib/fastruby/corelib.rb~ +1 -1
  6. data/lib/fastruby/modules/inliner/call.rb~ +3 -1
  7. data/lib/fastruby/modules/translator/call.rb +1 -1
  8. data/lib/fastruby/modules/translator/call.rb~ +1 -1
  9. data/lib/fastruby/object.rb~ +0 -6
  10. data/lib/fastruby.rb +1 -1
  11. data/lib/fastruby.rb~ +1 -1
  12. data/spec/corelib/numeric/fixnum_spec.rb +1 -1
  13. data/spec/corelib/numeric/fixnum_spec.rb~ +7 -1
  14. metadata +12 -40
  15. data/lib/fastruby/builder/inference_updater.rb~ +0 -76
  16. data/lib/fastruby/builder/inliner.rb~ +0 -60
  17. data/lib/fastruby/builder/lvar_type.rb~ +0 -44
  18. data/lib/fastruby/builder/pipeline.rb~ +0 -43
  19. data/lib/fastruby/builder/reductor.rb~ +0 -42
  20. data/lib/fastruby/corelib/integer.rb~ +0 -96
  21. data/lib/fastruby/modules/inliner/defn.rb~ +0 -29
  22. data/lib/fastruby/modules/inliner/recursive.rb~ +0 -40
  23. data/lib/fastruby/modules/lvar_type/call.rb~ +0 -36
  24. data/lib/fastruby/modules/lvar_type/defn.rb~ +0 -42
  25. data/lib/fastruby/modules/lvar_type/lasgn.rb~ +0 -42
  26. data/lib/fastruby/modules/lvar_type/recursive.rb~ +0 -33
  27. data/lib/fastruby/modules/reductor/nontree.rb~ +0 -32
  28. data/lib/fastruby/modules/reductor/recursive.rb~ +0 -31
  29. data/lib/fastruby/modules/translator/defn.rb~ +0 -267
  30. data/lib/fastruby/modules/translator/directive.rb~ +0 -44
  31. data/lib/fastruby/modules/translator/exceptions.rb~ +0 -120
  32. data/lib/fastruby/modules/translator/iter.rb~ +0 -745
  33. data/lib/fastruby/modules/translator/literal.rb~ +0 -150
  34. data/lib/fastruby/modules/translator/nonlocal.rb~ +0 -298
  35. data/lib/fastruby/modules/translator/static.rb~ +0 -291
  36. data/lib/fastruby/modules/translator/variable.rb~ +0 -280
  37. data/lib/fastruby/set_tree.rb~ +0 -71
  38. data/lib/fastruby/sexp_extension.rb~ +0 -262
  39. data/lib/fastruby/translator/scope_mode_helper.rb~ +0 -138
  40. data/lib/fastruby/translator/translator.rb~ +0 -1600
  41. data/lib/fastruby/translator/translator_modules.rb~ +0 -53
  42. data/lib/fastruby_only/base.rb +0 -1
@@ -1,1600 +0,0 @@
1
- =begin
2
-
3
- This file is part of the fastruby project, http://github.com/tario/fastruby
4
-
5
- Copyright (c) 2011 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
-
7
- fastruby is free software: you can redistribute it and/or modify
8
- it under the terms of the gnu general public license as published by
9
- the free software foundation, either version 3 of the license, or
10
- (at your option) any later version.
11
-
12
- fastruby is distributed in the hope that it will be useful,
13
- but without any warranty; without even the implied warranty of
14
- merchantability or fitness for a particular purpose. see the
15
- gnu general public license for more details.
16
-
17
- you should have received a copy of the gnu general public license
18
- along with fastruby. if not, see <http://www.gnu.org/licenses/>.
19
-
20
- =end
21
- require "set"
22
- require "rubygems"
23
- require "sexp"
24
- require "fastruby/method_extension"
25
- require "fastruby/set_tree"
26
- require "fastruby/exceptions"
27
- require "fastruby/translator/translator_modules"
28
- require "fastruby/translator/scope_mode_helper"
29
- require "fastruby/modules"
30
- require "define_method_handler"
31
- require "base64"
32
-
33
- module FastRuby
34
- class Context
35
- attr_accessor :locals
36
- attr_accessor :options
37
- attr_reader :no_cache
38
- attr_reader :init_extra
39
- attr_reader :extra_code
40
-
41
- class Value
42
- attr_accessor :value
43
- def initialize(v); @value = v; end
44
- end
45
-
46
- def self.define_translator_for(ntype, options = {}, &blk)
47
- condition_blk = proc do |*x|
48
- tree = x.first; tree.node_type == ntype
49
- end
50
-
51
- if options[:arity]
52
- if options[:arity] == 1
53
- condition_blk = proc do |*x|
54
- tree = x.first; x.size == 1 and tree.node_type == ntype
55
- end
56
- end
57
- end
58
-
59
- define_method_handler(:to_c, options, &blk).condition &condition_blk
60
- end
61
-
62
- define_method_handler(:to_c, :priority => 10000){|*x|
63
- "Qnil"
64
- }.condition{|*x| x.size == 1 and (not x.first)}
65
-
66
- define_method_handler(:to_c, :priority => 1000){|tree, result_var|
67
- "#{result_var} = #{to_c(tree)};"
68
- }.condition{|*x| x.size == 2 and (not x.first)}
69
-
70
- define_method_handler(:to_c, :priority => -9000){ |tree, result_var|
71
- "#{result_var} = #{to_c(tree)};"
72
- }.condition{|*x| x.size == 2 }
73
-
74
- define_method_handler(:to_c, :priority => -10000) do |*x|
75
- tree, result_var = x
76
-
77
- raise "undefined translator for node type :#{tree.node_type}"
78
- end
79
-
80
- define_method_handler(:initialize_to_c){|*x|}.condition{|*x|false}
81
-
82
- define_translator_for(:call, :priority => 100){ |*x|
83
- tree, result_var = x
84
-
85
- tree[2] = :fastruby_require
86
- to_c(tree)
87
- }.condition{|*x|
88
- tree = x.first; tree.node_type == :call && tree[2] == :require
89
- }
90
-
91
- define_method_handler(:infer_value, :priority => -1000) do |tree|
92
- nil
93
- end
94
-
95
- FastRuby::Modules.load_all("translator")
96
-
97
- def catch_block(*catchs)
98
- old_catch_blocks = @catch_blocks.dup
99
- begin
100
- catchs.each &@catch_blocks.method(:<<)
101
- return yield
102
- ensure
103
- @catch_blocks = old_catch_blocks
104
- end
105
- end
106
-
107
- def initialize(common_func = true, inferencer = nil)
108
- initialize_to_c
109
-
110
- @inferencer = inferencer
111
- @catch_blocks = []
112
- @no_cache = false
113
- @extra_code = ""
114
- @options = {}
115
- @init_extra = Array.new
116
- @frame_struct = "struct {
117
- void* parent_frame;
118
- void* plocals;
119
- jmp_buf jmp;
120
- VALUE return_value;
121
- int rescue;
122
- VALUE last_error;
123
- VALUE next_recv;
124
- int targetted;
125
- struct FASTRUBYTHREADDATA* thread_data;
126
- }"
127
-
128
- @block_struct = "struct {
129
- void* block_function_address;
130
- void* block_function_param;
131
- VALUE proc;
132
- }"
133
-
134
- extra_code << "
135
- static void frb_jump_tag(int state) {
136
- VALUE exception = rb_funcall(#{literal_value FastRuby::JumpTagException}, #{intern_num :new},1,INT2FIX(state));
137
- rb_exc_raise(exception);
138
- }
139
- "
140
-
141
- extra_code << "
142
- #define FASTRUBY_TAG_RETURN 0x80
143
- #define FASTRUBY_TAG_NEXT 0x81
144
- #define FASTRUBY_TAG_BREAK 0x82
145
- #define FASTRUBY_TAG_RAISE 0x83
146
- #define FASTRUBY_TAG_REDO 0x84
147
- #define FASTRUBY_TAG_RETRY 0x85
148
- #define TAG_RAISE 0x6
149
-
150
- # define PTR2NUM(x) (ULONG2NUM((unsigned long)(x)))
151
- # define NUM2PTR(x) ((void*)(NUM2ULONG(x)))
152
-
153
- #ifndef __INLINE_FASTRUBY_BASE
154
- #include \"#{FastRuby.fastruby_load_path}/../ext/fastruby_base/fastruby_base.inl\"
155
- #define __INLINE_FASTRUBY_BASE
156
- #endif
157
- "
158
-
159
- ruby_code = "
160
- unless $LOAD_PATH.include? #{FastRuby.fastruby_load_path.inspect}
161
- $LOAD_PATH << #{FastRuby.fastruby_load_path.inspect}
162
- end
163
- require #{FastRuby.fastruby_script_path.inspect}
164
- "
165
-
166
- init_extra << "
167
- rb_eval_string(#{ruby_code.inspect});
168
- "
169
-
170
-
171
- if RUBY_VERSION =~ /^1\.8/
172
-
173
- @lambda_node_gvar = add_global_name("NODE*", 0);
174
- @proc_node_gvar = add_global_name("NODE*", 0);
175
- @procnew_node_gvar = add_global_name("NODE*", 0);
176
- @callcc_node_gvar = add_global_name("NODE*", 0);
177
-
178
- init_extra << "
179
- #{@lambda_node_gvar} = rb_method_node(rb_cObject, #{intern_num :lambda});
180
- #{@proc_node_gvar} = rb_method_node(rb_cObject, #{intern_num :proc});
181
- #{@procnew_node_gvar} = rb_method_node(CLASS_OF(rb_cProc), #{intern_num :new});
182
- #{@callcc_node_gvar} = rb_method_node(rb_mKernel, #{intern_num :callcc});
183
- "
184
- elsif RUBY_VERSION =~ /^1\.9/
185
-
186
- @lambda_node_gvar = add_global_name("void*", 0);
187
- @proc_node_gvar = add_global_name("void*", 0);
188
- @procnew_node_gvar = add_global_name("void*", 0);
189
- @callcc_node_gvar = add_global_name("void*", 0);
190
-
191
- init_extra << "
192
- #{@lambda_node_gvar} = rb_method_entry(rb_cObject, #{intern_num :lambda});
193
- #{@proc_node_gvar} = rb_method_entry(rb_cObject, #{intern_num :proc});
194
- #{@procnew_node_gvar} = rb_method_entry(CLASS_OF(rb_const_get(rb_cObject, #{intern_num :Proc})), #{intern_num :new});
195
- #{@callcc_node_gvar} = rb_method_entry(rb_mKernel, #{intern_num :callcc});
196
- "
197
- end
198
-
199
- @common_func = common_func
200
- if common_func
201
- extra_code << "static VALUE _rb_gvar_set(void* ge,VALUE value) {
202
- rb_gvar_set((struct global_entry*)ge,value);
203
- return value;
204
- }
205
- "
206
-
207
- extra_code << "static VALUE re_yield(int argc, VALUE* argv, VALUE param, VALUE _parent_frame) {
208
- VALUE yield_args = rb_ary_new4(argc,argv);
209
- VALUE* yield_args_p = &yield_args;
210
-
211
- #{@frame_struct}* pframe;
212
- pframe = (typeof(pframe))_parent_frame;
213
-
214
- return #{protected_block("last_expression = rb_yield_splat(*(VALUE*)yield_args_p)",true,"yield_args_p",true)};
215
- }"
216
-
217
- extra_code << "static VALUE _rb_ivar_set(VALUE recv,ID idvar, VALUE value) {
218
- rb_ivar_set(recv,idvar,value);
219
- return value;
220
- }
221
- "
222
-
223
- extra_code << "static VALUE __rb_cvar_set(VALUE recv,ID idvar, VALUE value, int warn) {
224
- #{if RUBY_VERSION =~ /^1\.9/
225
- "rb_cvar_set(recv,idvar,value);"
226
- elsif RUBY_VERSION =~ /^1\.8/
227
- "rb_cvar_set(recv,idvar,value,warn);"
228
- else
229
- raise RuntimeError, "unsupported ruby version #{RUBY_VERSION}"
230
- end
231
- }
232
-
233
- return value;
234
- }
235
- "
236
-
237
- extra_code << "static VALUE _lvar_assing(VALUE* destination,VALUE value) {
238
- *destination = value;
239
- return value;
240
- }
241
-
242
- /*
243
- #{caller.join("\n")}
244
- */
245
-
246
- "
247
-
248
- end
249
- end
250
-
251
-
252
- def _raise(class_tree, message_tree = nil)
253
- class_tree = to_c class_tree unless class_tree.instance_of? String
254
-
255
- if message_tree.instance_of? String
256
- message_tree = "rb_str_new2(#{message_tree.inspect})"
257
- else
258
- message_tree = to_c message_tree
259
- end
260
-
261
- if message_tree
262
- return inline_block("
263
- pframe->thread_data->exception = rb_funcall(#{class_tree}, #{intern_num :exception},1,#{message_tree});
264
- longjmp(pframe->jmp, FASTRUBY_TAG_RAISE);
265
- return Qnil;
266
- ")
267
- else
268
- return inline_block("
269
- pframe->thread_data->exception = rb_funcall(#{class_tree}, #{intern_num :exception},0);
270
- longjmp(pframe->jmp, FASTRUBY_TAG_RAISE);
271
- return Qnil;
272
- ")
273
- end
274
-
275
- end
276
-
277
- def anonymous_function(*x)
278
-
279
- name = "anonymous" + rand(10000000).to_s
280
- extra_code << yield(name,*x)
281
-
282
- name
283
- end
284
-
285
- def frame_call(inner_code, precode = "", postcode = "")
286
- inline_block "
287
-
288
- volatile VALUE ret = Qnil;
289
- // create a call_frame
290
- #{@frame_struct} call_frame;
291
- typeof(call_frame)* volatile old_pframe = (void*)pframe;
292
-
293
- pframe = (typeof(pframe))&call_frame;
294
-
295
- call_frame.parent_frame = (void*)pframe;
296
- call_frame.plocals = plocals;
297
- call_frame.return_value = Qnil;
298
- call_frame.targetted = 0;
299
- call_frame.thread_data = old_pframe->thread_data;
300
- if (call_frame.thread_data == 0) call_frame.thread_data = rb_current_thread_data();
301
-
302
- void* volatile old_call_frame = plocals->call_frame;
303
- plocals->call_frame = &call_frame;
304
-
305
- #{precode}
306
-
307
- int aux = setjmp(call_frame.jmp);
308
- if (aux != 0) {
309
- if (call_frame.targetted == 0) {
310
- #{postcode}
311
- longjmp(old_pframe->jmp,aux);
312
- }
313
-
314
- if (aux == FASTRUBY_TAG_BREAK) {
315
- plocals->call_frame = old_call_frame;
316
- #{postcode}
317
- return call_frame.return_value;
318
- } else if (aux == FASTRUBY_TAG_RETRY ) {
319
- // do nothing and let the call execute again
320
- } else {
321
- plocals->call_frame = old_call_frame;
322
- #{postcode}
323
- return call_frame.return_value;
324
- }
325
- }
326
-
327
-
328
- #{inner_code};
329
-
330
- #{postcode}
331
-
332
- plocals->call_frame = old_call_frame;
333
- return ret;
334
- "
335
- end
336
-
337
- def initialize_method_structs(args_tree)
338
- @locals_struct = "struct {
339
- int size;
340
- void* call_frame;
341
- void* parent_locals;
342
- void* pframe;
343
- void* block_function_address;
344
- void* block_function_param;
345
- VALUE active;
346
- VALUE targetted;
347
- VALUE return_value;
348
- #{@locals.map{|l| "VALUE #{l};\n"}.join}
349
- }"
350
-
351
- end
352
-
353
- def add_main
354
- if options[:main]
355
-
356
- extra_code << "
357
- static VALUE #{@alt_method_name}(VALUE self__);
358
- static VALUE main_proc_call(VALUE self__, VALUE signature, VALUE class_self_) {
359
- #{@alt_method_name}(class_self_);
360
- return Qnil;
361
- }
362
-
363
- "
364
-
365
- init_extra << "
366
- {
367
- VALUE newproc = rb_funcall(rb_cObject,#{intern_num :new},0);
368
- rb_define_singleton_method(newproc, \"call\", main_proc_call, 2);
369
- rb_gv_set(\"$last_obj_proc\", newproc);
370
- }
371
- "
372
- end
373
- end
374
-
375
- def define_method_at_init(method_name, size, signature)
376
- extra_code << "
377
- static VALUE main_proc_call(VALUE self__, VALUE signature, VALUE class_self_) {
378
- VALUE method_name = rb_funcall(
379
- #{literal_value FastRuby},
380
- #{intern_num :make_str_signature},
381
- 2,
382
- #{literal_value method_name},
383
- signature
384
- );
385
-
386
- ID id = rb_intern(RSTRING_PTR(method_name));
387
-
388
- rb_funcall(
389
- #{literal_value FastRuby},
390
- #{intern_num :set_builder_module},
391
- 1,
392
- class_self_
393
- );
394
-
395
- VALUE rb_method_hash;
396
- void** address = 0;
397
- rb_method_hash = rb_funcall(class_self_, #{intern_num :method_hash},1,#{literal_value method_name});
398
-
399
- if (rb_method_hash != Qnil) {
400
- VALUE tmp = rb_hash_aref(rb_method_hash, PTR2NUM(id));
401
- if (tmp != Qnil) {
402
- address = (void*)NUM2PTR(tmp);
403
- }
404
- }
405
-
406
- if (address == 0) {
407
- address = malloc(sizeof(void*));
408
- }
409
- *address = #{@alt_method_name};
410
-
411
- rb_funcall(
412
- class_self_,
413
- #{intern_num :register_method_value},
414
- 3,
415
- #{literal_value method_name},
416
- PTR2NUM(id),
417
- PTR2NUM(address)
418
- );
419
-
420
- return Qnil;
421
- }
422
- "
423
-
424
- init_extra << "
425
- {
426
- VALUE newproc = rb_funcall(rb_cObject,#{intern_num :new},0);
427
- rb_define_singleton_method(newproc, \"call\", main_proc_call, 2);
428
- rb_gv_set(\"$last_obj_proc\", newproc);
429
- }
430
- "
431
- end
432
-
433
- def to_c_method(tree, signature = nil)
434
-
435
- if tree[0] == :defn
436
- method_name = tree[1]
437
- original_args_tree = tree[2]
438
- block_argument = tree[2].find{|x| x.to_s[0] == ?&}
439
- impl_tree = tree[3][1]
440
- elsif tree[0] == :defs
441
- method_name = tree[2]
442
- original_args_tree = tree[3]
443
- block_argument = tree[3].find{|x| x.to_s[0] == ?&}
444
- impl_tree = tree[4][1]
445
- end
446
-
447
- if "0".respond_to?(:ord)
448
- @alt_method_name = "_" + method_name.to_s.gsub("_x_", "_x__x_").gsub(/\W/){|x| "_x_#{x.ord}" } + "_" + rand(10000000000).to_s
449
- else
450
- @alt_method_name = "_" + method_name.to_s.gsub("_x_", "_x__x_").gsub(/\W/){|x| "_x_#{x[0]}" } + "_" + rand(10000000000).to_s
451
- end
452
-
453
- args_tree = original_args_tree.select{|x| x.to_s[0] != ?&}
454
-
455
- initialize_method_structs(original_args_tree)
456
-
457
- if options[:main] then
458
- strargs = if args_tree.size > 1
459
- "VALUE self, VALUE block, VALUE _parent_frame, #{(0..signature.size-1).map{|x| "VALUE arg#{x}"}.join(",")}"
460
- else
461
- "VALUE self, VALUE block, VALUE _parent_frame"
462
- end
463
-
464
- else
465
-
466
- strargs = "VALUE self, VALUE block, VALUE _parent_frame, int argc, VALUE* argv"
467
-
468
- splat_arg = args_tree[1..-1].find{|x| x.to_s.match(/\*/) }
469
-
470
- maxargnum = args_tree[1..-1].count{ |x|
471
- if x.instance_of? Symbol
472
- not x.to_s.match(/\*/) and not x.to_s.match(/\&/)
473
- else
474
- false
475
- end
476
- }
477
-
478
- minargnum = maxargnum
479
-
480
- args_tree[1..-1].each do |subtree|
481
- unless subtree.instance_of? Symbol
482
- if subtree[0] == :block
483
- minargnum = minargnum - (subtree.size-1)
484
- end
485
- end
486
- end
487
-
488
- if args_tree[1..-1].find{|x| x.to_s.match(/\*/)}
489
- maxargnum = 2147483647
490
- end
491
-
492
- read_arguments_code = ""
493
-
494
-
495
- validate_arguments_code = if signature.size-1 < minargnum
496
- "
497
- rb_raise(rb_eArgError, \"wrong number of arguments (#{signature.size-1} for #{minargnum})\");
498
- "
499
- elsif signature.size-1 > maxargnum
500
- "
501
- rb_raise(rb_eArgError, \"wrong number of arguments (#{signature.size-1} for #{maxargnum})\");
502
- "
503
- else
504
-
505
- default_block_tree = args_tree[1..-1].find{|subtree|
506
- unless subtree.instance_of? Symbol
507
- if subtree[0] == :block
508
- next true
509
- end
510
- end
511
-
512
- false
513
- }
514
-
515
- i = -1
516
-
517
- normalargsnum = args_tree[1..-1].count{|subtree|
518
- if subtree.instance_of? Symbol
519
- unless subtree.to_s.match(/\*/) or subtree.to_s.match(/\&/)
520
- next true
521
- end
522
- end
523
-
524
- false
525
- }
526
-
527
- read_arguments_code = args_tree[1..-1].map { |arg_|
528
- arg = arg_.to_s
529
- i = i + 1
530
-
531
- if i < normalargsnum
532
- if i < signature.size-1
533
- "plocals->#{arg} = argv[#{i}];\n"
534
- else
535
-
536
- if default_block_tree
537
- initialize_tree = default_block_tree[1..-1].find{|subtree| subtree[1] == arg_}
538
- if initialize_tree
539
- to_c(initialize_tree) + ";\n"
540
- else
541
- ""
542
- end
543
- else
544
- ";\n"
545
- end
546
- end
547
- else
548
- ""
549
- end
550
- }.join("")
551
-
552
- if splat_arg
553
- if signature.size-1 < normalargsnum then
554
- read_arguments_code << "
555
- plocals->#{splat_arg.to_s.gsub("*","")} = rb_ary_new3(0);
556
- "
557
- else
558
- read_arguments_code << "
559
- plocals->#{splat_arg.to_s.gsub("*","")} = rb_ary_new4(
560
- #{(signature.size-1) - (normalargsnum)}, argv+#{normalargsnum}
561
- );
562
- "
563
- end
564
-
565
- end
566
-
567
-
568
- ""
569
- end
570
-
571
- if block_argument
572
-
573
- 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))))
574
-
575
- require "fastruby/sexp_extension"
576
-
577
- read_arguments_code << "
578
- if (pblock ? pblock->proc != Qnil : 0) {
579
- plocals->#{block_argument.to_s.gsub("&","")} = pblock->proc;
580
- } else {
581
- plocals->#{block_argument.to_s.gsub("&","")} = #{to_c FastRuby::FastRubySexp.from_sexp(proc_reyield_block_tree)};
582
- }
583
- "
584
-
585
- read_arguments_code << "
586
- if (pblock) {
587
- rb_ivar_set(plocals->#{block_argument.to_s.gsub("&","")},
588
- #{intern_num "__block_address"}, PTR2NUM(pblock->block_function_address));
589
- rb_ivar_set(plocals->#{block_argument.to_s.gsub("&","")},
590
- #{intern_num "__block_param"}, PTR2NUM(pblock->block_function_param));
591
- }
592
-
593
- "
594
- end
595
-
596
- end
597
-
598
- require "fastruby/sexp_extension"
599
-
600
- trs = lambda{|tree|
601
- if not tree.respond_to? :node_type
602
- next tree
603
- elsif tree.node_type == :call
604
- mmname = tree[2]
605
- next trs.call(tree[1]) || tree[1] if mmname == :infer
606
- next fs(:nil) if mmname == :_throw or mmname == :_loop or mmname == :_raise
607
- next fs(:nil) if mmname == :== and infer_value(tree)
608
- elsif tree.node_type == :iter
609
- mmname = tree[1][2]
610
- next fs(:nil) if mmname == :_static
611
- next fs(:block, trs.call(tree[3]) || tree[3]) if mmname == :_catch
612
- end
613
-
614
- tree.map &trs
615
- }
616
-
617
- evaluate_tree = tree.transform &trs
618
-
619
- scope_mode = FastRuby::ScopeModeHelper.get_scope_mode(evaluate_tree)
620
- ret = "VALUE #{@alt_method_name || method_name}(#{options[:main] ? "VALUE self" : strargs}) {
621
- #{validate_arguments_code}
622
-
623
- #{@frame_struct} frame;
624
- #{@frame_struct} * volatile pframe;
625
-
626
- frame.parent_frame = #{options[:main] ? "0" : "(void*)_parent_frame"};
627
- frame.return_value = Qnil;
628
- frame.rescue = 0;
629
- frame.targetted = 0;
630
- frame.thread_data = #{options[:main] ? "0" : "((typeof(pframe))_parent_frame)->thread_data"};
631
- if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
632
-
633
- int stack_chunk_instantiated = 0;
634
-
635
- #{
636
- if scope_mode == :dag
637
- "
638
- volatile VALUE rb_previous_stack_chunk = Qnil;
639
- VALUE rb_stack_chunk = frame.thread_data->rb_stack_chunk;
640
- struct STACKCHUNK* volatile stack_chunk = 0;
641
-
642
- if (rb_stack_chunk != Qnil) {
643
- Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
644
- }
645
-
646
- if (stack_chunk == 0 || (stack_chunk == 0 ? 0 : stack_chunk_frozen(stack_chunk)) ) {
647
- rb_previous_stack_chunk = rb_stack_chunk;
648
- rb_gc_register_address(&rb_stack_chunk);
649
- stack_chunk_instantiated = 1;
650
-
651
- rb_stack_chunk = rb_stack_chunk_create(Qnil);
652
- frame.thread_data->rb_stack_chunk = rb_stack_chunk;
653
-
654
- rb_ivar_set(rb_stack_chunk, #{intern_num :_parent_stack_chunk}, rb_previous_stack_chunk);
655
-
656
- Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
657
- }
658
-
659
- #{@locals_struct}* volatile plocals;
660
-
661
- volatile int previous_stack_position = stack_chunk_get_current_position(stack_chunk);
662
- plocals = (typeof(plocals))stack_chunk_alloc(stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
663
-
664
- "
665
- else
666
- "
667
- #{@locals_struct} locals;
668
- typeof(locals) * volatile plocals = &locals;
669
- "
670
- end
671
- }
672
-
673
- plocals->parent_locals = (frame.thread_data->last_plocals);
674
- void* volatile old_parent_locals = frame.thread_data->last_plocals;
675
-
676
- #{
677
- if scope_mode == :dag
678
- "frame.thread_data->last_plocals = plocals;\n"
679
- end
680
- }
681
-
682
- frame.plocals = plocals;
683
- plocals->active = Qtrue;
684
- plocals->targetted = Qfalse;
685
- plocals->pframe = (&frame);
686
- plocals->call_frame = (0);
687
-
688
- pframe = (void*)&frame;
689
-
690
- #{@block_struct} * volatile pblock;
691
- volatile VALUE last_expression = Qnil;
692
-
693
- int aux = setjmp(pframe->jmp);
694
- if (aux != 0) {
695
- plocals->active = Qfalse;
696
-
697
- #{
698
- if scope_mode == :dag
699
- "
700
- stack_chunk_set_current_position(stack_chunk, previous_stack_position);
701
-
702
- if (stack_chunk_instantiated) {
703
- rb_gc_unregister_address(&rb_stack_chunk);
704
- frame.thread_data->rb_stack_chunk = rb_previous_stack_chunk;
705
- }
706
- "
707
- end
708
- }
709
- #{
710
- unless options[:main]
711
- "
712
- if (plocals->targetted == Qfalse || aux != FASTRUBY_TAG_RETURN) {
713
- frame.thread_data->last_plocals = old_parent_locals;
714
-
715
- longjmp(((typeof(pframe))_parent_frame)->jmp,aux);
716
- }
717
- "
718
- end
719
- }
720
-
721
- frame.thread_data->last_plocals = old_parent_locals;
722
-
723
- return plocals->return_value;
724
- }
725
-
726
- plocals->self = self;
727
-
728
- #{
729
- unless options[:main]
730
- "
731
- pblock = (void*)block;
732
- if (pblock) {
733
- plocals->block_function_address = pblock->block_function_address;
734
- plocals->block_function_param = pblock->block_function_param;
735
- } else {
736
- plocals->block_function_address = (0);
737
- plocals->block_function_param = 0;
738
- }
739
- "
740
- end
741
- }
742
-
743
- #{read_arguments_code}
744
-
745
- #{to_c impl_tree, "last_expression"};
746
-
747
- local_return:
748
- #{
749
- if scope_mode == :dag
750
- "
751
- stack_chunk_set_current_position(stack_chunk, previous_stack_position);
752
-
753
- if (stack_chunk_instantiated) {
754
- rb_gc_unregister_address(&rb_stack_chunk);
755
- frame.thread_data->rb_stack_chunk = rb_previous_stack_chunk;
756
- }
757
- "
758
- end
759
- }
760
- plocals->active = Qfalse;
761
-
762
- frame.thread_data->last_plocals = old_parent_locals;
763
-
764
- return last_expression;
765
- }"
766
-
767
- add_main
768
- extra_code << ret
769
-
770
- "
771
- static VALUE dummy_#{@alt_method_name}_#{rand(1000000000000000000000000000000000)}(VALUE a) {
772
- return Qnil;
773
- }
774
- "
775
- end
776
-
777
- def locals_accessor
778
- "plocals->"
779
- end
780
-
781
- def locals_scope(locals)
782
- old_locals = @locals
783
- old_locals_struct = @locals_struct
784
-
785
- @locals = locals
786
- @locals_struct = "struct {
787
- int size;
788
- void* call_frame;
789
- void* parent_locals;
790
- void* pframe;
791
- void* block_function_address;
792
- void* block_function_param;
793
- VALUE active;
794
- VALUE targetted;
795
- VALUE return_value;
796
- #{@locals.map{|l| "VALUE #{l};\n"}.join}
797
- }"
798
-
799
- begin
800
- yield
801
- ensure
802
- @locals = old_locals
803
- @locals_struct = old_locals_struct
804
- end
805
- end
806
-
807
- def infer_type(recv)
808
- array = @inferencer.infer(recv).to_a
809
-
810
- if array.size == 1
811
- array[0]
812
- else
813
- nil
814
- end
815
- end
816
-
817
- def on_block
818
- old_on_block = @on_block
819
- @on_block = true
820
- return yield
821
- ensure
822
- @on_block = old_on_block
823
- end
824
-
825
- def directive(tree)
826
- recv = tree[1]
827
- mname = tree[2]
828
- args = tree[3]
829
-
830
- if mname == :infer
831
- return to_c(recv)
832
- elsif mname == :block_given?
833
- return "plocals->block_function_address == 0 ? Qfalse : Qtrue"
834
- elsif mname == :inline_c
835
-
836
- code = args[1][1]
837
-
838
- unless (args[2] == s(:false))
839
- return anonymous_function{ |name| "
840
- static VALUE #{name}(VALUE param) {
841
- #{@frame_struct} *pframe = (void*)param;
842
- #{@locals_struct} *plocals = (void*)pframe->plocals;
843
- #{code};
844
-
845
- return Qnil;
846
- }
847
- "
848
- }+"((VALUE)pframe)"
849
- else
850
- code
851
- end
852
-
853
- else
854
- nil
855
- end
856
- end
857
-
858
- def inline_block_reference(arg, nolocals = false)
859
- code = nil
860
-
861
- if arg.instance_of? FastRuby::FastRubySexp
862
- code = to_c(arg);
863
- else
864
- code = arg
865
- end
866
-
867
- anonymous_function{ |name| "
868
- static VALUE #{name}(VALUE param) {
869
- #{@frame_struct} *pframe = (void*)param;
870
-
871
- #{nolocals ? "" : "#{@locals_struct} *plocals = (void*)pframe->plocals;"}
872
- VALUE last_expression = Qnil;
873
-
874
- #{code};
875
- return last_expression;
876
- }
877
- "
878
- }
879
- end
880
-
881
- def catch_on_throw
882
- old_catch_jmp_on_throw = @catch_jmp_on_throw || false
883
- @catch_jmp_on_throw = true
884
- begin
885
- ret = yield
886
- ensure
887
- @catch_jmp_on_throw = old_catch_jmp_on_throw
888
- end
889
-
890
- ret
891
- end
892
-
893
- def inline_block(*args)
894
-
895
- unless block_given?
896
- code = args.first
897
- return inline_block(*args[1..-1]) {
898
- code
899
- }
900
- end
901
-
902
- repass_var = args[0]
903
- nolocals = args[1] || false
904
-
905
- code = catch_on_throw{ yield }
906
-
907
- anonymous_function{ |name| "
908
- static VALUE #{name}(VALUE param#{repass_var ? ",void* " + repass_var : "" }) {
909
- #{@frame_struct} * volatile pframe = (void*)param;
910
-
911
- #{nolocals ? "" : "#{@locals_struct} * volatile plocals = (void*)pframe->plocals;"}
912
- volatile VALUE last_expression = Qnil;
913
-
914
- #{code}
915
- return Qnil;
916
-
917
-
918
- #{@catch_blocks.map { |cb|
919
- "#{cb.to_s}_end:
920
-
921
- plocals->return_value = last_expression;
922
- plocals->targetted = 1;
923
- longjmp(pframe->jmp, #{intern_num( cb.to_s + "_end")});
924
-
925
- #{cb.to_s}_start:
926
-
927
- plocals->return_value = last_expression;
928
- plocals->targetted = 1;
929
- longjmp(pframe->jmp, #{intern_num( cb.to_s + "_start")});
930
-
931
- "
932
-
933
- }.join("\n")
934
- }
935
- #{unless nolocals
936
- "
937
- local_return:
938
- plocals->return_value = last_expression;
939
- plocals->targetted = 1;
940
- longjmp(pframe->jmp, FASTRUBY_TAG_RETURN);
941
- return last_expression;
942
- "
943
- end
944
- }
945
- fastruby_local_redo:
946
- longjmp(pframe->jmp,FASTRUBY_TAG_REDO);
947
- return Qnil;
948
- fastruby_local_next:
949
- longjmp(pframe->jmp,FASTRUBY_TAG_NEXT);
950
- return Qnil;
951
-
952
-
953
- }
954
- "
955
- } + "((VALUE)pframe#{repass_var ? ", " + repass_var : "" })"
956
- end
957
-
958
- def inline_ruby(proced, parameter)
959
- "rb_funcall(#{proced.__id__}, #{intern_num :call}, 1, #{parameter})"
960
- end
961
-
962
- def protected_block(*args)
963
- unless block_given?
964
- inner_code = args.first
965
- return protected_block(*args[1..-1]) {
966
- inner_code
967
- }
968
- end
969
-
970
- repass_var = args[1]
971
- nolocals = args[2] || false
972
-
973
- inline_block(repass_var, nolocals) do
974
- generate_protected_block(yield, *args)
975
- end
976
- end
977
-
978
- def generate_protected_block(inner_code, always_rescue = false,repass_var = nil, nolocals = false)
979
- body = nil
980
- rescue_args = nil
981
-
982
- body = anonymous_function{ |name| "
983
- static VALUE #{name}(VALUE param) {
984
-
985
- #{@frame_struct} frame;
986
-
987
- typeof(frame)* volatile pframe;
988
-
989
- #{if repass_var
990
- "typeof(frame)* parent_frame = ((typeof(pframe))((void**)param)[0]);"
991
- else
992
- "typeof(frame)* parent_frame = (typeof(pframe))param;"
993
- end
994
- }
995
-
996
- frame.parent_frame = 0;
997
- frame.return_value = Qnil;
998
- frame.rescue = 0;
999
- frame.last_error = Qnil;
1000
- frame.targetted = 0;
1001
- frame.thread_data = parent_frame->thread_data;
1002
- frame.next_recv = parent_frame->next_recv;
1003
- if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
1004
-
1005
- pframe = &frame;
1006
-
1007
- #{
1008
- nolocals ? "frame.plocals = 0;" : "#{@locals_struct}* plocals = parent_frame->plocals;
1009
- frame.plocals = plocals;
1010
- "
1011
- }
1012
-
1013
- int aux = setjmp(frame.jmp);
1014
- if (aux != 0) {
1015
-
1016
- if (frame.targetted == 1) {
1017
- return frame.return_value;
1018
- } else {
1019
- frb_jump_tag(aux);
1020
- }
1021
- }
1022
-
1023
- #{if repass_var
1024
- "VALUE #{repass_var} = (VALUE)((void**)param)[1];"
1025
- end
1026
- }
1027
- volatile VALUE last_expression = Qnil;
1028
- #{inner_code};
1029
- return last_expression;
1030
- }
1031
- "
1032
- }
1033
-
1034
- if repass_var
1035
- rescue_args = ""
1036
- rescue_args = "(VALUE)(VALUE[]){(VALUE)pframe,(VALUE)#{repass_var}}"
1037
- else
1038
- rescue_args = "(VALUE)pframe"
1039
- end
1040
-
1041
- wrapper_code = "
1042
- if (str.state >= 0x80) {
1043
- longjmp(pframe->jmp, str.state);
1044
- } else {
1045
- if (str.last_error != Qnil) {
1046
- // raise emulation
1047
- pframe->thread_data->exception = str.last_error;
1048
- longjmp(pframe->jmp, FASTRUBY_TAG_RAISE);
1049
- return Qnil;
1050
- }
1051
- }
1052
- "
1053
-
1054
- return_err_struct = "struct {
1055
- VALUE last_error;
1056
- int state;
1057
- }
1058
- "
1059
-
1060
- rescue_body = anonymous_function{ |name| "
1061
- static VALUE #{name}(VALUE param, VALUE err) {
1062
- #{return_err_struct} *pstr = (void*)param;
1063
-
1064
- if (rb_obj_is_instance_of(err, #{literal_value FastRuby::JumpTagException})) {
1065
- pstr->state = FIX2INT(rb_funcall(err, #{intern_num :state}, 0));
1066
- } else {
1067
- pstr->last_error = err;
1068
- }
1069
-
1070
- return Qnil;
1071
- }
1072
- "
1073
- }
1074
-
1075
- rescue_code = "rb_rescue2(#{body}, #{rescue_args}, #{rescue_body}, (VALUE)&str, rb_eException, (VALUE)0)"
1076
-
1077
- if always_rescue
1078
- "
1079
- #{return_err_struct} str;
1080
-
1081
- str.state = 0;
1082
- str.last_error = Qnil;
1083
-
1084
- pframe->last_error = Qnil;
1085
- VALUE result = #{rescue_code};
1086
-
1087
- #{wrapper_code}
1088
-
1089
- return result;
1090
- "
1091
- else
1092
- "
1093
- VALUE result;
1094
- #{return_err_struct} str;
1095
-
1096
- str.state = 0;
1097
- str.last_error = Qnil;
1098
-
1099
- pframe->last_error = Qnil;
1100
-
1101
- if (pframe->rescue) {
1102
- result = #{rescue_code};
1103
- #{wrapper_code}
1104
- } else {
1105
- VALUE last_expression = Qnil;
1106
- #{inner_code};
1107
- return last_expression;
1108
- }
1109
-
1110
- return result;
1111
- "
1112
- end
1113
- end
1114
-
1115
- def c_escape(str)
1116
- str.inspect
1117
- end
1118
-
1119
- def literal_value(value)
1120
- @literal_value_hash = Hash.new unless @literal_value_hash
1121
- return @literal_value_hash[value] if @literal_value_hash[value]
1122
-
1123
- name = self.add_global_name("VALUE", "Qnil");
1124
-
1125
- begin
1126
-
1127
- str = Marshal.dump(value)
1128
-
1129
-
1130
- if value.instance_of? Module
1131
-
1132
- container_str = value.to_s.split("::")[0..-2].join("::")
1133
-
1134
- init_extra << "
1135
- #{name} = rb_define_module_under(
1136
- #{container_str == "" ? "rb_cObject" : literal_value(eval(container_str))}
1137
- ,\"#{value.to_s.split("::").last}\");
1138
-
1139
- rb_funcall(#{name},#{intern_num :gc_register_object},0);
1140
- "
1141
- elsif value.instance_of? Class
1142
- container_str = value.to_s.split("::")[0..-2].join("::")
1143
-
1144
- str_class_name = value.to_s.split("::").last
1145
-
1146
- if (str_class_name == "Object")
1147
- init_extra << "
1148
- #{name} = rb_cObject;
1149
- "
1150
- else
1151
- init_extra << "
1152
- #{name} = rb_define_class_under(
1153
- #{container_str == "" ? "rb_cObject" : literal_value(eval(container_str))}
1154
- ,\"#{str_class_name}\"
1155
- ,#{value.superclass == Object ? "rb_cObject" : literal_value(value.superclass)});
1156
-
1157
- rb_funcall(#{name},#{intern_num :gc_register_object},0);
1158
- "
1159
- end
1160
- elsif value.instance_of? Array
1161
- init_extra << "
1162
- #{name} = rb_ary_new3(#{value.size}, #{value.map{|x| literal_value x}.join(",")} );
1163
- rb_funcall(#{name},#{intern_num :gc_register_object},0);
1164
- "
1165
- else
1166
-
1167
- init_extra << "
1168
-
1169
- {
1170
- VALUE encoded_str = rb_str_new2(#{Base64.encode64(str).inspect});
1171
- VALUE str = rb_funcall(rb_cObject, #{intern_num :decode64}, 1, encoded_str);
1172
- #{name} = rb_marshal_load(str);
1173
-
1174
- rb_funcall(#{name},#{intern_num :gc_register_object},0);
1175
- }
1176
-
1177
- "
1178
- end
1179
- rescue TypeError => e
1180
- @no_cache = true
1181
- FastRuby.logger.info "#{value} disabling cache for extension"
1182
- init_extra << "
1183
- #{name} = rb_funcall(rb_const_get(rb_cObject, #{intern_num :ObjectSpace}), #{intern_num :_id2ref}, 1, INT2FIX(#{value.__id__}));
1184
- "
1185
-
1186
- end
1187
- @literal_value_hash[value] = name
1188
-
1189
- name
1190
- end
1191
-
1192
- def encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name = nil, is_block_call = false)
1193
- name = self.add_global_name("void*", 0);
1194
- address_name = self.add_global_name("void**", 0);
1195
- @last_address_name = address_name
1196
- cfunc_address_name = self.add_global_name("void**", 0);
1197
- cfunc_real_address_name = self.add_global_name("void*", 0);
1198
- tree_pointer_name = self.add_global_name("VALUE*", 0);
1199
-
1200
- if call_tree[3].select{|st| st.respond_to?(:node_type) ? st[0] == :block_pass : false}
1201
- is_block_call = true
1202
- end
1203
-
1204
- args_tree = call_tree[3].reject{|st| st.respond_to?(:node_type) ? st[0] == :block_pass : false}
1205
- method_tree = nil
1206
-
1207
- begin
1208
- method_tree = recvtype.instance_method(@method_name.to_sym).fastruby.tree
1209
- rescue NoMethodError
1210
- end
1211
-
1212
- strargs_signature = (0..args_tree.size-2).map{|x| "VALUE arg#{x}"}.join(",")
1213
- strargs = (0..args_tree.size-2).map{|x| "arg#{x}"}.join(",")
1214
- inprocstrargs = (1..args_tree.size-1).map{|x| "((VALUE*)method_arguments)[#{x}]"}.join(",")
1215
-
1216
- if args_tree.size > 1
1217
- strargs_signature = "," + strargs_signature
1218
- toprocstrargs = "self,"+strargs
1219
- strargs = "," + strargs
1220
- inprocstrargs = ","+inprocstrargs
1221
- else
1222
- toprocstrargs = "self"
1223
- end
1224
-
1225
- value_cast = ( ["VALUE"]*(args_tree.size) ).join(",") + ",VALUE,VALUE"
1226
-
1227
- recvdump = nil
1228
-
1229
- begin
1230
- recvdump = literal_value recvtype
1231
- rescue
1232
- end
1233
-
1234
- pureruby_wrapper = anonymous_function{ |funcname| "
1235
- static VALUE #{funcname}(VALUE self,void* block,void* frame, int argc, VALUE* argv){
1236
- #{@frame_struct}* pframe = frame;
1237
- VALUE method_arguments[3];
1238
-
1239
- method_arguments[0] = (VALUE)argc;
1240
- method_arguments[1] = (VALUE)argv;
1241
- method_arguments[2] = (VALUE)self;
1242
-
1243
- return #{
1244
- protected_block "last_expression = rb_funcall2(((VALUE*)method_arguments)[2], #{intern_num mname.to_sym}, ((int*)method_arguments)[0], ((VALUE**)method_arguments)[1]);", false, "method_arguments"
1245
- };
1246
- }
1247
- "
1248
- }
1249
-
1250
- generic_wrapper = anonymous_function{ |funcname| "
1251
- static VALUE #{funcname}(VALUE self,void* block,void* frame, int argc, VALUE* argv){
1252
- #{@frame_struct}* pframe = frame;
1253
- VALUE method_arguments[4];
1254
-
1255
- method_arguments[0] = (VALUE)argc;
1256
- method_arguments[1] = (VALUE)argv;
1257
- method_arguments[2] = (VALUE)self;
1258
- method_arguments[3] = (VALUE)block;
1259
-
1260
- void* fptr = 0;
1261
-
1262
- if (*#{address_name} == 0) {
1263
- if (#{tree_pointer_name} != 0) {
1264
- if (*#{tree_pointer_name} != Qnil) {
1265
- VALUE signature = #{literal_value signature};
1266
- VALUE recvtype = #{recvdump};
1267
- VALUE mname = #{literal_value mname};
1268
-
1269
- rb_funcall(recvtype, #{intern_num :build}, 2, signature, mname);
1270
- }
1271
- }
1272
- }
1273
-
1274
- fptr = *#{address_name};
1275
-
1276
- if (fptr == 0) {
1277
- fptr = *#{cfunc_address_name};
1278
- if (fptr != 0) {
1279
- return ( (VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*) ) (fptr) )(self,(VALUE)block,(VALUE)frame, argc, argv);
1280
- }
1281
- }
1282
-
1283
- if (fptr == 0) {
1284
- if (block==0) {
1285
- return #{
1286
- protected_block "last_expression = rb_funcall2(((VALUE*)method_arguments)[2], #{intern_num mname.to_sym}, ((int*)method_arguments)[0], ((VALUE**)method_arguments)[1]);", false, "method_arguments"
1287
- };
1288
-
1289
- } else {
1290
- return #{
1291
- protected_block "
1292
- #{@block_struct} *pblock;
1293
- pblock = (typeof(pblock))( ((VALUE*)method_arguments)[3] );
1294
- last_expression = rb_iterate(
1295
- #{anonymous_function{|name_|
1296
- "
1297
- static VALUE #{name_} (VALUE data) {
1298
- VALUE* method_arguments = (VALUE*)data;
1299
- return rb_funcall2(((VALUE*)method_arguments)[2], #{intern_num mname.to_sym}, ((int*)method_arguments)[0], ((VALUE**)method_arguments)[1]);
1300
- }
1301
- "
1302
- }},
1303
- (VALUE)method_arguments,
1304
-
1305
- #{anonymous_function{|name_|
1306
- "
1307
- static VALUE #{name_} (VALUE arg_, VALUE param, int argc, VALUE* argv) {
1308
-
1309
- VALUE arg;
1310
- #{
1311
- # TODO: access directly to argc and argv for optimal execution
1312
- if RUBY_VERSION =~ /^1\.9/
1313
- "
1314
- if (TYPE(arg_) == T_ARRAY) {
1315
- if (_RARRAY_LEN(arg_) <= 1) {
1316
- arg = rb_ary_new4(argc,argv);
1317
- } else {
1318
- arg = arg_;
1319
- }
1320
- } else {
1321
- arg = rb_ary_new4(argc,argv);
1322
- }
1323
- "
1324
- else
1325
- "arg = arg_;"
1326
- end
1327
- }
1328
-
1329
- return rb_proc_call(param, arg);
1330
- }
1331
- "
1332
- }},
1333
- pblock->proc
1334
- );
1335
- ", false, "method_arguments"
1336
- };
1337
- }
1338
-
1339
- } else {
1340
- return ( (VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*)) (fptr) )(self,(VALUE)block,(VALUE)frame,argc,argv);
1341
- }
1342
- }
1343
- "
1344
- }
1345
-
1346
-
1347
- cfuncall1inprocargs = (0..args_tree.size-2).map{|x| "argv[#{x}]"}.join(",")
1348
- cfuncall1inprocargs = ","+cfuncall1inprocargs if cfuncall1inprocargs != ""
1349
-
1350
- cfunc_value_cast = (["VALUE"]*args_tree.size).join(",")
1351
- cfunc_wrapper = anonymous_function{ |funcname| "
1352
- static VALUE #{funcname}(VALUE self, void* block,void* frame, int argc, VALUE* argv){
1353
- return rb_vm_call(ruby_current_thread, self, #{intern_num mname.to_sym}, argc, argv, #{cfunc_real_address_name});
1354
- }
1355
- "
1356
- }
1357
-
1358
- toprocstrargs = (0..25).map{|x| "arg#{x}"}.join(",")
1359
- strargs_signature = (0..25).map{|x| "VALUE arg#{x}"}.join(",")
1360
-
1361
- cfunc_wrapper_1 = anonymous_function{ |funcname| "
1362
- static VALUE #{funcname}(VALUE self, void* block,void* frame, int argc, VALUE* argv){
1363
- return ( (VALUE(*)(int, VALUE*, VALUE)) (#{cfunc_real_address_name}) )(argc,argv,self);
1364
- }
1365
- "
1366
- }
1367
-
1368
- cfunc_wrapper_2 = anonymous_function{ |funcname| "
1369
- static VALUE #{funcname}(VALUE self, void* block,void* frame, int argc, VALUE* argv){
1370
- VALUE args = rb_ary_new3(argc, argv);
1371
- return ( (VALUE(*)(VALUE,VALUE)) (#{cfunc_real_address_name}) )(self,args);
1372
- }
1373
- "
1374
- }
1375
-
1376
- update_cfunc_method = anonymous_function{ |funcname| "
1377
- static VALUE #{funcname}(){
1378
- void** default_address = (void**)#{cfunc_address_name};
1379
- ID default_id = rb_intern(\"default\");
1380
- VALUE recvtype = #{recvdump};
1381
-
1382
- if (1) {
1383
- *default_address = 0;
1384
-
1385
- #{
1386
- if RUBY_VERSION == "1.9.2"
1387
-
1388
- "
1389
- rb_method_entry_t* me = rb_method_entry(recvtype,#{intern_num mname});
1390
- if (me != 0) {
1391
- rb_method_definition_t* def = me->def;
1392
-
1393
- if (def->type == VM_METHOD_TYPE_CFUNC) {
1394
- *default_address = #{cfunc_wrapper};
1395
- #{cfunc_real_address_name} = (void*)me;
1396
- }
1397
- }
1398
- "
1399
- end
1400
- }
1401
- if (default_address != 0) {
1402
- if (recvtype != Qnil) {
1403
- rb_funcall(
1404
- recvtype,
1405
- #{intern_num :register_method_value},
1406
- 3,
1407
- #{literal_value mname},
1408
- PTR2NUM(default_id),
1409
- PTR2NUM(default_address)
1410
- );
1411
- }
1412
- }
1413
- }
1414
- return Qnil;
1415
- }
1416
- "
1417
- }
1418
-
1419
-
1420
-
1421
- if recvdump and recvtype
1422
- init_extra << "
1423
- {
1424
- VALUE recvtype = #{recvdump};
1425
- rb_funcall(#{literal_value FastRuby}, #{intern_num :set_builder_module}, 1, recvtype);
1426
- VALUE signature = #{literal_value signature};
1427
- VALUE mname = #{literal_value mname};
1428
- VALUE tree = #{literal_value method_tree};
1429
- VALUE rb_str_signature = rb_funcall(
1430
- #{literal_value FastRuby},
1431
- #{intern_num :make_str_signature},
1432
- 2,
1433
- mname,
1434
- signature);
1435
-
1436
-
1437
-
1438
- VALUE fastruby_method = rb_funcall(recvtype, #{intern_num :fastruby_method}, 1, mname);
1439
- #{tree_pointer_name} = (VALUE*)NUM2PTR(fastruby_method_tree_pointer(fastruby_method));
1440
-
1441
- ID id;
1442
- ID default_id = rb_intern(\"default\");
1443
- VALUE rb_method_hash;
1444
- void** address = 0;
1445
- void** default_address = 0;
1446
- id = rb_intern(RSTRING_PTR(rb_str_signature));
1447
- rb_method_hash = rb_funcall(recvtype, #{intern_num :method_hash},1,mname);
1448
-
1449
- if (rb_method_hash != Qnil) {
1450
- VALUE tmp = rb_hash_aref(rb_method_hash, PTR2NUM(id));
1451
- if (tmp != Qnil) {
1452
- address = (void*)NUM2PTR(tmp);
1453
- }
1454
-
1455
- tmp = rb_hash_aref(rb_method_hash, PTR2NUM(default_id));
1456
- if (tmp != Qnil) {
1457
- default_address = (void*)NUM2PTR(tmp);
1458
- }
1459
- }
1460
-
1461
- if (default_address==0) {
1462
- default_address = malloc(sizeof(void*));
1463
- *default_address = 0;
1464
- }
1465
- #{cfunc_address_name} = default_address;
1466
- #{unless is_block_call
1467
- "
1468
- #{update_cfunc_method}();
1469
- rb_iterate(#{anonymous_function{|funcname|
1470
- "static VALUE #{funcname}(VALUE recv) {
1471
- return rb_funcall(recv, #{intern_num :observe}, 1, #{literal_value(@alt_method_name + "#" + cfunc_address_name)});
1472
- }
1473
- "
1474
- }},fastruby_method,#{update_cfunc_method},Qnil);
1475
- "
1476
- end
1477
- }
1478
-
1479
- if (address==0) {
1480
- address = malloc(sizeof(void*));
1481
-
1482
- if (recvtype != Qnil) {
1483
- rb_funcall(
1484
- recvtype,
1485
- #{intern_num :register_method_value},
1486
- 3,
1487
- #{literal_value mname},
1488
- PTR2NUM(id),
1489
- PTR2NUM(address)
1490
- );
1491
- }
1492
-
1493
- *address = 0; //(void*)
1494
- }
1495
-
1496
- #{address_name} = address;
1497
- #{name} = (void*)#{generic_wrapper};
1498
- }
1499
- "
1500
- else
1501
- init_extra << "
1502
- // ruby, wrap rb_funcall
1503
- #{name} = (void*)#{pureruby_wrapper};
1504
- "
1505
- end
1506
-
1507
- name
1508
- end
1509
-
1510
- def intern_num(symbol)
1511
- symbol = symbol.to_sym
1512
- @intern_num_hash = Hash.new unless @intern_num_hash
1513
- return @intern_num_hash[symbol] if @intern_num_hash[symbol]
1514
-
1515
- name = self.add_global_name("ID", 0);
1516
-
1517
- init_extra << "
1518
- #{name} = rb_intern(\"#{symbol.to_s}\");
1519
- "
1520
-
1521
- @intern_num_hash[symbol] = name
1522
-
1523
- name
1524
- end
1525
-
1526
- def add_global_name(ctype, default)
1527
- name = "glb" + rand(1000000000).to_s
1528
-
1529
- extra_code << "
1530
- static #{ctype} #{name} = #{default};
1531
- "
1532
- name
1533
- end
1534
-
1535
- def global_entry(glbname)
1536
- name = add_global_name("struct global_entry*", 0);
1537
-
1538
- init_extra << "
1539
- #{name} = rb_global_entry(SYM2ID(#{literal_value glbname}));
1540
- "
1541
-
1542
- name
1543
- end
1544
-
1545
-
1546
- def frame(code, jmp_code, not_jmp_code = "", rescued = nil)
1547
-
1548
- anonymous_function{ |name| "
1549
- static VALUE #{name}(VALUE param) {
1550
- volatile VALUE last_expression = Qnil;
1551
- #{@frame_struct} frame;
1552
-
1553
- typeof(frame)* volatile pframe;
1554
- typeof(frame)* volatile parent_frame;
1555
- #{@locals_struct}* volatile plocals;
1556
-
1557
- parent_frame = (void*)param;
1558
-
1559
- frame.parent_frame = (void*)param;
1560
- frame.plocals = parent_frame->plocals;
1561
- frame.rescue = #{rescued ? rescued : "parent_frame->rescue"};
1562
- frame.targetted = 0;
1563
- frame.thread_data = parent_frame->thread_data;
1564
- if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
1565
-
1566
- plocals = frame.plocals;
1567
- pframe = &frame;
1568
-
1569
- int aux = setjmp(frame.jmp);
1570
- if (aux != 0) {
1571
- last_expression = pframe->return_value;
1572
-
1573
- // restore previous frame
1574
- typeof(pframe) original_frame = pframe;
1575
- pframe = parent_frame;
1576
-
1577
- #{jmp_code};
1578
-
1579
- if (original_frame->targetted == 0) {
1580
- longjmp(pframe->jmp,aux);
1581
- }
1582
-
1583
- return last_expression;
1584
- }
1585
-
1586
- #{code};
1587
-
1588
- // restore previous frame
1589
- volatile typeof(pframe) original_frame = pframe;
1590
- pframe = parent_frame;
1591
- #{not_jmp_code};
1592
-
1593
- return last_expression;
1594
-
1595
- }
1596
- "
1597
- } + "((VALUE)pframe)"
1598
- end
1599
- end
1600
- end