Mercurial > hg > truffle
comparison graal/com.oracle.jvmci.code/src/com/oracle/jvmci/code/CalleeSaveLayout.java @ 21556:48c1ebd24120
renamed com.oracle.graal.api[meta|code] modules to com.oracle.jvmci.[meta|code] (JBS:GRAAL-53)
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Wed, 27 May 2015 00:36:16 +0200 |
parents | graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CalleeSaveLayout.java@1cde96b96673 |
children | f5b549811bac |
comparison
equal
deleted
inserted
replaced
21555:d12eaef9af72 | 21556:48c1ebd24120 |
---|---|
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.oracle.jvmci.code; | |
24 | |
25 import com.oracle.jvmci.meta.PlatformKind; | |
26 import java.util.*; | |
27 | |
28 | |
29 /** | |
30 * The callee save area (CSA) is a contiguous space in a stack frame used to save (and restore) the | |
31 * values of the caller's registers. This class describes the layout of a CSA in terms of its | |
32 * {@linkplain #size size}, {@linkplain #slotSize slot size} and the {@linkplain #registers callee | |
33 * save registers} covered by the CSA. | |
34 */ | |
35 public class CalleeSaveLayout { | |
36 | |
37 /** | |
38 * The size (in bytes) of the CSA. | |
39 */ | |
40 public final int size; | |
41 | |
42 /** | |
43 * The size (in bytes) of an {@linkplain #registerAt(int) indexable} slot in the CSA. | |
44 */ | |
45 public final int slotSize; | |
46 | |
47 /** | |
48 * Map from {@linkplain Register#number register numbers} to slot indexes in the CSA. | |
49 */ | |
50 private final int[] regNumToIndex; | |
51 | |
52 private final Register[] indexToReg; | |
53 | |
54 /** | |
55 * The list of registers {@linkplain #contains(int) contained} by this CSA. | |
56 */ | |
57 public final Register[] registers; | |
58 | |
59 /** | |
60 * The offset from the frame pointer to the CSA. If this is not known, then this field will have | |
61 * the value {@link Integer#MAX_VALUE}. | |
62 */ | |
63 public final int frameOffsetToCSA; | |
64 | |
65 /** | |
66 * Creates a CSA layout. | |
67 * | |
68 * @param size size (in bytes) of the CSA. If this is {@code -1}, then the CSA size will be | |
69 * computed from {@code registers}. | |
70 * @param slotSize the size (in bytes) of an {@linkplain #registerAt(int) indexable} slot in the | |
71 * CSA | |
72 * @param registers the registers that can be saved in the CSA | |
73 */ | |
74 public CalleeSaveLayout(TargetDescription target, int frameOffsetToCSA, int size, int slotSize, Register... registers) { | |
75 this.frameOffsetToCSA = frameOffsetToCSA; | |
76 assert slotSize == 0 || CodeUtil.isPowerOf2(slotSize); | |
77 this.slotSize = slotSize; | |
78 int maxRegNum = -1; | |
79 int maxOffset = 0; | |
80 this.registers = registers; | |
81 int offset = 0; | |
82 for (Register reg : registers) { | |
83 assert offset % slotSize == 0; | |
84 assert reg.number >= 0; | |
85 if (reg.number > maxRegNum) { | |
86 maxRegNum = reg.number; | |
87 } | |
88 if (offset > maxOffset) { | |
89 maxOffset = offset; | |
90 } | |
91 PlatformKind kind = target.arch.getLargestStorableKind(reg.getRegisterCategory()); | |
92 offset += target.getSizeInBytes(kind); | |
93 } | |
94 if (size == -1) { | |
95 this.size = offset; | |
96 } else { | |
97 assert offset <= size; | |
98 this.size = size; | |
99 } | |
100 | |
101 this.regNumToIndex = new int[maxRegNum + 1]; | |
102 this.indexToReg = offset == 0 ? new Register[0] : new Register[offset / slotSize]; | |
103 Arrays.fill(regNumToIndex, -1); | |
104 offset = 0; | |
105 for (Register reg : registers) { | |
106 int index = offset / slotSize; | |
107 regNumToIndex[reg.number] = index; | |
108 indexToReg[index] = reg; | |
109 PlatformKind kind = target.arch.getLargestStorableKind(reg.getRegisterCategory()); | |
110 offset += target.getSizeInBytes(kind); | |
111 } | |
112 } | |
113 | |
114 /** | |
115 * Gets the offset of a given register in the CSA. | |
116 * | |
117 * @return the offset (in bytes) of {@code reg} in the CSA | |
118 * @throws IllegalArgumentException if {@code reg} does not have a slot in the CSA | |
119 */ | |
120 public int offsetOf(int reg) { | |
121 return indexOf(reg) * slotSize; | |
122 } | |
123 | |
124 /** | |
125 * Gets the index of a given register in the CSA. | |
126 * | |
127 * @return the index of {@code reg} in the CSA | |
128 * @throws IllegalArgumentException if {@code reg} does not have a slot in the CSA | |
129 */ | |
130 public int indexOf(int reg) { | |
131 if (!contains(reg)) { | |
132 throw new IllegalArgumentException(String.valueOf(reg)); | |
133 } | |
134 return regNumToIndex[reg]; | |
135 } | |
136 | |
137 /** | |
138 * Gets the offset of a given register in the CSA. | |
139 * | |
140 * @return the offset (in bytes) of {@code reg} in the CSA | |
141 * @throws IllegalArgumentException if {@code reg} does not have a slot in the CSA | |
142 */ | |
143 public int offsetOf(Register reg) { | |
144 return offsetOf(reg.number); | |
145 } | |
146 | |
147 /** | |
148 * Determines if the CSA includes a slot for a given register. | |
149 * | |
150 * @param reg the register to test | |
151 * @return true if the CSA contains a slot for {@code reg} | |
152 */ | |
153 public boolean contains(int reg) { | |
154 return reg >= 0 && reg < regNumToIndex.length && regNumToIndex[reg] != -1; | |
155 } | |
156 | |
157 /** | |
158 * Gets the register whose slot in the CSA is at a given index. | |
159 * | |
160 * @param index an index of a slot in the CSA | |
161 * @return the register whose slot in the CSA is at {@code index} or {@code null} if | |
162 * {@code index} does not denote a slot in the CSA aligned with a register | |
163 */ | |
164 public Register registerAt(int index) { | |
165 if (index < 0 || index >= indexToReg.length) { | |
166 return null; | |
167 } | |
168 return indexToReg[index]; | |
169 } | |
170 | |
171 @Override | |
172 public String toString() { | |
173 StringBuilder sb = new StringBuilder("["); | |
174 for (Register reg : registers) { | |
175 if (sb.length() != 1) { | |
176 sb.append(", "); | |
177 } | |
178 sb.append(reg).append("{+").append(offsetOf(reg)).append('}'); | |
179 } | |
180 return sb.append("] size=").append(size).toString(); | |
181 } | |
182 } |