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,508 @@
1
+ module YTLJit
2
+ module VM
3
+ class YARVContext
4
+ include Node
5
+
6
+ def initialize
7
+ @the_top = TopTopNode.new(nil, Object)
8
+ @top_nodes = [@the_top]
9
+ @current_file_name = nil
10
+ @current_class_node = the_top
11
+ @current_method_name = nil
12
+
13
+ @enc_label = ""
14
+ @enc_pos_in_source = ""
15
+ @current_line_no = 0
16
+ @current_local_label = nil
17
+
18
+ @current_node = @the_top
19
+ @vmtab = []
20
+
21
+ @expstack = []
22
+ @local_label_tab = {}
23
+
24
+ @not_reached_pos = false
25
+ end
26
+
27
+ attr :the_top
28
+ attr :top_nodes
29
+
30
+ attr_accessor :current_file_name
31
+ attr_accessor :current_class_node
32
+ attr_accessor :current_method_name
33
+
34
+ attr_accessor :enc_label
35
+ attr_accessor :enc_pos_in_source
36
+ attr_accessor :current_line_no
37
+ attr_accessor :current_local_label
38
+
39
+ attr_accessor :current_node
40
+ attr :vmtab
41
+
42
+ attr :expstack
43
+ attr :local_label_tab
44
+
45
+ attr_accessor :not_reached_pos
46
+ end
47
+
48
+ class YARVTranslatorBase
49
+ def initialize(iseqs)
50
+ @iseqs = iseqs
51
+ end
52
+
53
+ def translate(context = nil)
54
+ if context == nil then
55
+ context = YARVContext.new
56
+ end
57
+ @iseqs.each do |code|
58
+ pos = "#{code.header['filename']}:#{context.current_line_no}"
59
+ context.enc_pos_in_source = pos
60
+ if code.header['type'] == :block then
61
+ lstr = context.enc_label + "+blk+" +
62
+ context.current_method_name.to_s
63
+ context.enc_label = lstr
64
+ end
65
+ translate_block(code, context)
66
+ end
67
+
68
+ context.the_top
69
+ end
70
+
71
+ def translate_block(code, context)
72
+ visit_block_start(code, nil, context)
73
+ code.body.each do |ins|
74
+ pos = "#{code.header['filename']}:#{context.current_line_no}"
75
+ context.enc_pos_in_source = pos
76
+ if ins == nil then
77
+ # do nothing
78
+ elsif ins.is_a?(Fixnum) then
79
+ # line no
80
+ context.current_line_no = ins
81
+ elsif ins.is_a?(Symbol) then
82
+ context.not_reached_pos = false
83
+ visit_symbol(code, ins, context)
84
+
85
+ elsif !context.not_reached_pos then
86
+ opname = ins[0].to_s
87
+ send(("visit_" + opname).to_sym, code, ins, context)
88
+ end
89
+ end
90
+ visit_block_end(code, nil, context)
91
+ end
92
+ end
93
+
94
+ module YARVTranslatorSimpleMixin
95
+ include Node
96
+
97
+ def get_vmnode_from_label(context, label)
98
+ curnode = context.current_node
99
+ nllab = context.local_label_tab[label]
100
+ if nllab == nil then
101
+ nllab = LocalLabel.new(curnode, label)
102
+ context.local_label_tab[label] = nllab
103
+ end
104
+
105
+ nllab
106
+ end
107
+
108
+ def visit_symbol(code, ins, context)
109
+ context.current_local_label = ins
110
+
111
+ curnode = context.current_node
112
+ nllab = get_vmnode_from_label(context, ins)
113
+
114
+ unless curnode.is_a?(JumpNode)
115
+ jmpnode = JumpNode.new(curnode, nllab)
116
+ nllab.parent = jmpnode
117
+
118
+ val = context.expstack.pop
119
+ nllab.come_from[jmpnode] = val
120
+
121
+ curnode.body = jmpnode
122
+ jmpnode.body = nllab
123
+ context.expstack.push nllab.value_node
124
+ end
125
+
126
+ context.current_node = nllab
127
+ end
128
+
129
+ def visit_block_start(code, ins, context)
130
+ mtopnode = context.current_node
131
+
132
+ locals = code.header['locals']
133
+ args = code.header['misc'][:arg_size]
134
+
135
+ context.current_node = mtopnode.construct_frame_info(locals, args)
136
+ end
137
+
138
+ def visit_block_end(code, ins, context)
139
+ end
140
+
141
+ def depth_of_block(code)
142
+ dep = 0
143
+ ccode = code
144
+ while ccode.header['type'] == :block
145
+ ccode = code.parent
146
+ dep += 1
147
+ end
148
+
149
+ dep
150
+ end
151
+
152
+ def visit_getlocal(code, ins, context)
153
+ dep = depth_of_block(code)
154
+ visit_getdynamic(code, [:getlocal, ins[1], dep], context)
155
+ end
156
+
157
+ def visit_setlocal(code, ins, context)
158
+ dep = depth_of_block(code)
159
+ visit_setdynamic(code, [:setlocal, ins[1], dep], context)
160
+ end
161
+
162
+ # getspecial
163
+ # setspecial
164
+
165
+ def visit_getdynamic(code, ins, context)
166
+ # + 3 mean prtv_env/pointer to block function/self
167
+ offset = code.header['misc'][:local_size] + 3 - ins[1]
168
+ node = LocalVarRefNode.new(context.current_node, offset, ins[2])
169
+ context.expstack.push node
170
+ end
171
+
172
+ def visit_setdynamic(code, ins, context)
173
+ val = context.expstack.pop
174
+ curnode = context.current_node
175
+ offset = code.header['misc'][:local_size] + 3 - ins[1]
176
+ node = LocalAssignNode.new(curnode, offset, ins[2], val)
177
+ curnode.body = node
178
+ context.current_node = node
179
+ end
180
+
181
+ =begin
182
+ def visit_getinstancevariable(code, ins, context)
183
+ end
184
+
185
+ def visit_setinstancevariable(code, ins, context)
186
+ end
187
+ =end
188
+
189
+ # getclassvariable
190
+ # setclassvariable
191
+
192
+ def visit_getconstant(code, ins, context)
193
+ end
194
+
195
+ def visit_setconstant(code, ins, context)
196
+ end
197
+
198
+ # getglobal
199
+ # setglobal
200
+
201
+ def visit_putnil(code, ins, context)
202
+ nnode = LiteralNode.new(nil, nil)
203
+ context.expstack.push nnode
204
+ end
205
+
206
+ def visit_putself(code, ins, context)
207
+ curnode = context.current_node
208
+ nnode = SelfRefNode.new(curnode)
209
+ context.expstack.push nnode
210
+ end
211
+
212
+ def visit_putobject(code, ins, context)
213
+ nnode = LiteralNode.new(nil, ins[1])
214
+ context.expstack.push nnode
215
+ end
216
+
217
+ def visit_putspecialobject(code, ins, context)
218
+ context.expstack.push SpecialObjectNode.new(nil, ins[1])
219
+ end
220
+
221
+ def visit_putiseq(code, ins, context)
222
+ body = VMLib::InstSeqTree.new(code, ins[1])
223
+ curnode = context.current_node
224
+ ncontext = YARVContext.new
225
+
226
+ case body.header['type']
227
+ when :block
228
+ mtopnode = BlockTopNode.new(curnode)
229
+ when :method
230
+ mtopnode = MethodTopNode.new(curnode)
231
+ when :class
232
+ mtopnode = ClassTopNode.new(curnode)
233
+ when :top
234
+ raise "Maybe bug not appear top block."
235
+ end
236
+ ncontext.current_node = mtopnode
237
+ ncontext.top_nodes.push mtopnode
238
+
239
+ ncontext.current_file_name = context.current_file_name
240
+ ncontext.current_class_node = context.current_class_node
241
+ mname = context.expstack.last
242
+ ncontext.current_method_name = mname
243
+
244
+ tr = self.class.new([body])
245
+ tr.translate(ncontext)
246
+ context.expstack.push mtopnode
247
+ end
248
+
249
+ def visit_putstring(code, ins, context)
250
+ nnode = LiteralNode.new(nil, ins[1])
251
+ context.expstack.push nnode
252
+ end
253
+
254
+ # concatstrings
255
+ # tostring
256
+ # toregexp
257
+ # newarray
258
+
259
+ def visit_duparray(code, ins, context)
260
+ nnode = LiteralNode.new(nil, ins[1])
261
+ context.expstack.push nnode
262
+ end
263
+
264
+ # expandarray
265
+ # concatarray
266
+ # splatarray
267
+ # checkincludearray
268
+ # newhash
269
+ # newrange
270
+
271
+ def visit_pop(code, ins, context)
272
+ node = context.expstack.pop
273
+ curnode = context.current_node
274
+ node.parent = curnode
275
+ curnode.body = node
276
+ context.current_node = node
277
+
278
+ context
279
+ end
280
+
281
+ def visit_dup(code, ins, context)
282
+ context.expstack.push context.expstack.last
283
+ end
284
+
285
+ def visit_dupn(code, ins, context)
286
+ end
287
+
288
+ def visit_swap(code, ins, context)
289
+ end
290
+
291
+ # reput
292
+
293
+ def visit_topn(code, ins, context)
294
+ end
295
+
296
+ def visit_setn(code, ins, context)
297
+ end
298
+
299
+ # adjuststack
300
+ # defined
301
+
302
+ def visit_trace(code, ins, context)
303
+ end
304
+
305
+ def visit_defineclass(code, ins, context)
306
+ name = ins[1]
307
+ supklsnode = context.expstack.pop
308
+ klassobj = Object.const_get(name, true)
309
+
310
+ if klassobj == nil then
311
+ klassnode = context.nested_class_tab[name]
312
+ if klassnode then
313
+ klassobj = klassnodne.klasss_object
314
+
315
+ else
316
+ case ins[3]
317
+ when 0
318
+ supklass = nil
319
+ if supklsnode then
320
+ supklass = supklasnode.klasss_object
321
+ end
322
+ klassobj = Class.new(supklass)
323
+
324
+ when 2
325
+ klassobj = Module.new(supklass)
326
+ end
327
+ end
328
+ end
329
+ cnode = ClassTopNode.new(context.current_class_node, klassobj, name)
330
+
331
+ body = VMLib::InstSeqTree.new(code, ins[2])
332
+ ncontext = YARVContext.new
333
+ ncontext.current_file_name = context.current_file_name
334
+ ncontext.current_node = cnode
335
+ ncontext.current_class_node = cnode
336
+ ncontext.top_nodes.push mtopnode
337
+
338
+ tr = self.class.new([body])
339
+ tr.translate(ncontext)
340
+
341
+ context.current_class_node.nested_class_tab[name] = cnode
342
+ context
343
+ end
344
+
345
+ def visit_send(code, ins, context)
346
+ blk_iseq = ins[3]
347
+ curnode = context.current_node
348
+ numarg = ins[2]
349
+
350
+ # regular arguments
351
+ arg = []
352
+ numarg.times do |i|
353
+ argele = context.expstack.pop
354
+ arg.push argele
355
+ end
356
+
357
+ # self
358
+ arg.push context.expstack.pop
359
+
360
+ # block
361
+ if blk_iseq then
362
+ body = VMLib::InstSeqTree.new(code, blk_iseq)
363
+ ncontext = YARVContext.new
364
+ ncontext.current_file_name = context.current_file_name
365
+ ncontext.current_class_node = curnode
366
+ btn = ncontext.current_node = BlockTopNode.new(curnode)
367
+ ncontext.top_nodes.push btn
368
+
369
+ tr = self.class.new([body])
370
+ tr.translate(ncontext)
371
+ arg.push btn # block
372
+ else
373
+ arg.push LiteralNode.new(curnode, nil) # block(dymmy)
374
+ end
375
+
376
+ # perv env
377
+ arg.push LiteralNode.new(curnode, nil)
378
+
379
+ arg = arg.reverse
380
+
381
+ func = MethodSelectNode.new(curnode, ins[1])
382
+ op_flag = ins[4]
383
+ sn = SendNode.make_send_node(curnode, func, arg, op_flag)
384
+ func.set_reciever(sn)
385
+ context.expstack.push sn
386
+
387
+ context
388
+ end
389
+
390
+ def visit_invokesuper(code, ins, context)
391
+ end
392
+
393
+ def visit_invokeblock(code, ins, context)
394
+ curnode = context.current_node
395
+ func = YieldNode.new(curnode)
396
+ numarg = ins[1]
397
+ op_flag = ins[2]
398
+
399
+ # regular arguments
400
+ args = []
401
+ numarg.times do |i|
402
+ argele = context.expstack.pop
403
+ args.push argele
404
+ end
405
+
406
+ frameinfo = func.frame_info
407
+ roff = frameinfo.real_offset(0) # offset of prevenv
408
+ framelayout = frameinfo.frame_layout
409
+
410
+ # self
411
+ args.push framelayout[roff + 2]
412
+
413
+ # block
414
+ args.push framelayout[roff + 1]
415
+
416
+ # perv env
417
+ args.push framelayout[roff]
418
+
419
+ args = args.reverse
420
+
421
+ nnode = SendNode.new(curnode, func, args, op_flag)
422
+ func.parent = nnode
423
+ context.expstack.push nnode
424
+
425
+ context
426
+ end
427
+
428
+ def visit_leave(code, ins, context)
429
+ curnode = context.current_node
430
+
431
+ vnode = context.expstack.pop
432
+ srnode = SetResultNode.new(curnode, vnode)
433
+ curnode.body = srnode
434
+
435
+ context.current_node = srnode
436
+
437
+ case code.header['type']
438
+ when :method
439
+ nnode = MethodEndNode.new(srnode)
440
+ when :block
441
+ nnode = BlockEndNode.new(srnode)
442
+ when :class
443
+ nnode = ClassEndNode.new(srnode)
444
+ when :top
445
+ nnode = ClassEndNode.new(srnode)
446
+ end
447
+
448
+ context.top_nodes.last.end_nodes.push nnode
449
+ srnode.body = nnode
450
+ end
451
+
452
+ def visit_throw(code, ins, context)
453
+ end
454
+
455
+ def visit_jump(code, ins, context)
456
+ curnode = context.current_node
457
+ nllab = get_vmnode_from_label(context, ins[1])
458
+
459
+ jpnode = JumpNode.new(curnode, nllab)
460
+
461
+ val = context.expstack.pop
462
+ nllab.come_from[jpnode] = val
463
+
464
+ curnode.body = jpnode
465
+ context.current_node = jpnode
466
+ context.not_reached_pos = true
467
+ end
468
+
469
+ def visit_branchif(code, ins, context)
470
+ curnode = context.current_node
471
+ nllab = get_vmnode_from_label(context, ins[1])
472
+
473
+ cond = context.expstack.pop
474
+
475
+ node = BranchIfNode.new(curnode, cond, nllab)
476
+ nllab.come_from[node] = nil
477
+
478
+ curnode.body = node
479
+ context.current_node = node
480
+ end
481
+
482
+ def visit_branchunless(code, ins, context)
483
+ curnode = context.current_node
484
+ nllab = get_vmnode_from_label(context, ins[1])
485
+
486
+ cond = context.expstack.pop
487
+
488
+ node = BranchUnlessNode.new(curnode, cond, nllab)
489
+ nllab.come_from[node] = nil
490
+
491
+ curnode.body = node
492
+ context.current_node = node
493
+ end
494
+
495
+ # getinlinecache
496
+ # onceinlinecache
497
+ # setinlinecache
498
+
499
+ # Optimized instructions is not support. You must compile option for
500
+ # avoid optimized instructions.
501
+ end
502
+
503
+ class YARVTranslatorSimple<YARVTranslatorBase
504
+ include YARVTranslatorSimpleMixin
505
+ end
506
+ end
507
+ end
508
+