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.
5 #ifndef V8_FRAMES_INL_H_
6 #define V8_FRAMES_INL_H_
8 #include "src/frames.h"
9 #include "src/isolate.h"
10 #include "src/v8memory.h"
12 #if V8_TARGET_ARCH_IA32
13 #include "src/ia32/frames-ia32.h"
14 #elif V8_TARGET_ARCH_X64
15 #include "src/x64/frames-x64.h"
16 #elif V8_TARGET_ARCH_ARM64
17 #include "src/arm64/frames-arm64.h"
18 #elif V8_TARGET_ARCH_ARM
19 #include "src/arm/frames-arm.h"
20 #elif V8_TARGET_ARCH_MIPS
21 #include "src/mips/frames-mips.h"
22 #elif V8_TARGET_ARCH_X87
23 #include "src/x87/frames-x87.h"
25 #error Unsupported target architecture.
32 inline Address StackHandler::address() const {
33 return reinterpret_cast<Address>(const_cast<StackHandler*>(this));
37 inline StackHandler* StackHandler::next() const {
38 const int offset = StackHandlerConstants::kNextOffset;
39 return FromAddress(Memory::Address_at(address() + offset));
43 inline bool StackHandler::includes(Address address) const {
44 Address start = this->address();
45 Address end = start + StackHandlerConstants::kSize;
46 return start <= address && address <= end;
50 inline void StackHandler::Iterate(ObjectVisitor* v, Code* holder) const {
51 v->VisitPointer(context_address());
52 v->VisitPointer(code_address());
56 inline StackHandler* StackHandler::FromAddress(Address address) {
57 return reinterpret_cast<StackHandler*>(address);
61 inline bool StackHandler::is_js_entry() const {
62 return kind() == JS_ENTRY;
66 inline bool StackHandler::is_catch() const {
67 return kind() == CATCH;
71 inline bool StackHandler::is_finally() const {
72 return kind() == FINALLY;
76 inline StackHandler::Kind StackHandler::kind() const {
77 const int offset = StackHandlerConstants::kStateOffset;
78 return KindField::decode(Memory::unsigned_at(address() + offset));
82 inline unsigned StackHandler::index() const {
83 const int offset = StackHandlerConstants::kStateOffset;
84 return IndexField::decode(Memory::unsigned_at(address() + offset));
88 inline Object** StackHandler::context_address() const {
89 const int offset = StackHandlerConstants::kContextOffset;
90 return reinterpret_cast<Object**>(address() + offset);
94 inline Object** StackHandler::code_address() const {
95 const int offset = StackHandlerConstants::kCodeOffset;
96 return reinterpret_cast<Object**>(address() + offset);
100 inline StackFrame::StackFrame(StackFrameIteratorBase* iterator)
101 : iterator_(iterator), isolate_(iterator_->isolate()) {
105 inline StackHandler* StackFrame::top_handler() const {
106 return iterator_->handler();
110 inline Code* StackFrame::LookupCode() const {
111 return GetContainingCode(isolate(), pc());
115 inline Code* StackFrame::GetContainingCode(Isolate* isolate, Address pc) {
116 return isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code;
120 inline Address* StackFrame::ResolveReturnAddressLocation(Address* pc_address) {
121 if (return_address_location_resolver_ == NULL) {
124 return reinterpret_cast<Address*>(
125 return_address_location_resolver_(
126 reinterpret_cast<uintptr_t>(pc_address)));
131 inline EntryFrame::EntryFrame(StackFrameIteratorBase* iterator)
132 : StackFrame(iterator) {
136 inline EntryConstructFrame::EntryConstructFrame(
137 StackFrameIteratorBase* iterator)
138 : EntryFrame(iterator) {
142 inline ExitFrame::ExitFrame(StackFrameIteratorBase* iterator)
143 : StackFrame(iterator) {
147 inline StandardFrame::StandardFrame(StackFrameIteratorBase* iterator)
148 : StackFrame(iterator) {
152 inline Object* StandardFrame::GetExpression(int index) const {
153 return Memory::Object_at(GetExpressionAddress(index));
157 inline void StandardFrame::SetExpression(int index, Object* value) {
158 Memory::Object_at(GetExpressionAddress(index)) = value;
162 inline Object* StandardFrame::context() const {
163 const int offset = StandardFrameConstants::kContextOffset;
164 return Memory::Object_at(fp() + offset);
168 inline Address StandardFrame::caller_fp() const {
169 return Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset);
173 inline Address StandardFrame::caller_pc() const {
174 return Memory::Address_at(ComputePCAddress(fp()));
178 inline Address StandardFrame::ComputePCAddress(Address fp) {
179 return fp + StandardFrameConstants::kCallerPCOffset;
183 inline Address StandardFrame::ComputeConstantPoolAddress(Address fp) {
184 return fp + StandardFrameConstants::kConstantPoolOffset;
188 inline bool StandardFrame::IsArgumentsAdaptorFrame(Address fp) {
190 Memory::Object_at(fp + StandardFrameConstants::kContextOffset);
191 return marker == Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR);
195 inline bool StandardFrame::IsConstructFrame(Address fp) {
197 Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset);
198 return marker == Smi::FromInt(StackFrame::CONSTRUCT);
202 inline JavaScriptFrame::JavaScriptFrame(StackFrameIteratorBase* iterator)
203 : StandardFrame(iterator) {
207 Address JavaScriptFrame::GetParameterSlot(int index) const {
208 int param_count = ComputeParametersCount();
209 ASSERT(-1 <= index && index < param_count);
210 int parameter_offset = (param_count - index - 1) * kPointerSize;
211 return caller_sp() + parameter_offset;
215 Object* JavaScriptFrame::GetParameter(int index) const {
216 return Memory::Object_at(GetParameterSlot(index));
220 inline Address JavaScriptFrame::GetOperandSlot(int index) const {
221 Address base = fp() + JavaScriptFrameConstants::kLocal0Offset;
222 ASSERT(IsAddressAligned(base, kPointerSize));
223 ASSERT_EQ(type(), JAVA_SCRIPT);
224 ASSERT_LT(index, ComputeOperandsCount());
226 // Operand stack grows down.
227 return base - index * kPointerSize;
231 inline Object* JavaScriptFrame::GetOperand(int index) const {
232 return Memory::Object_at(GetOperandSlot(index));
236 inline int JavaScriptFrame::ComputeOperandsCount() const {
237 Address base = fp() + JavaScriptFrameConstants::kLocal0Offset;
238 // Base points to low address of first operand and stack grows down, so add
239 // kPointerSize to get the actual stack size.
240 intptr_t stack_size_in_bytes = (base + kPointerSize) - sp();
241 ASSERT(IsAligned(stack_size_in_bytes, kPointerSize));
242 ASSERT(type() == JAVA_SCRIPT);
243 ASSERT(stack_size_in_bytes >= 0);
244 return static_cast<int>(stack_size_in_bytes >> kPointerSizeLog2);
248 inline Object* JavaScriptFrame::receiver() const {
249 return GetParameter(-1);
253 inline void JavaScriptFrame::set_receiver(Object* value) {
254 Memory::Object_at(GetParameterSlot(-1)) = value;
258 inline bool JavaScriptFrame::has_adapted_arguments() const {
259 return IsArgumentsAdaptorFrame(caller_fp());
263 inline JSFunction* JavaScriptFrame::function() const {
264 return JSFunction::cast(function_slot_object());
268 inline StubFrame::StubFrame(StackFrameIteratorBase* iterator)
269 : StandardFrame(iterator) {
273 inline OptimizedFrame::OptimizedFrame(StackFrameIteratorBase* iterator)
274 : JavaScriptFrame(iterator) {
278 inline ArgumentsAdaptorFrame::ArgumentsAdaptorFrame(
279 StackFrameIteratorBase* iterator) : JavaScriptFrame(iterator) {
283 inline InternalFrame::InternalFrame(StackFrameIteratorBase* iterator)
284 : StandardFrame(iterator) {
288 inline StubFailureTrampolineFrame::StubFailureTrampolineFrame(
289 StackFrameIteratorBase* iterator) : StandardFrame(iterator) {
293 inline ConstructFrame::ConstructFrame(StackFrameIteratorBase* iterator)
294 : InternalFrame(iterator) {
298 inline JavaScriptFrameIterator::JavaScriptFrameIterator(
300 : iterator_(isolate) {
301 if (!done()) Advance();
305 inline JavaScriptFrameIterator::JavaScriptFrameIterator(
306 Isolate* isolate, ThreadLocalTop* top)
307 : iterator_(isolate, top) {
308 if (!done()) Advance();
312 inline JavaScriptFrame* JavaScriptFrameIterator::frame() const {
313 // TODO(1233797): The frame hierarchy needs to change. It's
314 // problematic that we can't use the safe-cast operator to cast to
315 // the JavaScript frame type, because we may encounter arguments
317 StackFrame* frame = iterator_.frame();
318 ASSERT(frame->is_java_script() || frame->is_arguments_adaptor());
319 return static_cast<JavaScriptFrame*>(frame);
323 inline StackFrame* SafeStackFrameIterator::frame() const {
325 ASSERT(frame_->is_java_script() || frame_->is_exit());
330 } } // namespace v8::internal
332 #endif // V8_FRAMES_INL_H_