1 // Copyright 2017 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_FRAME_CONSTANTS_H_ 6 #define V8_FRAME_CONSTANTS_H_ 7 8 #include "src/flags.h" 9 #include "src/globals.h" 10 11 namespace v8 { 12 namespace internal { 13 14 // Every pointer in a frame has a slot id. On 32-bit platforms, doubles consume 15 // two slots. 16 // 17 // Stack slot indices >= 0 access the callee stack with slot 0 corresponding to 18 // the callee's saved return address and 1 corresponding to the saved frame 19 // pointer. Some frames have additional information stored in the fixed header, 20 // for example JSFunctions store the function context and marker in the fixed 21 // header, with slot index 2 corresponding to the current function context and 3 22 // corresponding to the frame marker/JSFunction. 23 // 24 // slot JS frame 25 // +-----------------+-------------------------------- 26 // -n-1 | parameter 0 | ^ 27 // |- - - - - - - - -| | 28 // -n | | Caller 29 // ... | ... | frame slots 30 // -2 | parameter n-1 | (slot < 0) 31 // |- - - - - - - - -| | 32 // -1 | parameter n | v 33 // -----+-----------------+-------------------------------- 34 // 0 | return addr | ^ ^ 35 // |- - - - - - - - -| | | 36 // 1 | saved frame ptr | Fixed | 37 // |- - - - - - - - -| Header <-- frame ptr | 38 // 2 | [Constant Pool] | | | 39 // |- - - - - - - - -| | | 40 // 2+cp |Context/Frm. Type| v if a constant pool | 41 // |-----------------+---- is used, cp = 1, | 42 // 3+cp | | ^ otherwise, cp = 0 | 43 // |- - - - - - - - -| | | 44 // 4+cp | | | Callee 45 // |- - - - - - - - -| | frame slots 46 // ... | | Frame slots (slot >= 0) 47 // |- - - - - - - - -| | | 48 // | | v | 49 // -----+-----------------+----- <-- stack ptr ------------- 50 // 51 class CommonFrameConstants : public AllStatic { 52 public: 53 static constexpr int kCallerFPOffset = 0 * kPointerSize; 54 static constexpr int kCallerPCOffset = kCallerFPOffset + 1 * kFPOnStackSize; 55 static constexpr int kCallerSPOffset = kCallerPCOffset + 1 * kPCOnStackSize; 56 57 // Fixed part of the frame consists of return address, caller fp, 58 // constant pool (if FLAG_enable_embedded_constant_pool), context, and 59 // function. StandardFrame::IterateExpressions assumes that kLastObjectOffset 60 // is the last object pointer. 61 static constexpr int kFixedFrameSizeAboveFp = kPCOnStackSize + kFPOnStackSize; 62 static constexpr int kFixedSlotCountAboveFp = 63 kFixedFrameSizeAboveFp / kPointerSize; 64 static constexpr int kCPSlotSize = 65 FLAG_enable_embedded_constant_pool ? kPointerSize : 0; 66 static constexpr int kCPSlotCount = kCPSlotSize / kPointerSize; 67 static constexpr int kConstantPoolOffset = 68 kCPSlotSize ? -1 * kPointerSize : 0; 69 static constexpr int kContextOrFrameTypeSize = kPointerSize; 70 static constexpr int kContextOrFrameTypeOffset = 71 -(kCPSlotSize + kContextOrFrameTypeSize); 72 }; 73 74 // StandardFrames are used for interpreted, full-codegen and optimized 75 // JavaScript frames. They always have a context below the saved fp/constant 76 // pool and below that the JSFunction of the executing function. 77 // 78 // slot JS frame 79 // +-----------------+-------------------------------- 80 // -n-1 | parameter 0 | ^ 81 // |- - - - - - - - -| | 82 // -n | | Caller 83 // ... | ... | frame slots 84 // -2 | parameter n-1 | (slot < 0) 85 // |- - - - - - - - -| | 86 // -1 | parameter n | v 87 // -----+-----------------+-------------------------------- 88 // 0 | return addr | ^ ^ 89 // |- - - - - - - - -| | | 90 // 1 | saved frame ptr | Fixed | 91 // |- - - - - - - - -| Header <-- frame ptr | 92 // 2 | [Constant Pool] | | | 93 // |- - - - - - - - -| | | 94 // 2+cp | Context | | if a constant pool | 95 // |- - - - - - - - -| | is used, cp = 1, | 96 // 3+cp | JSFunction | v otherwise, cp = 0 | 97 // +-----------------+---- | 98 // 4+cp | | ^ Callee 99 // |- - - - - - - - -| | frame slots 100 // ... | | Frame slots (slot >= 0) 101 // |- - - - - - - - -| | | 102 // | | v | 103 // -----+-----------------+----- <-- stack ptr ------------- 104 // 105 class StandardFrameConstants : public CommonFrameConstants { 106 public: 107 static constexpr int kFixedFrameSizeFromFp = 2 * kPointerSize + kCPSlotSize; 108 static constexpr int kFixedFrameSize = 109 kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp; 110 static constexpr int kFixedSlotCountFromFp = 111 kFixedFrameSizeFromFp / kPointerSize; 112 static constexpr int kFixedSlotCount = kFixedFrameSize / kPointerSize; 113 static constexpr int kContextOffset = kContextOrFrameTypeOffset; 114 static constexpr int kFunctionOffset = -2 * kPointerSize - kCPSlotSize; 115 static constexpr int kExpressionsOffset = -3 * kPointerSize - kCPSlotSize; 116 static constexpr int kLastObjectOffset = kContextOffset; 117 }; 118 119 // OptimizedBuiltinFrameConstants are used for TF-generated builtins. They 120 // always have a context below the saved fp/constant pool and below that the 121 // JSFunction of the executing function and below that an integer (not a Smi) 122 // containing the number of arguments passed to the builtin. 123 // 124 // slot JS frame 125 // +-----------------+-------------------------------- 126 // -n-1 | parameter 0 | ^ 127 // |- - - - - - - - -| | 128 // -n | | Caller 129 // ... | ... | frame slots 130 // -2 | parameter n-1 | (slot < 0) 131 // |- - - - - - - - -| | 132 // -1 | parameter n | v 133 // -----+-----------------+-------------------------------- 134 // 0 | return addr | ^ ^ 135 // |- - - - - - - - -| | | 136 // 1 | saved frame ptr | Fixed | 137 // |- - - - - - - - -| Header <-- frame ptr | 138 // 2 | [Constant Pool] | | | 139 // |- - - - - - - - -| | | 140 // 2+cp | Context | | if a constant pool | 141 // |- - - - - - - - -| | is used, cp = 1, | 142 // 3+cp | JSFunction | | otherwise, cp = 0 | 143 // |- - - - - - - - -| | | 144 // 4+cp | argc | v | 145 // +-----------------+---- | 146 // 5+cp | | ^ Callee 147 // |- - - - - - - - -| | frame slots 148 // ... | | Frame slots (slot >= 0) 149 // |- - - - - - - - -| | | 150 // | | v | 151 // -----+-----------------+----- <-- stack ptr ------------- 152 // 153 class OptimizedBuiltinFrameConstants : public StandardFrameConstants { 154 public: 155 static constexpr int kArgCSize = kPointerSize; 156 static constexpr int kArgCOffset = -3 * kPointerSize - kCPSlotSize; 157 static constexpr int kFixedFrameSize = kFixedFrameSizeAboveFp - kArgCOffset; 158 static constexpr int kFixedSlotCount = kFixedFrameSize / kPointerSize; 159 }; 160 161 // TypedFrames have a SMI type maker value below the saved FP/constant pool to 162 // distinguish them from StandardFrames, which have a context in that position 163 // instead. 164 // 165 // slot JS frame 166 // +-----------------+-------------------------------- 167 // -n-1 | parameter 0 | ^ 168 // |- - - - - - - - -| | 169 // -n | | Caller 170 // ... | ... | frame slots 171 // -2 | parameter n-1 | (slot < 0) 172 // |- - - - - - - - -| | 173 // -1 | parameter n | v 174 // -----+-----------------+-------------------------------- 175 // 0 | return addr | ^ ^ 176 // |- - - - - - - - -| | | 177 // 1 | saved frame ptr | Fixed | 178 // |- - - - - - - - -| Header <-- frame ptr | 179 // 2 | [Constant Pool] | | | 180 // |- - - - - - - - -| | | 181 // 2+cp |Frame Type Marker| v if a constant pool | 182 // |-----------------+---- is used, cp = 1, | 183 // 3+cp | | ^ otherwise, cp = 0 | 184 // |- - - - - - - - -| | | 185 // 4+cp | | | Callee 186 // |- - - - - - - - -| | frame slots 187 // ... | | Frame slots (slot >= 0) 188 // |- - - - - - - - -| | | 189 // | | v | 190 // -----+-----------------+----- <-- stack ptr ------------- 191 // 192 class TypedFrameConstants : public CommonFrameConstants { 193 public: 194 static constexpr int kFrameTypeSize = kContextOrFrameTypeSize; 195 static constexpr int kFrameTypeOffset = kContextOrFrameTypeOffset; 196 static constexpr int kFixedFrameSizeFromFp = kCPSlotSize + kFrameTypeSize; 197 static constexpr int kFixedSlotCountFromFp = 198 kFixedFrameSizeFromFp / kPointerSize; 199 static constexpr int kFixedFrameSize = 200 StandardFrameConstants::kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp; 201 static constexpr int kFixedSlotCount = kFixedFrameSize / kPointerSize; 202 static constexpr int kFirstPushedFrameValueOffset = 203 -StandardFrameConstants::kCPSlotSize - kFrameTypeSize - kPointerSize; 204 }; 205 206 #define TYPED_FRAME_PUSHED_VALUE_OFFSET(x) \ 207 (TypedFrameConstants::kFirstPushedFrameValueOffset - (x)*kPointerSize) 208 #define TYPED_FRAME_SIZE(count) \ 209 (TypedFrameConstants::kFixedFrameSize + (count)*kPointerSize) 210 #define TYPED_FRAME_SIZE_FROM_SP(count) \ 211 (TypedFrameConstants::kFixedFrameSizeFromFp + (count)*kPointerSize) 212 #define DEFINE_TYPED_FRAME_SIZES(count) \ 213 static constexpr int kFixedFrameSize = TYPED_FRAME_SIZE(count); \ 214 static constexpr int kFixedSlotCount = kFixedFrameSize / kPointerSize; \ 215 static constexpr int kFixedFrameSizeFromFp = \ 216 TYPED_FRAME_SIZE_FROM_SP(count); \ 217 static constexpr int kFixedSlotCountFromFp = \ 218 kFixedFrameSizeFromFp / kPointerSize 219 220 class ArgumentsAdaptorFrameConstants : public TypedFrameConstants { 221 public: 222 // FP-relative. 223 static constexpr int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); 224 static constexpr int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1); 225 static constexpr int kPaddingOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2); 226 DEFINE_TYPED_FRAME_SIZES(3); 227 }; 228 229 class BuiltinFrameConstants : public TypedFrameConstants { 230 public: 231 // FP-relative. 232 static constexpr int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); 233 static constexpr int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1); 234 DEFINE_TYPED_FRAME_SIZES(2); 235 }; 236 237 class ConstructFrameConstants : public TypedFrameConstants { 238 public: 239 // FP-relative. 240 static constexpr int kContextOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); 241 static constexpr int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1); 242 static constexpr int kConstructorOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2); 243 static constexpr int kPaddingOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(3); 244 static constexpr int kNewTargetOrImplicitReceiverOffset = 245 TYPED_FRAME_PUSHED_VALUE_OFFSET(4); 246 DEFINE_TYPED_FRAME_SIZES(5); 247 }; 248 249 class WasmCompiledFrameConstants : public TypedFrameConstants { 250 public: 251 // FP-relative. 252 static constexpr int kWasmInstanceOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); 253 DEFINE_TYPED_FRAME_SIZES(1); 254 }; 255 256 class BuiltinContinuationFrameConstants : public TypedFrameConstants { 257 public: 258 // FP-relative. 259 static constexpr int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); 260 static constexpr int kFrameSPtoFPDeltaAtDeoptimize = 261 TYPED_FRAME_PUSHED_VALUE_OFFSET(1); 262 static constexpr int kBuiltinContextOffset = 263 TYPED_FRAME_PUSHED_VALUE_OFFSET(2); 264 static constexpr int kBuiltinOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(3); 265 266 // The argument count is in the first allocatable register, stored below the 267 // fixed part of the frame and therefore is not part of the fixed frame size. 268 static constexpr int kArgCOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(4); 269 DEFINE_TYPED_FRAME_SIZES(4); 270 271 // Returns the number of padding stack slots needed when we have 272 // 'register_count' register slots. 273 // This is needed on some architectures to ensure the stack pointer is 274 // aligned. 275 static int PaddingSlotCount(int register_count); 276 }; 277 278 // Behaves like an exit frame but with target and new target args. 279 class BuiltinExitFrameConstants : public CommonFrameConstants { 280 public: 281 static constexpr int kNewTargetOffset = kCallerPCOffset + 1 * kPointerSize; 282 static constexpr int kTargetOffset = kNewTargetOffset + 1 * kPointerSize; 283 static constexpr int kArgcOffset = kTargetOffset + 1 * kPointerSize; 284 static constexpr int kPaddingOffset = kArgcOffset + 1 * kPointerSize; 285 static constexpr int kFirstArgumentOffset = kPaddingOffset + 1 * kPointerSize; 286 static constexpr int kNumExtraArgsWithReceiver = 5; 287 }; 288 289 class InterpreterFrameConstants : public AllStatic { 290 public: 291 // Fixed frame includes bytecode array and bytecode offset. 292 static constexpr int kFixedFrameSize = 293 StandardFrameConstants::kFixedFrameSize + 2 * kPointerSize; 294 static constexpr int kFixedFrameSizeFromFp = 295 StandardFrameConstants::kFixedFrameSizeFromFp + 2 * kPointerSize; 296 297 // FP-relative. 298 static constexpr int kLastParamFromFp = 299 StandardFrameConstants::kCallerSPOffset; 300 static constexpr int kCallerPCOffsetFromFp = 301 StandardFrameConstants::kCallerPCOffset; 302 static constexpr int kBytecodeArrayFromFp = 303 -StandardFrameConstants::kFixedFrameSizeFromFp - 1 * kPointerSize; 304 static constexpr int kBytecodeOffsetFromFp = 305 -StandardFrameConstants::kFixedFrameSizeFromFp - 2 * kPointerSize; 306 static constexpr int kRegisterFileFromFp = 307 -StandardFrameConstants::kFixedFrameSizeFromFp - 3 * kPointerSize; 308 309 static constexpr int kExpressionsOffset = kRegisterFileFromFp; 310 311 // Number of fixed slots in addition to a {StandardFrame}. 312 static constexpr int kExtraSlotCount = 313 InterpreterFrameConstants::kFixedFrameSize / kPointerSize - 314 StandardFrameConstants::kFixedFrameSize / kPointerSize; 315 316 // Expression index for {StandardFrame::GetExpressionAddress}. 317 static constexpr int kBytecodeArrayExpressionIndex = -2; 318 static constexpr int kBytecodeOffsetExpressionIndex = -1; 319 static constexpr int kRegisterFileExpressionIndex = 0; 320 321 // Returns the number of stack slots needed for 'register_count' registers. 322 // This is needed because some architectures must pad the stack frame with 323 // additional stack slots to ensure the stack pointer is aligned. 324 static int RegisterStackSlotCount(int register_count); 325 }; 326 327 inline static int FPOffsetToFrameSlot(int frame_offset) { 328 return StandardFrameConstants::kFixedSlotCountAboveFp - 1 - 329 frame_offset / kPointerSize; 330 } 331 332 inline static int FrameSlotToFPOffset(int slot) { 333 return (StandardFrameConstants::kFixedSlotCountAboveFp - 1 - slot) * 334 kPointerSize; 335 } 336 337 } // namespace internal 338 } // namespace v8 339 340 #if V8_TARGET_ARCH_IA32 341 #include "src/ia32/frame-constants-ia32.h" // NOLINT 342 #elif V8_TARGET_ARCH_X64 343 #include "src/x64/frame-constants-x64.h" // NOLINT 344 #elif V8_TARGET_ARCH_ARM64 345 #include "src/arm64/frame-constants-arm64.h" // NOLINT 346 #elif V8_TARGET_ARCH_ARM 347 #include "src/arm/frame-constants-arm.h" // NOLINT 348 #elif V8_TARGET_ARCH_PPC 349 #include "src/ppc/frame-constants-ppc.h" // NOLINT 350 #elif V8_TARGET_ARCH_MIPS 351 #include "src/mips/frame-constants-mips.h" // NOLINT 352 #elif V8_TARGET_ARCH_MIPS64 353 #include "src/mips64/frame-constants-mips64.h" // NOLINT 354 #elif V8_TARGET_ARCH_S390 355 #include "src/s390/frame-constants-s390.h" // NOLINT 356 #else 357 #error Unsupported target architecture. 358 #endif 359 360 #endif // V8_FRAME_CONSTANTS_H_ 361