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/frame-constants.h" 9 #include "src/frames.h" 10 #include "src/isolate.h" 11 #include "src/objects-inl.h" 12 #include "src/v8memory.h" 13 14 namespace v8 { 15 namespace internal { 16 address()17inline Address StackHandler::address() const { 18 return reinterpret_cast<Address>(const_cast<StackHandler*>(this)); 19 } 20 21 next()22inline StackHandler* StackHandler::next() const { 23 const int offset = StackHandlerConstants::kNextOffset; 24 return FromAddress(Memory<Address>(address() + offset)); 25 } 26 27 FromAddress(Address address)28inline StackHandler* StackHandler::FromAddress(Address address) { 29 return reinterpret_cast<StackHandler*>(address); 30 } 31 32 StackFrame(StackFrameIteratorBase * iterator)33inline StackFrame::StackFrame(StackFrameIteratorBase* iterator) 34 : iterator_(iterator), isolate_(iterator_->isolate()) { 35 } 36 37 top_handler()38inline StackHandler* StackFrame::top_handler() const { 39 return iterator_->handler(); 40 } 41 42 ResolveReturnAddressLocation(Address * pc_address)43inline Address* StackFrame::ResolveReturnAddressLocation(Address* pc_address) { 44 if (return_address_location_resolver_ == nullptr) { 45 return pc_address; 46 } else { 47 return reinterpret_cast<Address*>( 48 return_address_location_resolver_( 49 reinterpret_cast<uintptr_t>(pc_address))); 50 } 51 } 52 NativeFrame(StackFrameIteratorBase * iterator)53inline NativeFrame::NativeFrame(StackFrameIteratorBase* iterator) 54 : StackFrame(iterator) {} 55 GetCallerStackPointer()56inline Address NativeFrame::GetCallerStackPointer() const { 57 return fp() + CommonFrameConstants::kCallerSPOffset; 58 } 59 EntryFrame(StackFrameIteratorBase * iterator)60inline EntryFrame::EntryFrame(StackFrameIteratorBase* iterator) 61 : StackFrame(iterator) {} 62 ConstructEntryFrame(StackFrameIteratorBase * iterator)63inline ConstructEntryFrame::ConstructEntryFrame( 64 StackFrameIteratorBase* iterator) 65 : EntryFrame(iterator) {} 66 ExitFrame(StackFrameIteratorBase * iterator)67inline ExitFrame::ExitFrame(StackFrameIteratorBase* iterator) 68 : StackFrame(iterator) {} 69 BuiltinExitFrame(StackFrameIteratorBase * iterator)70inline BuiltinExitFrame::BuiltinExitFrame(StackFrameIteratorBase* iterator) 71 : ExitFrame(iterator) {} 72 receiver_slot_object()73inline Object* BuiltinExitFrame::receiver_slot_object() const { 74 // The receiver is the first argument on the frame. 75 // fp[1]: return address. 76 // fp[2]: the last argument (new target). 77 // fp[4]: argc. 78 // fp[2 + argc - 1]: receiver. 79 Object* argc_slot = argc_slot_object(); 80 DCHECK(argc_slot->IsSmi()); 81 int argc = Smi::ToInt(argc_slot); 82 83 const int receiverOffset = 84 BuiltinExitFrameConstants::kNewTargetOffset + (argc - 1) * kPointerSize; 85 return Memory<Object*>(fp() + receiverOffset); 86 } 87 argc_slot_object()88inline Object* BuiltinExitFrame::argc_slot_object() const { 89 return Memory<Object*>(fp() + BuiltinExitFrameConstants::kArgcOffset); 90 } 91 target_slot_object()92inline Object* BuiltinExitFrame::target_slot_object() const { 93 return Memory<Object*>(fp() + BuiltinExitFrameConstants::kTargetOffset); 94 } 95 new_target_slot_object()96inline Object* BuiltinExitFrame::new_target_slot_object() const { 97 return Memory<Object*>(fp() + BuiltinExitFrameConstants::kNewTargetOffset); 98 } 99 StandardFrame(StackFrameIteratorBase * iterator)100inline StandardFrame::StandardFrame(StackFrameIteratorBase* iterator) 101 : StackFrame(iterator) { 102 } 103 104 GetExpression(int index)105inline Object* StandardFrame::GetExpression(int index) const { 106 return Memory<Object*>(GetExpressionAddress(index)); 107 } 108 109 SetExpression(int index,Object * value)110inline void StandardFrame::SetExpression(int index, Object* value) { 111 Memory<Object*>(GetExpressionAddress(index)) = value; 112 } 113 114 caller_fp()115inline Address StandardFrame::caller_fp() const { 116 return Memory<Address>(fp() + StandardFrameConstants::kCallerFPOffset); 117 } 118 119 caller_pc()120inline Address StandardFrame::caller_pc() const { 121 return Memory<Address>(ComputePCAddress(fp())); 122 } 123 124 ComputePCAddress(Address fp)125inline Address StandardFrame::ComputePCAddress(Address fp) { 126 return fp + StandardFrameConstants::kCallerPCOffset; 127 } 128 129 ComputeConstantPoolAddress(Address fp)130inline Address StandardFrame::ComputeConstantPoolAddress(Address fp) { 131 return fp + StandardFrameConstants::kConstantPoolOffset; 132 } 133 134 IsArgumentsAdaptorFrame(Address fp)135inline bool StandardFrame::IsArgumentsAdaptorFrame(Address fp) { 136 intptr_t frame_type = 137 Memory<intptr_t>(fp + TypedFrameConstants::kFrameTypeOffset); 138 return frame_type == StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR); 139 } 140 141 IsConstructFrame(Address fp)142inline bool StandardFrame::IsConstructFrame(Address fp) { 143 intptr_t frame_type = 144 Memory<intptr_t>(fp + TypedFrameConstants::kFrameTypeOffset); 145 return frame_type == StackFrame::TypeToMarker(StackFrame::CONSTRUCT); 146 } 147 JavaScriptFrame(StackFrameIteratorBase * iterator)148inline JavaScriptFrame::JavaScriptFrame(StackFrameIteratorBase* iterator) 149 : StandardFrame(iterator) {} 150 GetParameterSlot(int index)151Address JavaScriptFrame::GetParameterSlot(int index) const { 152 int param_count = ComputeParametersCount(); 153 DCHECK(-1 <= index && 154 (index < param_count || 155 param_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel)); 156 int parameter_offset = (param_count - index - 1) * kPointerSize; 157 return caller_sp() + parameter_offset; 158 } 159 set_receiver(Object * value)160inline void JavaScriptFrame::set_receiver(Object* value) { 161 Memory<Object*>(GetParameterSlot(-1)) = value; 162 } 163 164 has_adapted_arguments()165inline bool JavaScriptFrame::has_adapted_arguments() const { 166 return IsArgumentsAdaptorFrame(caller_fp()); 167 } 168 169 function_slot_object()170inline Object* JavaScriptFrame::function_slot_object() const { 171 const int offset = JavaScriptFrameConstants::kFunctionOffset; 172 return Memory<Object*>(fp() + offset); 173 } 174 StubFrame(StackFrameIteratorBase * iterator)175inline StubFrame::StubFrame(StackFrameIteratorBase* iterator) 176 : StandardFrame(iterator) { 177 } 178 179 OptimizedFrame(StackFrameIteratorBase * iterator)180inline OptimizedFrame::OptimizedFrame(StackFrameIteratorBase* iterator) 181 : JavaScriptFrame(iterator) { 182 } 183 184 InterpretedFrame(StackFrameIteratorBase * iterator)185inline InterpretedFrame::InterpretedFrame(StackFrameIteratorBase* iterator) 186 : JavaScriptFrame(iterator) {} 187 188 ArgumentsAdaptorFrame(StackFrameIteratorBase * iterator)189inline ArgumentsAdaptorFrame::ArgumentsAdaptorFrame( 190 StackFrameIteratorBase* iterator) : JavaScriptFrame(iterator) { 191 } 192 BuiltinFrame(StackFrameIteratorBase * iterator)193inline BuiltinFrame::BuiltinFrame(StackFrameIteratorBase* iterator) 194 : JavaScriptFrame(iterator) {} 195 WasmCompiledFrame(StackFrameIteratorBase * iterator)196inline WasmCompiledFrame::WasmCompiledFrame(StackFrameIteratorBase* iterator) 197 : StandardFrame(iterator) {} 198 WasmInterpreterEntryFrame(StackFrameIteratorBase * iterator)199inline WasmInterpreterEntryFrame::WasmInterpreterEntryFrame( 200 StackFrameIteratorBase* iterator) 201 : StandardFrame(iterator) {} 202 WasmToJsFrame(StackFrameIteratorBase * iterator)203inline WasmToJsFrame::WasmToJsFrame(StackFrameIteratorBase* iterator) 204 : StubFrame(iterator) {} 205 JsToWasmFrame(StackFrameIteratorBase * iterator)206inline JsToWasmFrame::JsToWasmFrame(StackFrameIteratorBase* iterator) 207 : StubFrame(iterator) {} 208 CWasmEntryFrame(StackFrameIteratorBase * iterator)209inline CWasmEntryFrame::CWasmEntryFrame(StackFrameIteratorBase* iterator) 210 : StubFrame(iterator) {} 211 WasmCompileLazyFrame(StackFrameIteratorBase * iterator)212inline WasmCompileLazyFrame::WasmCompileLazyFrame( 213 StackFrameIteratorBase* iterator) 214 : StandardFrame(iterator) {} 215 InternalFrame(StackFrameIteratorBase * iterator)216inline InternalFrame::InternalFrame(StackFrameIteratorBase* iterator) 217 : StandardFrame(iterator) { 218 } 219 ConstructFrame(StackFrameIteratorBase * iterator)220inline ConstructFrame::ConstructFrame(StackFrameIteratorBase* iterator) 221 : InternalFrame(iterator) { 222 } 223 BuiltinContinuationFrame(StackFrameIteratorBase * iterator)224inline BuiltinContinuationFrame::BuiltinContinuationFrame( 225 StackFrameIteratorBase* iterator) 226 : InternalFrame(iterator) {} 227 JavaScriptBuiltinContinuationFrame(StackFrameIteratorBase * iterator)228inline JavaScriptBuiltinContinuationFrame::JavaScriptBuiltinContinuationFrame( 229 StackFrameIteratorBase* iterator) 230 : JavaScriptFrame(iterator) {} 231 232 inline JavaScriptBuiltinContinuationWithCatchFrame:: JavaScriptBuiltinContinuationWithCatchFrame(StackFrameIteratorBase * iterator)233 JavaScriptBuiltinContinuationWithCatchFrame( 234 StackFrameIteratorBase* iterator) 235 : JavaScriptBuiltinContinuationFrame(iterator) {} 236 JavaScriptFrameIterator(Isolate * isolate)237inline JavaScriptFrameIterator::JavaScriptFrameIterator( 238 Isolate* isolate) 239 : iterator_(isolate) { 240 if (!done()) Advance(); 241 } 242 JavaScriptFrameIterator(Isolate * isolate,ThreadLocalTop * top)243inline JavaScriptFrameIterator::JavaScriptFrameIterator( 244 Isolate* isolate, ThreadLocalTop* top) 245 : iterator_(isolate, top) { 246 if (!done()) Advance(); 247 } 248 frame()249inline JavaScriptFrame* JavaScriptFrameIterator::frame() const { 250 // TODO(1233797): The frame hierarchy needs to change. It's 251 // problematic that we can't use the safe-cast operator to cast to 252 // the JavaScript frame type, because we may encounter arguments 253 // adaptor frames. 254 StackFrame* frame = iterator_.frame(); 255 DCHECK(frame->is_java_script() || frame->is_arguments_adaptor()); 256 return static_cast<JavaScriptFrame*>(frame); 257 } 258 frame()259inline StandardFrame* StackTraceFrameIterator::frame() const { 260 StackFrame* frame = iterator_.frame(); 261 DCHECK(frame->is_java_script() || frame->is_arguments_adaptor() || 262 frame->is_wasm()); 263 return static_cast<StandardFrame*>(frame); 264 } 265 is_javascript()266bool StackTraceFrameIterator::is_javascript() const { 267 return frame()->is_java_script(); 268 } 269 is_wasm()270bool StackTraceFrameIterator::is_wasm() const { return frame()->is_wasm(); } 271 javascript_frame()272JavaScriptFrame* StackTraceFrameIterator::javascript_frame() const { 273 return JavaScriptFrame::cast(frame()); 274 } 275 frame()276inline StackFrame* SafeStackFrameIterator::frame() const { 277 DCHECK(!done()); 278 DCHECK(frame_->is_java_script() || frame_->is_exit() || 279 frame_->is_builtin_exit() || frame_->is_wasm()); 280 return frame_; 281 } 282 283 284 } // namespace internal 285 } // namespace v8 286 287 #endif // V8_FRAMES_INL_H_ 288