ruby-libjit 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +6 -0
- data/LGPL +515 -0
- data/LICENSE +20 -0
- data/README +50 -0
- data/ext/extconf.rb +100 -0
- data/ext/insns.inc.rpp +204 -0
- data/ext/jit.c +1521 -0
- data/ext/method_data.c +385 -0
- data/ext/method_data.c.rpp +294 -0
- data/ext/method_data.h +11 -0
- data/ext/minimal_node.c +35 -0
- data/ext/minimal_node.h +52 -0
- data/ext/rubyjit.h +20 -0
- data/ext/rubypp.rb +97 -0
- data/lib/jit/array.rb +135 -0
- data/lib/jit/function.rb +201 -0
- data/lib/jit/struct.rb +163 -0
- data/lib/jit/value.rb +199 -0
- data/lib/jit.rb +5 -0
- data/sample/fib.rb +29 -0
- data/sample/gcd_benchmark.rb +117 -0
- data/sample/simple.rb +15 -0
- data/test/test_jit_array.rb +70 -0
- data/test/test_jit_function.rb +329 -0
- data/test/test_jit_struct.rb +111 -0
- data/test/test_jit_value.rb +258 -0
- metadata +77 -0
data/ext/extconf.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
if not have_library('jit', 'jit_init', ["jit/jit.h"]) then
|
4
|
+
$stderr.puts "libjit not found"
|
5
|
+
exit 1
|
6
|
+
end
|
7
|
+
|
8
|
+
if not have_macro("SIZEOF_VALUE", "ruby.h") then
|
9
|
+
check_sizeof("VALUE", "ruby.h")
|
10
|
+
end
|
11
|
+
|
12
|
+
if not have_macro("SIZEOF_ID", "ruby.h") then
|
13
|
+
check_sizeof("ID", "ruby.h")
|
14
|
+
end
|
15
|
+
|
16
|
+
if have_macro("_GNU_SOURCE", "ruby.h") then
|
17
|
+
$defs.push("-DRUBY_DEFINES_GNU_SOURCE")
|
18
|
+
end
|
19
|
+
|
20
|
+
have_func("rb_class_boot", "ruby.h")
|
21
|
+
have_func("rb_errinfo", "ruby.h")
|
22
|
+
have_func('fmemopen')
|
23
|
+
have_func("rb_ensure", "ruby.h")
|
24
|
+
|
25
|
+
if have_header('ruby/node.h') then
|
26
|
+
# ruby.h defines HAVE_RUBY_NODE_H, even though it is not there
|
27
|
+
$defs.push("-DREALLY_HAVE_RUBY_NODE_H")
|
28
|
+
elsif have_header('node.h') then
|
29
|
+
# okay
|
30
|
+
else
|
31
|
+
$defs.push("-DNEED_MINIMAL_NODE")
|
32
|
+
end
|
33
|
+
|
34
|
+
have_header('env.h')
|
35
|
+
|
36
|
+
checking_for("whether VALUE is a pointer") do
|
37
|
+
if not try_link(<<"SRC")
|
38
|
+
#include <ruby.h>
|
39
|
+
int main()
|
40
|
+
{
|
41
|
+
VALUE v;
|
42
|
+
v /= 5;
|
43
|
+
}
|
44
|
+
SRC
|
45
|
+
then
|
46
|
+
$defs.push("-DVALUE_IS_PTR");
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
if defined?(RUBY_ENGINE) and RUBY_ENGINE == 'rbx' then
|
51
|
+
$defs.push("-DHAVE_RUBINIUS")
|
52
|
+
end
|
53
|
+
|
54
|
+
rb_files = Dir['*.rb']
|
55
|
+
rpp_files = Dir['*.rpp']
|
56
|
+
generated_files = rpp_files.map { |f| f.sub(/\.rpp$/, '') }
|
57
|
+
|
58
|
+
srcs = Dir['*.c']
|
59
|
+
generated_files.each do |f|
|
60
|
+
if f =~ /\.c$/ then
|
61
|
+
srcs << f
|
62
|
+
end
|
63
|
+
end
|
64
|
+
srcs.uniq!
|
65
|
+
$objs = srcs.map { |f| f.sub(/\.c$/, ".#{$OBJEXT}") }
|
66
|
+
|
67
|
+
if Config::CONFIG['CC'] == 'gcc' then
|
68
|
+
# $CFLAGS << ' -Wall -g -pedantic -Wno-long-long'
|
69
|
+
$CFLAGS << ' -Wall -g'
|
70
|
+
end
|
71
|
+
|
72
|
+
create_makefile("jit")
|
73
|
+
|
74
|
+
append_to_makefile = ''
|
75
|
+
|
76
|
+
rpp_files.each do |rpp_file|
|
77
|
+
dest_file = rpp_file.sub(/\.rpp$/, '')
|
78
|
+
append_to_makefile << <<END
|
79
|
+
#{dest_file}: #{rpp_file} #{rb_files.join(' ')}
|
80
|
+
$(RUBY) rubypp.rb #{rpp_file} #{dest_file}
|
81
|
+
END
|
82
|
+
end
|
83
|
+
|
84
|
+
generated_headers = generated_files.select { |x| x =~ /\.h$/ || x =~ /\.inc$/ }
|
85
|
+
append_to_makefile << <<END
|
86
|
+
$(OBJS): #{generated_headers.join(' ')}
|
87
|
+
clean: clean_generated_files
|
88
|
+
clean_generated_files:
|
89
|
+
@$(RM) #{generated_files.join(' ')}
|
90
|
+
|
91
|
+
install: $(includedir)/rubyjit.h
|
92
|
+
|
93
|
+
$(includedir)/rubyjit.h: rubyjit.h
|
94
|
+
$(INSTALL_PROG) rubyjit.h $(includedir)
|
95
|
+
END
|
96
|
+
|
97
|
+
File.open('Makefile', 'a') do |makefile|
|
98
|
+
makefile.puts(append_to_makefile)
|
99
|
+
end
|
100
|
+
|
data/ext/insns.inc.rpp
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
#ruby <<END
|
2
|
+
|
3
|
+
V = :value
|
4
|
+
L = :label_ptr
|
5
|
+
B = :label
|
6
|
+
N = :nint
|
7
|
+
T = :type_t
|
8
|
+
_ = :void
|
9
|
+
|
10
|
+
def incoming_args(arg_types)
|
11
|
+
num_args = arg_types.length
|
12
|
+
return (1..num_args).map { |n| ", VALUE arg#{n}" }.join
|
13
|
+
end
|
14
|
+
|
15
|
+
def declaration(name, type)
|
16
|
+
case type
|
17
|
+
when V then return "jit_value_t #{name};"
|
18
|
+
when L then return "jit_label_t * #{name};"
|
19
|
+
when B then return "jit_label_t * #{name};"
|
20
|
+
when N then return "jit_nint #{name};"
|
21
|
+
when T then return "jit_type_t #{name};"
|
22
|
+
when :void then nil
|
23
|
+
else raise "Invalid type #{type}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def write_declaration(name, type, indent)
|
28
|
+
d = declaration(name, type)
|
29
|
+
if d then
|
30
|
+
puts "#{' '*indent}#{d}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def ruby_type(type)
|
35
|
+
case type
|
36
|
+
when V then return "rb_cValue"
|
37
|
+
when L then return "rb_cLabel"
|
38
|
+
when B then return "rb_cLabel"
|
39
|
+
when N then return "rb_cFixnum"
|
40
|
+
when T then return "rb_cType"
|
41
|
+
else raise "Invalid type #{type}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def jit_type(type)
|
46
|
+
case type
|
47
|
+
when V then return "struct _jit_value"
|
48
|
+
when L then return "jit_label_t"
|
49
|
+
when B then return "jit_label_t"
|
50
|
+
when T then return "struct _jit_type"
|
51
|
+
else raise "Invalid type #{type}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def get_value(type, arg, j_arg)
|
56
|
+
case type
|
57
|
+
when N then
|
58
|
+
return "#{j_arg} = NUM2INT(#{arg})"
|
59
|
+
else
|
60
|
+
return "Data_Get_Struct(#{arg}, #{jit_type(type)}, #{j_arg})"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def jit_insn_args(arg_types)
|
65
|
+
num_args = arg_types.length
|
66
|
+
arg_list = (1..num_args).map do |n|
|
67
|
+
case arg_types[n-1]
|
68
|
+
when B then ", *j_arg#{n}"
|
69
|
+
else ", j_arg#{n}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
return arg_list.join
|
73
|
+
end
|
74
|
+
|
75
|
+
def write_insn(name, retval_type, arg_types)
|
76
|
+
num_args = arg_types.length
|
77
|
+
an = [?a, ?e, ?i, ?o, ?u].include?(name[0])
|
78
|
+
puts "/* Generate a#{an} #{name} instruction (see the libjit documentation for more"
|
79
|
+
puts " * details. */"
|
80
|
+
puts "static VALUE function_insn_#{name}(VALUE self#{incoming_args(arg_types)})"
|
81
|
+
puts "{"
|
82
|
+
puts " jit_function_t function;"
|
83
|
+
write_declaration('retval', retval_type, 2)
|
84
|
+
arg_types.each_with_index do |type, n|
|
85
|
+
write_declaration("j_arg#{n+1}", type, 2)
|
86
|
+
end
|
87
|
+
puts
|
88
|
+
arg_types.each_with_index do |type, n|
|
89
|
+
puts " check_type(\"arg#{n+1}\", #{ruby_type(type)}, arg#{n+1});"
|
90
|
+
end
|
91
|
+
puts
|
92
|
+
puts " Data_Get_Struct(self, struct _jit_function, function);"
|
93
|
+
arg_types.each_with_index do |type, n|
|
94
|
+
puts " " + get_value(type, "arg#{n+1}", "j_arg#{n+1}") + ";"
|
95
|
+
end
|
96
|
+
puts
|
97
|
+
if retval_type == V then
|
98
|
+
puts " retval = jit_insn_#{name}(function#{jit_insn_args(arg_types)});"
|
99
|
+
puts " return Data_Wrap_Struct(rb_cValue, 0, 0, retval);"
|
100
|
+
elsif retval_type == :void then
|
101
|
+
puts " jit_insn_#{name}(function#{jit_insn_args(arg_types)});"
|
102
|
+
puts " return Qnil;"
|
103
|
+
else
|
104
|
+
raise "Invalid retval type #{retval_type}"
|
105
|
+
end
|
106
|
+
puts "}"
|
107
|
+
end
|
108
|
+
|
109
|
+
insns = [
|
110
|
+
[ 'load' , V, V ] ,
|
111
|
+
[ 'store' , _, V, V ] ,
|
112
|
+
[ 'dup' , V, V ] ,
|
113
|
+
[ 'add' , V, V, V ] ,
|
114
|
+
[ 'add_ovf' , V, V, V ] ,
|
115
|
+
[ 'sub' , V, V, V ] ,
|
116
|
+
[ 'sub_ovf' , V, V, V ] ,
|
117
|
+
[ 'mul' , V, V, V ] ,
|
118
|
+
[ 'mul_ovf' , V, V, V ] ,
|
119
|
+
[ 'div' , V, V, V ] ,
|
120
|
+
[ 'rem' , V, V, V ] ,
|
121
|
+
[ 'rem_ieee' , V, V, V ] ,
|
122
|
+
[ 'neg' , V, V ] ,
|
123
|
+
[ 'and' , V, V, V ] ,
|
124
|
+
[ 'or' , V, V, V ] ,
|
125
|
+
[ 'xor' , V, V, V ] ,
|
126
|
+
[ 'not' , V, V ] ,
|
127
|
+
[ 'shl' , V, V, V ] ,
|
128
|
+
[ 'shr' , V, V, V ] ,
|
129
|
+
[ 'ushr' , V, V, V ] ,
|
130
|
+
[ 'sshr' , V, V, V ] ,
|
131
|
+
[ 'eq' , V, V, V ] ,
|
132
|
+
[ 'ne' , V, V, V ] ,
|
133
|
+
[ 'lt' , V, V, V ] ,
|
134
|
+
[ 'le' , V, V, V ] ,
|
135
|
+
[ 'gt' , V, V, V ] ,
|
136
|
+
[ 'ge' , V, V, V ] ,
|
137
|
+
[ 'cmpl' , V, V, V ] ,
|
138
|
+
[ 'cmpg' , V, V, V ] ,
|
139
|
+
[ 'to_bool' , V, V ] ,
|
140
|
+
[ 'to_not_bool' , V, V ] ,
|
141
|
+
[ 'acos' , V, V ] ,
|
142
|
+
[ 'asin' , V, V ] ,
|
143
|
+
[ 'atan' , V, V ] ,
|
144
|
+
[ 'atan2' , V, V, V ] ,
|
145
|
+
[ 'ceil' , V, V ] ,
|
146
|
+
[ 'cos' , V, V ] ,
|
147
|
+
[ 'cosh' , V, V ] ,
|
148
|
+
[ 'exp' , V, V ] ,
|
149
|
+
[ 'floor' , V, V ] ,
|
150
|
+
[ 'log' , V, V ] ,
|
151
|
+
[ 'log10' , V, V ] ,
|
152
|
+
[ 'pow' , V, V, V ] ,
|
153
|
+
[ 'rint' , V, V ] ,
|
154
|
+
[ 'round' , V, V ] ,
|
155
|
+
[ 'sin' , V, V ] ,
|
156
|
+
[ 'sinh' , V, V ] ,
|
157
|
+
[ 'sqrt' , V, V ] ,
|
158
|
+
[ 'tan' , V, V ] ,
|
159
|
+
[ 'tanh' , V, V ] ,
|
160
|
+
[ 'is_nan' , V, V ] ,
|
161
|
+
[ 'is_finite' , V, V ] ,
|
162
|
+
[ 'is_inf' , V, V ] ,
|
163
|
+
[ 'abs' , V, V ] ,
|
164
|
+
[ 'min' , V, V, V ] ,
|
165
|
+
[ 'max' , V, V, V ] ,
|
166
|
+
[ 'sign' , V, V ] ,
|
167
|
+
[ 'branch' , _, L ] ,
|
168
|
+
[ 'branch_if' , _, V, L ] ,
|
169
|
+
[ 'branch_if_not' , _, V, L ] ,
|
170
|
+
[ 'label' , _, L ] ,
|
171
|
+
[ 'address_of' , V, V ] ,
|
172
|
+
[ 'address_of_label' , V, L ] ,
|
173
|
+
[ 'store_relative' , _, V, N, V ] ,
|
174
|
+
[ 'load_relative' , V, V, N, T ] ,
|
175
|
+
[ 'add_relative' , V ,V, N ] ,
|
176
|
+
[ 'memcpy' , _, V, V, V ] ,
|
177
|
+
[ 'memmove' , _, V, V, V ] ,
|
178
|
+
[ 'memset' , _, V, V, V ] ,
|
179
|
+
[ 'alloca' , V, V ] ,
|
180
|
+
[ 'load_elem' , V, V, V, T ] ,
|
181
|
+
[ 'store_elem' , _, V, V, V ] ,
|
182
|
+
[ 'move_blocks_to_end' , _, B, B ] ,
|
183
|
+
[ 'move_blocks_to_start' , _, B, B ] ,
|
184
|
+
[ 'push' , _, V ] ,
|
185
|
+
[ 'push_ptr' , _, V, T ] ,
|
186
|
+
[ 'pop_stack' , _, N ] ,
|
187
|
+
[ 'stack_top' , V ] ,
|
188
|
+
]
|
189
|
+
|
190
|
+
insns.each do |name, retval_type, *arg_types|
|
191
|
+
write_insn(name, retval_type, arg_types)
|
192
|
+
puts
|
193
|
+
end
|
194
|
+
|
195
|
+
puts "static void init_insns()"
|
196
|
+
puts "{"
|
197
|
+
insns.each do |name, retval_type, *arg_types|
|
198
|
+
num_args = arg_types.length
|
199
|
+
puts " rb_define_method(rb_cFunction, \"insn_#{name}\", function_insn_#{name}, #{num_args});"
|
200
|
+
end
|
201
|
+
puts "}"
|
202
|
+
|
203
|
+
END
|
204
|
+
|