1 // Copyright 2012 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_FRAMES_INL_H_
6 #define V8_FRAMES_INL_H_
7
8 #include "src/frames.h"
9 #include "src/isolate.h"
10 #include "src/v8memory.h"
11
12 #if V8_TARGET_ARCH_IA32
13 #include "src/ia32/frames-ia32.h" // NOLINT
14 #elif V8_TARGET_ARCH_X64
15 #include "src/x64/frames-x64.h" // NOLINT
16 #elif V8_TARGET_ARCH_ARM64
17 #include "src/arm64/frames-arm64.h" // NOLINT
18 #elif V8_TARGET_ARCH_ARM
19 #include "src/arm/frames-arm.h" // NOLINT
20 #elif V8_TARGET_ARCH_MIPS
21 #include "src/mips/frames-mips.h" // NOLINT
22 #elif V8_TARGET_ARCH_MIPS64
23 #include "src/mips64/frames-mips64.h" // NOLINT
24 #elif V8_TARGET_ARCH_X87
25 #include "src/x87/frames-x87.h" // NOLINT
26 #else
27 #error Unsupported target architecture.
28 #endif
29
30 namespace v8 {
31 namespace internal {
32
33
address()34 inline Address StackHandler::address() const {
35 return reinterpret_cast<Address>(const_cast<StackHandler*>(this));
36 }
37
38
next()39 inline StackHandler* StackHandler::next() const {
40 const int offset = StackHandlerConstants::kNextOffset;
41 return FromAddress(Memory::Address_at(address() + offset));
42 }
43
44
includes(Address address)45 inline bool StackHandler::includes(Address address) const {
46 Address start = this->address();
47 Address end = start + StackHandlerConstants::kSize;
48 return start <= address && address <= end;
49 }
50
51
Iterate(ObjectVisitor * v,Code * holder)52 inline void StackHandler::Iterate(ObjectVisitor* v, Code* holder) const {
53 v->VisitPointer(context_address());
54 v->VisitPointer(code_address());
55 }
56
57
FromAddress(Address address)58 inline StackHandler* StackHandler::FromAddress(Address address) {
59 return reinterpret_cast<StackHandler*>(address);
60 }
61
62
is_js_entry()63 inline bool StackHandler::is_js_entry() const {
64 return kind() == JS_ENTRY;
65 }
66
67
is_catch()68 inline bool StackHandler::is_catch() const {
69 return kind() == CATCH;
70 }
71
72
is_finally()73 inline bool StackHandler::is_finally() const {
74 return kind() == FINALLY;
75 }
76
77
kind()78 inline StackHandler::Kind StackHandler::kind() const {
79 const int offset = StackHandlerConstants::kStateOffset;
80 return KindField::decode(Memory::unsigned_at(address() + offset));
81 }
82
83
index()84 inline unsigned StackHandler::index() const {
85 const int offset = StackHandlerConstants::kStateOffset;
86 return IndexField::decode(Memory::unsigned_at(address() + offset));
87 }
88
89
context_address()90 inline Object** StackHandler::context_address() const {
91 const int offset = StackHandlerConstants::kContextOffset;
92 return reinterpret_cast<Object**>(address() + offset);
93 }
94
95
code_address()96 inline Object** StackHandler::code_address() const {
97 const int offset = StackHandlerConstants::kCodeOffset;
98 return reinterpret_cast<Object**>(address() + offset);
99 }
100
101
StackFrame(StackFrameIteratorBase * iterator)102 inline StackFrame::StackFrame(StackFrameIteratorBase* iterator)
103 : iterator_(iterator), isolate_(iterator_->isolate()) {
104 }
105
106
top_handler()107 inline StackHandler* StackFrame::top_handler() const {
108 return iterator_->handler();
109 }
110
111
LookupCode()112 inline Code* StackFrame::LookupCode() const {
113 return GetContainingCode(isolate(), pc());
114 }
115
116
GetContainingCode(Isolate * isolate,Address pc)117 inline Code* StackFrame::GetContainingCode(Isolate* isolate, Address pc) {
118 return isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code;
119 }
120
121
ResolveReturnAddressLocation(Address * pc_address)122 inline Address* StackFrame::ResolveReturnAddressLocation(Address* pc_address) {
123 if (return_address_location_resolver_ == NULL) {
124 return pc_address;
125 } else {
126 return reinterpret_cast<Address*>(
127 return_address_location_resolver_(
128 reinterpret_cast<uintptr_t>(pc_address)));
129 }
130 }
131
132
EntryFrame(StackFrameIteratorBase * iterator)133 inline EntryFrame::EntryFrame(StackFrameIteratorBase* iterator)
134 : StackFrame(iterator) {
135 }
136
137
EntryConstructFrame(StackFrameIteratorBase * iterator)138 inline EntryConstructFrame::EntryConstructFrame(
139 StackFrameIteratorBase* iterator)
140 : EntryFrame(iterator) {
141 }
142
143
ExitFrame(StackFrameIteratorBase * iterator)144 inline ExitFrame::ExitFrame(StackFrameIteratorBase* iterator)
145 : StackFrame(iterator) {
146 }
147
148
StandardFrame(StackFrameIteratorBase * iterator)149 inline StandardFrame::StandardFrame(StackFrameIteratorBase* iterator)
150 : StackFrame(iterator) {
151 }
152
153
GetExpression(int index)154 inline Object* StandardFrame::GetExpression(int index) const {
155 return Memory::Object_at(GetExpressionAddress(index));
156 }
157
158
SetExpression(int index,Object * value)159 inline void StandardFrame::SetExpression(int index, Object* value) {
160 Memory::Object_at(GetExpressionAddress(index)) = value;
161 }
162
163
context()164 inline Object* StandardFrame::context() const {
165 const int offset = StandardFrameConstants::kContextOffset;
166 return Memory::Object_at(fp() + offset);
167 }
168
169
caller_fp()170 inline Address StandardFrame::caller_fp() const {
171 return Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset);
172 }
173
174
caller_pc()175 inline Address StandardFrame::caller_pc() const {
176 return Memory::Address_at(ComputePCAddress(fp()));
177 }
178
179
ComputePCAddress(Address fp)180 inline Address StandardFrame::ComputePCAddress(Address fp) {
181 return fp + StandardFrameConstants::kCallerPCOffset;
182 }
183
184
ComputeConstantPoolAddress(Address fp)185 inline Address StandardFrame::ComputeConstantPoolAddress(Address fp) {
186 return fp + StandardFrameConstants::kConstantPoolOffset;
187 }
188
189
IsArgumentsAdaptorFrame(Address fp)190 inline bool StandardFrame::IsArgumentsAdaptorFrame(Address fp) {
191 Object* marker =
192 Memory::Object_at(fp + StandardFrameConstants::kContextOffset);
193 return marker == Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR);
194 }
195
196
IsConstructFrame(Address fp)197 inline bool StandardFrame::IsConstructFrame(Address fp) {
198 Object* marker =
199 Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset);
200 return marker == Smi::FromInt(StackFrame::CONSTRUCT);
201 }
202
203
JavaScriptFrame(StackFrameIteratorBase * iterator)204 inline JavaScriptFrame::JavaScriptFrame(StackFrameIteratorBase* iterator)
205 : StandardFrame(iterator) {
206 }
207
208
GetParameterSlot(int index)209 Address JavaScriptFrame::GetParameterSlot(int index) const {
210 int param_count = ComputeParametersCount();
211 DCHECK(-1 <= index && index < param_count);
212 int parameter_offset = (param_count - index - 1) * kPointerSize;
213 return caller_sp() + parameter_offset;
214 }
215
216
GetParameter(int index)217 Object* JavaScriptFrame::GetParameter(int index) const {
218 return Memory::Object_at(GetParameterSlot(index));
219 }
220
221
GetOperandSlot(int index)222 inline Address JavaScriptFrame::GetOperandSlot(int index) const {
223 Address base = fp() + JavaScriptFrameConstants::kLocal0Offset;
224 DCHECK(IsAddressAligned(base, kPointerSize));
225 DCHECK_EQ(type(), JAVA_SCRIPT);
226 DCHECK_LT(index, ComputeOperandsCount());
227 DCHECK_LE(0, index);
228 // Operand stack grows down.
229 return base - index * kPointerSize;
230 }
231
232
GetOperand(int index)233 inline Object* JavaScriptFrame::GetOperand(int index) const {
234 return Memory::Object_at(GetOperandSlot(index));
235 }
236
237
ComputeOperandsCount()238 inline int JavaScriptFrame::ComputeOperandsCount() const {
239 Address base = fp() + JavaScriptFrameConstants::kLocal0Offset;
240 // Base points to low address of first operand and stack grows down, so add
241 // kPointerSize to get the actual stack size.
242 intptr_t stack_size_in_bytes = (base + kPointerSize) - sp();
243 DCHECK(IsAligned(stack_size_in_bytes, kPointerSize));
244 DCHECK(type() == JAVA_SCRIPT);
245 DCHECK(stack_size_in_bytes >= 0);
246 return static_cast<int>(stack_size_in_bytes >> kPointerSizeLog2);
247 }
248
249
receiver()250 inline Object* JavaScriptFrame::receiver() const {
251 return GetParameter(-1);
252 }
253
254
set_receiver(Object * value)255 inline void JavaScriptFrame::set_receiver(Object* value) {
256 Memory::Object_at(GetParameterSlot(-1)) = value;
257 }
258
259
has_adapted_arguments()260 inline bool JavaScriptFrame::has_adapted_arguments() const {
261 return IsArgumentsAdaptorFrame(caller_fp());
262 }
263
264
function()265 inline JSFunction* JavaScriptFrame::function() const {
266 return JSFunction::cast(function_slot_object());
267 }
268
269
StubFrame(StackFrameIteratorBase * iterator)270 inline StubFrame::StubFrame(StackFrameIteratorBase* iterator)
271 : StandardFrame(iterator) {
272 }
273
274
OptimizedFrame(StackFrameIteratorBase * iterator)275 inline OptimizedFrame::OptimizedFrame(StackFrameIteratorBase* iterator)
276 : JavaScriptFrame(iterator) {
277 }
278
279
ArgumentsAdaptorFrame(StackFrameIteratorBase * iterator)280 inline ArgumentsAdaptorFrame::ArgumentsAdaptorFrame(
281 StackFrameIteratorBase* iterator) : JavaScriptFrame(iterator) {
282 }
283
284
InternalFrame(StackFrameIteratorBase * iterator)285 inline InternalFrame::InternalFrame(StackFrameIteratorBase* iterator)
286 : StandardFrame(iterator) {
287 }
288
289
StubFailureTrampolineFrame(StackFrameIteratorBase * iterator)290 inline StubFailureTrampolineFrame::StubFailureTrampolineFrame(
291 StackFrameIteratorBase* iterator) : StandardFrame(iterator) {
292 }
293
294
ConstructFrame(StackFrameIteratorBase * iterator)295 inline ConstructFrame::ConstructFrame(StackFrameIteratorBase* iterator)
296 : InternalFrame(iterator) {
297 }
298
299
JavaScriptFrameIterator(Isolate * isolate)300 inline JavaScriptFrameIterator::JavaScriptFrameIterator(
301 Isolate* isolate)
302 : iterator_(isolate) {
303 if (!done()) Advance();
304 }
305
306
JavaScriptFrameIterator(Isolate * isolate,ThreadLocalTop * top)307 inline JavaScriptFrameIterator::JavaScriptFrameIterator(
308 Isolate* isolate, ThreadLocalTop* top)
309 : iterator_(isolate, top) {
310 if (!done()) Advance();
311 }
312
313
frame()314 inline JavaScriptFrame* JavaScriptFrameIterator::frame() const {
315 // TODO(1233797): The frame hierarchy needs to change. It's
316 // problematic that we can't use the safe-cast operator to cast to
317 // the JavaScript frame type, because we may encounter arguments
318 // adaptor frames.
319 StackFrame* frame = iterator_.frame();
320 DCHECK(frame->is_java_script() || frame->is_arguments_adaptor());
321 return static_cast<JavaScriptFrame*>(frame);
322 }
323
324
frame()325 inline StackFrame* SafeStackFrameIterator::frame() const {
326 DCHECK(!done());
327 DCHECK(frame_->is_java_script() || frame_->is_exit());
328 return frame_;
329 }
330
331
332 } } // namespace v8::internal
333
334 #endif // V8_FRAMES_INL_H_
335