Class: Laser::Analysis::ControlFlow::Instruction
- Inherits:
-
BasicObject
- Defined in:
- lib/laser/analysis/control_flow/cfg_instruction.rb
Instance Attribute Summary (collapse)
Instance Method Summary
(collapse)
Constructor Details
- (Instruction) initialize(body, opts = {})
A new instance of Instruction
8
9
10
11
12
13
14
15
16
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 8
def initialize(body, opts={})
@body = body
@node = opts[:node]
@block = opts[:block]
@raise_frequency = :unknown
@raise_type = Types::EMPTY
@ignore_privacy = opts[:ignore_privacy]
@true_successor = @false_successor = nil
end
|
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
- (Object) method_missing(meth, *args, &blk)
49
50
51
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 49
def method_missing(meth, *args, &blk)
@body.send(meth, *args, &blk)
end
|
Instance Attribute Details
- (Object) block
Returns the value of attribute block
6
7
8
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 6
def block
@block
end
|
- (Object) body
Returns the value of attribute body
6
7
8
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 6
def body
@body
end
|
- (Object) ignore_privacy
Returns the value of attribute ignore_privacy
6
7
8
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 6
def ignore_privacy
@ignore_privacy
end
|
- (Object) node
Returns the value of attribute node
6
7
8
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 6
def node
@node
end
|
- (Object) raise_frequency
Returns the value of attribute raise_frequency
7
8
9
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 7
def raise_frequency
@raise_frequency
end
|
- (Object) raise_type
Returns the value of attribute raise_type
7
8
9
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 7
def raise_type
@raise_type
end
|
Instance Method Details
- (Object) ==(other)
26
27
28
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 26
def ==(other)
@body == other.body
end
|
- (Object) block_operand
131
132
133
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 131
def block_operand
::Hash === last ? last[:block] : nil
end
|
- (Object) calculate_branch_successors
81
82
83
84
85
86
87
88
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 81
def calculate_branch_successors
return if @true_successor
successors = block.successors.to_a
if successors[0].name == self[2]
then @true_successor, @false_successor = successors[0..1]
else @false_successor, @true_successor = successors[0..1]
end
end
|
- (Object) class
22
23
24
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 22
def class
Instruction
end
|
- (Object) deep_dup(temp_lookup, opts = {})
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 30
def deep_dup(temp_lookup, opts={})
new_body = @body[1..-1].map do |arg|
case arg
when Bindings::ConstantBinding then arg
when Bindings::Base then temp_lookup[arg]
when ::Hash
if arg[:block]
then arg.merge(block: temp_lookup[arg[:block]])
else arg
end
else arg.dup rescue arg
end
end
new_body.unshift(self[0]) new_opts = {node: @node, block: temp_lookup[@block], ignore_privacy: @ignore_privacy}.merge(opts)
self.class.new(new_body, new_opts)
end
|
- (Object) explicit_targets
Gets all bindings that are explicitly set in this instruction (no aliasing
concerns)
122
123
124
125
126
127
128
129
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 122
def explicit_targets
case self[0]
when :assign, :call, :call_vararg, :super, :super_vararg, :lambda, :phi
self[1] ? ::Set[self[1]] : ::Set[]
else
::Set[]
end
end
|
- (Object) false_successor
75
76
77
78
79
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 75
def false_successor
require_branch('#false_successor')
calculate_branch_successors
return @false_successor
end
|
- (Boolean) method_call?
53
54
55
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 53
def method_call?
[:call, :call_vararg, :super, :super_vararg].include?(type)
end
|
- (Object) operands
Gets all bindings that are operands in this instruction
140
141
142
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 140
def operands
self[operand_range].select { |x| Bindings::Base === x && x != Bootstrap::VISIBILITY_STACK }
end
|
- (Object) possible_methods(opts)
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 105
def possible_methods(opts)
require_method_call
if type == :call || type == :call_vararg
if Bindings::ConstantBinding === self[2]
[self[2].value.singleton_class.instance_method(self[3])].compact
elsif LaserObject === self[2].value
[self[2].value.klass.instance_method(self[3])].compact
else
self[2].expr_type.matching_methods(self[3])
end
else
[opts[:method].super_method]
end
end
|
- (Object) possible_public_methods
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 90
def possible_public_methods
require_method_call
if type == :call || type == :call_vararg
if Bindings::ConstantBinding === self[2]
[self[2].value.singleton_class.public_instance_method(self[3])].compact
elsif LaserObject === self[2].value
[self[2].value.klass.public_instance_method(self[3])].compact
else
self[2].expr_type.public_matching_methods(self[3])
end
else
end
end
|
- (Object) replace_block_operand(new_block)
135
136
137
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 135
def replace_block_operand(new_block)
last[:block] = new_block
end
|
- (Object) replace_operands(new_operands)
Replaces the operands with a new list. Used by SSA renaming.
145
146
147
148
149
150
151
152
153
154
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 145
def replace_operands(new_operands)
index = operand_range.begin
while new_operands.any? && index < @body.size
if Bindings::Base === self[index] && self[index] != Bootstrap::VISIBILITY_STACK
self[index] = new_operands.shift
end
index += 1
end
end
|
- (Object) replace_target(original_target, new_target)
Replaces a target of the instruction. Used by SSA renaming. Currently, all
instructions only have at most 1 target.
158
159
160
161
162
163
164
165
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 158
def replace_target(original_target, new_target)
if self[1] == original_target
self[1] = new_target
else
raise ArgumentError.new("#{original_target.inspect} is not a "+
"target of #{self.inspect}")
end
end
|
- (Object) require_branch(method_needed = 'the requested operation')
63
64
65
66
67
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 63
def require_branch(method_needed='the requested operation')
unless type == :branch
raise TypeError.new("#{method_needed} is not defined on #{type} instructions.")
end
end
|
- (Object) require_method_call
57
58
59
60
61
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 57
def require_method_call
unless method_call?
raise TypeError.new("#possible_methods is not defined on #{type} instructions.")
end
end
|
- (Object) true_successor
69
70
71
72
73
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 69
def true_successor
require_branch('#true_successor')
calculate_branch_successors
return @true_successor
end
|
- (Object) type
18
19
20
|
# File 'lib/laser/analysis/control_flow/cfg_instruction.rb', line 18
def type
@body[0]
end
|