blob: 80157fc9c2c98a8eeb6c71448c2b06cb631189e7 (
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
|
module RubyVM::RJIT
# Represent the type of a value (local/stack/self) in RJIT
Type = Data.define(:type) do
# Returns a boolean representing whether the value is truthy if known, otherwise nil
def known_truthy
case self
in Type::Nil | Type::False
false
in Type::UnknownHeap
true
in Type::Unknown | Type::UnknownImm
nil
else
true
end
end
def diff(dst)
if self == dst
return TypeDiff::Compatible[0]
end
return TypeDiff::Incompatible
end
def upgrade(new_type)
assert(new_type.diff(self) != TypeDiff::Incompatible)
new_type
end
private
def assert(cond)
unless cond
raise "'#{cond.inspect}' was not true"
end
end
end
# This returns an appropriate Type based on a known value
class << Type
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
return Type::CString
end
if val_class == C.rb_cArray
return Type::CArray
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
private
def fixnum?(obj)
(C.to_value(obj) & C::RUBY_FIXNUM_FLAG) == C::RUBY_FIXNUM_FLAG
end
def flonum?(obj)
(C.to_value(obj) & C::RUBY_FLONUM_MASK) == C::RUBY_FLONUM_FLAG
end
def static_symbol?(obj)
(C.to_value(obj) & 0xff) == C::RUBY_SYMBOL_FLAG
end
end
# List of types
Type::Unknown = Type[:Unknown]
Type::UnknownImm = Type[:UnknownImm]
Type::UnknownHeap = Type[:UnknownHeap]
Type::Nil = Type[:Nil]
Type::True = Type[:True]
Type::False = Type[:False]
Type::Fixnum = Type[:Fixnum]
Type::Flonum = Type[:Flonum]
Type::Hash = Type[:Hash]
Type::ImmSymbol = Type[:ImmSymbol]
Type::HeapSymbol = Type[:HeapSymbol]
Type::TString = Type[:TString] # An object with the T_STRING flag set, possibly an rb_cString
Type::CString = Type[:CString] # An un-subclassed string of type rb_cString (can have instance vars in some cases)
Type::TArray = Type[:TArray] # An object with the T_ARRAY flag set, possibly an rb_cArray
Type::CArray = Type[:CArray] # An un-subclassed string of type rb_cArray (can have instance vars in some cases)
Type::BlockParamProxy = Type[:BlockParamProxy] # A special sentinel value indicating the block parameter should be read from
module TypeDiff
Compatible = Data.define(:diversion) # The smaller, the more compatible.
Incompatible = :Incompatible
end
end
|