1 /*
2  * Copyright (c) 2013, 2014, 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 jdk.vm.ci.code;
24 
25 import java.util.Arrays;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Map;
29 import java.util.TreeMap;
30 
31 /**
32  * A map from registers to frame slots. This can be used to describe where callee saved registers
33  * are saved in a callee's frame.
34  */
35 public final class RegisterSaveLayout {
36 
37     /**
38      * Keys.
39      */
40     private final Register[] registers;
41 
42     /**
43      * Slot indexes relative to stack pointer.
44      */
45     private final int[] slots;
46 
47     /**
48      * Creates a map from registers to frame slots.
49      *
50      * @param registers the keys in the map
51      * @param slots frame slot index for each register in {@code registers}
52      */
53     @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `registers` and `slots`")
RegisterSaveLayout(Register[] registers, int[] slots)54     public RegisterSaveLayout(Register[] registers, int[] slots) {
55         assert registers.length == slots.length;
56         this.registers = registers;
57         this.slots = slots;
58         assert registersToSlots(false).size() == registers.length : "non-unique registers";
59         assert new HashSet<>(registersToSlots(false).values()).size() == slots.length : "non-unqiue slots";
60     }
61 
62     /**
63      * Gets the frame slot index for a given register.
64      *
65      * @param register register to get the frame slot index for
66      * @return frame slot index
67      */
registerToSlot(Register register)68     public int registerToSlot(Register register) {
69         for (int i = 0; i < registers.length; i++) {
70             if (register.equals(registers[i])) {
71                 return slots[i];
72             }
73         }
74         throw new IllegalArgumentException(register + " not saved by this layout: " + this);
75     }
76 
77     /**
78      * Gets this layout information as a {@link Map} from registers to slots.
79      */
registersToSlots(boolean sorted)80     public Map<Register, Integer> registersToSlots(boolean sorted) {
81         Map<Register, Integer> result;
82         if (sorted) {
83             result = new TreeMap<>();
84         } else {
85             result = new HashMap<>();
86         }
87         for (int i = 0; i < registers.length; i++) {
88             result.put(registers[i], slots[i]);
89         }
90         return result;
91     }
92 
93     /**
94      * Gets this layout information as a {@link Map} from slots to registers.
95      */
slotsToRegisters(boolean sorted)96     public Map<Integer, Register> slotsToRegisters(boolean sorted) {
97         Map<Integer, Register> result;
98         if (sorted) {
99             result = new TreeMap<>();
100         } else {
101             result = new HashMap<>();
102         }
103         for (int i = 0; i < registers.length; i++) {
104             result.put(slots[i], registers[i]);
105         }
106         return result;
107     }
108 
109     @Override
hashCode()110     public int hashCode() {
111         throw new UnsupportedOperationException();
112     }
113 
114     @Override
equals(Object obj)115     public boolean equals(Object obj) {
116         if (this == obj) {
117             return true;
118         }
119         if (obj instanceof RegisterSaveLayout) {
120             RegisterSaveLayout that = (RegisterSaveLayout) obj;
121             if (Arrays.equals(registers, that.registers) && Arrays.equals(slots, that.slots)) {
122                 return true;
123             }
124         }
125         return false;
126     }
127 
128     @Override
toString()129     public String toString() {
130         return registersToSlots(true).toString();
131     }
132 }
133