ytljit 0.0.1

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 (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