frame-constants.h 19.6 KB
Newer Older
1 2 3 4
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
#ifndef V8_EXECUTION_FRAME_CONSTANTS_H_
#define V8_EXECUTION_FRAME_CONSTANTS_H_
7

8 9
#include "src/common/globals.h"
#include "src/flags/flags.h"
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

namespace v8 {
namespace internal {

// Every pointer in a frame has a slot id. On 32-bit platforms, doubles consume
// two slots.
//
// Stack slot indices >= 0 access the callee stack with slot 0 corresponding to
// the callee's saved return address and 1 corresponding to the saved frame
// pointer. Some frames have additional information stored in the fixed header,
// for example JSFunctions store the function context and marker in the fixed
// header, with slot index 2 corresponding to the current function context and 3
// corresponding to the frame marker/JSFunction.
//
//  slot      JS frame
//       +-----------------+--------------------------------
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
//  -----+-----------------+--------------------------------
//   0   |   return addr   |   ^                        ^
//       |- - - - - - - - -|   |                        |
//   1   | saved frame ptr | Fixed                      |
//       |- - - - - - - - -| Header <-- frame ptr       |
//   2   | [Constant Pool] |   |                        |
//       |- - - - - - - - -|   |                        |
// 2+cp  |Context/Frm. Type|   v   if a constant pool   |
//       |-----------------+----    is used, cp = 1,    |
// 3+cp  |                 |   ^   otherwise, cp = 0    |
//       |- - - - - - - - -|   |                        |
// 4+cp  |                 |   |                      Callee
//       |- - - - - - - - -|   |                   frame slots
//  ...  |                 | Frame slots           (slot >= 0)
//       |- - - - - - - - -|   |                        |
//       |                 |   v                        |
//  -----+-----------------+----- <-- stack ptr -------------
//
class CommonFrameConstants : public AllStatic {
 public:
53
  static constexpr int kCallerFPOffset = 0 * kSystemPointerSize;
54 55
  static constexpr int kCallerPCOffset = kCallerFPOffset + 1 * kFPOnStackSize;
  static constexpr int kCallerSPOffset = kCallerPCOffset + 1 * kPCOnStackSize;
56 57 58

  // Fixed part of the frame consists of return address, caller fp,
  // constant pool (if FLAG_enable_embedded_constant_pool), context, and
59
  // function. CommonFrame::IterateExpressions assumes that kLastObjectOffset
60
  // is the last object pointer.
61 62
  static constexpr int kFixedFrameSizeAboveFp = kPCOnStackSize + kFPOnStackSize;
  static constexpr int kFixedSlotCountAboveFp =
63
      kFixedFrameSizeAboveFp / kSystemPointerSize;
64
  static constexpr int kCPSlotSize =
65 66
      FLAG_enable_embedded_constant_pool ? kSystemPointerSize : 0;
  static constexpr int kCPSlotCount = kCPSlotSize / kSystemPointerSize;
67
  static constexpr int kConstantPoolOffset =
68 69
      kCPSlotSize ? -1 * kSystemPointerSize : 0;
  static constexpr int kContextOrFrameTypeSize = kSystemPointerSize;
70
  static constexpr int kContextOrFrameTypeOffset =
71 72 73
      -(kCPSlotSize + kContextOrFrameTypeSize);
};

74
// StandardFrames are used for both unoptimized and optimized JavaScript
75
// frames. They always have a context below the saved fp/constant
76 77 78
// pool, below that the JSFunction of the executing function and below that an
// integer (not a Smi) containing the actual number of arguments passed to the
// JavaScript code.
79 80 81
//
//  slot      JS frame
//       +-----------------+--------------------------------
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 91 92 93 94 95 96 97
//  -----+-----------------+--------------------------------
//   0   |   return addr   |   ^                        ^
//       |- - - - - - - - -|   |                        |
//   1   | saved frame ptr | Fixed                      |
//       |- - - - - - - - -| Header <-- frame ptr       |
//   2   | [Constant Pool] |   |                        |
//       |- - - - - - - - -|   |                        |
// 2+cp  |     Context     |   |   if a constant pool   |
//       |- - - - - - - - -|   |    is used, cp = 1,    |
98 99 100
// 3+cp  |    JSFunction   |   |   otherwise, cp = 0    |
//       |- - - - - - - - -|   |                        |
// 4+cp  |      argc       |   v                        |
101
//       +-----------------+----                        |
102
// 5+cp  |  expressions or |   ^                      Callee
103
//       |- - - - - - - - -|   |                   frame slots
104
//  ...  |  pushed values  | Frame slots           (slot >= 0)
105 106 107 108 109 110
//       |- - - - - - - - -|   |                        |
//       |                 |   v                        |
//  -----+-----------------+----- <-- stack ptr -------------
//
class StandardFrameConstants : public CommonFrameConstants {
 public:
111
  static constexpr int kFixedFrameSizeFromFp =
112
      3 * kSystemPointerSize + kCPSlotSize;
113
  static constexpr int kFixedFrameSize =
114
      kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp;
115
  static constexpr int kFixedSlotCountFromFp =
116 117
      kFixedFrameSizeFromFp / kSystemPointerSize;
  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 129 130 131 132
// distinguish them from StandardFrames, which have a context in that position
// instead.
//
//  slot      JS frame
//       +-----------------+--------------------------------
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 142 143 144 145 146 147 148
//  -----+-----------------+--------------------------------
//   0   |   return addr   |   ^                        ^
//       |- - - - - - - - -|   |                        |
//   1   | saved frame ptr | Fixed                      |
//       |- - - - - - - - -| Header <-- frame ptr       |
//   2   | [Constant Pool] |   |                        |
//       |- - - - - - - - -|   |                        |
// 2+cp  |Frame Type Marker|   v   if a constant pool   |
//       |-----------------+----    is used, cp = 1,    |
149
// 3+cp  |  pushed value 0 |   ^   otherwise, cp = 0    |
150
//       |- - - - - - - - -|   |                        |
151
// 4+cp  |  pushed value 1 |   |                      Callee
152 153 154 155 156 157 158 159
//       |- - - - - - - - -|   |                   frame slots
//  ...  |                 | Frame slots           (slot >= 0)
//       |- - - - - - - - -|   |                        |
//       |                 |   v                        |
//  -----+-----------------+----- <-- stack ptr -------------
//
class TypedFrameConstants : public CommonFrameConstants {
 public:
160 161 162 163
  static constexpr int kFrameTypeSize = kContextOrFrameTypeSize;
  static constexpr int kFrameTypeOffset = kContextOrFrameTypeOffset;
  static constexpr int kFixedFrameSizeFromFp = kCPSlotSize + kFrameTypeSize;
  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 173 174 175 176 177 178 179
#define FRAME_PUSHED_VALUE_OFFSET(parent, x) \
  (parent::kFirstPushedFrameValueOffset - (x)*kSystemPointerSize)
#define FRAME_SIZE(parent, count) \
  (parent::kFixedFrameSize + (count)*kSystemPointerSize)
#define FRAME_SIZE_FROM_FP(parent, count) \
  (parent::kFixedFrameSizeFromFp + (count)*kSystemPointerSize)
#define DEFINE_FRAME_SIZES(parent, count)                                      \
  static constexpr int kFixedFrameSize = FRAME_SIZE(parent, count);            \
180 181
  static constexpr int kFixedSlotCount = kFixedFrameSize / kSystemPointerSize; \
  static constexpr int kFixedFrameSizeFromFp =                                 \
182
      FRAME_SIZE_FROM_FP(parent, count);                                       \
183
  static constexpr int kFixedSlotCountFromFp =                                 \
184 185 186 187 188 189 190 191 192 193 194 195 196 197
      kFixedFrameSizeFromFp / kSystemPointerSize;                              \
  static constexpr int kExtraSlotCount =                                       \
      kFixedFrameSize / kSystemPointerSize -                                   \
      parent::kFixedFrameSize / kSystemPointerSize

#define STANDARD_FRAME_EXTRA_PUSHED_VALUE_OFFSET(x) \
  FRAME_PUSHED_VALUE_OFFSET(StandardFrameConstants, x)
#define DEFINE_STANDARD_FRAME_SIZES(count) \
  DEFINE_FRAME_SIZES(StandardFrameConstants, count)

#define TYPED_FRAME_PUSHED_VALUE_OFFSET(x) \
  FRAME_PUSHED_VALUE_OFFSET(TypedFrameConstants, x)
#define DEFINE_TYPED_FRAME_SIZES(count) \
  DEFINE_FRAME_SIZES(TypedFrameConstants, count)
198 199 200 201

class BuiltinFrameConstants : public TypedFrameConstants {
 public:
  // FP-relative.
202 203
  static constexpr int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
  static constexpr int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
204 205 206
  DEFINE_TYPED_FRAME_SIZES(2);
};

207 208
// Fixed frame slots shared by the js-to-wasm wrapper, the
// ReturnPromiseOnSuspend wrapper and the WasmResume wrapper.
209 210 211 212 213
class BuiltinWasmWrapperConstants : public TypedFrameConstants {
 public:
  // This slot contains the number of slots at the top of the frame that need to
  // be scanned by the GC.
  static constexpr int kGCScanSlotCountOffset =
214
      TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
215 216 217 218
  // The number of parameters passed to this function.
  static constexpr int kInParamCountOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
  // The number of parameters according to the signature.
  static constexpr int kParamCountOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2);
219 220
};

221 222 223
class ConstructFrameConstants : public TypedFrameConstants {
 public:
  // FP-relative.
224 225 226 227 228
  static constexpr int kContextOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
  static constexpr int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
  static constexpr int kConstructorOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2);
  static constexpr int kPaddingOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(3);
  static constexpr int kNewTargetOrImplicitReceiverOffset =
229 230
      TYPED_FRAME_PUSHED_VALUE_OFFSET(4);
  DEFINE_TYPED_FRAME_SIZES(5);
231 232
};

233
#if V8_ENABLE_WEBASSEMBLY
234 235 236 237 238 239 240
class CWasmEntryFrameConstants : public TypedFrameConstants {
 public:
  // FP-relative:
  static constexpr int kCEntryFPOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
  DEFINE_TYPED_FRAME_SIZES(1);
};

241
class WasmFrameConstants : public TypedFrameConstants {
242 243 244 245 246 247
 public:
  // FP-relative.
  static constexpr int kWasmInstanceOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
  DEFINE_TYPED_FRAME_SIZES(1);
};

248
class WasmExitFrameConstants : public WasmFrameConstants {
249 250 251 252 253
 public:
  // FP-relative.
  static const int kCallingPCOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
  DEFINE_TYPED_FRAME_SIZES(2);
};
254
#endif  // V8_ENABLE_WEBASSEMBLY
255

256 257 258
class BuiltinContinuationFrameConstants : public TypedFrameConstants {
 public:
  // FP-relative.
259 260
  static constexpr int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
  static constexpr int kFrameSPtoFPDeltaAtDeoptimize =
261
      TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
262 263
  static constexpr int kBuiltinContextOffset =
      TYPED_FRAME_PUSHED_VALUE_OFFSET(2);
264
  static constexpr int kBuiltinIndexOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(3);
265

266 267
  // The argument count is in the first allocatable register, stored below the
  // 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 272 273 274 275

  // Returns the number of padding stack slots needed when we have
  // 'register_count' register slots.
  // This is needed on some architectures to ensure the stack pointer is
  // aligned.
  static int PaddingSlotCount(int register_count);
276 277
};

278 279 280 281 282 283 284 285 286 287 288
class ExitFrameConstants : public TypedFrameConstants {
 public:
  static constexpr int kSPOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
  static constexpr int kLastExitFrameField = kSPOffset;
  DEFINE_TYPED_FRAME_SIZES(1);

  // FP-relative displacement of the caller's SP.  It points just
  // below the saved PC.
  static constexpr int kCallerSPDisplacement = kCallerSPOffset;
};

289
// Behaves like an exit frame but with target and new target args.
290
class BuiltinExitFrameConstants : public ExitFrameConstants {
291
 public:
292 293 294 295 296 297 298 299
  static constexpr int kNewTargetOffset =
      kCallerPCOffset + 1 * kSystemPointerSize;
  static constexpr int kTargetOffset =
      kNewTargetOffset + 1 * kSystemPointerSize;
  static constexpr int kArgcOffset = kTargetOffset + 1 * kSystemPointerSize;
  static constexpr int kPaddingOffset = kArgcOffset + 1 * kSystemPointerSize;
  static constexpr int kFirstArgumentOffset =
      kPaddingOffset + 1 * kSystemPointerSize;
300 301 302
  static constexpr int kNumExtraArgsWithoutReceiver = 4;
  static constexpr int kNumExtraArgsWithReceiver =
      kNumExtraArgsWithoutReceiver + 1;
303 304
};

305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
// Unoptimized frames are used for interpreted and baseline-compiled JavaScript
// frames. They are a "standard" frame, with an additional fixed header for the
// BytecodeArray, bytecode offset (if running interpreted), feedback vector (if
// running baseline code), and then the interpreter register file.
//
//  slot      JS frame
//       +-----------------+--------------------------------
//  -n-1 |   parameter n   |                            ^
//       |- - - - - - - - -|                            |
//  -n   |  parameter n-1  |                          Caller
//  ...  |       ...       |                       frame slots
//  -2   |   parameter 1   |                       (slot < 0)
//       |- - - - - - - - -|                            |
//  -1   |   parameter 0   |                            v
//  -----+-----------------+--------------------------------
//   0   |   return addr   |   ^                        ^
//       |- - - - - - - - -|   |                        |
//   1   | saved frame ptr | Fixed                      |
//       |- - - - - - - - -| Header <-- frame ptr       |
//   2   | [Constant Pool] |   |                        |
//       |- - - - - - - - -|   |                        |
// 2+cp  |     Context     |   |   if a constant pool   |
//       |- - - - - - - - -|   |    is used, cp = 1,    |
// 3+cp  |    JSFunction   |   |   otherwise, cp = 0    |
//       |- - - - - - - - -|   |                        |
// 4+cp  |      argc       |   v                        |
//       +-----------------+----                        |
// 5+cp  |  BytecodeArray  |   ^                        |
//       |- - - - - - - - -| Unoptimized code header    |
// 6+cp  |  offset or FBV  |   v                        |
//       +-----------------+----                        |
// 7+cp  |   register 0    |   ^                     Callee
//       |- - - - - - - - -|   |                   frame slots
// 8+cp  |   register 1    | Register file         (slot >= 0)
//  ...  |       ...       |   |                        |
//       |  register n-1   |   |                        |
//       |- - - - - - - - -|   |                        |
// 8+cp+n|   register n    |   v                        v
//  -----+-----------------+----- <-- stack ptr -------------
//
class UnoptimizedFrameConstants : public StandardFrameConstants {
346 347
 public:
  // FP-relative.
348 349
  static constexpr int kBytecodeArrayFromFp =
      STANDARD_FRAME_EXTRA_PUSHED_VALUE_OFFSET(0);
350
  static constexpr int kBytecodeOffsetOrFeedbackVectorFromFp =
351 352 353
      STANDARD_FRAME_EXTRA_PUSHED_VALUE_OFFSET(1);
  DEFINE_STANDARD_FRAME_SIZES(2);

354 355
  static constexpr int kFirstParamFromFp =
      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 366 367 368

  // Returns the number of stack slots needed for 'register_count' registers.
  // This is needed because some architectures must pad the stack frame with
  // additional stack slots to ensure the stack pointer is aligned.
  static int RegisterStackSlotCount(int register_count);
369 370
};

371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
// Interpreter frames are unoptimized frames that are being executed by the
// interpreter. In this case, the "offset or FBV" slot contains the bytecode
// offset of the currently executing bytecode.
class InterpreterFrameConstants : public UnoptimizedFrameConstants {
 public:
  static constexpr int kBytecodeOffsetExpressionIndex =
      kBytecodeOffsetOrFeedbackVectorExpressionIndex;

  static constexpr int kBytecodeOffsetFromFp =
      kBytecodeOffsetOrFeedbackVectorFromFp;
};

// Sparkplug frames are unoptimized frames that are being executed by
// sparkplug-compiled baseline code. base. In this case, the "offset or FBV"
// slot contains a cached pointer to the feedback vector.
class BaselineFrameConstants : public UnoptimizedFrameConstants {
 public:
  static constexpr int kFeedbackVectorExpressionIndex =
      kBytecodeOffsetOrFeedbackVectorExpressionIndex;

  static constexpr int kFeedbackVectorFromFp =
      kBytecodeOffsetOrFeedbackVectorFromFp;
};

395 396
inline static int FPOffsetToFrameSlot(int frame_offset) {
  return StandardFrameConstants::kFixedSlotCountAboveFp - 1 -
397
         frame_offset / kSystemPointerSize;
398 399 400 401
}

inline static int FrameSlotToFPOffset(int slot) {
  return (StandardFrameConstants::kFixedSlotCountAboveFp - 1 - slot) *
402
         kSystemPointerSize;
403 404 405 406 407 408
}

}  // namespace internal
}  // namespace v8

#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 423
#elif V8_TARGET_ARCH_LOONG64
#include "src/execution/loong64/frame-constants-loong64.h"
424
#elif V8_TARGET_ARCH_S390
425
#include "src/execution/s390/frame-constants-s390.h"
Brice Dobry's avatar
Brice Dobry committed
426
#elif V8_TARGET_ARCH_RISCV64
427
#include "src/execution/riscv64/frame-constants-riscv64.h"
428 429 430 431
#else
#error Unsupported target architecture.
#endif

432
#endif  // V8_EXECUTION_FRAME_CONSTANTS_H_