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 35 namespace v8 { 36 namespace internal { 37 38 39 inline Address StackHandler::address() const { 40 return reinterpret_cast<Address>(const_cast<StackHandler*>(this)); 41 } 42 43 44 inline StackHandler* StackHandler::next() const { 45 const int offset = StackHandlerConstants::kNextOffset; 46 return FromAddress(Memory::Address_at(address() + offset)); 47 } 48 49 50 inline StackHandler* StackHandler::FromAddress(Address address) { 51 return reinterpret_cast<StackHandler*>(address); 52 } 53 54 55 inline StackFrame::StackFrame(StackFrameIteratorBase* iterator) 56 : iterator_(iterator), isolate_(iterator_->isolate()) { 57 } 58 59 60 inline StackHandler* StackFrame::top_handler() const { 61 return iterator_->handler(); 62 } 63 64 65 inline 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 72 inline Code* StackFrame::GetContainingCode(Isolate* isolate, Address pc) { 73 return isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code; 74 } 75 76 77 inline 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 88 inline EntryFrame::EntryFrame(StackFrameIteratorBase* iterator) 89 : StackFrame(iterator) { 90 } 91 92 93 inline EntryConstructFrame::EntryConstructFrame( 94 StackFrameIteratorBase* iterator) 95 : EntryFrame(iterator) { 96 } 97 98 99 inline ExitFrame::ExitFrame(StackFrameIteratorBase* iterator) 100 : StackFrame(iterator) { 101 } 102 103 inline BuiltinExitFrame::BuiltinExitFrame(StackFrameIteratorBase* iterator) 104 : ExitFrame(iterator) {} 105 106 inline 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 121 inline Object* BuiltinExitFrame::argc_slot_object() const { 122 return Memory::Object_at(fp() + BuiltinExitFrameConstants::kArgcOffset); 123 } 124 125 inline Object* BuiltinExitFrame::target_slot_object() const { 126 return Memory::Object_at(fp() + BuiltinExitFrameConstants::kTargetOffset); 127 } 128 129 inline Object* BuiltinExitFrame::new_target_slot_object() const { 130 return Memory::Object_at(fp() + BuiltinExitFrameConstants::kNewTargetOffset); 131 } 132 133 inline StandardFrame::StandardFrame(StackFrameIteratorBase* iterator) 134 : StackFrame(iterator) { 135 } 136 137 138 inline Object* StandardFrame::GetExpression(int index) const { 139 return Memory::Object_at(GetExpressionAddress(index)); 140 } 141 142 143 inline void StandardFrame::SetExpression(int index, Object* value) { 144 Memory::Object_at(GetExpressionAddress(index)) = value; 145 } 146 147 148 inline Address StandardFrame::caller_fp() const { 149 return Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset); 150 } 151 152 153 inline Address StandardFrame::caller_pc() const { 154 return Memory::Address_at(ComputePCAddress(fp())); 155 } 156 157 158 inline Address StandardFrame::ComputePCAddress(Address fp) { 159 return fp + StandardFrameConstants::kCallerPCOffset; 160 } 161 162 163 inline Address StandardFrame::ComputeConstantPoolAddress(Address fp) { 164 return fp + StandardFrameConstants::kConstantPoolOffset; 165 } 166 167 168 inline bool StandardFrame::IsArgumentsAdaptorFrame(Address fp) { 169 intptr_t frame_type = 170 Memory::intptr_at(fp + TypedFrameConstants::kFrameTypeOffset); 171 return frame_type == StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR); 172 } 173 174 175 inline bool StandardFrame::IsConstructFrame(Address fp) { 176 intptr_t frame_type = 177 Memory::intptr_at(fp + TypedFrameConstants::kFrameTypeOffset); 178 return frame_type == StackFrame::TypeToMarker(StackFrame::CONSTRUCT); 179 } 180 181 inline JavaScriptFrame::JavaScriptFrame(StackFrameIteratorBase* iterator) 182 : StandardFrame(iterator) {} 183 184 Address 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 191 inline 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 202 inline Object* JavaScriptFrame::GetOperand(int index) const { 203 return Memory::Object_at(GetOperandSlot(index)); 204 } 205 206 207 inline 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 219 inline void JavaScriptFrame::set_receiver(Object* value) { 220 Memory::Object_at(GetParameterSlot(-1)) = value; 221 } 222 223 224 inline bool JavaScriptFrame::has_adapted_arguments() const { 225 return IsArgumentsAdaptorFrame(caller_fp()); 226 } 227 228 229 inline Object* JavaScriptFrame::function_slot_object() const { 230 const int offset = JavaScriptFrameConstants::kFunctionOffset; 231 return Memory::Object_at(fp() + offset); 232 } 233 234 inline StubFrame::StubFrame(StackFrameIteratorBase* iterator) 235 : StandardFrame(iterator) { 236 } 237 238 239 inline OptimizedFrame::OptimizedFrame(StackFrameIteratorBase* iterator) 240 : JavaScriptFrame(iterator) { 241 } 242 243 244 inline InterpretedFrame::InterpretedFrame(StackFrameIteratorBase* iterator) 245 : JavaScriptFrame(iterator) {} 246 247 248 inline ArgumentsAdaptorFrame::ArgumentsAdaptorFrame( 249 StackFrameIteratorBase* iterator) : JavaScriptFrame(iterator) { 250 } 251 252 inline BuiltinFrame::BuiltinFrame(StackFrameIteratorBase* iterator) 253 : JavaScriptFrame(iterator) {} 254 255 inline WasmCompiledFrame::WasmCompiledFrame(StackFrameIteratorBase* iterator) 256 : StandardFrame(iterator) {} 257 258 inline WasmInterpreterEntryFrame::WasmInterpreterEntryFrame( 259 StackFrameIteratorBase* iterator) 260 : StandardFrame(iterator) {} 261 262 inline WasmToJsFrame::WasmToJsFrame(StackFrameIteratorBase* iterator) 263 : StubFrame(iterator) {} 264 265 inline JsToWasmFrame::JsToWasmFrame(StackFrameIteratorBase* iterator) 266 : StubFrame(iterator) {} 267 268 inline InternalFrame::InternalFrame(StackFrameIteratorBase* iterator) 269 : StandardFrame(iterator) { 270 } 271 272 273 inline StubFailureTrampolineFrame::StubFailureTrampolineFrame( 274 StackFrameIteratorBase* iterator) : StandardFrame(iterator) { 275 } 276 277 278 inline ConstructFrame::ConstructFrame(StackFrameIteratorBase* iterator) 279 : InternalFrame(iterator) { 280 } 281 282 inline JavaScriptFrameIterator::JavaScriptFrameIterator( 283 Isolate* isolate) 284 : iterator_(isolate) { 285 if (!done()) Advance(); 286 } 287 288 inline JavaScriptFrameIterator::JavaScriptFrameIterator( 289 Isolate* isolate, ThreadLocalTop* top) 290 : iterator_(isolate, top) { 291 if (!done()) Advance(); 292 } 293 294 inline JavaScriptFrame* JavaScriptFrameIterator::frame() const { 295 // TODO(1233797): The frame hierarchy needs to change. It's 296 // problematic that we can't use the safe-cast operator to cast to 297 // the JavaScript frame type, because we may encounter arguments 298 // adaptor frames. 299 StackFrame* frame = iterator_.frame(); 300 DCHECK(frame->is_java_script() || frame->is_arguments_adaptor()); 301 return static_cast<JavaScriptFrame*>(frame); 302 } 303 304 inline StandardFrame* StackTraceFrameIterator::frame() const { 305 StackFrame* frame = iterator_.frame(); 306 DCHECK(frame->is_java_script() || frame->is_arguments_adaptor() || 307 frame->is_wasm()); 308 return static_cast<StandardFrame*>(frame); 309 } 310 311 bool StackTraceFrameIterator::is_javascript() const { 312 return frame()->is_java_script(); 313 } 314 315 bool StackTraceFrameIterator::is_wasm() const { return frame()->is_wasm(); } 316 317 JavaScriptFrame* StackTraceFrameIterator::javascript_frame() const { 318 return JavaScriptFrame::cast(frame()); 319 } 320 321 inline StackFrame* SafeStackFrameIterator::frame() const { 322 DCHECK(!done()); 323 DCHECK(frame_->is_java_script() || frame_->is_exit() || 324 frame_->is_builtin_exit()); 325 return frame_; 326 } 327 328 329 } // namespace internal 330 } // namespace v8 331 332 #endif // V8_FRAMES_INL_H_ 333