]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - offlineasm/opt.rb
JavaScriptCore-1097.3.tar.gz
[apple/javascriptcore.git] / offlineasm / opt.rb
diff --git a/offlineasm/opt.rb b/offlineasm/opt.rb
new file mode 100644 (file)
index 0000000..3170d3a
--- /dev/null
@@ -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
+