1
/**********************************************************************
6
$Date: 2007-05-28 04:12:43 +0900 (月, 28 5月 2007) $
7
created at: 04/01/01 01:17:22 JST
9
Copyright (C) 2004-2006 Koichi Sasada
11
**********************************************************************/
63
/* from Ruby 1.9 eval.c */
64
#ifdef HAVE_STDARG_PROTOTYPES
66
#define va_init_list(a,b) va_start(a,b)
69
#define va_init_list(a,b) va_start(a)
76
rb_thread_t *ruby_current_thread = 0;
77
rb_vm_t *ruby_current_vm = 0;
78
static VALUE ruby_vm_list = Qnil;
80
RUBY_EXTERN int ruby_nerrs;
83
compile_string(VALUE str, VALUE file, VALUE line)
86
node = rb_compile_string(StringValueCStr(file), str, NUM2INT(line));
90
rb_exc_raise(GET_THREAD()->errinfo); /* TODO: check err */
96
yarvcore_eval_iseq(VALUE iseq)
98
return rb_thread_eval(GET_THREAD(), iseq);
102
th_compile_from_node(rb_thread_t *th, NODE * node, VALUE file)
105
if (th->base_block) {
106
iseq = rb_iseq_new(node,
107
th->base_block->iseq->name,
109
th->base_block->iseq->self,
113
iseq = rb_iseq_new(node, rb_str_new2("<main>"), file,
114
Qfalse, ISEQ_TYPE_TOP);
120
th_compile(rb_thread_t *th, VALUE str, VALUE file, VALUE line)
122
NODE *node = (NODE *) compile_string(str, file, line);
123
return th_compile_from_node(th, (NODE *) node, file);
127
yarvcore_eval_parsed(NODE *node, VALUE file)
129
VALUE iseq = th_compile_from_node(GET_THREAD(), node, file);
130
return yarvcore_eval_iseq(iseq);
134
yarvcore_eval(VALUE self, VALUE str, VALUE file, VALUE line)
137
node = compile_string(str, file, line);
138
return yarvcore_eval_parsed(node, file);
145
void native_thread_cleanup(void *);
150
FREE_REPORT_ENTER("vm");
152
rb_vm_t *vmobj = ptr;
154
st_free_table(vmobj->living_threads);
155
/* TODO: MultiVM Instance */
156
/* VM object should not be cleaned by GC */
157
/* ruby_xfree(ptr); */
158
/* ruby_current_vm = 0; */
160
FREE_REPORT_LEAVE("vm");
164
vm_mark_each_thread_func(st_data_t key, st_data_t value, st_data_t dummy)
166
VALUE thval = (VALUE)key;
172
mark_event_hooks(rb_event_hook_t *hook)
175
rb_gc_mark(hook->data);
183
MARK_REPORT_ENTER("vm");
184
GC_INFO("-------------------------------------------------\n");
187
if (vm->living_threads) {
188
st_foreach(vm->living_threads, vm_mark_each_thread_func, 0);
190
MARK_UNLESS_NULL(vm->thgroup_default);
191
MARK_UNLESS_NULL(vm->mark_object_ary);
192
MARK_UNLESS_NULL(vm->last_status);
193
MARK_UNLESS_NULL(vm->loaded_features);
195
if (vm->loading_table) {
196
rb_mark_tbl(vm->loading_table);
199
mark_event_hooks(vm->event_hooks);
202
MARK_REPORT_LEAVE("vm");
206
rb_vm_mark(void *ptr)
212
vm_init2(rb_vm_t *vm)
214
MEMZERO(vm, rb_vm_t, 1);
222
thread_free(void *ptr)
225
FREE_REPORT_ENTER("thread");
229
FREE_UNLESS_NULL(th->stack);
231
if (th->local_storage) {
232
st_free_table(th->local_storage);
237
VALUE *ptr = th->value_cache_ptr;
240
RBASIC(v)->flags = 0;
241
RBASIC(v)->klass = 0;
247
if (th->vm->main_thread == th) {
248
GC_INFO("main thread\n");
254
FREE_REPORT_LEAVE("thread");
257
void yarv_machine_stack_mark(rb_thread_t *th);
260
thread_mark(void *ptr)
262
rb_thread_t *th = NULL;
263
MARK_REPORT_ENTER("thread");
267
VALUE *p = th->stack;
268
VALUE *sp = th->cfp->sp + th->mark_stack_len;
269
rb_control_frame_t *cfp = th->cfp;
270
rb_control_frame_t *limit_cfp =
271
(void *)(th->stack + th->stack_size);
276
while (cfp != limit_cfp) {
277
rb_gc_mark(cfp->proc);
278
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
282
/* mark ruby objects */
283
MARK_UNLESS_NULL(th->first_proc);
284
MARK_UNLESS_NULL(th->first_args);
286
MARK_UNLESS_NULL(th->thgroup);
287
MARK_UNLESS_NULL(th->value);
288
MARK_UNLESS_NULL(th->errinfo);
289
MARK_UNLESS_NULL(th->local_svar);
290
MARK_UNLESS_NULL(th->top_self);
291
MARK_UNLESS_NULL(th->top_wrapper);
292
MARK_UNLESS_NULL(th->fiber);
293
MARK_UNLESS_NULL(th->root_fiber);
295
rb_mark_tbl(th->local_storage);
297
if (GET_THREAD() != th && th->machine_stack_start && th->machine_stack_end) {
298
yarv_machine_stack_mark(th);
299
rb_gc_mark_locations((VALUE *)&th->machine_regs,
300
(VALUE *)(&th->machine_regs) +
301
sizeof(th->machine_regs) / sizeof(VALUE));
304
mark_event_hooks(th->event_hooks);
307
MARK_UNLESS_NULL(th->stat_insn_usage);
308
MARK_REPORT_LEAVE("thread");
312
rb_thread_mark(void *ptr)
318
thread_alloc(VALUE klass)
322
obj = Data_Make_Struct(klass, rb_thread_t,
323
thread_mark, thread_free, th);
328
th_init2(rb_thread_t *th)
330
MEMZERO(th, rb_thread_t, 1);
332
/* allocate thread stack */
333
th->stack = ALLOC_N(VALUE, RUBY_VM_THREAD_STACK_SIZE);
335
th->stack_size = RUBY_VM_THREAD_STACK_SIZE;
336
th->cfp = (void *)(th->stack + th->stack_size);
340
th->cfp->sp = th->stack + 1;
342
th->cfp->lfp = th->stack;
344
th->cfp->dfp = th->stack;
345
th->cfp->self = Qnil;
349
th->cfp->block_iseq = 0;
351
th->status = THREAD_RUNNABLE;
355
th->value_cache_ptr = &th->value_cache[0];
360
th_init(rb_thread_t *th)
365
extern VALUE ruby_top_self;
368
ruby_thread_init(VALUE self)
371
rb_vm_t *vm = GET_THREAD()->vm;
372
GetThreadPtr(self, th);
379
th->top_self = ruby_top_self;
384
rb_thread_alloc(VALUE klass)
386
VALUE self = thread_alloc(klass);
387
ruby_thread_init(self);
391
/********************************************************************/
393
VALUE insns_name_array(void);
394
extern VALUE *rb_gc_stack_start;
406
VALUE ary = rb_ary_new();
408
#include <execinfo.h>
409
#define MAX_NATIVE_TRACE 1024
410
static void *trace[MAX_NATIVE_TRACE];
411
int n = backtrace(trace, MAX_NATIVE_TRACE);
412
char **syms = backtrace_symbols(trace, n);
419
for (i=0; i<n; i++) {
420
rb_ary_push(ary, rb_str_new2(syms[i]));
427
static char *yarv_options = ""
428
#if OPT_DIRECT_THREADED_CODE
429
"[direct threaded code] "
430
#elif OPT_TOKEN_THREADED_CODE
431
"[token threaded code] "
432
#elif OPT_CALL_THREADED_CODE
433
"[call threaded code] "
436
#if OPT_BASIC_OPERATIONS
437
"[optimize basic operation] "
439
#if OPT_STACK_CACHING
442
#if OPT_OPERANDS_UNIFICATION
443
"[operands unification] "
445
#if OPT_INSTRUCTIONS_UNIFICATION
446
"[instructions unification] "
448
#if OPT_INLINE_METHOD_CACHE
449
"[inline method cache] "
451
#if OPT_BLOCKINLINING
456
void yarv_init_redefined_flag(void);
462
rb_cVM = rb_define_class("VM", rb_cObject);
463
rb_undef_alloc_func(rb_cVM);
466
rb_cEnv = rb_define_class_under(rb_cVM, "Env", rb_cObject);
467
rb_undef_alloc_func(rb_cEnv);
470
rb_cThread = rb_define_class("Thread", rb_cObject);
471
rb_undef_alloc_func(rb_cThread);
472
rb_define_method(rb_cThread, "initialize", ruby_thread_init, 0);
474
/* ::VM::USAGE_ANALISYS_* */
475
rb_define_const(rb_cVM, "USAGE_ANALISYS_INSN", rb_hash_new());
476
rb_define_const(rb_cVM, "USAGE_ANALISYS_REGS", rb_hash_new());
477
rb_define_const(rb_cVM, "USAGE_ANALISYS_INSN_BIGRAM", rb_hash_new());
478
rb_define_const(rb_cVM, "OPTS", rb_str_new2(yarv_options));
480
/* ::VM::InsnNameArray */
481
rb_define_const(rb_cVM, "InsnNameArray", insns_name_array());
484
rb_define_singleton_method(rb_cVM, "eval", yarvcore_eval, 3);
486
/* debug functions ::VM::SDR(), ::VM::NSDR() */
487
rb_define_singleton_method(rb_cVM, "SDR", sdr, 0);
488
rb_define_singleton_method(rb_cVM, "NSDR", nsdr, 0);
491
symIFUNC = ID2SYM(rb_intern("<IFUNC>"));
492
symCFUNC = ID2SYM(rb_intern("<CFUNC>"));
495
idPLUS = rb_intern("+");
496
idMINUS = rb_intern("-");
497
idMULT = rb_intern("*");
498
idDIV = rb_intern("/");
499
idMOD = rb_intern("%");
500
idLT = rb_intern("<");
501
idLTLT = rb_intern("<<");
502
idLE = rb_intern("<=");
503
idGT = rb_intern(">");
504
idGE = rb_intern(">=");
505
idEq = rb_intern("==");
506
idEqq = rb_intern("===");
507
idBackquote = rb_intern("`");
508
idEqTilde = rb_intern("=~");
510
idAREF = rb_intern("[]");
511
idASET = rb_intern("[]=");
513
idEach = rb_intern("each");
514
idTimes = rb_intern("times");
515
idLength = rb_intern("length");
516
idLambda = rb_intern("lambda");
517
idIntern = rb_intern("intern");
518
idGets = rb_intern("gets");
519
idSucc = rb_intern("succ");
520
idEnd = rb_intern("end");
521
idRangeEachLT = rb_intern("Range#each#LT");
522
idRangeEachLE = rb_intern("Range#each#LE");
523
idArrayEach = rb_intern("Array#each");
524
idMethodMissing = rb_intern("method_missing");
526
idThrowState = rb_intern("#__ThrowState__");
528
idBitblt = rb_intern("bitblt");
529
idAnswer = rb_intern("the_answer_to_life_the_universe_and_everything");
530
idSvarPlaceholder = rb_intern("#svar");
532
idSend = rb_intern("send");
533
id__send__ = rb_intern("__send__");
534
id__send = rb_intern("__send");
535
idFuncall = rb_intern("funcall");
536
id__send_bang = rb_intern("__send!");
538
/* VM bootstrap: phase 2 */
540
rb_vm_t *vm = ruby_current_vm;
541
rb_thread_t *th = GET_THREAD();
543
/* create vm object */
544
vm->self = Data_Wrap_Struct(rb_cVM, vm_mark, vm_free, vm);
546
/* create main thread */
547
th->self = Data_Wrap_Struct(rb_cThread, thread_mark, thread_free, th);
549
vm->main_thread = th;
550
vm->running_thread = th;
553
th->top_self = ruby_top_self;
554
rb_thread_set_current(th);
556
vm->living_threads = st_init_numtable();
557
st_insert(vm->living_threads, th->self, (st_data_t) th->thread_id);
559
yarv_init_redefined_flag();
565
/* VM bootstrap: phase 1 */
566
rb_vm_t *vm = ALLOC(rb_vm_t);
567
rb_thread_t *th = ALLOC(rb_thread_t);
570
ruby_current_vm = vm;
574
th->machine_stack_start = rb_gc_stack_start;
575
rb_thread_set_current_raw(th);