class RubyVM::InstructionSequence
InstructionSequence 类表示 MRI 中使用的虚拟机编译后的指令序列。并非所有 Ruby 的实现都会实现这个类,并且对于实现了它的实现,定义的方法以及方法的行为可能在任何版本中都会发生变化。
有了它,你可以获得构成方法或 proc 的指令的句柄,将 Ruby 代码字符串编译成 VM 指令,并将指令序列反汇编成字符串以便于检查。如果你想了解 YARV 的工作原理,它会很有用,但它也允许你控制 Ruby iseq 编译器的各种设置。
你可以在 Ruby 源代码的 insns.def 文件中找到 VM 指令的源代码。
指令序列的结果几乎肯定会随着 Ruby 的变化而变化,因此此文档中的示例输出可能与你看到的不同。
当然,这个类是 MRI 特定的。
Public Class Methods
Source
static VALUE
iseqw_s_compile(int argc, VALUE *argv, VALUE self)
{
return iseqw_s_compile_parser(argc, argv, self, rb_ruby_prism_p());
}
接受 source,它可以是 Ruby 代码字符串,也可以是包含 Ruby 源代码的已打开的 File 对象。
可选地接受 file、path 和 line,它们描述了 source 中 Ruby 代码的文件路径、真实路径和首行号,这些是附加到返回的 iseq 的元数据。
file 用于 __FILE__ 和异常回溯。path 用于 require_relative 的基础。建议这些应该具有相同的完整路径。
options,可以是 true、false 或 Hash,用于修改 Ruby iseq 编译器默认行为。
有关有效编译选项的详细信息,请参阅 ::compile_option=。
RubyVM::InstructionSequence.compile("a = 1 + 2") #=> <RubyVM::InstructionSequence:<compiled>@<compiled>> path = "test.rb" RubyVM::InstructionSequence.compile(File.read(path), path, File.expand_path(path)) #=> <RubyVM::InstructionSequence:<compiled>@test.rb:1> file = File.open("test.rb") RubyVM::InstructionSequence.compile(file) #=> <RubyVM::InstructionSequence:<compiled>@<compiled>:1> path = File.expand_path("test.rb") RubyVM::InstructionSequence.compile(File.read(path), path, path) #=> <RubyVM::InstructionSequence:<compiled>@/absolute/path/to/test.rb:1>
Source
static VALUE
iseqw_s_compile_file(int argc, VALUE *argv, VALUE self)
{
VALUE file, opt = Qnil;
VALUE parser, f, exc = Qnil, ret;
rb_ast_t *ast;
VALUE ast_value;
rb_compile_option_t option;
int i;
i = rb_scan_args(argc, argv, "1*:", &file, NULL, &opt);
if (i > 1+NIL_P(opt)) rb_error_arity(argc, 1, 2);
switch (i) {
case 2: opt = argv[--i];
}
FilePathValue(file);
file = rb_fstring(file); /* rb_io_t->pathv gets frozen anyways */
f = rb_file_open_str(file, "r");
rb_execution_context_t *ec = GET_EC();
VALUE v = rb_vm_push_frame_fname(ec, file);
parser = rb_parser_new();
rb_parser_set_context(parser, NULL, FALSE);
ast_value = rb_parser_load_file(parser, file);
ast = rb_ruby_ast_data_get(ast_value);
if (!ast->body.root) exc = GET_EC()->errinfo;
rb_io_close(f);
if (!ast->body.root) {
rb_ast_dispose(ast);
rb_exc_raise(exc);
}
make_compile_option(&option, opt);
ret = iseqw_new(rb_iseq_new_with_opt(ast_value, rb_fstring_lit("<main>"),
file,
rb_realpath_internal(Qnil, file, 1),
1, NULL, 0, ISEQ_TYPE_TOP, &option,
Qnil));
rb_ast_dispose(ast);
RB_GC_GUARD(ast_value);
rb_vm_pop_frame(ec);
RB_GC_GUARD(v);
return ret;
}
接受 file,一个包含 Ruby 源文件位置的 String,读取、解析和编译该文件,并返回 iseq,即带有源位置元数据设置的已编译 InstructionSequence。
可选地接受 options,可以是 true、false 或 Hash,用于修改 Ruby iseq 编译器默认行为。
有关有效编译选项的详细信息,请参阅 ::compile_option=。
# /tmp/hello.rb puts "Hello, world!" # elsewhere RubyVM::InstructionSequence.compile_file("/tmp/hello.rb") #=> <RubyVM::InstructionSequence:<main>@/tmp/hello.rb>
Source
static VALUE
iseqw_s_compile_file_prism(int argc, VALUE *argv, VALUE self)
{
VALUE file, opt = Qnil, ret;
rb_compile_option_t option;
int i;
i = rb_scan_args(argc, argv, "1*:", &file, NULL, &opt);
if (i > 1+NIL_P(opt)) rb_error_arity(argc, 1, 2);
switch (i) {
case 2: opt = argv[--i];
}
FilePathValue(file);
file = rb_fstring(file); /* rb_io_t->pathv gets frozen anyways */
rb_execution_context_t *ec = GET_EC();
VALUE v = rb_vm_push_frame_fname(ec, file);
pm_parse_result_t result = { 0 };
result.options.line = 1;
result.node.coverage_enabled = 1;
VALUE script_lines;
VALUE error = pm_load_parse_file(&result, file, ruby_vm_keep_script_lines ? &script_lines : NULL);
if (error == Qnil) {
make_compile_option(&option, opt);
int error_state;
rb_iseq_t *iseq = pm_iseq_new_with_opt(&result.node, rb_fstring_lit("<main>"),
file,
rb_realpath_internal(Qnil, file, 1),
1, NULL, 0, ISEQ_TYPE_TOP, &option, &error_state);
pm_parse_result_free(&result);
if (error_state) {
RUBY_ASSERT(iseq == NULL);
rb_jump_tag(error_state);
}
ret = iseqw_new(iseq);
rb_vm_pop_frame(ec);
RB_GC_GUARD(v);
return ret;
}
else {
pm_parse_result_free(&result);
rb_vm_pop_frame(ec);
RB_GC_GUARD(v);
rb_exc_raise(error);
}
}
接受 file,一个包含 Ruby 源文件位置的 String,读取、解析和编译该文件,并返回 iseq,即带有源位置元数据设置的已编译 InstructionSequence。它使用 prism 进行解析和编译。
可选地接受 options,可以是 true、false 或 Hash,用于修改 Ruby iseq 编译器默认行为。
有关有效编译选项的详细信息,请参阅 ::compile_option=。
# /tmp/hello.rb puts "Hello, world!" # elsewhere RubyVM::InstructionSequence.compile_file_prism("/tmp/hello.rb") #=> <RubyVM::InstructionSequence:<main>@/tmp/hello.rb>
Source
static VALUE
iseqw_s_compile_option_get(VALUE self)
{
return make_compile_option_value(&COMPILE_OPTION_DEFAULT);
}
返回 Ruby iseq 编译器使用的默认选项的哈希。
有关详细信息,请参阅 InstructionSequence.compile_option=。
Source
static VALUE
iseqw_s_compile_option_set(VALUE self, VALUE opt)
{
rb_compile_option_t option;
make_compile_option(&option, opt);
COMPILE_OPTION_DEFAULT = option;
return opt;
}
设置 Ruby iseq 编译器中各种优化的默认值。
options 的可能值包括 true,表示启用所有选项;false,表示禁用所有选项;以及 nil,表示不更改任何选项。
你也可以传递一个要更改的 options Hash,哈希中不存在的任何选项都将保持不变。
可以设置为 true 或 false 的可能选项名称(它们是 options 的键)包括:
-
:inline_const_cache -
:instructions_unification -
:operands_unification -
:peephole_optimization -
:specialized_instruction -
:tailcall_optimization
此外,:debug_level 可以设置为一个整数。
这些默认选项可以通过将上述任何值作为 options 参数传递给 ::new、::compile 和 ::compile_file 来为 iseq 编译器单次运行覆盖。
Source
static VALUE
iseqw_s_compile_parsey(int argc, VALUE *argv, VALUE self)
{
return iseqw_s_compile_parser(argc, argv, self, false);
}
接受 source,它可以是 Ruby 代码字符串,也可以是包含 Ruby 源代码的已打开的 File 对象。它使用 parse.y 进行解析和编译。
可选地接受 file、path 和 line,它们描述了 source 中 Ruby 代码的文件路径、真实路径和首行号,这些是附加到返回的 iseq 的元数据。
file 用于 __FILE__ 和异常回溯。path 用于 require_relative 的基础。建议这些应该具有相同的完整路径。
options,可以是 true、false 或 Hash,用于修改 Ruby iseq 编译器默认行为。
有关有效编译选项的详细信息,请参阅 ::compile_option=。
RubyVM::InstructionSequence.compile_parsey("a = 1 + 2") #=> <RubyVM::InstructionSequence:<compiled>@<compiled>> path = "test.rb" RubyVM::InstructionSequence.compile_parsey(File.read(path), path, File.expand_path(path)) #=> <RubyVM::InstructionSequence:<compiled>@test.rb:1> file = File.open("test.rb") RubyVM::InstructionSequence.compile_parsey(file) #=> <RubyVM::InstructionSequence:<compiled>@<compiled>:1> path = File.expand_path("test.rb") RubyVM::InstructionSequence.compile_parsey(File.read(path), path, path) #=> <RubyVM::InstructionSequence:<compiled>@/absolute/path/to/test.rb:1>
Source
static VALUE
iseqw_s_compile_prism(int argc, VALUE *argv, VALUE self)
{
return iseqw_s_compile_parser(argc, argv, self, true);
}
接受 source,它可以是 Ruby 代码字符串,也可以是包含 Ruby 源代码的已打开的 File 对象。它使用 prism 进行解析和编译。
可选地接受 file、path 和 line,它们描述了 source 中 Ruby 代码的文件路径、真实路径和首行号,这些是附加到返回的 iseq 的元数据。
file 用于 __FILE__ 和异常回溯。path 用于 require_relative 的基础。建议这些应该具有相同的完整路径。
options,可以是 true、false 或 Hash,用于修改 Ruby iseq 编译器默认行为。
有关有效编译选项的详细信息,请参阅 ::compile_option=。
RubyVM::InstructionSequence.compile_prism("a = 1 + 2") #=> <RubyVM::InstructionSequence:<compiled>@<compiled>> path = "test.rb" RubyVM::InstructionSequence.compile_prism(File.read(path), path, File.expand_path(path)) #=> <RubyVM::InstructionSequence:<compiled>@test.rb:1> file = File.open("test.rb") RubyVM::InstructionSequence.compile_prism(file) #=> <RubyVM::InstructionSequence:<compiled>@<compiled>:1> path = File.expand_path("test.rb") RubyVM::InstructionSequence.compile_prism(File.read(path), path, path) #=> <RubyVM::InstructionSequence:<compiled>@/absolute/path/to/test.rb:1>
Source
static VALUE
iseqw_s_disasm(VALUE klass, VALUE body)
{
VALUE iseqw = iseqw_s_of(klass, body);
return NIL_P(iseqw) ? Qnil : rb_iseq_disasm(iseqw_check(iseqw));
}
接受 body,一个 Method 或 Proc 对象,并返回一个包含 body 的人类可读指令的 String。
对于 Method 对象
# /tmp/method.rb def hello puts "hello, world" end puts RubyVM::InstructionSequence.disasm(method(:hello))
生成
== disasm: <RubyVM::InstructionSequence:hello@/tmp/method.rb>============ 0000 trace 8 ( 1) 0002 trace 1 ( 2) 0004 putself 0005 putstring "hello, world" 0007 send :puts, 1, nil, 8, <ic:0> 0013 trace 16 ( 3) 0015 leave ( 2)
对于 Proc 对象
# /tmp/proc.rb p = proc { num = 1 + 2 } puts RubyVM::InstructionSequence.disasm(p)
生成
== disasm: <RubyVM::InstructionSequence:block in <main>@/tmp/proc.rb>=== == catch table | catch type: redo st: 0000 ed: 0012 sp: 0000 cont: 0000 | catch type: next st: 0000 ed: 0012 sp: 0000 cont: 0012 |------------------------------------------------------------------------ local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1) [ 2] num 0000 trace 1 ( 1) 0002 putobject 1 0004 putobject 2 0006 opt_plus <ic:1> 0008 dup 0009 setlocal num, 0 0012 leave
Source
static VALUE
iseqw_s_disasm(VALUE klass, VALUE body)
{
VALUE iseqw = iseqw_s_of(klass, body);
return NIL_P(iseqw) ? Qnil : rb_iseq_disasm(iseqw_check(iseqw));
}
接受 body,一个 Method 或 Proc 对象,并返回一个包含 body 的人类可读指令的 String。
对于 Method 对象
# /tmp/method.rb def hello puts "hello, world" end puts RubyVM::InstructionSequence.disasm(method(:hello))
生成
== disasm: <RubyVM::InstructionSequence:hello@/tmp/method.rb>============ 0000 trace 8 ( 1) 0002 trace 1 ( 2) 0004 putself 0005 putstring "hello, world" 0007 send :puts, 1, nil, 8, <ic:0> 0013 trace 16 ( 3) 0015 leave ( 2)
对于 Proc 对象
# /tmp/proc.rb p = proc { num = 1 + 2 } puts RubyVM::InstructionSequence.disasm(p)
生成
== disasm: <RubyVM::InstructionSequence:block in <main>@/tmp/proc.rb>=== == catch table | catch type: redo st: 0000 ed: 0012 sp: 0000 cont: 0000 | catch type: next st: 0000 ed: 0012 sp: 0000 cont: 0012 |------------------------------------------------------------------------ local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1) [ 2] num 0000 trace 1 ( 1) 0002 putobject 1 0004 putobject 2 0006 opt_plus <ic:1> 0008 dup 0009 setlocal num, 0 0012 leave
Source
static VALUE
iseqw_s_load_from_binary(VALUE self, VALUE str)
{
return iseqw_new(rb_iseq_ibf_load(str));
}
从 RubyVM::InstructionSequence.to_binary 创建的二进制格式 String 对象加载 iseq 对象。
此加载器没有验证器,因此加载损坏/修改的二进制文件会导致严重问题。
你不应该加载他人提供的二进制数据。你应该使用你自己翻译的二进制数据。
Source
static VALUE
iseqw_s_load_from_binary_extra_data(VALUE self, VALUE str)
{
return rb_iseq_ibf_load_extra_data(str);
}
加载嵌入到二进制格式 String 对象中的额外数据。
Source
static VALUE
iseqw_s_compile(int argc, VALUE *argv, VALUE self)
{
return iseqw_s_compile_parser(argc, argv, self, rb_ruby_prism_p());
}
接受 source,它可以是 Ruby 代码字符串,也可以是包含 Ruby 源代码的已打开的 File 对象。
可选地接受 file、path 和 line,它们描述了 source 中 Ruby 代码的文件路径、真实路径和首行号,这些是附加到返回的 iseq 的元数据。
file 用于 __FILE__ 和异常回溯。path 用于 require_relative 的基础。建议这些应该具有相同的完整路径。
options,可以是 true、false 或 Hash,用于修改 Ruby iseq 编译器默认行为。
有关有效编译选项的详细信息,请参阅 ::compile_option=。
RubyVM::InstructionSequence.compile("a = 1 + 2") #=> <RubyVM::InstructionSequence:<compiled>@<compiled>> path = "test.rb" RubyVM::InstructionSequence.compile(File.read(path), path, File.expand_path(path)) #=> <RubyVM::InstructionSequence:<compiled>@test.rb:1> file = File.open("test.rb") RubyVM::InstructionSequence.compile(file) #=> <RubyVM::InstructionSequence:<compiled>@<compiled>:1> path = File.expand_path("test.rb") RubyVM::InstructionSequence.compile(File.read(path), path, path) #=> <RubyVM::InstructionSequence:<compiled>@/absolute/path/to/test.rb:1>
Source
static VALUE
iseqw_s_of(VALUE klass, VALUE body)
{
const rb_iseq_t *iseq = NULL;
if (rb_frame_info_p(body)) {
iseq = rb_get_iseq_from_frame_info(body);
}
else if (rb_obj_is_proc(body)) {
iseq = vm_proc_iseq(body);
if (!rb_obj_is_iseq((VALUE)iseq)) {
iseq = NULL;
}
}
else if (rb_obj_is_method(body)) {
iseq = rb_method_iseq(body);
}
else if (rb_typeddata_is_instance_of(body, &iseqw_data_type)) {
return body;
}
return iseq ? iseqw_new(iseq) : Qnil;
}
返回包含给定 proc 或方法的指令序列。
例如,使用 irb
# a proc
> p = proc { num = 1 + 2 }
> RubyVM::InstructionSequence.of(p)
> #=> <RubyVM::InstructionSequence:block in irb_binding@(irb)>
# for a method
> def foo(bar); puts bar; end
> RubyVM::InstructionSequence.of(method(:foo))
> #=> <RubyVM::InstructionSequence:foo@(irb)>
# /tmp/iseq_of.rb
def hello
puts "hello, world"
end
$a_global_proc = proc { str = 'a' + 'b' }
# in irb
> require '/tmp/iseq_of.rb'
# first the method hello
> RubyVM::InstructionSequence.of(method(:hello))
> #=> #<RubyVM::InstructionSequence:0x007fb73d7cb1d0>
# then the global proc
> RubyVM::InstructionSequence.of($a_global_proc)
> #=> #<RubyVM::InstructionSequence:0x007fb73d7caf78>
Public Instance Methods
Source
static VALUE
iseqw_absolute_path(VALUE self)
{
return rb_iseq_realpath(iseqw_check(self));
}
返回此指令序列的绝对路径。
如果 iseq 是从字符串评估的,则为 nil。
例如,使用 ::compile_file
# /tmp/method.rb
def hello
puts "hello, world"
end
# in irb
> iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
> iseq.absolute_path #=> /tmp/method.rb
Source
static VALUE
iseqw_base_label(VALUE self)
{
return rb_iseq_base_label(iseqw_check(self));
}
返回此指令序列的基本标签。
例如,使用 irb
iseq = RubyVM::InstructionSequence.compile('num = 1 + 2') #=> <RubyVM::InstructionSequence:<compiled>@<compiled>> iseq.base_label #=> "<compiled>"
# /tmp/method.rb
def hello
puts "hello, world"
end
# in irb
> iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
> iseq.base_label #=> <main>
Source
static VALUE
iseqw_disasm(VALUE self)
{
return rb_iseq_disasm(iseqw_check(self));
}
以人类可读形式将指令序列作为 String 返回。
puts RubyVM::InstructionSequence.compile('1 + 2').disasm
生成
== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>========== 0000 trace 1 ( 1) 0002 putobject 1 0004 putobject 2 0006 opt_plus <ic:1> 0008 leave
以人类可读形式将指令序列作为 String 返回。
puts RubyVM::InstructionSequence.compile('1 + 2').disasm
生成
== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>========== 0000 trace 1 ( 1) 0002 putobject 1 0004 putobject 2 0006 opt_plus <ic:1> 0008 leave
Source
static VALUE
iseqw_each_child(VALUE self)
{
const rb_iseq_t *iseq = iseqw_check(self);
iseq_iterate_children(iseq, yield_each_children, NULL);
return self;
}
迭代所有直接子指令序列。迭代顺序是实现/版本定义的,因此人们不应依赖于顺序。
Source
static VALUE
iseqw_eval(VALUE self)
{
const rb_iseq_t *iseq = iseqw_check(self);
if (0 == ISEQ_BODY(iseq)->iseq_size) {
rb_raise(rb_eTypeError, "attempt to evaluate dummy InstructionSequence");
}
return rb_iseq_eval(iseq, rb_current_box());
}
评估指令序列并返回结果。
RubyVM::InstructionSequence.compile("1 + 2").eval #=> 3
Source
static VALUE
iseqw_first_lineno(VALUE self)
{
return rb_iseq_first_lineno(iseqw_check(self));
}
返回加载指令序列的首个源行号。
例如,使用 irb
iseq = RubyVM::InstructionSequence.compile('num = 1 + 2') #=> <RubyVM::InstructionSequence:<compiled>@<compiled>> iseq.first_lineno #=> 1
Source
static VALUE
iseqw_inspect(VALUE self)
{
const rb_iseq_t *iseq = iseqw_check(self);
const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
VALUE klass = rb_class_name(rb_obj_class(self));
if (!body->location.label) {
return rb_sprintf("#<%"PRIsVALUE": uninitialized>", klass);
}
else {
return rb_sprintf("<%"PRIsVALUE":%"PRIsVALUE"@%"PRIsVALUE":%d>",
klass,
body->location.label, rb_iseq_path(iseq),
FIX2INT(rb_iseq_first_lineno(iseq)));
}
}
Source
static VALUE
iseqw_label(VALUE self)
{
return rb_iseq_label(iseqw_check(self));
}
返回此指令序列的标签。
如果是顶层,则为 <main>;如果是从字符串评估的,则为 <compiled>。
例如,使用 irb
iseq = RubyVM::InstructionSequence.compile('num = 1 + 2') #=> <RubyVM::InstructionSequence:<compiled>@<compiled>> iseq.label #=> "<compiled>"
# /tmp/method.rb
def hello
puts "hello, world"
end
# in irb
> iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
> iseq.label #=> <main>
Source
static VALUE
iseqw_path(VALUE self)
{
return rb_iseq_path(iseqw_check(self));
}
返回此指令序列的路径。
如果 iseq 是从字符串评估的,则为 <compiled>。
例如,使用 irb
iseq = RubyVM::InstructionSequence.compile('num = 1 + 2') #=> <RubyVM::InstructionSequence:<compiled>@<compiled>> iseq.path #=> "<compiled>"
# /tmp/method.rb
def hello
puts "hello, world"
end
# in irb
> iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
> iseq.path #=> /tmp/method.rb
Source
static VALUE
iseqw_script_lines(VALUE self)
{
const rb_iseq_t *iseq = iseqw_check(self);
return ISEQ_BODY(iseq)->variable.script_lines;
}
如果可用,则返回记录的脚本行。脚本行不限于 iseq 范围,而是源文件的全部行。
请注意,这是 ruby 内部使用、调试和研究的 API。请勿将其用于任何其他目的。不保证兼容性。
Source
static VALUE
iseqw_to_a(VALUE self)
{
const rb_iseq_t *iseq = iseqw_check(self);
return iseq_data_to_ary(iseq);
}
返回一个包含 14 个元素的 Array,表示指令序列,包含以下数据:
- magic
-
标识数据格式的字符串。始终为
YARVInstructionSequence/SimpleDataFormat。 - major_version
-
指令序列的主版本。
- minor_version
-
指令序列的次版本。
- format_type
-
标识数据格式的数字。始终为 1。
- misc
-
包含以下内容的哈希:
:arg_size-
方法或块接受的总参数数量(如果 iseq 不代表方法或块,则为 0)
:local_size-
局部变量的数量 + 1
:stack_max-
用于计算引发
SystemStackError的堆栈深度。
label-
此指令序列所属的上下文(块、方法、类、模块等)的名称。
如果是顶层,则为
<main>;如果是从字符串评估的,则为<compiled>。 path-
指令序列加载的 Ruby 文件的相对路径。
如果 iseq 是从字符串评估的,则为
<compiled>。 absolute_path-
指令序列加载的 Ruby 文件的绝对路径。
如果 iseq 是从字符串评估的,则为
nil。 first_lineno-
加载指令序列的首个源行号。
- type
-
指令序列的类型。
有效值为
:top、:method、:block、:class、:rescue、:ensure、:eval、:main和plain。 - locals
-
包含所有参数和局部变量名称(作为符号)的数组。
- 参数
-
包含参数信息的
Hash对象。有关这些值的更多信息可以在
vm_core.h中找到。 - catch_table
-
异常和控制流运算符(rescue、next、redo、break 等)列表。
- bytecode
-
包含构成指令序列主体的指令名称和操作数的数组。
请注意,此格式是 MRI 特定的,并且依赖于版本。
Source
static VALUE
iseqw_to_binary(int argc, VALUE *argv, VALUE self)
{
VALUE opt = !rb_check_arity(argc, 0, 1) ? Qnil : argv[0];
return rb_iseq_ibf_dump(iseqw_check(self), opt);
}
返回序列化的 iseq 二进制格式数据作为 String 对象。相应的 iseq 对象由 RubyVM::InstructionSequence.load_from_binary() 方法创建。
String extra_data 将随二进制数据一起保存。你可以使用 RubyVM::InstructionSequence.load_from_binary_extra_data(binary) 访问此数据。
请注意,转换后的二进制数据不可移植。你不能将此二进制数据移动到另一台机器。你不能使用由另一版本/另一架构的 Ruby 创建的二进制数据。
Source
static VALUE
iseqw_trace_points(VALUE self)
{
const rb_iseq_t *iseq = iseqw_check(self);
const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
unsigned int i;
VALUE ary = rb_ary_new();
for (i=0; i<body->insns_info.size; i++) {
const struct iseq_insn_info_entry *entry = &body->insns_info.body[i];
if (entry->events) {
push_event_info(iseq, entry->events, entry->line_no, ary);
}
}
return ary;
}
返回指令序列中的跟踪点。返回 [行号, 事件符号] 对的数组。