blob: 0d1a27c3f3e2c36791df8489fc2cb4c0e6618293 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_FRAMES_ARM_H_
29#define V8_FRAMES_ARM_H_
30
31namespace v8 { namespace internal {
32
33
34// The ARM ABI does not specify the usage of register r9, which may be reserved
35// as the static base or thread register on some platforms, in which case we
36// leave it alone. Adjust the value of kR9Available accordingly:
37static const int kR9Available = 1; // 1 if available to us, 0 if reserved
38
39
40// Register list in load/store instructions
41// Note that the bit values must match those used in actual instruction encoding
42static const int kNumRegs = 16;
43
44
45// Caller-saved/arguments registers
46static const RegList kJSCallerSaved =
47 1 << 0 | // r0 a1
48 1 << 1 | // r1 a2
49 1 << 2 | // r2 a3
50 1 << 3; // r3 a4
51
52static const int kNumJSCallerSaved = 4;
53
54typedef Object* JSCallerSavedBuffer[kNumJSCallerSaved];
55
56// Return the code of the n-th caller-saved register available to JavaScript
57// e.g. JSCallerSavedReg(0) returns r0.code() == 0
58int JSCallerSavedCode(int n);
59
60
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000061// Callee-saved registers preserved when switching from C to JavaScript
kasper.lund7276f142008-07-30 08:49:36 +000062static const RegList kCalleeSaved =
63 1 << 4 | // r4 v1
64 1 << 5 | // r5 v2
65 1 << 6 | // r6 v3
66 1 << 7 | // r7 v4
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000067 1 << 8 | // r8 v5 (cp in JavaScript code)
kasper.lund7276f142008-07-30 08:49:36 +000068 kR9Available
69 << 9 | // r9 v6
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000070 1 << 10 | // r10 v7 (pp in JavaScript code)
mads.s.ager31e71382008-08-13 09:32:07 +000071 1 << 11; // r11 v8 (fp in JavaScript code)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000072
kasper.lund7276f142008-07-30 08:49:36 +000073static const int kNumCalleeSaved = 7 + kR9Available;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000074
75
76// ----------------------------------------------------
77
78
79class StackHandlerConstants : public AllStatic {
80 public:
81 // TODO(1233780): Get rid of the code slot in stack handlers.
82 static const int kCodeOffset = 0 * kPointerSize;
83 static const int kNextOffset = 1 * kPointerSize;
84 static const int kStateOffset = 2 * kPointerSize;
85 static const int kPPOffset = 3 * kPointerSize;
86 static const int kFPOffset = 4 * kPointerSize;
87 static const int kPCOffset = 5 * kPointerSize;
88
89 static const int kAddressDisplacement = -1 * kPointerSize;
90 static const int kSize = kPCOffset + kPointerSize;
91};
92
93
94class EntryFrameConstants : public AllStatic {
95 public:
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000096 static const int kCallerFPOffset = -3 * kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000097};
98
99
100class ExitFrameConstants : public AllStatic {
101 public:
102 // Exit frames have a debug marker on the stack.
103 static const int kSPDisplacement = -1 * kPointerSize;
104
105 // The debug marker is just above the frame pointer.
106 static const int kDebugMarkOffset = -1 * kPointerSize;
107
108 static const int kSavedRegistersOffset = 0 * kPointerSize;
109
110 // Let the parameters pointer for exit frames point just below the
kasper.lund7276f142008-07-30 08:49:36 +0000111 // frame structure on the stack.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000112 static const int kPPDisplacement = 3 * kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000113
kasper.lund7276f142008-07-30 08:49:36 +0000114 // The caller fields are below the frame pointer on the stack.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000115 static const int kCallerFPOffset = +0 * kPointerSize;
116 static const int kCallerPPOffset = +1 * kPointerSize;
117 static const int kCallerPCOffset = +2 * kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000118};
119
120
121class StandardFrameConstants : public AllStatic {
122 public:
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000123 static const int kExpressionsOffset = -3 * kPointerSize;
124 static const int kMarkerOffset = -2 * kPointerSize;
125 static const int kContextOffset = -1 * kPointerSize;
126 static const int kCallerFPOffset = 0 * kPointerSize;
127 static const int kCallerPCOffset = +1 * kPointerSize;
128 static const int kCallerSPOffset = +2 * kPointerSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000129};
130
131
132class JavaScriptFrameConstants : public AllStatic {
133 public:
134 // FP-relative.
135 static const int kLocal0Offset = StandardFrameConstants::kExpressionsOffset;
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000136 static const int kSavedRegistersOffset = +2 * kPointerSize;
137 static const int kFunctionOffset = StandardFrameConstants::kMarkerOffset;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000138
139 // PP-relative.
140 static const int kParam0Offset = -2 * kPointerSize;
141 static const int kReceiverOffset = -1 * kPointerSize;
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000142};
143
144
145class ArgumentsAdaptorFrameConstants : public AllStatic {
146 public:
147 static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000148};
149
150
151class InternalFrameConstants : public AllStatic {
152 public:
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000153 static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000154};
155
156
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000157inline Object* JavaScriptFrame::function() const {
158 const int offset = JavaScriptFrameConstants::kFunctionOffset;
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000159 Object* result = Memory::Object_at(fp() + offset);
160 ASSERT(result->IsJSFunction());
161 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000162}
163
164
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000165// ----------------------------------------------------
166
167
168
169
170 // lower | Stack |
171 // addresses | ^ |
172 // | | |
173 // | |
174 // | JS frame |
175 // | |
176 // | |
177 // ----------- +=============+ <--- sp (stack pointer)
178 // | function |
179 // +-------------+
kasper.lund7276f142008-07-30 08:49:36 +0000180 // +-------------+
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000181 // | |
182 // | expressions |
183 // | |
184 // +-------------+
185 // | |
186 // a | locals |
187 // c | |
188 // t +- - - - - - -+ <---
189 // i -4 | local0 | ^
190 // v +-------------+ |
191 // a -3 | code | |
192 // t +-------------+ | kLocal0Offset
193 // i -2 | context | |
194 // o +-------------+ |
195 // n -1 | args_length | v
196 // +-------------+ <--- fp (frame pointer)
197 // 0 | caller_pp |
198 // f +-------------+
199 // r 1 | caller_fp |
200 // a +-------------+
201 // m 2 | sp_on_exit | (pp if return, caller_sp if no return)
202 // e +-------------+
203 // 3 | caller_pc |
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000204 // +-------------+ <--- caller_sp (incl. parameters)
205 // | |
206 // | parameters |
207 // | |
208 // +- - - - - - -+ <---
209 // -2 | parameter0 | ^
210 // +-------------+ | kParam0Offset
211 // -1 | receiver | v
212 // ----------- +=============+ <--- pp (parameter pointer, r10)
213 // 0 | function |
214 // +-------------+
215 // | |
216 // |caller-saved | (must be valid JS values, traversed during GC)
217 // | regs |
218 // | |
219 // +-------------+
220 // | |
221 // | caller |
222 // higher | expressions |
223 // addresses | |
224 // | |
225 // | JS frame |
226
227
228
229 // Handler frames (part of expressions of JS frames):
230
231 // lower | Stack |
232 // addresses | ^ |
233 // | | |
234 // | |
235 // h | expressions |
236 // a | |
237 // n +-------------+
238 // d -1 | code |
239 // l +-------------+ <--- handler sp
240 // e 0 | next_sp | link to next handler (next handler's sp)
241 // r +-------------+
242 // 1 | state |
243 // f +-------------+
244 // r 2 | pp |
245 // a +-------------+
246 // m 3 | fp |
247 // e +-------------+
248 // 4 | pc |
249 // +-------------+
250 // | |
251 // higher | expressions |
252 // addresses | |
253
254
255
256 // JS entry frames: When calling from C to JS, we construct two extra
257 // frames: An entry frame (C) and a trampoline frame (JS). The
258 // following pictures shows the two frames:
259
260 // lower | Stack |
261 // addresses | ^ |
262 // | | |
263 // | |
264 // | JS frame |
265 // | |
266 // | |
267 // ----------- +=============+ <--- sp (stack pointer)
268 // | |
269 // | parameters |
270 // t | |
271 // r +- - - - - - -+
272 // a | parameter0 |
273 // m +-------------+
274 // p | receiver |
275 // o +-------------+
276 // l | function |
277 // i +-------------+
278 // n -3 | code |
279 // e +-------------+
280 // -2 | NULL | context is always NULL
281 // +-------------+
282 // f -1 | 0 | args_length is always zero
283 // r +-------------+ <--- fp (frame pointer)
284 // a 0 | NULL | caller pp is always NULL for entries
285 // m +-------------+
286 // e 1 | caller_fp |
287 // +-------------+
288 // 2 | sp_on_exit | (caller_sp)
289 // +-------------+
290 // 3 | caller_pc |
291 // ----------- +=============+ <--- caller_sp == pp
292 // . ^
293 // . | try-handler, fake, not GC'ed
294 // . v
295 // +-------------+ <---
296 // -2 | next top pp |
297 // +-------------+
298 // -1 | next top fp |
299 // +-------------+ <--- fp
300 // | r4 | r4-r9 holding non-JS values must be preserved
301 // +-------------+
302 // J | r5 | before being initialized not to confuse GC
303 // S +-------------+
304 // | r6 |
305 // +-------------+
306 // e | r7 |
307 // n +-------------+
308 // t | r8 |
309 // r +-------------+
310 // y [ | r9 | ] only if r9 available
311 // +-------------+
312 // | r10 |
313 // f +-------------+
314 // r | r11 |
315 // a +-------------+
316 // m | caller_sp |
317 // e +-------------+
318 // | caller_pc |
319 // +-------------+ <--- caller_sp
320 // | argv | passed on stack from C code
321 // +-------------+
322 // | |
323 // higher | |
324 // addresses | C frame |
325
326
327 // The first 4 args are passed from C in r0-r3 and are not spilled on entry:
328 // r0: code entry
329 // r1: function
330 // r2: receiver
331 // r3: argc
332 // [sp+0]: argv
333
334
335 // C entry frames: When calling from JS to C, we construct one extra
336 // frame:
337
338 // lower | Stack |
339 // addresses | ^ |
340 // | | |
341 // | |
342 // | C frame |
343 // | |
344 // | |
345 // ----------- +=============+ <--- sp (stack pointer)
346 // | |
347 // | parameters | (first 4 args are passed in r0-r3)
348 // | |
349 // +-------------+ <--- fp (frame pointer)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000350 // f 4/5 | caller_fp |
351 // r +-------------+
352 // a 5/6 | sp_on_exit | (pp)
353 // m +-------------+
354 // e 6/7 | caller_pc |
355 // +-------------+ <--- caller_sp (incl. parameters)
356 // 7/8 | |
357 // | parameters |
358 // | |
359 // +- - - - - - -+ <---
360 // -2 | parameter0 | ^
361 // +-------------+ | kParam0Offset
362 // -1 | receiver | v
363 // ----------- +=============+ <--- pp (parameter pointer, r10)
364 // 0 | function |
365 // +-------------+
366 // | |
367 // |caller-saved |
368 // | regs |
369 // | |
370 // +-------------+
371 // | |
372 // | caller |
373 // | expressions |
374 // | |
375 // higher | |
376 // addresses | JS frame |
377
378
379} } // namespace v8::internal
380
381#endif // V8_FRAMES_ARM_H_