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--> +--------------------------------+--------------------------- 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