frame-constants.h 16.2 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

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.
//
24 25 26
// If V8_REVERSE_JSARGS is set, then the parameters are reversed in the stack,
// i.e., the first parameter (the receiver) is just above the return address.
//
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
//  slot      JS frame
//       +-----------------+--------------------------------
//  -n-1 |   parameter 0   |                            ^
//       |- - - - - - - - -|                            |
//  -n   |                 |                          Caller
//  ...  |       ...       |                       frame slots
//  -2   |  parameter n-1  |                       (slot < 0)
//       |- - - - - - - - -|                            |
//  -1   |   parameter n   |                            v
//  -----+-----------------+--------------------------------
//   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:
56
  static constexpr int kCallerFPOffset = 0 * kSystemPointerSize;
57 58
  static constexpr int kCallerPCOffset = kCallerFPOffset + 1 * kFPOnStackSize;
  static constexpr int kCallerSPOffset = kCallerPCOffset + 1 * kPCOnStackSize;
59 60 61 62 63

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

77 78
// StandardFrames are used for interpreted and optimized JavaScript
// frames. They always have a context below the saved fp/constant
79 80 81
// 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.
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
//
//  slot      JS frame
//       +-----------------+--------------------------------
//  -n-1 |   parameter 0   |                            ^
//       |- - - - - - - - -|                            |
//  -n   |                 |                          Caller
//  ...  |       ...       |                       frame slots
//  -2   |  parameter n-1  |                       (slot < 0)
//       |- - - - - - - - -|                            |
//  -1   |   parameter n   |                            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,    |
101 102 103
// 3+cp  |    JSFunction   |   |   otherwise, cp = 0    |
//       |- - - - - - - - -|   |                        |
// 4+cp  |      argc       |   v                        |
104
//       +-----------------+----                        |
105
// 5+cp  |                 |   ^                      Callee
106 107 108 109 110 111 112 113
//       |- - - - - - - - -|   |                   frame slots
//  ...  |                 | Frame slots           (slot >= 0)
//       |- - - - - - - - -|   |                        |
//       |                 |   v                        |
//  -----+-----------------+----- <-- stack ptr -------------
//
class StandardFrameConstants : public CommonFrameConstants {
 public:
114
  static constexpr int kFixedFrameSizeFromFp =
115
      3 * kSystemPointerSize + kCPSlotSize;
116
  static constexpr int kFixedFrameSize =
117
      kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp;
118
  static constexpr int kFixedSlotCountFromFp =
119 120
      kFixedFrameSizeFromFp / kSystemPointerSize;
  static constexpr int kFixedSlotCount = kFixedFrameSize / kSystemPointerSize;
121
  static constexpr int kContextOffset = kContextOrFrameTypeOffset;
122
  static constexpr int kFunctionOffset = -2 * kSystemPointerSize - kCPSlotSize;
123
  static constexpr int kArgCOffset = -3 * kSystemPointerSize - kCPSlotSize;
124
  static constexpr int kExpressionsOffset =
125
      -4 * kSystemPointerSize - kCPSlotSize;
126
  static constexpr int kLastObjectOffset = kContextOffset;
127 128
};

129
// TypedFrames have a type maker value below the saved FP/constant pool to
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
// distinguish them from StandardFrames, which have a context in that position
// instead.
//
//  slot      JS frame
//       +-----------------+--------------------------------
//  -n-1 |   parameter 0   |                            ^
//       |- - - - - - - - -|                            |
//  -n   |                 |                          Caller
//  ...  |       ...       |                       frame slots
//  -2   |  parameter n-1  |                       (slot < 0)
//       |- - - - - - - - -|                            |
//  -1   |   parameter n   |                            v
//  -----+-----------------+--------------------------------
//   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,    |
// 3+cp  |                 |   ^   otherwise, cp = 0    |
//       |- - - - - - - - -|   |                        |
// 4+cp  |                 |   |                      Callee
//       |- - - - - - - - -|   |                   frame slots
//  ...  |                 | Frame slots           (slot >= 0)
//       |- - - - - - - - -|   |                        |
//       |                 |   v                        |
//  -----+-----------------+----- <-- stack ptr -------------
//
class TypedFrameConstants : public CommonFrameConstants {
 public:
162 163 164 165
  static constexpr int kFrameTypeSize = kContextOrFrameTypeSize;
  static constexpr int kFrameTypeOffset = kContextOrFrameTypeOffset;
  static constexpr int kFixedFrameSizeFromFp = kCPSlotSize + kFrameTypeSize;
  static constexpr int kFixedSlotCountFromFp =
166
      kFixedFrameSizeFromFp / kSystemPointerSize;
167
  static constexpr int kFixedFrameSize =
168
      StandardFrameConstants::kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp;
169
  static constexpr int kFixedSlotCount = kFixedFrameSize / kSystemPointerSize;
170
  static constexpr int kFirstPushedFrameValueOffset =
171
      -kFixedFrameSizeFromFp - kSystemPointerSize;
172 173 174
};

#define TYPED_FRAME_PUSHED_VALUE_OFFSET(x) \
175
  (TypedFrameConstants::kFirstPushedFrameValueOffset - (x)*kSystemPointerSize)
176
#define TYPED_FRAME_SIZE(count) \
177
  (TypedFrameConstants::kFixedFrameSize + (count)*kSystemPointerSize)
178
#define TYPED_FRAME_SIZE_FROM_FP(count) \
179 180 181 182 183
  (TypedFrameConstants::kFixedFrameSizeFromFp + (count)*kSystemPointerSize)
#define DEFINE_TYPED_FRAME_SIZES(count)                                        \
  static constexpr int kFixedFrameSize = TYPED_FRAME_SIZE(count);              \
  static constexpr int kFixedSlotCount = kFixedFrameSize / kSystemPointerSize; \
  static constexpr int kFixedFrameSizeFromFp =                                 \
184
      TYPED_FRAME_SIZE_FROM_FP(count);                                         \
185 186
  static constexpr int kFixedSlotCountFromFp =                                 \
      kFixedFrameSizeFromFp / kSystemPointerSize
187 188 189 190

class ArgumentsAdaptorFrameConstants : public TypedFrameConstants {
 public:
  // FP-relative.
191 192 193
  static constexpr int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
  static constexpr int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
  static constexpr int kPaddingOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2);
194
  DEFINE_TYPED_FRAME_SIZES(3);
195 196 197 198 199
};

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

class ConstructFrameConstants : public TypedFrameConstants {
 public:
  // FP-relative.
208 209 210 211 212
  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 =
213 214
      TYPED_FRAME_PUSHED_VALUE_OFFSET(4);
  DEFINE_TYPED_FRAME_SIZES(5);
215 216
};

217 218 219 220 221 222 223
class CWasmEntryFrameConstants : public TypedFrameConstants {
 public:
  // FP-relative:
  static constexpr int kCEntryFPOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
  DEFINE_TYPED_FRAME_SIZES(1);
};

224
class WasmFrameConstants : public TypedFrameConstants {
225 226 227 228 229 230
 public:
  // FP-relative.
  static constexpr int kWasmInstanceOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
  DEFINE_TYPED_FRAME_SIZES(1);
};

231
class WasmExitFrameConstants : public WasmFrameConstants {
232 233 234 235 236 237
 public:
  // FP-relative.
  static const int kCallingPCOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
  DEFINE_TYPED_FRAME_SIZES(2);
};

238 239 240
class BuiltinContinuationFrameConstants : public TypedFrameConstants {
 public:
  // FP-relative.
241 242
  static constexpr int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
  static constexpr int kFrameSPtoFPDeltaAtDeoptimize =
243
      TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
244 245
  static constexpr int kBuiltinContextOffset =
      TYPED_FRAME_PUSHED_VALUE_OFFSET(2);
246
  static constexpr int kBuiltinIndexOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(3);
247

248 249
  // 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.
250
  static constexpr int kArgCOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(4);
251
  DEFINE_TYPED_FRAME_SIZES(4);
252 253 254 255 256 257

  // 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);
258 259
};

260 261 262 263 264 265 266 267 268 269 270
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;
};

271 272 273
// Behaves like an exit frame but with target and new target args.
class BuiltinExitFrameConstants : public CommonFrameConstants {
 public:
274 275 276 277 278 279 280 281
  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;
282
  static constexpr int kNumExtraArgsWithReceiver = 5;
283 284 285 286
};

class InterpreterFrameConstants : public AllStatic {
 public:
287
  // Fixed frame includes bytecode array and bytecode offset.
288
  static constexpr int kFixedFrameSize =
289
      StandardFrameConstants::kFixedFrameSize + 2 * kSystemPointerSize;
290
  static constexpr int kFixedFrameSizeFromFp =
291
      StandardFrameConstants::kFixedFrameSizeFromFp + 2 * kSystemPointerSize;
292 293

  // FP-relative.
294 295 296 297
#ifdef V8_REVERSE_JSARGS
  static constexpr int kFirstParamFromFp =
      StandardFrameConstants::kCallerSPOffset;
#else
298 299
  static constexpr int kLastParamFromFp =
      StandardFrameConstants::kCallerSPOffset;
300
#endif
301
  static constexpr int kCallerPCOffsetFromFp =
302
      StandardFrameConstants::kCallerPCOffset;
303
  static constexpr int kBytecodeArrayFromFp =
304
      -StandardFrameConstants::kFixedFrameSizeFromFp - 1 * kSystemPointerSize;
305
  static constexpr int kBytecodeOffsetFromFp =
306
      -StandardFrameConstants::kFixedFrameSizeFromFp - 2 * kSystemPointerSize;
307
  static constexpr int kRegisterFileFromFp =
308
      -StandardFrameConstants::kFixedFrameSizeFromFp - 3 * kSystemPointerSize;
309

310
  static constexpr int kExpressionsOffset = kRegisterFileFromFp;
311 312

  // Number of fixed slots in addition to a {StandardFrame}.
313
  static constexpr int kExtraSlotCount =
314 315
      InterpreterFrameConstants::kFixedFrameSize / kSystemPointerSize -
      StandardFrameConstants::kFixedFrameSize / kSystemPointerSize;
316 317

  // Expression index for {StandardFrame::GetExpressionAddress}.
318 319 320
  static constexpr int kBytecodeArrayExpressionIndex = -2;
  static constexpr int kBytecodeOffsetExpressionIndex = -1;
  static constexpr int kRegisterFileExpressionIndex = 0;
321 322 323 324 325

  // 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);
326 327 328 329
};

inline static int FPOffsetToFrameSlot(int frame_offset) {
  return StandardFrameConstants::kFixedSlotCountAboveFp - 1 -
330
         frame_offset / kSystemPointerSize;
331 332 333 334
}

inline static int FrameSlotToFPOffset(int slot) {
  return (StandardFrameConstants::kFixedSlotCountAboveFp - 1 - slot) *
335
         kSystemPointerSize;
336 337 338 339 340 341
}

}  // namespace internal
}  // namespace v8

#if V8_TARGET_ARCH_IA32
342
#include "src/execution/ia32/frame-constants-ia32.h"  // NOLINT
343
#elif V8_TARGET_ARCH_X64
344
#include "src/execution/x64/frame-constants-x64.h"  // NOLINT
345
#elif V8_TARGET_ARCH_ARM64
346
#include "src/execution/arm64/frame-constants-arm64.h"  // NOLINT
347
#elif V8_TARGET_ARCH_ARM
348
#include "src/execution/arm/frame-constants-arm.h"  // NOLINT
349
#elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64
350
#include "src/execution/ppc/frame-constants-ppc.h"  // NOLINT
351
#elif V8_TARGET_ARCH_MIPS
352
#include "src/execution/mips/frame-constants-mips.h"  // NOLINT
353
#elif V8_TARGET_ARCH_MIPS64
354
#include "src/execution/mips64/frame-constants-mips64.h"  // NOLINT
355
#elif V8_TARGET_ARCH_S390
356
#include "src/execution/s390/frame-constants-s390.h"  // NOLINT
357 358 359 360
#else
#error Unsupported target architecture.
#endif

361
#endif  // V8_EXECUTION_FRAME_CONSTANTS_H_