64 * : ... : | positive | |
65 * | outgoing overflow argument 0 | | offsets v v
66 * %sp--> +--------------------------------+---------------------------
67 *
68 * </pre>
69 *
70 * The spill slot area also includes stack allocated memory blocks (ALLOCA blocks). The size of such
71 * a block may be greater than the size of a normal spill slot or the word size.
72 * <p>
73 * A runtime can reserve space at the beginning of the overflow argument area. The calling
74 * convention can specify that the first overflow stack argument is not at offset 0, but at a
75 * specified offset. Use {@link CodeCacheProvider#getMinimumOutgoingSize()} to make sure that
76 * call-free methods also have this space reserved. Then the VM can use the memory at offset 0
77 * relative to the stack pointer.
78 */
79 public class AMD64FrameMap extends FrameMap {
80
81 private StackSlot rbpSpillSlot;
82
83 public AMD64FrameMap(CodeCacheProvider codeCache, RegisterConfig registerConfig, ReferenceMapBuilderFactory referenceMapFactory) {
84 super(codeCache, registerConfig, referenceMapFactory);
85 // (negative) offset relative to sp + total frame size
86 initialSpillSize = returnAddressSize();
87 spillSize = initialSpillSize;
88 }
89
90 @Override
91 public int totalFrameSize() {
92 return frameSize() + returnAddressSize();
93 }
94
95 @Override
96 public int currentFrameSize() {
97 return alignFrameSize(outgoingSize + spillSize - returnAddressSize());
98 }
99
100 @Override
101 protected int alignFrameSize(int size) {
102 return NumUtil.roundUp(size + returnAddressSize(), getTarget().stackAlignment) - returnAddressSize();
103 }
104
105 @Override
106 public int offsetForStackSlot(StackSlot slot) {
107 // @formatter:off
108 assert (!slot.getRawAddFrameSize() && slot.getRawOffset() < outgoingSize) ||
109 (slot.getRawAddFrameSize() && slot.getRawOffset() < 0 && -slot.getRawOffset() <= spillSize) ||
110 (slot.getRawAddFrameSize() && slot.getRawOffset() >= 0) :
111 String.format("RawAddFrameSize: %b RawOffset: 0x%x spillSize: 0x%x outgoingSize: 0x%x", slot.getRawAddFrameSize(), slot.getRawOffset(), spillSize, outgoingSize);
112 // @formatter:on
113 return super.offsetForStackSlot(slot);
114 }
115
116 /**
117 * For non-leaf methods, RBP is preserved in the special stack slot required by the HotSpot
118 * runtime for walking/inspecting frames of such methods.
119 */
120 StackSlot allocateRBPSpillSlot() {
121 assert spillSize == initialSpillSize : "RBP spill slot must be the first allocated stack slots";
122 rbpSpillSlot = allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
|
64 * : ... : | positive | |
65 * | outgoing overflow argument 0 | | offsets v v
66 * %sp--> +--------------------------------+---------------------------
67 *
68 * </pre>
69 *
70 * The spill slot area also includes stack allocated memory blocks (ALLOCA blocks). The size of such
71 * a block may be greater than the size of a normal spill slot or the word size.
72 * <p>
73 * A runtime can reserve space at the beginning of the overflow argument area. The calling
74 * convention can specify that the first overflow stack argument is not at offset 0, but at a
75 * specified offset. Use {@link CodeCacheProvider#getMinimumOutgoingSize()} to make sure that
76 * call-free methods also have this space reserved. Then the VM can use the memory at offset 0
77 * relative to the stack pointer.
78 */
79 public class AMD64FrameMap extends FrameMap {
80
81 private StackSlot rbpSpillSlot;
82
83 public AMD64FrameMap(CodeCacheProvider codeCache, RegisterConfig registerConfig, ReferenceMapBuilderFactory referenceMapFactory) {
84 this(codeCache, registerConfig, referenceMapFactory, false);
85 }
86
87 public AMD64FrameMap(CodeCacheProvider codeCache, RegisterConfig registerConfig, ReferenceMapBuilderFactory referenceMapFactory, boolean useBasePointer) {
88 super(codeCache, registerConfig, referenceMapFactory);
89 // (negative) offset relative to sp + total frame size
90 initialSpillSize = returnAddressSize() + (useBasePointer ? getTarget().arch.getWordSize() : 0);
91 spillSize = initialSpillSize;
92 }
93
94 @Override
95 public int totalFrameSize() {
96 int result = frameSize() + initialSpillSize;
97 assert result % getTarget().stackAlignment == 0 : "Total frame size not aligned: " + result;
98 return result;
99 }
100
101 @Override
102 public int currentFrameSize() {
103 return alignFrameSize(outgoingSize + spillSize - initialSpillSize);
104 }
105
106 @Override
107 protected int alignFrameSize(int size) {
108 return NumUtil.roundUp(size + initialSpillSize, getTarget().stackAlignment) - initialSpillSize;
109 }
110
111 @Override
112 public int offsetForStackSlot(StackSlot slot) {
113 // @formatter:off
114 assert (!slot.getRawAddFrameSize() && slot.getRawOffset() < outgoingSize) ||
115 (slot.getRawAddFrameSize() && slot.getRawOffset() < 0 && -slot.getRawOffset() <= spillSize) ||
116 (slot.getRawAddFrameSize() && slot.getRawOffset() >= 0) :
117 String.format("RawAddFrameSize: %b RawOffset: 0x%x spillSize: 0x%x outgoingSize: 0x%x", slot.getRawAddFrameSize(), slot.getRawOffset(), spillSize, outgoingSize);
118 // @formatter:on
119 return super.offsetForStackSlot(slot);
120 }
121
122 /**
123 * For non-leaf methods, RBP is preserved in the special stack slot required by the HotSpot
124 * runtime for walking/inspecting frames of such methods.
125 */
126 StackSlot allocateRBPSpillSlot() {
127 assert spillSize == initialSpillSize : "RBP spill slot must be the first allocated stack slots";
128 rbpSpillSlot = allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
|