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 * +-> | FP=0 | <-- "end of vm stack" sentinel . 049 * | +---------------+ . caller's frame 050 * | | cmid=0 | <-- "invisible method" id . 051 * | +---------------+ ---. 052 * | | parameter0 | \ | . 053 * | +---------------+ \ parameter area | . 054 * | | parameter1 | / (== caller's operand stack area) | . 055 * --- | +---------------+ / |... 056 * | | | saved IP | <-- return address (in caller) | 057 * | \ +---------------+ | 058 * header FP-> | saved FP | <-- this frame's caller's frame | 059 * | +---------------+ | 060 * | | cmid | <-- 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-> | operand1 | / | 073 * | +---------------+ / | 074 * | | ... | | 075 * --- +===============+ --- 076 * | ... | 077 * +---------------+ 078 * stackLimit-> | ... | \ 079 * +---------------+ \_guard region for detecting & 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 * +-> | FP=0 | <-- "end of vm stack" sentinel . 094 * | +---------------+ . caller's frame 095 * | | cmid=-1 | <-- "invisible method" id . 096 * | +---------------+ ---. 097 * | | parameter0 | \ | . 098 * | +---------------+ \ parameter area | . 099 * | | parameter1 | / (== caller's operand stack area) | . 100 * --- | +---------------+ / |... 101 * | | | saved IP | <-- return address (in caller) | 102 * | \ +---------------+ | 103 * header FP-> | saved FP | <-- this frame's caller's frame | 104 * | +---------------+ | 105 * | | cmid | <-- this frame's compiledmethod id | 106 * --- +---------------+ | 107 * | | | | 108 * | | Spill Area | <-- 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] | <-- 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-> | parameter1 | / | 129 * | +---------------+ / | 130 * | | ... | | 131 * --- +===============+ --- 132 * | ... | 133 * +---------------+ 134 * stackLimit-> | ... | \ 135 * +---------------+ \_guard region for detecting & 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}