AMD64FrameMap.java revision 12968:4d8a004e5c6d
1251881Speter/*
2251881Speter * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
3251881Speter * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4251881Speter *
5251881Speter * This code is free software; you can redistribute it and/or modify it
6251881Speter * under the terms of the GNU General Public License version 2 only, as
7251881Speter * published by the Free Software Foundation.
8251881Speter *
9251881Speter * This code is distributed in the hope that it will be useful, but WITHOUT
10251881Speter * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11251881Speter * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12251881Speter * version 2 for more details (a copy is included in the LICENSE file that
13251881Speter * accompanied this code).
14251881Speter *
15251881Speter * You should have received a copy of the GNU General Public License version
16251881Speter * 2 along with this work; if not, write to the Free Software Foundation,
17251881Speter * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18251881Speter *
19251881Speter * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20251881Speter * or visit www.oracle.com if you need additional information or have any
21251881Speter * questions.
22251881Speter */
23299742Sdimpackage org.graalvm.compiler.lir.amd64;
24251881Speter
25251881Speterimport static jdk.vm.ci.code.ValueUtil.asStackSlot;
26251881Speter
27251881Speterimport org.graalvm.compiler.core.common.NumUtil;
28251881Speterimport org.graalvm.compiler.core.common.LIRKind;
29251881Speterimport org.graalvm.compiler.lir.framemap.FrameMap;
30251881Speter
31251881Speterimport jdk.vm.ci.amd64.AMD64Kind;
32251881Speterimport jdk.vm.ci.code.CodeCacheProvider;
33251881Speterimport jdk.vm.ci.code.RegisterConfig;
34251881Speterimport jdk.vm.ci.code.StackSlot;
35251881Speter
36251881Speter/**
37251881Speter * AMD64 specific frame map.
38251881Speter *
39251881Speter * This is the format of an AMD64 stack frame:
40251881Speter *
41251881Speter * <pre>
42251881Speter *   Base       Contents
43251881Speter *
44251881Speter *            :                                :  -----
45251881Speter *   caller   | incoming overflow argument n   |    ^
46251881Speter *   frame    :     ...                        :    | positive
47251881Speter *            | incoming overflow argument 0   |    | offsets
48251881Speter *   ---------+--------------------------------+---------------------
49251881Speter *            | return address                 |    |            ^
50251881Speter *   current  +--------------------------------+    |            |    -----
51251881Speter *   frame    |                                |    |            |      ^
52251881Speter *            : callee save area               :    |            |      |
53251881Speter *            |                                |    |            |      |
54251881Speter *            +--------------------------------+    |            |      |
55251881Speter *            | spill slot 0                   |    | negative   |      |
56251881Speter *            :     ...                        :    v offsets    |      |
57251881Speter *            | spill slot n                   |  -----        total  frame
58251881Speter *            +--------------------------------+               frame  size
59251881Speter *            | alignment padding              |               size     |
60251881Speter *            +--------------------------------+  -----          |      |
61251881Speter *            | outgoing overflow argument n   |    ^            |      |
62251881Speter *            :     ...                        :    | positive   |      |
63251881Speter *            | outgoing overflow argument 0   |    | offsets    v      v
64251881Speter *    %sp--&gt;  +--------------------------------+---------------------------
65251881Speter *
66251881Speter * </pre>
67251881Speter *
68251881Speter * The spill slot area also includes stack allocated memory blocks (ALLOCA blocks). The size of such
69251881Speter * a block may be greater than the size of a normal spill slot or the word size.
70251881Speter * <p>
71251881Speter * A runtime can reserve space at the beginning of the overflow argument area. The calling
72251881Speter * convention can specify that the first overflow stack argument is not at offset 0, but at a
73251881Speter * specified offset. Use {@link CodeCacheProvider#getMinimumOutgoingSize()} to make sure that
74251881Speter * call-free methods also have this space reserved. Then the VM can use the memory at offset 0
75251881Speter * relative to the stack pointer.
76251881Speter */
77251881Speterpublic class AMD64FrameMap extends FrameMap {
78251881Speter
79251881Speter    private StackSlot rbpSpillSlot;
80251881Speter
81251881Speter    public AMD64FrameMap(CodeCacheProvider codeCache, RegisterConfig registerConfig, ReferenceMapBuilderFactory referenceMapFactory) {
82251881Speter        super(codeCache, registerConfig, referenceMapFactory);
83251881Speter        // (negative) offset relative to sp + total frame size
84251881Speter        initialSpillSize = returnAddressSize();
85251881Speter        spillSize = initialSpillSize;
86251881Speter    }
87251881Speter
88251881Speter    @Override
89251881Speter    public int totalFrameSize() {
90251881Speter        return frameSize() + returnAddressSize();
91251881Speter    }
92251881Speter
93251881Speter    @Override
94251881Speter    public int currentFrameSize() {
95251881Speter        return alignFrameSize(outgoingSize + spillSize - returnAddressSize());
96251881Speter    }
97251881Speter
98251881Speter    @Override
99251881Speter    protected int alignFrameSize(int size) {
100251881Speter        return NumUtil.roundUp(size + returnAddressSize(), getTarget().stackAlignment) - returnAddressSize();
101251881Speter    }
102251881Speter
103251881Speter    @Override
104251881Speter    public int offsetForStackSlot(StackSlot slot) {
105251881Speter        // @formatter:off
106251881Speter        assert (!slot.getRawAddFrameSize() && slot.getRawOffset() <  outgoingSize) ||
107251881Speter               (slot.getRawAddFrameSize() && slot.getRawOffset()  <  0 && -slot.getRawOffset() <= spillSize) ||
108251881Speter               (slot.getRawAddFrameSize() && slot.getRawOffset()  >= 0) :
109251881Speter                   String.format("RawAddFrameSize: %b RawOffset: 0x%x spillSize: 0x%x outgoingSize: 0x%x", slot.getRawAddFrameSize(), slot.getRawOffset(), spillSize, outgoingSize);
110251881Speter        // @formatter:on
111251881Speter        return super.offsetForStackSlot(slot);
112251881Speter    }
113251881Speter
114251881Speter    /**
115251881Speter     * For non-leaf methods, RBP is preserved in the special stack slot required by the HotSpot
116251881Speter     * runtime for walking/inspecting frames of such methods.
117251881Speter     */
118251881Speter    StackSlot allocateRBPSpillSlot() {
119251881Speter        assert spillSize == initialSpillSize : "RBP spill slot must be the first allocated stack slots";
120251881Speter        rbpSpillSlot = allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
121251881Speter        assert asStackSlot(rbpSpillSlot).getRawOffset() == -16 : asStackSlot(rbpSpillSlot).getRawOffset();
122251881Speter        return rbpSpillSlot;
123251881Speter    }
124251881Speter
125251881Speter    void freeRBPSpillSlot() {
126251881Speter        int size = spillSlotSize(LIRKind.value(AMD64Kind.QWORD));
127251881Speter        assert spillSize == NumUtil.roundUp(initialSpillSize + size, size) : "RBP spill slot can not be freed after allocation other stack slots";
128251881Speter        spillSize = initialSpillSize;
129251881Speter    }
130251881Speter
131251881Speter    public StackSlot allocateDeoptimizationRescueSlot() {
132251881Speter        assert spillSize == initialSpillSize || spillSize == initialSpillSize +
133251881Speter                        spillSlotSize(LIRKind.value(AMD64Kind.QWORD)) : "Deoptimization rescue slot must be the first or second (if there is an RBP spill slot) stack slot";
134251881Speter        return allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
135251881Speter    }
136251881Speter}
137251881Speter