ytljit 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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,299 @@
1
+ module YTLJit
2
+ module TypeUtil
3
+ class KlassTree
4
+ def initialize(defkey = [], defval = [])
5
+ @node = KlassTreeNode.new(defkey, defval)
6
+ end
7
+
8
+ def add(key, value)
9
+ cnode = @node
10
+ snode = @node
11
+ ocnode = nil
12
+ while cnode
13
+ ocnode = cnode
14
+ if key == cnode.key then
15
+ return cnode
16
+ end
17
+
18
+ if key.zip(cnode.key).all? {|k, n| k.is_a?(n.class)} then
19
+ cnode = cnode.same_klass
20
+ if cnode == nil then
21
+ ocnode.same_klass = KlassTreeNode.new(key, value)
22
+ return ocnode.same_klass
23
+ else
24
+ snode = cnode
25
+ end
26
+ else
27
+ cnode = cnode.next_klass
28
+ if cnode == nil then
29
+ ocnode.next_klass = KlassTreeNode.new(key, value)
30
+ return ocnode.next_klass
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ def search(key)
37
+ cnode = @node
38
+
39
+ while cnode
40
+ if key == cnode.key then
41
+ return cnode
42
+ end
43
+
44
+ if key.zip(cnode.key).all? {|a, b|
45
+ if a then
46
+ atype = a.ruby_type
47
+
48
+ if b then
49
+ btype = b.ruby_type
50
+ btype.is_a?(atype.class)
51
+ else
52
+ nil
53
+ end
54
+ else
55
+ return !b
56
+ end
57
+ } then
58
+ cnode = cnode.same_klass
59
+ else
60
+ cnode = cnode.next_klass
61
+ end
62
+ end
63
+
64
+ nil
65
+ end
66
+ end
67
+
68
+ class KlassTreeNode
69
+ def initialize(key, value)
70
+ @same_klass = nil
71
+ @next_klass = nil
72
+
73
+ @key = key
74
+ @value = value
75
+ end
76
+
77
+ attr_accessor :same_klass
78
+ attr_accessor :next_klass
79
+ attr :key
80
+ attr_accessor :value
81
+ end
82
+
83
+ class TypeContainer
84
+ def initialize
85
+ @types_tree = KlassTree.new
86
+ end
87
+
88
+ def to_key(context, offset = -1)
89
+ context.current_method_signature[offset]
90
+ end
91
+
92
+ def search_types(key)
93
+ @types_tree.search(key)
94
+ end
95
+
96
+ def add_type(key, type)
97
+ tvs = @types_tree.search(key)
98
+ if tvs then
99
+ tvsv = tvs.value
100
+ if !tvsv.include? type then
101
+ tvsv.push type
102
+ end
103
+ else
104
+ # inherit types of most similar signature
105
+ ival = []
106
+ simnode = @types_tree.add(key, ival)
107
+ =begin
108
+ simnode.value.each do |ele|
109
+ ival.push ele
110
+ end
111
+ =end
112
+
113
+ if !ival.include? type then
114
+ ival.push type
115
+ end
116
+ end
117
+ end
118
+
119
+ def add_node(key)
120
+ # inherit types of most similar signature
121
+ ival = []
122
+ simnode = @types_tree.add(key, ival)
123
+ =begin
124
+ simnode.value.each do |ele|
125
+ ival.push ele
126
+ end
127
+ =end
128
+
129
+ simnode
130
+ end
131
+
132
+ def type_list(key)
133
+ res = search_types(key)
134
+ if res == nil then
135
+ res = add_node(key)
136
+ end
137
+
138
+ res
139
+ end
140
+ end
141
+ end
142
+
143
+ module RubyType
144
+ def self.define_wraped_class(klass, base = RubyTypeBoxed)
145
+ cn = nil
146
+
147
+ if klass then
148
+ cn = klass.name.to_sym
149
+ basett, boxtt, unboxtt = BaseType.type_tab
150
+ if boxtt[cn] == nil then
151
+ BaseType.related_ruby_class(klass, base)
152
+ end
153
+
154
+ boxobj = boxtt[cn]
155
+ unboxobj = unboxtt[cn]
156
+ [boxobj, unboxobj]
157
+ end
158
+ end
159
+
160
+ class BaseType
161
+ @@base_type_tab = {}
162
+ @@boxed_type_tab = {}
163
+ @@unboxed_type_tab = {}
164
+
165
+ def self.type_tab
166
+ [@@base_type_tab, @@boxed_type_tab, @@unboxed_type_tab]
167
+ end
168
+
169
+ def self.related_ruby_class(klass, base)
170
+ baseslf = base.new(klass)
171
+ boxslf = RubyTypeBoxed.new(klass)
172
+ unboxslf = RubyTypeUnboxed.new(klass)
173
+
174
+ klass.ancestors.reverse.each do |curcls|
175
+ box_unbox = base.name.gsub(/.*::Ruby/, "")
176
+ mixinname = curcls.name + box_unbox + "CodeGen"
177
+ begin
178
+ mixin = VM::TypeCodeGen.const_get(mixinname)
179
+ baseslf.extend mixin
180
+ rescue NameError
181
+ end
182
+
183
+ mixinname = curcls.name + "TypeBoxedCodeGen"
184
+ begin
185
+ mixin = VM::TypeCodeGen.const_get(mixinname)
186
+ boxslf.extend mixin
187
+ rescue NameError
188
+ end
189
+
190
+ mixinname = curcls.name + "TypeUnboxedCodeGen"
191
+ begin
192
+ mixin = VM::TypeCodeGen.const_get(mixinname)
193
+ unboxslf.extend mixin
194
+ rescue NameError
195
+ end
196
+ end
197
+
198
+ @@base_type_tab[klass] = baseslf
199
+ @@boxed_type_tab[klass] = boxslf
200
+ @@unboxed_type_tab[klass] = unboxslf
201
+
202
+ [boxslf, unboxslf]
203
+ end
204
+
205
+ def self.from_object(obj)
206
+ from_ruby_class(obj.class)
207
+ end
208
+
209
+ def self.from_ruby_class(rcls)
210
+ tobj = @@base_type_tab[rcls]
211
+ if tobj == nil then
212
+ DefaultType0.new
213
+ else
214
+ tobj.instance
215
+ end
216
+ end
217
+
218
+ def initialize(rtype)
219
+ @asm_type = AsmType::MACHINE_WORD
220
+ @ruby_type = rtype
221
+ end
222
+
223
+ attr_accessor :asm_type
224
+ attr_accessor :ruby_type
225
+ end
226
+
227
+ # Same as VALUE type in MRI
228
+ # Type0 makes you can define "Defalut" class
229
+ class DefaultType0<BaseType
230
+ def initialize
231
+ super(Object)
232
+ end
233
+
234
+ def boxed
235
+ true
236
+ end
237
+
238
+ def to_unbox
239
+ self
240
+ end
241
+
242
+ def to_box
243
+ self
244
+ end
245
+
246
+ def ==(other)
247
+ if other then
248
+ self.ruby_type == other.ruby_type and
249
+ boxed == other.boxed
250
+ else
251
+ nil
252
+ end
253
+ end
254
+
255
+ include VM::TypeCodeGen::DefaultTypeCodeGen
256
+ end
257
+
258
+ class RubyTypeBoxed<BaseType
259
+ def boxed
260
+ true
261
+ end
262
+
263
+ def to_unbox
264
+ @@unboxed_type_tab[@ruby_type].instance
265
+ end
266
+
267
+ def to_box
268
+ self
269
+ end
270
+
271
+ include VM::TypeCodeGen::DefaultTypeCodeGen
272
+ end
273
+
274
+ class RubyTypeUnboxed<BaseType
275
+ def boxed
276
+ false
277
+ end
278
+
279
+ def to_box
280
+ @@boxed_type_tab[@ruby_type].instance
281
+ end
282
+
283
+ def to_unbox
284
+ self
285
+ end
286
+
287
+ include VM::TypeCodeGen::DefaultTypeCodeGen
288
+ end
289
+
290
+ YTLJit::RubyType::define_wraped_class(NilClass, RubyTypeBoxed)
291
+ YTLJit::RubyType::define_wraped_class(Fixnum, RubyTypeUnboxed)
292
+ YTLJit::RubyType::define_wraped_class(Float, RubyTypeUnboxed)
293
+ YTLJit::RubyType::define_wraped_class(TrueClass, RubyTypeBoxed)
294
+ YTLJit::RubyType::define_wraped_class(FalseClass, RubyTypeBoxed)
295
+ YTLJit::RubyType::define_wraped_class(String, RubyTypeBoxed)
296
+ YTLJit::RubyType::define_wraped_class(Array, RubyTypeBoxed)
297
+ YTLJit::RubyType::define_wraped_class(Hash, RubyTypeBoxed)
298
+ end
299
+ end
@@ -0,0 +1,158 @@
1
+ module YTLJit
2
+ module VM
3
+ module TypeCodeGen
4
+ module DefaultTypeCodeGen
5
+ def instance
6
+ self
7
+ end
8
+
9
+ def init_type
10
+ end
11
+
12
+ def have_element?
13
+ false
14
+ end
15
+
16
+ def gen_boxing(context)
17
+ context
18
+ end
19
+
20
+ def gen_unboxing(context)
21
+ context
22
+ end
23
+
24
+ def gen_copy(context)
25
+ context
26
+ end
27
+
28
+ def inspect
29
+ "{ #{boxed ? "BOXED" : "UNBOXED"} #{@ruby_type}}"
30
+ end
31
+ end
32
+
33
+ module FixnumTypeUnboxedCodeGen
34
+ include AbsArch
35
+
36
+ def gen_boxing(context)
37
+ asm = context.assembler
38
+ val = context.ret_reg
39
+ vnode = context.ret_node
40
+ asm.with_retry do
41
+ if val != TMPR then
42
+ asm.mov(TMPR, val)
43
+ end
44
+ asm.add(TMPR, TMPR)
45
+ asm.add(TMPR, OpImmidiate8.new(1))
46
+ end
47
+
48
+ context.set_reg_content(TMPR, vnode)
49
+ context.ret_reg = TMPR
50
+ context
51
+ end
52
+
53
+ def gen_unboxing(context)
54
+ context
55
+ end
56
+ end
57
+
58
+ module FixnumTypeBoxedCodeGen
59
+ include AbsArch
60
+
61
+ def gen_boxing(context)
62
+ context
63
+ end
64
+
65
+ def gen_unboxing(context)
66
+ asm = context.assembler
67
+ val = context.ret_reg
68
+ vnode = context.ret_node
69
+ asm.with_retry do
70
+ if val != TMPR then
71
+ asm.mov(TMPR, val)
72
+ end
73
+ asm.sar(TMPR)
74
+ end
75
+ context.set_reg_content(TMPR, vnode)
76
+ context.ret_reg = TMPR
77
+ context
78
+ end
79
+ end
80
+
81
+ module FloatTypeBoxedCodeGen
82
+ include AbsArch
83
+
84
+ def gen_boxing(context)
85
+ p "boxingaaa"
86
+ context
87
+ end
88
+
89
+ def gen_unboxing(context)
90
+ p "inboxing"
91
+ context
92
+ end
93
+ end
94
+
95
+ module FloatTypeUnboxedCodeGen
96
+ include AbsArch
97
+
98
+ def gen_boxing(context)
99
+ asm = context.assembler
100
+ val = context.ret_reg
101
+ vnode = context.ret_node
102
+ context.start_using_reg(FUNC_FLOAT_ARG[0])
103
+ rbfloatnew = OpMemAddress.new(address_of("rb_float_new"))
104
+ asm.with_retry do
105
+ asm.mov(FUNC_FLOAT_ARG[0], val)
106
+ asm.call_with_arg(rbfloatnew, 1)
107
+ end
108
+ context.end_using_reg(FUNC_FLOAT_ARG[0])
109
+ context.ret_reg = RETR
110
+ context
111
+ end
112
+
113
+ def gen_unboxing(context)
114
+ p "unboxing"
115
+ context
116
+ end
117
+ end
118
+
119
+ module ArrayTypeBoxedCodeGen
120
+ include AbsArch
121
+
122
+ def instance
123
+ ni = self.dup
124
+ ni.instance_eval { extend ArrayTypeBoxedCodeGen }
125
+ ni.init
126
+ ni
127
+ end
128
+
129
+ def init
130
+ @element_type = nil
131
+ end
132
+
133
+ attr_accessor :element_type
134
+
135
+ def have_element?
136
+ true
137
+ end
138
+
139
+ def gen_copy(context)
140
+ p "copy"
141
+ context
142
+ end
143
+
144
+ def ==(other)
145
+ other.is_a?(self.class) and
146
+ self.class == other.class and
147
+ @element_type == other.element_type
148
+ end
149
+ end
150
+
151
+ module ArrayTypeUnboxedCodeGen
152
+ def have_element?
153
+ true
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,98 @@
1
+ module YTLJit
2
+ module VM
3
+ module Node
4
+ class TISelfRefNode<SelfRefNode
5
+ def initialize(parent)
6
+ super(parent)
7
+ end
8
+
9
+ def compile_main(context)
10
+ slf = context.slf
11
+ slfval = lambda { slf.address }
12
+ slfadd = OpVarImmdiateAddress.new(slfval)
13
+ asm = context.assembler
14
+ asm.with_retry do
15
+ asm.mov(RETR, slfadd)
16
+ end
17
+
18
+ context.ret_reg = RETR
19
+ context
20
+ end
21
+ end
22
+
23
+ class TIInstanceVarRefNode<InstanceVarRefNode
24
+ def initialize(parent, name)
25
+ super(parent, name)
26
+ end
27
+
28
+ def compile_main(context)
29
+ slf = context.slf
30
+ ivval = lambda { slf.instance_var_address_of(@name) }
31
+ ivadd = OpVarImmidiateAddress.new(ivval)
32
+ asm = context.assembler
33
+ asm.with_retry do
34
+ asm.mov(TMPR, ivadd)
35
+ asm.mov(RETR, INDIRECT_TMPR)
36
+ end
37
+
38
+ context.ret_reg = RETR
39
+ context
40
+ end
41
+ end
42
+
43
+ class TIInstanceVarAssignNode<InstanceVarAssignNode
44
+ def initialize(parent, name, val)
45
+ super(parent, name, val)
46
+ end
47
+
48
+ def compile_main(context)
49
+ context = @val.compile(context)
50
+ valr = context.ret_reg
51
+ slf = context.slf
52
+ ivval = lambda { slf.instance_var_address_of(@name) }
53
+ ivadd = OpVarImmdiateAddress.new(ivval)
54
+ asm = context.assembler
55
+ asm.with_retry do
56
+ asm.mov(TMPR, ivadd)
57
+ asm.mov(INDIRECT_TMPR, valr)
58
+ end
59
+
60
+ context.ret_reg = RETR
61
+ context
62
+ end
63
+ end
64
+ end
65
+
66
+ module YARVTranslatorTypeInferenceMixin
67
+ include Node
68
+
69
+ def initialize(parent)
70
+ super(parent)
71
+ end
72
+
73
+ def visit_putself(code, ins, context)
74
+ curnode = context.current_node
75
+ nnode = TISelfRefNode.new(curnode)
76
+ context.expstack.push nnode
77
+ end
78
+
79
+ def visit_getinstancevariable(code, ins, context)
80
+ curnode = context.current_node
81
+ node = TIInstanceVarRefNode.new(curnode, ins[1])
82
+ context.expstack.push node
83
+ end
84
+
85
+ def visit_setinstancevariable(code, ins, context)
86
+ val = context.expstack.pop
87
+ curnode = context.current_node
88
+ node = TiInstanceVarAssignNode.new(curnode, ins[1], val)
89
+ curnode.body = node
90
+ context.current_node = node
91
+ end
92
+ end
93
+
94
+ class YARVTranslatorTypeInference<YARVTranslatorSimple
95
+ include YARVTranslatorTypeInferenceMixin
96
+ end
97
+ end
98
+ end
data/lib/ytljit.rb ADDED
@@ -0,0 +1,46 @@
1
+ require "rubygems"
2
+
3
+ require 'tempfile'
4
+ require 'rbconfig'
5
+ require 'pp'
6
+ if $ruby_platform == nil then
7
+ $ruby_platform = RUBY_PLATFORM
8
+ end
9
+ # $ruby_platform = "x86_64" # You can select CPU type for debug.
10
+
11
+ require 'iseq'
12
+
13
+ require "ytljit_ext"
14
+
15
+ require 'ytljit/codespace'
16
+
17
+ require 'ytljit/marshal'
18
+ require 'ytljit/util'
19
+ require 'ytljit/error'
20
+
21
+ require 'ytljit/asm'
22
+ require 'ytljit/instruction'
23
+ require 'ytljit/instruction_x86'
24
+ require 'ytljit/instruction_x64'
25
+ require 'ytljit/instruction_ia'
26
+ require 'ytljit/type'
27
+ require 'ytljit/struct'
28
+ require 'ytljit/asmutil'
29
+ require 'ytljit/asmext_x86'
30
+ require 'ytljit/asmext_x64'
31
+ require 'ytljit/asmext'
32
+
33
+ require 'ytljit/rubyvm'
34
+
35
+ require 'ytljit/vm_codegen'
36
+ require 'ytljit/vm_inspect'
37
+ require 'ytljit/vm'
38
+
39
+ require 'ytljit/vm_inline_method'
40
+ require 'ytljit/vm_sendnode'
41
+
42
+ require 'ytljit/vm_trans'
43
+ require 'ytljit/vm_type_gen'
44
+ require 'ytljit/vm_type'
45
+
46
+ require 'ytljit/vm_typeinf'
data/test/asmsample.rb ADDED
@@ -0,0 +1,117 @@
1
+ require 'ytljit.rb'
2
+
3
+ include YTLJit
4
+
5
+ # sample for file output
6
+ def file_output
7
+ File.open("foo.bin", "w") {|fp|
8
+ asm = Assembler.new(FileOutputStream.new(fp))
9
+
10
+ # registor definition
11
+ eax = OpEAX.instance
12
+ ecx = OpECX.instance
13
+
14
+ asm.mov(eax, OpImmidiate32.new(0))
15
+ loop = asm.var_current_address
16
+ asm.add(eax, OpImmidiate8.new(1))
17
+ asm.jo(loop)
18
+ arynew = address_of("rb_ary_new")
19
+ asm.call(arynew)
20
+ asm.ret
21
+ }
22
+ end
23
+
24
+ # Hello World
25
+ include AbsArch
26
+ def hello
27
+ asm = Assembler.new(cs = CodeSpace.new)
28
+
29
+ # registor definition
30
+ hello = "Hello World".address
31
+ asm.step_mode = true
32
+ asm.with_retry do
33
+ asm.mov(FUNC_ARG[0], hello)
34
+ rbp = address_of("rb_p")
35
+ asm.call_with_arg(rbp, 1)
36
+ asm.ret
37
+ end
38
+ cs.fill_disasm_cache
39
+ cs.disassemble
40
+ cs.call(cs.base_address)
41
+ end
42
+ hello
43
+
44
+ # Hello World (Use puts)
45
+ def hello2
46
+ csentry = CodeSpace.new
47
+ asm = Assembler.new(cs = CodeSpace.new)
48
+
49
+ # registor definition
50
+ hello ="Hello World11234".address
51
+ # asm.step_mode = true
52
+ InternalRubyType::rstring_ptr(hello, csentry, cs)
53
+ asm.with_retry do
54
+ asm.mov(FUNC_ARG[0], TMPR)
55
+ rbp = address_of("puts")
56
+ asm.call_with_arg(rbp, 1)
57
+ asm.ret
58
+ end
59
+ cs.disassemble
60
+ csentry.disassemble
61
+ csentry.call(csentry.base_address)
62
+ end
63
+ hello2
64
+
65
+ # Fib number
66
+ def fib(n)
67
+ cs0 = CodeSpace.new
68
+ cs1 = CodeSpace.new
69
+ cs2 = CodeSpace.new
70
+
71
+ asm = Assembler.new(cs0)
72
+ # asm.step_mode = true
73
+ ent = nil
74
+ asm.with_retry do
75
+ ent = cs1.var_base_address
76
+ asm.mov(TMPR, OpImmidiate32.new(n))
77
+ asm.call(ent)
78
+ asm.add(TMPR, TMPR)
79
+ asm.add(TMPR, OpImmidiate8.new(1))
80
+ asm.ret
81
+ end
82
+
83
+ asm = Assembler.new(cs1)
84
+ # asm.step_mode = true
85
+ asm.with_retry do
86
+ asm.cmp(TMPR, OpImmidiate32.new(2))
87
+ asm.jl(cs2.var_base_address)
88
+ asm.sub(TMPR, OpImmidiate32.new(1))
89
+ asm.push(TMPR)
90
+ asm.call(ent)
91
+ asm.pop(TMPR2)
92
+ asm.sub(TMPR2, OpImmidiate32.new(1))
93
+ asm.push(TMPR)
94
+ asm.mov(TMPR, TMPR2)
95
+ asm.call(ent)
96
+ asm.pop(TMPR2)
97
+ asm.add(TMPR, TMPR2)
98
+ asm.ret
99
+ end
100
+
101
+ asm = Assembler.new(cs2)
102
+ # asm.step_mode = true
103
+ asm.with_retry do
104
+ asm.mov(TMPR, OpImmidiate32.new(1))
105
+ asm.ret
106
+ end
107
+
108
+ # cs0.disassemble
109
+ # cs1.disassemble
110
+ # cs2.disassemble
111
+
112
+ cs0.call(cs0.base_address)
113
+ end
114
+
115
+ (1..20).each do |i|
116
+ p fib(i)
117
+ end