chromium/v8/src/execution/frame-constants.h

// 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.

#ifndef V8_EXECUTION_FRAME_CONSTANTS_H_
#define V8_EXECUTION_FRAME_CONSTANTS_H_

#include "src/common/globals.h"
#include "src/flags/flags.h"

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
//       +-----------------+--------------------------------
//  -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/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 {};

// StandardFrames are used for both unoptimized and optimized JavaScript
// frames. They always have a context below the saved fp/constant
// 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.
//
//  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  |  expressions or |   ^                      Callee
//       |- - - - - - - - -|   |                   frame slots
//  ...  |  pushed values  | Frame slots           (slot >= 0)
//       |- - - - - - - - -|   |                        |
//       |                 |   v                        |
//  -----+-----------------+----- <-- stack ptr -------------
//
class StandardFrameConstants : public CommonFrameConstants {};

// TypedFrames have a type maker value below the saved FP/constant pool to
// distinguish them from StandardFrames, which have a context in that position
// instead.
//
//  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  |Frame Type Marker|   v   if a constant pool   |
//       |-----------------+----    is used, cp = 1,    |
// 3+cp  |  pushed value 0 |   ^   otherwise, cp = 0    |
//       |- - - - - - - - -|   |                        |
// 4+cp  |  pushed value 1 |   |                      Callee
//       |- - - - - - - - -|   |                   frame slots
//  ...  |                 | Frame slots           (slot >= 0)
//       |- - - - - - - - -|   |                        |
//       |                 |   v                        |
//  -----+-----------------+----- <-- stack ptr -------------
//
class TypedFrameConstants : public CommonFrameConstants {};

#define FRAME_PUSHED_VALUE_OFFSET(parent, x)
#define FRAME_SIZE(parent, count)
#define FRAME_SIZE_FROM_FP(parent, count)
#define DEFINE_FRAME_SIZES(parent, count)

#define STANDARD_FRAME_EXTRA_PUSHED_VALUE_OFFSET(x)
#define DEFINE_STANDARD_FRAME_SIZES(count)

#define TYPED_FRAME_PUSHED_VALUE_OFFSET(x)
#define DEFINE_TYPED_FRAME_SIZES(count)

class BuiltinFrameConstants : public TypedFrameConstants {};

class ConstructFrameConstants : public TypedFrameConstants {};

class FastConstructFrameConstants : public TypedFrameConstants {};

#if V8_ENABLE_WEBASSEMBLY
class CWasmEntryFrameConstants : public TypedFrameConstants {};

class WasmFrameConstants : public TypedFrameConstants {};

#if V8_ENABLE_DRUMBRAKE
class WasmInterpreterFrameConstants : public TypedFrameConstants {
 public:
  // FP-relative.
  static constexpr int kWasmInstanceObjectOffset =
      TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
  DEFINE_TYPED_FRAME_SIZES(1);
};

// Fixed frame slots shared by the interpreter wasm-to-js wrapper.
class WasmToJSInterpreterFrameConstants : 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 =
      TYPED_FRAME_PUSHED_VALUE_OFFSET(0);

  // The stack pointer at the moment of the JS function call.
  static constexpr int kGCSPOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
};

class WasmInterpreterCWasmEntryConstants : public TypedFrameConstants {
 public:
  // FP-relative:
  static constexpr int kCEntryFPOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
  static constexpr int kSPFPOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
  DEFINE_TYPED_FRAME_SIZES(2);
};
#endif  // V8_ENABLE_DRUMBRAKE

class WasmExitFrameConstants : public WasmFrameConstants {};

// Fixed frame slots used by the js-to-wasm wrapper.
class JSToWasmWrapperFrameConstants : public TypedFrameConstants {};

// Fixed frame slots used by the ReturnPromiseOnSuspendAsm wrapper
// and the WasmResume wrapper.
class StackSwitchFrameConstants : public JSToWasmWrapperFrameConstants {};

class WasmToJSWrapperConstants {};

#if V8_ENABLE_DRUMBRAKE
class BuiltinWasmInterpreterWrapperConstants : 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 =
      TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
  // 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);
  // The number of return values according to the siganture.
  static constexpr int kReturnCountOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(3);
  // `reps_` of wasm::FunctionSig.
  static constexpr int kValueTypesArrayStartOffset =
      TYPED_FRAME_PUSHED_VALUE_OFFSET(4);
  // Array of arguments/return values.
  static constexpr int kArgRetsAddressOffset =
      TYPED_FRAME_PUSHED_VALUE_OFFSET(5);
  // Whether the array is for arguments or return values.
  static constexpr int kArgRetsIsArgsOffset =
      TYPED_FRAME_PUSHED_VALUE_OFFSET(6);
  // The index of the argument or return value being converted.
  static constexpr int kCurrentIndexOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(7);
  // Precomputed signature data.
  static constexpr int kSignatureDataOffset =
      TYPED_FRAME_PUSHED_VALUE_OFFSET(8);
};
#endif  // V8_ENABLE_DRUMBRAKE
#endif  // V8_ENABLE_WEBASSEMBLY

class BuiltinContinuationFrameConstants : public TypedFrameConstants {};

class ExitFrameConstants : public TypedFrameConstants {};
#define EXIT_FRAME_PUSHED_VALUE_OFFSET(x)
#define DEFINE_EXIT_FRAME_SIZES(x)

// Behaves like an exit frame but with target, new target and arguments count
// args.
class BuiltinExitFrameConstants : public ExitFrameConstants {};

// Behaves like an exit frame but with v8::FunctionCallbackInfo's implicit
// arguments (FCI), followed by JS arguments passed to the JS function
// (receiver and etc.).
//
//  slot      JS frame
//       +-----------------+--------------------------------
// -n-1-k|   parameter n   |                            ^
//       |- - - - - - - - -|                            |
//  -n-k |  parameter n-1  |                          Caller
//  ...  |       ...       |                       frame slots
//  -2-k |   parameter 1   |                       (slot < 0)
//       |- - - - - - - - -|                            |
//  -1-k |    receiver     |                            v
//  -----+-----------------+--------------------------------
//  -k   |   FCI slot k-1  |                            ^
//       |- - - - - - - - -|                            |
//  -k+1 |   FCI slot k-2  |                 v8::FunctionCallbackInfo's
//  ...  |       ...       |                   FCI::implicit_args[k]
//  -2   |   FCI slot 1    |                   k := FCI::kArgsLength
//       |- - - - - - - - -|                            |
//  -1   |   FCI slot 0    |                            v
//  -----+-----------------+--------------------------------
//   0   |   return addr   |   ^                        ^
//       |- - - - - - - - -|   |                        |
//   1   | saved frame ptr | ExitFrame                  |
//       |- - - - - - - - -| Header     <-- frame ptr   |
//   2   | [Constant Pool] |   |                        |
//       |- - - - - - - - -|   |                        |
// 2+cp  |Frame Type Marker|   |   if a constant pool   |
//       |- - - - - - - - -|   |    is used, cp = 1,    |
// 3+cp  |    caller SP    |   v   otherwise, cp = 0    |
//       |-----------------+----                        |
// 4+cp  | FCI::argc_      |   ^                      Callee
//       |- - - - - - - - -|   |                   frame slots
// 5+cp  | FCI::values_    |   |                   (slot >= 0)
//       |- - - - - - - - -|   |                        |
// 6+cp  | FCI::imp._args_ | Frame slots                |
//       |- - - - - - - - -|   |                        |
//  ...  | C function args |   |                        |
//       |- - - - - - - - -|   |                        |
//       |                 |   v                        |
//  -----+-----------------+----- <-- stack ptr -------------
//
class ApiCallbackExitFrameConstants : public ExitFrameConstants {};

// Behaves like an exit frame but with v8::PropertyCallbackInfo's (PCI)
// fields allocated in GC-ed area of the exit frame, followed by zero or
// more parameters (required by some callback kinds).
//
//  slot      JS frame
//       +-----------------+--------------------------------
// -n-1-k|   parameter n   |                            ^
//       |- - - - - - - - -|                            |
//  -n-k |  parameter n-1  |                          Caller
//  ...  |       ...       |                       frame slots
//  -2-k |   parameter 1   |                       (slot < 0)
//       |- - - - - - - - -|                            |
//  -1-k |   parameter 0   |                            v
//  -----+-----------------+--------------------------------
//  -k   |   PCI slot k-1  |                            ^
//       |- - - - - - - - -|                            |
//  -k+1 |   PCI slot k-2  |                 v8::PropertyCallbackInfo's
//  ...  |       ...       |                       PCI::args[k]
//  -2   |   PCI slot 1    |                   k := PCI::kArgsLength
//       |- - - - - - - - -|                            |
//  -1   |   PCI slot 0    |                            v
//  -----+-----------------+--------------------------------   <-- PCI object
//   0   |   return addr   |   ^                        ^
//       |- - - - - - - - -|   |                        |
//   1   | saved frame ptr | ExitFrame                  |
//       |- - - - - - - - -| Header     <-- frame ptr   |
//   2   | [Constant Pool] |   |                        |
//       |- - - - - - - - -|   |                        |
// 2+cp  |Frame Type Marker|   |   if a constant pool   |
//       |- - - - - - - - -|   |    is used, cp = 1,    |
// 3+cp  |    caller SP    |   v   otherwise, cp = 0    |
//       |-----------------+----                        |
// 4+cp  |                 |   ^                      Callee
//       |- - - - - - - - -|   |                   frame slots
//  ...  | C function args | Frame slots           (slot >= 0)
//       |- - - - - - - - -|   |                        |
//       |                 |   v                        |
//  -----+-----------------+----- <-- stack ptr -------------
//
class ApiAccessorExitFrameConstants : public ExitFrameConstants {};

// 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  |   ^                        |
//       |- - - - - - - - -|   |                        |
// 6+cp  |  offset / cell  | Unoptimized code header    |
//       |- - - - - - - - -|   |                        |
// 7+cp  |      FBV        |   v                        |
//       +-----------------+----                        |
// 8+cp  |   register 0    |   ^                     Callee
//       |- - - - - - - - -|   |                   frame slots
// 9+cp  |   register 1    | Register file         (slot >= 0)
//  ...  |       ...       |   |                        |
//       |  register n-1   |   |                        |
//       |- - - - - - - - -|   |                        |
// 9+cp+n|   register n    |   v                        v
//  -----+-----------------+----- <-- stack ptr -------------
//
class UnoptimizedFrameConstants : public StandardFrameConstants {};

// Interpreter frames are unoptimized frames that are being executed by the
// interpreter. In this case, the "offset or cell" slot contains the bytecode
// offset of the currently executing bytecode.
class InterpreterFrameConstants : public UnoptimizedFrameConstants {};

// Sparkplug frames are unoptimized frames that are being executed by
// sparkplug-compiled baseline code. base. In this case, the "offset or cell"
// slot contains the closure feedback cell.
class BaselineFrameConstants : public UnoptimizedFrameConstants {};

inline static int FPOffsetToFrameSlot(int frame_offset) {}

inline static int FrameSlotToFPOffset(int slot) {}

}  // namespace internal
}  // namespace v8

#if V8_TARGET_ARCH_IA32
#include "src/execution/ia32/frame-constants-ia32.h"
#elif V8_TARGET_ARCH_X64
#include "src/execution/x64/frame-constants-x64.h"
#elif V8_TARGET_ARCH_ARM64
#include "src/execution/arm64/frame-constants-arm64.h"
#elif V8_TARGET_ARCH_ARM
#include "src/execution/arm/frame-constants-arm.h"
#elif V8_TARGET_ARCH_PPC64
#include "src/execution/ppc/frame-constants-ppc.h"
#elif V8_TARGET_ARCH_MIPS64
#include "src/execution/mips64/frame-constants-mips64.h"
#elif V8_TARGET_ARCH_LOONG64
#include "src/execution/loong64/frame-constants-loong64.h"
#elif V8_TARGET_ARCH_S390
#include "src/execution/s390/frame-constants-s390.h"
#elif V8_TARGET_ARCH_RISCV32 || V8_TARGET_ARCH_RISCV64
#include "src/execution/riscv/frame-constants-riscv.h"
#else
#error Unsupported target architecture.
#endif

#endif  // V8_EXECUTION_FRAME_CONSTANTS_H_