Skip to content
This repository has been archived by the owner on Nov 2, 2019. It is now read-only.

Commit

Permalink
Fix constant propagation and propagate params in Local2SSA.
Browse files Browse the repository at this point in the history
  • Loading branch information
whitequark committed Sep 1, 2012
1 parent 781ba18 commit 7fe05c9
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 19 deletions.
2 changes: 1 addition & 1 deletion Gemfile
Expand Up @@ -5,4 +5,4 @@ gemspec
gem "pry" gem "pry"
gem "ruby-prof", :platforms => :mri gem "ruby-prof", :platforms => :mri


gem "furnace", :github => 'whitequark/furnace' gem "furnace", :github => 'whitequark/furnace', :branch => 'master'
3 changes: 2 additions & 1 deletion lib/furnace-avm2/source/decompiler.rb
Expand Up @@ -465,7 +465,8 @@ def local_token(node)
end end
end end
end end
alias :expr_this :local_token alias :expr_this :local_token
alias :expr_param :local_token


def expr_get(node) def expr_get(node)
index, = node.children index, = node.children
Expand Down
29 changes: 21 additions & 8 deletions lib/furnace-avm2/transform/convert_locals_to_ssa.rb
Expand Up @@ -30,19 +30,32 @@ def on_get_local(node)
end end
end end


def initialize(options={})
@method = options[:method]
end

def transform(cfg) def transform(cfg)
next_id = 0 next_id = 0
variable_map = Hash.new { |h, k| h[k] = Set[] } variable_map = Hash.new { |h, k| h[k] = Set[] }


# Prepend implicit `this'. # Prepend implicit `this' and params.
this_set = AST::Node.new(:set_local, [ implicit = 0.upto(1 + @method.param_count).map do |local|
0, AST::Node.new(:this) case local
], { when 0
read_barrier: Set[], inner_node = AST::Node.new(:this)
write_barrier: Set[], else
}) inner_node = AST::Node.new(:param, [ local - 1 ])
end

AST::Node.new(:set_local, [
local, inner_node
], {
read_barrier: Set[],
write_barrier: Set[],
})
end


cfg.entry.insns.insert(0, this_set) cfg.entry.insns.insert(0, *implicit)


# Convert (set-local) to (s). # Convert (set-local) to (s).
cfg.nodes.each do |block| cfg.nodes.each do |block|
Expand Down
11 changes: 6 additions & 5 deletions lib/furnace-avm2/transform/propagate_constants.rb
Expand Up @@ -16,14 +16,15 @@ def transform(cfg)
# TODO add options for folding complex constants # TODO add options for folding complex constants
if evaluator.immediate?(set_value) || if evaluator.immediate?(set_value) ||
set_value.type == :this || set_value.type == :this ||
set_value.type == :param ||
set_value.type == :find_property_strict set_value.type == :find_property_strict


replace_r_nodes(cfg, block, id, set_value) do |child_block| replaced_all = replace_r_nodes(cfg, block, id, set_value)
child_block.metadata.live.delete id
end


block.metadata.remove_set id if replaced_all
block.insns.delete set block.metadata.remove_set id
block.insns.delete set
end


changed = true changed = true
end end
Expand Down
20 changes: 16 additions & 4 deletions lib/furnace-avm2/transform/subgraph_operations.rb
Expand Up @@ -85,18 +85,30 @@ def reduce_phi_nodes(cfg, root, target_id, supplementary_id)
end end


def replace_r_nodes(cfg, root, target_id, replacement) def replace_r_nodes(cfg, root, target_id, replacement)
replaced_all = true

walk_live_nodes(cfg, root, target_id) do |block| walk_live_nodes(cfg, root, target_id) do |block|
gets = block.metadata.gets_map[target_id] gets = block.metadata.gets_map[target_id]
gets.each do |get| gets.each do |get|
get.update(replacement.type, if get.children.one?
replacement.children, get.update(replacement.type,
replacement.metadata) replacement.children,
replacement.metadata)
else
replaced_all = false
end
end end


block.metadata.unregister_get target_id block.metadata.unregister_get target_id
end


yield block if block_given? if replaced_all
walk_live_nodes(cfg, root, target_id) do |block|
block.metadata.live.delete target_id
end
end end

replaced_all
end end
end end
end end
Expand Down

0 comments on commit 7fe05c9

Please sign in to comment.