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.
- 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