comparison graal/com.oracle.max.graal.compiler/src/com/sun/c1x/alloc/OperandPool.java @ 2872:0341b6424579

Project renaming.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Wed, 08 Jun 2011 08:42:25 +0200
parents graal/GraalCompiler/src/com/sun/c1x/alloc/OperandPool.java@16b9a8b5ad39
children
comparison
equal deleted inserted replaced
2871:d704eb526603 2872:0341b6424579
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 }