ruby-libjit 0.1.0
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/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
|
+
|