ruby-libjit 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/jit/value.rb ADDED
@@ -0,0 +1,199 @@
1
+ require 'jit'
2
+
3
+ module JIT
4
+ class Value
5
+ module UNINITIALIZED; end
6
+
7
+ # Create a new JIT::Value. If value is specified, the value will be
8
+ # variable, otherwise it will be a constant with the given value.
9
+ #
10
+ # +function+:: The function to which this value will belong.
11
+ # +type+:: The type of the new value.
12
+ # +value+: The value to use, if this is a constant.
13
+ #
14
+ def self.new(function, type, value=UNINITIALIZED)
15
+ # TODO: Not sure if I like this...
16
+ if value == UNINITIALIZED then
17
+ return function.value(type)
18
+ else
19
+ return function.const(type, value)
20
+ end
21
+ end
22
+
23
+ # Assign +value+ to this JIT::Value.
24
+ #
25
+ # +value+:: The value to assign.
26
+ #
27
+ def store(value)
28
+ lhs, rhs = coerce(value)
29
+ self.function.insn_store(lhs, rhs)
30
+ end
31
+
32
+ # Return the address of this value.
33
+ def address
34
+ return self.function.insn_address_of(self)
35
+ end
36
+
37
+ # Add this value to another and return the result.
38
+ #
39
+ # +rhs+:: The right hand side of the addition operator.
40
+ #
41
+ def +(rhs)
42
+ lhs, rhs = coerce(rhs)
43
+ return self.function.insn_add(lhs, rhs)
44
+ end
45
+
46
+ # Subtract another value from this one and return the result.
47
+ #
48
+ # +rhs+:: The right hand side of the subtraction operator.
49
+ #
50
+ def -(rhs)
51
+ lhs, rhs = coerce(rhs)
52
+ return self.function.insn_sub(lhs, rhs)
53
+ end
54
+
55
+ # Multiply this value by another and return the result.
56
+ #
57
+ # +rhs+:: The right hand side of the multiplication operator.
58
+ #
59
+ def *(rhs)
60
+ lhs, rhs = coerce(rhs)
61
+ return self.function.insn_mul(lhs, rhs)
62
+ end
63
+
64
+ # Divide this value by another and return the quotient.
65
+ #
66
+ # +rhs+:: The right hand side of the division operator.
67
+ #
68
+ def /(rhs)
69
+ lhs, rhs = coerce(rhs)
70
+ return self.function.insn_div(lhs, rhs)
71
+ end
72
+
73
+ # Return the additive inverse (negation) of this value.
74
+ def -@()
75
+ rhs, lhs = coerce(0) # inverted, since we are subtracting from 0
76
+ return lhs - rhs
77
+ end
78
+
79
+ # Divide this value by another and return the remainder.
80
+ #
81
+ # +rhs+:: The right hand side of the modulus operator.
82
+ #
83
+ def %(rhs)
84
+ lhs, rhs = coerce(rhs)
85
+ return self.function.insn_rem(lhs, rhs)
86
+ end
87
+
88
+ # Perform a bitwise and between this value and another.
89
+ #
90
+ # +rhs+:: The right hand side of the operator.
91
+ #
92
+ def &(rhs)
93
+ lhs, rhs = coerce(rhs)
94
+ return self.function.insn_and(lhs, rhs)
95
+ end
96
+
97
+ # Perform a bitwise or between this value and another.
98
+ #
99
+ # +rhs+:: The right hand side of the operator.
100
+ #
101
+ def |(rhs)
102
+ lhs, rhs = coerce(rhs)
103
+ return self.function.insn_or(lhs, rhs)
104
+ end
105
+
106
+ # Perform a bitwise xor between this value and another.
107
+ #
108
+ # +rhs+:: The right hand side of the operator.
109
+ #
110
+ def ^(rhs)
111
+ lhs, rhs = coerce(rhs)
112
+ return self.function.insn_xor(lhs, rhs)
113
+ end
114
+
115
+ # Compare this value to another, returning 1 if the left hand is
116
+ # less than the right hand side or 0 otherwise.
117
+ #
118
+ # +rhs+:: The right hand side of the comparison.
119
+ #
120
+ def <(rhs)
121
+ lhs, rhs = coerce(rhs)
122
+ return self.function.insn_lt(lhs, rhs)
123
+ end
124
+
125
+ # Compare this value to another, returning 1 if the left hand is
126
+ # greater than the right hand side or 0 otherwise.
127
+ #
128
+ # +rhs+:: The right hand side of the comparison.
129
+ #
130
+ def >(rhs)
131
+ lhs, rhs = coerce(rhs)
132
+ return self.function.insn_gt(lhs, rhs)
133
+ end
134
+
135
+ # Compare this value to another, returning 1 if the left hand is
136
+ # equal to the right hand side or 0 otherwise.
137
+ #
138
+ # +rhs+:: The right hand side of the comparison.
139
+ #
140
+ def ==(rhs)
141
+ lhs, rhs = coerce(rhs)
142
+ return self.function.insn_eq(lhs, rhs)
143
+ end
144
+
145
+ # Compare this value to another, returning 1 if the left hand is
146
+ # not equal to the right hand side or 0 otherwise.
147
+ #
148
+ # +rhs+:: The right hand side of the comparison.
149
+ #
150
+ def neq(rhs)
151
+ lhs, rhs = coerce(rhs)
152
+ return self.function.insn_ne(lhs, rhs)
153
+ end
154
+
155
+ # Compare this value to another, returning 1 if the left hand is
156
+ # less than or equal to the right hand side or 0 otherwise.
157
+ #
158
+ # +rhs+:: The right hand side of the comparison.
159
+ #
160
+ def <=(rhs)
161
+ lhs, rhs = coerce(rhs)
162
+ return self.function.insn_le(lhs, rhs)
163
+ end
164
+
165
+ # Compare this value to another, returning 1 if the left hand is
166
+ # greater than or equal to the right hand side or 0 otherwise.
167
+ #
168
+ # +rhs+:: The right hand side of the comparison.
169
+ #
170
+ def >=(rhs)
171
+ lhs, rhs = coerce(rhs)
172
+ return self.function.insn_ge(lhs, rhs)
173
+ end
174
+
175
+ # Shift this value left by the given number of bits.
176
+ #
177
+ # +rhs+:: The number of bits to shift by.
178
+ #
179
+ def <<(rhs)
180
+ lhs, rhs = coerce(rhs)
181
+ return self.function.insn_shl(lhs, rhs)
182
+ end
183
+
184
+ # Shift this value right by the given number of bits.
185
+ #
186
+ # +rhs+:: The number of bits to shift by.
187
+ #
188
+ def >>(rhs)
189
+ lhs, rhs = coerce(rhs)
190
+ return self.function.insn_shr(lhs, rhs)
191
+ end
192
+
193
+ # Return the logical inverse of this value.
194
+ def ~()
195
+ return self.function.insn_not(self)
196
+ end
197
+ end
198
+ end
199
+
data/lib/jit.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'jit.so'
2
+ require 'jit/array'
3
+ require 'jit/function'
4
+ require 'jit/struct'
5
+ require 'jit/value'
data/sample/fib.rb ADDED
@@ -0,0 +1,29 @@
1
+ require 'jit'
2
+
3
+ fib = nil
4
+ signature = JIT::Type.create_signature(
5
+ JIT::ABI::CDECL,
6
+ JIT::Type::INT,
7
+ [ JIT::Type::INT ])
8
+ fib = JIT::Function.build(signature) do |f|
9
+ n = f.param(0)
10
+
11
+ a = f.value(JIT::Type::INT, 0)
12
+ b = f.value(JIT::Type::INT, 1)
13
+ c = f.value(JIT::Type::INT, 1)
14
+
15
+ i = f.value(JIT::Type::INT, 0)
16
+
17
+ f.while(proc { i < n }) {
18
+ c.store(a + b)
19
+ a.store(b)
20
+ b.store(c)
21
+ i.store(i + 1)
22
+ }.end
23
+
24
+ f.return(c)
25
+ end
26
+
27
+ values = (0...10).collect { |x| fib.apply(x) }
28
+ p values #=> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
29
+
@@ -0,0 +1,117 @@
1
+ require 'jit'
2
+ require 'benchmark'
3
+
4
+ # GCD, JIT-compiled
5
+
6
+ jit_gcd = nil
7
+
8
+ JIT::Context.build do |context|
9
+ signature = JIT::Type.create_signature(
10
+ JIT::ABI::CDECL,
11
+ JIT::Type::INT,
12
+ [ JIT::Type::INT, JIT::Type::INT ])
13
+ jit_gcd = JIT::Function.compile(context, signature) do |f|
14
+ x = f.get_param(0)
15
+ y = f.get_param(1)
16
+ temp1 = f.insn_eq(x, y)
17
+ label1 = JIT::Label.new
18
+ f.insn_branch_if_not(temp1, label1)
19
+ f.insn_return(x)
20
+ f.insn_label(label1)
21
+ temp2 = f.insn_lt(x, y)
22
+ label2 = JIT::Label.new
23
+ f.insn_branch_if_not(temp2, label2)
24
+ s1 = f.insn_sub(y, x)
25
+ temp3 = f.insn_call("gcd", f, 0, x, s1)
26
+ f.insn_return(temp3)
27
+ f.insn_label(label2)
28
+ s2 = f.insn_sub(x, y)
29
+ temp4 = f.insn_call("gcd", f, 0, s2, y)
30
+ f.insn_return(temp4)
31
+
32
+ f.optimization_level = 3
33
+ end
34
+ end
35
+
36
+ if jit_gcd.apply(28, 21) != 7 then
37
+ puts "jit_gcd is broken"
38
+ exit 1
39
+ end
40
+
41
+
42
+ # GCD with tail recursion optimization
43
+
44
+ jit_gcd_tail = nil
45
+
46
+ JIT::Context.build do |context|
47
+ signature = JIT::Type.create_signature(
48
+ JIT::ABI::CDECL,
49
+ JIT::Type::INT,
50
+ [ JIT::Type::INT, JIT::Type::INT ])
51
+ jit_gcd_tail = JIT::Function.compile(context, signature) do |f|
52
+ x = f.get_param(0)
53
+ y = f.get_param(1)
54
+ temp1 = f.insn_eq(x, y)
55
+ label1 = JIT::Label.new
56
+ f.insn_branch_if_not(temp1, label1)
57
+ f.insn_return(x)
58
+ f.insn_label(label1)
59
+ temp2 = f.insn_lt(x, y)
60
+ label2 = JIT::Label.new
61
+ f.insn_branch_if_not(temp2, label2)
62
+ s1 = f.insn_sub(y, x)
63
+ temp3 = f.insn_call("gcd", f, JIT::Call::TAIL, x, s1)
64
+ # f.insn_return(temp3)
65
+ f.insn_label(label2)
66
+ s2 = f.insn_sub(x, y)
67
+ temp4 = f.insn_call("gcd", f, JIT::Call::TAIL, s2, x)
68
+ # f.insn_return(temp4)
69
+
70
+ f.optimization_level = 3
71
+ end
72
+ end
73
+
74
+ if jit_gcd_tail.apply(28, 21) != 7 then
75
+ puts "jit_gcd_tail is broken"
76
+ exit 1
77
+ end
78
+
79
+
80
+ # GCD in ruby with recursion
81
+
82
+ def gcd(x, y)
83
+ if x == y
84
+ return x
85
+ elsif x < y
86
+ return gcd(x, y - x)
87
+ else
88
+ return gcd(x - y, y)
89
+ end
90
+ end
91
+
92
+
93
+ # GCD in ruby without recursion
94
+
95
+ def gcd2(x, y)
96
+ while x != y do
97
+ if x < y
98
+ y -= x
99
+ else
100
+ x -= y
101
+ end
102
+ end
103
+ return x
104
+ end
105
+
106
+ N = 1000
107
+
108
+ X = 1000
109
+ Y = 1005
110
+
111
+ Benchmark.bm(16) do |x|
112
+ x.report("jit") { N.times { jit_gcd.apply(X, Y) } }
113
+ x.report("jit tail:") { N.times { jit_gcd_tail.apply(X, Y) } }
114
+ x.report("ruby recur:") { N.times { gcd(X, Y) } }
115
+ x.report("ruby iter:") { N.times { gcd2(X, Y) } }
116
+ end
117
+
data/sample/simple.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'jit'
2
+
3
+ function = nil
4
+ JIT::Context.build do |context|
5
+ signature = JIT::Type.create_signature(
6
+ JIT::ABI::CDECL,
7
+ JIT::Type::INT, # returns an integer
8
+ [ JIT::Type::INT ]) # and tages an integer as a parameter
9
+ function = JIT::Function.compile(context, signature) do |f|
10
+ value = f.get_param(0)
11
+ f.insn_return(value)
12
+ end
13
+ end
14
+
15
+ p function.apply(42) #=> 42
@@ -0,0 +1,70 @@
1
+ require 'jit/array'
2
+ require 'jit/function'
3
+ require 'test/unit'
4
+ require 'assertions'
5
+
6
+ class TestJitArray < Test::Unit::TestCase
7
+ include JitAssertions
8
+
9
+ def test_new_array
10
+ a_type = JIT::Array.new(JIT::Type::INT, 12)
11
+ assert_equal JIT::Type::INT, a_type.type
12
+ assert_equal 12, a_type.length
13
+ end
14
+
15
+ # TODO: wrap
16
+
17
+ def test_create
18
+ p = proc { |f|
19
+ a_type = JIT::Array.new(JIT::Type::INT, 4)
20
+ a = a_type.create(f)
21
+ f.return f.const(JIT::Type::INT, 0)
22
+ }
23
+ assert_function_result(
24
+ :result => [ JIT::Type::INT, 0 ],
25
+ &p)
26
+ end
27
+
28
+ def test_offset_of
29
+ a_type = JIT::Array.new(JIT::Type::INT, 4)
30
+ assert_equal 0, a_type.offset_of(0)
31
+ assert_equal 4, a_type.offset_of(1)
32
+ assert_equal 8, a_type.offset_of(2)
33
+ assert_equal 12, a_type.offset_of(3)
34
+ # TODO: check out of bounds
35
+ end
36
+
37
+ def test_type_of
38
+ a_type = JIT::Array.new(JIT::Type::INT, 4)
39
+ assert_equal JIT::Type::INT, a_type.type_of(0)
40
+ assert_equal JIT::Type::INT, a_type.type_of(1)
41
+ assert_equal JIT::Type::INT, a_type.type_of(2)
42
+ assert_equal JIT::Type::INT, a_type.type_of(3)
43
+ # TODO: check out of bounds
44
+ end
45
+
46
+ def test_instance_bracket
47
+ p = proc { |f|
48
+ a_type = JIT::Array.new(JIT::Type::INT, 4)
49
+ a = a_type.create(f)
50
+ f.insn_store_relative(a.ptr, 4, f.const(JIT::Type::INT, 42))
51
+ f.return a[1]
52
+ }
53
+ assert_function_result(
54
+ :result => [ JIT::Type::INT, 42 ],
55
+ &p)
56
+ end
57
+
58
+ def test_instance_bracket_eq
59
+ p = proc { |f|
60
+ a_type = JIT::Array.new(JIT::Type::INT, 4)
61
+ a = a_type.create(f)
62
+ a[1] = f.const(JIT::Type::INT, 42)
63
+ f.return a[1]
64
+ }
65
+ assert_function_result(
66
+ :result => [ JIT::Type::INT, 42 ],
67
+ &p)
68
+ end
69
+ end
70
+