ytljit 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/README +29 -0
  2. data/Rakefile +22 -0
  3. data/ext/code_alloc.c +266 -0
  4. data/ext/extconf.rb +3 -0
  5. data/ext/ytljit.c +527 -0
  6. data/ext/ytljit.h +285 -0
  7. data/lib/ytljit/asm.rb +205 -0
  8. data/lib/ytljit/asmext.rb +199 -0
  9. data/lib/ytljit/asmext_x64.rb +212 -0
  10. data/lib/ytljit/asmext_x86.rb +128 -0
  11. data/lib/ytljit/asmutil.rb +182 -0
  12. data/lib/ytljit/codespace.rb +92 -0
  13. data/lib/ytljit/error.rb +7 -0
  14. data/lib/ytljit/instruction.rb +138 -0
  15. data/lib/ytljit/instruction_ia.rb +1298 -0
  16. data/lib/ytljit/instruction_x64.rb +41 -0
  17. data/lib/ytljit/instruction_x86.rb +11 -0
  18. data/lib/ytljit/marshal.rb +133 -0
  19. data/lib/ytljit/matcher.rb +235 -0
  20. data/lib/ytljit/rubyvm.rb +63 -0
  21. data/lib/ytljit/struct.rb +125 -0
  22. data/lib/ytljit/type.rb +112 -0
  23. data/lib/ytljit/util.rb +63 -0
  24. data/lib/ytljit/vm.rb +1649 -0
  25. data/lib/ytljit/vm_codegen.rb +491 -0
  26. data/lib/ytljit/vm_inline_method.rb +85 -0
  27. data/lib/ytljit/vm_inspect.rb +74 -0
  28. data/lib/ytljit/vm_sendnode.rb +561 -0
  29. data/lib/ytljit/vm_trans.rb +508 -0
  30. data/lib/ytljit/vm_type.rb +299 -0
  31. data/lib/ytljit/vm_type_gen.rb +158 -0
  32. data/lib/ytljit/vm_typeinf.rb +98 -0
  33. data/lib/ytljit.rb +46 -0
  34. data/test/asmsample.rb +117 -0
  35. data/test/cstest.rb +61 -0
  36. data/test/marshaltest.rb +27 -0
  37. data/test/test_assemble.rb +148 -0
  38. data/test/test_assemble2.rb +286 -0
  39. data/test/test_codespace.rb +102 -0
  40. data/test/test_typeinf.rb +21 -0
  41. data/test/tivmtest.rb +54 -0
  42. data/test/vmtest.rb +59 -0
  43. data/test/vmtest2.rb +41 -0
  44. data/test/vmtest3.rb +22 -0
  45. data/test/vmtest_compile_only.rb +41 -0
  46. data/test/vmtest_execute_only.rb +22 -0
  47. metadata +121 -0
@@ -0,0 +1,561 @@
1
+ module YTLJit
2
+ module VM
3
+ # Expression of VM is a set of Nodes
4
+ module Node
5
+ # Opt_flag operation
6
+ module OptFlagOp
7
+ def is_args_splat
8
+ (@opt_flag & (1 << 1)) != 0
9
+ end
10
+
11
+ def is_args_blockarg
12
+ (@opt_flag & (1 << 2)) != 0
13
+ end
14
+
15
+ def is_fcall
16
+ (@opt_flag & (1 << 3)) != 0
17
+ end
18
+
19
+ def is_vcall
20
+ (@opt_flag & (1 << 4)) != 0
21
+ end
22
+
23
+ def is_tailcall
24
+ (@opt_flag & (1 << 5)) != 0
25
+ end
26
+
27
+ def is_tailrecursion
28
+ (@opt_flag & (1 << 6)) != 0
29
+ end
30
+
31
+ def is_super
32
+ (@opt_flag & (1 << 7)) != 0
33
+ end
34
+
35
+ def is_opt_send
36
+ (@opt_flag & (1 << 8)) != 0
37
+ end
38
+ end
39
+
40
+ # Send methodes
41
+ class SendNode<BaseNode
42
+ include HaveChildlenMixin
43
+ include OptFlagOp
44
+ include SendNodeCodeGen
45
+ include NodeUtil
46
+ include SendUtil
47
+
48
+ @@current_node = nil
49
+ @@special_node_tab = {}
50
+
51
+ def self.node
52
+ @@current_node
53
+ end
54
+
55
+ def self.add_special_send_node(name)
56
+ @@special_node_tab[name] = self
57
+ end
58
+
59
+ def self.make_send_node(parent, func, arguments, op_flag)
60
+ spcl = @@special_node_tab[func.name]
61
+ newobj = nil
62
+ if spcl then
63
+ newobj = spcl.new(parent, func, arguments, op_flag)
64
+ else
65
+ newobj = self.new(parent, func, arguments, op_flag)
66
+ end
67
+ func.parent = newobj
68
+ arguments.each do |ele|
69
+ ele.parent = newobj
70
+ end
71
+
72
+ newobj
73
+ end
74
+
75
+ def initialize(parent, func, arguments, op_flag)
76
+ super(parent)
77
+ @func = func
78
+ @arguments = arguments
79
+ @opt_flag = op_flag
80
+ @var_return_address = nil
81
+ @next_node = @@current_node
82
+ @@current_node = self
83
+
84
+ @class_top = search_class_top
85
+ @frame_info = search_frame_info
86
+
87
+ @modified_instance_var = nil
88
+ @modified_local_var = [{}]
89
+ end
90
+
91
+ attr_accessor :func
92
+ attr_accessor :arguments
93
+ attr :opt_flag
94
+ attr :var_return_address
95
+ attr :next_node
96
+ attr :class_top
97
+ attr :modified_local_var
98
+ attr :modified_instance_var
99
+
100
+ def traverse_childlen
101
+ @arguments.each do |arg|
102
+ yield arg
103
+ end
104
+ yield @func
105
+ end
106
+
107
+ def collect_candidate_type_regident(context, slf)
108
+ p @func.name
109
+ context
110
+ end
111
+
112
+ def collect_info(context)
113
+ traverse_childlen {|rec|
114
+ context = rec.collect_info(context)
115
+ }
116
+ if is_fcall or is_vcall then
117
+ # Call method of same class
118
+ mt = @class_top.method_tab[@func.name]
119
+ if mt then
120
+ miv = mt.modified_instance_var
121
+ if miv then
122
+ miv.each do |vname, vall|
123
+ context.modified_instance_var[vname] = vall
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ @modified_local_var = context.modified_local_var.dup
130
+ @modified_instance_var = context.modified_instance_var.dup
131
+
132
+ context
133
+ end
134
+
135
+ def collect_candidate_type(context)
136
+ # prev env
137
+ context = @arguments[0].collect_candidate_type(context)
138
+
139
+ # block is after detect method
140
+ blknode = @arguments[1]
141
+
142
+ # other
143
+ @arguments[2.. -1].each do |arg|
144
+ context = arg.collect_candidate_type(context)
145
+ end
146
+
147
+ # function select
148
+ context = @func.collect_candidate_type(context)
149
+
150
+ signat = signature(context)
151
+ mt = nil
152
+ if is_fcall or is_vcall then
153
+ mt = @func.method_top_node(@class_top, nil)
154
+ else
155
+ @arguments[2].decide_type_once(context.to_key)
156
+ slf = @arguments[2].type
157
+ if slf.instance_of?(RubyType::DefaultType0) then
158
+ # Chaos
159
+
160
+ else
161
+ mt = @func.method_top_node(@class_top, slf)
162
+ end
163
+ end
164
+
165
+ if mt then
166
+ same_type(self, mt, context.to_key, signat, context)
167
+ same_type(mt, self, signat, context.to_key, context)
168
+
169
+ context.current_method_signature_node.push @arguments
170
+ mt.yield_node.map do |ynode|
171
+ yargs = ynode.arguments
172
+ ysignat = ynode.signature(context)
173
+ same_type(blknode, ynode, ysignat, signat, context)
174
+ same_type(ynode, blknode, signat, ysignat, context)
175
+ end
176
+ context.current_method_signature_node.pop
177
+
178
+ context = mt.collect_candidate_type(context, @arguments, signat)
179
+
180
+ context.current_method_signature_node.push @arguments
181
+ mt.yield_node.map do |ynode|
182
+ yargs = ynode.arguments
183
+ ysignat = ynode.signature(context)
184
+ if blknode.is_a?(TopNode) then
185
+ # Have block
186
+ context = blknode.collect_candidate_type(context,
187
+ yargs, ysignat)
188
+ else
189
+ context = blknode.collect_candidate_type(context)
190
+ end
191
+ end
192
+ context.current_method_signature_node.pop
193
+ else
194
+ context = collect_candidate_type_regident(context, slf)
195
+ end
196
+
197
+ @body.collect_candidate_type(context)
198
+ end
199
+
200
+ def compile(context)
201
+ context = super(context)
202
+
203
+ context.start_using_reg(TMPR2)
204
+ context.start_using_reg(TMPR3)
205
+ callconv = @func.calling_convention(context)
206
+ fnc = nil
207
+
208
+ case callconv
209
+ when :c_vararg
210
+ context.start_using_reg(TMPR2)
211
+
212
+ context = gen_make_argv(context) do |context, rarg|
213
+ context.start_using_reg(FUNC_ARG[0])
214
+ context.start_using_reg(FUNC_ARG[1])
215
+ context.start_using_reg(FUNC_ARG[2])
216
+
217
+ context.cpustack_pushn(3 * AsmType::MACHINE_WORD.size)
218
+ casm = context.assembler
219
+ # Method Select
220
+ # it is legal. use TMPR2 for method select
221
+ # use TMPR3 for store self
222
+ context = @func.compile(context)
223
+ fnc = context.ret_reg
224
+ casm.with_retry do
225
+ casm.mov(FUNC_ARG[0], rarg.size) # argc
226
+ casm.mov(FUNC_ARG[1], TMPR2) # argv
227
+ casm.mov(FUNC_ARG[2], TMPR3) # self
228
+ end
229
+ context.set_reg_content(FUNC_ARG[0], nil)
230
+ context.set_reg_content(FUNC_ARG[1], TMPR2)
231
+ context.set_reg_content(FUNC_ARG[2], context.ret_node)
232
+
233
+ context = gen_call(context, fnc, 3)
234
+ context.cpustack_popn(3 * AsmType::MACHINE_WORD.size)
235
+
236
+ context.end_using_reg(FUNC_ARG[2])
237
+ context.end_using_reg(FUNC_ARG[1])
238
+ context.end_using_reg(FUNC_ARG[0])
239
+ context.end_using_reg(TMPR2)
240
+ context.ret_reg = RETR
241
+ context.ret_node = self
242
+
243
+ decide_type_once(context.to_key)
244
+ context = @type.to_box.gen_unboxing(context)
245
+
246
+ context
247
+ end
248
+
249
+ when :c_fixarg
250
+ numarg = @arguments.size - 2
251
+
252
+ numarg.times do |i|
253
+ context.start_using_reg(FUNC_ARG[i])
254
+ end
255
+ context.cpustack_pushn(numarg * AsmType::MACHINE_WORD.size)
256
+
257
+ argpos = 0
258
+ cursrc = 0
259
+ @arguments.each do |arg|
260
+ # skip prevenv and block_argument
261
+ if cursrc < 2 then
262
+ cursrc = cursrc + 1
263
+ next
264
+ end
265
+
266
+ if cursrc == 2 then
267
+ # Self
268
+ # Method Select
269
+ # it is legal. use TMPR2 for method select
270
+ # use TMPR3 for store self
271
+ context = @func.compile(context)
272
+ fnc = context.ret_reg
273
+ casm = context.assembler
274
+ casm.with_retry do
275
+ casm.mov(FUNC_ARG[0], TMPR3)
276
+ end
277
+ context.set_reg_content(FUNC_ARG[0], context.ret_node)
278
+ else
279
+ # other arg.
280
+ context = arg.compile(context)
281
+ context.ret_node.decide_type_once(context.to_key)
282
+ rtype = context.ret_node.type
283
+ context = rtype.gen_boxing(context)
284
+ casm = context.assembler
285
+ casm.with_retry do
286
+ casm.mov(FUNC_ARG[argpos], context.ret_reg)
287
+ end
288
+ context.set_reg_content(FUNC_ARG[argpos], context.ret_node)
289
+ end
290
+ argpos = argpos + 1
291
+ cursrc = cursrc + 1
292
+ end
293
+
294
+ context = gen_call(context, fnc, numarg)
295
+
296
+ context.cpustack_popn(numarg * AsmType::MACHINE_WORD.size)
297
+ numarg.times do |i|
298
+ context.end_using_reg(FUNC_ARG[numarg - i - 1])
299
+ end
300
+ context.end_using_reg(fnc)
301
+
302
+ decide_type_once(context.to_key)
303
+ context = @type.to_box.gen_unboxing(context)
304
+
305
+ when :ytl
306
+ numarg = @arguments.size
307
+
308
+ numarg.times do |i|
309
+ context.start_using_reg(FUNC_ARG_YTL[i])
310
+ end
311
+ context.cpustack_pushn(numarg * 8)
312
+
313
+ # push prev env
314
+ casm = context.assembler
315
+ casm.with_retry do
316
+ casm.mov(FUNC_ARG_YTL[0], BPR)
317
+ end
318
+ context.set_reg_content(FUNC_ARG_YTL[0], BPR)
319
+
320
+ # block
321
+ # eval block
322
+ # local block
323
+
324
+ # compile block with other code space and context
325
+ tcontext = context.dup
326
+ @arguments[1].compile(tcontext)
327
+
328
+ casm = context.assembler
329
+ casm.with_retry do
330
+ entry = @arguments[1].code_space.var_base_immidiate_address
331
+ casm.mov(FUNC_ARG_YTL[1], entry)
332
+ end
333
+ context.set_reg_content(FUNC_ARG_YTL[1], nil)
334
+
335
+ # other arguments
336
+ @arguments[3..-1].each_with_index do |arg, i|
337
+ context = arg.compile(context)
338
+ casm = context.assembler
339
+ casm.with_retry do
340
+ casm.mov(FUNC_ARG_YTL[i + 3], context.ret_reg)
341
+ end
342
+ context.set_reg_content(FUNC_ARG_YTL[i + 3], context.ret_node)
343
+ end
344
+
345
+ # self
346
+ # Method Select
347
+ # it is legal. use TMPR2 for method select
348
+ # use TMPR3 for store self
349
+ context = @func.compile(context)
350
+ fnc = context.ret_reg
351
+ casm = context.assembler
352
+ casm.with_retry do
353
+ casm.mov(FUNC_ARG_YTL[2], TMPR3)
354
+ end
355
+ context.set_reg_content(FUNC_ARG_YTL[2], @arguments[2])
356
+
357
+ context = gen_call(context, fnc, numarg)
358
+
359
+ context.cpustack_popn(numarg * 8)
360
+ numarg.size.times do |i|
361
+ context.end_using_reg(FUNC_ARG_YTL[numarg - i])
362
+ end
363
+ context.end_using_reg(fnc)
364
+ end
365
+
366
+ decide_type_once(context.to_key)
367
+ if @type.is_a?(RubyType::RubyTypeUnboxed) and
368
+ @type.ruby_type == Float then
369
+ context.ret_reg = XMM0
370
+ else
371
+ context.ret_reg = RETR
372
+ end
373
+ context.ret_node = self
374
+ context.end_using_reg(TMPR3)
375
+ context.end_using_reg(TMPR2)
376
+
377
+ context = @body.compile(context)
378
+ context
379
+ end
380
+ end
381
+
382
+ class SendCoreDefineMethodNode<SendNode
383
+ add_special_send_node :"core#define_method"
384
+ def initialize(parent, func, arguments, op_flag)
385
+ super
386
+ @new_method = arguments[5]
387
+ if arguments[4].is_a?(LiteralNode) then
388
+ @new_method.name = arguments[4].value
389
+ @class_top.method_tab[arguments[4].value] = @new_method
390
+ end
391
+ end
392
+
393
+ def traverse_childlen
394
+ yield @body
395
+ yield @new_method
396
+ end
397
+
398
+ def collect_candidate_type(context)
399
+ # type inference of @new method execute when "send" instruction.
400
+ @body.collect_candidate_type(context)
401
+ context
402
+ end
403
+
404
+ def compile(context)
405
+ context = @body.compile(context)
406
+ ocs = context.code_space
407
+ # Allocate new code space in compiling @new_method
408
+ context = @new_method.compile(context)
409
+ context.set_code_space(ocs)
410
+
411
+ context
412
+ end
413
+ end
414
+
415
+ class SendPlusNode<SendNode
416
+ include ArithmeticOperationUtil
417
+ include SendUtil
418
+ add_special_send_node :+
419
+
420
+ def initialize(parent, func, arguments, op_flag)
421
+ super
422
+ end
423
+
424
+ def collect_candidate_type_regident(context, slf)
425
+ case [slf.ruby_type]
426
+ when [Fixnum], [Float], [String]
427
+ same_type(@arguments[3], @arguments[2],
428
+ context.to_key, context.to_key, context)
429
+ same_type(@arguments[2], @arguments[3],
430
+ context.to_key, context.to_key, context)
431
+ same_type(self, @arguments[2],
432
+ context.to_key, context.to_key, context)
433
+ same_type(@arguments[2], self,
434
+ context.to_key, context.to_key, context)
435
+ end
436
+
437
+ context
438
+ end
439
+
440
+ #=begin
441
+ def compile(context)
442
+ @arguments[2].decide_type_once(context.to_key)
443
+ rtype = @arguments[2].type
444
+ if rtype.is_a?(RubyType::DefaultType0) or
445
+ @class_top.method_tab(rtype.ruby_type)[@func.name] then
446
+ return super(context)
447
+ end
448
+
449
+ context.current_method_signature.push signature(context)
450
+ context = gen_eval_self(context)
451
+ if rtype.ruby_type == Fixnum then
452
+ context = gen_arithmetic_operation(context, :add, TMPR2, TMPR)
453
+ elsif rtype.ruby_type == Float then
454
+ context = gen_arithmetic_operation(context, :addsd, XMM4, XMM0)
455
+ else
456
+ raise "Unkown method #{rtype.ruby_type}##{@func.name}"
457
+ end
458
+ context.current_method_signature.pop
459
+ @body.compile(context)
460
+ end
461
+ #=end
462
+ end
463
+
464
+ class SendCompareNode<SendNode
465
+ include SendUtil
466
+ def collect_candidate_type_regident(context, slf)
467
+ same_type(@arguments[3], @arguments[2],
468
+ context.to_key, context.to_key, context)
469
+ same_type(@arguments[2], @arguments[3],
470
+ context.to_key, context.to_key, context)
471
+ tt = RubyType::BaseType.from_ruby_class(true)
472
+ @type_list.add_type(context.to_key, tt)
473
+ tt = RubyType::BaseType.from_ruby_class(false)
474
+ @type_list.add_type(context.to_key, tt)
475
+
476
+ context
477
+ end
478
+
479
+ def compile(context)
480
+ @arguments[2].decide_type_once(context.to_key)
481
+ rtype = @arguments[2].type
482
+ if rtype.ruby_type.is_a?(RubyType::DefaultType0) or
483
+ @class_top.method_tab(rtype.ruby_type)[@func.name] then
484
+ return super(context)
485
+ end
486
+
487
+ context.current_method_signature.push signature(context)
488
+ context = gen_eval_self(context)
489
+ if rtype.ruby_type == Fixnum then
490
+ context = compile_compare(context)
491
+ else
492
+ raise "Unkown method #{rtype.ruby_type} #{@func.name}"
493
+ end
494
+ context.current_method_signature.pop
495
+ @body.compile(context)
496
+ end
497
+ end
498
+
499
+ class SendGtNode<SendCompareNode
500
+ include CompareOperationUtil
501
+ add_special_send_node :<
502
+ def compile_compare(context)
503
+ context = gen_compare_operation(context , :setg, TMPR2, TMPR)
504
+ end
505
+ end
506
+
507
+ class SendGeNode<SendCompareNode
508
+ include CompareOperationUtil
509
+ add_special_send_node :<=
510
+ def compile_compare(context)
511
+ context = gen_compare_operation(context , :setge, TMPR2, TMPR)
512
+ end
513
+ end
514
+
515
+ class SendLtNode<SendCompareNode
516
+ include CompareOperationUtil
517
+ add_special_send_node :>
518
+ def compile_compare(context)
519
+ context = gen_compare_operation(context , :setl, TMPR2, TMPR)
520
+ end
521
+ end
522
+
523
+ class SendLeNode<SendCompareNode
524
+ include CompareOperationUtil
525
+ add_special_send_node :>=
526
+ def compile_compare(context)
527
+ context = gen_compare_operation(context , :setle, TMPR2, TMPR)
528
+ end
529
+ end
530
+
531
+ class SendRefNode<SendNode
532
+ include SendUtil
533
+ add_special_send_node :[]
534
+ def collect_candidate_type_regident(context, slf)
535
+ case [slf.ruby_type]
536
+ when [Array]
537
+ fixtype = RubyType::BaseType.from_ruby_class(Fixnum)
538
+ @arguments[3].add_type(context.to_key, fixtype)
539
+ @arguments[2].add_element_node(context.to_key, self, context)
540
+ key = context.to_key
541
+ decide_type_once(key)
542
+ # @arguments[2].type = nil
543
+ # @arguments[2].decide_type_once(context.to_key)
544
+ epare = @arguments[2].element_node_list[0]
545
+ ekey = epare[0]
546
+ enode = epare[1]
547
+ if enode != self then
548
+ same_type(self, enode, key, ekey, context)
549
+ same_type(enode, self, ekey, key, context)
550
+ end
551
+
552
+ when [Hash]
553
+ @arguments[2].add_element_node(context.to_key, self, context)
554
+ end
555
+
556
+ context
557
+ end
558
+ end
559
+ end
560
+ end
561
+ end