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/frame-constants.h"
9#include "src/frames.h"
10#include "src/isolate.h"
11#include "src/objects-inl.h"
12#include "src/v8memory.h"
13
14namespace v8 {
15namespace internal {
16
17class InnerPointerToCodeCache {
18 public:
19 struct InnerPointerToCodeCacheEntry {
20 Address inner_pointer;
21 Code code;
22 SafepointEntry safepoint_entry;
23 };
24
25 explicit InnerPointerToCodeCache(Isolate* isolate) : isolate_(isolate) {
26 Flush();
27 }
28
29 void Flush() { memset(static_cast<void*>(&cache_[0]), 0, sizeof(cache_)); }
30
31 InnerPointerToCodeCacheEntry* GetCacheEntry(Address inner_pointer);
32
33 private:
34 InnerPointerToCodeCacheEntry* cache(int index) { return &cache_[index]; }
35
36 Isolate* isolate_;
37
38 static const int kInnerPointerToCodeCacheSize = 1024;
39 InnerPointerToCodeCacheEntry cache_[kInnerPointerToCodeCacheSize];
40
41 DISALLOW_COPY_AND_ASSIGN(InnerPointerToCodeCache);
42};
43
44inline Address StackHandler::address() const {
45 return reinterpret_cast<Address>(const_cast<StackHandler*>(this));
46}
47
48
49inline StackHandler* StackHandler::next() const {
50 const int offset = StackHandlerConstants::kNextOffset;
51 return FromAddress(Memory<Address>(address() + offset));
52}
53
54inline Address StackHandler::next_address() const {
55 return Memory<Address>(address() + StackHandlerConstants::kNextOffset);
56}
57
58inline StackHandler* StackHandler::FromAddress(Address address) {
59 return reinterpret_cast<StackHandler*>(address);
60}
61
62
63inline StackFrame::StackFrame(StackFrameIteratorBase* iterator)
64 : iterator_(iterator), isolate_(iterator_->isolate()) {
65}
66
67
68inline StackHandler* StackFrame::top_handler() const {
69 return iterator_->handler();
70}
71
72
73inline Address* StackFrame::ResolveReturnAddressLocation(Address* pc_address) {
74 if (return_address_location_resolver_ == nullptr) {
75 return pc_address;
76 } else {
77 return reinterpret_cast<Address*>(
78 return_address_location_resolver_(
79 reinterpret_cast<uintptr_t>(pc_address)));
80 }
81}
82
83inline NativeFrame::NativeFrame(StackFrameIteratorBase* iterator)
84 : StackFrame(iterator) {}
85
86inline Address NativeFrame::GetCallerStackPointer() const {
87 return fp() + CommonFrameConstants::kCallerSPOffset;
88}
89
90inline EntryFrame::EntryFrame(StackFrameIteratorBase* iterator)
91 : StackFrame(iterator) {}
92
93inline ConstructEntryFrame::ConstructEntryFrame(
94 StackFrameIteratorBase* iterator)
95 : EntryFrame(iterator) {}
96
97inline ExitFrame::ExitFrame(StackFrameIteratorBase* iterator)
98 : StackFrame(iterator) {}
99
100inline BuiltinExitFrame::BuiltinExitFrame(StackFrameIteratorBase* iterator)
101 : ExitFrame(iterator) {}
102
103inline Object BuiltinExitFrame::receiver_slot_object() const {
104 // The receiver is the first argument on the frame.
105 // fp[1]: return address.
106 // fp[2]: the last argument (new target).
107 // fp[4]: argc.
108 // fp[2 + argc - 1]: receiver.
109 Object argc_slot = argc_slot_object();
110 DCHECK(argc_slot->IsSmi());
111 int argc = Smi::ToInt(argc_slot);
112
113 const int receiverOffset = BuiltinExitFrameConstants::kNewTargetOffset +
114 (argc - 1) * kSystemPointerSize;
115 return Object(Memory<Address>(fp() + receiverOffset));
116}
117
118inline Object BuiltinExitFrame::argc_slot_object() const {
119 return Object(Memory<Address>(fp() + BuiltinExitFrameConstants::kArgcOffset));
120}
121
122inline Object BuiltinExitFrame::target_slot_object() const {
123 return Object(
124 Memory<Address>(fp() + BuiltinExitFrameConstants::kTargetOffset));
125}
126
127inline Object BuiltinExitFrame::new_target_slot_object() const {
128 return Object(
129 Memory<Address>(fp() + BuiltinExitFrameConstants::kNewTargetOffset));
130}
131
132inline StandardFrame::StandardFrame(StackFrameIteratorBase* iterator)
133 : StackFrame(iterator) {
134}
135
136inline Object StandardFrame::GetExpression(int index) const {
137 return Object(Memory<Address>(GetExpressionAddress(index)));
138}
139
140inline void StandardFrame::SetExpression(int index, Object value) {
141 Memory<Address>(GetExpressionAddress(index)) = value->ptr();
142}
143
144inline Address StandardFrame::caller_fp() const {
145 return Memory<Address>(fp() + StandardFrameConstants::kCallerFPOffset);
146}
147
148
149inline Address StandardFrame::caller_pc() const {
150 return Memory<Address>(ComputePCAddress(fp()));
151}
152
153
154inline Address StandardFrame::ComputePCAddress(Address fp) {
155 return fp + StandardFrameConstants::kCallerPCOffset;
156}
157
158
159inline Address StandardFrame::ComputeConstantPoolAddress(Address fp) {
160 return fp + StandardFrameConstants::kConstantPoolOffset;
161}
162
163
164inline bool StandardFrame::IsArgumentsAdaptorFrame(Address fp) {
165 intptr_t frame_type =
166 Memory<intptr_t>(fp + TypedFrameConstants::kFrameTypeOffset);
167 return frame_type == StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR);
168}
169
170
171inline bool StandardFrame::IsConstructFrame(Address fp) {
172 intptr_t frame_type =
173 Memory<intptr_t>(fp + TypedFrameConstants::kFrameTypeOffset);
174 return frame_type == StackFrame::TypeToMarker(StackFrame::CONSTRUCT);
175}
176
177inline JavaScriptFrame::JavaScriptFrame(StackFrameIteratorBase* iterator)
178 : StandardFrame(iterator) {}
179
180Address JavaScriptFrame::GetParameterSlot(int index) const {
181 int param_count = ComputeParametersCount();
182 DCHECK(-1 <= index &&
183 (index < param_count ||
184 param_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel));
185 int parameter_offset = (param_count - index - 1) * kSystemPointerSize;
186 return caller_sp() + parameter_offset;
187}
188
189inline void JavaScriptFrame::set_receiver(Object value) {
190 Memory<Address>(GetParameterSlot(-1)) = value->ptr();
191}
192
193inline bool JavaScriptFrame::has_adapted_arguments() const {
194 return IsArgumentsAdaptorFrame(caller_fp());
195}
196
197inline Object JavaScriptFrame::function_slot_object() const {
198 const int offset = JavaScriptFrameConstants::kFunctionOffset;
199 return Object(Memory<Address>(fp() + offset));
200}
201
202inline StubFrame::StubFrame(StackFrameIteratorBase* iterator)
203 : StandardFrame(iterator) {
204}
205
206
207inline OptimizedFrame::OptimizedFrame(StackFrameIteratorBase* iterator)
208 : JavaScriptFrame(iterator) {
209}
210
211
212inline InterpretedFrame::InterpretedFrame(StackFrameIteratorBase* iterator)
213 : JavaScriptFrame(iterator) {}
214
215
216inline ArgumentsAdaptorFrame::ArgumentsAdaptorFrame(
217 StackFrameIteratorBase* iterator) : JavaScriptFrame(iterator) {
218}
219
220inline BuiltinFrame::BuiltinFrame(StackFrameIteratorBase* iterator)
221 : JavaScriptFrame(iterator) {}
222
223inline WasmCompiledFrame::WasmCompiledFrame(StackFrameIteratorBase* iterator)
224 : StandardFrame(iterator) {}
225
226inline WasmInterpreterEntryFrame::WasmInterpreterEntryFrame(
227 StackFrameIteratorBase* iterator)
228 : StandardFrame(iterator) {}
229
230inline WasmToJsFrame::WasmToJsFrame(StackFrameIteratorBase* iterator)
231 : StubFrame(iterator) {}
232
233inline JsToWasmFrame::JsToWasmFrame(StackFrameIteratorBase* iterator)
234 : StubFrame(iterator) {}
235
236inline CWasmEntryFrame::CWasmEntryFrame(StackFrameIteratorBase* iterator)
237 : StubFrame(iterator) {}
238
239inline WasmCompileLazyFrame::WasmCompileLazyFrame(
240 StackFrameIteratorBase* iterator)
241 : StandardFrame(iterator) {}
242
243inline InternalFrame::InternalFrame(StackFrameIteratorBase* iterator)
244 : StandardFrame(iterator) {
245}
246
247inline ConstructFrame::ConstructFrame(StackFrameIteratorBase* iterator)
248 : InternalFrame(iterator) {
249}
250
251inline BuiltinContinuationFrame::BuiltinContinuationFrame(
252 StackFrameIteratorBase* iterator)
253 : InternalFrame(iterator) {}
254
255inline JavaScriptBuiltinContinuationFrame::JavaScriptBuiltinContinuationFrame(
256 StackFrameIteratorBase* iterator)
257 : JavaScriptFrame(iterator) {}
258
259inline JavaScriptBuiltinContinuationWithCatchFrame::
260 JavaScriptBuiltinContinuationWithCatchFrame(
261 StackFrameIteratorBase* iterator)
262 : JavaScriptBuiltinContinuationFrame(iterator) {}
263
264inline JavaScriptFrameIterator::JavaScriptFrameIterator(
265 Isolate* isolate)
266 : iterator_(isolate) {
267 if (!done()) Advance();
268}
269
270inline JavaScriptFrameIterator::JavaScriptFrameIterator(
271 Isolate* isolate, ThreadLocalTop* top)
272 : iterator_(isolate, top) {
273 if (!done()) Advance();
274}
275
276inline JavaScriptFrame* JavaScriptFrameIterator::frame() const {
277 // TODO(1233797): The frame hierarchy needs to change. It's
278 // problematic that we can't use the safe-cast operator to cast to
279 // the JavaScript frame type, because we may encounter arguments
280 // adaptor frames.
281 StackFrame* frame = iterator_.frame();
282 DCHECK(frame->is_java_script() || frame->is_arguments_adaptor());
283 return static_cast<JavaScriptFrame*>(frame);
284}
285
286inline StandardFrame* StackTraceFrameIterator::frame() const {
287 StackFrame* frame = iterator_.frame();
288 DCHECK(frame->is_java_script() || frame->is_arguments_adaptor() ||
289 frame->is_wasm());
290 return static_cast<StandardFrame*>(frame);
291}
292
293bool StackTraceFrameIterator::is_javascript() const {
294 return frame()->is_java_script();
295}
296
297bool StackTraceFrameIterator::is_wasm() const { return frame()->is_wasm(); }
298
299JavaScriptFrame* StackTraceFrameIterator::javascript_frame() const {
300 return JavaScriptFrame::cast(frame());
301}
302
303inline StackFrame* SafeStackFrameIterator::frame() const {
304 DCHECK(!done());
305 DCHECK(frame_->is_java_script() || frame_->is_exit() ||
306 frame_->is_builtin_exit() || frame_->is_wasm());
307 return frame_;
308}
309
310
311} // namespace internal
312} // namespace v8
313
314#endif // V8_FRAMES_INL_H_
315