diff options
Diffstat (limited to 'vm_exec.c')
| -rw-r--r-- | vm_exec.c | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/vm_exec.c b/vm_exec.c new file mode 100644 index 0000000000..bd8c170d76 --- /dev/null +++ b/vm_exec.c @@ -0,0 +1,154 @@ +/* -*-c-*- */ +/********************************************************************** + + vm_exec.c - + + $Author$ + + Copyright (C) 2004-2007 Koichi Sasada + +**********************************************************************/ + +#include <math.h> + +#if USE_YJIT || USE_ZJIT +// The number of instructions executed on vm_exec_core. --yjit-stats and --zjit-stats use this. +uint64_t rb_vm_insn_count = 0; +#endif + +#if VM_COLLECT_USAGE_DETAILS +static void vm_analysis_insn(int insn); +#endif + +#if VMDEBUG > 0 +#define DECL_SC_REG(type, r, reg) register type reg_##r + +#elif defined(__GNUC__) && defined(__x86_64__) +#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("r" reg) + +#elif defined(__GNUC__) && defined(__i386__) +#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("e" reg) + +#elif defined(__GNUC__) && (defined(__powerpc64__) || defined(__POWERPC__)) +#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("r" reg) + +#elif defined(__GNUC__) && defined(__aarch64__) +#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("x" reg) + +#else +#define DECL_SC_REG(type, r, reg) register type reg_##r +#endif +/* #define DECL_SC_REG(r, reg) VALUE reg_##r */ + +#if !OPT_CALL_THREADED_CODE +static VALUE +vm_exec_core(rb_execution_context_t *ec) +{ +#if defined(__GNUC__) && defined(__i386__) + DECL_SC_REG(const VALUE *, pc, "di"); + DECL_SC_REG(rb_control_frame_t *, cfp, "si"); +#define USE_MACHINE_REGS 1 + +#elif defined(__GNUC__) && defined(__x86_64__) + DECL_SC_REG(const VALUE *, pc, "14"); + DECL_SC_REG(rb_control_frame_t *, cfp, "15"); +#define USE_MACHINE_REGS 1 + +#elif defined(__GNUC__) && (defined(__powerpc64__) || defined(__POWERPC__)) + DECL_SC_REG(const VALUE *, pc, "14"); + DECL_SC_REG(rb_control_frame_t *, cfp, "15"); +#define USE_MACHINE_REGS 1 + +#elif defined(__GNUC__) && defined(__aarch64__) + DECL_SC_REG(const VALUE *, pc, "19"); + DECL_SC_REG(rb_control_frame_t *, cfp, "20"); +#define USE_MACHINE_REGS 1 + +#else + register rb_control_frame_t *reg_cfp; + const VALUE *reg_pc; +#define USE_MACHINE_REGS 0 + +#endif + +#if USE_MACHINE_REGS + +#undef RESTORE_REGS +#define RESTORE_REGS() \ +{ \ + VM_REG_CFP = ec->cfp; \ + reg_pc = reg_cfp->pc; \ +} + +#undef VM_REG_PC +#define VM_REG_PC reg_pc +#undef GET_PC +#define GET_PC() (reg_pc) +#undef SET_PC +#define SET_PC(x) (reg_cfp->pc = VM_REG_PC = (x)) +#endif + +#if OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE +#include "vmtc.inc" + if (UNLIKELY(ec == 0)) { + return (VALUE)insns_address_table; + } +#endif + reg_cfp = ec->cfp; + reg_pc = reg_cfp->pc; + + first: + INSN_DISPATCH(); +/*****************/ + #include "vm.inc" +/*****************/ + END_INSNS_DISPATCH(); + + /* unreachable */ + rb_bug("vm_eval: unreachable"); + goto first; +} + +const void ** +rb_vm_get_insns_address_table(void) +{ + return (const void **)vm_exec_core(0); +} + +#else /* OPT_CALL_THREADED_CODE */ + +#include "vm.inc" +#include "vmtc.inc" + +const void ** +rb_vm_get_insns_address_table(void) +{ + return (const void **)insns_address_table; +} + +static VALUE +vm_exec_core(rb_execution_context_t *ec) +{ + register rb_control_frame_t *reg_cfp = ec->cfp; + rb_thread_t *th; + + while (1) { + reg_cfp = ((rb_insn_func_t) (*GET_PC()))(ec, reg_cfp); + + if (UNLIKELY(reg_cfp == 0)) { + break; + } + } + + if (!UNDEF_P((th = rb_ec_thread_ptr(ec))->retval)) { + VALUE ret = th->retval; + th->retval = Qundef; + return ret; + } + else { + VALUE err = ec->errinfo; + ec->errinfo = Qnil; + return err; + } +} +#endif |
