1 /*
2  * Copyright (c) 2010, 2016, 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 jdk.vm.ci.meta.AllocatableValue;
26 import jdk.vm.ci.meta.ValueKind;
27 
28 /**
29  * Represents a compiler spill slot or an outgoing stack-based argument in a method's frame or an
30  * incoming stack-based argument in a method's {@linkplain #isInCallerFrame() caller's frame}.
31  */
32 public final class StackSlot extends AllocatableValue {
33 
34     private final int offset;
35     private final boolean addFrameSize;
36 
37     /**
38      * Gets a {@link StackSlot} instance representing a stack slot at a given index holding a value
39      * of a given kind.
40      *
41      * @param kind The kind of the value stored in the stack slot.
42      * @param offset The offset of the stack slot (in bytes)
43      * @param addFrameSize Specifies if the offset is relative to the stack pointer, or the
44      *            beginning of the frame (stack pointer + total frame size).
45      */
get(ValueKind<?> kind, int offset, boolean addFrameSize)46     public static StackSlot get(ValueKind<?> kind, int offset, boolean addFrameSize) {
47         assert addFrameSize || offset >= 0;
48         return new StackSlot(kind, offset, addFrameSize);
49     }
50 
51     /**
52      * Private constructor to enforce use of {@link #get(ValueKind, int, boolean)} so that a cache
53      * can be used.
54      */
StackSlot(ValueKind<?> kind, int offset, boolean addFrameSize)55     private StackSlot(ValueKind<?> kind, int offset, boolean addFrameSize) {
56         super(kind);
57         this.offset = offset;
58         this.addFrameSize = addFrameSize;
59     }
60 
61     /**
62      * Gets the offset of this stack slot, relative to the stack pointer.
63      *
64      * @return The offset of this slot (in bytes).
65      */
getOffset(int totalFrameSize)66     public int getOffset(int totalFrameSize) {
67         assert totalFrameSize > 0 || !addFrameSize;
68         int result = offset + (addFrameSize ? totalFrameSize : 0);
69         assert result >= 0;
70         return result;
71     }
72 
isInCallerFrame()73     public boolean isInCallerFrame() {
74         return addFrameSize && offset >= 0;
75     }
76 
getRawOffset()77     public int getRawOffset() {
78         return offset;
79     }
80 
getRawAddFrameSize()81     public boolean getRawAddFrameSize() {
82         return addFrameSize;
83     }
84 
85     @Override
toString()86     public String toString() {
87         if (!addFrameSize) {
88             return "out:" + offset + getKindSuffix();
89         } else if (offset >= 0) {
90             return "in:" + offset + getKindSuffix();
91         } else {
92             return "stack:" + (-offset) + getKindSuffix();
93         }
94     }
95 
96     /**
97      * Gets this stack slot used to pass an argument from the perspective of a caller.
98      */
asOutArg()99     public StackSlot asOutArg() {
100         assert offset >= 0;
101         if (addFrameSize) {
102             return get(getValueKind(), offset, false);
103         }
104         return this;
105     }
106 
107     /**
108      * Gets this stack slot used to pass an argument from the perspective of a callee.
109      */
asInArg()110     public StackSlot asInArg() {
111         assert offset >= 0;
112         if (!addFrameSize) {
113             return get(getValueKind(), offset, true);
114         }
115         return this;
116     }
117 
118     @Override
hashCode()119     public int hashCode() {
120         final int prime = 37;
121         int result = super.hashCode();
122         result = prime * result + (addFrameSize ? 1231 : 1237);
123         result = prime * result + offset;
124         return result;
125     }
126 
127     @Override
equals(Object obj)128     public boolean equals(Object obj) {
129         if (obj instanceof StackSlot) {
130             StackSlot other = (StackSlot) obj;
131             return super.equals(obj) && addFrameSize == other.addFrameSize && offset == other.offset;
132         }
133         return false;
134     }
135 }
136