• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
11 namespace v8 {
12 namespace 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 //
51 class 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 //
109 class 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 //
158 class 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 
199 class 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.
209 class 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 
221 class 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
234 class 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 
241 class 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 
248 class 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 
256 class 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 
278 class 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.
290 class 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 //
345 class 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.
374 class 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.
386 class BaselineFrameConstants : public UnoptimizedFrameConstants {
387  public:
388   static constexpr int kFeedbackVectorExpressionIndex =
389       kBytecodeOffsetOrFeedbackVectorExpressionIndex;
390 
391   static constexpr int kFeedbackVectorFromFp =
392       kBytecodeOffsetOrFeedbackVectorFromFp;
393 };
394 
FPOffsetToFrameSlot(int frame_offset)395 inline static int FPOffsetToFrameSlot(int frame_offset) {
396   return StandardFrameConstants::kFixedSlotCountAboveFp - 1 -
397          frame_offset / kSystemPointerSize;
398 }
399 
FrameSlotToFPOffset(int slot)400 inline 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