Class: RubyVM::RJIT::Type

Inherits:
Data
  • Object
show all
Defined in:
lib/ruby_vm/rjit/type.rb

Overview

Represent the type of a value (local/stack/self) in RJIT

Constant Summary collapse

Unknown =

List of types

Type[:Unknown]
UnknownImm =
Type[:UnknownImm]
UnknownHeap =
Type[:UnknownHeap]
Nil =
Type[:Nil]
True =
Type[:True]
False =
Type[:False]
Fixnum =
Type[:Fixnum]
Flonum =
Type[:Flonum]
Hash =
Type[:Hash]
ImmSymbol =
Type[:ImmSymbol]
HeapSymbol =
Type[:HeapSymbol]
TString =

An object with the T_STRING flag set, possibly an rb_cString

Type[:TString]
CString =

An un-subclassed string of type rb_cString (can have instance vars in some cases)

Type[:CString]
TArray =

An object with the T_ARRAY flag set, possibly an rb_cArray

Type[:TArray]
BlockParamProxy =

A special sentinel value indicating the block parameter should be read from

Type[:BlockParamProxy]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#type ⇒ Object (readonly)

Returns the value of attribute type

Returns:

  • (Object) —

    the current value of type



3
4
5
# File 'lib/ruby_vm/rjit/type.rb', line 3

def type
  @type
end

Class Method Details

.from(val) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/ruby_vm/rjit/type.rb', line 145

def from(val)
  if C::SPECIAL_CONST_P(val)
    if fixnum?(val)
      Type::Fixnum
    elsif val.nil?
      Type::Nil
    elsif val == true
      Type::True
    elsif val == false
      Type::False
    elsif static_symbol?(val)
      Type::ImmSymbol
    elsif flonum?(val)
      Type::Flonum
    else
      raise "Illegal value: #{val.inspect}"
    end
  else
    val_class = C.to_value(C.rb_class_of(val))
    if val_class == C.rb_cString && C.rb_obj_frozen_p(val)
      return Type::CString
    end
    if C.to_value(val) == C.rb_block_param_proxy
      return Type::BlockParamProxy
    end
    case C::BUILTIN_TYPE(val)
    in C::RUBY_T_ARRAY
      Type::TArray
    in C::RUBY_T_HASH
      Type::Hash
    in C::RUBY_T_STRING
      Type::TString
    else
      Type::UnknownHeap
    end
  end
end

Instance Method Details

#array? ⇒ Boolean

Check if it's a T_ARRAY object

Returns:

  • (Boolean)


48
49
50
51
52
53
# File 'lib/ruby_vm/rjit/type.rb', line 48

def array?
  case self
  in Type::TArray then true
  else false
  end
end

#diff(dst) ⇒ Object



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
# File 'lib/ruby_vm/rjit/type.rb', line 99

def diff(dst)
  # Perfect match, difference is zero
  if self == dst
    return TypeDiff::Compatible[0]
  end

  # Any type can flow into an unknown type
  if dst == Type::Unknown
    return TypeDiff::Compatible[1]
  end

  # A CString is also a TString.
  if self == Type::CString && dst == Type::TString
    return TypeDiff::Compatible[1]
  end

  # Specific heap type into unknown heap type is imperfect but valid
  if self.heap? && dst == Type::UnknownHeap
    return TypeDiff::Compatible[1]
  end

  # Specific immediate type into unknown immediate type is imperfect but valid
  if self.imm? && dst == Type::UnknownImm
    return TypeDiff::Compatible[1]
  end

  # Incompatible types
  return TypeDiff::Incompatible
end

#heap? ⇒ Boolean

Check if the type is a heap object

Returns:

  • (Boolean)


34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/ruby_vm/rjit/type.rb', line 34

def heap?
  case self
  in Type::UnknownHeap then true
  in Type::TArray then true
  in Type::Hash then true
  in Type::HeapSymbol then true
  in Type::TString then true
  in Type::CString then true
  in Type::BlockParamProxy then true
  else false
  end
end

#imm? ⇒ Boolean

Check if the type is an immediate

Returns:

  • (Boolean)


5
6
7
8
9
10
11
12
13
14
15
16
# File 'lib/ruby_vm/rjit/type.rb', line 5

def imm?
  case self
  in Type::UnknownImm then true
  in Type::Nil then true
  in Type::True then true
  in Type::False then true
  in Type::Fixnum then true
  in Type::Flonum then true
  in Type::ImmSymbol then true
  else false
  end
end

#known_class ⇒ Object

Returns the class if it is known, otherwise nil



65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/ruby_vm/rjit/type.rb', line 65

def known_class
  case self
  in Type::Nil then C.rb_cNilClass
  in Type::True then C.rb_cTrueClass
  in Type::False then C.rb_cFalseClass
  in Type::Fixnum then C.rb_cInteger
  in Type::Flonum then C.rb_cFloat
  in Type::ImmSymbol | Type::HeapSymbol then C.rb_cSymbol
  in Type::CString then C.rb_cString
  else nil
  end
end

#known_nil ⇒ Object

Returns a boolean representing whether the value is equal to nil if known, otherwise nil



90
91
92
93
94
95
96
97
# File 'lib/ruby_vm/rjit/type.rb', line 90

def known_nil
  case [self, self.known_truthy]
  in Type::Nil, _ then true
  in Type::False, _ then false # Qfalse is not nil
  in _, true then false # if truthy, can't be nil
  in _, _ then nil # otherwise unknown
  end
end

#known_truthy ⇒ Object

Returns a boolean representing whether the value is truthy if known, otherwise nil



79
80
81
82
83
84
85
86
87
# File 'lib/ruby_vm/rjit/type.rb', line 79

def known_truthy
  case self
  in Type::Nil then false
  in Type::False then false
  in Type::UnknownHeap then false
  in Type::Unknown | Type::UnknownImm then nil
  else true
  end
end

#specific? ⇒ Boolean

Returns true when we know the VALUE is a specific handle type, such as a static symbol ([Type::ImmSymbol], i.e. true from RB_STATIC_SYM_P()). Opposite of [Self::is_unknown].

Returns:

  • (Boolean)


29
30
31
# File 'lib/ruby_vm/rjit/type.rb', line 29

def specific?
  !self.unknown?
end

#string? ⇒ Boolean

Check if it's a T_STRING object (both TString and CString are T_STRING)

Returns:

  • (Boolean)


56
57
58
59
60
61
62
# File 'lib/ruby_vm/rjit/type.rb', line 56

def string?
  case self
  in Type::TString then true
  in Type::CString then true
  else false
  end
end

#unknown? ⇒ Boolean

Returns true when the type is not specific.

Returns:

  • (Boolean)


19
20
21
22
23
24
# File 'lib/ruby_vm/rjit/type.rb', line 19

def unknown?
  case self
  in Type::Unknown | Type::UnknownImm | Type::UnknownHeap then true
  else false
  end
end

#upgrade(new_type) ⇒ Object



129
130
131
132
# File 'lib/ruby_vm/rjit/type.rb', line 129

def upgrade(new_type)
  assert(new_type.diff(self) != TypeDiff::Incompatible)
  new_type
end