frames-inl.h revision 958fae7ec3f466955f8e5b50fa5b8d38b9e91675
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
30namespace v8 {
31namespace internal {
32
33
34inline Address StackHandler::address() const {
35  return reinterpret_cast<Address>(const_cast<StackHandler*>(this));
36}
37
38
39inline StackHandler* StackHandler::next() const {
40  const int offset = StackHandlerConstants::kNextOffset;
41  return FromAddress(Memory::Address_at(address() + offset));
42}
43
44
45inline 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
52inline void StackHandler::Iterate(ObjectVisitor* v, Code* holder) const {
53  v->VisitPointer(context_address());
54  v->VisitPointer(code_address());
55}
56
57
58inline StackHandler* StackHandler::FromAddress(Address address) {
59  return reinterpret_cast<StackHandler*>(address);
60}
61
62
63inline bool StackHandler::is_js_entry() const {
64  return kind() == JS_ENTRY;
65}
66
67
68inline bool StackHandler::is_catch() const {
69  return kind() == CATCH;
70}
71
72
73inline bool StackHandler::is_finally() const {
74  return kind() == FINALLY;
75}
76
77
78inline StackHandler::Kind StackHandler::kind() const {
79  const int offset = StackHandlerConstants::kStateIntOffset;
80  return KindField::decode(Memory::unsigned_at(address() + offset));
81}
82
83
84inline unsigned StackHandler::index() const {
85  const int offset = StackHandlerConstants::kStateIntOffset;
86  return IndexField::decode(Memory::unsigned_at(address() + offset));
87}
88
89
90inline Object** StackHandler::context_address() const {
91  const int offset = StackHandlerConstants::kContextOffset;
92  return reinterpret_cast<Object**>(address() + offset);
93}
94
95
96inline Object** StackHandler::code_address() const {
97  const int offset = StackHandlerConstants::kCodeOffset;
98  return reinterpret_cast<Object**>(address() + offset);
99}
100
101
102inline StackFrame::StackFrame(StackFrameIteratorBase* iterator)
103    : iterator_(iterator), isolate_(iterator_->isolate()) {
104}
105
106
107inline StackHandler* StackFrame::top_handler() const {
108  return iterator_->handler();
109}
110
111
112inline Code* StackFrame::LookupCode() const {
113  return GetContainingCode(isolate(), pc());
114}
115
116
117inline Code* StackFrame::GetContainingCode(Isolate* isolate, Address pc) {
118  return isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code;
119}
120
121
122inline 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
133inline EntryFrame::EntryFrame(StackFrameIteratorBase* iterator)
134    : StackFrame(iterator) {
135}
136
137
138inline EntryConstructFrame::EntryConstructFrame(
139    StackFrameIteratorBase* iterator)
140    : EntryFrame(iterator) {
141}
142
143
144inline ExitFrame::ExitFrame(StackFrameIteratorBase* iterator)
145    : StackFrame(iterator) {
146}
147
148
149inline StandardFrame::StandardFrame(StackFrameIteratorBase* iterator)
150    : StackFrame(iterator) {
151}
152
153
154inline Object* StandardFrame::GetExpression(int index) const {
155  return Memory::Object_at(GetExpressionAddress(index));
156}
157
158
159inline void StandardFrame::SetExpression(int index, Object* value) {
160  Memory::Object_at(GetExpressionAddress(index)) = value;
161}
162
163
164inline Object* StandardFrame::context() const {
165  const int offset = StandardFrameConstants::kContextOffset;
166  return Memory::Object_at(fp() + offset);
167}
168
169
170inline Address StandardFrame::caller_fp() const {
171  return Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset);
172}
173
174
175inline Address StandardFrame::caller_pc() const {
176  return Memory::Address_at(ComputePCAddress(fp()));
177}
178
179
180inline Address StandardFrame::ComputePCAddress(Address fp) {
181  return fp + StandardFrameConstants::kCallerPCOffset;
182}
183
184
185inline Address StandardFrame::ComputeConstantPoolAddress(Address fp) {
186  return fp + StandardFrameConstants::kConstantPoolOffset;
187}
188
189
190inline 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
197inline 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
204inline JavaScriptFrame::JavaScriptFrame(StackFrameIteratorBase* iterator)
205    : StandardFrame(iterator) {
206}
207
208
209Address 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
217Object* JavaScriptFrame::GetParameter(int index) const {
218  return Memory::Object_at(GetParameterSlot(index));
219}
220
221
222inline 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
233inline Object* JavaScriptFrame::GetOperand(int index) const {
234  return Memory::Object_at(GetOperandSlot(index));
235}
236
237
238inline 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
250inline Object* JavaScriptFrame::receiver() const {
251  return GetParameter(-1);
252}
253
254
255inline void JavaScriptFrame::set_receiver(Object* value) {
256  Memory::Object_at(GetParameterSlot(-1)) = value;
257}
258
259
260inline bool JavaScriptFrame::has_adapted_arguments() const {
261  return IsArgumentsAdaptorFrame(caller_fp());
262}
263
264
265inline JSFunction* JavaScriptFrame::function() const {
266  return JSFunction::cast(function_slot_object());
267}
268
269
270inline StubFrame::StubFrame(StackFrameIteratorBase* iterator)
271    : StandardFrame(iterator) {
272}
273
274
275inline OptimizedFrame::OptimizedFrame(StackFrameIteratorBase* iterator)
276    : JavaScriptFrame(iterator) {
277}
278
279
280inline ArgumentsAdaptorFrame::ArgumentsAdaptorFrame(
281    StackFrameIteratorBase* iterator) : JavaScriptFrame(iterator) {
282}
283
284
285inline InternalFrame::InternalFrame(StackFrameIteratorBase* iterator)
286    : StandardFrame(iterator) {
287}
288
289
290inline StubFailureTrampolineFrame::StubFailureTrampolineFrame(
291    StackFrameIteratorBase* iterator) : StandardFrame(iterator) {
292}
293
294
295inline ConstructFrame::ConstructFrame(StackFrameIteratorBase* iterator)
296    : InternalFrame(iterator) {
297}
298
299
300inline JavaScriptFrameIterator::JavaScriptFrameIterator(
301    Isolate* isolate)
302    : iterator_(isolate) {
303  if (!done()) Advance();
304}
305
306
307inline JavaScriptFrameIterator::JavaScriptFrameIterator(
308    Isolate* isolate, ThreadLocalTop* top)
309    : iterator_(isolate, top) {
310  if (!done()) Advance();
311}
312
313
314inline 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
325inline 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