001/* 002 * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.lir.amd64; 024 025import jdk.internal.jvmci.code.*; 026import jdk.internal.jvmci.meta.*; 027import static jdk.internal.jvmci.code.ValueUtil.*; 028 029import com.oracle.graal.asm.*; 030import com.oracle.graal.lir.framemap.*; 031 032/** 033 * AMD64 specific frame map. 034 * 035 * This is the format of an AMD64 stack frame: 036 * 037 * <pre> 038 * Base Contents 039 * 040 * : : ----- 041 * caller | incoming overflow argument n | ^ 042 * frame : ... : | positive 043 * | incoming overflow argument 0 | | offsets 044 * ---------+--------------------------------+--------------------- 045 * | return address | | ^ 046 * current +--------------------------------+ | | ----- 047 * frame | | | | ^ 048 * : callee save area : | | | 049 * | | | | | 050 * +--------------------------------+ | | | 051 * | spill slot 0 | | negative | | 052 * : ... : v offsets | | 053 * | spill slot n | ----- total frame 054 * +--------------------------------+ frame size 055 * | alignment padding | size | 056 * +--------------------------------+ ----- | | 057 * | outgoing overflow argument n | ^ | | 058 * : ... : | positive | | 059 * | outgoing overflow argument 0 | | offsets v v 060 * %sp--> +--------------------------------+--------------------------- 061 * 062 * </pre> 063 * 064 * The spill slot area also includes stack allocated memory blocks (ALLOCA blocks). The size of such 065 * a block may be greater than the size of a normal spill slot or the word size. 066 * <p> 067 * A runtime can reserve space at the beginning of the overflow argument area. The calling 068 * convention can specify that the first overflow stack argument is not at offset 0, but at a 069 * specified offset. Use {@link CodeCacheProvider#getMinimumOutgoingSize()} to make sure that 070 * call-free methods also have this space reserved. Then the VM can use the memory at offset 0 071 * relative to the stack pointer. 072 */ 073public class AMD64FrameMap extends FrameMap { 074 075 private StackSlot rbpSpillSlot; 076 077 public AMD64FrameMap(CodeCacheProvider codeCache, RegisterConfig registerConfig, ReferenceMapBuilderFactory referenceMapFactory) { 078 super(codeCache, registerConfig, referenceMapFactory); 079 // (negative) offset relative to sp + total frame size 080 initialSpillSize = returnAddressSize() + calleeSaveAreaSize(); 081 spillSize = initialSpillSize; 082 } 083 084 @Override 085 public int totalFrameSize() { 086 return frameSize() + returnAddressSize(); 087 } 088 089 @Override 090 public int currentFrameSize() { 091 return alignFrameSize(outgoingSize + spillSize - returnAddressSize()); 092 } 093 094 @Override 095 protected int alignFrameSize(int size) { 096 return NumUtil.roundUp(size + returnAddressSize(), getTarget().stackAlignment) - returnAddressSize(); 097 } 098 099 @Override 100 public int offsetToCalleeSaveArea() { 101 return frameSize() - calleeSaveAreaSize(); 102 } 103 104 @Override 105 protected StackSlot allocateNewSpillSlot(LIRKind kind, int additionalOffset) { 106 return StackSlot.get(kind, -spillSize + additionalOffset, true); 107 } 108 109 @Override 110 public int offsetForStackSlot(StackSlot slot) { 111 // @formatter:off 112 assert (!slot.getRawAddFrameSize() && slot.getRawOffset() < outgoingSize) || 113 (slot.getRawAddFrameSize() && slot.getRawOffset() < 0 && -slot.getRawOffset() <= spillSize) || 114 (slot.getRawAddFrameSize() && slot.getRawOffset() >= 0) : 115 String.format("RawAddFrameSize: %b RawOffset: 0x%x spillSize: 0x%x outgoingSize: 0x%x", slot.getRawAddFrameSize(), slot.getRawOffset(), spillSize, outgoingSize); 116 // @formatter:on 117 return super.offsetForStackSlot(slot); 118 } 119 120 /** 121 * For non-leaf methods, RBP is preserved in the special stack slot required by the HotSpot 122 * runtime for walking/inspecting frames of such methods. 123 */ 124 StackSlot allocateRBPSpillSlot() { 125 assert spillSize == initialSpillSize : "RBP spill slot must be the first allocated stack slots"; 126 rbpSpillSlot = allocateSpillSlot(LIRKind.value(Kind.Long)); 127 assert asStackSlot(rbpSpillSlot).getRawOffset() == -16 : asStackSlot(rbpSpillSlot).getRawOffset(); 128 return rbpSpillSlot; 129 } 130 131 void freeRBPSpillSlot() { 132 int size = spillSlotSize(LIRKind.value(Kind.Long)); 133 assert spillSize == NumUtil.roundUp(initialSpillSize + size, size) : "RBP spill slot can not be freed after allocation other stack slots"; 134 spillSize = initialSpillSize; 135 } 136 137 public StackSlot allocateDeoptimizationRescueSlot() { 138 assert spillSize == initialSpillSize || spillSize == initialSpillSize + spillSlotSize(LIRKind.value(Kind.Long)) : "Deoptimization rescue slot must be the first or second (if there is an RBP spill slot) stack slot"; 139 return allocateSpillSlot(LIRKind.value(Kind.Long)); 140 } 141}