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
data/lib/ytljit/vm.rb
ADDED
@@ -0,0 +1,1649 @@
|
|
1
|
+
module YTLJit
|
2
|
+
|
3
|
+
=begin
|
4
|
+
Typical struct of node
|
5
|
+
|
6
|
+
def fact(x)
|
7
|
+
if x == 0 then
|
8
|
+
return 1
|
9
|
+
else
|
10
|
+
return x * fact(x - 1)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
MethodTopNode
|
16
|
+
name -> "fact"
|
17
|
+
body
|
18
|
+
|
|
19
|
+
LocalFrameInfo
|
20
|
+
frame -- infomation of frame (access via insptance methodes)
|
21
|
+
body
|
22
|
+
|
|
23
|
+
GuardInfo
|
24
|
+
type_list -> [[a, Fixnum], [v, Fixnum]], [[a, Float], [v, Fixnum]] ...
|
25
|
+
body
|
26
|
+
# Compile each element of type_list.
|
27
|
+
|
|
28
|
+
BranchIfNode
|
29
|
+
epart------------------+
|
30
|
+
tpart----------------+ |
|
31
|
+
cond | |
|
32
|
+
| | |
|
33
|
+
SendNode | |
|
34
|
+
func -> == | |
|
35
|
+
arg[0]------------+ | |
|
36
|
+
arg[1] | | |
|
37
|
+
| | | |
|
38
|
+
LiteralNode | | |
|
39
|
+
value -> 0 | | |
|
40
|
+
| | |
|
41
|
+
+---------------+ | |
|
42
|
+
| | |
|
43
|
+
LocalVarNode | |
|
44
|
+
offset -> 0 | |
|
45
|
+
depth -> 0 | |
|
46
|
+
| |
|
47
|
+
+------------------+ |
|
48
|
+
| |
|
49
|
+
MethodEndNode |
|
50
|
+
value |
|
51
|
+
| |
|
52
|
+
LiteralNode |
|
53
|
+
value -> 0 |
|
54
|
+
|
|
55
|
+
+--------------------+
|
56
|
+
|
|
57
|
+
MethodEndNode
|
58
|
+
value
|
59
|
+
|
|
60
|
+
SendNode
|
61
|
+
func -> *
|
62
|
+
arg[0] --------------+
|
63
|
+
arg[1] |
|
64
|
+
| |
|
65
|
+
SendNode |
|
66
|
+
func -> fact |
|
67
|
+
arg[0] |
|
68
|
+
| |
|
69
|
+
SendNode |
|
70
|
+
func -> - |
|
71
|
+
arg[0] -----+ |
|
72
|
+
arg[1] | |
|
73
|
+
| | |
|
74
|
+
LiteralNode | |
|
75
|
+
value -> 0 | |
|
76
|
+
| |
|
77
|
+
+----------+ |
|
78
|
+
| |
|
79
|
+
LocalVarNode |
|
80
|
+
offset -> 0 |
|
81
|
+
depth -> 0 |
|
82
|
+
|
|
83
|
+
+-------------------+
|
84
|
+
|
|
85
|
+
LocalVarNode
|
86
|
+
offset -> 0
|
87
|
+
depth -> 0
|
88
|
+
|
89
|
+
=end
|
90
|
+
|
91
|
+
module VM
|
92
|
+
# Expression of VM is a set of Nodes
|
93
|
+
module Node
|
94
|
+
class BaseNode
|
95
|
+
include Inspect
|
96
|
+
include AbsArch
|
97
|
+
|
98
|
+
def initialize(parent)
|
99
|
+
cs = CodeSpace.new
|
100
|
+
asm = Assembler.new(cs)
|
101
|
+
asm.with_retry do
|
102
|
+
asm.mov(TMPR, 4)
|
103
|
+
asm.ret
|
104
|
+
end
|
105
|
+
|
106
|
+
# iv for structure of VM
|
107
|
+
@parent = parent
|
108
|
+
@code_space = nil
|
109
|
+
@id = nil
|
110
|
+
if @parent then
|
111
|
+
@id = @parent.id.dup
|
112
|
+
@id[-1] = @id[-1] + 1
|
113
|
+
else
|
114
|
+
@id = [0]
|
115
|
+
end
|
116
|
+
|
117
|
+
# iv for type inference
|
118
|
+
@type = nil
|
119
|
+
@type_list = TypeUtil::TypeContainer.new
|
120
|
+
@element_node_list = []
|
121
|
+
@type_inference_proc = cs
|
122
|
+
@type_cache = nil
|
123
|
+
|
124
|
+
@ti_observer = {}
|
125
|
+
end
|
126
|
+
|
127
|
+
attr_accessor :parent
|
128
|
+
attr :code_space
|
129
|
+
attr :id
|
130
|
+
|
131
|
+
attr_accessor :type
|
132
|
+
attr_accessor :element_node_list
|
133
|
+
|
134
|
+
def add_type(key, type)
|
135
|
+
@type_list.add_type(key, type)
|
136
|
+
end
|
137
|
+
|
138
|
+
def type_list(key)
|
139
|
+
@type_list.type_list(key).value
|
140
|
+
end
|
141
|
+
|
142
|
+
def set_type_list(key, val)
|
143
|
+
@type_list.type_list(key).value = val
|
144
|
+
end
|
145
|
+
|
146
|
+
def collect_info(context)
|
147
|
+
if is_a?(HaveChildlenMixin) then
|
148
|
+
traverse_childlen {|rec|
|
149
|
+
context = rec.collect_info(context)
|
150
|
+
}
|
151
|
+
end
|
152
|
+
|
153
|
+
context
|
154
|
+
end
|
155
|
+
|
156
|
+
def ti_add_observer(dst, dkey, skey, context)
|
157
|
+
if @ti_observer[dst] == nil then
|
158
|
+
@ti_observer[dst] = []
|
159
|
+
end
|
160
|
+
|
161
|
+
if @ti_observer[dst].all? {|edkey, eskey, eprc|
|
162
|
+
(edkey != dkey) or (eskey != skey)
|
163
|
+
} then
|
164
|
+
prc = lambda { send(:ti_update, dst, self, dkey, skey, context) }
|
165
|
+
@ti_observer[dst].push [dkey, skey, prc]
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def ti_changed
|
170
|
+
@ti_observer.each do |rec, lst|
|
171
|
+
lst.each do |dkey, skey, prc|
|
172
|
+
prc.call
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def merge_type(dst, src)
|
178
|
+
res = dst
|
179
|
+
src.each do |sele|
|
180
|
+
if ! dst.include? sele then
|
181
|
+
res.push sele
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
res
|
186
|
+
end
|
187
|
+
|
188
|
+
def ti_update(dst, src, dkey, skey, context)
|
189
|
+
dtlist = dst.type_list(dkey)
|
190
|
+
stlist = src.type_list(skey)
|
191
|
+
=begin
|
192
|
+
print dkey.map(&:ruby_type), "\n"
|
193
|
+
print dtlist.map(&:ruby_type), "\n"
|
194
|
+
print stlist.map(&:ruby_type), "\n"
|
195
|
+
=end
|
196
|
+
orgsize = dtlist.size
|
197
|
+
# p "#{dst.class} #{src.class} #{dtlist} #{stlist}"
|
198
|
+
dst.set_type_list(dkey, merge_type(dtlist, stlist))
|
199
|
+
|
200
|
+
if orgsize != dtlist.size then
|
201
|
+
dst.type = nil
|
202
|
+
dst.ti_changed
|
203
|
+
context.convergent = false
|
204
|
+
end
|
205
|
+
|
206
|
+
dtlist = dst.element_node_list
|
207
|
+
stlist = src.element_node_list
|
208
|
+
orgsize = dtlist.size
|
209
|
+
dst.element_node_list = merge_type(dtlist, stlist)
|
210
|
+
if orgsize != dtlist.size then
|
211
|
+
dst.ti_changed
|
212
|
+
context.convergent = false
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def same_type(dst, src, dkey, skey, context)
|
217
|
+
=begin
|
218
|
+
print "#{src.class} -> #{dst.class} \n"
|
219
|
+
if dst.is_a?(LocalVarNode) then
|
220
|
+
print "#{dst.name} \n"
|
221
|
+
end
|
222
|
+
if dst.is_a?(LiteralNode) then
|
223
|
+
print "#{dst.value.inspect} \n"
|
224
|
+
end
|
225
|
+
=end
|
226
|
+
|
227
|
+
if dst.is_a?(BaseNode) then
|
228
|
+
src.ti_add_observer(dst, dkey, skey, context)
|
229
|
+
end
|
230
|
+
|
231
|
+
ti_update(dst, src, dkey, skey, context)
|
232
|
+
end
|
233
|
+
|
234
|
+
def add_element_node(key, type, context)
|
235
|
+
slfetnode = @element_node_list
|
236
|
+
unless slfetnode.include?(type)
|
237
|
+
@element_node_list.push [key, type]
|
238
|
+
orgkey = @element_node_list[0][0]
|
239
|
+
orgtype = @element_node_list[0][1]
|
240
|
+
if orgtype != type then
|
241
|
+
same_type(orgtype, type, orgkey, key, context)
|
242
|
+
end
|
243
|
+
ti_changed
|
244
|
+
# context.convergent = false
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
def collect_candidate_type(context)
|
249
|
+
raise "You must define collect_candidate_type per node"
|
250
|
+
context
|
251
|
+
end
|
252
|
+
|
253
|
+
def decide_type_core(tlist)
|
254
|
+
tlist = tlist.select {|e| e.class != RubyType::DefaultType0 }
|
255
|
+
case tlist.size
|
256
|
+
when 0
|
257
|
+
RubyType::DefaultType0.new
|
258
|
+
|
259
|
+
when 1
|
260
|
+
if tlist[0].have_element? then
|
261
|
+
key = @element_node_list[0][0]
|
262
|
+
node = @element_node_list[0][1]
|
263
|
+
node.decide_type_once(key)
|
264
|
+
tlist[0].element_type = node.type
|
265
|
+
end
|
266
|
+
tlist[0]
|
267
|
+
|
268
|
+
else
|
269
|
+
RubyType::DefaultType0.new
|
270
|
+
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
def decide_type_once(key)
|
275
|
+
if @type.equal?(nil) # or @type.is_a?(RubyType::DefaultType0) then
|
276
|
+
tlist = @type_list.type_list(key).value
|
277
|
+
@type = decide_type_core(tlist)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
def decide_type(key)
|
282
|
+
decide_type_once(key)
|
283
|
+
|
284
|
+
if is_a?(HaveChildlenMixin) then
|
285
|
+
traverse_childlen {|rec|
|
286
|
+
rec.decide_type(key)
|
287
|
+
}
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
def inference_type
|
292
|
+
cs = @type_inference_proc
|
293
|
+
cs.call(cs.var_base_address)
|
294
|
+
end
|
295
|
+
|
296
|
+
def gen_type_inference_proc(code)
|
297
|
+
end
|
298
|
+
|
299
|
+
def compile(context)
|
300
|
+
@code_space = context.code_space
|
301
|
+
context
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
module HaveChildlenMixin
|
306
|
+
def initialize(*args)
|
307
|
+
super
|
308
|
+
@body = DummyNode.new
|
309
|
+
end
|
310
|
+
|
311
|
+
attr_accessor :body
|
312
|
+
|
313
|
+
def traverse_childlen
|
314
|
+
raise "You must define traverse_childlen #{self.class}"
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
module NodeUtil
|
319
|
+
def search_class_top
|
320
|
+
cnode = @parent
|
321
|
+
|
322
|
+
# ClassTopNode include TopTopNode
|
323
|
+
while !cnode.is_a?(ClassTopNode)
|
324
|
+
cnode = cnode.parent
|
325
|
+
end
|
326
|
+
|
327
|
+
cnode
|
328
|
+
end
|
329
|
+
|
330
|
+
def search_top
|
331
|
+
cnode = @parent
|
332
|
+
|
333
|
+
# ClassTopNode include TopTopNode
|
334
|
+
while !cnode.is_a?(TopNode)
|
335
|
+
cnode = cnode.parent
|
336
|
+
end
|
337
|
+
|
338
|
+
cnode
|
339
|
+
end
|
340
|
+
|
341
|
+
def search_end
|
342
|
+
cnode = @parent
|
343
|
+
|
344
|
+
# ClassTopNode include TopTopNode
|
345
|
+
while !cnode.is_a?(MethodEndNode)
|
346
|
+
cnode = cnode.body
|
347
|
+
end
|
348
|
+
|
349
|
+
cnode
|
350
|
+
end
|
351
|
+
|
352
|
+
def search_frame_info
|
353
|
+
cnode = @parent
|
354
|
+
|
355
|
+
# ClassTopNode include TopTopNode
|
356
|
+
while !cnode.is_a?(LocalFrameInfoNode)
|
357
|
+
cnode = cnode.parent
|
358
|
+
end
|
359
|
+
|
360
|
+
cnode
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
module SendUtil
|
365
|
+
def gen_eval_self(context)
|
366
|
+
# eval 1st arg(self)
|
367
|
+
slfnode = @arguments[2]
|
368
|
+
context = slfnode.compile(context)
|
369
|
+
|
370
|
+
rtype = context.ret_node.type
|
371
|
+
rtype.gen_unboxing(context)
|
372
|
+
end
|
373
|
+
|
374
|
+
def signature(context)
|
375
|
+
res = []
|
376
|
+
@arguments.each do |ele|
|
377
|
+
ele.decide_type_once(context.to_key)
|
378
|
+
res.push ele.type
|
379
|
+
end
|
380
|
+
|
381
|
+
res
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
class DummyNode
|
386
|
+
def collect_candidate_type(context)
|
387
|
+
context
|
388
|
+
end
|
389
|
+
|
390
|
+
def compile(context)
|
391
|
+
# Not need super because this is dummy
|
392
|
+
context
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
# The top of top node
|
397
|
+
class TopNode<BaseNode
|
398
|
+
include HaveChildlenMixin
|
399
|
+
include NodeUtil
|
400
|
+
def initialize(parent, name = nil)
|
401
|
+
super(parent)
|
402
|
+
@name = name
|
403
|
+
@code_spaces = [] # [[nil, CodeSpace.new]]
|
404
|
+
@yield_node = nil
|
405
|
+
if @parent then
|
406
|
+
@classtop = search_class_top
|
407
|
+
else
|
408
|
+
@classtop = self
|
409
|
+
end
|
410
|
+
@end_nodes = []
|
411
|
+
end
|
412
|
+
|
413
|
+
attr_accessor :name
|
414
|
+
attr :end_nodes
|
415
|
+
attr :yield_node
|
416
|
+
|
417
|
+
def modified_instance_var
|
418
|
+
search_end.modified_instance_var
|
419
|
+
end
|
420
|
+
|
421
|
+
def traverse_childlen
|
422
|
+
yield @body
|
423
|
+
end
|
424
|
+
|
425
|
+
def find_cs_by_signature(sig)
|
426
|
+
@code_spaces.each do |key, val|
|
427
|
+
if key == sig then
|
428
|
+
return val
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
nil
|
433
|
+
end
|
434
|
+
|
435
|
+
def add_cs_for_signature(sig)
|
436
|
+
cs = find_cs_by_signature(sig)
|
437
|
+
if cs then
|
438
|
+
return nil
|
439
|
+
|
440
|
+
else
|
441
|
+
cs = CodeSpace.new
|
442
|
+
@code_spaces.push [sig, cs]
|
443
|
+
return cs
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
def construct_frame_info(locals, argnum)
|
448
|
+
finfo = LocalFrameInfoNode.new(self)
|
449
|
+
|
450
|
+
# 3 means BP, BP and SP
|
451
|
+
lsize = locals.size + 3
|
452
|
+
|
453
|
+
# construct frame
|
454
|
+
frame_layout = Array.new(lsize)
|
455
|
+
i = 0
|
456
|
+
fargstart = lsize - argnum
|
457
|
+
argnum.times do
|
458
|
+
lnode = LocalVarNode.new(finfo, locals[i], fargstart + i)
|
459
|
+
frame_layout[fargstart + i] = lnode
|
460
|
+
i += 1
|
461
|
+
end
|
462
|
+
|
463
|
+
frame_layout[fargstart - 1] = SystemValueNode.new(finfo,
|
464
|
+
:RET_ADDR,
|
465
|
+
fargstart - 1)
|
466
|
+
frame_layout[fargstart - 2] = SystemValueNode.new(finfo,
|
467
|
+
:OLD_BP,
|
468
|
+
fargstart - 2)
|
469
|
+
frame_layout[fargstart - 3] = SystemValueNode.new(finfo,
|
470
|
+
:OLD_BPSTACK,
|
471
|
+
fargstart - 3)
|
472
|
+
|
473
|
+
j = 0
|
474
|
+
while i < lsize - 3 do
|
475
|
+
lnode = LocalVarNode.new(finfo, locals[i], j)
|
476
|
+
frame_layout[j] = lnode
|
477
|
+
i += 1
|
478
|
+
j += 1
|
479
|
+
end
|
480
|
+
finfo.frame_layout = frame_layout
|
481
|
+
finfo.argument_num = argnum
|
482
|
+
finfo.system_num = 3 # BP ON Stack, BP, RET
|
483
|
+
|
484
|
+
@body = finfo
|
485
|
+
finfo
|
486
|
+
end
|
487
|
+
|
488
|
+
def collect_info(context)
|
489
|
+
context.modified_local_var.push Hash.new
|
490
|
+
context.modified_instance_var = {}
|
491
|
+
context.yield_node.push []
|
492
|
+
@body.collect_info(context)
|
493
|
+
@yield_node = context.yield_node.pop
|
494
|
+
context
|
495
|
+
end
|
496
|
+
|
497
|
+
def collect_candidate_type(context, signode, sig)
|
498
|
+
if add_cs_for_signature(sig) == nil then
|
499
|
+
# return context
|
500
|
+
end
|
501
|
+
context.current_method_signature_node.push signode
|
502
|
+
context = @body.collect_candidate_type(context)
|
503
|
+
@end_nodes.each do |enode|
|
504
|
+
same_type(self, enode, context.to_key, context.to_key, context)
|
505
|
+
same_type(enode, self, context.to_key, context.to_key, context)
|
506
|
+
end
|
507
|
+
context.current_method_signature_node.pop
|
508
|
+
context
|
509
|
+
end
|
510
|
+
|
511
|
+
def disp_signature
|
512
|
+
tcontext = CompileContext.new(self)
|
513
|
+
print "#{@classtop.klass_object}##{@name} "
|
514
|
+
@code_spaces.each do |sig, cs|
|
515
|
+
print sig, " -> "
|
516
|
+
tl = @type_list.type_list(sig).value
|
517
|
+
print decide_type_core(tl).inspect, "\n"
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
def compile(context)
|
522
|
+
oldcs = context.code_space
|
523
|
+
@code_spaces.each do |sig, cs|
|
524
|
+
context.current_method_signature.push sig
|
525
|
+
context.set_code_space(cs)
|
526
|
+
context = super(context)
|
527
|
+
context.reset_using_reg
|
528
|
+
context = gen_method_prologue(context)
|
529
|
+
context = @body.compile(context)
|
530
|
+
context.current_method_signature.pop
|
531
|
+
end
|
532
|
+
|
533
|
+
if oldcs then
|
534
|
+
context.set_code_space(oldcs)
|
535
|
+
end
|
536
|
+
disp_signature
|
537
|
+
context
|
538
|
+
end
|
539
|
+
end
|
540
|
+
|
541
|
+
# Top of method definition
|
542
|
+
class MethodTopNode<TopNode
|
543
|
+
include MethodTopCodeGen
|
544
|
+
|
545
|
+
def construct_frame_info(locals, argnum)
|
546
|
+
locals.unshift :_self
|
547
|
+
locals.unshift :_block
|
548
|
+
locals.unshift :_prev_env
|
549
|
+
argnum += 3
|
550
|
+
super(locals, argnum)
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
class BlockTopNode<MethodTopNode
|
555
|
+
include MethodTopCodeGen
|
556
|
+
end
|
557
|
+
|
558
|
+
class ClassTopNode<TopNode
|
559
|
+
include MethodTopCodeGen
|
560
|
+
@@class_top_tab = {}
|
561
|
+
|
562
|
+
def initialize(parent, klassobj, name = nil)
|
563
|
+
super(parent, name)
|
564
|
+
@nested_class_tab = {}
|
565
|
+
@method_tab = {}
|
566
|
+
@klass_object = klassobj
|
567
|
+
unless @@class_top_tab[klassobj]
|
568
|
+
@@class_top_tab[klassobj] = self
|
569
|
+
end
|
570
|
+
end
|
571
|
+
|
572
|
+
def method_tab(klassobj = nil)
|
573
|
+
if klassobj then
|
574
|
+
ktop = @@class_top_tab[klassobj]
|
575
|
+
if ktop then
|
576
|
+
ktop.method_tab
|
577
|
+
else
|
578
|
+
{}
|
579
|
+
end
|
580
|
+
else
|
581
|
+
@method_tab
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
585
|
+
attr :nested_class_tab
|
586
|
+
attr :klass_object
|
587
|
+
|
588
|
+
def construct_frame_info(locals, argnum)
|
589
|
+
locals.unshift :_self
|
590
|
+
locals.unshift :_block
|
591
|
+
locals.unshift :_prev_env
|
592
|
+
argnum += 3
|
593
|
+
super(locals, argnum)
|
594
|
+
end
|
595
|
+
end
|
596
|
+
|
597
|
+
class TopTopNode<ClassTopNode
|
598
|
+
include MethodTopCodeGen
|
599
|
+
|
600
|
+
def initialize(parent, klassobj, name = :top)
|
601
|
+
super
|
602
|
+
|
603
|
+
@code_space_tab = []
|
604
|
+
@asm_tab = {}
|
605
|
+
@id.push 0
|
606
|
+
end
|
607
|
+
|
608
|
+
def add_code_space(oldcs, newcs)
|
609
|
+
if !@code_space_tab.include?(newcs) then
|
610
|
+
@code_space_tab.push newcs
|
611
|
+
end
|
612
|
+
end
|
613
|
+
|
614
|
+
def collect_candidate_type(context, signode, sig)
|
615
|
+
context.convergent = true
|
616
|
+
super
|
617
|
+
end
|
618
|
+
|
619
|
+
attr :code_space_tab
|
620
|
+
attr :asm_tab
|
621
|
+
end
|
622
|
+
|
623
|
+
class LocalFrameInfoNode<BaseNode
|
624
|
+
include HaveChildlenMixin
|
625
|
+
|
626
|
+
def initialize(parent)
|
627
|
+
super(parent)
|
628
|
+
@frame_layout = []
|
629
|
+
@argument_num = nil
|
630
|
+
@system_num = nil
|
631
|
+
@previous_frame = search_previous_frame(parent)
|
632
|
+
@offset_cache = {}
|
633
|
+
end
|
634
|
+
|
635
|
+
def search_previous_frame(mtop)
|
636
|
+
cnode = mtop.parent
|
637
|
+
while !cnode.is_a?(TopNode)
|
638
|
+
if cnode then
|
639
|
+
cnode = cnode.parent
|
640
|
+
else
|
641
|
+
return nil
|
642
|
+
end
|
643
|
+
end
|
644
|
+
|
645
|
+
return cnode.body
|
646
|
+
end
|
647
|
+
|
648
|
+
def copy_frame_layout
|
649
|
+
@frame_layout.each { |ele| ele.dup }
|
650
|
+
end
|
651
|
+
|
652
|
+
attr_accessor :frame_layout
|
653
|
+
attr_accessor :argument_num
|
654
|
+
attr_accessor :system_num
|
655
|
+
attr :previous_frame
|
656
|
+
|
657
|
+
def traverse_childlen
|
658
|
+
@frame_layout.each do |vinf|
|
659
|
+
yield vinf
|
660
|
+
end
|
661
|
+
yield @body
|
662
|
+
end
|
663
|
+
|
664
|
+
def frame_size
|
665
|
+
@frame_layout.inject(0) {|sum, slot| sum += slot.size}
|
666
|
+
end
|
667
|
+
|
668
|
+
def local_area_size
|
669
|
+
localnum = @frame_layout.size - @argument_num - @system_num
|
670
|
+
@frame_layout[0, localnum].inject(0) {|sum, slot| sum += slot.size}
|
671
|
+
end
|
672
|
+
|
673
|
+
def real_offset(off)
|
674
|
+
if off >= @argument_num then
|
675
|
+
off = off - @argument_num
|
676
|
+
else
|
677
|
+
off = off + (@frame_layout.size - @argument_num)
|
678
|
+
end
|
679
|
+
|
680
|
+
off
|
681
|
+
end
|
682
|
+
|
683
|
+
def offset_by_byte(off)
|
684
|
+
off = real_offset(off)
|
685
|
+
|
686
|
+
obyte = 0
|
687
|
+
off.times do |i|
|
688
|
+
obyte += @frame_layout[i].size
|
689
|
+
end
|
690
|
+
|
691
|
+
obyte - local_area_size
|
692
|
+
end
|
693
|
+
|
694
|
+
def offset_arg(n, basereg)
|
695
|
+
rc = @offset_cache[n]
|
696
|
+
unless rc
|
697
|
+
off = offset_by_byte(n)
|
698
|
+
rc = @offset_cache[n] = OpIndirect.new(basereg, off)
|
699
|
+
end
|
700
|
+
|
701
|
+
rc
|
702
|
+
end
|
703
|
+
|
704
|
+
def collect_candidate_type(context)
|
705
|
+
traverse_childlen {|rec|
|
706
|
+
context = rec.collect_candidate_type(context)
|
707
|
+
}
|
708
|
+
@body.collect_candidate_type(context)
|
709
|
+
end
|
710
|
+
|
711
|
+
def compile(context)
|
712
|
+
context = super(context)
|
713
|
+
siz = local_area_size
|
714
|
+
if siz != 0 then
|
715
|
+
asm = context.assembler
|
716
|
+
asm.with_retry do
|
717
|
+
asm.sub(SPR, siz)
|
718
|
+
end
|
719
|
+
cpustack_pushn(siz)
|
720
|
+
end
|
721
|
+
context = @body.compile(context)
|
722
|
+
context
|
723
|
+
end
|
724
|
+
end
|
725
|
+
|
726
|
+
class LocalVarNode<BaseNode
|
727
|
+
def initialize(parent, name, offset)
|
728
|
+
super(parent)
|
729
|
+
@name = name
|
730
|
+
@offset = offset
|
731
|
+
end
|
732
|
+
|
733
|
+
attr :name
|
734
|
+
|
735
|
+
def size
|
736
|
+
8
|
737
|
+
end
|
738
|
+
|
739
|
+
def collect_candidate_type(context)
|
740
|
+
flay = @parent.frame_layout
|
741
|
+
fragstart = flay.size - @parent.argument_num
|
742
|
+
if fragstart <= @offset then
|
743
|
+
argoff = @offset - fragstart
|
744
|
+
tobj = context.current_method_signature_node.last[argoff]
|
745
|
+
if tobj then
|
746
|
+
same_type(self, tobj,
|
747
|
+
context.to_key, context.to_key(-2), context)
|
748
|
+
same_type(tobj, self,
|
749
|
+
context.to_key(-2), context.to_key, context)
|
750
|
+
end
|
751
|
+
end
|
752
|
+
context
|
753
|
+
end
|
754
|
+
|
755
|
+
def compile(context)
|
756
|
+
context = super(context)
|
757
|
+
context
|
758
|
+
end
|
759
|
+
end
|
760
|
+
|
761
|
+
class SystemValueNode<BaseNode
|
762
|
+
def initialize(parent, kind, offset)
|
763
|
+
super(parent)
|
764
|
+
@kind = kind
|
765
|
+
@offset = offset
|
766
|
+
end
|
767
|
+
|
768
|
+
attr :offset
|
769
|
+
|
770
|
+
def collect_candidate_type(context)
|
771
|
+
context
|
772
|
+
end
|
773
|
+
|
774
|
+
def size
|
775
|
+
AsmType::MACHINE_WORD.size
|
776
|
+
end
|
777
|
+
|
778
|
+
def compile(context)
|
779
|
+
context = super(context)
|
780
|
+
context
|
781
|
+
end
|
782
|
+
end
|
783
|
+
|
784
|
+
# Guard (type information holder and type checking of tree)
|
785
|
+
class GuardNode<BaseNode
|
786
|
+
include HaveChildlenMixin
|
787
|
+
end
|
788
|
+
|
789
|
+
# End of method definition
|
790
|
+
class MethodEndNode<BaseNode
|
791
|
+
include MethodEndCodeGen
|
792
|
+
|
793
|
+
def initialize(parent)
|
794
|
+
super(parent)
|
795
|
+
@modified_instance_var = nil
|
796
|
+
end
|
797
|
+
|
798
|
+
attr :modified_instance_var
|
799
|
+
|
800
|
+
def collect_info(context)
|
801
|
+
context.modified_local_var.pop
|
802
|
+
@modified_instance_var = context.modified_instance_var
|
803
|
+
context
|
804
|
+
end
|
805
|
+
|
806
|
+
def collect_candidate_type(context)
|
807
|
+
same_type(self, @parent, context.to_key, context.to_key, context)
|
808
|
+
same_type(@parent, self, context.to_key, context.to_key, context)
|
809
|
+
context
|
810
|
+
end
|
811
|
+
|
812
|
+
def compile(context)
|
813
|
+
context = super(context)
|
814
|
+
context = gen_method_epilogue(context)
|
815
|
+
curas = context.assembler
|
816
|
+
curas.with_retry do
|
817
|
+
curas.ret
|
818
|
+
end
|
819
|
+
context
|
820
|
+
end
|
821
|
+
end
|
822
|
+
|
823
|
+
class BlockEndNode<MethodEndNode
|
824
|
+
include MethodEndCodeGen
|
825
|
+
end
|
826
|
+
|
827
|
+
class ClassEndNode<MethodEndNode
|
828
|
+
include MethodEndCodeGen
|
829
|
+
end
|
830
|
+
|
831
|
+
# Set result of method/block
|
832
|
+
class SetResultNode<BaseNode
|
833
|
+
include HaveChildlenMixin
|
834
|
+
|
835
|
+
def initialize(parent, valnode)
|
836
|
+
super(parent)
|
837
|
+
@value_node = valnode
|
838
|
+
end
|
839
|
+
|
840
|
+
def traverse_childlen
|
841
|
+
yield @value_node
|
842
|
+
yield @body
|
843
|
+
end
|
844
|
+
|
845
|
+
def collect_candidate_type(context)
|
846
|
+
context = @value_node.collect_candidate_type(context)
|
847
|
+
same_type(self, @value_node,
|
848
|
+
context.to_key, context.to_key, context)
|
849
|
+
same_type(@value_node, self,
|
850
|
+
context.to_key, context.to_key, context)
|
851
|
+
context = @body.collect_candidate_type(context)
|
852
|
+
context
|
853
|
+
end
|
854
|
+
|
855
|
+
def compile(context)
|
856
|
+
context = super(context)
|
857
|
+
context = @value_node.compile(context)
|
858
|
+
if context.ret_reg != RETR then
|
859
|
+
if context.ret_reg.is_a?(OpRegXMM) then
|
860
|
+
context = @type.gen_boxing(context)
|
861
|
+
if context.ret_reg != RETR then
|
862
|
+
curas = context.assembler
|
863
|
+
curas.with_retry do
|
864
|
+
curas.mov(RETR, context.ret_reg)
|
865
|
+
end
|
866
|
+
|
867
|
+
context.set_reg_content(RETR, context.ret_node)
|
868
|
+
end
|
869
|
+
else
|
870
|
+
curas = context.assembler
|
871
|
+
curas.with_retry do
|
872
|
+
curas.mov(RETR, context.ret_reg)
|
873
|
+
end
|
874
|
+
end
|
875
|
+
context.set_reg_content(TMPR, context.ret_node)
|
876
|
+
end
|
877
|
+
|
878
|
+
context.ret_reg = RETR
|
879
|
+
context = @body.compile(context)
|
880
|
+
|
881
|
+
context
|
882
|
+
end
|
883
|
+
end
|
884
|
+
|
885
|
+
class PhiNode<BaseNode
|
886
|
+
def initialize(parent)
|
887
|
+
super(parent)
|
888
|
+
@local_label = parent
|
889
|
+
end
|
890
|
+
|
891
|
+
def collect_candidate_type(context)
|
892
|
+
@local_label.come_from.values.each do |vnode|
|
893
|
+
same_type(self, vnode,
|
894
|
+
context.to_key, context.to_key, context)
|
895
|
+
same_type(vnode, self,
|
896
|
+
context.to_key, context.to_key, context)
|
897
|
+
end
|
898
|
+
context
|
899
|
+
end
|
900
|
+
|
901
|
+
def compile(context)
|
902
|
+
context = super(context)
|
903
|
+
context.set_reg_content(TMPR, self)
|
904
|
+
context.ret_node = self
|
905
|
+
context.ret_reg = RETR
|
906
|
+
context
|
907
|
+
end
|
908
|
+
end
|
909
|
+
|
910
|
+
class LocalLabel<BaseNode
|
911
|
+
include HaveChildlenMixin
|
912
|
+
def initialize(parent, name)
|
913
|
+
super(parent)
|
914
|
+
@name = name
|
915
|
+
@come_from = {}
|
916
|
+
@come_from_val = []
|
917
|
+
@code_space = CodeSpace.new
|
918
|
+
@value_node = PhiNode.new(self)
|
919
|
+
@modified_local_var_list = []
|
920
|
+
@modified_instance_var_list = []
|
921
|
+
end
|
922
|
+
|
923
|
+
attr :name
|
924
|
+
attr :come_from
|
925
|
+
attr :value_node
|
926
|
+
|
927
|
+
def traverse_childlen
|
928
|
+
yield @body
|
929
|
+
yield @value_node
|
930
|
+
end
|
931
|
+
|
932
|
+
def collect_info(context)
|
933
|
+
modlocvar = context.modified_local_var.map {|ele| ele.dup}
|
934
|
+
@modified_local_var_list.push modlocvar
|
935
|
+
modinsvar = context.modified_instance_var.dup
|
936
|
+
@modified_instance_var_list.push modinsvar
|
937
|
+
if @modified_instance_var_list.size == @come_from.size then
|
938
|
+
context.merge_local_var(@modified_local_var_list)
|
939
|
+
context.merge_instance_var(@modified_instance_var_list)
|
940
|
+
@body.collect_info(context)
|
941
|
+
else
|
942
|
+
context
|
943
|
+
end
|
944
|
+
end
|
945
|
+
|
946
|
+
def compile_block_value(context, comefrom)
|
947
|
+
valnode = @come_from[comefrom]
|
948
|
+
if valnode then
|
949
|
+
context = valnode.compile(context)
|
950
|
+
asm = context.assembler
|
951
|
+
if !context.ret_reg.is_a?(OpRegXMM) then
|
952
|
+
if RETR != context.ret_reg then
|
953
|
+
asm.with_retry do
|
954
|
+
asm.mov(RETR, context.ret_reg)
|
955
|
+
end
|
956
|
+
context.set_reg_content(RETR, context.ret_node)
|
957
|
+
context.ret_reg = RETR
|
958
|
+
end
|
959
|
+
end
|
960
|
+
end
|
961
|
+
|
962
|
+
context
|
963
|
+
end
|
964
|
+
|
965
|
+
def traverse_block_value(comefrom, &block)
|
966
|
+
valnode = @come_from[comefrom]
|
967
|
+
if valnode then
|
968
|
+
yield valnode
|
969
|
+
else
|
970
|
+
nil
|
971
|
+
end
|
972
|
+
end
|
973
|
+
|
974
|
+
def collect_candidate_type(context, sender = nil)
|
975
|
+
if @come_from.keys[0] == sender then
|
976
|
+
context = @body.collect_candidate_type(context)
|
977
|
+
end
|
978
|
+
|
979
|
+
context
|
980
|
+
end
|
981
|
+
|
982
|
+
def compile(context)
|
983
|
+
context = super(context)
|
984
|
+
@come_from_val.push context.ret_reg
|
985
|
+
|
986
|
+
# When all node finish to compile, next node compile
|
987
|
+
if @come_from_val.size == @come_from.size then
|
988
|
+
@body.compile(context)
|
989
|
+
else
|
990
|
+
context
|
991
|
+
end
|
992
|
+
|
993
|
+
context
|
994
|
+
end
|
995
|
+
end
|
996
|
+
|
997
|
+
class BranchCommonNode<BaseNode
|
998
|
+
include HaveChildlenMixin
|
999
|
+
include IfNodeCodeGen
|
1000
|
+
|
1001
|
+
def initialize(parent, cond, jmpto)
|
1002
|
+
super(parent)
|
1003
|
+
@cond = cond
|
1004
|
+
@jmp_to_node = jmpto
|
1005
|
+
end
|
1006
|
+
|
1007
|
+
def traverse_childlen(&block)
|
1008
|
+
@jmp_to_node.traverse_block_value(self, &block)
|
1009
|
+
yield @cond
|
1010
|
+
yield @jmp_to_node
|
1011
|
+
yield @body
|
1012
|
+
end
|
1013
|
+
|
1014
|
+
def branch(as, address)
|
1015
|
+
# as.jn(address)
|
1016
|
+
# as.je(address)
|
1017
|
+
raise "Don't use this node direct"
|
1018
|
+
end
|
1019
|
+
|
1020
|
+
def collect_candidate_type(context)
|
1021
|
+
context = @cond.collect_candidate_type(context)
|
1022
|
+
context = @jmp_to_node.collect_candidate_type(context, self)
|
1023
|
+
@body.collect_candidate_type(context)
|
1024
|
+
end
|
1025
|
+
|
1026
|
+
def compile(context)
|
1027
|
+
context = super(context)
|
1028
|
+
context = @jmp_to_node.compile_block_value(context, self)
|
1029
|
+
|
1030
|
+
jmptocs = @jmp_to_node.code_space
|
1031
|
+
context = @cond.compile(context)
|
1032
|
+
curas = context.assembler
|
1033
|
+
curas.with_retry do
|
1034
|
+
if context.ret_reg != TMPR then
|
1035
|
+
curas.mov(TMPR, context.ret_reg)
|
1036
|
+
end
|
1037
|
+
|
1038
|
+
# In 64bit mode. It will be sign extended to 64 bit
|
1039
|
+
curas.and(TMPR, OpImmidiate32.new(~4))
|
1040
|
+
end
|
1041
|
+
|
1042
|
+
curas.with_retry do
|
1043
|
+
branch(curas, jmptocs.var_base_address)
|
1044
|
+
end
|
1045
|
+
|
1046
|
+
context = @body.compile(context)
|
1047
|
+
oldcs = context.set_code_space(jmptocs)
|
1048
|
+
context = @jmp_to_node.compile(context)
|
1049
|
+
# context.set_code_space(oldcs)
|
1050
|
+
|
1051
|
+
context
|
1052
|
+
end
|
1053
|
+
end
|
1054
|
+
|
1055
|
+
class BranchIfNode<BranchCommonNode
|
1056
|
+
def branch(as, address)
|
1057
|
+
as.jnz(address)
|
1058
|
+
end
|
1059
|
+
end
|
1060
|
+
|
1061
|
+
class BranchUnlessNode<BranchCommonNode
|
1062
|
+
def branch(as, address)
|
1063
|
+
as.jz(address)
|
1064
|
+
end
|
1065
|
+
end
|
1066
|
+
|
1067
|
+
class JumpNode<BaseNode
|
1068
|
+
include HaveChildlenMixin
|
1069
|
+
|
1070
|
+
def initialize(parent, jmpto)
|
1071
|
+
super(parent)
|
1072
|
+
@jmp_to_node = jmpto
|
1073
|
+
end
|
1074
|
+
|
1075
|
+
def traverse_childlen(&block)
|
1076
|
+
@jmp_to_node.traverse_block_value(self, &block)
|
1077
|
+
yield @jmp_to_node
|
1078
|
+
end
|
1079
|
+
|
1080
|
+
def collect_candidate_type(context)
|
1081
|
+
block = lambda {|rec|
|
1082
|
+
rec.collect_candidate_type(context)
|
1083
|
+
}
|
1084
|
+
tcontext = @jmp_to_node.traverse_block_value(self, &block)
|
1085
|
+
if tcontext then
|
1086
|
+
context = tcontext
|
1087
|
+
end
|
1088
|
+
@jmp_to_node.collect_candidate_type(context, self)
|
1089
|
+
end
|
1090
|
+
|
1091
|
+
def compile(context)
|
1092
|
+
context = super(context)
|
1093
|
+
context = @jmp_to_node.compile_block_value(context, self)
|
1094
|
+
|
1095
|
+
jmptocs = @jmp_to_node.code_space
|
1096
|
+
curas = context.assembler
|
1097
|
+
curas.with_retry do
|
1098
|
+
curas.jmp(jmptocs.var_base_address)
|
1099
|
+
end
|
1100
|
+
|
1101
|
+
oldcs = context.set_code_space(jmptocs)
|
1102
|
+
context = @jmp_to_node.compile(context)
|
1103
|
+
context.set_code_space(oldcs)
|
1104
|
+
context
|
1105
|
+
end
|
1106
|
+
end
|
1107
|
+
|
1108
|
+
# Holder of Nodes Assign. These assignes execute parallel potencially.
|
1109
|
+
class LetNode<BaseNode
|
1110
|
+
include HaveChildlenMixin
|
1111
|
+
end
|
1112
|
+
|
1113
|
+
# Literal
|
1114
|
+
class LiteralNode<BaseNode
|
1115
|
+
def initialize(parent, val)
|
1116
|
+
super(parent)
|
1117
|
+
@value = val
|
1118
|
+
@type = RubyType::BaseType.from_object(val)
|
1119
|
+
end
|
1120
|
+
|
1121
|
+
attr :value
|
1122
|
+
|
1123
|
+
def collect_candidate_type(context)
|
1124
|
+
@type_list.add_type(context.to_key, @type)
|
1125
|
+
case @value
|
1126
|
+
when Array
|
1127
|
+
key = context.to_key
|
1128
|
+
@element_node_list = [[key, BaseNode.new(self)]]
|
1129
|
+
@value.each do |ele|
|
1130
|
+
etype = RubyType::BaseType.from_object(ele)
|
1131
|
+
@element_node_list[0][1].add_type(key, etype)
|
1132
|
+
end
|
1133
|
+
end
|
1134
|
+
context
|
1135
|
+
end
|
1136
|
+
|
1137
|
+
def compile(context)
|
1138
|
+
context = super(context)
|
1139
|
+
|
1140
|
+
decide_type_once(context.to_key)
|
1141
|
+
case @value
|
1142
|
+
when Fixnum
|
1143
|
+
val = @value
|
1144
|
+
if @type.boxed then
|
1145
|
+
val = val.boxing
|
1146
|
+
end
|
1147
|
+
context.ret_node = self
|
1148
|
+
context.ret_reg = OpImmidiateMachineWord.new(val)
|
1149
|
+
|
1150
|
+
when Float
|
1151
|
+
val = @value
|
1152
|
+
if @type.boxed then
|
1153
|
+
val = val.boxing
|
1154
|
+
context.ret_reg = OpImmidiateMachineWord.new(val)
|
1155
|
+
else
|
1156
|
+
offm4 = OpIndirect.new(SPR, -AsmType::DOUBLE.size)
|
1157
|
+
asm = context.assembler
|
1158
|
+
asm.with_retry do
|
1159
|
+
asm.mov64(offm4, val.unboxing)
|
1160
|
+
asm.movsd(XMM0, offm4)
|
1161
|
+
end
|
1162
|
+
context.ret_reg = XMM0
|
1163
|
+
end
|
1164
|
+
context.ret_node = self
|
1165
|
+
|
1166
|
+
else
|
1167
|
+
if @var_value == nil then
|
1168
|
+
add = lambda { @value.address }
|
1169
|
+
@var_value = OpVarImmidiateAddress.new(add)
|
1170
|
+
end
|
1171
|
+
|
1172
|
+
context.ret_node = self
|
1173
|
+
context.ret_reg = @var_value
|
1174
|
+
context = @type.gen_copy(context)
|
1175
|
+
end
|
1176
|
+
|
1177
|
+
context
|
1178
|
+
end
|
1179
|
+
end
|
1180
|
+
|
1181
|
+
class SpecialObjectNode<BaseNode
|
1182
|
+
def initialize(parent, kind)
|
1183
|
+
super(parent)
|
1184
|
+
@kind = kind
|
1185
|
+
end
|
1186
|
+
|
1187
|
+
attr :kind
|
1188
|
+
|
1189
|
+
def collect_candidate_type(context)
|
1190
|
+
context
|
1191
|
+
end
|
1192
|
+
|
1193
|
+
def compile(context)
|
1194
|
+
# raise "Can't compile"
|
1195
|
+
context = super(context)
|
1196
|
+
context
|
1197
|
+
end
|
1198
|
+
end
|
1199
|
+
|
1200
|
+
# yield(invokeblock)
|
1201
|
+
class YieldNode<BaseNode
|
1202
|
+
include NodeUtil
|
1203
|
+
include SendUtil
|
1204
|
+
|
1205
|
+
def initialize(parent)
|
1206
|
+
super(parent)
|
1207
|
+
@name = "block yield"
|
1208
|
+
@frame_info = search_frame_info
|
1209
|
+
end
|
1210
|
+
|
1211
|
+
attr :name
|
1212
|
+
attr :frame_info
|
1213
|
+
|
1214
|
+
def collect_info(context)
|
1215
|
+
context.yield_node.last.push @parent
|
1216
|
+
context
|
1217
|
+
end
|
1218
|
+
|
1219
|
+
def collect_candidate_type(context)
|
1220
|
+
context
|
1221
|
+
end
|
1222
|
+
|
1223
|
+
def calling_convention(context)
|
1224
|
+
:ytl
|
1225
|
+
end
|
1226
|
+
|
1227
|
+
def method_top_node(ctop, slf)
|
1228
|
+
nil
|
1229
|
+
end
|
1230
|
+
|
1231
|
+
def compile(context)
|
1232
|
+
context = super(context)
|
1233
|
+
asm = context.assembler
|
1234
|
+
slfarg = @frame_info.offset_arg(2, BPR)
|
1235
|
+
asm.with_retry do
|
1236
|
+
asm.mov(TMPR3, slfarg)
|
1237
|
+
end
|
1238
|
+
|
1239
|
+
context.ret_reg = @frame_info.offset_arg(1, BPR)
|
1240
|
+
context.ret_node = self
|
1241
|
+
context
|
1242
|
+
end
|
1243
|
+
end
|
1244
|
+
|
1245
|
+
# Method name
|
1246
|
+
class MethodSelectNode<BaseNode
|
1247
|
+
def initialize(parent, val)
|
1248
|
+
super(parent)
|
1249
|
+
@name = val
|
1250
|
+
@calling_convention = :unkown
|
1251
|
+
@reciever = nil
|
1252
|
+
@send_node = nil
|
1253
|
+
end
|
1254
|
+
|
1255
|
+
def set_reciever(sendnode)
|
1256
|
+
@send_node = sendnode
|
1257
|
+
if sendnode.is_fcall then
|
1258
|
+
@reciever = @parent.class_top
|
1259
|
+
else
|
1260
|
+
@reciever = sendnode.arguments[2]
|
1261
|
+
end
|
1262
|
+
end
|
1263
|
+
|
1264
|
+
attr :name
|
1265
|
+
attr :calling_convention
|
1266
|
+
attr_accessor :reciever
|
1267
|
+
|
1268
|
+
def collect_candidate_type(context)
|
1269
|
+
context
|
1270
|
+
end
|
1271
|
+
|
1272
|
+
def method_top_node(ctop, slf)
|
1273
|
+
if slf then
|
1274
|
+
ctop.method_tab(slf.ruby_type)[@name]
|
1275
|
+
else
|
1276
|
+
ctop.method_tab[@name]
|
1277
|
+
end
|
1278
|
+
end
|
1279
|
+
|
1280
|
+
def calling_convention(context)
|
1281
|
+
if @send_node.is_fcall or @send_node.is_vcall then
|
1282
|
+
mtop = @reciever.method_tab[@name]
|
1283
|
+
if mtop then
|
1284
|
+
@calling_convention = :ytl
|
1285
|
+
else
|
1286
|
+
# reciever = Object
|
1287
|
+
if @reciever.klass_object then
|
1288
|
+
addr = @reciever.klass_object.method_address_of(@name)
|
1289
|
+
if addr then
|
1290
|
+
if variable_argument?(@eciever.method(@name).parameters) then
|
1291
|
+
@calling_convention = :c_vararg
|
1292
|
+
else
|
1293
|
+
@calling_convention = :c_fixarg
|
1294
|
+
end
|
1295
|
+
else
|
1296
|
+
raise "Unkown method - #{@name}"
|
1297
|
+
@calling_convention = :c
|
1298
|
+
end
|
1299
|
+
else
|
1300
|
+
raise "foo"
|
1301
|
+
end
|
1302
|
+
end
|
1303
|
+
else
|
1304
|
+
context = @reciever.compile(context)
|
1305
|
+
context.ret_node.decide_type_once(context.to_key)
|
1306
|
+
rtype = context.ret_node.type
|
1307
|
+
rklass = rtype.ruby_type
|
1308
|
+
mth = rklass.instance_method(@name)
|
1309
|
+
if variable_argument?(mth.parameters) then
|
1310
|
+
@calling_convention = :c_vararg
|
1311
|
+
else
|
1312
|
+
@calling_convention = :c_fixarg
|
1313
|
+
end
|
1314
|
+
end
|
1315
|
+
|
1316
|
+
@calling_convention
|
1317
|
+
end
|
1318
|
+
|
1319
|
+
def compile(context)
|
1320
|
+
context = super(context)
|
1321
|
+
if @send_node.is_fcall or @send_node.is_vcall then
|
1322
|
+
asm = context.assembler
|
1323
|
+
asm.with_retry do
|
1324
|
+
asm.mov(TMPR3, 4)
|
1325
|
+
end
|
1326
|
+
mtop = @reciever.method_tab[@name]
|
1327
|
+
if mtop then
|
1328
|
+
sig = @parent.signature(context)
|
1329
|
+
cs = mtop.find_cs_by_signature(sig)
|
1330
|
+
context.ret_reg = cs.var_base_address
|
1331
|
+
else
|
1332
|
+
if @reciever.klass_object then
|
1333
|
+
addr = lambda {
|
1334
|
+
@reciever.klass_object.method_address_of(@name)
|
1335
|
+
}
|
1336
|
+
if addr.call then
|
1337
|
+
context.ret_reg = OpVarMemAddress.new(addr)
|
1338
|
+
context.code_space.refer_operands.push context.ret_reg
|
1339
|
+
context.ret_node = self
|
1340
|
+
else
|
1341
|
+
raise "Unkown method - #{@name}"
|
1342
|
+
context.ret_reg = OpImmidiateAddress.new(0)
|
1343
|
+
context.ret_node = self
|
1344
|
+
end
|
1345
|
+
else
|
1346
|
+
raise "foo"
|
1347
|
+
end
|
1348
|
+
end
|
1349
|
+
else
|
1350
|
+
context = @reciever.compile(context)
|
1351
|
+
context.ret_node.decide_type_once(context.to_key)
|
1352
|
+
rtype = context.ret_node.type
|
1353
|
+
context = rtype.gen_boxing(context)
|
1354
|
+
recval = context.ret_reg
|
1355
|
+
|
1356
|
+
if rtype.is_a?(RubyType::DefaultType0) then
|
1357
|
+
# Can't type inference. Dynamic method search
|
1358
|
+
mnval = @name.address
|
1359
|
+
objclass = OpMemAddress.new(address_of("rb_obj_class"))
|
1360
|
+
addr = address_of("ytl_method_address_of_raw")
|
1361
|
+
meaddrof = OpMemAddress.new(addr)
|
1362
|
+
|
1363
|
+
context.start_using_reg(TMPR2)
|
1364
|
+
context.start_using_reg(FUNC_ARG[0])
|
1365
|
+
context.start_using_reg(FUNC_ARG[1])
|
1366
|
+
|
1367
|
+
asm = context.assembler
|
1368
|
+
asm.with_retry do
|
1369
|
+
asm.push(recval)
|
1370
|
+
asm.mov(FUNC_ARG[0], recval)
|
1371
|
+
asm.call_with_arg(objclass, 1)
|
1372
|
+
asm.mov(FUNC_ARG[0], RETR)
|
1373
|
+
asm.mov(FUNC_ARG[1], mnval)
|
1374
|
+
asm.call_with_arg(meaddrof, 2)
|
1375
|
+
asm.mov(TMPR2, RETR)
|
1376
|
+
asm.pop(TMPR3)
|
1377
|
+
end
|
1378
|
+
|
1379
|
+
context.end_using_reg(FUNC_ARG[1])
|
1380
|
+
context.end_using_reg(FUNC_ARG[0])
|
1381
|
+
|
1382
|
+
context.ret_node = self
|
1383
|
+
context.set_reg_content(RETR, self)
|
1384
|
+
context.set_reg_content(TMPR2, self)
|
1385
|
+
context.set_reg_content(TMPR3, @reciever)
|
1386
|
+
context.ret_reg = TMPR2
|
1387
|
+
else
|
1388
|
+
asm = context.assembler
|
1389
|
+
asm.with_retry do
|
1390
|
+
asm.mov(TMPR3, recval)
|
1391
|
+
end
|
1392
|
+
|
1393
|
+
addr = lambda {
|
1394
|
+
rtype.ruby_type.method_address_of(@name)
|
1395
|
+
}
|
1396
|
+
if addr.call then
|
1397
|
+
context.ret_reg = OpVarMemAddress.new(addr)
|
1398
|
+
context.code_space.refer_operands.push context.ret_reg
|
1399
|
+
context.ret_node = self
|
1400
|
+
else
|
1401
|
+
raise "Unkown method - #{@name}"
|
1402
|
+
context.ret_reg = OpImmidiateAddress.new(0)
|
1403
|
+
context.ret_node = self
|
1404
|
+
end
|
1405
|
+
end
|
1406
|
+
end
|
1407
|
+
context
|
1408
|
+
end
|
1409
|
+
end
|
1410
|
+
|
1411
|
+
# Variable Common
|
1412
|
+
class VariableRefCommonNode<BaseNode
|
1413
|
+
end
|
1414
|
+
|
1415
|
+
# Local Variable
|
1416
|
+
class LocalVarRefCommonNode<VariableRefCommonNode
|
1417
|
+
include LocalVarNodeCodeGen
|
1418
|
+
include NodeUtil
|
1419
|
+
|
1420
|
+
def initialize(parent, offset, depth)
|
1421
|
+
super(parent)
|
1422
|
+
@offset = offset
|
1423
|
+
@depth = depth
|
1424
|
+
|
1425
|
+
tnode = search_frame_info
|
1426
|
+
@frame_info = tnode
|
1427
|
+
depth.times do |i|
|
1428
|
+
tnode = tnode.previous_frame
|
1429
|
+
end
|
1430
|
+
@current_frame_info = tnode
|
1431
|
+
end
|
1432
|
+
|
1433
|
+
attr :frame_info
|
1434
|
+
attr :current_frame_info
|
1435
|
+
end
|
1436
|
+
|
1437
|
+
class LocalVarRefNode<LocalVarRefCommonNode
|
1438
|
+
def initialize(parent, offset, depth)
|
1439
|
+
super
|
1440
|
+
@var_type_info = nil
|
1441
|
+
end
|
1442
|
+
|
1443
|
+
def collect_info(context)
|
1444
|
+
vti = context.modified_local_var[@depth][@offset]
|
1445
|
+
if vti then
|
1446
|
+
@var_type_info = vti.dup
|
1447
|
+
else
|
1448
|
+
roff = @current_frame_info.real_offset(@offset)
|
1449
|
+
@var_type_info = [@current_frame_info.frame_layout[roff]]
|
1450
|
+
end
|
1451
|
+
|
1452
|
+
context
|
1453
|
+
end
|
1454
|
+
|
1455
|
+
def collect_candidate_type(context)
|
1456
|
+
@var_type_info.each do |src|
|
1457
|
+
same_type(self, src,
|
1458
|
+
context.to_key, context.to_key, context)
|
1459
|
+
end
|
1460
|
+
context
|
1461
|
+
end
|
1462
|
+
|
1463
|
+
def compile(context)
|
1464
|
+
context = super(context)
|
1465
|
+
context = gen_pursue_parent_function(context, @depth)
|
1466
|
+
asm = context.assembler
|
1467
|
+
base = context.ret_reg
|
1468
|
+
offarg = @current_frame_info.offset_arg(@offset, base)
|
1469
|
+
context.ret_node = self
|
1470
|
+
context.ret_reg = offarg
|
1471
|
+
context
|
1472
|
+
end
|
1473
|
+
end
|
1474
|
+
|
1475
|
+
class SelfRefNode<LocalVarRefNode
|
1476
|
+
def initialize(parent)
|
1477
|
+
super(parent, 0, 2)
|
1478
|
+
@classtop = search_class_top
|
1479
|
+
end
|
1480
|
+
|
1481
|
+
def compile_main(context)
|
1482
|
+
context = gen_pursue_parent_function(context, @depth)
|
1483
|
+
base = context.ret_reg
|
1484
|
+
offarg = @current_frame_info.offset_arg(@offset, base)
|
1485
|
+
context.ret_node = self
|
1486
|
+
context.ret_reg = offarg
|
1487
|
+
end
|
1488
|
+
|
1489
|
+
def collect_candidate_type(context)
|
1490
|
+
@type = RubyType::BaseType.from_ruby_class(@classtop.klass_object)
|
1491
|
+
@type_list.add_type(context.to_key, @type)
|
1492
|
+
context
|
1493
|
+
end
|
1494
|
+
|
1495
|
+
def compile(context)
|
1496
|
+
context = super(context)
|
1497
|
+
comile_main(context)
|
1498
|
+
end
|
1499
|
+
end
|
1500
|
+
|
1501
|
+
class LocalAssignNode<LocalVarRefCommonNode
|
1502
|
+
include HaveChildlenMixin
|
1503
|
+
def initialize(parent, offset, depth, val)
|
1504
|
+
super(parent, offset, depth)
|
1505
|
+
val.parent = self
|
1506
|
+
@val = val
|
1507
|
+
end
|
1508
|
+
|
1509
|
+
def traverse_childlen
|
1510
|
+
yield @val
|
1511
|
+
yield @body
|
1512
|
+
end
|
1513
|
+
|
1514
|
+
def collect_info(context)
|
1515
|
+
context = @val.collect_info(context)
|
1516
|
+
context.modified_local_var[@depth][@offset] = [self]
|
1517
|
+
@body.collect_info(context)
|
1518
|
+
end
|
1519
|
+
|
1520
|
+
def collect_candidate_type(context)
|
1521
|
+
context = @val.collect_candidate_type(context)
|
1522
|
+
same_type(self, @val,
|
1523
|
+
context.to_key, context.to_key, context)
|
1524
|
+
@body.collect_candidate_type(context)
|
1525
|
+
end
|
1526
|
+
|
1527
|
+
def compile(context)
|
1528
|
+
context = super(context)
|
1529
|
+
context = @val.compile(context)
|
1530
|
+
#=begin
|
1531
|
+
decide_type_once(context.to_key)
|
1532
|
+
if @type.boxed then
|
1533
|
+
@val.decide_type_once(context.to_key)
|
1534
|
+
rtype = @val.type
|
1535
|
+
context = rtype.gen_boxing(context)
|
1536
|
+
end
|
1537
|
+
#=end
|
1538
|
+
valr = context.ret_reg
|
1539
|
+
context = gen_pursue_parent_function(context, @depth)
|
1540
|
+
base = context.ret_reg
|
1541
|
+
offarg = @current_frame_info.offset_arg(@offset, base)
|
1542
|
+
|
1543
|
+
asm = context.assembler
|
1544
|
+
if valr.is_a?(OpRegistor) or valr.is_a?(OpImmidiate) then
|
1545
|
+
asm.with_retry do
|
1546
|
+
asm.mov(offarg, valr)
|
1547
|
+
end
|
1548
|
+
|
1549
|
+
else
|
1550
|
+
asm.with_retry do
|
1551
|
+
asm.mov(TMPR, valr)
|
1552
|
+
asm.mov(offarg, TMPR)
|
1553
|
+
end
|
1554
|
+
end
|
1555
|
+
|
1556
|
+
context.ret_reg = nil
|
1557
|
+
context = @body.compile(context)
|
1558
|
+
context
|
1559
|
+
end
|
1560
|
+
end
|
1561
|
+
|
1562
|
+
# Instance Variable
|
1563
|
+
class InstanceVarRefCommonNode<VariableRefCommonNode
|
1564
|
+
include NodeUtil
|
1565
|
+
|
1566
|
+
def initialize(parent, name)
|
1567
|
+
super(parent)
|
1568
|
+
@name = name
|
1569
|
+
@class_top = search_class_top
|
1570
|
+
end
|
1571
|
+
end
|
1572
|
+
|
1573
|
+
class InstanceVarRefNode<InstanceVarRefCommonNode
|
1574
|
+
def initialize(parent, name)
|
1575
|
+
super
|
1576
|
+
@var_type_info = nil
|
1577
|
+
end
|
1578
|
+
|
1579
|
+
def collect_info(context)
|
1580
|
+
vti = context.modified_instance_var[@name]
|
1581
|
+
if vti then
|
1582
|
+
@var_type_info = vti.dup
|
1583
|
+
else
|
1584
|
+
@var_type_info = nil
|
1585
|
+
end
|
1586
|
+
|
1587
|
+
context
|
1588
|
+
end
|
1589
|
+
|
1590
|
+
def collect_candidate_type(context)
|
1591
|
+
@var_type_info.each do |src|
|
1592
|
+
same_type(self, src,
|
1593
|
+
context.to_key, context.to_key, context)
|
1594
|
+
end
|
1595
|
+
context
|
1596
|
+
end
|
1597
|
+
|
1598
|
+
def compile_main(context)
|
1599
|
+
context
|
1600
|
+
end
|
1601
|
+
|
1602
|
+
def compile(context)
|
1603
|
+
context = super(context)
|
1604
|
+
compile_main(context)
|
1605
|
+
end
|
1606
|
+
end
|
1607
|
+
|
1608
|
+
class InstanceVarAssignNode<InstanceVarRefCommonNode
|
1609
|
+
include HaveChildlenMixin
|
1610
|
+
def initialize(parent, name, val)
|
1611
|
+
super(parent, name)
|
1612
|
+
val.parent = self
|
1613
|
+
@val = val
|
1614
|
+
end
|
1615
|
+
|
1616
|
+
def traverse_childlen
|
1617
|
+
yield @val
|
1618
|
+
yield @body
|
1619
|
+
end
|
1620
|
+
|
1621
|
+
def collect_info(context)
|
1622
|
+
context = @val.collect_info(context)
|
1623
|
+
context.modified_instance_var[@name] = [self]
|
1624
|
+
@body.collect_info(context)
|
1625
|
+
end
|
1626
|
+
|
1627
|
+
def collect_candidate_type(context)
|
1628
|
+
context = @val.collect_candidate_type(context)
|
1629
|
+
same_type(self, @val,
|
1630
|
+
context.to_key, context.to_key, context)
|
1631
|
+
@body.collect_candidate_type(context)
|
1632
|
+
end
|
1633
|
+
|
1634
|
+
def compile_main(context)
|
1635
|
+
context
|
1636
|
+
end
|
1637
|
+
|
1638
|
+
def compile(context)
|
1639
|
+
context = super(context)
|
1640
|
+
compile_main(context)
|
1641
|
+
end
|
1642
|
+
end
|
1643
|
+
|
1644
|
+
# Reference Register
|
1645
|
+
class RefRegister
|
1646
|
+
end
|
1647
|
+
end
|
1648
|
+
end
|
1649
|
+
end
|