001 /*
002 * This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 * This file is licensed to You under the Eclipse Public License (EPL);
005 * You may not use this file except in compliance with the License. You
006 * may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 * See the COPYRIGHT.txt file distributed with this work for information
011 * regarding copyright ownership.
012 */
013 package org.jikesrvm.ia32;
014
015 import org.jikesrvm.SizeConstants;
016 import org.jikesrvm.VM;
017 import org.vmmagic.unboxed.Address;
018 import static org.jikesrvm.ia32.BaselineConstants.WORDSIZE;
019
020 /**----------------------------------------------------------------------
021 * Stackframe layout conventions - Intel version.
022 *-----------------------------------------------------------------------
023 *
024 * A stack is an array of "slots", declared formally as integers, each slot
025 * containing either a primitive (byte, int, float, etc), an object pointer,
026 * a machine code pointer (a return address pointer), or a pointer to another
027 * slot in the same stack (a frame pointer). The interpretation of a slot's
028 * contents depends on the current value of IP, the machine instruction
029 * address register.
030 * Each machine code generator provides maps, for use by the garbage collector,
031 * that tell how to interpret the stack slots at "safe points" in the
032 * program's execution.
033 *
034 * Here's a picture of what a stack might look like in memory.
035 *
036 * Note: this (array) object is drawn upside down compared to other objects
037 * because the hardware stack grows from high memory to low memory, but
038 * array objects are layed out from low memory to high (header first).
039 * <pre>
040 * hi-memory
041 * +---------------+ ...
042 * | IP=0 | .
043 * +---------------+ .
044 * +-> | FP=0 | <-- "end of vm stack" sentinel .
045 * | +---------------+ . caller's frame
046 * | | cmid=0 | <-- "invisible method" id .
047 * | +---------------+ ---.
048 * | | parameter0 | \ | .
049 * | +---------------+ \ parameter area | .
050 * | | parameter1 | / (== caller's operand stack area) | .
051 * --- | +---------------+ / |...
052 * | | | saved IP | <-- return address (in caller) |
053 * | \ +---------------+ |
054 * header FP-> | saved FP | <-- this frame's caller's frame |
055 * | +---------------+ |
056 * | | cmid | <-- this frame's compiledmethod id |
057 * | +---------------+ |
058 * | | saved GPRs | \ |
059 * | +---------------+ \ nonvolatile register save area |
060 * | | saved FPRS | / | frame
061 * | +---------------+ |
062 * | | local0 | \ |
063 * body +---------------+ \_local variables area |
064 * | | local1 | / |
065 * | +---------------+ / |
066 * | | operand0 | \ |
067 * | +---------------+ \_operand stack area |
068 * | SP-> | operand1 | / |
069 * | +---------------+ / |
070 * | | ... | |
071 * --- +===============+ ---
072 * | ... |
073 * +---------------+
074 * stackLimit-> | ... | \
075 * +---------------+ \_guard region for detecting & processing stack overflow
076 * | ... | /
077 * +---------------+ /
078 * |(object header)|
079 * low-memory +---------------+
080 *
081 *
082 *
083 * The opt compiler uses a different stackframe layout
084 *
085 * hi-memory
086 * +---------------+ ...
087 * | IP=0 | .
088 * +---------------+ .
089 * +-> | FP=0 | <-- "end of vm stack" sentinel .
090 * | +---------------+ . caller's frame
091 * | | cmid=-1 | <-- "invisible method" id .
092 * | +---------------+ ---.
093 * | | parameter0 | \ | .
094 * | +---------------+ \ parameter area | .
095 * | | parameter1 | / (== caller's operand stack area) | .
096 * --- | +---------------+ / |...
097 * | | | saved IP | <-- return address (in caller) |
098 * | \ +---------------+ |
099 * header FP-> | saved FP | <-- this frame's caller's frame |
100 * | +---------------+ |
101 * | | cmid | <-- this frame's compiledmethod id |
102 * --- +---------------+ |
103 * | | | |
104 * | | Spill Area | <-- spills and other method-specific |
105 * | | ... | compiler-managed storage |
106 * | +---------------+ |
107 * | | Saved FP | only SaveVolatile Frames |
108 * | | State | |
109 * | +---------------+ |
110 * | | VolGPR[0] | |
111 * | | ... | only SaveVolatile Frames |
112 * | | VolGPR[n] | |
113 * | +---------------+ |
114 * body | NVolGPR[k] | <-- info.getUnsignedNonVolatileOffset() | frame
115 * | | ... | k == info.getFirstNonVolatileGPR() |
116 * | | NVolGPR[n] | |
117 * | +---------------+ |
118 * | | NVolFPR[k] | |
119 * | | ... | k == info.getFirstNonVolatileFPR() |
120 * | | NVolFPR[n] | |
121 * | +---------------+ |
122 * | | parameter0 | \ |
123 * | +---------------+ \_parameters to callee frame |
124 * | SP-> | parameter1 | / |
125 * | +---------------+ / |
126 * | | ... | |
127 * --- +===============+ ---
128 * | ... |
129 * +---------------+
130 * stackLimit-> | ... | \
131 * +---------------+ \_guard region for detecting & processing stack overflow
132 * | ... | /
133 * +---------------+ /
134 * |(object header)|
135 * low-memory +---------------+
136 *
137 * </pre>
138 */
139 public interface StackframeLayoutConstants {
140
141 int LOG_BYTES_IN_STACKSLOT = SizeConstants.LOG_BYTES_IN_ADDRESS;
142 int BYTES_IN_STACKSLOT = 1 << LOG_BYTES_IN_STACKSLOT;
143
144 /** offset of caller's return address from FP */
145 int STACKFRAME_RETURN_ADDRESS_OFFSET = WORDSIZE;
146 /** base of this frame */
147 int STACKFRAME_FRAME_POINTER_OFFSET = 0;
148 /** offset of method id from FP */
149 int STACKFRAME_METHOD_ID_OFFSET = -WORDSIZE;
150 /** offset of work area from FP */
151 int STACKFRAME_BODY_OFFSET = -2*WORDSIZE;
152 /** size of frame header, in bytes */
153 int STACKFRAME_HEADER_SIZE = 3*WORDSIZE;
154
155 // space to save entire FPU state. The FPU state is saved only for 'bridge' frames
156 int FPU_STATE_SIZE = 108;
157 int XMM_STATE_SIZE = 8 * 4; // Currently only use the low 8 bytes, only use 4 SSE2 params
158
159 /** fp value indicating end of stack walkback */
160 Address STACKFRAME_SENTINEL_FP = Address.fromIntSignExtend(-2);
161 /** marker for "assembler" frames that have no associated RVMMethod */
162 int INVISIBLE_METHOD_ID = -1;
163
164 // Stackframe alignment.
165 // Align to 8 byte boundary for good floating point save/restore performance (on powerPC, anyway).
166 //
167 int STACKFRAME_ALIGNMENT = 8;
168
169 // Sizes for stacks and subregions thereof.
170 // Values are in bytes and must be a multiple of WORDSIZE (size of a stack slot).
171 //
172 /** how much to grow stack when overflow detected */
173 int STACK_SIZE_GROW = (VM.BuildFor64Addr ? 16 : 8) * 1024;
174 /** max space needed for stack overflow trap processing */
175 int STACK_SIZE_GUARD = 64 * 1024;
176 /** max space needed for any native code called by vm */
177 int STACK_SIZE_SYSCALL = (VM.BuildFor64Addr ? 8 : 4) * 1024;
178 /** max space needed for dlopen sys call */
179 int STACK_SIZE_DLOPEN = 30 * 1024;
180 /** max space needed while running with gc disabled */
181 int STACK_SIZE_GCDISABLED = (VM.BuildFor64Addr ? 8 : 4) * 1024;
182
183 // Complications:
184 // - STACK_SIZE_GUARD must be greater than STACK_SIZE_NATIVE or STACK_SIZE_GCDISABLED
185 // to ensure that frames allocated by stack growing code will fit within guard region.
186 // - STACK_SIZE_GROW must be greater than STACK_SIZE_NATIVE or STACK_SIZE_GCDISABLED
187 // to ensure that, if stack is grown prior to disabling gc or calling native code,
188 // the new stack will accomodate that code without generating a stack overflow trap.
189 // - Values chosen for STACK_SIZE_NATIVE and STACK_SIZE_GCDISABLED are pure guesswork
190 // selected by trial and error.
191
192 // Stacks for "normal" threads grow as needed by trapping on guard region.
193 // Stacks for "boot" and "collector" threads are fixed in size and cannot grow.
194 //
195 /** initial stack space to allocate for normal thread (includes guard region) */
196 int STACK_SIZE_NORMAL =
197 STACK_SIZE_GUARD +
198 STACK_SIZE_GCDISABLED +
199 200 * 1024; // initial stack space to allocate for normal thread (includes guard region)
200 int STACK_SIZE_BOOT =
201 STACK_SIZE_GUARD +
202 STACK_SIZE_GCDISABLED +
203 30 * 1024; // total stack space to allocate for boot thread (includes guard region)
204 int STACK_SIZE_COLLECTOR =
205 STACK_SIZE_GUARD +
206 STACK_SIZE_GCDISABLED +
207 20 * 1024; // total stack space to allocate for collector thread (includes guard region)
208 int STACK_SIZE_MAX =
209 STACK_SIZE_GUARD + STACK_SIZE_GCDISABLED + 200 * 1024; // upper limit on stack size (includes guard region)
210
211 int STACK_SIZE_JNINATIVE_GROW = 0; // TODO!!;
212 }