• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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_ARM64_FRAME_CONSTANTS_ARM64_H_
6 #define V8_EXECUTION_ARM64_FRAME_CONSTANTS_ARM64_H_
7 
8 #include "src/base/bits.h"
9 #include "src/base/macros.h"
10 #include "src/codegen/register.h"
11 #include "src/codegen/reglist.h"
12 #include "src/common/globals.h"
13 #include "src/execution/frame-constants.h"
14 
15 namespace v8 {
16 namespace internal {
17 
18 // The layout of an EntryFrame is as follows:
19 //
20 //         BOTTOM OF THE STACK   HIGHEST ADDRESS
21 //  slot      Entry frame
22 //       +---------------------+-----------------------
23 // -19   | saved register d15  |
24 // ...   |        ...          |
25 // -12   | saved register d8   |
26 //       |- - - - - - - - - - -|
27 // -11   | saved register x28  |
28 // ...   |        ...          |
29 //  -2   | saved register x19  |
30 //       |- - - - - - - - - - -|
31 //  -1   |   saved lr (x30)    |
32 //       |- - - - - - - - - - -|
33 //   0   |   saved fp (x29)    |  <-- frame ptr
34 //       |- - - - - - - - - - -|
35 //   1   | stack frame marker  |
36 //       |      (ENTRY)        |
37 //       |- - - - - - - - - - -|
38 //   2   | stack frame marker  |
39 //       |        (0)          |
40 //       |- - - - - - - - - - -|
41 //   3   |     C entry FP      |
42 //       |- - - - - - - - - - -|
43 //   4   |   JS entry frame    |  <-- stack ptr
44 //       |       marker        |
45 //  -----+---------------------+-----------------------
46 //          TOP OF THE STACK     LOWEST ADDRESS
47 //
48 class EntryFrameConstants : public AllStatic {
49  public:
50   // This is the offset to where JSEntry pushes the current value of
51   // Isolate::c_entry_fp onto the stack.
52   static constexpr int kCallerFPOffset = -3 * kSystemPointerSize;
53   static constexpr int kFixedFrameSize = 4 * kSystemPointerSize;
54 
55   // The following constants are defined so we can static-assert their values
56   // near the relevant JSEntry assembly code, not because they're actually very
57   // useful.
58   static constexpr int kCalleeSavedRegisterBytesPushedBeforeFpLrPair =
59       18 * kSystemPointerSize;
60   static constexpr int kCalleeSavedRegisterBytesPushedAfterFpLrPair = 0;
61   static constexpr int kOffsetToCalleeSavedRegisters = 0;
62 
63   // These offsets refer to the immediate caller (a native frame), not to the
64   // previous JS exit frame like kCallerFPOffset above.
65   static constexpr int kDirectCallerFPOffset =
66       kCalleeSavedRegisterBytesPushedAfterFpLrPair +
67       kOffsetToCalleeSavedRegisters;
68   static constexpr int kDirectCallerPCOffset =
69       kDirectCallerFPOffset + 1 * kSystemPointerSize;
70   static constexpr int kDirectCallerSPOffset =
71       kDirectCallerPCOffset + 1 * kSystemPointerSize +
72       kCalleeSavedRegisterBytesPushedBeforeFpLrPair;
73 };
74 
75 class WasmCompileLazyFrameConstants : public TypedFrameConstants {
76  public:
77   static constexpr int kNumberOfSavedGpParamRegs = 8;
78   static constexpr int kNumberOfSavedFpParamRegs = 8;
79 
80   // FP-relative.
81   // The instance is pushed as part of the saved registers. Being in {r7}, it is
82   // the first register pushed (highest register code in
83   // {wasm::kGpParamRegisters}). Because of padding of the frame header, it is
84   // actually one word further down the stack though (thus at position {1}).
85   static constexpr int kWasmInstanceOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
86   static constexpr int kFixedFrameSizeFromFp =
87       // Header is padded to 16 byte (see {MacroAssembler::EnterFrame}).
88       RoundUp<16>(TypedFrameConstants::kFixedFrameSizeFromFp) +
89       kNumberOfSavedGpParamRegs * kSystemPointerSize +
90       kNumberOfSavedFpParamRegs * kSimd128Size;
91 };
92 
93 // Frame constructed by the {WasmDebugBreak} builtin.
94 // After pushing the frame type marker, the builtin pushes all Liftoff cache
95 // registers (see liftoff-assembler-defs.h).
96 class WasmDebugBreakFrameConstants : public TypedFrameConstants {
97  public:
98   // x16: ip0, x17: ip1, x18: platform register, x26: root, x28: base, x29: fp,
99   // x30: lr, x31: xzr.
100   static constexpr RegList kPushedGpRegs = {
101       x0,  x1,  x2,  x3,  x4,  x5,  x6,  x7,  x8,  x9,  x10, x11,
102       x12, x13, x14, x15, x19, x20, x21, x22, x23, x24, x25, x27};
103 
104   // We push FpRegs as 128-bit SIMD registers, so 16-byte frame alignment
105   // is guaranteed regardless of register count.
106   static constexpr DoubleRegList kPushedFpRegs = {
107       d0,  d1,  d2,  d3,  d4,  d5,  d6,  d7,  d8,  d9,  d10, d11, d12, d13, d14,
108       d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29};
109 
110   static constexpr int kNumPushedGpRegisters = kPushedGpRegs.Count();
111   static_assert(kNumPushedGpRegisters % 2 == 0,
112                 "stack frames need to be 16-byte aligned");
113 
114   static constexpr int kNumPushedFpRegisters = kPushedFpRegs.Count();
115 
116   static constexpr int kLastPushedGpRegisterOffset =
117       // Header is padded to 16 byte (see {MacroAssembler::EnterFrame}).
118       -RoundUp<16>(TypedFrameConstants::kFixedFrameSizeFromFp) -
119       kSystemPointerSize * kNumPushedGpRegisters;
120   static constexpr int kLastPushedFpRegisterOffset =
121       kLastPushedGpRegisterOffset - kSimd128Size * kNumPushedFpRegisters;
122 
123   // Offsets are fp-relative.
GetPushedGpRegisterOffset(int reg_code)124   static int GetPushedGpRegisterOffset(int reg_code) {
125     DCHECK_NE(0, kPushedGpRegs.bits() & (1 << reg_code));
126     uint32_t lower_regs =
127         kPushedGpRegs.bits() & ((uint32_t{1} << reg_code) - 1);
128     return kLastPushedGpRegisterOffset +
129            base::bits::CountPopulation(lower_regs) * kSystemPointerSize;
130   }
131 
GetPushedFpRegisterOffset(int reg_code)132   static int GetPushedFpRegisterOffset(int reg_code) {
133     DCHECK_NE(0, kPushedFpRegs.bits() & (1 << reg_code));
134     uint32_t lower_regs =
135         kPushedFpRegs.bits() & ((uint32_t{1} << reg_code) - 1);
136     return kLastPushedFpRegisterOffset +
137            base::bits::CountPopulation(lower_regs) * kSimd128Size;
138   }
139 };
140 
141 }  // namespace internal
142 }  // namespace v8
143 
144 #endif  // V8_EXECUTION_ARM64_FRAME_CONSTANTS_ARM64_H_
145