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