RubyVM中的putspecialobject操作码如何工作?

时间:2009-05-22 01:49:37

标签: ruby opcode vm-implementation

我正在研究RubyVM的实现,并且我已经搜索了所有关于操作码的文档,但无济于事。

如果有人特别知道putspecialobject操作码是如何工作的,或者甚至只是链接到一些完整的文档,我会非常感激!

1 个答案:

答案 0 :(得分:4)

来自insns.def:

DEFINE_INSN putspecialobject (rb_num_t value_type) () (VALUE val)
{
  switch (value_type) {
    case VM_SPECIAL_OBJECT_VMCORE:
      val = rb_mRubyVMFrozenCore;
      break;
    case VM_SPECIAL_OBJECT_CBASE:
      val = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP());
      break;
    default:
      rb_bug("putspecialobject insn: unknown value_type");
  }
}

其中:

VM_SPECIAL_OBJECT_VMCORE = 1
VM_SPECIAL_OBJECT_CBASE  = 2

换句话说,如果参数为1,则会在堆栈上推送rb_mRubyVMFrozenCore,这是在VM启动早期创建的对象,它将某些语言功能实现为方法:

set_method_alias(klass,:new,:old)             alias new old
set_variable_alias(:$new,:$old)               alias $new $old
undef_method(klass,:foo)                      undef foo
define_method(klass,:foo,&block)              def foo ... end
define_singleton_method(obj,:foo,&block)      def obj.foo ... end
set_postexe(&block)                           END { ... }

如果参数为2,则在堆栈上推送当前类上下文的类/模块。这是解决常量并且defalias生效的词法范围。它也是作为'klass'传递给上述方法的类。

所以

def foo
  ...
end

编译到:

[:putspecialobject, 1],
[:putspecialobject, 2],
[:putobject, :foo],
[:putiseq, [...]],
[:send, :"core#define_method", 3, nil, 0, nil]

这就像我可以进行逆向工程一样,这对于这段代码来说并不容易。