ytljit 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/README +29 -0
  2. data/Rakefile +22 -0
  3. data/ext/code_alloc.c +266 -0
  4. data/ext/extconf.rb +3 -0
  5. data/ext/ytljit.c +527 -0
  6. data/ext/ytljit.h +285 -0
  7. data/lib/ytljit/asm.rb +205 -0
  8. data/lib/ytljit/asmext.rb +199 -0
  9. data/lib/ytljit/asmext_x64.rb +212 -0
  10. data/lib/ytljit/asmext_x86.rb +128 -0
  11. data/lib/ytljit/asmutil.rb +182 -0
  12. data/lib/ytljit/codespace.rb +92 -0
  13. data/lib/ytljit/error.rb +7 -0
  14. data/lib/ytljit/instruction.rb +138 -0
  15. data/lib/ytljit/instruction_ia.rb +1298 -0
  16. data/lib/ytljit/instruction_x64.rb +41 -0
  17. data/lib/ytljit/instruction_x86.rb +11 -0
  18. data/lib/ytljit/marshal.rb +133 -0
  19. data/lib/ytljit/matcher.rb +235 -0
  20. data/lib/ytljit/rubyvm.rb +63 -0
  21. data/lib/ytljit/struct.rb +125 -0
  22. data/lib/ytljit/type.rb +112 -0
  23. data/lib/ytljit/util.rb +63 -0
  24. data/lib/ytljit/vm.rb +1649 -0
  25. data/lib/ytljit/vm_codegen.rb +491 -0
  26. data/lib/ytljit/vm_inline_method.rb +85 -0
  27. data/lib/ytljit/vm_inspect.rb +74 -0
  28. data/lib/ytljit/vm_sendnode.rb +561 -0
  29. data/lib/ytljit/vm_trans.rb +508 -0
  30. data/lib/ytljit/vm_type.rb +299 -0
  31. data/lib/ytljit/vm_type_gen.rb +158 -0
  32. data/lib/ytljit/vm_typeinf.rb +98 -0
  33. data/lib/ytljit.rb +46 -0
  34. data/test/asmsample.rb +117 -0
  35. data/test/cstest.rb +61 -0
  36. data/test/marshaltest.rb +27 -0
  37. data/test/test_assemble.rb +148 -0
  38. data/test/test_assemble2.rb +286 -0
  39. data/test/test_codespace.rb +102 -0
  40. data/test/test_typeinf.rb +21 -0
  41. data/test/tivmtest.rb +54 -0
  42. data/test/vmtest.rb +59 -0
  43. data/test/vmtest2.rb +41 -0
  44. data/test/vmtest3.rb +22 -0
  45. data/test/vmtest_compile_only.rb +41 -0
  46. data/test/vmtest_execute_only.rb +22 -0
  47. 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
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+
3
+ create_makefile("ytljit_ext");