ytljit 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. data/README +29 -0
  2. data/Rakefile +22 -0
  3. data/ext/code_alloc.c +266 -0
  4. data/ext/extconf.rb +3 -0
  5. data/ext/ytljit.c +527 -0
  6. data/ext/ytljit.h +285 -0
  7. data/lib/ytljit/asm.rb +205 -0
  8. data/lib/ytljit/asmext.rb +199 -0
  9. data/lib/ytljit/asmext_x64.rb +212 -0
  10. data/lib/ytljit/asmext_x86.rb +128 -0
  11. data/lib/ytljit/asmutil.rb +182 -0
  12. data/lib/ytljit/codespace.rb +92 -0
  13. data/lib/ytljit/error.rb +7 -0
  14. data/lib/ytljit/instruction.rb +138 -0
  15. data/lib/ytljit/instruction_ia.rb +1298 -0
  16. data/lib/ytljit/instruction_x64.rb +41 -0
  17. data/lib/ytljit/instruction_x86.rb +11 -0
  18. data/lib/ytljit/marshal.rb +133 -0
  19. data/lib/ytljit/matcher.rb +235 -0
  20. data/lib/ytljit/rubyvm.rb +63 -0
  21. data/lib/ytljit/struct.rb +125 -0
  22. data/lib/ytljit/type.rb +112 -0
  23. data/lib/ytljit/util.rb +63 -0
  24. data/lib/ytljit/vm.rb +1649 -0
  25. data/lib/ytljit/vm_codegen.rb +491 -0
  26. data/lib/ytljit/vm_inline_method.rb +85 -0
  27. data/lib/ytljit/vm_inspect.rb +74 -0
  28. data/lib/ytljit/vm_sendnode.rb +561 -0
  29. data/lib/ytljit/vm_trans.rb +508 -0
  30. data/lib/ytljit/vm_type.rb +299 -0
  31. data/lib/ytljit/vm_type_gen.rb +158 -0
  32. data/lib/ytljit/vm_typeinf.rb +98 -0
  33. data/lib/ytljit.rb +46 -0
  34. data/test/asmsample.rb +117 -0
  35. data/test/cstest.rb +61 -0
  36. data/test/marshaltest.rb +27 -0
  37. data/test/test_assemble.rb +148 -0
  38. data/test/test_assemble2.rb +286 -0
  39. data/test/test_codespace.rb +102 -0
  40. data/test/test_typeinf.rb +21 -0
  41. data/test/tivmtest.rb +54 -0
  42. data/test/vmtest.rb +59 -0
  43. data/test/vmtest2.rb +41 -0
  44. data/test/vmtest3.rb +22 -0
  45. data/test/vmtest_compile_only.rb +41 -0
  46. data/test/vmtest_execute_only.rb +22 -0
  47. metadata +121 -0
@@ -0,0 +1,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