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.
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");