64 #if VM_COLLECT_USAGE_DETAILS
65 static void vm_collect_usage_operand(
int insn,
int n,
VALUE op);
66 static void vm_collect_usage_insn(
int insn);
67 static void vm_collect_usage_register(
int reg,
int isset);
141 static VALUE sym_global_method_state, sym_global_constant_state, sym_class_serial;
152 }
else if (arg ==
Qnil) {
156 if (sym_global_method_state == 0) {
157 #define S(s) sym_##s = ID2SYM(rb_intern_const(#s))
158 S(global_method_state);
159 S(global_constant_state);
164 #define SET(name, attr) \
165 if (key == sym_##name) \
166 return SERIALT2NUM(attr); \
167 else if (hash != Qnil) \
168 rb_hash_aset(hash, sym_##name, SERIALT2NUM(attr));
189 if (iseq->
type != ISEQ_TYPE_TOP) {
294 while (th->
cfp != cfp) {
296 printf(
"skipped frame: %s\n", vm_frametype_name(th->
cfp));
329 typedef void rb_vm_at_exit_func(
rb_vm_t*);
345 #define ENV_IN_HEAP_P(th, env) \
346 (!((th)->stack <= (env) && (env) < ((th)->stack + (th)->stack_size)))
347 #define ENV_VAL(env) ((env)[1])
428 fprintf(stderr,
"---\n");
429 fprintf(stderr,
"envptr: %p\n", (
void *)&env->
block.
ep[0]);
430 fprintf(stderr,
"envval: %10p ", (
void *)env->
block.
ep[1]);
432 fprintf(stderr,
"ep: %10p\n", (
void *)env->
block.
ep);
434 fprintf(stderr,
">>\n");
436 fprintf(stderr,
"<<\n");
458 VALUE envval, penvval = 0;
467 if (envptr != endptr) {
475 while (pcfp->
ep != penvptr) {
503 for (i = 0; i <= local_size; i++) {
504 env->
env[i] = envptr[-local_size + i];
506 fprintf(stderr,
"%2d ", &envptr[-local_size + i] - th->
stack);
dp(env->
env[i]);
509 envptr[-local_size + i] = 0;
515 nenvptr = &env->
env[i - 1];
595 *blockprocptr = blockprocval;
615 (cfp->
iseq->
type == ISEQ_TYPE_RESCUE ||
616 cfp->
iseq->
type == ISEQ_TYPE_ENSURE)) {
621 VALUE epval = *escape_ep;
658 VALUE procval, envval, blockprocval = 0;
663 rb_bug(
"rb_vm_make_proc: Proc value is already created.");
684 rb_bug(
"invalid ptr: block->ep");
700 ID minibuf[4], *dyns = minibuf;
703 if (dyncount < 0)
return 0;
707 base_block = &env->
block;
708 base_iseq = base_block->
iseq;
713 MEMCPY(dyns + 1, dynvars,
ID, dyncount);
717 base_iseq->
self, ISEQ_TYPE_EVAL);
744 int i, opt_pc, arg_size = iseq->
arg_size;
750 for (i=0; i<
argc; i++) {
751 cfp->
sp[i] = argv[i];
866 argc, argv, blockptr);
874 while (cfp->
pc == 0) {
1002 debug_cref(
NODE *cref)
1006 printf(
"%ld\n", cref->nd_visi);
1007 cref = cref->nd_next;
1204 #define OP(mid_, bop_) (mid = id##mid_, bop = BOP_##bop_, ruby_vm_redefined_flag[bop] = 0)
1205 #define C(k) add_opt_method(rb_c##k, mid, bop)
1206 OP(PLUS, PLUS), (
C(Fixnum),
C(Float),
C(String),
C(Array));
1207 OP(MINUS, MINUS), (
C(Fixnum),
C(Float));
1208 OP(MULT, MULT), (
C(Fixnum),
C(Float));
1211 OP(Eq, EQ), (
C(Fixnum),
C(Float),
C(String));
1212 OP(Eqq, EQQ), (
C(Fixnum),
C(Bignum),
C(Float),
C(Symbol),
C(String));
1213 OP(LT, LT), (
C(Fixnum),
C(Float));
1214 OP(LE, LE), (
C(Fixnum),
C(Float));
1215 OP(GT, GT), (
C(Fixnum),
C(Float));
1216 OP(GE, GE), (
C(Fixnum),
C(Float));
1217 OP(LTLT, LTLT), (
C(String),
C(Array));
1219 OP(ASET, ASET), (
C(Array),
C(Hash));
1220 OP(Length, LENGTH), (
C(Array),
C(String),
C(Hash));
1221 OP(Size, SIZE), (
C(Array),
C(String),
C(Hash));
1222 OP(EmptyP, EMPTY_P), (
C(Array),
C(String),
C(Hash));
1223 OP(Succ, SUCC), (
C(Fixnum),
C(String),
C(Time));
1225 OP(Freeze, FREEZE), (
C(String));
1364 if ((state = th->
state) != 0) {
1367 goto exception_handler;
1373 unsigned long epc, cont_pc, cont_sp;
1374 VALUE catch_iseqval;
1382 cont_pc = cont_sp = catch_iseqval = 0;
1400 if (cfp->
ep == escape_ep) {
1409 if (entry->
start < epc && entry->
end >= epc) {
1411 catch_iseqval = entry->
iseq;
1412 cont_pc = entry->
cont;
1413 cont_sp = entry->
sp;
1418 if (!catch_iseqval) {
1436 #if OPT_STACK_CACHING
1450 if (entry->
start < epc && entry->
end >= epc) {
1454 catch_iseqval = entry->
iseq;
1455 cont_pc = entry->
cont;
1456 cont_sp = entry->
sp;
1465 if (entry->
start < epc && entry->
end >= epc) {
1468 catch_iseqval = entry->
iseq;
1469 cont_pc = entry->
cont;
1470 cont_sp = entry->
sp;
1476 if (cfp->
ep == escape_ep) {
1485 else if (state ==
TAG_BREAK && ((
VALUE)escape_ep & ~0x03) == 0) {
1488 search_restart_point:
1492 if (entry->
start < epc && entry->
end >= epc) {
1494 catch_iseqval = entry->
iseq;
1495 cont_pc = entry->
cont;
1496 cont_sp = entry->
sp;
1499 else if (entry->
type == type) {
1504 #if OPT_STACK_CACHING
1519 goto search_restart_point;
1523 goto search_restart_point;
1528 if (entry->
start < epc && entry->
end >= epc) {
1531 catch_iseqval = entry->
iseq;
1532 cont_pc = entry->
cont;
1533 cont_sp = entry->
sp;
1540 if (catch_iseqval != 0) {
1595 goto exception_handler;
1636 if (!iseq && cfp->
me) {
1638 if (klassp) *klassp = cfp->
me->
klass;
1644 if (klassp) *klassp = 0;
1649 if (klassp) *klassp = iseq->
klass;
1678 if (cfp->
iseq != 0) {
1732 RUBY_GC_INFO(
"-------------------------------------------------\n");
1788 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
1803 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
1810 ruby_current_vm = 0;
1847 #define SET(name) rb_hash_aset(result, ID2SYM(rb_intern(#name)), SIZET2NUM(vm->default_params.name));
1848 SET(thread_vm_stack_size);
1849 SET(thread_machine_stack_size);
1850 SET(fiber_vm_stack_size);
1851 SET(fiber_machine_stack_size);
1861 size_t result = default_value;
1862 if ((envval =
getenv(name)) != 0) {
1863 long val = atol(envval);
1864 if (val < (
long)min_value) {
1865 val = (long)min_value;
1869 if (0) fprintf(stderr,
"%s: %"PRIdSIZE"\n", name, result);
1877 #ifdef PTHREAD_STACK_MIN
1878 size_t size = *sizep;
1881 #ifdef __SYMBIAN32__
1885 #ifdef PTHREAD_STACK_MIN
1886 if (size < PTHREAD_STACK_MIN) {
1887 *sizep = PTHREAD_STACK_MIN * 2;
1901 get_param(
"RUBY_THREAD_MACHINE_STACK_SIZE",
1911 get_param(
"RUBY_FIBER_MACHINE_STACK_SIZE",
1933 #define USE_THREAD_DATA_RECYCLE 1
1935 #if USE_THREAD_DATA_RECYCLE
1936 #define RECYCLE_MAX 64
1943 if (thread_recycle_stack_count) {
1953 #define thread_recycle_stack(size) ALLOC_N(VALUE, (size))
1959 #if USE_THREAD_DATA_RECYCLE
1961 thread_recycle_stack_slot[thread_recycle_stack_count++] = stack;
1968 #ifdef USE_THREAD_RECYCLE
1970 thread_recycle_struct(
void)
1996 while (cfp != limit_cfp) {
2061 rb_bug(
"thread_free: locking_mutex must be NULL (%p:%p)", (
void *)th, (
void *)th->
locking_mutex);
2064 rb_bug(
"thread_free: keeping_mutexes must be NULL (%p:%p)", (
void *)th, (
void *)th->
keeping_mutexes);
2075 #ifdef USE_SIGALTSTACK
2082 if (ruby_current_thread == th)
2083 ruby_current_thread =
NULL;
2108 #define thread_data_type ruby_threadptr_data_type
2134 #ifdef USE_THREAD_RECYCLE
2150 #ifdef USE_SIGALTSTACK
2171 #if OPT_CALL_THREADED_CODE
2205 VALUE klass = cref->nd_clss;
2206 int noex = (int)cref->nd_visi;
2228 miseq->defined_method_id =
id;
2237 #define REWIND_CFP(expr) do { \
2238 rb_thread_t *th__ = GET_THREAD(); \
2239 th__->cfp++; expr; th__->cfp--; \
2305 for (i=0; i<
argc; i+=2) {
2396 if (argc < 2) hash = kw;
2404 extern VALUE *rb_gc_register_stack_start;
2423 #include <execinfo.h>
2424 #define MAX_NATIVE_TRACE 1024
2425 static void *trace[MAX_NATIVE_TRACE];
2426 int n = backtrace(trace, MAX_NATIVE_TRACE);
2427 char **syms = backtrace_symbols(trace, n);
2434 for (i=0; i<n; i++) {
2442 #if VM_COLLECT_USAGE_DETAILS
2443 static VALUE usage_analysis_insn_stop(
VALUE self);
2444 static VALUE usage_analysis_operand_stop(
VALUE self);
2445 static VALUE usage_analysis_register_stop(
VALUE self);
2639 #if VM_COLLECT_USAGE_DETAILS
2641 #define define_usage_analysis_hash(name) \
2642 rb_define_const(rb_cRubyVM, "USAGE_ANALYSIS_"#name, rb_hash_new())
2643 define_usage_analysis_hash(
"INSN");
2644 define_usage_analysis_hash(
"REGS");
2645 define_usage_analysis_hash(
"INSN_BIGRAM");
2655 #if OPT_DIRECT_THREADED_CODE
2657 #elif OPT_TOKEN_THREADED_CODE
2659 #elif OPT_CALL_THREADED_CODE
2663 #if OPT_STACK_CACHING
2666 #if OPT_OPERANDS_UNIFICATION
2669 #if OPT_INSTRUCTIONS_UNIFICATION
2672 #if OPT_INLINE_METHOD_CACHE
2675 #if OPT_BLOCKINLINING
2705 volatile VALUE th_self;
2752 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
2763 fprintf(stderr,
"[FATAL] failed to allocate memory\n");
2770 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
2773 ruby_current_vm = vm;
2793 return GET_VM()->top_self;
2836 int len,
size_t pos,
VALUE *pnop,
VALUE child);
2838 #if VM_COLLECT_USAGE_DETAILS
2840 #define HASH_ASET(h, k, v) rb_hash_aset((h), (st_data_t)(k), (st_data_t)(v))
2854 vm_analysis_insn(
int insn)
2858 static int prev_insn = -1;
2864 CONST_ID(usage_hash,
"USAGE_ANALYSIS_INSN");
2865 CONST_ID(bigram_hash,
"USAGE_ANALYSIS_INSN_BIGRAM");
2869 HASH_ASET(uh,
INT2FIX(insn), ihash);
2877 if (prev_insn != -1) {
2896 vm_analysis_operand(
int insn,
int n,
VALUE op)
2906 CONST_ID(usage_hash,
"USAGE_ANALYSIS_INSN");
2911 HASH_ASET(uh,
INT2FIX(insn), ihash);
2915 HASH_ASET(ihash,
INT2FIX(n), ophash);
2928 vm_analysis_register(
int reg,
int isset)
2933 static const char regstrs[][5] = {
2941 static const char getsetstr[][4] = {
2945 static VALUE syms[
sizeof(regstrs) /
sizeof(regstrs[0])][2];
2949 CONST_ID(usage_hash,
"USAGE_ANALYSIS_REGS");
2954 for (i = 0; i < (int)(
sizeof(regstrs) /
sizeof(regstrs[0])); i++) {
2956 for (j = 0; j < 2; j++) {
2957 snprintf(buff, 0x10,
"%d %s %-4s", i, getsetstr[j], regstrs[i]);
2962 valstr = syms[reg][isset];
2979 usage_analysis_insn_stop(
VALUE self)
2987 usage_analysis_operand_stop(
VALUE self)
2995 usage_analysis_register_stop(
VALUE self)
3009 #if VM_COLLECT_USAGE_DETAILS
3012 vm_collect_usage_insn(
int insn)
3014 if (RUBY_DTRACE_INSN_ENABLED()) {
3018 (*ruby_vm_collect_usage_func_insn)(insn);
3026 vm_collect_usage_operand(
int insn,
int n,
VALUE op)
3028 if (RUBY_DTRACE_INSN_OPERAND_ENABLED()) {
3037 (*ruby_vm_collect_usage_func_operand)(insn, n, op);
3043 vm_collect_usage_register(
int reg,
int isset)
3046 (*ruby_vm_collect_usage_func_register)(reg, isset);