fastruby 0.0.20 → 0.0.21

Sign up to get free protection for your applications and to get access to all the features.
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