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_EXECUTION_FRAME_CONSTANTS_H_ 6#define V8_EXECUTION_FRAME_CONSTANTS_H_ 7 8#include "src/common/globals.h" 9#include "src/flags/flags.h" 10 11namespace v8 { 12namespace 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 n | ^ 27// |- - - - - - - - -| | 28// -n | parameter n-1 | Caller 29// ... | ... | frame slots 30// -2 | parameter 1 | (slot < 0) 31// |- - - - - - - - -| | 32// -1 | parameter 0 | 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// 51class CommonFrameConstants : public AllStatic { 52 public: 53 static constexpr int kCallerFPOffset = 0 * kSystemPointerSize; 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. CommonFrame::IterateExpressions assumes that kLastObjectOffset 60 // is the last object pointer. 61 static constexpr int kFixedFrameSizeAboveFp = kPCOnStackSize + kFPOnStackSize; 62 static constexpr int kFixedSlotCountAboveFp = 63 kFixedFrameSizeAboveFp / kSystemPointerSize; 64 static constexpr int kCPSlotSize = 65 FLAG_enable_embedded_constant_pool ? kSystemPointerSize : 0; 66 static constexpr int kCPSlotCount = kCPSlotSize / kSystemPointerSize; 67 static constexpr int kConstantPoolOffset = 68 kCPSlotSize ? -1 * kSystemPointerSize : 0; 69 static constexpr int kContextOrFrameTypeSize = kSystemPointerSize; 70 static constexpr int kContextOrFrameTypeOffset = 71 -(kCPSlotSize + kContextOrFrameTypeSize); 72}; 73 74// StandardFrames are used for both unoptimized and optimized JavaScript 75// frames. They always have a context below the saved fp/constant 76// pool, below that the JSFunction of the executing function and below that an 77// integer (not a Smi) containing the actual number of arguments passed to the 78// JavaScript code. 79// 80// slot JS frame 81// +-----------------+-------------------------------- 82// -n-1 | parameter n | ^ 83// |- - - - - - - - -| | 84// -n | parameter n-1 | Caller 85// ... | ... | frame slots 86// -2 | parameter 1 | (slot < 0) 87// |- - - - - - - - -| | 88// -1 | parameter 0 | v 89// -----+-----------------+-------------------------------- 90// 0 | return addr | ^ ^ 91// |- - - - - - - - -| | | 92// 1 | saved frame ptr | Fixed | 93// |- - - - - - - - -| Header <-- frame ptr | 94// 2 | [Constant Pool] | | | 95// |- - - - - - - - -| | | 96// 2+cp | Context | | if a constant pool | 97// |- - - - - - - - -| | is used, cp = 1, | 98// 3+cp | JSFunction | | otherwise, cp = 0 | 99// |- - - - - - - - -| | | 100// 4+cp | argc | v | 101// +-----------------+---- | 102// 5+cp | expressions or | ^ Callee 103// |- - - - - - - - -| | frame slots 104// ... | pushed values | Frame slots (slot >= 0) 105// |- - - - - - - - -| | | 106// | | v | 107// -----+-----------------+----- <-- stack ptr ------------- 108// 109class StandardFrameConstants : public CommonFrameConstants { 110 public: 111 static constexpr int kFixedFrameSizeFromFp = 112 3 * kSystemPointerSize + kCPSlotSize; 113 static constexpr int kFixedFrameSize = 114 kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp; 115 static constexpr int kFixedSlotCountFromFp = 116 kFixedFrameSizeFromFp / kSystemPointerSize; 117 static constexpr int kFixedSlotCount = kFixedFrameSize / kSystemPointerSize; 118 static constexpr int kContextOffset = kContextOrFrameTypeOffset; 119 static constexpr int kFunctionOffset = -2 * kSystemPointerSize - kCPSlotSize; 120 static constexpr int kArgCOffset = -3 * kSystemPointerSize - kCPSlotSize; 121 static constexpr int kExpressionsOffset = 122 -4 * kSystemPointerSize - kCPSlotSize; 123 static constexpr int kFirstPushedFrameValueOffset = kExpressionsOffset; 124 static constexpr int kLastObjectOffset = kContextOffset; 125}; 126 127// TypedFrames have a type maker value below the saved FP/constant pool to 128// distinguish them from StandardFrames, which have a context in that position 129// instead. 130// 131// slot JS frame 132// +-----------------+-------------------------------- 133// -n-1 | parameter n | ^ 134// |- - - - - - - - -| | 135// -n | parameter n-1 | Caller 136// ... | ... | frame slots 137// -2 | parameter 1 | (slot < 0) 138// |- - - - - - - - -| | 139// -1 | parameter 0 | v 140// -----+-----------------+-------------------------------- 141// 0 | return addr | ^ ^ 142// |- - - - - - - - -| | | 143// 1 | saved frame ptr | Fixed | 144// |- - - - - - - - -| Header <-- frame ptr | 145// 2 | [Constant Pool] | | | 146// |- - - - - - - - -| | | 147// 2+cp |Frame Type Marker| v if a constant pool | 148// |-----------------+---- is used, cp = 1, | 149// 3+cp | pushed value 0 | ^ otherwise, cp = 0 | 150// |- - - - - - - - -| | | 151// 4+cp | pushed value 1 | | Callee 152// |- - - - - - - - -| | frame slots 153// ... | | Frame slots (slot >= 0) 154// |- - - - - - - - -| | | 155// | | v | 156// -----+-----------------+----- <-- stack ptr ------------- 157// 158class TypedFrameConstants : public CommonFrameConstants { 159 public: 160 static constexpr int kFrameTypeSize = kContextOrFrameTypeSize; 161 static constexpr int kFrameTypeOffset = kContextOrFrameTypeOffset; 162 static constexpr int kFixedFrameSizeFromFp = kCPSlotSize + kFrameTypeSize; 163 static constexpr int kFixedSlotCountFromFp = 164 kFixedFrameSizeFromFp / kSystemPointerSize; 165 static constexpr int kFixedFrameSize = 166 StandardFrameConstants::kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp; 167 static constexpr int kFixedSlotCount = kFixedFrameSize / kSystemPointerSize; 168 static constexpr int kFirstPushedFrameValueOffset = 169 -kFixedFrameSizeFromFp - kSystemPointerSize; 170}; 171 172#define FRAME_PUSHED_VALUE_OFFSET(parent, x) \ 173 (parent::kFirstPushedFrameValueOffset - (x)*kSystemPointerSize) 174#define FRAME_SIZE(parent, count) \ 175 (parent::kFixedFrameSize + (count)*kSystemPointerSize) 176#define FRAME_SIZE_FROM_FP(parent, count) \ 177 (parent::kFixedFrameSizeFromFp + (count)*kSystemPointerSize) 178#define DEFINE_FRAME_SIZES(parent, count) \ 179 static constexpr int kFixedFrameSize = FRAME_SIZE(parent, count); \ 180 static constexpr int kFixedSlotCount = kFixedFrameSize / kSystemPointerSize; \ 181 static constexpr int kFixedFrameSizeFromFp = \ 182 FRAME_SIZE_FROM_FP(parent, count); \ 183 static constexpr int kFixedSlotCountFromFp = \ 184 kFixedFrameSizeFromFp / kSystemPointerSize; \ 185 static constexpr int kExtraSlotCount = \ 186 kFixedFrameSize / kSystemPointerSize - \ 187 parent::kFixedFrameSize / kSystemPointerSize 188 189#define STANDARD_FRAME_EXTRA_PUSHED_VALUE_OFFSET(x) \ 190 FRAME_PUSHED_VALUE_OFFSET(StandardFrameConstants, x) 191#define DEFINE_STANDARD_FRAME_SIZES(count) \ 192 DEFINE_FRAME_SIZES(StandardFrameConstants, count) 193 194#define TYPED_FRAME_PUSHED_VALUE_OFFSET(x) \ 195 FRAME_PUSHED_VALUE_OFFSET(TypedFrameConstants, x) 196#define DEFINE_TYPED_FRAME_SIZES(count) \ 197 DEFINE_FRAME_SIZES(TypedFrameConstants, count) 198 199class BuiltinFrameConstants : public TypedFrameConstants { 200 public: 201 // FP-relative. 202 static constexpr int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); 203 static constexpr int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1); 204 DEFINE_TYPED_FRAME_SIZES(2); 205}; 206 207// Fixed frame slots shared by the js-to-wasm wrapper, the 208// ReturnPromiseOnSuspend wrapper and the WasmResume wrapper. 209class BuiltinWasmWrapperConstants : public TypedFrameConstants { 210 public: 211 // This slot contains the number of slots at the top of the frame that need to 212 // be scanned by the GC. 213 static constexpr int kGCScanSlotCountOffset = 214 TYPED_FRAME_PUSHED_VALUE_OFFSET(0); 215 // The number of parameters passed to this function. 216 static constexpr int kInParamCountOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1); 217 // The number of parameters according to the signature. 218 static constexpr int kParamCountOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2); 219}; 220 221class ConstructFrameConstants : public TypedFrameConstants { 222 public: 223 // FP-relative. 224 static constexpr int kContextOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); 225 static constexpr int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1); 226 static constexpr int kConstructorOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2); 227 static constexpr int kPaddingOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(3); 228 static constexpr int kNewTargetOrImplicitReceiverOffset = 229 TYPED_FRAME_PUSHED_VALUE_OFFSET(4); 230 DEFINE_TYPED_FRAME_SIZES(5); 231}; 232 233#if V8_ENABLE_WEBASSEMBLY 234class CWasmEntryFrameConstants : public TypedFrameConstants { 235 public: 236 // FP-relative: 237 static constexpr int kCEntryFPOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); 238 DEFINE_TYPED_FRAME_SIZES(1); 239}; 240 241class WasmFrameConstants : public TypedFrameConstants { 242 public: 243 // FP-relative. 244 static constexpr int kWasmInstanceOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); 245 DEFINE_TYPED_FRAME_SIZES(1); 246}; 247 248class WasmExitFrameConstants : public WasmFrameConstants { 249 public: 250 // FP-relative. 251 static const int kCallingPCOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1); 252 DEFINE_TYPED_FRAME_SIZES(2); 253}; 254#endif // V8_ENABLE_WEBASSEMBLY 255 256class 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 kBuiltinIndexOffset = 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 278class ExitFrameConstants : public TypedFrameConstants { 279 public: 280 static constexpr int kSPOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0); 281 static constexpr int kLastExitFrameField = kSPOffset; 282 DEFINE_TYPED_FRAME_SIZES(1); 283 284 // FP-relative displacement of the caller's SP. It points just 285 // below the saved PC. 286 static constexpr int kCallerSPDisplacement = kCallerSPOffset; 287}; 288 289// Behaves like an exit frame but with target and new target args. 290class BuiltinExitFrameConstants : public ExitFrameConstants { 291 public: 292 static constexpr int kNewTargetOffset = 293 kCallerPCOffset + 1 * kSystemPointerSize; 294 static constexpr int kTargetOffset = 295 kNewTargetOffset + 1 * kSystemPointerSize; 296 static constexpr int kArgcOffset = kTargetOffset + 1 * kSystemPointerSize; 297 static constexpr int kPaddingOffset = kArgcOffset + 1 * kSystemPointerSize; 298 static constexpr int kFirstArgumentOffset = 299 kPaddingOffset + 1 * kSystemPointerSize; 300 static constexpr int kNumExtraArgsWithoutReceiver = 4; 301 static constexpr int kNumExtraArgsWithReceiver = 302 kNumExtraArgsWithoutReceiver + 1; 303}; 304 305// Unoptimized frames are used for interpreted and baseline-compiled JavaScript 306// frames. They are a "standard" frame, with an additional fixed header for the 307// BytecodeArray, bytecode offset (if running interpreted), feedback vector (if 308// running baseline code), and then the interpreter register file. 309// 310// slot JS frame 311// +-----------------+-------------------------------- 312// -n-1 | parameter n | ^ 313// |- - - - - - - - -| | 314// -n | parameter n-1 | Caller 315// ... | ... | frame slots 316// -2 | parameter 1 | (slot < 0) 317// |- - - - - - - - -| | 318// -1 | parameter 0 | v 319// -----+-----------------+-------------------------------- 320// 0 | return addr | ^ ^ 321// |- - - - - - - - -| | | 322// 1 | saved frame ptr | Fixed | 323// |- - - - - - - - -| Header <-- frame ptr | 324// 2 | [Constant Pool] | | | 325// |- - - - - - - - -| | | 326// 2+cp | Context | | if a constant pool | 327// |- - - - - - - - -| | is used, cp = 1, | 328// 3+cp | JSFunction | | otherwise, cp = 0 | 329// |- - - - - - - - -| | | 330// 4+cp | argc | v | 331// +-----------------+---- | 332// 5+cp | BytecodeArray | ^ | 333// |- - - - - - - - -| Unoptimized code header | 334// 6+cp | offset or FBV | v | 335// +-----------------+---- | 336// 7+cp | register 0 | ^ Callee 337// |- - - - - - - - -| | frame slots 338// 8+cp | register 1 | Register file (slot >= 0) 339// ... | ... | | | 340// | register n-1 | | | 341// |- - - - - - - - -| | | 342// 8+cp+n| register n | v v 343// -----+-----------------+----- <-- stack ptr ------------- 344// 345class UnoptimizedFrameConstants : public StandardFrameConstants { 346 public: 347 // FP-relative. 348 static constexpr int kBytecodeArrayFromFp = 349 STANDARD_FRAME_EXTRA_PUSHED_VALUE_OFFSET(0); 350 static constexpr int kBytecodeOffsetOrFeedbackVectorFromFp = 351 STANDARD_FRAME_EXTRA_PUSHED_VALUE_OFFSET(1); 352 DEFINE_STANDARD_FRAME_SIZES(2); 353 354 static constexpr int kFirstParamFromFp = 355 StandardFrameConstants::kCallerSPOffset; 356 static constexpr int kRegisterFileFromFp = 357 -kFixedFrameSizeFromFp - kSystemPointerSize; 358 static constexpr int kExpressionsOffset = kRegisterFileFromFp; 359 360 // Expression index for {JavaScriptFrame::GetExpressionAddress}. 361 static constexpr int kBytecodeArrayExpressionIndex = -2; 362 static constexpr int kBytecodeOffsetOrFeedbackVectorExpressionIndex = -1; 363 static constexpr int kRegisterFileExpressionIndex = 0; 364 365 // Returns the number of stack slots needed for 'register_count' registers. 366 // This is needed because some architectures must pad the stack frame with 367 // additional stack slots to ensure the stack pointer is aligned. 368 static int RegisterStackSlotCount(int register_count); 369}; 370 371// Interpreter frames are unoptimized frames that are being executed by the 372// interpreter. In this case, the "offset or FBV" slot contains the bytecode 373// offset of the currently executing bytecode. 374class InterpreterFrameConstants : public UnoptimizedFrameConstants { 375 public: 376 static constexpr int kBytecodeOffsetExpressionIndex = 377 kBytecodeOffsetOrFeedbackVectorExpressionIndex; 378 379 static constexpr int kBytecodeOffsetFromFp = 380 kBytecodeOffsetOrFeedbackVectorFromFp; 381}; 382 383// Sparkplug frames are unoptimized frames that are being executed by 384// sparkplug-compiled baseline code. base. In this case, the "offset or FBV" 385// slot contains a cached pointer to the feedback vector. 386class BaselineFrameConstants : public UnoptimizedFrameConstants { 387 public: 388 static constexpr int kFeedbackVectorExpressionIndex = 389 kBytecodeOffsetOrFeedbackVectorExpressionIndex; 390 391 static constexpr int kFeedbackVectorFromFp = 392 kBytecodeOffsetOrFeedbackVectorFromFp; 393}; 394 395inline static int FPOffsetToFrameSlot(int frame_offset) { 396 return StandardFrameConstants::kFixedSlotCountAboveFp - 1 - 397 frame_offset / kSystemPointerSize; 398} 399 400inline static int FrameSlotToFPOffset(int slot) { 401 return (StandardFrameConstants::kFixedSlotCountAboveFp - 1 - slot) * 402 kSystemPointerSize; 403} 404 405} // namespace internal 406} // namespace v8 407 408#if V8_TARGET_ARCH_IA32 409#include "src/execution/ia32/frame-constants-ia32.h" 410#elif V8_TARGET_ARCH_X64 411#include "src/execution/x64/frame-constants-x64.h" 412#elif V8_TARGET_ARCH_ARM64 413#include "src/execution/arm64/frame-constants-arm64.h" 414#elif V8_TARGET_ARCH_ARM 415#include "src/execution/arm/frame-constants-arm.h" 416#elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64 417#include "src/execution/ppc/frame-constants-ppc.h" 418#elif V8_TARGET_ARCH_MIPS 419#include "src/execution/mips/frame-constants-mips.h" 420#elif V8_TARGET_ARCH_MIPS64 421#include "src/execution/mips64/frame-constants-mips64.h" 422#elif V8_TARGET_ARCH_LOONG64 423#include "src/execution/loong64/frame-constants-loong64.h" 424#elif V8_TARGET_ARCH_S390 425#include "src/execution/s390/frame-constants-s390.h" 426#elif V8_TARGET_ARCH_RISCV64 427#include "src/execution/riscv64/frame-constants-riscv64.h" 428#else 429#error Unsupported target architecture. 430#endif 431 432#endif // V8_EXECUTION_FRAME_CONSTANTS_H_ 433