summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/offlineasm/opt.rb
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/offlineasm/opt.rb')
-rw-r--r--Source/JavaScriptCore/offlineasm/opt.rb134
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
+