mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
b7aae52851
to count up total calls properly. Some places (especially CALL_METHOD) invoke mjit_exec twice for one method call. It would be problematic when debugging, or possibly it would result in a wrong profiling result. This commit doesn't have impact for performance: * Optcarrot benchmark ** before fps: 59.37757770848619 fps: 56.49998488958699 fps: 59.07900362739362 fps: 58.924749807695996 fps: 57.667905665594894 fps: 57.540021018385254 fps: 59.5518055679647 fps: 55.93831555148311 fps: 57.82685112863262 fps: 59.22391754481736 checksum: 59662 ** after fps: 58.461881158098194 fps: 59.32685183081354 fps: 54.11334310279802 fps: 59.2281560439788 fps: 58.60495705318312 fps: 55.696478648491045 fps: 58.49003452654724 fps: 58.387771929393224 fps: 59.24156772816439 fps: 56.68804731968107 checksum: 59662 * Discourse Your Results: (note for timings- percentile is first, duration is second in millisecs) ** before (without JIT) categories_admin: 50: 16 75: 17 90: 24 99: 37 home_admin: 50: 20 75: 20 90: 24 99: 42 topic_admin: 50: 16 75: 16 90: 18 99: 28 categories: 50: 36 75: 37 90: 45 99: 68 home: 50: 38 75: 40 90: 53 99: 92 topic: 50: 14 75: 15 90: 17 99: 26 ** after (without JIT) categories_admin: 50: 16 75: 16 90: 24 99: 36 home_admin: 50: 19 75: 20 90: 23 99: 41 topic_admin: 50: 16 75: 16 90: 19 99: 33 categories: 50: 35 75: 36 90: 44 99: 61 home: 50: 38 75: 40 90: 52 99: 101 topic: 50: 14 75: 15 90: 15 99: 24 ** before (with JIT) categories_admin: 50: 19 75: 23 90: 29 99: 44 home_admin: 50: 24 75: 26 90: 32 99: 46 topic_admin: 50: 20 75: 22 90: 27 99: 44 categories: 50: 41 75: 43 90: 51 99: 66 home: 50: 46 75: 49 90: 56 99: 68 topic: 50: 18 75: 19 90: 22 99: 31 ** after (with JIT) categories_admin: 50: 18 75: 21 90: 28 99: 42 home_admin: 50: 23 75: 25 90: 31 99: 51 topic_admin: 50: 19 75: 20 90: 24 99: 31 categories: 50: 41 75: 44 90: 52 99: 69 home: 50: 45 75: 48 90: 61 99: 88 topic: 50: 19 75: 20 90: 24 99: 33 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62641 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
214 lines
5.2 KiB
C
214 lines
5.2 KiB
C
/**********************************************************************
|
|
|
|
vm.h -
|
|
|
|
$Author$
|
|
created at: 04/01/01 16:56:59 JST
|
|
|
|
Copyright (C) 2004-2007 Koichi Sasada
|
|
|
|
**********************************************************************/
|
|
|
|
#ifndef RUBY_VM_EXEC_H
|
|
#define RUBY_VM_EXEC_H
|
|
|
|
typedef long OFFSET;
|
|
typedef unsigned long lindex_t;
|
|
typedef VALUE GENTRY;
|
|
typedef rb_iseq_t *ISEQ;
|
|
|
|
#ifdef __GCC__
|
|
/* TODO: machine dependent prefetch instruction */
|
|
#define PREFETCH(pc)
|
|
#else
|
|
#define PREFETCH(pc)
|
|
#endif
|
|
|
|
#if VMDEBUG > 0
|
|
#define debugs printf
|
|
#define DEBUG_ENTER_INSN(insn) \
|
|
rb_vmdebug_debug_print_pre(ec, GET_CFP(), GET_PC());
|
|
|
|
#if OPT_STACK_CACHING
|
|
#define SC_REGS() , reg_a, reg_b
|
|
#else
|
|
#define SC_REGS()
|
|
#endif
|
|
|
|
#define DEBUG_END_INSN() \
|
|
rb_vmdebug_debug_print_post(th, GET_CFP() SC_REGS());
|
|
|
|
#else
|
|
|
|
#define debugs
|
|
#define DEBUG_ENTER_INSN(insn)
|
|
#define DEBUG_END_INSN()
|
|
#endif
|
|
|
|
#define throwdebug if(0)printf
|
|
/* #define throwdebug printf */
|
|
|
|
/************************************************/
|
|
#if defined(DISPATCH_XXX)
|
|
error !
|
|
/************************************************/
|
|
#elif OPT_CALL_THREADED_CODE
|
|
|
|
#define LABEL(x) insn_func_##x
|
|
#define ELABEL(x)
|
|
#define LABEL_PTR(x) &LABEL(x)
|
|
|
|
#define INSN_ENTRY(insn) \
|
|
static rb_control_frame_t * \
|
|
FUNC_FASTCALL(LABEL(insn))(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp) {
|
|
|
|
#define END_INSN(insn) return reg_cfp;}
|
|
|
|
#define NEXT_INSN() return reg_cfp;
|
|
|
|
#define START_OF_ORIGINAL_INSN(x) /* ignore */
|
|
#define DISPATCH_ORIGINAL_INSN(x) return LABEL(x)(ec, reg_cfp);
|
|
|
|
/************************************************/
|
|
#elif OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE
|
|
/* threaded code with gcc */
|
|
|
|
#define LABEL(x) INSN_LABEL_##x
|
|
#define ELABEL(x) INSN_ELABEL_##x
|
|
#define LABEL_PTR(x) RB_GNUC_EXTENSION(&&LABEL(x))
|
|
|
|
#define INSN_ENTRY_SIG(insn) \
|
|
if (0) fprintf(stderr, "exec: %s@(%d, %d)@%s:%d\n", #insn, \
|
|
(int)(reg_pc - reg_cfp->iseq->body->iseq_encoded), \
|
|
(int)(reg_cfp->pc - reg_cfp->iseq->body->iseq_encoded), \
|
|
RSTRING_PTR(rb_iseq_path(reg_cfp->iseq)), \
|
|
(int)(rb_iseq_line_no(reg_cfp->iseq, reg_pc - reg_cfp->iseq->body->iseq_encoded)));
|
|
|
|
#define INSN_DISPATCH_SIG(insn)
|
|
|
|
#define INSN_ENTRY(insn) \
|
|
LABEL(insn): \
|
|
INSN_ENTRY_SIG(insn); \
|
|
|
|
/* dispatcher */
|
|
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && __GNUC__ == 3
|
|
#define DISPATCH_ARCH_DEPEND_WAY(addr) \
|
|
__asm__ __volatile__("jmp *%0;\t# -- inserted by vm.h\t[length = 2]" : : "r" (addr))
|
|
|
|
#else
|
|
#define DISPATCH_ARCH_DEPEND_WAY(addr) \
|
|
/* do nothing */
|
|
#endif
|
|
|
|
/**********************************/
|
|
#if OPT_DIRECT_THREADED_CODE
|
|
|
|
/* for GCC 3.4.x */
|
|
#define TC_DISPATCH(insn) \
|
|
INSN_DISPATCH_SIG(insn); \
|
|
RB_GNUC_EXTENSION_BLOCK(goto *(void const *)GET_CURRENT_INSN()); \
|
|
;
|
|
|
|
#else
|
|
/* token threaded code */
|
|
|
|
#define TC_DISPATCH(insn) \
|
|
DISPATCH_ARCH_DEPEND_WAY(insns_address_table[GET_CURRENT_INSN()]); \
|
|
INSN_DISPATCH_SIG(insn); \
|
|
RB_GNUC_EXTENSION_BLOCK(goto *insns_address_table[GET_CURRENT_INSN()]); \
|
|
rb_bug("tc error");
|
|
|
|
|
|
#endif /* DISPATCH_DIRECT_THREADED_CODE */
|
|
|
|
#define END_INSN(insn) \
|
|
DEBUG_END_INSN(); \
|
|
TC_DISPATCH(insn);
|
|
|
|
#define INSN_DISPATCH() \
|
|
TC_DISPATCH(__START__) \
|
|
{
|
|
|
|
#define END_INSNS_DISPATCH() \
|
|
rb_bug("unknown insn: %"PRIdVALUE, GET_CURRENT_INSN()); \
|
|
} /* end of while loop */ \
|
|
|
|
#define NEXT_INSN() TC_DISPATCH(__NEXT_INSN__)
|
|
|
|
#define START_OF_ORIGINAL_INSN(x) start_of_##x:
|
|
#define DISPATCH_ORIGINAL_INSN(x) goto start_of_##x;
|
|
|
|
/************************************************/
|
|
#else /* no threaded code */
|
|
/* most common method */
|
|
|
|
#define INSN_ENTRY(insn) \
|
|
case BIN(insn):
|
|
|
|
#define END_INSN(insn) \
|
|
DEBUG_END_INSN(); \
|
|
break;
|
|
|
|
#define INSN_DISPATCH() \
|
|
while (1) { \
|
|
switch (GET_CURRENT_INSN()) {
|
|
|
|
#define END_INSNS_DISPATCH() \
|
|
default: \
|
|
SDR(); \
|
|
rb_bug("unknown insn: %ld", GET_CURRENT_INSN()); \
|
|
} /* end of switch */ \
|
|
} /* end of while loop */ \
|
|
|
|
#define NEXT_INSN() goto first
|
|
|
|
#define START_OF_ORIGINAL_INSN(x) start_of_##x:
|
|
#define DISPATCH_ORIGINAL_INSN(x) goto start_of_##x;
|
|
|
|
#endif
|
|
|
|
#ifdef MJIT_HEADER
|
|
#define EXEC_EC_CFP(mjit_enable_p) do { \
|
|
VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH); \
|
|
val = vm_exec(ec, mjit_enable_p); \
|
|
} while (0)
|
|
#else
|
|
#define EXEC_EC_CFP(mjit_enable_p) do { \
|
|
RESTORE_REGS(); \
|
|
NEXT_INSN(); \
|
|
} while (0)
|
|
#endif
|
|
|
|
#define VM_SP_CNT(ec, sp) ((sp) - (ec)->vm_stack)
|
|
|
|
#ifdef MJIT_HEADER
|
|
#define THROW_EXCEPTION(exc) do { \
|
|
ec->errinfo = (VALUE)(exc); \
|
|
EC_JUMP_TAG(ec, ec->tag->state); \
|
|
} while (0)
|
|
#else
|
|
#if OPT_CALL_THREADED_CODE
|
|
#define THROW_EXCEPTION(exc) do { \
|
|
ec->errinfo = (VALUE)(exc); \
|
|
return 0; \
|
|
} while (0)
|
|
#else
|
|
#define THROW_EXCEPTION(exc) return (VALUE)(exc)
|
|
#endif
|
|
#endif
|
|
|
|
#define SCREG(r) (reg_##r)
|
|
|
|
#define VM_DEBUG_STACKOVERFLOW 0
|
|
|
|
#if VM_DEBUG_STACKOVERFLOW
|
|
#define CHECK_VM_STACK_OVERFLOW_FOR_INSN(cfp, margin) \
|
|
WHEN_VM_STACK_OVERFLOWED(cfp, (cfp)->sp, margin) vm_stack_overflow_for_insn()
|
|
#else
|
|
#define CHECK_VM_STACK_OVERFLOW_FOR_INSN(cfp, margin)
|
|
#endif
|
|
|
|
#define INSN_LABEL2(insn, name) INSN_LABEL_ ## insn ## _ ## name
|
|
#define INSN_LABEL(x) INSN_LABEL2(NAME_OF_CURRENT_INSN, x)
|
|
|
|
#endif /* RUBY_VM_EXEC_H */
|