diff options
Diffstat (limited to 'Source/JavaScriptCore/offlineasm/opt.rb')
-rw-r--r-- | Source/JavaScriptCore/offlineasm/opt.rb | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/offlineasm/opt.rb b/Source/JavaScriptCore/offlineasm/opt.rb new file mode 100644 index 000000000..3170d3ae1 --- /dev/null +++ b/Source/JavaScriptCore/offlineasm/opt.rb @@ -0,0 +1,134 @@ +# Copyright (C) 2011 Apple Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. + +require "ast" + +# +# "Optimization" passes. These are used to lower the representation for +# backends that cannot handle some of our higher-level instructions. +# + +# +# A temporary - a variable that will be allocated to a register after we're +# done. +# + +class Node + def replaceTemporariesWithRegisters(kind) + mapChildren { + | node | + node.replaceTemporariesWithRegisters(kind) + } + end +end + +class Tmp < NoChildren + attr_reader :firstMention, :lastMention + attr_reader :kind + attr_accessor :register + + def initialize(codeOrigin, kind) + super(codeOrigin) + @kind = kind + end + + def dump + "$tmp#{object_id}" + end + + def mention!(position) + if not @firstMention or position < @firstMention + @firstMention = position + end + if not @lastMention or position > @lastMention + @lastMention = position + end + end + + def replaceTemporariesWithRegisters(kind) + if @kind == kind + raise "Did not allocate register to temporary at #{codeOriginString}" unless @register + @register + else + self + end + end + + def address? + false + end + + def label? + false + end + + def immediate? + false + end + + def register? + true + end +end + +# Assign registers to temporaries, by finding which temporaries interfere +# with each other. Note that this relies on temporary live ranges not crossing +# basic block boundaries. + +def assignRegistersToTemporaries(list, kind, registers) + list.each_with_index { + | node, index | + node.filter(Tmp).uniq.each { + | tmp | + if tmp.kind == kind + tmp.mention! index + end + } + } + + freeRegisters = registers.dup + list.each_with_index { + | node, index | + tmpList = node.filter(Tmp).uniq + tmpList.each { + | tmp | + if tmp.kind == kind and tmp.firstMention == index + raise "Could not allocate register to temporary at #{node.codeOriginString}" if freeRegisters.empty? + tmp.register = freeRegisters.pop + end + } + tmpList.each { + | tmp | + if tmp.kind == kind and tmp.lastMention == index + freeRegisters.push tmp.register + raise "Register allocation inconsistency at #{node.codeOriginString}" if freeRegisters.size > registers.size + end + } + } + + list.map { + | node | + node.replaceTemporariesWithRegisters(kind) + } +end + |