类 RubyVM

RubyVM 模块仅在 MRI 上存在。RubyVM 在其他 Ruby 实现(如 JRuby 和 TruffleRuby)中未定义。

RubyVM 模块提供对 MRI 内部的一些访问。此模块仅用于非常有限的目的,例如调试、原型设计和研究。普通用户不得使用它。此模块在不同的 Ruby 实现之间不可移植。

常量

DEFAULT_PARAMS

DEFAULT_PARAMS 此常量公开 VM 的默认参数。请注意,更改这些值不会影响 VM 执行。规范不稳定,您不应该依赖此值。当然,此常量是 MRI 特定的。

INSTRUCTION_NAMES

INSTRUCTION_NAMES MRI 中字节码指令名称的列表。此常量是 MRI 特定的。

OPTS

OPTS 一个 Array 的 VM 构建选项。此常量是 MRI 特定的。

公共类方法

keep_script_lines → true 或 false 点击切换源代码

返回当前 keep_script_lines 状态。现在它只返回 truefalse,但在将来可能会返回其他对象。

请注意,这是一个用于 Ruby 内部使用、调试和研究的 API。不要将其用于任何其他目的。兼容性无法保证。

static VALUE
vm_keep_script_lines(VALUE self)
{
    return RBOOL(ruby_vm_keep_script_lines);
}
keep_script_lines = true / false 点击切换源代码

它设置 keep_script_lines 标志。如果设置了该标志,所有加载的脚本都将在解释器进程中记录。

请注意,这是一个用于 Ruby 内部使用、调试和研究的 API。不要将其用于任何其他目的。兼容性无法保证。

static VALUE
vm_keep_script_lines_set(VALUE self, VALUE flags)
{
    ruby_vm_keep_script_lines = RTEST(flags);
    return flags;
}
stat → Hash 点击切换源代码
stat(hsh) → hsh
stat(Symbol) → Numeric

返回一个 Hash,其中包含 VM 内部实现相关的计数器。

此哈希包含有关方法/常量缓存的信息

{
  :constant_cache_invalidations=>2,
  :constant_cache_misses=>14,
  :global_cvar_state=>27
}

如果启用了 USE_DEBUG_COUNTER,则将包含调试计数器。

哈希的内容是实现特定的,将来可能会改变。

此方法仅适用于 C Ruby。

static VALUE
vm_stat(int argc, VALUE *argv, VALUE self)
{
    static VALUE sym_constant_cache_invalidations, sym_constant_cache_misses, sym_global_cvar_state, sym_next_shape_id;
    static VALUE sym_shape_cache_size;
    VALUE arg = Qnil;
    VALUE hash = Qnil, key = Qnil;

    if (rb_check_arity(argc, 0, 1) == 1) {
        arg = argv[0];
        if (SYMBOL_P(arg))
            key = arg;
        else if (RB_TYPE_P(arg, T_HASH))
            hash = arg;
        else
            rb_raise(rb_eTypeError, "non-hash or symbol given");
    }
    else {
        hash = rb_hash_new();
    }

#define S(s) sym_##s = ID2SYM(rb_intern_const(#s))
    S(constant_cache_invalidations);
    S(constant_cache_misses);
        S(global_cvar_state);
    S(next_shape_id);
    S(shape_cache_size);
#undef S

#define SET(name, attr) \
    if (key == sym_##name) \
        return SERIALT2NUM(attr); \
    else if (hash != Qnil) \
        rb_hash_aset(hash, sym_##name, SERIALT2NUM(attr));

    SET(constant_cache_invalidations, ruby_vm_constant_cache_invalidations);
    SET(constant_cache_misses, ruby_vm_constant_cache_misses);
    SET(global_cvar_state, ruby_vm_global_cvar_state);
    SET(next_shape_id, (rb_serial_t)GET_SHAPE_TREE()->next_shape_id);
    SET(shape_cache_size, (rb_serial_t)GET_SHAPE_TREE()->cache_size);
#undef SET

#if USE_DEBUG_COUNTER
    ruby_debug_counter_show_at_exit(FALSE);
    for (size_t i = 0; i < RB_DEBUG_COUNTER_MAX; i++) {
        const VALUE name = rb_sym_intern_ascii_cstr(rb_debug_counter_names[i]);
        const VALUE boxed_value = SIZET2NUM(rb_debug_counter[i]);

        if (key == name) {
            return boxed_value;
        }
        else if (hash != Qnil) {
            rb_hash_aset(hash, name, boxed_value);
        }
    }
#endif

    if (!NIL_P(key)) { /* matched key should return above */
        rb_raise(rb_eArgError, "unknown key: %"PRIsVALUE, rb_sym2str(key));
    }

    return hash;
}