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 * 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 | // |
105 | class 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 | // |
155 | class 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 | // |
194 | class 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 | |
223 | class 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 | |
232 | class 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 | |
240 | class 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 | |
252 | class 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 | |
259 | class 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. |
282 | class 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 = 5; |
293 | }; |
294 | |
295 | class 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 = |
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 | |
333 | inline static int FPOffsetToFrameSlot(int frame_offset) { |
334 | return StandardFrameConstants::kFixedSlotCountAboveFp - 1 - |
335 | frame_offset / kSystemPointerSize; |
336 | } |
337 | |
338 | inline 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 | |