Class: FastRuby::Inliner
- Defined in:
- lib/fastruby/inliner/inliner.rb,
lib/fastruby/inliner/modules/call.rb,
lib/fastruby/inliner/modules/recursive.rb
Defined Under Namespace
Classes: BlockProcessing
Instance Attribute Summary collapse
-
#extra_inferences ⇒ Object
readonly
Returns the value of attribute extra_inferences.
-
#extra_locals ⇒ Object
readonly
Returns the value of attribute extra_locals.
-
#infer_lvar_map ⇒ Object
Returns the value of attribute infer_lvar_map.
-
#infer_self ⇒ Object
Returns the value of attribute infer_self.
-
#inlined_methods ⇒ Object
readonly
Returns the value of attribute inlined_methods.
Instance Method Summary collapse
- #add_local(local) ⇒ Object
- #add_prefix(tree, prefix) ⇒ Object
- #catch_block(name, tree) ⇒ Object
- #infer_type(recv) ⇒ Object
-
#initialize ⇒ Inliner
constructor
A new instance of Inliner.
- #inline_local_name(method_name, local_name) ⇒ Object
- #method_obj_or_gtfo(klass, method_name) ⇒ Object
- #method_tree_to_inlined_block(mobject, call_tree, method_name, block_args_tree = nil, block_tree = nil) ⇒ Object
- #recursive_inline(tree) ⇒ Object
Constructor Details
#initialize ⇒ Inliner
Returns a new instance of Inliner.
33 34 35 36 37 |
# File 'lib/fastruby/inliner/inliner.rb', line 33 def initialize @extra_locals = Set.new @extra_inferences = Hash.new @inlined_methods = Array.new end |
Instance Attribute Details
#extra_inferences ⇒ Object (readonly)
Returns the value of attribute extra_inferences.
30 31 32 |
# File 'lib/fastruby/inliner/inliner.rb', line 30 def extra_inferences @extra_inferences end |
#extra_locals ⇒ Object (readonly)
Returns the value of attribute extra_locals.
29 30 31 |
# File 'lib/fastruby/inliner/inliner.rb', line 29 def extra_locals @extra_locals end |
#infer_lvar_map ⇒ Object
Returns the value of attribute infer_lvar_map.
27 28 29 |
# File 'lib/fastruby/inliner/inliner.rb', line 27 def infer_lvar_map @infer_lvar_map end |
#infer_self ⇒ Object
Returns the value of attribute infer_self.
28 29 30 |
# File 'lib/fastruby/inliner/inliner.rb', line 28 def infer_self @infer_self end |
#inlined_methods ⇒ Object (readonly)
Returns the value of attribute inlined_methods.
31 32 33 |
# File 'lib/fastruby/inliner/inliner.rb', line 31 def inlined_methods @inlined_methods end |
Instance Method Details
#add_local(local) ⇒ Object
47 48 49 |
# File 'lib/fastruby/inliner/inliner.rb', line 47 def add_local(local) @extra_locals << local end |
#add_prefix(tree, prefix) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/fastruby/inliner/modules/call.rb', line 80 def add_prefix(tree, prefix) tree = tree.duplicate tree.walk_tree do |subtree| if subtree.node_type == :lvar or subtree.node_type == :lasgn subtree[1] = inline_local_name(prefix, subtree[1]) add_local subtree[1] end end tree end |
#catch_block(name, tree) ⇒ Object
92 93 94 |
# File 'lib/fastruby/inliner/modules/call.rb', line 92 def catch_block(name,tree) fs(:block,fs(:iter, fs(:call, nil, :_catch, fs(:arglist, fs(:lit,name.to_sym))),nil,tree)) end |
#infer_type(recv) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/fastruby/inliner/inliner.rb', line 51 def infer_type(recv) if recv[0] == :call if recv[2] == :infer eval(recv[3].last.last.to_s) end elsif recv[0] == :lvar @infer_lvar_map[recv[1]] elsif recv[0] == :self @infer_self elsif recv[0] == :str or recv[0] == :lit recv[1].class else nil end end |
#inline_local_name(method_name, local_name) ⇒ Object
71 72 73 |
# File 'lib/fastruby/inliner/modules/call.rb', line 71 def inline_local_name(method_name, local_name) "__inlined_#{method_name}_#{local_name}".to_sym end |
#method_obj_or_gtfo(klass, method_name) ⇒ Object
75 76 77 78 |
# File 'lib/fastruby/inliner/modules/call.rb', line 75 def method_obj_or_gtfo(klass, method_name) return nil unless klass.respond_to?(:fastruby_method) klass.fastruby_method(method_name) end |
#method_tree_to_inlined_block(mobject, call_tree, method_name, block_args_tree = nil, block_tree = nil) ⇒ Object
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 137 138 139 140 141 142 143 144 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 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/fastruby/inliner/modules/call.rb', line 96 def method_tree_to_inlined_block(mobject, call_tree, method_name, block_args_tree = nil, block_tree = nil) args_tree = call_tree[3] recv_tree = call_tree[1] || fs(:self) target_method_tree = mobject.tree @method_index = (@method_index || 0) + 1 prefix = method_name.to_s + "_" + @method_index.to_s target_method_tree_block = add_prefix(target_method_tree.find_tree(:scope)[1], prefix) if target_method_tree_block.find_tree(:return) inlined_name = inline_local_name(method_name, "main_return_tagname") target_method_tree_block = catch_block(inlined_name,target_method_tree_block) target_method_tree_block.walk_tree do |subtree| if subtree[0] == :return if subtree[1] subtree[0..-1] = fs(:call, nil, :_throw, fs(:arglist, fs(:lit,inlined_name.to_sym), subtree[1])) else subtree[0..-1] = fs(:call, nil, :_throw, fs(:arglist, fs(:lit,inlined_name.to_sym), fs(:nil))) end end end end target_method_tree_args = target_method_tree[2] newblock = fs(:block) (1..args_tree.size-1).each do |i| itype = infer_type(args_tree[i]) inlined_name = inline_local_name(prefix, target_method_tree_args[i]) add_local inlined_name self.extra_inferences[inlined_name] = itype if itype newblock << fs(:lasgn, inlined_name, recursive_inline(args_tree[i].duplicate)) end inlined_name = inline_local_name(prefix, :self) add_local inlined_name newblock << fs(:lasgn, inlined_name, recv_tree.duplicate) return nil if target_method_tree_block.find_tree(:return) break_tag = nil if block_tree block_tree = recursive_inline(block_tree) if block_tree.find_tree(:break) # FIXME: discard nested iter calls on finding break_tag = inline_local_name(prefix, "__break_tag") end end block_num = 0 target_method_tree_block.walk_tree do |subtree| if subtree.node_type == :call if subtree[1] == nil if subtree[2] == :block_given? subtree[0..-1] = fs(:false) else subtree[1] = recv_tree.duplicate end end end if subtree.node_type == :self subtree[0] = :lvar subtree[1] = inline_local_name(prefix, :self) end if subtree.node_type == :yield if block_tree # inline yield yield_call_args = subtree.duplicate subtree[0..-1] = fs(:block) if block_args_tree return nil if yield_call_args[1..-1].find{|x| x.node_type == :splat} if block_args_tree.node_type == :masgn return nil if block_args_tree[1].size != yield_call_args.size return nil if block_args_tree[1][1..-1].find{|x| x.node_type == :splat} (1..yield_call_args.size-1).each do |i| inlined_name = block_args_tree[1][i][1] add_local inlined_name subtree << fs(:lasgn, inlined_name, yield_call_args[i]) end else return nil if 2 != yield_call_args.size inlined_name = block_args_tree[1] add_local inlined_name subtree << fs(:lasgn, inlined_name, yield_call_args[1]) end else return nil if yield_call_args.size > 1 end if block_tree.find_tree(:next) or block_tree.find_tree(:redo) or break_tag inlined_name = inline_local_name(prefix, "block_block_#{block_num}") block_num = block_num + 1 alt_block_tree = BlockProcessing.new(inlined_name, break_tag).process(block_tree) alt_block_tree = catch_block(inlined_name,alt_block_tree) else alt_block_tree = block_tree.duplicate end subtree << alt_block_tree else subtree[0..-1] = fs(:call, fs(:nil), :raise, fs(:arglist, fs(:const, :LocalJumpError), fs(:str, "no block given"))) end end end @inlined_methods << mobject if break_tag inner_block = fs(:block) target_method_tree_block[1..-1].each do |subtree| inner_block << subtree end newblock << catch_block(break_tag,inner_block) else target_method_tree_block[1..-1].each do |subtree| newblock << subtree end end newblock end |
#recursive_inline(tree) ⇒ Object
28 29 30 |
# File 'lib/fastruby/inliner/modules/recursive.rb', line 28 def recursive_inline(tree) tree.map &method(:inline) end |