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_FRAME_CONSTANTS_H_
6#define V8_FRAME_CONSTANTS_H_
7
8#include "src/flags.h"
9#include "src/globals.h"
10
11namespace v8 {
12namespace 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 0 | ^
27// |- - - - - - - - -| |
28// -n | | Caller
29// ... | ... | frame slots
30// -2 | parameter n-1 | (slot < 0)
31// |- - - - - - - - -| |
32// -1 | parameter n | 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//
51class 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. StandardFrame::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 interpreted and optimized JavaScript
75// frames. They always have a context below the saved fp/constant
76// pool and below that the JSFunction of the executing function.
77//
78// slot JS frame
79// +-----------------+--------------------------------
80// -n-1 | parameter 0 | ^
81// |- - - - - - - - -| |
82// -n | | Caller
83// ... | ... | frame slots
84// -2 | parameter n-1 | (slot < 0)
85// |- - - - - - - - -| |
86// -1 | parameter n | v
87// -----+-----------------+--------------------------------
88// 0 | return addr | ^ ^
89// |- - - - - - - - -| | |
90// 1 | saved frame ptr | Fixed |
91// |- - - - - - - - -| Header <-- frame ptr |
92// 2 | [Constant Pool] | | |
93// |- - - - - - - - -| | |
94// 2+cp | Context | | if a constant pool |
95// |- - - - - - - - -| | is used, cp = 1, |
96// 3+cp | JSFunction | v otherwise, cp = 0 |
97// +-----------------+---- |
98// 4+cp | | ^ Callee
99// |- - - - - - - - -| | frame slots
100// ... | | Frame slots (slot >= 0)
101// |- - - - - - - - -| | |
102// | | v |
103// -----+-----------------+----- <-- stack ptr -------------
104//
105class StandardFrameConstants : public CommonFrameConstants {
106 public:
107 static constexpr int kFixedFrameSizeFromFp =
108 2 * kSystemPointerSize + kCPSlotSize;
109 static constexpr int kFixedFrameSize =
110 kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp;
111 static constexpr int kFixedSlotCountFromFp =
112 kFixedFrameSizeFromFp / kSystemPointerSize;
113 static constexpr int kFixedSlotCount = kFixedFrameSize / kSystemPointerSize;
114 static constexpr int kContextOffset = kContextOrFrameTypeOffset;
115 static constexpr int kFunctionOffset = -2 * kSystemPointerSize - kCPSlotSize;
116 static constexpr int kExpressionsOffset =
117 -3 * kSystemPointerSize - kCPSlotSize;
118 static constexpr int kLastObjectOffset = kContextOffset;
119};
120
121// OptimizedBuiltinFrameConstants are used for TF-generated builtins. They
122// always have a context below the saved fp/constant pool and below that the
123// JSFunction of the executing function and below that an integer (not a Smi)
124// containing the number of arguments passed to the builtin.
125//
126// slot JS frame
127// +-----------------+--------------------------------
128// -n-1 | parameter 0 | ^
129// |- - - - - - - - -| |
130// -n | | Caller
131// ... | ... | frame slots
132// -2 | parameter n-1 | (slot < 0)
133// |- - - - - - - - -| |
134// -1 | parameter n | v
135// -----+-----------------+--------------------------------
136// 0 | return addr | ^ ^
137// |- - - - - - - - -| | |
138// 1 | saved frame ptr | Fixed |
139// |- - - - - - - - -| Header <-- frame ptr |
140// 2 | [Constant Pool] | | |
141// |- - - - - - - - -| | |
142// 2+cp | Context | | if a constant pool |
143// |- - - - - - - - -| | is used, cp = 1, |
144// 3+cp | JSFunction | | otherwise, cp = 0 |
145// |- - - - - - - - -| | |
146// 4+cp | argc | v |
147// +-----------------+---- |
148// 5+cp | | ^ Callee
149// |- - - - - - - - -| | frame slots
150// ... | | Frame slots (slot >= 0)
151// |- - - - - - - - -| | |
152// | | v |
153// -----+-----------------+----- <-- stack ptr -------------
154//
155class OptimizedBuiltinFrameConstants : public StandardFrameConstants {
156 public:
157 static constexpr int kArgCSize = kSystemPointerSize;
158 static constexpr int kArgCOffset = -3 * kSystemPointerSize - kCPSlotSize;
159 static constexpr int kFixedFrameSize = kFixedFrameSizeAboveFp - kArgCOffset;
160 static constexpr int kFixedSlotCount = kFixedFrameSize / kSystemPointerSize;
161};
162
163// TypedFrames have a SMI type maker value below the saved FP/constant pool to
164// distinguish them from StandardFrames, which have a context in that position
165// instead.
166//
167// slot JS frame
168// +-----------------+--------------------------------
169// -n-1 | parameter 0 | ^
170// |- - - - - - - - -| |
171// -n | | Caller
172// ... | ... | frame slots
173// -2 | parameter n-1 | (slot < 0)
174// |- - - - - - - - -| |
175// -1 | parameter n | v
176// -----+-----------------+--------------------------------
177// 0 | return addr | ^ ^
178// |- - - - - - - - -| | |
179// 1 | saved frame ptr | Fixed |
180// |- - - - - - - - -| Header <-- frame ptr |
181// 2 | [Constant Pool] | | |
182// |- - - - - - - - -| | |
183// 2+cp |Frame Type Marker| v if a constant pool |
184// |-----------------+---- is used, cp = 1, |
185// 3+cp | | ^ otherwise, cp = 0 |
186// |- - - - - - - - -| | |
187// 4+cp | | | Callee
188// |- - - - - - - - -| | frame slots
189// ... | | Frame slots (slot >= 0)
190// |- - - - - - - - -| | |
191// | | v |
192// -----+-----------------+----- <-- stack ptr -------------
193//
194class TypedFrameConstants : public CommonFrameConstants {
195 public:
196 static constexpr int kFrameTypeSize = kContextOrFrameTypeSize;
197 static constexpr int kFrameTypeOffset = kContextOrFrameTypeOffset;
198 static constexpr int kFixedFrameSizeFromFp = kCPSlotSize + kFrameTypeSize;
199 static constexpr int kFixedSlotCountFromFp =
200 kFixedFrameSizeFromFp / kSystemPointerSize;
201 static constexpr int kFixedFrameSize =
202 StandardFrameConstants::kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp;
203 static constexpr int kFixedSlotCount = kFixedFrameSize / kSystemPointerSize;
204 static constexpr int kFirstPushedFrameValueOffset =
205 -StandardFrameConstants::kCPSlotSize - kFrameTypeSize -
206 kSystemPointerSize;
207};
208
209#define TYPED_FRAME_PUSHED_VALUE_OFFSET(x) \
210 (TypedFrameConstants::kFirstPushedFrameValueOffset - (x)*kSystemPointerSize)
211#define TYPED_FRAME_SIZE(count) \
212 (TypedFrameConstants::kFixedFrameSize + (count)*kSystemPointerSize)
213#define TYPED_FRAME_SIZE_FROM_SP(count) \
214 (TypedFrameConstants::kFixedFrameSizeFromFp + (count)*kSystemPointerSize)
215#define DEFINE_TYPED_FRAME_SIZES(count) \
216 static constexpr int kFixedFrameSize = TYPED_FRAME_SIZE(count); \
217 static constexpr int kFixedSlotCount = kFixedFrameSize / kSystemPointerSize; \
218 static constexpr int kFixedFrameSizeFromFp = \
219 TYPED_FRAME_SIZE_FROM_SP(count); \
220 static constexpr int kFixedSlotCountFromFp = \
221 kFixedFrameSizeFromFp / kSystemPointerSize
222
223class ArgumentsAdaptorFrameConstants : public TypedFrameConstants {
224 public:
225 // FP-relative.
226 static constexpr int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
227 static constexpr int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
228 static constexpr int kPaddingOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2);
229 DEFINE_TYPED_FRAME_SIZES(3);
230};
231
232class BuiltinFrameConstants : public TypedFrameConstants {
233 public:
234 // FP-relative.
235 static constexpr int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
236 static constexpr int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
237 DEFINE_TYPED_FRAME_SIZES(2);
238};
239
240class ConstructFrameConstants : public TypedFrameConstants {
241 public:
242 // FP-relative.
243 static constexpr int kContextOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
244 static constexpr int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
245 static constexpr int kConstructorOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2);
246 static constexpr int kPaddingOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(3);
247 static constexpr int kNewTargetOrImplicitReceiverOffset =
248 TYPED_FRAME_PUSHED_VALUE_OFFSET(4);
249 DEFINE_TYPED_FRAME_SIZES(5);
250};
251
252class WasmCompiledFrameConstants : public TypedFrameConstants {
253 public:
254 // FP-relative.
255 static constexpr int kWasmInstanceOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
256 DEFINE_TYPED_FRAME_SIZES(1);
257};
258
259class BuiltinContinuationFrameConstants : public TypedFrameConstants {
260 public:
261 // FP-relative.
262 static constexpr int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
263 static constexpr int kFrameSPtoFPDeltaAtDeoptimize =
264 TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
265 static constexpr int kBuiltinContextOffset =
266 TYPED_FRAME_PUSHED_VALUE_OFFSET(2);
267 static constexpr int kBuiltinOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(3);
268
269 // The argument count is in the first allocatable register, stored below the
270 // fixed part of the frame and therefore is not part of the fixed frame size.
271 static constexpr int kArgCOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(4);
272 DEFINE_TYPED_FRAME_SIZES(4);
273
274 // Returns the number of padding stack slots needed when we have
275 // 'register_count' register slots.
276 // This is needed on some architectures to ensure the stack pointer is
277 // aligned.
278 static int PaddingSlotCount(int register_count);
279};
280
281// Behaves like an exit frame but with target and new target args.
282class BuiltinExitFrameConstants : public CommonFrameConstants {
283 public:
284 static constexpr int kNewTargetOffset =
285 kCallerPCOffset + 1 * kSystemPointerSize;
286 static constexpr int kTargetOffset =
287 kNewTargetOffset + 1 * kSystemPointerSize;
288 static constexpr int kArgcOffset = kTargetOffset + 1 * kSystemPointerSize;
289 static constexpr int kPaddingOffset = kArgcOffset + 1 * kSystemPointerSize;
290 static constexpr int kFirstArgumentOffset =
291 kPaddingOffset + 1 * kSystemPointerSize;
292 static constexpr int kNumExtraArgsWithReceiver = 5;
293};
294
295class InterpreterFrameConstants : public AllStatic {
296 public:
297 // Fixed frame includes bytecode array and bytecode offset.
298 static constexpr int kFixedFrameSize =
299 StandardFrameConstants::kFixedFrameSize + 2 * kSystemPointerSize;
300 static constexpr int kFixedFrameSizeFromFp =
301 StandardFrameConstants::kFixedFrameSizeFromFp + 2 * kSystemPointerSize;
302
303 // FP-relative.
304 static constexpr int kLastParamFromFp =
305 StandardFrameConstants::kCallerSPOffset;
306 static constexpr int kCallerPCOffsetFromFp =
307 StandardFrameConstants::kCallerPCOffset;
308 static constexpr int kBytecodeArrayFromFp =
309 -StandardFrameConstants::kFixedFrameSizeFromFp - 1 * kSystemPointerSize;
310 static constexpr int kBytecodeOffsetFromFp =
311 -StandardFrameConstants::kFixedFrameSizeFromFp - 2 * kSystemPointerSize;
312 static constexpr int kRegisterFileFromFp =
313 -StandardFrameConstants::kFixedFrameSizeFromFp - 3 * kSystemPointerSize;
314
315 static constexpr int kExpressionsOffset = kRegisterFileFromFp;
316
317 // Number of fixed slots in addition to a {StandardFrame}.
318 static constexpr int kExtraSlotCount =
319 InterpreterFrameConstants::kFixedFrameSize / kSystemPointerSize -
320 StandardFrameConstants::kFixedFrameSize / kSystemPointerSize;
321
322 // Expression index for {StandardFrame::GetExpressionAddress}.
323 static constexpr int kBytecodeArrayExpressionIndex = -2;
324 static constexpr int kBytecodeOffsetExpressionIndex = -1;
325 static constexpr int kRegisterFileExpressionIndex = 0;
326
327 // Returns the number of stack slots needed for 'register_count' registers.
328 // This is needed because some architectures must pad the stack frame with
329 // additional stack slots to ensure the stack pointer is aligned.
330 static int RegisterStackSlotCount(int register_count);
331};
332
333inline static int FPOffsetToFrameSlot(int frame_offset) {
334 return StandardFrameConstants::kFixedSlotCountAboveFp - 1 -
335 frame_offset / kSystemPointerSize;
336}
337
338inline static int FrameSlotToFPOffset(int slot) {
339 return (StandardFrameConstants::kFixedSlotCountAboveFp - 1 - slot) *
340 kSystemPointerSize;
341}
342
343} // namespace internal
344} // namespace v8
345
346#if V8_TARGET_ARCH_IA32
347#include "src/ia32/frame-constants-ia32.h" // NOLINT
348#elif V8_TARGET_ARCH_X64
349#include "src/x64/frame-constants-x64.h" // NOLINT
350#elif V8_TARGET_ARCH_ARM64
351#include "src/arm64/frame-constants-arm64.h" // NOLINT
352#elif V8_TARGET_ARCH_ARM
353#include "src/arm/frame-constants-arm.h" // NOLINT
354#elif V8_TARGET_ARCH_PPC
355#include "src/ppc/frame-constants-ppc.h" // NOLINT
356#elif V8_TARGET_ARCH_MIPS
357#include "src/mips/frame-constants-mips.h" // NOLINT
358#elif V8_TARGET_ARCH_MIPS64
359#include "src/mips64/frame-constants-mips64.h" // NOLINT
360#elif V8_TARGET_ARCH_S390
361#include "src/s390/frame-constants-s390.h" // NOLINT
362#else
363#error Unsupported target architecture.
364#endif
365
366#endif // V8_FRAME_CONSTANTS_H_
367