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.
- data/Rakefile +1 -1
- data/lib/fastruby/builder.rb~ +5 -1
- data/lib/fastruby/corelib/fixnum.rb +1 -1
- data/lib/fastruby/corelib/fixnum.rb~ +0 -71
- data/lib/fastruby/corelib.rb~ +1 -1
- data/lib/fastruby/modules/inliner/call.rb~ +3 -1
- data/lib/fastruby/modules/translator/call.rb +1 -1
- data/lib/fastruby/modules/translator/call.rb~ +1 -1
- data/lib/fastruby/object.rb~ +0 -6
- data/lib/fastruby.rb +1 -1
- data/lib/fastruby.rb~ +1 -1
- data/spec/corelib/numeric/fixnum_spec.rb +1 -1
- data/spec/corelib/numeric/fixnum_spec.rb~ +7 -1
- metadata +12 -40
- data/lib/fastruby/builder/inference_updater.rb~ +0 -76
- data/lib/fastruby/builder/inliner.rb~ +0 -60
- data/lib/fastruby/builder/lvar_type.rb~ +0 -44
- data/lib/fastruby/builder/pipeline.rb~ +0 -43
- data/lib/fastruby/builder/reductor.rb~ +0 -42
- data/lib/fastruby/corelib/integer.rb~ +0 -96
- data/lib/fastruby/modules/inliner/defn.rb~ +0 -29
- data/lib/fastruby/modules/inliner/recursive.rb~ +0 -40
- data/lib/fastruby/modules/lvar_type/call.rb~ +0 -36
- data/lib/fastruby/modules/lvar_type/defn.rb~ +0 -42
- data/lib/fastruby/modules/lvar_type/lasgn.rb~ +0 -42
- data/lib/fastruby/modules/lvar_type/recursive.rb~ +0 -33
- data/lib/fastruby/modules/reductor/nontree.rb~ +0 -32
- data/lib/fastruby/modules/reductor/recursive.rb~ +0 -31
- data/lib/fastruby/modules/translator/defn.rb~ +0 -267
- data/lib/fastruby/modules/translator/directive.rb~ +0 -44
- data/lib/fastruby/modules/translator/exceptions.rb~ +0 -120
- data/lib/fastruby/modules/translator/iter.rb~ +0 -745
- data/lib/fastruby/modules/translator/literal.rb~ +0 -150
- data/lib/fastruby/modules/translator/nonlocal.rb~ +0 -298
- data/lib/fastruby/modules/translator/static.rb~ +0 -291
- data/lib/fastruby/modules/translator/variable.rb~ +0 -280
- data/lib/fastruby/set_tree.rb~ +0 -71
- data/lib/fastruby/sexp_extension.rb~ +0 -262
- data/lib/fastruby/translator/scope_mode_helper.rb~ +0 -138
- data/lib/fastruby/translator/translator.rb~ +0 -1600
- data/lib/fastruby/translator/translator_modules.rb~ +0 -53
- data/lib/fastruby_only/base.rb +0 -1
@@ -1,745 +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
|
-
module FastRuby
|
22
|
-
class Context
|
23
|
-
|
24
|
-
define_translator_for(:iter, :method => :to_c_iter)
|
25
|
-
def to_c_iter(tree, result_var = nil)
|
26
|
-
|
27
|
-
call_tree = tree[1]
|
28
|
-
args_tree = tree[2]
|
29
|
-
recv_tree = call_tree[1]
|
30
|
-
|
31
|
-
directive_code = directive(call_tree)
|
32
|
-
if directive_code
|
33
|
-
if result_var
|
34
|
-
return "#{result_var} = #{directive_code};\n"
|
35
|
-
else
|
36
|
-
return directive_code
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
other_call_tree = call_tree.dup
|
41
|
-
other_call_tree[1] = s(:lvar, :arg)
|
42
|
-
|
43
|
-
mname = call_tree[2]
|
44
|
-
|
45
|
-
call_args_tree = call_tree[3]
|
46
|
-
|
47
|
-
caller_code = nil
|
48
|
-
|
49
|
-
recvtype = infer_type(recv_tree || s(:self))
|
50
|
-
|
51
|
-
address = nil
|
52
|
-
mobject = nil
|
53
|
-
len = nil
|
54
|
-
|
55
|
-
if recvtype
|
56
|
-
|
57
|
-
inference_complete = true
|
58
|
-
signature = [recvtype]
|
59
|
-
|
60
|
-
call_args_tree[1..-1].each do |arg|
|
61
|
-
argtype = infer_type(arg)
|
62
|
-
if argtype
|
63
|
-
signature << argtype
|
64
|
-
else
|
65
|
-
inference_complete = false
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
anonymous_impl = tree[3]
|
71
|
-
|
72
|
-
str_lvar_initialization = "#{@frame_struct} *pframe;
|
73
|
-
#{@locals_struct} *plocals;
|
74
|
-
|
75
|
-
"
|
76
|
-
|
77
|
-
str_arg_initialization = ""
|
78
|
-
|
79
|
-
str_impl = ""
|
80
|
-
on_block do
|
81
|
-
str_impl = to_c(anonymous_impl, "last_expression")
|
82
|
-
end
|
83
|
-
|
84
|
-
if not args_tree
|
85
|
-
elsif args_tree.first == :lasgn
|
86
|
-
if RUBY_VERSION =~ /^1\.8/
|
87
|
-
str_arg_initialization << "plocals->#{args_tree[1]} = arg;"
|
88
|
-
elsif RUBY_VERSION =~ /^1\.9/
|
89
|
-
str_arg_initialization << "
|
90
|
-
if (TYPE(arg) != T_ARRAY) {
|
91
|
-
plocals->#{args_tree[1]} = arg;
|
92
|
-
} else {
|
93
|
-
plocals->#{args_tree[1]} = rb_ary_entry(arg,0);
|
94
|
-
}
|
95
|
-
"
|
96
|
-
end
|
97
|
-
elsif args_tree.first == :masgn
|
98
|
-
|
99
|
-
if RUBY_VERSION =~ /^1\.8/
|
100
|
-
str_arg_initialization << "
|
101
|
-
{
|
102
|
-
if (TYPE(arg) != T_ARRAY) {
|
103
|
-
if (arg != Qnil) {
|
104
|
-
arg = rb_ary_new4(1,&arg);
|
105
|
-
} else {
|
106
|
-
arg = rb_ary_new2(0);
|
107
|
-
}
|
108
|
-
} else if (_RARRAY_LEN(arg) <= 1) {
|
109
|
-
arg = rb_ary_new4(1,&arg);
|
110
|
-
}
|
111
|
-
}
|
112
|
-
"
|
113
|
-
elsif RUBY_VERSION =~ /^1\.9/
|
114
|
-
str_arg_initialization << "
|
115
|
-
{
|
116
|
-
}
|
117
|
-
"
|
118
|
-
end
|
119
|
-
|
120
|
-
arguments = args_tree[1][1..-1]
|
121
|
-
|
122
|
-
(0..arguments.size-1).each do |i|
|
123
|
-
arg = arguments[i]
|
124
|
-
if arg[0] == :lasgn
|
125
|
-
str_arg_initialization << "plocals->#{arguments[i].last} = rb_ary_entry(arg,#{i});\n"
|
126
|
-
elsif arg[0] == :splat
|
127
|
-
str_arg_initialization << "plocals->#{arg.last.last} = rb_ary_new2(_RARRAY_LEN(arg)-#{i});\n
|
128
|
-
|
129
|
-
int i;
|
130
|
-
for (i=#{i};i<_RARRAY_LEN(arg);i++){
|
131
|
-
rb_ary_store(plocals->#{arg.last.last},i-#{i},rb_ary_entry(arg,i));
|
132
|
-
}
|
133
|
-
"
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
str_recv = "pframe->next_recv"
|
138
|
-
str_recv = "plocals->self" unless recv_tree
|
139
|
-
|
140
|
-
strargs = if call_args_tree.size > 1
|
141
|
-
"," + (0..call_args_tree.size-2).map{|i| "arg#{i}"}.join(",")
|
142
|
-
else
|
143
|
-
""
|
144
|
-
end
|
145
|
-
|
146
|
-
str_evaluate_args = ""
|
147
|
-
|
148
|
-
rb_funcall_caller_code = proc { |name, call_type| "
|
149
|
-
static VALUE #{name}(VALUE param) {
|
150
|
-
// call to #{call_tree[2]}
|
151
|
-
VALUE last_expression = Qnil;
|
152
|
-
VALUE* args_array = (VALUE*)param;
|
153
|
-
|
154
|
-
#{str_lvar_initialization}
|
155
|
-
pframe = (void*)args_array[0];
|
156
|
-
plocals = (void*)pframe->plocals;
|
157
|
-
#{str_evaluate_args};
|
158
|
-
|
159
|
-
VALUE ret = rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, #{call_args_tree.size-1} #{strargs});
|
160
|
-
#{
|
161
|
-
if call_type == :lambda
|
162
|
-
"
|
163
|
-
|
164
|
-
// freeze all stacks
|
165
|
-
struct FASTRUBYTHREADDATA* thread_data = rb_current_thread_data();
|
166
|
-
|
167
|
-
if (thread_data != 0) {
|
168
|
-
VALUE rb_stack_chunk = thread_data->rb_stack_chunk;
|
169
|
-
|
170
|
-
// add reference to stack chunk to lambda object
|
171
|
-
rb_ivar_set(ret,#{intern_num :_fastruby_stack_chunk},rb_stack_chunk);
|
172
|
-
|
173
|
-
// freeze the complete chain of stack chunks
|
174
|
-
while (rb_stack_chunk != Qnil) {
|
175
|
-
struct STACKCHUNK* stack_chunk;
|
176
|
-
Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
|
177
|
-
|
178
|
-
stack_chunk_freeze(stack_chunk);
|
179
|
-
|
180
|
-
rb_stack_chunk = rb_ivar_get(rb_stack_chunk,#{intern_num :_parent_stack_chunk});
|
181
|
-
}
|
182
|
-
}
|
183
|
-
"
|
184
|
-
end
|
185
|
-
}
|
186
|
-
return ret;
|
187
|
-
}
|
188
|
-
"
|
189
|
-
}
|
190
|
-
|
191
|
-
|
192
|
-
if call_args_tree.size > 1
|
193
|
-
if call_args_tree.last[0] == :splat
|
194
|
-
rb_funcall_caller_code = proc { |name,call_type| "
|
195
|
-
static VALUE #{name}(VALUE param) {
|
196
|
-
// call to #{call_tree[2]}
|
197
|
-
|
198
|
-
VALUE* args_array = (VALUE*)param;
|
199
|
-
int argc = args_array[1];
|
200
|
-
VALUE* argv = args_array[2];
|
201
|
-
|
202
|
-
VALUE last_expression = Qnil;
|
203
|
-
#{str_lvar_initialization}
|
204
|
-
|
205
|
-
pframe = (void*)args_array[0];
|
206
|
-
plocals = (void*)pframe->plocals;
|
207
|
-
|
208
|
-
return rb_funcall2(#{str_recv}, #{intern_num call_tree[2]}, argc, argv);
|
209
|
-
}
|
210
|
-
"
|
211
|
-
}
|
212
|
-
else
|
213
|
-
str_evaluate_args = "
|
214
|
-
#{
|
215
|
-
(0..call_args_tree.size-2).map{|i|
|
216
|
-
"VALUE arg#{i} = args_array[#{i+1}];"
|
217
|
-
}.join("\n")
|
218
|
-
}
|
219
|
-
|
220
|
-
"
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
argument_array_read = "
|
225
|
-
VALUE arg;
|
226
|
-
#{
|
227
|
-
# TODO: access directly to argc and argv for optimal execution
|
228
|
-
if RUBY_VERSION =~ /^1\.9/
|
229
|
-
"
|
230
|
-
if (TYPE(arg_) == T_ARRAY) {
|
231
|
-
if (_RARRAY_LEN(arg_) <= 1) {
|
232
|
-
arg = rb_ary_new4(argc,argv);
|
233
|
-
} else {
|
234
|
-
arg = arg_;
|
235
|
-
}
|
236
|
-
} else {
|
237
|
-
arg = rb_ary_new4(argc,argv);
|
238
|
-
}
|
239
|
-
"
|
240
|
-
else
|
241
|
-
"arg = arg_;"
|
242
|
-
end
|
243
|
-
}
|
244
|
-
"
|
245
|
-
|
246
|
-
rb_funcall_block_code = proc { |name,call_type| "
|
247
|
-
static VALUE #{name}(VALUE arg_, VALUE _plocals, int argc, VALUE* argv) {
|
248
|
-
// block for call to #{call_tree[2]}
|
249
|
-
#{argument_array_read}
|
250
|
-
|
251
|
-
volatile VALUE last_expression = Qnil;
|
252
|
-
|
253
|
-
#{@frame_struct} frame;
|
254
|
-
#{@frame_struct} * volatile pframe = (void*)&frame;
|
255
|
-
#{@locals_struct} * volatile plocals = (void*)_plocals;
|
256
|
-
|
257
|
-
frame.plocals = plocals;
|
258
|
-
frame.parent_frame = 0;
|
259
|
-
frame.return_value = Qnil;
|
260
|
-
frame.rescue = 0;
|
261
|
-
frame.targetted = 0;
|
262
|
-
frame.thread_data = rb_current_thread_data();
|
263
|
-
|
264
|
-
#{str_arg_initialization}
|
265
|
-
|
266
|
-
#{
|
267
|
-
if call_type == :lambda or call_type == :proc_new
|
268
|
-
"
|
269
|
-
void* volatile old_call_frame = ((typeof(plocals))(pframe->plocals))->call_frame;
|
270
|
-
((typeof(plocals))(pframe->plocals))->call_frame = pframe;
|
271
|
-
"
|
272
|
-
end
|
273
|
-
}
|
274
|
-
|
275
|
-
int aux = setjmp(frame.jmp);
|
276
|
-
if (aux != 0) {
|
277
|
-
|
278
|
-
if (aux == FASTRUBY_TAG_NEXT) {
|
279
|
-
last_expression = pframe->thread_data->accumulator;
|
280
|
-
goto fastruby_local_next;
|
281
|
-
} else if (aux == FASTRUBY_TAG_REDO) {
|
282
|
-
// do nothing and let execute the block again
|
283
|
-
#{
|
284
|
-
if call_type == :lambda
|
285
|
-
"
|
286
|
-
|
287
|
-
} else if (aux == FASTRUBY_TAG_BREAK) {
|
288
|
-
last_expression = frame.return_value;
|
289
|
-
typeof(pframe) target_frame_ = (void*)plocals->call_frame;
|
290
|
-
|
291
|
-
if (target_frame_ == 0) {
|
292
|
-
goto fastruby_local_next;
|
293
|
-
} else {
|
294
|
-
if (target_frame_->targetted == 1) {
|
295
|
-
goto fastruby_local_next;
|
296
|
-
} else {
|
297
|
-
#{_raise("rb_eLocalJumpError","illegal break")};
|
298
|
-
}
|
299
|
-
}
|
300
|
-
"
|
301
|
-
end
|
302
|
-
}
|
303
|
-
#{
|
304
|
-
if call_type == :lambda or call_type == :proc_new
|
305
|
-
"
|
306
|
-
} else if (aux == FASTRUBY_TAG_RAISE) {
|
307
|
-
rb_funcall(((typeof(plocals))(pframe->plocals))->self, #{intern_num :raise}, 1, frame.thread_data->exception);
|
308
|
-
return Qnil;
|
309
|
-
"
|
310
|
-
end
|
311
|
-
}
|
312
|
-
} else {
|
313
|
-
#{
|
314
|
-
case call_type
|
315
|
-
when :proc_new
|
316
|
-
"
|
317
|
-
_local_return:
|
318
|
-
if (plocals->targetted == 1) {
|
319
|
-
if (plocals->active == Qfalse) {
|
320
|
-
rb_raise(rb_eLocalJumpError,\"return from proc-closure\");
|
321
|
-
} else {
|
322
|
-
((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
|
323
|
-
frb_jump_tag(aux);
|
324
|
-
}
|
325
|
-
} else {
|
326
|
-
rb_raise(rb_eLocalJumpError, \"unexpected return\");
|
327
|
-
}
|
328
|
-
"
|
329
|
-
when :lambda
|
330
|
-
"
|
331
|
-
if (aux == FASTRUBY_TAG_RETURN) {
|
332
|
-
if (plocals->targetted == 1) {
|
333
|
-
last_expression = ((typeof(plocals))(pframe->plocals))->return_value;
|
334
|
-
goto fastruby_local_next;
|
335
|
-
|
336
|
-
} else {
|
337
|
-
rb_raise(rb_eLocalJumpError, \"unexpected return\");
|
338
|
-
}
|
339
|
-
} else {
|
340
|
-
rb_raise(rb_eLocalJumpError, \"unexpected return\");
|
341
|
-
}
|
342
|
-
"
|
343
|
-
else
|
344
|
-
"
|
345
|
-
frb_jump_tag(aux);
|
346
|
-
return frame.return_value;
|
347
|
-
"
|
348
|
-
end
|
349
|
-
}
|
350
|
-
|
351
|
-
}
|
352
|
-
}
|
353
|
-
|
354
|
-
#{
|
355
|
-
if call_type == :callcc
|
356
|
-
"
|
357
|
-
if (rb_obj_is_kind_of(arg, rb_const_get(rb_cObject, #{intern_num :Continuation}))) {
|
358
|
-
struct FASTRUBYTHREADDATA* thread_data = frame.thread_data;
|
359
|
-
rb_ivar_set(arg,#{intern_num :__stack_chunk},thread_data->rb_stack_chunk);
|
360
|
-
}
|
361
|
-
"
|
362
|
-
end
|
363
|
-
}
|
364
|
-
|
365
|
-
fastruby_local_redo:
|
366
|
-
#{str_impl};
|
367
|
-
|
368
|
-
#{
|
369
|
-
case call_type
|
370
|
-
when :proc_new
|
371
|
-
"
|
372
|
-
return last_expression;
|
373
|
-
local_return:
|
374
|
-
aux = FASTRUBY_TAG_RETURN;
|
375
|
-
plocals->return_value = last_expression;
|
376
|
-
plocals->targetted = 1;
|
377
|
-
goto _local_return;
|
378
|
-
"
|
379
|
-
when :lambda
|
380
|
-
"
|
381
|
-
local_return:
|
382
|
-
"
|
383
|
-
else
|
384
|
-
"
|
385
|
-
return last_expression;
|
386
|
-
local_return:
|
387
|
-
plocals->return_value = last_expression;
|
388
|
-
plocals->targetted = 1;
|
389
|
-
frb_jump_tag(FASTRUBY_TAG_RETURN);
|
390
|
-
"
|
391
|
-
end
|
392
|
-
}
|
393
|
-
|
394
|
-
|
395
|
-
fastruby_local_next:
|
396
|
-
#{
|
397
|
-
if call_type == :proc_new or call_type == :lambda
|
398
|
-
"
|
399
|
-
((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
|
400
|
-
"
|
401
|
-
end
|
402
|
-
}
|
403
|
-
return last_expression;
|
404
|
-
}
|
405
|
-
"
|
406
|
-
}
|
407
|
-
|
408
|
-
fastruby_str_arg_initialization = ""
|
409
|
-
|
410
|
-
if not args_tree
|
411
|
-
fastruby_str_arg_initialization = ""
|
412
|
-
elsif args_tree.first == :lasgn
|
413
|
-
fastruby_str_arg_initialization = "plocals->#{args_tree[1]} = argv[0];"
|
414
|
-
elsif args_tree.first == :masgn
|
415
|
-
arguments = args_tree[1][1..-1]
|
416
|
-
|
417
|
-
(0..arguments.size-1).each do |i|
|
418
|
-
arg = arguments[i]
|
419
|
-
if arg[0] == :lasgn
|
420
|
-
fastruby_str_arg_initialization << "plocals->#{arg.last} = #{i} < argc ? argv[#{i}] : Qnil;\n"
|
421
|
-
elsif arg[0] == :splat
|
422
|
-
fastruby_str_arg_initialization << "plocals->#{arg.last.last} = rb_ary_new2(#{arguments.size-1-i});\n
|
423
|
-
{
|
424
|
-
int i;
|
425
|
-
for (i=#{i};i<argc;i++){
|
426
|
-
rb_ary_store(plocals->#{arg.last.last},i-#{i},argv[i]);
|
427
|
-
}
|
428
|
-
}
|
429
|
-
"
|
430
|
-
end
|
431
|
-
end
|
432
|
-
end
|
433
|
-
|
434
|
-
block_code = proc { |name| "
|
435
|
-
static VALUE #{name}(int argc, VALUE* argv, VALUE _locals, VALUE _parent_frame) {
|
436
|
-
// block for call to #{call_tree[2]}
|
437
|
-
volatile VALUE last_expression = Qnil;
|
438
|
-
#{@frame_struct} frame;
|
439
|
-
#{@frame_struct} * volatile pframe = (void*)&frame;
|
440
|
-
#{@frame_struct} * volatile parent_frame = (void*)_parent_frame;
|
441
|
-
#{@locals_struct} * volatile plocals;
|
442
|
-
|
443
|
-
frame.plocals = (void*)_locals;
|
444
|
-
frame.parent_frame = parent_frame;
|
445
|
-
frame.return_value = Qnil;
|
446
|
-
frame.rescue = 0;
|
447
|
-
frame.targetted = 0;
|
448
|
-
frame.thread_data = parent_frame->thread_data;
|
449
|
-
if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
|
450
|
-
|
451
|
-
plocals = frame.plocals;
|
452
|
-
|
453
|
-
#{fastruby_str_arg_initialization}
|
454
|
-
|
455
|
-
int aux = setjmp(frame.jmp);
|
456
|
-
if (aux != 0) {
|
457
|
-
if (pframe->targetted == 0) {
|
458
|
-
if (aux == FASTRUBY_TAG_NEXT) {
|
459
|
-
return pframe->thread_data->accumulator;
|
460
|
-
} else if (aux == FASTRUBY_TAG_REDO) {
|
461
|
-
// do nothing and let execute the block again
|
462
|
-
} else {
|
463
|
-
longjmp(((typeof(pframe))_parent_frame)->jmp,aux);
|
464
|
-
}
|
465
|
-
}
|
466
|
-
|
467
|
-
}
|
468
|
-
|
469
|
-
fastruby_local_redo:
|
470
|
-
#{str_impl};
|
471
|
-
|
472
|
-
return last_expression;
|
473
|
-
local_return:
|
474
|
-
plocals->return_value = last_expression;
|
475
|
-
plocals->targetted = 1;
|
476
|
-
longjmp(pframe->jmp, FASTRUBY_TAG_RETURN);
|
477
|
-
fastruby_local_next:
|
478
|
-
return last_expression; }
|
479
|
-
"
|
480
|
-
}
|
481
|
-
|
482
|
-
caller_code = nil
|
483
|
-
convention_global_name = add_global_name("int",0)
|
484
|
-
|
485
|
-
precode = "
|
486
|
-
struct FASTRUBYTHREADDATA* thread_data = 0;
|
487
|
-
VALUE saved_rb_stack_chunk = Qnil;
|
488
|
-
|
489
|
-
VALUE next_recv = plocals->self;
|
490
|
-
|
491
|
-
#{
|
492
|
-
if recv_tree
|
493
|
-
to_c recv_tree, "next_recv"
|
494
|
-
end
|
495
|
-
};
|
496
|
-
|
497
|
-
pframe->next_recv = next_recv;
|
498
|
-
#ifdef RUBY_1_8
|
499
|
-
NODE* node = rb_method_node(CLASS_OF(pframe->next_recv), #{intern_num mname});
|
500
|
-
#endif
|
501
|
-
#ifdef RUBY_1_9
|
502
|
-
void* node = rb_method_entry(CLASS_OF(pframe->next_recv), #{intern_num mname});
|
503
|
-
#endif
|
504
|
-
|
505
|
-
if (node == #{@callcc_node_gvar}) {
|
506
|
-
|
507
|
-
// freeze all stacks
|
508
|
-
thread_data = rb_current_thread_data();
|
509
|
-
|
510
|
-
if (thread_data != 0) {
|
511
|
-
VALUE rb_stack_chunk = thread_data->rb_stack_chunk;
|
512
|
-
saved_rb_stack_chunk = rb_stack_chunk;
|
513
|
-
|
514
|
-
// freeze the complete chain of stack chunks
|
515
|
-
while (rb_stack_chunk != Qnil) {
|
516
|
-
struct STACKCHUNK* stack_chunk;
|
517
|
-
Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
|
518
|
-
|
519
|
-
stack_chunk_freeze(stack_chunk);
|
520
|
-
|
521
|
-
rb_stack_chunk = rb_ivar_get(rb_stack_chunk,#{intern_num :_parent_stack_chunk});
|
522
|
-
}
|
523
|
-
}
|
524
|
-
}
|
525
|
-
"
|
526
|
-
|
527
|
-
postcode = "
|
528
|
-
if (node == #{@callcc_node_gvar}) {
|
529
|
-
thread_data->rb_stack_chunk = saved_rb_stack_chunk;
|
530
|
-
}
|
531
|
-
"
|
532
|
-
|
533
|
-
|
534
|
-
funcall_call_code = "
|
535
|
-
#{
|
536
|
-
frame_call(
|
537
|
-
"ret = " + protected_block("
|
538
|
-
|
539
|
-
void* caller_func;
|
540
|
-
void* block_func;
|
541
|
-
typeof(plocals) current_plocals;
|
542
|
-
|
543
|
-
if (pframe->thread_data == 0) pframe->thread_data = rb_current_thread_data();
|
544
|
-
void* last_plocals = pframe->thread_data->last_plocals;
|
545
|
-
|
546
|
-
#ifdef RUBY_1_8
|
547
|
-
NODE* node = rb_method_node(CLASS_OF(pframe->next_recv), #{intern_num mname});
|
548
|
-
#endif
|
549
|
-
#ifdef RUBY_1_9
|
550
|
-
void* node = rb_method_entry(CLASS_OF(pframe->next_recv), #{intern_num mname});
|
551
|
-
#endif
|
552
|
-
|
553
|
-
if (
|
554
|
-
node == #{@proc_node_gvar} ||
|
555
|
-
node == #{@lambda_node_gvar}
|
556
|
-
) {
|
557
|
-
|
558
|
-
caller_func = #{anonymous_function(:lambda,&rb_funcall_caller_code)};
|
559
|
-
block_func = #{anonymous_function(:lambda,&rb_funcall_block_code)};
|
560
|
-
} else if (node == #{@procnew_node_gvar} && pframe->next_recv == rb_cProc) {
|
561
|
-
caller_func = #{anonymous_function(:lambda,&rb_funcall_caller_code)};
|
562
|
-
block_func = #{anonymous_function(:proc_new,&rb_funcall_block_code)};
|
563
|
-
} else if (node == #{@callcc_node_gvar}) {
|
564
|
-
caller_func = #{anonymous_function(:normal,&rb_funcall_caller_code)};
|
565
|
-
block_func = #{anonymous_function(:callcc,&rb_funcall_block_code)};
|
566
|
-
} else {
|
567
|
-
caller_func = #{anonymous_function(:normal,&rb_funcall_caller_code)};
|
568
|
-
block_func = #{anonymous_function(:normal,&rb_funcall_block_code)};
|
569
|
-
}
|
570
|
-
|
571
|
-
|
572
|
-
#{if call_args_tree.size > 1 and call_args_tree.last[0] == :splat
|
573
|
-
"
|
574
|
-
VALUE args_array[3];
|
575
|
-
VALUE array = Qnil;
|
576
|
-
|
577
|
-
#{to_c call_args_tree.last[1], "array"};
|
578
|
-
|
579
|
-
if (TYPE(array) != T_ARRAY) {
|
580
|
-
array = rb_ary_new4(1,&array);
|
581
|
-
}
|
582
|
-
|
583
|
-
int argc = #{call_args_tree.size-2};
|
584
|
-
VALUE argv[#{call_args_tree.size} + _RARRAY_LEN(array)];
|
585
|
-
|
586
|
-
VALUE aux_ = Qnil;;
|
587
|
-
#{
|
588
|
-
i = -1
|
589
|
-
call_args_tree[1..-2].map {|arg|
|
590
|
-
i = i + 1
|
591
|
-
"
|
592
|
-
#{to_c arg, "aux_"};
|
593
|
-
argv[#{i}] = aux_;
|
594
|
-
"
|
595
|
-
}.join(";\n")
|
596
|
-
};
|
597
|
-
|
598
|
-
int array_len = _RARRAY_LEN(array);
|
599
|
-
|
600
|
-
int i;
|
601
|
-
for (i=0; i<array_len;i++) {
|
602
|
-
argv[argc] = rb_ary_entry(array,i);
|
603
|
-
argc++;
|
604
|
-
}
|
605
|
-
|
606
|
-
args_array[0] = (VALUE)pframe;
|
607
|
-
args_array[1] = (VALUE)argc;
|
608
|
-
args_array[2] = (VALUE)argv;
|
609
|
-
|
610
|
-
last_expression = rb_iterate(
|
611
|
-
caller_func,
|
612
|
-
(VALUE)args_array,
|
613
|
-
block_func,
|
614
|
-
(VALUE)plocals);
|
615
|
-
|
616
|
-
"
|
617
|
-
else
|
618
|
-
"
|
619
|
-
|
620
|
-
VALUE args_array[#{call_args_tree.size+2}];
|
621
|
-
VALUE aux___ = Qnil;
|
622
|
-
args_array[0] = (VALUE)pframe;
|
623
|
-
|
624
|
-
#{
|
625
|
-
(0..call_args_tree.size-2).map{|i|
|
626
|
-
to_c(call_args_tree[i+1], "aux___")+";"+
|
627
|
-
"args_array[#{i+1}] = aux___;"
|
628
|
-
}.join("\n")
|
629
|
-
}
|
630
|
-
|
631
|
-
last_expression = rb_iterate(
|
632
|
-
caller_func,
|
633
|
-
(VALUE)args_array,
|
634
|
-
block_func,
|
635
|
-
(VALUE)plocals);
|
636
|
-
"
|
637
|
-
end
|
638
|
-
}
|
639
|
-
if (node == #{@callcc_node_gvar}) {
|
640
|
-
|
641
|
-
// remove active flags of abandoned stack
|
642
|
-
current_plocals = pframe->thread_data->last_plocals;
|
643
|
-
while (current_plocals) {
|
644
|
-
current_plocals->active = Qfalse;
|
645
|
-
current_plocals = (typeof(current_plocals))(current_plocals->parent_locals);
|
646
|
-
}
|
647
|
-
|
648
|
-
// restore last_plocals
|
649
|
-
pframe->thread_data->last_plocals = last_plocals;
|
650
|
-
|
651
|
-
// mark all scopes as active
|
652
|
-
current_plocals = last_plocals;
|
653
|
-
|
654
|
-
while (current_plocals) {
|
655
|
-
current_plocals->active = Qtrue;
|
656
|
-
current_plocals = (typeof(current_plocals))(current_plocals->parent_locals);
|
657
|
-
}
|
658
|
-
}
|
659
|
-
", true), precode, postcode
|
660
|
-
)
|
661
|
-
};
|
662
|
-
"
|
663
|
-
|
664
|
-
recvtype = nil if call_args_tree.size > 1 ? call_args_tree.last[0] == :splat : false
|
665
|
-
unless recvtype
|
666
|
-
if result_var
|
667
|
-
"#{result_var} = #{funcall_call_code};"
|
668
|
-
else
|
669
|
-
funcall_call_code
|
670
|
-
end
|
671
|
-
else
|
672
|
-
encoded_address = encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name, true)
|
673
|
-
|
674
|
-
if call_args_tree.size > 1
|
675
|
-
strargs = (0..call_args_tree.size-2).map{|i| "arg#{i}"}.join(",")
|
676
|
-
else
|
677
|
-
strargs = ""
|
678
|
-
end
|
679
|
-
|
680
|
-
fastruby_call_code = "
|
681
|
-
// call to #{call_tree[2]}
|
682
|
-
#{
|
683
|
-
if call_args_tree.size > 1
|
684
|
-
" #{
|
685
|
-
(0..call_args_tree.size-2).map{|i|
|
686
|
-
"VALUE arg#{i} = Qnil;"
|
687
|
-
}.join("\n")
|
688
|
-
}
|
689
|
-
|
690
|
-
#{
|
691
|
-
(0..call_args_tree.size-2).map{|i|
|
692
|
-
to_c(call_args_tree[i+1], "arg#{i}")+";"
|
693
|
-
}.join("\n")
|
694
|
-
}
|
695
|
-
"
|
696
|
-
end
|
697
|
-
};
|
698
|
-
|
699
|
-
VALUE recv = plocals->self;
|
700
|
-
|
701
|
-
#{
|
702
|
-
if recv_tree
|
703
|
-
to_c recv_tree, "recv"
|
704
|
-
end
|
705
|
-
}
|
706
|
-
|
707
|
-
ret = ((VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*))#{encoded_address})(recv, (VALUE)&block, (VALUE)&call_frame, #{call_args_tree.size-1}, (VALUE[]){#{strargs}});
|
708
|
-
"
|
709
|
-
|
710
|
-
code = "
|
711
|
-
if (#{@last_address_name} == 0) {
|
712
|
-
return #{funcall_call_code};
|
713
|
-
} else {
|
714
|
-
#{if recvtype and inference_complete
|
715
|
-
"if (*#{@last_address_name} == 0) {
|
716
|
-
rb_funcall(#{literal_value recvtype},#{intern_num :build}, 2, #{literal_value signature}, #{literal_value mname});
|
717
|
-
}
|
718
|
-
"
|
719
|
-
end
|
720
|
-
}
|
721
|
-
if (*#{@last_address_name} == 0) {
|
722
|
-
return #{funcall_call_code};
|
723
|
-
} else {
|
724
|
-
#{fastruby_call_code}
|
725
|
-
}
|
726
|
-
}
|
727
|
-
"
|
728
|
-
|
729
|
-
fastruby_precode = " #{@block_struct} block;
|
730
|
-
|
731
|
-
block.block_function_address = ((void*)#{anonymous_function(&block_code)});
|
732
|
-
block.block_function_param = ((void*)plocals);
|
733
|
-
block.proc = Qnil;
|
734
|
-
"
|
735
|
-
|
736
|
-
if result_var
|
737
|
-
"#{result_var} = #{frame_call(code,fastruby_precode,"")}"
|
738
|
-
else
|
739
|
-
frame_call(code,fastruby_precode,"")
|
740
|
-
end
|
741
|
-
|
742
|
-
end
|
743
|
-
end
|
744
|
-
end
|
745
|
-
end
|