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