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 }