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.
- data/README +29 -0
- data/Rakefile +22 -0
- data/ext/code_alloc.c +266 -0
- data/ext/extconf.rb +3 -0
- data/ext/ytljit.c +527 -0
- data/ext/ytljit.h +285 -0
- data/lib/ytljit/asm.rb +205 -0
- data/lib/ytljit/asmext.rb +199 -0
- data/lib/ytljit/asmext_x64.rb +212 -0
- data/lib/ytljit/asmext_x86.rb +128 -0
- data/lib/ytljit/asmutil.rb +182 -0
- data/lib/ytljit/codespace.rb +92 -0
- data/lib/ytljit/error.rb +7 -0
- data/lib/ytljit/instruction.rb +138 -0
- data/lib/ytljit/instruction_ia.rb +1298 -0
- data/lib/ytljit/instruction_x64.rb +41 -0
- data/lib/ytljit/instruction_x86.rb +11 -0
- data/lib/ytljit/marshal.rb +133 -0
- data/lib/ytljit/matcher.rb +235 -0
- data/lib/ytljit/rubyvm.rb +63 -0
- data/lib/ytljit/struct.rb +125 -0
- data/lib/ytljit/type.rb +112 -0
- data/lib/ytljit/util.rb +63 -0
- data/lib/ytljit/vm.rb +1649 -0
- data/lib/ytljit/vm_codegen.rb +491 -0
- data/lib/ytljit/vm_inline_method.rb +85 -0
- data/lib/ytljit/vm_inspect.rb +74 -0
- data/lib/ytljit/vm_sendnode.rb +561 -0
- data/lib/ytljit/vm_trans.rb +508 -0
- data/lib/ytljit/vm_type.rb +299 -0
- data/lib/ytljit/vm_type_gen.rb +158 -0
- data/lib/ytljit/vm_typeinf.rb +98 -0
- data/lib/ytljit.rb +46 -0
- data/test/asmsample.rb +117 -0
- data/test/cstest.rb +61 -0
- data/test/marshaltest.rb +27 -0
- data/test/test_assemble.rb +148 -0
- data/test/test_assemble2.rb +286 -0
- data/test/test_codespace.rb +102 -0
- data/test/test_typeinf.rb +21 -0
- data/test/tivmtest.rb +54 -0
- data/test/vmtest.rb +59 -0
- data/test/vmtest2.rb +41 -0
- data/test/vmtest3.rb +22 -0
- data/test/vmtest_compile_only.rb +41 -0
- data/test/vmtest_execute_only.rb +22 -0
- 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
|
+
|