ytljit 0.0.8 → 0.0.9

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