summaryrefslogtreecommitdiff
path: root/mjit_compiler.rb
blob: 9e032fc747703e10278a64a981355c8a2c620f76 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# frozen_string_literal: true
# TODO: Merge this to mjit.rb
if RubyVM::MJIT.enabled?
  begin
    require 'etc'
    require 'fiddle'
  rescue LoadError
    return # skip miniruby
  end

  if Fiddle::SIZEOF_VOIDP == 8
    require 'mjit/c_64'
  else
    require 'mjit/c_32'
  end

  class << RubyVM::MJIT::C
    def ROBJECT_EMBED_LEN_MAX
      Primitive.cexpr! 'INT2NUM(RBIMPL_EMBED_LEN_MAX_OF(VALUE))'
    end

    def cdhash_to_hash(cdhash_addr)
      Primitive.cdhash_to_hash(cdhash_addr)
    end

    def builtin_compiler(f, bf, index, stack_size, builtin_inline_p)
      Primitive.builtin_compile(f, bf.to_i, index, stack_size, builtin_inline_p)
    end

    def has_cache_for_send(cc, insn)
      Primitive.has_cache_for_send(cc.to_i, insn)
    end

    def rb_iseq_check(iseq)
      _iseq_addr = iseq.to_i
      iseq_addr = Primitive.cexpr! 'PTR2NUM((VALUE)rb_iseq_check((rb_iseq_t *)NUM2PTR(_iseq_addr)))'
      rb_iseq_t.new(iseq_addr)
    end

    def rb_iseq_path(iseq)
      _iseq_addr = iseq.to_i
      Primitive.cexpr! 'rb_iseq_path((rb_iseq_t *)NUM2PTR(_iseq_addr))'
    end

    def vm_ci_argc(ci)
      _ci_addr = ci.to_i
      Primitive.cexpr! 'UINT2NUM(vm_ci_argc((CALL_INFO)NUM2PTR(_ci_addr)))'
    end

    def vm_ci_flag(ci)
      _ci_addr = ci.to_i
      Primitive.cexpr! 'UINT2NUM(vm_ci_flag((CALL_INFO)NUM2PTR(_ci_addr)))'
    end

    def rb_splat_or_kwargs_p(ci)
      _ci_addr = ci.to_i
      Primitive.cexpr! 'RBOOL(rb_splat_or_kwargs_p((CALL_INFO)NUM2PTR(_ci_addr)))'
    end

    def fastpath_applied_iseq_p(ci, cc, iseq)
      _ci_addr = ci.to_i
      _cc_addr = cc.to_i
      _iseq_addr = iseq.to_i
      Primitive.cexpr! 'RBOOL(fastpath_applied_iseq_p((CALL_INFO)NUM2PTR(_ci_addr), (CALL_CACHE)NUM2PTR(_cc_addr), (rb_iseq_t *)NUM2PTR(_iseq_addr)))'
    end

    def mjit_opts
      addr = Primitive.cexpr! 'PTR2NUM((VALUE)&mjit_opts)'
      mjit_options.new(addr)
    end

    def mjit_call_attribute_sp_inc(insn, operands)
      _operands_addr = operands.to_i
      Primitive.cexpr! 'LONG2NUM(mjit_call_attribute_sp_inc(NUM2INT(insn), (VALUE *)NUM2PTR(_operands_addr)))'
    end

    def mjit_capture_cc_entries(compiled_body, captured_body)
      _compiled_body_addr = compiled_body.to_i
      _captured_body_addr = captured_body.to_i
      Primitive.cexpr! 'INT2NUM(mjit_capture_cc_entries((struct rb_iseq_constant_body *)NUM2PTR(_compiled_body_addr), (struct rb_iseq_constant_body *)NUM2PTR(_captured_body_addr)))'
    end

    #const struct rb_iseq_constant_body *body, union iseq_inline_storage_entry *is_entries
    def mjit_capture_is_entries(body, is_entries)
      _body_addr = body.to_i
      _is_entries_addr = is_entries.to_i
      Primitive.cstmt! %{
        mjit_capture_is_entries((struct rb_iseq_constant_body *)NUM2PTR(_body_addr), (union iseq_inline_storage_entry *)NUM2PTR(_is_entries_addr));
        return Qnil;
      }
    end

    # Convert encoded VM pointers to insn BINs.
    def rb_vm_insn_decode(encoded)
      Primitive.cexpr! 'INT2NUM(rb_vm_insn_decode(NUM2PTR(encoded)))'
    end

    # Convert insn BINs to encoded VM pointers. This one is not used by the compiler, but useful for debugging.
    def rb_vm_insn_encode(bin)
      Primitive.cexpr! 'PTR2NUM((VALUE)rb_vm_get_insns_address_table()[NUM2INT(bin)])'
    end

    def insn_may_depend_on_sp_or_pc(insn, opes)
      _opes_addr = opes.to_i
      Primitive.cexpr! 'RBOOL(insn_may_depend_on_sp_or_pc(NUM2INT(insn), (VALUE *)NUM2PTR(_opes_addr)))'
    end

    # Convert Integer VALUE to an actual Ruby object
    def to_ruby(value)
      Primitive.cexpr! '(VALUE)NUM2PTR(value)'
    end

    # Convert RubyVM::InstructionSequence to C.rb_iseq_t. Not used by the compiler, but useful for debugging.
    def rb_iseqw_to_iseq(iseqw)
      iseq_addr = Primitive.cexpr! 'PTR2NUM((VALUE)rb_iseqw_to_iseq(iseqw))'
      rb_iseq_t.new(iseq_addr)
    end

    # TODO: remove this after migration
    def fprintf(f, str)
      Primitive.cstmt! %{
        fprintf((FILE *)NUM2PTR(f), "%s", RSTRING_PTR(str));
        return Qnil;
      }
    end

    def rb_cFalseClass; Primitive.cexpr! 'PTR2NUM(rb_cFalseClass)' end
    def rb_cNilClass;   Primitive.cexpr! 'PTR2NUM(rb_cNilClass)'   end
    def rb_cTrueClass;  Primitive.cexpr! 'PTR2NUM(rb_cTrueClass)'  end
    def rb_cInteger;    Primitive.cexpr! 'PTR2NUM(rb_cInteger)'    end
    def rb_cSymbol;     Primitive.cexpr! 'PTR2NUM(rb_cSymbol)'     end
    def rb_cFloat;      Primitive.cexpr! 'PTR2NUM(rb_cFloat)'      end
  end

  require "mjit/compiler"
end