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 +2 -2
- data/ext/memory.c +2 -5
- data/ext/thread.c +144 -0
- data/ext/thread.h +24 -0
- data/ext/ytljit.c +33 -6
- data/ext/ytljit.h +33 -0
- data/lib/ytljit.rb +1 -1
- data/lib/ytljit/asm.rb +11 -4
- data/lib/ytljit/asmext_x64.rb +1 -1
- data/lib/ytljit/asmext_x86.rb +1 -1
- data/lib/ytljit/dyna_method.rb +136 -0
- data/lib/ytljit/marshal.rb +11 -0
- data/lib/ytljit/type.rb +2 -2
- data/lib/ytljit/vm.rb +781 -211
- data/lib/ytljit/vm_codegen.rb +73 -24
- data/lib/ytljit/vm_cruby_obj.rb +42 -30
- data/lib/ytljit/vm_inline_method.rb +40 -14
- data/lib/ytljit/vm_sendnode.rb +609 -190
- data/lib/ytljit/vm_trans.rb +60 -16
- data/lib/ytljit/vm_type.rb +29 -9
- data/lib/ytljit/vm_type_gen.rb +131 -56
- data/test/foo.rb +12 -0
- metadata +9 -16
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=%
|
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("
|
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
|
-
|
432
|
-
VALUE
|
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
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
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
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
|
data/lib/ytljit/asmext_x64.rb
CHANGED
@@ -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,
|
137
|
+
code += asm.update_state(gen.send(inst, dst, TMPR))
|
138
138
|
code
|
139
139
|
end
|
140
140
|
end
|
data/lib/ytljit/asmext_x86.rb
CHANGED
@@ -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
|