Mercurial > hg > truffle
comparison graal/Compiler/src/com/sun/c1x/alloc/OperandPool.java @ 2507:9ec15d6914ca
Pull over of compiler from maxine repository.
author | Thomas Wuerthinger <thomas@wuerthinger.net> |
---|---|
date | Wed, 27 Apr 2011 11:43:22 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2506:4a3bf8a5bf41 | 2507:9ec15d6914ca |
---|---|
1 /* | |
2 * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 */ | |
23 package com.sun.c1x.alloc; | |
24 | |
25 import java.util.*; | |
26 | |
27 import com.sun.c1x.*; | |
28 import com.sun.c1x.ir.*; | |
29 import com.sun.cri.ci.*; | |
30 | |
31 /** | |
32 * An ordered, 0-based indexable pool of instruction operands for a method being compiled. | |
33 * The physical {@linkplain CiRegister registers} of the platform occupy the front of the | |
34 * pool (starting at index 0) followed by {@linkplain CiVariable variable} operands. | |
35 * The index of an operand in the pool is its {@linkplain #operandNumber(CiValue) operand number}. | |
36 * | |
37 * In the original HotSpot C1 source code, this pool corresponds to the | |
38 * "flat register file" mentioned in c1_LinearScan.cpp. | |
39 * | |
40 * @author Doug Simon | |
41 */ | |
42 public final class OperandPool { | |
43 | |
44 public static final int INITIAL_VARIABLE_CAPACITY = 20; | |
45 | |
46 /** | |
47 * The physical registers occupying the head of the operand pool. This is the complete | |
48 * {@linkplain CiArchitecture#registers register set} of the target architecture, not | |
49 * just the allocatable registers. | |
50 */ | |
51 private final CiRegister[] registers; | |
52 | |
53 /** | |
54 * The variable operands allocated from this pool. The {@linkplain #operandNumber(CiValue) number} | |
55 * of the first variable operand in this pool is one greater than the number of the last | |
56 * register operand in the pool. | |
57 */ | |
58 private final ArrayList<CiVariable> variables; | |
59 | |
60 /** | |
61 * Map from a {@linkplain CiVariable#index variable index} to the instruction whose result is stored in the denoted variable. | |
62 * This map is only populated and used if {@link C1XOptions#DetailedAsserts} is {@code true}. | |
63 */ | |
64 private final ArrayList<Value> variableDefs; | |
65 | |
66 /** | |
67 * The {@linkplain #operandNumber(CiValue) number} of the first variable operand | |
68 * {@linkplain #newVariable(CiKind) allocated} from this pool. | |
69 */ | |
70 private final int firstVariableNumber; | |
71 | |
72 /** | |
73 * Records which variable operands have the {@link VariableFlag#MustBeByteRegister} flag set. | |
74 */ | |
75 private CiBitMap mustBeByteRegister; | |
76 | |
77 /** | |
78 * Records which variable operands have the {@link VariableFlag#MustStartInMemory} flag set. | |
79 */ | |
80 private CiBitMap mustStartInMemory; | |
81 | |
82 /** | |
83 * Records which variable operands have the {@link VariableFlag#MustStayInMemory} flag set. | |
84 */ | |
85 private CiBitMap mustStayInMemory; | |
86 | |
87 /** | |
88 * Flags that can be set for {@linkplain CiValue#isVariable() variable} operands. | |
89 */ | |
90 public enum VariableFlag { | |
91 /** | |
92 * Denotes a variable that needs to be assigned a memory location | |
93 * at the beginning, but may then be loaded in a register. | |
94 */ | |
95 MustStartInMemory, | |
96 | |
97 /** | |
98 * Denotes a variable that needs to be assigned a memory location | |
99 * at the beginning and never subsequently loaded in a register. | |
100 */ | |
101 MustStayInMemory, | |
102 | |
103 /** | |
104 * Denotes a variable that must be assigned to a byte-sized register. | |
105 */ | |
106 MustBeByteRegister; | |
107 | |
108 public static final VariableFlag[] VALUES = values(); | |
109 } | |
110 | |
111 private static CiBitMap set(CiBitMap map, CiVariable variable) { | |
112 if (map == null) { | |
113 int length = CiBitMap.roundUpLength(variable.index + 1); | |
114 map = new CiBitMap(length); | |
115 } else if (map.size() <= variable.index) { | |
116 int length = CiBitMap.roundUpLength(variable.index + 1); | |
117 map.grow(length); | |
118 } | |
119 map.set(variable.index); | |
120 return map; | |
121 } | |
122 | |
123 private static boolean get(CiBitMap map, CiVariable variable) { | |
124 if (map == null || map.size() <= variable.index) { | |
125 return false; | |
126 } | |
127 return map.get(variable.index); | |
128 } | |
129 | |
130 /** | |
131 * Creates a new operand pool. | |
132 * | |
133 * @param target description of the target architecture for a compilation | |
134 */ | |
135 public OperandPool(CiTarget target) { | |
136 CiRegister[] registers = target.arch.registers; | |
137 this.firstVariableNumber = registers.length; | |
138 this.registers = registers; | |
139 variables = new ArrayList<CiVariable>(INITIAL_VARIABLE_CAPACITY); | |
140 variableDefs = C1XOptions.DetailedAsserts ? new ArrayList<Value>(INITIAL_VARIABLE_CAPACITY) : null; | |
141 } | |
142 | |
143 /** | |
144 * Creates a new {@linkplain CiVariable variable} operand. | |
145 * | |
146 * @param kind the kind of the variable | |
147 * @return a new variable | |
148 */ | |
149 public CiVariable newVariable(CiKind kind) { | |
150 return newVariable(kind, kind == CiKind.Boolean || kind == CiKind.Byte ? VariableFlag.MustBeByteRegister : null); | |
151 } | |
152 | |
153 /** | |
154 * Creates a new {@linkplain CiVariable variable} operand. | |
155 * | |
156 * @param kind the kind of the variable | |
157 * @param flag a flag that is set for the new variable operand (ignored if {@code null}) | |
158 * @return a new variable operand | |
159 */ | |
160 public CiVariable newVariable(CiKind kind, VariableFlag flag) { | |
161 assert kind != CiKind.Void; | |
162 int varIndex = variables.size(); | |
163 CiVariable var = CiVariable.get(kind, varIndex); | |
164 if (flag == VariableFlag.MustBeByteRegister) { | |
165 mustBeByteRegister = set(mustBeByteRegister, var); | |
166 } else if (flag == VariableFlag.MustStartInMemory) { | |
167 mustStartInMemory = set(mustStartInMemory, var); | |
168 } else if (flag == VariableFlag.MustStayInMemory) { | |
169 mustStayInMemory = set(mustStayInMemory, var); | |
170 } else { | |
171 assert flag == null; | |
172 } | |
173 variables.add(var); | |
174 return var; | |
175 } | |
176 | |
177 /** | |
178 * Gets the unique number for an operand contained in this pool. | |
179 * | |
180 * | |
181 * @param operand an operand | |
182 * @return the unique number for {@code operand} in the range {@code [0 .. size())} | |
183 */ | |
184 public int operandNumber(CiValue operand) { | |
185 if (operand.isRegister()) { | |
186 int number = operand.asRegister().number; | |
187 assert number < firstVariableNumber; | |
188 return number; | |
189 } | |
190 assert operand.isVariable(); | |
191 return firstVariableNumber + ((CiVariable) operand).index; | |
192 } | |
193 | |
194 /** | |
195 * Gets the operand in this pool denoted by a given operand number. | |
196 * | |
197 * @param operandNumber a value that must be in the range {@code [0 .. size())} | |
198 * @return the operand in this pool denoted by {@code operandNumber} | |
199 */ | |
200 public CiValue operandFor(int operandNumber) { | |
201 if (operandNumber < firstVariableNumber) { | |
202 assert operandNumber >= 0; | |
203 return registers[operandNumber].asValue(); | |
204 } | |
205 int index = operandNumber - firstVariableNumber; | |
206 CiVariable variable = variables.get(index); | |
207 assert variable.index == index; | |
208 return variable; | |
209 } | |
210 | |
211 /** | |
212 * Records that the result of {@code instruction} is stored in {@code result}. | |
213 * | |
214 * @param result the variable storing the result of {@code instruction} | |
215 * @param instruction an instruction that produces a result (i.e. pushes a value to the stack) | |
216 */ | |
217 public void recordResult(CiVariable result, Value instruction) { | |
218 while (variableDefs.size() <= result.index) { | |
219 variableDefs.add(null); | |
220 } | |
221 variableDefs.set(result.index, instruction); | |
222 } | |
223 | |
224 /** | |
225 * Gets the instruction whose result is recorded in a given variable. | |
226 * | |
227 * @param result the variable storing the result of an instruction | |
228 * @return the instruction that stores its result in {@code result} | |
229 */ | |
230 public Value instructionForResult(CiVariable result) { | |
231 if (variableDefs.size() > result.index) { | |
232 return variableDefs.get(result.index); | |
233 } | |
234 return null; | |
235 } | |
236 | |
237 public boolean mustStartInMemory(CiVariable operand) { | |
238 return get(mustStartInMemory, operand) || get(mustStayInMemory, operand); | |
239 } | |
240 | |
241 public boolean mustStayInMemory(CiVariable operand) { | |
242 return get(mustStayInMemory, operand); | |
243 } | |
244 | |
245 public boolean mustBeByteRegister(CiValue operand) { | |
246 return get(mustBeByteRegister, (CiVariable) operand); | |
247 } | |
248 | |
249 public void setMustBeByteRegister(CiVariable operand) { | |
250 mustBeByteRegister = set(mustBeByteRegister, operand); | |
251 } | |
252 | |
253 /** | |
254 * Gets the number of operands in this pool. This value will increase by 1 for | |
255 * each new variable operand {@linkplain #newVariable(CiKind) allocated} from this pool. | |
256 */ | |
257 public int size() { | |
258 return firstVariableNumber + variables.size(); | |
259 } | |
260 | |
261 /** | |
262 * Gets the highest operand number for a register operand in this pool. This value will | |
263 * never change for the lifetime of this pool. | |
264 */ | |
265 public int maxRegisterNumber() { | |
266 return firstVariableNumber - 1; | |
267 } | |
268 } |