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