diff options
Diffstat (limited to 'lib/ruby_vm/mjit/insn_compiler.rb')
-rw-r--r-- | lib/ruby_vm/mjit/insn_compiler.rb | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/lib/ruby_vm/mjit/insn_compiler.rb b/lib/ruby_vm/mjit/insn_compiler.rb new file mode 100644 index 0000000000..9c3e2f2a95 --- /dev/null +++ b/lib/ruby_vm/mjit/insn_compiler.rb @@ -0,0 +1,51 @@ +module RubyVM::MJIT + # ec: rdi + # cfp: rsi + # sp: rbx + # scratch regs: rax + class InsnCompiler + # @param jit [RubyVM::MJIT::JITState] + # @param ctx [RubyVM::MJIT::Context] + # @param asm [RubyVM::MJIT::X86Assembler] + def putnil(jit, ctx, asm) + asm.mov([SP], Qnil) + ctx.stack_size += 1 + KeepCompiling + end + + # @param jit [RubyVM::MJIT::JITState] + # @param ctx [RubyVM::MJIT::Context] + # @param asm [RubyVM::MJIT::X86Assembler] + def leave(jit, ctx, asm) + assert_eq!(ctx.stack_size, 1) + + asm.comment("RUBY_VM_CHECK_INTS(ec)") + asm.mov(:eax, [EC, C.rb_execution_context_t.offsetof(:interrupt_flag)]) + asm.test(:eax, :eax) + asm.jz(not_interrupted = asm.new_label(:not_interrupted)) + Compiler.compile_exit(jit, ctx, asm) # TODO: use ocb + asm.write_label(not_interrupted) + + asm.comment("pop stack frame") + asm.add(CFP, C.rb_control_frame_t.size) # cfp = cfp + 1 + asm.mov([EC, C.rb_execution_context_t.offsetof(:cfp)], CFP) # ec->cfp = cfp + + # Return a value + asm.mov(:rax, [SP]) + + # Restore callee-saved registers + asm.pop(SP) + + asm.ret + EndBlock + end + + private + + def assert_eq!(left, right) + if left != right + raise "'#{left.inspect}' was not '#{right.inspect}'" + end + end + end +end |