ytljit 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
data/ext/code_alloc.c CHANGED
@@ -175,11 +175,11 @@ search_free_chunk(CodeSpaceArena *arena)
175
175
  while (arena) {
176
176
  for (i = 0;(cbitmap = arena->bitmap[i]) == 0; i++);
177
177
  if (i < alocarea_off) {
178
- arena_search_tab[logsize] = arena;
179
-
180
178
  /* found free chunk */
181
179
  int bitpos = ffs64(cbitmap);
182
180
 
181
+ arena_search_tab[logsize] = arena;
182
+
183
183
  /* bitmap free -> used */
184
184
  // fprintf(stderr, "%x %x\n", bitpos, arena->bitmap[i]);
185
185
  arena->bitmap[i] = cbitmap & (cbitmap - 1);
data/ext/memory.c CHANGED
@@ -26,7 +26,7 @@ ytl_arena_mark(struct ArenaHeader *arenah)
26
26
  start = arenah->lastptr;
27
27
  appear = 1;
28
28
  }
29
- else if (appear) {
29
+ else if (appear) {
30
30
  start = bodyptr->body;
31
31
  }
32
32
  else {
@@ -47,8 +47,6 @@ ytl_arena_mark(struct ArenaHeader *arenah)
47
47
  void
48
48
  ytl_arena_free(struct ArenaHeader *arenah)
49
49
  {
50
- VALUE *base;
51
- VALUE *start;
52
50
  struct ArenaBody *curptr;
53
51
  struct ArenaBody *curptr_next;
54
52
 
@@ -169,7 +167,6 @@ ytl_arena_emit(VALUE self, VALUE offset, VALUE src)
169
167
  struct ArenaHeader *arenah;
170
168
 
171
169
  int raw_offset;
172
- int newsize;
173
170
  VALUE *newlastptr;
174
171
 
175
172
  Data_Get_Struct(self, struct ArenaHeader, arenah);
@@ -228,7 +225,7 @@ ytl_arena_to_s(VALUE self)
228
225
 
229
226
  Data_Get_Struct(self, struct ArenaHeader, arenah);
230
227
 
231
- return rb_sprintf("#<Arena %p size=%d body=%p last=%p>",
228
+ return rb_sprintf("#<Arena %p size=%lu body=%p last=%p>",
232
229
  (void *)self,
233
230
  ytl_arena_size(self) / 2,
234
231
  (void *)arenah->body->body,
data/ext/thread.c ADDED
@@ -0,0 +1,144 @@
1
+ #include <stdlib.h>
2
+ #include <pthread.h>
3
+ #include "ruby.h"
4
+
5
+ #include "ytljit.h"
6
+ #include "thread.h"
7
+
8
+ VALUE ytl_cThread;
9
+
10
+ static void
11
+ ytl_thread_mark(struct ytl_thread *th)
12
+ {
13
+ rb_gc_mark(th->pself);
14
+ rb_gc_mark(th->cself);
15
+ }
16
+
17
+ /* You may think arguments order is wrong. But it is correct.
18
+ This is for efficient code. See SendThreadNewNode#compile in
19
+ github#ytl/lib/ytl/thread.rb
20
+ */
21
+ VALUE
22
+ ytl_thread_create(void *argv, void *(*entry)(void *))
23
+ {
24
+ struct ytl_thread *th;
25
+
26
+ th = malloc(sizeof(struct ytl_thread));
27
+ th->pself = ((VALUE *)argv)[4];
28
+ th->cself = ((VALUE *)argv)[3];
29
+ pthread_attr_init(&th->attr);
30
+ pthread_attr_setstacksize(&th->attr, 64 * 1024);
31
+ pthread_create(&th->thread, &th->attr, entry, argv);
32
+
33
+ //printf("%x %x \n", th->pself, th->cself);
34
+
35
+ return Data_Wrap_Struct(ytl_cThread, ytl_thread_mark, NULL, (void *)th);
36
+ }
37
+
38
+ static void
39
+ ytl_obj_copy(VALUE dest, VALUE obj)
40
+ {
41
+ rb_copy_generic_ivar(dest, obj);
42
+ rb_gc_copy_finalizer(dest, obj);
43
+ rb_copy_generic_ivar(dest, obj);
44
+ rb_gc_copy_finalizer(dest, obj);
45
+ switch (TYPE(obj)) {
46
+ case T_OBJECT:
47
+ if (!(RBASIC(dest)->flags & ROBJECT_EMBED) && ROBJECT_IVPTR(dest)) {
48
+ xfree(ROBJECT_IVPTR(dest));
49
+ ROBJECT(dest)->as.heap.ivptr = 0;
50
+ ROBJECT(dest)->as.heap.numiv = 0;
51
+ ROBJECT(dest)->as.heap.iv_index_tbl = 0;
52
+ }
53
+ if (RBASIC(obj)->flags & ROBJECT_EMBED) {
54
+ MEMCPY(ROBJECT(dest)->as.ary, ROBJECT(obj)->as.ary, VALUE, ROBJECT_EMBED_LEN_MAX);
55
+ RBASIC(dest)->flags |= ROBJECT_EMBED;
56
+ }
57
+ else {
58
+ long len = ROBJECT(obj)->as.heap.numiv;
59
+ VALUE *ptr = ALLOC_N(VALUE, len);
60
+ MEMCPY(ptr, ROBJECT(obj)->as.heap.ivptr, VALUE, len);
61
+ ROBJECT(dest)->as.heap.ivptr = ptr;
62
+ ROBJECT(dest)->as.heap.numiv = len;
63
+ ROBJECT(dest)->as.heap.iv_index_tbl = ROBJECT(obj)->as.heap.iv_index_tbl;
64
+ RBASIC(dest)->flags &= ~ROBJECT_EMBED;
65
+ }
66
+ break;
67
+
68
+ #if 0
69
+ case T_CLASS:
70
+ case T_MODULE:
71
+ if (RCLASS_IV_TBL(dest)) {
72
+ st_free_table(RCLASS_IV_TBL(dest));
73
+ RCLASS_IV_TBL(dest) = 0;
74
+ }
75
+ if (RCLASS_CONST_TBL(dest)) {
76
+ rb_free_const_table(RCLASS_CONST_TBL(dest));
77
+ RCLASS_CONST_TBL(dest) = 0;
78
+ }
79
+ if (RCLASS_IV_TBL(obj)) {
80
+ RCLASS_IV_TBL(dest) = st_copy(RCLASS_IV_TBL(obj));
81
+ }
82
+ break;
83
+ #endif
84
+ }
85
+ }
86
+
87
+ void
88
+ ytl_thread_exit(VALUE val)
89
+ {
90
+ pthread_exit((void *)val);
91
+ }
92
+
93
+ VALUE
94
+ ytl_thread_join(VALUE self)
95
+ {
96
+ struct ytl_thread *th;
97
+
98
+ Data_Get_Struct(self, struct ytl_thread, th);
99
+ pthread_join(th->thread, NULL);
100
+ pthread_attr_destroy(&th->attr);
101
+
102
+ return self;
103
+ }
104
+
105
+ VALUE
106
+ ytl_thread_merge(VALUE self, VALUE newself)
107
+ {
108
+ struct ytl_thread *th;
109
+ Data_Get_Struct(self, struct ytl_thread, th);
110
+
111
+ if (th->pself != newself) {
112
+ ytl_obj_copy(th->pself, newself);
113
+ }
114
+
115
+ return self;
116
+ }
117
+
118
+ VALUE
119
+ ytl_thread_pself(VALUE self)
120
+ {
121
+ struct ytl_thread *th;
122
+
123
+ Data_Get_Struct(self, struct ytl_thread, th);
124
+ return th->pself;
125
+ }
126
+
127
+ VALUE
128
+ ytl_thread_set_pself(VALUE self, VALUE val)
129
+ {
130
+ struct ytl_thread *th;
131
+
132
+ Data_Get_Struct(self, struct ytl_thread, th);
133
+ th->pself = val;
134
+ return val;
135
+ }
136
+
137
+ VALUE
138
+ ytl_thread_cself(VALUE self)
139
+ {
140
+ struct ytl_thread *th;
141
+
142
+ Data_Get_Struct(self, struct ytl_thread, th);
143
+ return th->cself;
144
+ }
data/ext/thread.h ADDED
@@ -0,0 +1,24 @@
1
+ enum ytl_thread_status {
2
+ YTL_RUN = 0,
3
+ YTL_SLEEP = 1,
4
+ YTL_ABORTING = 2,
5
+ YTL_DEAD = 3,
6
+ };
7
+
8
+ struct ytl_thread {
9
+ enum ytl_thread_status status;
10
+ pthread_t thread;
11
+ pthread_attr_t attr;
12
+ VALUE pself; /* thread creater's self */
13
+ VALUE cself; /* child thread's self */
14
+ };
15
+
16
+ extern VALUE ytl_thread_create(void *, void *(*)(void *));
17
+ extern void ytl_thread_exit(VALUE);
18
+ extern VALUE ytl_thread_join(VALUE);
19
+ extern VALUE ytl_thread_merge(VALUE, VALUE);
20
+ extern VALUE ytl_thread_pself(VALUE);
21
+ extern VALUE ytl_thread_set_pself(VALUE, VALUE);
22
+ extern VALUE ytl_thread_cself(VALUE);
23
+ extern VALUE ytl_cThread;
24
+
data/ext/ytljit.c CHANGED
@@ -6,6 +6,7 @@
6
6
  #include "ruby/st.h"
7
7
 
8
8
  #include "ytljit.h"
9
+ #include "thread.h"
9
10
 
10
11
  VALUE ytl_mYTLJit;
11
12
  VALUE ytl_cCodeSpace;
@@ -106,7 +107,6 @@ ytl_method_address_of_raw(VALUE klass, VALUE mname)
106
107
  VALUE
107
108
  ytl_binding_to_a(VALUE self)
108
109
  {
109
- rb_proc_t *proc;
110
110
  rb_binding_t *bptr;
111
111
  rb_env_t *env;
112
112
  VALUE resary;
@@ -337,9 +337,23 @@ ytl_code_call(int argc, VALUE *argv, VALUE self)
337
337
  raddr = (void *)NUM2ULONG(addr);
338
338
 
339
339
  #ifdef __x86_64__
340
- asm("mov %1, %%rax;"
340
+ asm("push %%rbx;"
341
+ "push %%rdi;"
342
+ "push %%rsi;"
343
+ "push %%r12;"
344
+ "push %%r13;"
345
+ "push %%r14;"
346
+ "push %%r15;"
347
+ "mov %1, %%rax;"
341
348
  "call *%2;"
342
349
  "mov %%rax, %0;"
350
+ "pop %%r15;"
351
+ "pop %%r14;"
352
+ "pop %%r13;"
353
+ "pop %%r12;"
354
+ "pop %%rsi;"
355
+ "pop %%rdi;"
356
+ "pop %%rbx;"
343
357
  : "=r"(rc)
344
358
  : "r"(args), "r"(raddr)
345
359
  : "%rax", "%rbx");
@@ -427,13 +441,15 @@ body(uintptr_t *regbuf)
427
441
  void
428
442
  ytl_backtrace(VALUE rip,
429
443
  VALUE rax, VALUE rcx, VALUE rdx, VALUE rbx,
430
- VALUE rbp, VALUE rsp, VALUE rdi, VALUE rsi,
431
- VALUE r8, VALUE r9, VALUE r10, VALUE r11,
432
- VALUE r12, VALUE r13, VALUE r14, VALUE r15)
444
+ VALUE rbp, VALUE rsp, VALUE rdi, VALUE rsi
445
+ #ifdef __x86_64__
446
+ , VALUE r8, VALUE r9, VALUE r10, VALUE r11,
447
+ VALUE r12, VALUE r13, VALUE r14, VALUE r15
448
+ #endif
449
+ )
433
450
  {
434
451
  VALUE *argv;
435
452
  uintptr_t sp;
436
- int i;
437
453
 
438
454
  argv = ALLOCA_N(VALUE, NUMREGS + 1);
439
455
 
@@ -445,6 +461,7 @@ ytl_backtrace(VALUE rip,
445
461
  argv[5] = ULONG2NUM(rbp);
446
462
  argv[6] = ULONG2NUM(rdi);
447
463
  argv[7] = ULONG2NUM(rsi);
464
+ #ifdef __x86_64__
448
465
  argv[8] = ULONG2NUM(r8);
449
466
  argv[9] = ULONG2NUM(r9);
450
467
  argv[10] = ULONG2NUM(r10);
@@ -453,6 +470,7 @@ ytl_backtrace(VALUE rip,
453
470
  argv[13] = ULONG2NUM(r13);
454
471
  argv[14] = ULONG2NUM(r14);
455
472
  argv[15] = ULONG2NUM(r15);
473
+ #endif
456
474
  sp = (uintptr_t)rsp;
457
475
  sp += NUMREGS * sizeof(uintptr_t); /* reg save area */
458
476
  sp += sizeof(uintptr_t); /* stored pc by call instruction */
@@ -613,6 +631,8 @@ ytl_ivar_set_boxing(VALUE slf, int off, VALUE val)
613
631
  }
614
632
  }
615
633
  ROBJECT_IVPTR(slf)[off] = val;
634
+
635
+ return val;
616
636
  }
617
637
 
618
638
  void
@@ -670,6 +690,13 @@ Init_ytljit_ext()
670
690
  rb_define_method(ytl_cArena, "raw_address", ytl_arena_raw_address, 0);
671
691
  rb_define_method(ytl_cArena, "to_s", ytl_arena_to_s, 0);
672
692
 
693
+ ytl_cThread = rb_define_class_under(ytl_mRuntime, "Thread", rb_cObject);
694
+ rb_define_method(ytl_cThread, "_join", ytl_thread_join, 0);
695
+ rb_define_method(ytl_cThread, "_merge", ytl_thread_merge, 1);
696
+ rb_define_method(ytl_cThread, "pself", ytl_thread_pself, 0);
697
+ rb_define_method(ytl_cThread, "pself=", ytl_thread_set_pself, 1);
698
+ rb_define_method(ytl_cThread, "cself", ytl_thread_cself, 0);
699
+
673
700
  /* Open Handles */
674
701
  #ifdef __CYGWIN__
675
702
  OPEN_CHECK(dl_handles[used_dl_handles] = dlopen("cygwin1.dll", RTLD_LAZY));
data/ext/ytljit.h CHANGED
@@ -316,3 +316,36 @@ typedef struct {
316
316
  } rb_binding_t;
317
317
 
318
318
  rb_iseq_t *rb_method_get_iseq(VALUE method);
319
+
320
+ #ifndef RCLASS_M_TBL
321
+ #define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
322
+ #endif
323
+
324
+ #ifndef RCLASS_SUPER
325
+ #define RCLASS_SUPER(c) (RCLASS(c)->ptr->super)
326
+ #endif
327
+
328
+ #ifndef RCLASS_IV_INDEX_TBL
329
+ #define RCLASS_IV_INDEX_TBL(c) (RCLASS(c)->iv_index_tbl)
330
+ #endif
331
+
332
+ #ifndef ROBJECT_NUMIV
333
+ #define ROBJECT_NUMIV(o) \
334
+ ((RBASIC(o)->flags & ROBJECT_EMBED) ? \
335
+ ROBJECT_EMBED_LEN_MAX : \
336
+ ROBJECT(o)->as.heap.numiv)
337
+ #endif
338
+
339
+ #ifndef ROBJECT_IVPTR
340
+ #define ROBJECT_IVPTR(o) \
341
+ ((RBASIC(o)->flags & ROBJECT_EMBED) ? \
342
+ ROBJECT(o)->as.ary : \
343
+ ROBJECT(o)->as.heap.ivptr)
344
+ #endif
345
+
346
+ #ifndef ROBJECT_IV_INDEX_TBL
347
+ #define ROBJECT_IV_INDEX_TBL(o) \
348
+ ((RBASIC(o)->flags & ROBJECT_EMBED) ? \
349
+ RCLASS_IV_INDEX_TBL(rb_obj_class(o)) : \
350
+ ROBJECT(o)->as.heap.iv_index_tbl)
351
+ #endif
data/lib/ytljit.rb CHANGED
@@ -55,6 +55,6 @@ require 'runtime/object.rb'
55
55
  require 'runtime/gc.rb'
56
56
 
57
57
  module YTLJit
58
- VERSION = "0.0.8"
58
+ VERSION = "0.0.9"
59
59
  end
60
60
 
data/lib/ytljit/asm.rb CHANGED
@@ -24,6 +24,7 @@ module YTLJit
24
24
  if frame_struct_tab[pc] then
25
25
  STDERR.print frame_struct_tab[pc][0].class, "\n"
26
26
  STDERR.print frame_struct_tab[pc][0].debug_info, "\n"
27
+ STDERR.print frame_struct_tab[pc][3], "\n"
27
28
  STDERR.print frame_struct_tab[pc][2].map {|n| n.class}, "\n"
28
29
  bp = memref(bp)
29
30
  backtrace(bp)
@@ -36,6 +37,7 @@ module YTLJit
36
37
  frame_struct_tab = VM::Node::TopTopNode.get_frame_struct_tab
37
38
  STDERR.print frame_struct_tab[regval[1]][0].debug_info, "\n"
38
39
  STDERR.print frame_struct_tab[regval[1]][2].map {|n| n.class}, "\n"
40
+ STDERR.print frame_struct_tab[regval[1]][3], "\n"
39
41
  REGS.each do |rname, no|
40
42
  STDERR.print rname
41
43
  STDERR.print ": 0x"
@@ -177,16 +179,21 @@ module YTLJit
177
179
  @retry_mode = org_retry_mode
178
180
  end
179
181
 
182
+ def get_value_table_entity
183
+ @@value_table_entity
184
+ end
185
+
180
186
  def add_value_entry(val)
181
187
  off= nil
182
188
  unless off = @@value_table_cache[val] then
183
189
  off = @@value_table_entity.current_pos
184
190
  @@value_table_entity.emit([val.value].pack("Q"))
185
191
  stfunc = lambda {
186
- oldpos = @@value_table_entity.current_pos
187
- @@value_table_entity.current_pos = off
188
- @@value_table_entity.emit([val.value].pack("Q"))
189
- @@value_table_entity.current_pos = oldpos
192
+ value_table_entity = get_value_table_entity
193
+ oldpos = value_table_entity.current_pos
194
+ value_table_entity.current_pos = off
195
+ value_table_entity.emit([val.value].pack("Q"))
196
+ value_table_entity.current_pos = oldpos
190
197
  }
191
198
  val.add_refer(stfunc)
192
199
  @@value_table_cache[val] = off
@@ -134,7 +134,7 @@ module YTLJit
134
134
  offset = 8 + spos * 8
135
135
  code += asm.update_state(gen.mov(TMPR, OpIndirect.new(SPR, offset)))
136
136
  end
137
- code += asm.update_state(gen.send(inst, src, TMPR))
137
+ code += asm.update_state(gen.send(inst, dst, TMPR))
138
138
  code
139
139
  end
140
140
  end
@@ -61,7 +61,7 @@ module YTLJit
61
61
  fainfo = gen.funcarg_info
62
62
  code = ""
63
63
  code += asm.update_state(gen.mov(TMPR, src_opecode))
64
- code += asm.update_state(gen.send(inst, src, TMPR))
64
+ code += asm.update_state(gen.send(inst, dst, TMPR))
65
65
  code
66
66
  end
67
67
  end
@@ -0,0 +1,136 @@
1
+ require '../../ext/ytljit_ext.so'
2
+ module YTLJit
3
+
4
+ =begin
5
+ Dynamic Method Search
6
+ using cuckoo hashing
7
+ =end
8
+
9
+ class CuckooHash
10
+ PRIMES = [
11
+ 3,
12
+ 5,
13
+ 7,
14
+ 8 + 3,
15
+ 17,
16
+ 16 + 3,
17
+ 32 + 5,
18
+ 64 + 3,
19
+ 128 + 3,
20
+ 256 + 27,
21
+ 512 + 9,
22
+ 1024 + 9,
23
+ 2048 + 5,
24
+ 4096 + 3,
25
+ 8192 + 27,
26
+ 16384 + 43,
27
+ 32768 + 3,
28
+ 65536 + 45,
29
+ 131072 + 29,
30
+ 262144 + 3,
31
+ 524288 + 21,
32
+ 1048576 + 7,
33
+ 2097152 + 17,
34
+ 4194304 + 15,
35
+ 8388608 + 9,
36
+ 16777216 + 43,
37
+ 33554432 + 35,
38
+ 67108864 + 15,
39
+ 134217728 + 29,
40
+ 268435456 + 3,
41
+ 536870912 + 11,
42
+ 1073741824 + 85,
43
+ 0
44
+ ]
45
+
46
+ def initialize(elements)
47
+ es = elements.size
48
+ @plimepos = 0
49
+ PRIMES.each_with_index do |n, i|
50
+ if es / 2 < n then
51
+ @primepos = i
52
+ break
53
+ end
54
+ end
55
+ @tabsizea = PRIMES[@primepos]
56
+ @tabsizeb = PRIMES[@primepos - 1]
57
+
58
+ @value = [Array.new(@tabsizea), Array.new(@tabsizeb)]
59
+ @key = [Array.new(@tabsizea), Array.new(@tabsizeb)]
60
+ @hfunc = [gen_hash_function_a(@tabsizea), gen_hash_function_b(@tabsizeb)]
61
+ fill(elements)
62
+ end
63
+
64
+ def fill(elements)
65
+ elements.each do |key, value|
66
+ keyadd = ((key.__id__ >> 1) << 2)
67
+ insert(keyadd, value)
68
+ end
69
+ end
70
+ def insert(keyadd, value)
71
+ while true
72
+ @tabsizea.times do
73
+ hv = @hfunc[0].call(keyadd)
74
+
75
+ vala = @value[0][hv]
76
+ keyadda = @key[0][hv]
77
+ @value[0][hv] = value
78
+ @key[0][hv] = keyadd
79
+ if vala == nil then
80
+ return true
81
+ end
82
+ keyadd = keyadda
83
+
84
+ hv = @hfunc[1].call(keyadd)
85
+ valb = @value[1][hv]
86
+ keyaddb = @key[1][hv]
87
+ @value[1][hv] = vala
88
+ @key[1][hv] = keyadd
89
+ if valb == nil then
90
+ return true
91
+ end
92
+ keyadd = keyaddb
93
+ value = valb
94
+ end
95
+
96
+ rehash
97
+ end
98
+ end
99
+
100
+ def rehash
101
+ ovalue = @value
102
+ okey = @key
103
+ if @tabsizea == @tabsizeb then
104
+ @primepos += 1
105
+ @tabsizea = PRIMES[@primepos]
106
+ else
107
+ @tabsizeb = PRIMES[@primepos]
108
+ end
109
+ @value = [Array.new(@tabsizea), Array.new(@tabsizeb)]
110
+ @key = [Array.new(@tabsizea), Array.new(@tabsizeb)]
111
+ @hfunc = [gen_hash_function_a(@tabsizea), gen_hash_function_b(@tabsizeb)]
112
+ [0, 1].each do |n|
113
+ okey[n].each_with_index do |ele, i|
114
+ if ele then
115
+ insert(ele, ovalue[n][i])
116
+ end
117
+ end
118
+ end
119
+ end
120
+
121
+ def gen_hash_function_a(size)
122
+ lambda {|v|
123
+ (v / 20 + v) % size
124
+ }
125
+ end
126
+
127
+ def gen_hash_function_b(size)
128
+ lambda {|v|
129
+ ((v / 21) + v * 31) % size
130
+ }
131
+ end
132
+ end
133
+ end
134
+
135
+ a = YTLJit::CuckooHash.new({})
136
+ p a.gen_hash_function_b(100).to_iseq.to_a