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