[Qt]REGRESSION(r92254): It made 2 tests timeout
[WebKit-https.git] / Source / JavaScriptCore / offlineasm / opt.rb
1 # Copyright (C) 2011 Apple Inc. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions
5 # are met:
6 # 1. Redistributions of source code must retain the above copyright
7 #    notice, this list of conditions and the following disclaimer.
8 # 2. Redistributions in binary form must reproduce the above copyright
9 #    notice, this list of conditions and the following disclaimer in the
10 #    documentation and/or other materials provided with the distribution.
11 #
12 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
13 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
14 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
15 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
16 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
18 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
19 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
22 # THE POSSIBILITY OF SUCH DAMAGE.
23
24 require "ast"
25
26 #
27 # "Optimization" passes. These are used to lower the representation for
28 # backends that cannot handle some of our higher-level instructions.
29 #
30
31 #
32 # A temporary - a variable that will be allocated to a register after we're
33 # done.
34 #
35
36 class Node
37     def replaceTemporariesWithRegisters(kind)
38         mapChildren {
39             | node |
40             node.replaceTemporariesWithRegisters(kind)
41         }
42     end
43 end
44
45 class Tmp < NoChildren
46     attr_reader :firstMention, :lastMention
47     attr_reader :kind
48     attr_accessor :register
49
50     def initialize(codeOrigin, kind)
51         super(codeOrigin)
52         @kind = kind
53     end
54     
55     def dump
56         "$tmp#{object_id}"
57     end
58     
59     def mention!(position)
60         if not @firstMention or position < @firstMention
61             @firstMention = position
62         end
63         if not @lastMention or position > @lastMention
64             @lastMention = position
65         end
66     end
67     
68     def replaceTemporariesWithRegisters(kind)
69         if @kind == kind
70             raise "Did not allocate register to temporary at #{codeOriginString}" unless @register
71             @register
72         else
73             self
74         end
75     end
76     
77     def address?
78         false
79     end
80     
81     def label?
82         false
83     end
84     
85     def immediate?
86         false
87     end
88     
89     def register?
90         true
91     end
92 end
93
94 # Assign registers to temporaries, by finding which temporaries interfere
95 # with each other. Note that this relies on temporary live ranges not crossing
96 # basic block boundaries.
97
98 def assignRegistersToTemporaries(list, kind, registers)
99     list.each_with_index {
100         | node, index |
101         node.filter(Tmp).uniq.each {
102             | tmp |
103             if tmp.kind == kind
104                 tmp.mention! index
105             end
106         }
107     }
108     
109     freeRegisters = registers.dup
110     list.each_with_index {
111         | node, index |
112         tmpList = node.filter(Tmp).uniq
113         tmpList.each {
114             | tmp |
115             if tmp.kind == kind and tmp.firstMention == index
116                 raise "Could not allocate register to temporary at #{node.codeOriginString}" if freeRegisters.empty?
117                 tmp.register = freeRegisters.pop
118             end
119         }
120         tmpList.each {
121             | tmp |
122             if tmp.kind == kind and tmp.lastMention == index
123                 freeRegisters.push tmp.register
124                 raise "Register allocation inconsistency at #{node.codeOriginString}" if freeRegisters.size > registers.size
125             end
126         }
127     }
128     
129     list.map {
130         | node |
131         node.replaceTemporariesWithRegisters(kind)
132     }
133 end
134