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/objects-inl.h" 11#include "src/v8memory.h" 12 13#if V8_TARGET_ARCH_IA32 14#include "src/ia32/frames-ia32.h" // NOLINT 15#elif V8_TARGET_ARCH_X64 16#include "src/x64/frames-x64.h" // NOLINT 17#elif V8_TARGET_ARCH_ARM64 18#include "src/arm64/frames-arm64.h" // NOLINT 19#elif V8_TARGET_ARCH_ARM 20#include "src/arm/frames-arm.h" // NOLINT 21#elif V8_TARGET_ARCH_PPC 22#include "src/ppc/frames-ppc.h" // NOLINT 23#elif V8_TARGET_ARCH_MIPS 24#include "src/mips/frames-mips.h" // NOLINT 25#elif V8_TARGET_ARCH_MIPS64 26#include "src/mips64/frames-mips64.h" // NOLINT 27#elif V8_TARGET_ARCH_S390 28#include "src/s390/frames-s390.h" // NOLINT 29#elif V8_TARGET_ARCH_X87 30#include "src/x87/frames-x87.h" // NOLINT 31#else 32#error Unsupported target architecture. 33#endif 34 35namespace v8 { 36namespace internal { 37 38 39inline Address StackHandler::address() const { 40 return reinterpret_cast<Address>(const_cast<StackHandler*>(this)); 41} 42 43 44inline StackHandler* StackHandler::next() const { 45 const int offset = StackHandlerConstants::kNextOffset; 46 return FromAddress(Memory::Address_at(address() + offset)); 47} 48 49 50inline StackHandler* StackHandler::FromAddress(Address address) { 51 return reinterpret_cast<StackHandler*>(address); 52} 53 54 55inline StackFrame::StackFrame(StackFrameIteratorBase* iterator) 56 : iterator_(iterator), isolate_(iterator_->isolate()) { 57} 58 59 60inline StackHandler* StackFrame::top_handler() const { 61 return iterator_->handler(); 62} 63 64 65inline Code* StackFrame::LookupCode() const { 66 // TODO(jgruber): This should really check that pc is within the returned 67 // code's instruction range [instruction_start(), instruction_end()[. 68 return GetContainingCode(isolate(), pc()); 69} 70 71 72inline Code* StackFrame::GetContainingCode(Isolate* isolate, Address pc) { 73 return isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code; 74} 75 76 77inline Address* StackFrame::ResolveReturnAddressLocation(Address* pc_address) { 78 if (return_address_location_resolver_ == NULL) { 79 return pc_address; 80 } else { 81 return reinterpret_cast<Address*>( 82 return_address_location_resolver_( 83 reinterpret_cast<uintptr_t>(pc_address))); 84 } 85} 86 87 88inline EntryFrame::EntryFrame(StackFrameIteratorBase* iterator) 89 : StackFrame(iterator) { 90} 91 92 93inline EntryConstructFrame::EntryConstructFrame( 94 StackFrameIteratorBase* iterator) 95 : EntryFrame(iterator) { 96} 97 98 99inline ExitFrame::ExitFrame(StackFrameIteratorBase* iterator) 100 : StackFrame(iterator) { 101} 102 103inline BuiltinExitFrame::BuiltinExitFrame(StackFrameIteratorBase* iterator) 104 : ExitFrame(iterator) {} 105 106inline Object* BuiltinExitFrame::receiver_slot_object() const { 107 // The receiver is the first argument on the frame. 108 // fp[1]: return address. 109 // fp[2]: the last argument (new target). 110 // fp[4]: argc. 111 // fp[2 + argc - 1]: receiver. 112 Object* argc_slot = argc_slot_object(); 113 DCHECK(argc_slot->IsSmi()); 114 int argc = Smi::cast(argc_slot)->value(); 115 116 const int receiverOffset = 117 BuiltinExitFrameConstants::kNewTargetOffset + (argc - 1) * kPointerSize; 118 return Memory::Object_at(fp() + receiverOffset); 119} 120 121inline Object* BuiltinExitFrame::argc_slot_object() const { 122 return Memory::Object_at(fp() + BuiltinExitFrameConstants::kArgcOffset); 123} 124 125inline Object* BuiltinExitFrame::target_slot_object() const { 126 return Memory::Object_at(fp() + BuiltinExitFrameConstants::kTargetOffset); 127} 128 129inline Object* BuiltinExitFrame::new_target_slot_object() const { 130 return Memory::Object_at(fp() + BuiltinExitFrameConstants::kNewTargetOffset); 131} 132 133inline StandardFrame::StandardFrame(StackFrameIteratorBase* iterator) 134 : StackFrame(iterator) { 135} 136 137 138inline Object* StandardFrame::GetExpression(int index) const { 139 return Memory::Object_at(GetExpressionAddress(index)); 140} 141 142 143inline void StandardFrame::SetExpression(int index, Object* value) { 144 Memory::Object_at(GetExpressionAddress(index)) = value; 145} 146 147 148inline Address StandardFrame::caller_fp() const { 149 return Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset); 150} 151 152 153inline Address StandardFrame::caller_pc() const { 154 return Memory::Address_at(ComputePCAddress(fp())); 155} 156 157 158inline Address StandardFrame::ComputePCAddress(Address fp) { 159 return fp + StandardFrameConstants::kCallerPCOffset; 160} 161 162 163inline Address StandardFrame::ComputeConstantPoolAddress(Address fp) { 164 return fp + StandardFrameConstants::kConstantPoolOffset; 165} 166 167 168inline bool StandardFrame::IsArgumentsAdaptorFrame(Address fp) { 169 Object* frame_type = 170 Memory::Object_at(fp + TypedFrameConstants::kFrameTypeOffset); 171 return frame_type == Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR); 172} 173 174 175inline bool StandardFrame::IsConstructFrame(Address fp) { 176 Object* frame_type = 177 Memory::Object_at(fp + TypedFrameConstants::kFrameTypeOffset); 178 return frame_type == Smi::FromInt(StackFrame::CONSTRUCT); 179} 180 181inline JavaScriptFrame::JavaScriptFrame(StackFrameIteratorBase* iterator) 182 : StandardFrame(iterator) {} 183 184Address JavaScriptFrame::GetParameterSlot(int index) const { 185 int param_count = ComputeParametersCount(); 186 DCHECK(-1 <= index && index < param_count); 187 int parameter_offset = (param_count - index - 1) * kPointerSize; 188 return caller_sp() + parameter_offset; 189} 190 191inline Address JavaScriptFrame::GetOperandSlot(int index) const { 192 Address base = fp() + JavaScriptFrameConstants::kLocal0Offset; 193 DCHECK(IsAddressAligned(base, kPointerSize)); 194 DCHECK_EQ(type(), JAVA_SCRIPT); 195 DCHECK_LT(index, ComputeOperandsCount()); 196 DCHECK_LE(0, index); 197 // Operand stack grows down. 198 return base - index * kPointerSize; 199} 200 201 202inline Object* JavaScriptFrame::GetOperand(int index) const { 203 return Memory::Object_at(GetOperandSlot(index)); 204} 205 206 207inline int JavaScriptFrame::ComputeOperandsCount() const { 208 Address base = fp() + JavaScriptFrameConstants::kLocal0Offset; 209 // Base points to low address of first operand and stack grows down, so add 210 // kPointerSize to get the actual stack size. 211 intptr_t stack_size_in_bytes = (base + kPointerSize) - sp(); 212 DCHECK(IsAligned(stack_size_in_bytes, kPointerSize)); 213 DCHECK(type() == JAVA_SCRIPT); 214 DCHECK(stack_size_in_bytes >= 0); 215 return static_cast<int>(stack_size_in_bytes >> kPointerSizeLog2); 216} 217 218 219inline void JavaScriptFrame::set_receiver(Object* value) { 220 Memory::Object_at(GetParameterSlot(-1)) = value; 221} 222 223 224inline bool JavaScriptFrame::has_adapted_arguments() const { 225 return IsArgumentsAdaptorFrame(caller_fp()); 226} 227 228 229inline Object* JavaScriptFrame::function_slot_object() const { 230 const int offset = JavaScriptFrameConstants::kFunctionOffset; 231 return Memory::Object_at(fp() + offset); 232} 233 234inline StubFrame::StubFrame(StackFrameIteratorBase* iterator) 235 : StandardFrame(iterator) { 236} 237 238 239inline OptimizedFrame::OptimizedFrame(StackFrameIteratorBase* iterator) 240 : JavaScriptFrame(iterator) { 241} 242 243 244inline InterpretedFrame::InterpretedFrame(StackFrameIteratorBase* iterator) 245 : JavaScriptFrame(iterator) {} 246 247 248inline ArgumentsAdaptorFrame::ArgumentsAdaptorFrame( 249 StackFrameIteratorBase* iterator) : JavaScriptFrame(iterator) { 250} 251 252inline BuiltinFrame::BuiltinFrame(StackFrameIteratorBase* iterator) 253 : JavaScriptFrame(iterator) {} 254 255inline WasmFrame::WasmFrame(StackFrameIteratorBase* iterator) 256 : StandardFrame(iterator) {} 257 258inline WasmToJsFrame::WasmToJsFrame(StackFrameIteratorBase* iterator) 259 : StubFrame(iterator) {} 260 261inline JsToWasmFrame::JsToWasmFrame(StackFrameIteratorBase* iterator) 262 : StubFrame(iterator) {} 263 264inline InternalFrame::InternalFrame(StackFrameIteratorBase* iterator) 265 : StandardFrame(iterator) { 266} 267 268 269inline StubFailureTrampolineFrame::StubFailureTrampolineFrame( 270 StackFrameIteratorBase* iterator) : StandardFrame(iterator) { 271} 272 273 274inline ConstructFrame::ConstructFrame(StackFrameIteratorBase* iterator) 275 : InternalFrame(iterator) { 276} 277 278inline JavaScriptFrameIterator::JavaScriptFrameIterator( 279 Isolate* isolate) 280 : iterator_(isolate) { 281 if (!done()) Advance(); 282} 283 284inline JavaScriptFrameIterator::JavaScriptFrameIterator( 285 Isolate* isolate, ThreadLocalTop* top) 286 : iterator_(isolate, top) { 287 if (!done()) Advance(); 288} 289 290inline JavaScriptFrame* JavaScriptFrameIterator::frame() const { 291 // TODO(1233797): The frame hierarchy needs to change. It's 292 // problematic that we can't use the safe-cast operator to cast to 293 // the JavaScript frame type, because we may encounter arguments 294 // adaptor frames. 295 StackFrame* frame = iterator_.frame(); 296 DCHECK(frame->is_java_script() || frame->is_arguments_adaptor()); 297 return static_cast<JavaScriptFrame*>(frame); 298} 299 300inline StandardFrame* StackTraceFrameIterator::frame() const { 301 StackFrame* frame = iterator_.frame(); 302 DCHECK(frame->is_java_script() || frame->is_arguments_adaptor() || 303 frame->is_wasm()); 304 return static_cast<StandardFrame*>(frame); 305} 306 307bool StackTraceFrameIterator::is_javascript() const { 308 return frame()->is_java_script(); 309} 310 311bool StackTraceFrameIterator::is_wasm() const { return frame()->is_wasm(); } 312 313JavaScriptFrame* StackTraceFrameIterator::javascript_frame() const { 314 DCHECK(is_javascript()); 315 return static_cast<JavaScriptFrame*>(frame()); 316} 317 318WasmFrame* StackTraceFrameIterator::wasm_frame() const { 319 DCHECK(is_wasm()); 320 return static_cast<WasmFrame*>(frame()); 321} 322 323inline StackFrame* SafeStackFrameIterator::frame() const { 324 DCHECK(!done()); 325 DCHECK(frame_->is_java_script() || frame_->is_exit() || 326 frame_->is_builtin_exit()); 327 return frame_; 328} 329 330 331} // namespace internal 332} // namespace v8 333 334#endif // V8_FRAMES_INL_H_ 335