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