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 return GetContainingCode(isolate(), pc()); 67 } 68 69 70 inline Code* StackFrame::GetContainingCode(Isolate* isolate, Address pc) { 71 return isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code; 72 } 73 74 75 inline Address* StackFrame::ResolveReturnAddressLocation(Address* pc_address) { 76 if (return_address_location_resolver_ == NULL) { 77 return pc_address; 78 } else { 79 return reinterpret_cast<Address*>( 80 return_address_location_resolver_( 81 reinterpret_cast<uintptr_t>(pc_address))); 82 } 83 } 84 85 86 inline EntryFrame::EntryFrame(StackFrameIteratorBase* iterator) 87 : StackFrame(iterator) { 88 } 89 90 91 inline EntryConstructFrame::EntryConstructFrame( 92 StackFrameIteratorBase* iterator) 93 : EntryFrame(iterator) { 94 } 95 96 97 inline ExitFrame::ExitFrame(StackFrameIteratorBase* iterator) 98 : StackFrame(iterator) { 99 } 100 101 102 inline StandardFrame::StandardFrame(StackFrameIteratorBase* iterator) 103 : StackFrame(iterator) { 104 } 105 106 107 inline Object* StandardFrame::GetExpression(int index) const { 108 return Memory::Object_at(GetExpressionAddress(index)); 109 } 110 111 112 inline void StandardFrame::SetExpression(int index, Object* value) { 113 Memory::Object_at(GetExpressionAddress(index)) = value; 114 } 115 116 117 inline Object* StandardFrame::context() const { 118 const int offset = StandardFrameConstants::kContextOffset; 119 Object* maybe_result = Memory::Object_at(fp() + offset); 120 DCHECK(!maybe_result->IsSmi()); 121 return maybe_result; 122 } 123 124 125 inline Address StandardFrame::caller_fp() const { 126 return Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset); 127 } 128 129 130 inline Address StandardFrame::caller_pc() const { 131 return Memory::Address_at(ComputePCAddress(fp())); 132 } 133 134 135 inline Address StandardFrame::ComputePCAddress(Address fp) { 136 return fp + StandardFrameConstants::kCallerPCOffset; 137 } 138 139 140 inline Address StandardFrame::ComputeConstantPoolAddress(Address fp) { 141 return fp + StandardFrameConstants::kConstantPoolOffset; 142 } 143 144 145 inline bool StandardFrame::IsArgumentsAdaptorFrame(Address fp) { 146 Object* frame_type = 147 Memory::Object_at(fp + TypedFrameConstants::kFrameTypeOffset); 148 return frame_type == Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR); 149 } 150 151 152 inline bool StandardFrame::IsConstructFrame(Address fp) { 153 Object* frame_type = 154 Memory::Object_at(fp + TypedFrameConstants::kFrameTypeOffset); 155 return frame_type == Smi::FromInt(StackFrame::CONSTRUCT); 156 } 157 158 inline JavaScriptFrame::JavaScriptFrame(StackFrameIteratorBase* iterator) 159 : StandardFrame(iterator) {} 160 161 Address JavaScriptFrame::GetParameterSlot(int index) const { 162 int param_count = ComputeParametersCount(); 163 DCHECK(-1 <= index && index < param_count); 164 int parameter_offset = (param_count - index - 1) * kPointerSize; 165 return caller_sp() + parameter_offset; 166 } 167 168 169 Object* JavaScriptFrame::GetParameter(int index) const { 170 return Memory::Object_at(GetParameterSlot(index)); 171 } 172 173 174 inline Address JavaScriptFrame::GetOperandSlot(int index) const { 175 Address base = fp() + JavaScriptFrameConstants::kLocal0Offset; 176 DCHECK(IsAddressAligned(base, kPointerSize)); 177 DCHECK_EQ(type(), JAVA_SCRIPT); 178 DCHECK_LT(index, ComputeOperandsCount()); 179 DCHECK_LE(0, index); 180 // Operand stack grows down. 181 return base - index * kPointerSize; 182 } 183 184 185 inline Object* JavaScriptFrame::GetOperand(int index) const { 186 return Memory::Object_at(GetOperandSlot(index)); 187 } 188 189 190 inline int JavaScriptFrame::ComputeOperandsCount() const { 191 Address base = fp() + JavaScriptFrameConstants::kLocal0Offset; 192 // Base points to low address of first operand and stack grows down, so add 193 // kPointerSize to get the actual stack size. 194 intptr_t stack_size_in_bytes = (base + kPointerSize) - sp(); 195 DCHECK(IsAligned(stack_size_in_bytes, kPointerSize)); 196 DCHECK(type() == JAVA_SCRIPT); 197 DCHECK(stack_size_in_bytes >= 0); 198 return static_cast<int>(stack_size_in_bytes >> kPointerSizeLog2); 199 } 200 201 202 inline void JavaScriptFrame::set_receiver(Object* value) { 203 Memory::Object_at(GetParameterSlot(-1)) = value; 204 } 205 206 207 inline bool JavaScriptFrame::has_adapted_arguments() const { 208 return IsArgumentsAdaptorFrame(caller_fp()); 209 } 210 211 212 inline Object* JavaScriptFrame::function_slot_object() const { 213 const int offset = JavaScriptFrameConstants::kFunctionOffset; 214 return Memory::Object_at(fp() + offset); 215 } 216 217 218 inline StubFrame::StubFrame(StackFrameIteratorBase* iterator) 219 : StandardFrame(iterator) { 220 } 221 222 223 inline OptimizedFrame::OptimizedFrame(StackFrameIteratorBase* iterator) 224 : JavaScriptFrame(iterator) { 225 } 226 227 228 inline InterpretedFrame::InterpretedFrame(StackFrameIteratorBase* iterator) 229 : JavaScriptFrame(iterator) {} 230 231 232 inline ArgumentsAdaptorFrame::ArgumentsAdaptorFrame( 233 StackFrameIteratorBase* iterator) : JavaScriptFrame(iterator) { 234 } 235 236 inline BuiltinFrame::BuiltinFrame(StackFrameIteratorBase* iterator) 237 : JavaScriptFrame(iterator) {} 238 239 inline WasmFrame::WasmFrame(StackFrameIteratorBase* iterator) 240 : StandardFrame(iterator) {} 241 242 inline WasmToJsFrame::WasmToJsFrame(StackFrameIteratorBase* iterator) 243 : StubFrame(iterator) {} 244 245 inline JsToWasmFrame::JsToWasmFrame(StackFrameIteratorBase* iterator) 246 : StubFrame(iterator) {} 247 248 inline InternalFrame::InternalFrame(StackFrameIteratorBase* iterator) 249 : StandardFrame(iterator) { 250 } 251 252 253 inline StubFailureTrampolineFrame::StubFailureTrampolineFrame( 254 StackFrameIteratorBase* iterator) : StandardFrame(iterator) { 255 } 256 257 258 inline ConstructFrame::ConstructFrame(StackFrameIteratorBase* iterator) 259 : InternalFrame(iterator) { 260 } 261 262 inline JavaScriptFrameIterator::JavaScriptFrameIterator( 263 Isolate* isolate) 264 : iterator_(isolate) { 265 if (!done()) Advance(); 266 } 267 268 inline JavaScriptFrameIterator::JavaScriptFrameIterator( 269 Isolate* isolate, ThreadLocalTop* top) 270 : iterator_(isolate, top) { 271 if (!done()) Advance(); 272 } 273 274 inline JavaScriptFrame* JavaScriptFrameIterator::frame() const { 275 // TODO(1233797): The frame hierarchy needs to change. It's 276 // problematic that we can't use the safe-cast operator to cast to 277 // the JavaScript frame type, because we may encounter arguments 278 // adaptor frames. 279 StackFrame* frame = iterator_.frame(); 280 DCHECK(frame->is_java_script() || frame->is_arguments_adaptor()); 281 return static_cast<JavaScriptFrame*>(frame); 282 } 283 284 inline StandardFrame* StackTraceFrameIterator::frame() const { 285 StackFrame* frame = iterator_.frame(); 286 DCHECK(frame->is_java_script() || frame->is_arguments_adaptor() || 287 frame->is_wasm()); 288 return static_cast<StandardFrame*>(frame); 289 } 290 291 bool StackTraceFrameIterator::is_javascript() const { 292 return frame()->is_java_script(); 293 } 294 295 bool StackTraceFrameIterator::is_wasm() const { return frame()->is_wasm(); } 296 297 JavaScriptFrame* StackTraceFrameIterator::javascript_frame() const { 298 DCHECK(is_javascript()); 299 return static_cast<JavaScriptFrame*>(frame()); 300 } 301 302 WasmFrame* StackTraceFrameIterator::wasm_frame() const { 303 DCHECK(is_wasm()); 304 return static_cast<WasmFrame*>(frame()); 305 } 306 307 inline StackFrame* SafeStackFrameIterator::frame() const { 308 DCHECK(!done()); 309 DCHECK(frame_->is_java_script() || frame_->is_exit()); 310 return frame_; 311 } 312 313 314 } // namespace internal 315 } // namespace v8 316 317 #endif // V8_FRAMES_INL_H_ 318