ytljit 0.0.6 → 0.0.7
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/ext/code_alloc.c +39 -17
- data/ext/memory.c +170 -22
- data/ext/ytljit.c +57 -2
- data/ext/ytljit.h +15 -2
- data/lib/ytljit/asm.rb +21 -0
- data/lib/ytljit/asmext_x64.rb +1 -1
- data/lib/ytljit/asmutil.rb +1 -0
- data/lib/ytljit/instruction.rb +6 -0
- data/lib/ytljit/instruction_ia.rb +31 -2
- data/lib/ytljit/util.rb +5 -4
- data/lib/ytljit/vm.rb +771 -182
- data/lib/ytljit/vm_codegen.rb +76 -25
- data/lib/ytljit/vm_cruby_obj.rb +34 -13
- data/lib/ytljit/vm_inline_method.rb +154 -32
- data/lib/ytljit/vm_sendnode.rb +597 -112
- data/lib/ytljit/vm_trans.rb +148 -35
- data/lib/ytljit/vm_type.rb +5 -1
- data/lib/ytljit/vm_type_gen.rb +224 -51
- data/lib/ytljit.rb +5 -0
- data/test/test_assemble2.rb +35 -5
- metadata +3 -3
data/lib/ytljit/vm_trans.rb
CHANGED
@@ -3,11 +3,15 @@ module YTLJit
|
|
3
3
|
class YARVContext
|
4
4
|
include Node
|
5
5
|
|
6
|
-
def initialize
|
7
|
-
|
6
|
+
def initialize(oldcontext = nil)
|
7
|
+
if oldcontext and false then
|
8
|
+
@the_top = oldcontext.the_top
|
9
|
+
else
|
10
|
+
@the_top = TopTopNode.new(nil, Object)
|
11
|
+
end
|
8
12
|
@top_nodes = [@the_top]
|
9
13
|
@current_file_name = nil
|
10
|
-
@current_class_node = the_top
|
14
|
+
@current_class_node = @the_top
|
11
15
|
@current_method_node = nil
|
12
16
|
|
13
17
|
@enc_label = ""
|
@@ -16,10 +20,15 @@ module YTLJit
|
|
16
20
|
@current_local_label = nil
|
17
21
|
|
18
22
|
@current_node = @the_top
|
23
|
+
|
19
24
|
@vmtab = []
|
20
25
|
|
21
26
|
@expstack = []
|
27
|
+
|
22
28
|
@local_label_tab = {}
|
29
|
+
@local_label_list = []
|
30
|
+
|
31
|
+
@exception_table = {}
|
23
32
|
|
24
33
|
@not_reached_pos = false
|
25
34
|
|
@@ -39,10 +48,14 @@ module YTLJit
|
|
39
48
|
attr_accessor :current_local_label
|
40
49
|
|
41
50
|
attr_accessor :current_node
|
51
|
+
|
42
52
|
attr :vmtab
|
43
53
|
|
44
54
|
attr :expstack
|
45
55
|
attr :local_label_tab
|
56
|
+
attr :local_label_list
|
57
|
+
|
58
|
+
attr_accessor :exception_table
|
46
59
|
|
47
60
|
attr_accessor :not_reached_pos
|
48
61
|
|
@@ -53,7 +66,19 @@ module YTLJit
|
|
53
66
|
if ctn == nil then
|
54
67
|
ctn = ClassTopNode.new(@the_top, klass, klass.name)
|
55
68
|
end
|
56
|
-
|
69
|
+
|
70
|
+
valnode = nil
|
71
|
+
if value.is_a?(Class) then
|
72
|
+
valnode = ClassTopNode.get_class_top_node(value)
|
73
|
+
if valnode == nil then
|
74
|
+
valnode = ClassTopNode.new(@the_top, value, value.name)
|
75
|
+
klassclass = valnode.klassclass
|
76
|
+
valnode.type = RubyType::BaseType.from_ruby_class(klassclass)
|
77
|
+
end
|
78
|
+
else
|
79
|
+
valnode = LiteralNode.new(ctn, value)
|
80
|
+
end
|
81
|
+
|
57
82
|
ctn.get_constant_tab[name] = valnode
|
58
83
|
end
|
59
84
|
|
@@ -71,6 +96,22 @@ module YTLJit
|
|
71
96
|
mname,
|
72
97
|
@current_line_no]
|
73
98
|
end
|
99
|
+
|
100
|
+
def current_exception_table
|
101
|
+
result = {}
|
102
|
+
@exception_table.each do |kind, lst|
|
103
|
+
lst.each do |st, ed, cnt, body|
|
104
|
+
if @local_label_list.include?(st) and
|
105
|
+
!@local_label_list.include?(ed) and
|
106
|
+
body then
|
107
|
+
result[kind] = [st, ed, cnt, body]
|
108
|
+
break
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
result
|
114
|
+
end
|
74
115
|
end
|
75
116
|
|
76
117
|
class YARVTranslatorBase
|
@@ -131,6 +172,7 @@ module YTLJit
|
|
131
172
|
nllab = context.local_label_tab[label]
|
132
173
|
if nllab == nil then
|
133
174
|
nllab = LocalLabel.new(curnode, label)
|
175
|
+
nllab.value_node = PhiNode.new(nllab)
|
134
176
|
nllab.debug_info = context.debug_info
|
135
177
|
context.local_label_tab[label] = nllab
|
136
178
|
end
|
@@ -148,23 +190,26 @@ module YTLJit
|
|
148
190
|
|
149
191
|
def visit_symbol(code, ins, context)
|
150
192
|
context.current_local_label = ins
|
193
|
+
context.local_label_list.push ins
|
151
194
|
|
152
195
|
curnode = context.current_node
|
153
196
|
nllab = get_vmnode_from_label(context, ins)
|
154
197
|
|
155
|
-
|
198
|
+
if !(curnode.is_a?(JumpNode) or
|
199
|
+
curnode.is_a?(MethodEndNode) or
|
200
|
+
curnode.is_a?(ThrowNode)) then
|
156
201
|
jmpnode = JumpNode.new(curnode, nllab)
|
157
202
|
jmpnode.debug_info = context.debug_info
|
158
203
|
nllab.parent = jmpnode
|
159
204
|
|
160
205
|
val = context.expstack.pop
|
161
206
|
nllab.come_from[jmpnode] = val
|
162
|
-
|
207
|
+
|
163
208
|
curnode.body = jmpnode
|
164
209
|
jmpnode.body = nllab
|
165
210
|
context.expstack.push nllab.value_node
|
166
211
|
end
|
167
|
-
|
212
|
+
|
168
213
|
context.current_node = nllab
|
169
214
|
end
|
170
215
|
|
@@ -187,20 +232,53 @@ module YTLJit
|
|
187
232
|
(arg_size - locals.size).times do
|
188
233
|
locals.push nil
|
189
234
|
end
|
190
|
-
|
191
235
|
cnode = mtopnode.construct_frame_info(locals, arg_size, args)
|
236
|
+
exptab = code.header['exception_table']
|
237
|
+
context.exception_table = {}
|
238
|
+
if exptab.size != 0 then
|
239
|
+
exptab.each do |tag, body, st, ed, cont, sp|
|
240
|
+
context.exception_table[tag] ||= []
|
241
|
+
nbody = nil
|
242
|
+
if body then
|
243
|
+
ncontext = YARVContext.new(context)
|
244
|
+
nbody = ExceptionTopNode.new(mtopnode)
|
245
|
+
nbody.debug_info = context.debug_info
|
246
|
+
ncontext.current_node = nbody
|
247
|
+
ncontext.top_nodes.push nbody
|
248
|
+
ncontext.current_file_name = context.current_file_name
|
249
|
+
ncontext.current_class_node = context.current_class_node
|
250
|
+
ncontext.current_method_node = context.current_method_node
|
251
|
+
tr = self.class.new([VMLib::InstSeqTree.new(code, body)])
|
252
|
+
tr.translate(ncontext)
|
253
|
+
end
|
254
|
+
context.exception_table[tag].push [st, ed, cont, nbody]
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
context.not_reached_pos = false
|
192
259
|
context.current_node = cnode
|
193
260
|
end
|
194
261
|
|
195
262
|
def visit_block_end(code, ins, context)
|
196
263
|
curnode = context.current_node
|
197
264
|
top = context.top_nodes.last
|
265
|
+
klassnode = context.current_class_node
|
266
|
+
top.exception_table = context.exception_table
|
198
267
|
if top.class == MethodTopNode then
|
199
268
|
if context.macro_method then
|
200
269
|
code = top.to_ruby(ToRubyContext.new).ret_code.last
|
201
|
-
# print code
|
270
|
+
# print code
|
202
271
|
proc = eval("lambda" + code)
|
203
|
-
SendNode.get_macro_tab[top.name]
|
272
|
+
if SendNode.get_macro_tab[top.name] == nil then
|
273
|
+
SendNode.get_macro_tab[top.name] = {}
|
274
|
+
end
|
275
|
+
SendNode.get_macro_tab[top.name][:last] = proc
|
276
|
+
else
|
277
|
+
if !SendNode.get_user_defined_method_tab[top.name] then
|
278
|
+
SendNode.get_user_defined_method_tab[top.name] = []
|
279
|
+
end
|
280
|
+
klassobj = klassnode.klass_object
|
281
|
+
SendNode.get_user_defined_method_tab[top.name].push klassobj
|
204
282
|
end
|
205
283
|
end
|
206
284
|
end
|
@@ -216,6 +294,9 @@ module YTLJit
|
|
216
294
|
dep
|
217
295
|
end
|
218
296
|
|
297
|
+
def visit_nop(code, ins, context)
|
298
|
+
end
|
299
|
+
|
219
300
|
def visit_getlocal(code, ins, context)
|
220
301
|
dep = depth_of_block(code)
|
221
302
|
visit_getdynamic(code, [:getlocal, ins[1], dep], context)
|
@@ -237,8 +318,14 @@ module YTLJit
|
|
237
318
|
curcode = curcode.parent
|
238
319
|
end
|
239
320
|
offset = curcode.header['misc'][:local_size] + 3 - ins[1]
|
240
|
-
node =
|
241
|
-
|
321
|
+
node = nil
|
322
|
+
if curcode.header['type'] == :ensure and offset == 3 then
|
323
|
+
node = LiteralNode.new(context.current_node, nil)
|
324
|
+
node.debug_info = context.debug_info
|
325
|
+
else
|
326
|
+
node = LocalVarRefNode.new(context.current_node, offset, dep)
|
327
|
+
node.debug_info = context.debug_info
|
328
|
+
end
|
242
329
|
context.expstack.push node
|
243
330
|
end
|
244
331
|
|
@@ -348,7 +435,7 @@ module YTLJit
|
|
348
435
|
def visit_putiseq(code, ins, context)
|
349
436
|
body = VMLib::InstSeqTree.new(code, ins[1])
|
350
437
|
curnode = context.current_node
|
351
|
-
ncontext = YARVContext.new
|
438
|
+
ncontext = YARVContext.new(context)
|
352
439
|
|
353
440
|
case body.header['type']
|
354
441
|
when :block
|
@@ -356,7 +443,7 @@ module YTLJit
|
|
356
443
|
when :method
|
357
444
|
mtopnode = MethodTopNode.new(curnode, body.header['name'].to_sym)
|
358
445
|
when :class
|
359
|
-
mtopnode = ClassTopNode.new(curnode, body.header['name'].to_sym)
|
446
|
+
mtopnode = ClassTopNode.new(curnode, Object, body.header['name'].to_sym)
|
360
447
|
when :top
|
361
448
|
raise "Maybe bug not appear top block."
|
362
449
|
end
|
@@ -426,7 +513,8 @@ module YTLJit
|
|
426
513
|
|
427
514
|
def visit_newarray(code, ins, context)
|
428
515
|
curnode = context.current_node
|
429
|
-
func = FixArgCApiNode.new(curnode, "rb_ary_new3",
|
516
|
+
func = FixArgCApiNode.new(curnode, "rb_ary_new3",
|
517
|
+
[:int, :VALUE, :"..."])
|
430
518
|
argnum = ins[1]
|
431
519
|
argnumnode = LiteralNode.new(nil, argnum)
|
432
520
|
args = []
|
@@ -453,7 +541,7 @@ module YTLJit
|
|
453
541
|
# newhash
|
454
542
|
|
455
543
|
def visit_newrange(code, ins, context)
|
456
|
-
exclflag = LiteralNode.new(nil, ins[1]
|
544
|
+
exclflag = LiteralNode.new(nil, ins[1] != 0)
|
457
545
|
context.expstack.push exclflag
|
458
546
|
newinst_to_sendnode(3, Range, code, ins, context)
|
459
547
|
end
|
@@ -483,7 +571,20 @@ module YTLJit
|
|
483
571
|
end
|
484
572
|
|
485
573
|
def visit_dupn(code, ins, context)
|
486
|
-
|
574
|
+
res = []
|
575
|
+
n = ins[1]
|
576
|
+
n.times do
|
577
|
+
orgnode = context.expstack.pop
|
578
|
+
nnode = MultiplexNode.new(orgnode)
|
579
|
+
res.push nnode
|
580
|
+
end
|
581
|
+
res = res.reverse
|
582
|
+
res.each do |ele|
|
583
|
+
context.expstack.push ele
|
584
|
+
end
|
585
|
+
res.each do |ele|
|
586
|
+
context.expstack.push ele
|
587
|
+
end
|
487
588
|
end
|
488
589
|
|
489
590
|
def visit_swap(code, ins, context)
|
@@ -568,7 +669,7 @@ module YTLJit
|
|
568
669
|
context.current_class_node.constant_tab[name] = cnode
|
569
670
|
|
570
671
|
body = VMLib::InstSeqTree.new(code, ins[2])
|
571
|
-
ncontext = YARVContext.new
|
672
|
+
ncontext = YARVContext.new(context)
|
572
673
|
ncontext.current_file_name = context.current_file_name
|
573
674
|
ncontext.current_node = cnode
|
574
675
|
ncontext.current_class_node = cnode
|
@@ -612,7 +713,7 @@ module YTLJit
|
|
612
713
|
# block
|
613
714
|
if blk_iseq then
|
614
715
|
body = VMLib::InstSeqTree.new(code, blk_iseq)
|
615
|
-
ncontext = YARVContext.new
|
716
|
+
ncontext = YARVContext.new(context)
|
616
717
|
ncontext.current_file_name = context.current_file_name
|
617
718
|
ncontext.current_class_node = context.current_class_node
|
618
719
|
ncontext.current_method_node = context.current_method_node
|
@@ -639,32 +740,30 @@ module YTLJit
|
|
639
740
|
arg = arg.reverse
|
640
741
|
|
641
742
|
func = MethodSelectNode.new(curnode, ins[1])
|
642
|
-
sn = SendNode.
|
643
|
-
if sn
|
644
|
-
|
645
|
-
|
743
|
+
sn = SendNode.macro_expand(context, func, arg, op_flag, seqno)
|
744
|
+
if sn == nil then
|
745
|
+
sn = SendNode.make_send_node(curnode, func, arg, op_flag, seqno)
|
746
|
+
sn.current_exception_table = context.current_exception_table
|
747
|
+
if sn.is_a?(SendEvalNode) then
|
748
|
+
if context.macro_method == nil then
|
749
|
+
context.macro_method = true
|
750
|
+
end
|
646
751
|
end
|
647
|
-
|
648
|
-
|
649
|
-
if sn.is_a?(SendNode) then
|
752
|
+
|
650
753
|
sn.debug_info = context.debug_info
|
651
754
|
func.set_reciever(sn)
|
652
755
|
context.expstack.push sn
|
653
|
-
|
654
|
-
elsif sn.is_a?(Array)
|
756
|
+
else
|
655
757
|
# macro(including eval method). execute in compile time and
|
656
758
|
# compile eval strings.
|
657
759
|
val, evalstr = sn
|
658
760
|
evalstr = evalstr.join("\n")
|
659
761
|
is = RubyVM::InstructionSequence.compile(
|
660
|
-
|
661
|
-
).to_a
|
762
|
+
evalstr, "macro #{ins[1]}", "", 0, YTL::ISEQ_OPTS).to_a
|
662
763
|
ncode = VMLib::InstSeqTree.new(code, is)
|
663
764
|
ncode.body.pop # Chop leave instruction
|
664
765
|
translate_main(ncode, context)
|
665
|
-
# context.expstack.push val
|
666
|
-
else
|
667
|
-
raise "Unexcepted data type #{sn.class}"
|
766
|
+
# context.expstack.push val
|
668
767
|
end
|
669
768
|
|
670
769
|
context
|
@@ -710,6 +809,7 @@ module YTLJit
|
|
710
809
|
args = args.reverse
|
711
810
|
|
712
811
|
nnode = SendNode.new(curnode, func, args, op_flag, seqno)
|
812
|
+
nnode.current_exception_table = context.current_exception_table
|
713
813
|
nnode.debug_info = context.debug_info
|
714
814
|
func.parent = nnode
|
715
815
|
context.expstack.push nnode
|
@@ -726,13 +826,16 @@ module YTLJit
|
|
726
826
|
visit_pop(code, ins, context)
|
727
827
|
curnode = context.current_node
|
728
828
|
vnode = SelfRefNode.new(curnode)
|
729
|
-
vnode.debug_info = context.debug_info
|
730
829
|
else
|
731
830
|
curnode = context.current_node
|
732
831
|
vnode = context.expstack.pop
|
733
|
-
vnode.debug_info = context.debug_info
|
734
832
|
end
|
735
833
|
|
834
|
+
if vnode then
|
835
|
+
vnode.debug_info = context.debug_info
|
836
|
+
else
|
837
|
+
vnode = LiteralNode.new(curnode, nil)
|
838
|
+
end
|
736
839
|
srnode = SetResultNode.new(curnode, vnode)
|
737
840
|
srnode.debug_info = context.debug_info
|
738
841
|
curnode.body = srnode
|
@@ -748,14 +851,24 @@ module YTLJit
|
|
748
851
|
nnode = ClassEndNode.new(srnode)
|
749
852
|
when :top
|
750
853
|
nnode = ClassEndNode.new(srnode)
|
854
|
+
else
|
855
|
+
raise "unkown type #{code.header['type']}"
|
751
856
|
end
|
752
857
|
nnode.debug_info = context.debug_info
|
753
858
|
|
754
859
|
context.top_nodes.last.end_nodes.push nnode
|
755
860
|
srnode.body = nnode
|
861
|
+
context.current_node = nnode
|
862
|
+
context.not_reached_pos = true
|
756
863
|
end
|
757
864
|
|
758
865
|
def visit_throw(code, ins, context)
|
866
|
+
curnode = context.current_node
|
867
|
+
exceptobj = context.expstack.pop
|
868
|
+
|
869
|
+
thnode = ThrowNode.new(curnode, ins[1], exceptobj)
|
870
|
+
curnode.body = thnode
|
871
|
+
context.current_node = thnode
|
759
872
|
end
|
760
873
|
|
761
874
|
def visit_jump(code, ins, context)
|
data/lib/ytljit/vm_type.rb
CHANGED
@@ -14,7 +14,7 @@ module YTLJit
|
|
14
14
|
return cnode
|
15
15
|
end
|
16
16
|
|
17
|
-
if key.zip(cnode.key).all? {|k, n| k.is_a?(n.class)}
|
17
|
+
if key.zip(cnode.key).all? {|k, n| k.is_a?(n.class)} then
|
18
18
|
cnode = cnode.same_klass
|
19
19
|
if cnode == nil then
|
20
20
|
ocnode.same_klass = KlassTreeNode.new(key, value)
|
@@ -245,6 +245,10 @@ module YTLJit
|
|
245
245
|
@ruby_type
|
246
246
|
end
|
247
247
|
|
248
|
+
def abnormal?
|
249
|
+
@@base_type_tab[ruby_type].boxed != boxed
|
250
|
+
end
|
251
|
+
|
248
252
|
attr_writer :ruby_type
|
249
253
|
end
|
250
254
|
|