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