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     * <p>
034     * Here's a picture of what a stack might look like in memory.
035     * <p>
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     * </pre>
081     *
082     *
083     *  The opt compiler uses a different stackframe layout
084     * <pre>
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      /** Currently only use the low 8 bytes, only use 4 SSE2 params */
158      int XMM_STATE_SIZE = 8 * 4;
159    
160      /** fp value indicating end of stack walkback */
161      Address STACKFRAME_SENTINEL_FP = Address.fromIntSignExtend(-2);
162      /** marker for "assembler" frames that have no associated RVMMethod */
163      int INVISIBLE_METHOD_ID = -1;
164    
165      // Stackframe alignment.
166      // Align to 8 byte boundary for good floating point save/restore performance (on powerPC, anyway).
167      //
168      int STACKFRAME_ALIGNMENT = 8;
169    
170      // Sizes for stacks and subregions thereof.
171      // Values are in bytes and must be a multiple of WORDSIZE (size of a stack slot).
172      //
173      /** how much to grow stack when overflow detected */
174      int STACK_SIZE_GROW = (VM.BuildFor64Addr ? 16 : 8) * 1024;
175      /** max space needed for stack overflow trap processing */
176      int STACK_SIZE_GUARD = 64 * 1024;
177      /** max space needed for any native code called by vm */
178      int STACK_SIZE_SYSCALL = (VM.BuildFor64Addr ? 8 : 4) * 1024;
179      /** max space needed for dlopen sys call */
180      int STACK_SIZE_DLOPEN = 30 * 1024;
181      /** max space needed while running with gc disabled */
182      int STACK_SIZE_GCDISABLED = (VM.BuildFor64Addr ? 8 : 4) * 1024;
183    
184       // Complications:
185       // - STACK_SIZE_GUARD must be greater than STACK_SIZE_NATIVE or STACK_SIZE_GCDISABLED
186       //   to ensure that frames allocated by stack growing code will fit within guard region.
187       // - STACK_SIZE_GROW must be greater than STACK_SIZE_NATIVE or STACK_SIZE_GCDISABLED
188       //   to ensure that, if stack is grown prior to disabling gc or calling native code,
189       //   the new stack will accommodate that code without generating a stack overflow trap.
190       // - Values chosen for STACK_SIZE_NATIVE and STACK_SIZE_GCDISABLED are pure guesswork
191       //   selected by trial and error.
192    
193       // Stacks for "normal" threads grow as needed by trapping on guard region.
194       // Stacks for "boot" and "collector" threads are fixed in size and cannot grow.
195       //
196    
197      /** initial stack space to allocate for normal thread (includes guard region) */
198      int STACK_SIZE_NORMAL =
199          STACK_SIZE_GUARD +
200          STACK_SIZE_GCDISABLED +
201          200 * 1024;
202      /** total stack space to allocate for boot thread (includes guard region) */
203      int STACK_SIZE_BOOT =
204          STACK_SIZE_GUARD +
205          STACK_SIZE_GCDISABLED +
206          30 * 1024;
207      /** total stack space to allocate for collector thread (includes guard region) */
208      int STACK_SIZE_COLLECTOR =
209          STACK_SIZE_GUARD +
210          STACK_SIZE_GCDISABLED +
211          20 * 1024;
212      /** upper limit on stack size (includes guard region) */
213      int STACK_SIZE_MAX =
214          STACK_SIZE_GUARD + STACK_SIZE_GCDISABLED + 200 * 1024;
215    
216      int STACK_SIZE_JNINATIVE_GROW = 0; // TODO!!;
217    }