ytljit 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +29 -0
- data/Rakefile +22 -0
- data/ext/code_alloc.c +266 -0
- data/ext/extconf.rb +3 -0
- data/ext/ytljit.c +527 -0
- data/ext/ytljit.h +285 -0
- data/lib/ytljit/asm.rb +205 -0
- data/lib/ytljit/asmext.rb +199 -0
- data/lib/ytljit/asmext_x64.rb +212 -0
- data/lib/ytljit/asmext_x86.rb +128 -0
- data/lib/ytljit/asmutil.rb +182 -0
- data/lib/ytljit/codespace.rb +92 -0
- data/lib/ytljit/error.rb +7 -0
- data/lib/ytljit/instruction.rb +138 -0
- data/lib/ytljit/instruction_ia.rb +1298 -0
- data/lib/ytljit/instruction_x64.rb +41 -0
- data/lib/ytljit/instruction_x86.rb +11 -0
- data/lib/ytljit/marshal.rb +133 -0
- data/lib/ytljit/matcher.rb +235 -0
- data/lib/ytljit/rubyvm.rb +63 -0
- data/lib/ytljit/struct.rb +125 -0
- data/lib/ytljit/type.rb +112 -0
- data/lib/ytljit/util.rb +63 -0
- data/lib/ytljit/vm.rb +1649 -0
- data/lib/ytljit/vm_codegen.rb +491 -0
- data/lib/ytljit/vm_inline_method.rb +85 -0
- data/lib/ytljit/vm_inspect.rb +74 -0
- data/lib/ytljit/vm_sendnode.rb +561 -0
- data/lib/ytljit/vm_trans.rb +508 -0
- data/lib/ytljit/vm_type.rb +299 -0
- data/lib/ytljit/vm_type_gen.rb +158 -0
- data/lib/ytljit/vm_typeinf.rb +98 -0
- data/lib/ytljit.rb +46 -0
- data/test/asmsample.rb +117 -0
- data/test/cstest.rb +61 -0
- data/test/marshaltest.rb +27 -0
- data/test/test_assemble.rb +148 -0
- data/test/test_assemble2.rb +286 -0
- data/test/test_codespace.rb +102 -0
- data/test/test_typeinf.rb +21 -0
- data/test/tivmtest.rb +54 -0
- data/test/vmtest.rb +59 -0
- data/test/vmtest2.rb +41 -0
- data/test/vmtest3.rb +22 -0
- data/test/vmtest_compile_only.rb +41 -0
- data/test/vmtest_execute_only.rb +22 -0
- metadata +121 -0
data/README
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
1. What is ytljit?
|
2
|
+
|
3
|
+
Ytljit is a native code generator for compiler.
|
4
|
+
You can generate native code using methods whose name is X86 mnemonic.
|
5
|
+
Why I deverop ytljit instead of using llvm? Because according to
|
6
|
+
my yarv2llvm's experience I think llvm don't have enough power
|
7
|
+
for Ruby compiler. I need rewriting native code and operation to raw stack
|
8
|
+
and refer to CPU flags (carry,zero,negative and so on).
|
9
|
+
|
10
|
+
2. Install
|
11
|
+
|
12
|
+
You must install iseq gem before installing ytljit
|
13
|
+
gem install iseq
|
14
|
+
|
15
|
+
GEM or install script doesn't exist yet.
|
16
|
+
compile extend library writting in C (ext/*).
|
17
|
+
copy extend library and main program writting in Ruby (lib/*) to
|
18
|
+
your ruby library directory.
|
19
|
+
|
20
|
+
3. License
|
21
|
+
|
22
|
+
Ruby's
|
23
|
+
|
24
|
+
4. Author
|
25
|
+
|
26
|
+
Miura Hideki
|
27
|
+
m-72 at tf6.so-net.ne.jp (e-mail)
|
28
|
+
http://twitter.com/miura1729 (twitter)
|
29
|
+
http://d.hatena.ne.jp/miura1729 (blog in japanese)
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#
|
2
|
+
|
3
|
+
require "rbconfig"
|
4
|
+
|
5
|
+
ruby_bin = File.join(RbConfig::CONFIG["bindir"], RbConfig::CONFIG["ruby_install_name"])
|
6
|
+
|
7
|
+
desc "compile ytljit_ext extension library"
|
8
|
+
task :ext do
|
9
|
+
Dir.chdir("ext") do
|
10
|
+
sh "#{ruby_bin} extconf.rb"
|
11
|
+
sh "make"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "run tests"
|
16
|
+
task :test do
|
17
|
+
Dir.glob(File.join("test", "*.rb")) do |f|
|
18
|
+
sh "#{ruby_bin} -I./ext -I./lib " + f
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
task :default => [:ext, :test]
|
data/ext/code_alloc.c
ADDED
@@ -0,0 +1,266 @@
|
|
1
|
+
/* Allocator for code space */
|
2
|
+
#include <assert.h>
|
3
|
+
#include <unistd.h>
|
4
|
+
#include <sys/mman.h>
|
5
|
+
#include <stdlib.h>
|
6
|
+
#include "ruby.h"
|
7
|
+
|
8
|
+
|
9
|
+
/* CodeSpaceArena is memory area for allocate codespace
|
10
|
+
CodeSpaceArena is same align and size. Current size is 16 Kbytes.
|
11
|
+
Structure of CodeSpaceArea is following format
|
12
|
+
|
13
|
+
Hi 16k | |
|
14
|
+
-----------------------------
|
15
|
+
| allocation area |
|
16
|
+
alocarea | |
|
17
|
+
----------------------------
|
18
|
+
| Gate Keeper 0xfffffff |
|
19
|
+
----------------------------
|
20
|
+
| bitmap(1 free, 0 used) |
|
21
|
+
8 | |
|
22
|
+
-----------------------------
|
23
|
+
Lo 0 | next_and_size |
|
24
|
+
|
25
|
+
next_and_size is following format
|
26
|
+
63 43 0
|
27
|
+
xxx .... xxxssss
|
28
|
+
x is next arena. next arena is same as current allocation size.
|
29
|
+
s is current allocation size. real size is 16 * 2**ssss.
|
30
|
+
*/
|
31
|
+
|
32
|
+
typedef struct {
|
33
|
+
uintptr_t next_and_size;
|
34
|
+
uint64_t bitmap[1];
|
35
|
+
} CodeSpaceArena;
|
36
|
+
|
37
|
+
#define ARENA_SIZE 16 * 1024
|
38
|
+
|
39
|
+
/* 2 * 64 means header and gatekeeper */
|
40
|
+
#define BITMAP_SIZE(ALOCSIZ) \
|
41
|
+
(((ARENA_SIZE) * 8 - 2 * 64) / ((ALOCSIZ) * 8 + 1))
|
42
|
+
|
43
|
+
/* Last "+ 1" means gatekeeper */
|
44
|
+
#define HEADER_SIZE(ALOCSIZ) \
|
45
|
+
(((BITMAP_SIZE(ALOCSIZ) + 63) / 64) + 1)
|
46
|
+
|
47
|
+
#define ALOCSIZLOG_MAX 10
|
48
|
+
|
49
|
+
static int csarena_allocarea_tab[ALOCSIZLOG_MAX] = {
|
50
|
+
HEADER_SIZE(16),
|
51
|
+
HEADER_SIZE(32),
|
52
|
+
HEADER_SIZE(64),
|
53
|
+
HEADER_SIZE(128),
|
54
|
+
HEADER_SIZE(256),
|
55
|
+
HEADER_SIZE(512),
|
56
|
+
HEADER_SIZE(1024),
|
57
|
+
HEADER_SIZE(2048),
|
58
|
+
HEADER_SIZE(4096),
|
59
|
+
HEADER_SIZE(8192),
|
60
|
+
};
|
61
|
+
|
62
|
+
static CodeSpaceArena *arena_tab[ALOCSIZLOG_MAX];
|
63
|
+
static CodeSpaceArena *arena_search_tab[ALOCSIZLOG_MAX];
|
64
|
+
|
65
|
+
static size_t page_size;
|
66
|
+
|
67
|
+
CodeSpaceArena *
|
68
|
+
alloc_arena(size_t aloclogsiz, CodeSpaceArena *prev_csa)
|
69
|
+
{
|
70
|
+
uint64_t rbitmap;
|
71
|
+
CodeSpaceArena *arena;
|
72
|
+
void *newmem;
|
73
|
+
int allocsiz;
|
74
|
+
int bitmap_size;
|
75
|
+
int allff_size;
|
76
|
+
int rest_size;
|
77
|
+
|
78
|
+
#if !defined(__CYGWIN__)
|
79
|
+
if (posix_memalign(&newmem, ARENA_SIZE, ARENA_SIZE)) {
|
80
|
+
rb_raise(rb_eNoMemError, "Can't allocate code space area");
|
81
|
+
}
|
82
|
+
if(mprotect(newmem, ARENA_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC)) {
|
83
|
+
rb_raise(rb_eNoMemError, "mprotect failed");
|
84
|
+
}
|
85
|
+
arena = (CodeSpaceArena *)newmem;
|
86
|
+
#else
|
87
|
+
if (!(arena = memalign(ARENA_SIZE, ARENA_SIZE))) {
|
88
|
+
rb_raise(rb_eNoMemError, "Can't allocate code space area");
|
89
|
+
}
|
90
|
+
#endif
|
91
|
+
|
92
|
+
arena->next_and_size = ((uintptr_t)prev_csa) | aloclogsiz;
|
93
|
+
|
94
|
+
/* fill bitmap: 1 means free */
|
95
|
+
allocsiz = 16 << aloclogsiz;
|
96
|
+
bitmap_size = BITMAP_SIZE(allocsiz);
|
97
|
+
allff_size = (bitmap_size / 64) * 8;
|
98
|
+
memset(arena->bitmap, 0xff, allff_size);
|
99
|
+
|
100
|
+
/* rest of bit */
|
101
|
+
rest_size = bitmap_size - allff_size * 8;
|
102
|
+
rbitmap = (1 << (rest_size)) - 1;
|
103
|
+
//fprintf(stderr, "%x %x \n", csarena_allocarea_tab[aloclogsiz], bitmap_size);
|
104
|
+
arena->bitmap[csarena_allocarea_tab[aloclogsiz] - 2] = rbitmap;
|
105
|
+
/* gatekeeper bit */
|
106
|
+
arena->bitmap[csarena_allocarea_tab[aloclogsiz] - 1] = 0xff;
|
107
|
+
|
108
|
+
return arena;
|
109
|
+
}
|
110
|
+
|
111
|
+
/* Ref. Beautiful Code (Japanese ver) Page. 158
|
112
|
+
http://chessprogramming.wikispaces.com/Population+Count
|
113
|
+
Ypsilon Scheme System (src/bit.cpp)
|
114
|
+
*/
|
115
|
+
inline int
|
116
|
+
popcount(uint64_t x)
|
117
|
+
{
|
118
|
+
x = x - ((x >> 1) & 0x5555555555555555ull);
|
119
|
+
x = (x & 0x3333333333333333ull) + ((x >> 2) & 0x3333333333333333ull);
|
120
|
+
x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0full;
|
121
|
+
x *= 0x0101010101010101ull;
|
122
|
+
return x >> 56;
|
123
|
+
}
|
124
|
+
|
125
|
+
/* Ref. Hacker's dilight (Japanese ver) Page.86 */
|
126
|
+
inline int
|
127
|
+
ffs64(uint64_t x)
|
128
|
+
{
|
129
|
+
x = x | (x << 1);
|
130
|
+
x = x | (x << 2);
|
131
|
+
x = x | (x << 4);
|
132
|
+
x = x | (x << 8);
|
133
|
+
x = x | (x << 16);
|
134
|
+
x = x | (x << 32);
|
135
|
+
return popcount(~x);
|
136
|
+
}
|
137
|
+
|
138
|
+
/* from Ypsilon Scheme System */
|
139
|
+
inline int
|
140
|
+
bytes_to_bucket(int x)
|
141
|
+
{
|
142
|
+
uint32_t n = 0;
|
143
|
+
uint32_t c = 16;
|
144
|
+
x = x - 1;
|
145
|
+
do {
|
146
|
+
uint32_t y = x >> c;
|
147
|
+
if (y != 0) { n = n + c; x = y; }
|
148
|
+
c = c >> 1;
|
149
|
+
} while (c != 0);
|
150
|
+
return n + x - 4;
|
151
|
+
}
|
152
|
+
|
153
|
+
void *
|
154
|
+
search_free_chunk(CodeSpaceArena *arena)
|
155
|
+
{
|
156
|
+
char *alocarea;
|
157
|
+
CodeSpaceArena *new_arena;
|
158
|
+
int i;
|
159
|
+
int alocarea_off;
|
160
|
+
int cbitmap;
|
161
|
+
int logsize;
|
162
|
+
|
163
|
+
logsize = arena->next_and_size & 0xf;
|
164
|
+
alocarea_off = csarena_allocarea_tab[logsize] - 1;
|
165
|
+
|
166
|
+
while (arena) {
|
167
|
+
for (i = 0;(cbitmap = arena->bitmap[i]) == 0; i++);
|
168
|
+
if (i < alocarea_off) {
|
169
|
+
arena_search_tab[logsize] = arena;
|
170
|
+
|
171
|
+
/* found free chunk */
|
172
|
+
int bitpos = ffs64(cbitmap);
|
173
|
+
|
174
|
+
/* bitmap free -> used */
|
175
|
+
// fprintf(stderr, "%x %x\n", bitpos, arena->bitmap[i]);
|
176
|
+
arena->bitmap[i] = cbitmap & (cbitmap - 1);
|
177
|
+
|
178
|
+
/* Compute chunk address */
|
179
|
+
alocarea = (char *)(&arena->bitmap[alocarea_off + 1]);
|
180
|
+
return (alocarea + (16 << logsize) * (i * 64 + bitpos));
|
181
|
+
}
|
182
|
+
|
183
|
+
/* Not found. Allocate new arena */
|
184
|
+
new_arena = (CodeSpaceArena *)(arena->next_and_size & ~(0xf));
|
185
|
+
if (new_arena == NULL) {
|
186
|
+
arena = alloc_arena(logsize, arena_tab[logsize]);
|
187
|
+
arena_tab[logsize] = arena_search_tab[logsize] = arena;
|
188
|
+
}
|
189
|
+
else {
|
190
|
+
arena = new_arena;
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
194
|
+
/* Here newver reach maybe...*/
|
195
|
+
assert(0);
|
196
|
+
}
|
197
|
+
|
198
|
+
void *
|
199
|
+
csalloc(int size)
|
200
|
+
{
|
201
|
+
int logsize;
|
202
|
+
void *res;
|
203
|
+
|
204
|
+
logsize = bytes_to_bucket(size);
|
205
|
+
res = search_free_chunk(arena_search_tab[logsize]);
|
206
|
+
// fprintf(stderr, "%x \n", res);
|
207
|
+
return res;
|
208
|
+
}
|
209
|
+
|
210
|
+
void
|
211
|
+
csfree(void *chunk)
|
212
|
+
{
|
213
|
+
CodeSpaceArena *arena;
|
214
|
+
CodeSpaceArena *tmpa;
|
215
|
+
CodeSpaceArena *sarena;
|
216
|
+
size_t offset;
|
217
|
+
size_t alocoff;
|
218
|
+
size_t bitpos;
|
219
|
+
int logsize;
|
220
|
+
int alocsize;
|
221
|
+
|
222
|
+
arena = (CodeSpaceArena *)(((uintptr_t)chunk) & (~(ARENA_SIZE - 1)));
|
223
|
+
logsize = arena->next_and_size & 0xf;
|
224
|
+
alocsize = 16 << logsize;
|
225
|
+
|
226
|
+
alocoff = csarena_allocarea_tab[logsize];
|
227
|
+
offset =(uintptr_t) chunk - (uintptr_t)(&(arena->bitmap[alocoff]));
|
228
|
+
if ((offset & (alocsize - 1)) != 0) {
|
229
|
+
rb_raise(rb_eArgError, "Maybe free illgal chunk");
|
230
|
+
}
|
231
|
+
bitpos = offset / alocsize;
|
232
|
+
arena->bitmap[bitpos / 64] ^= (1 << (bitpos & (64 - 1)));
|
233
|
+
|
234
|
+
/* Update arena_search_tab */
|
235
|
+
for (tmpa = arena_tab[logsize], sarena = arena_search_tab[logsize];
|
236
|
+
tmpa != sarena;
|
237
|
+
tmpa = (CodeSpaceArena *)(tmpa->next_and_size & (~0xf))) {
|
238
|
+
if (tmpa == arena) {
|
239
|
+
arena_search_tab[logsize] = tmpa;
|
240
|
+
break;
|
241
|
+
}
|
242
|
+
}
|
243
|
+
}
|
244
|
+
|
245
|
+
void
|
246
|
+
init_csarena()
|
247
|
+
{
|
248
|
+
int i;
|
249
|
+
|
250
|
+
#if defined(__APPLE__) && defined(__MACH__) /* Mac OS X */
|
251
|
+
page_size = getpagesize();
|
252
|
+
#elif __CYGWIN__
|
253
|
+
page_size = 4096;
|
254
|
+
#else
|
255
|
+
page_size = sysconf(_SC_PAGESIZE);
|
256
|
+
#endif
|
257
|
+
|
258
|
+
/* Check page_size is valid */
|
259
|
+
if ((ARENA_SIZE / page_size) * page_size != ARENA_SIZE) {
|
260
|
+
rb_raise(rb_eNoMemError, "Not support this architecture");
|
261
|
+
}
|
262
|
+
|
263
|
+
for (i = 0; i < ALOCSIZLOG_MAX; i++) {
|
264
|
+
arena_search_tab[i] = arena_tab[i] = alloc_arena(i, NULL);
|
265
|
+
}
|
266
|
+
}
|
data/ext/extconf.rb
ADDED