1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_FRAMES_INL_H_ 29 #define V8_FRAMES_INL_H_ 30 31 #include "frames.h" 32 #include "isolate.h" 33 #include "v8memory.h" 34 35 #if V8_TARGET_ARCH_IA32 36 #include "ia32/frames-ia32.h" 37 #elif V8_TARGET_ARCH_X64 38 #include "x64/frames-x64.h" 39 #elif V8_TARGET_ARCH_ARM 40 #include "arm/frames-arm.h" 41 #elif V8_TARGET_ARCH_MIPS 42 #include "mips/frames-mips.h" 43 #else 44 #error Unsupported target architecture. 45 #endif 46 47 namespace v8 { 48 namespace internal { 49 50 51 inline Address StackHandler::address() const { 52 return reinterpret_cast<Address>(const_cast<StackHandler*>(this)); 53 } 54 55 56 inline StackHandler* StackHandler::next() const { 57 const int offset = StackHandlerConstants::kNextOffset; 58 return FromAddress(Memory::Address_at(address() + offset)); 59 } 60 61 62 inline bool StackHandler::includes(Address address) const { 63 Address start = this->address(); 64 Address end = start + StackHandlerConstants::kSize; 65 return start <= address && address <= end; 66 } 67 68 69 inline void StackHandler::Iterate(ObjectVisitor* v, Code* holder) const { 70 v->VisitPointer(context_address()); 71 v->VisitPointer(code_address()); 72 } 73 74 75 inline StackHandler* StackHandler::FromAddress(Address address) { 76 return reinterpret_cast<StackHandler*>(address); 77 } 78 79 80 inline bool StackHandler::is_js_entry() const { 81 return kind() == JS_ENTRY; 82 } 83 84 85 inline bool StackHandler::is_catch() const { 86 return kind() == CATCH; 87 } 88 89 90 inline bool StackHandler::is_finally() const { 91 return kind() == FINALLY; 92 } 93 94 95 inline StackHandler::Kind StackHandler::kind() const { 96 const int offset = StackHandlerConstants::kStateOffset; 97 return KindField::decode(Memory::unsigned_at(address() + offset)); 98 } 99 100 101 inline unsigned StackHandler::index() const { 102 const int offset = StackHandlerConstants::kStateOffset; 103 return IndexField::decode(Memory::unsigned_at(address() + offset)); 104 } 105 106 107 inline Object** StackHandler::context_address() const { 108 const int offset = StackHandlerConstants::kContextOffset; 109 return reinterpret_cast<Object**>(address() + offset); 110 } 111 112 113 inline Object** StackHandler::code_address() const { 114 const int offset = StackHandlerConstants::kCodeOffset; 115 return reinterpret_cast<Object**>(address() + offset); 116 } 117 118 119 inline StackFrame::StackFrame(StackFrameIteratorBase* iterator) 120 : iterator_(iterator), isolate_(iterator_->isolate()) { 121 } 122 123 124 inline StackHandler* StackFrame::top_handler() const { 125 return iterator_->handler(); 126 } 127 128 129 inline Code* StackFrame::LookupCode() const { 130 return GetContainingCode(isolate(), pc()); 131 } 132 133 134 inline Code* StackFrame::GetContainingCode(Isolate* isolate, Address pc) { 135 return isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code; 136 } 137 138 139 inline Address* StackFrame::ResolveReturnAddressLocation(Address* pc_address) { 140 if (return_address_location_resolver_ == NULL) { 141 return pc_address; 142 } else { 143 return reinterpret_cast<Address*>( 144 return_address_location_resolver_( 145 reinterpret_cast<uintptr_t>(pc_address))); 146 } 147 } 148 149 150 inline EntryFrame::EntryFrame(StackFrameIteratorBase* iterator) 151 : StackFrame(iterator) { 152 } 153 154 155 inline EntryConstructFrame::EntryConstructFrame( 156 StackFrameIteratorBase* iterator) 157 : EntryFrame(iterator) { 158 } 159 160 161 inline ExitFrame::ExitFrame(StackFrameIteratorBase* iterator) 162 : StackFrame(iterator) { 163 } 164 165 166 inline StandardFrame::StandardFrame(StackFrameIteratorBase* iterator) 167 : StackFrame(iterator) { 168 } 169 170 171 inline Object* StandardFrame::GetExpression(int index) const { 172 return Memory::Object_at(GetExpressionAddress(index)); 173 } 174 175 176 inline void StandardFrame::SetExpression(int index, Object* value) { 177 Memory::Object_at(GetExpressionAddress(index)) = value; 178 } 179 180 181 inline Object* StandardFrame::context() const { 182 const int offset = StandardFrameConstants::kContextOffset; 183 return Memory::Object_at(fp() + offset); 184 } 185 186 187 inline Address StandardFrame::caller_fp() const { 188 return Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset); 189 } 190 191 192 inline Address StandardFrame::caller_pc() const { 193 return Memory::Address_at(ComputePCAddress(fp())); 194 } 195 196 197 inline Address StandardFrame::ComputePCAddress(Address fp) { 198 return fp + StandardFrameConstants::kCallerPCOffset; 199 } 200 201 202 inline bool StandardFrame::IsArgumentsAdaptorFrame(Address fp) { 203 Object* marker = 204 Memory::Object_at(fp + StandardFrameConstants::kContextOffset); 205 return marker == Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR); 206 } 207 208 209 inline bool StandardFrame::IsConstructFrame(Address fp) { 210 Object* marker = 211 Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset); 212 return marker == Smi::FromInt(StackFrame::CONSTRUCT); 213 } 214 215 216 inline JavaScriptFrame::JavaScriptFrame(StackFrameIteratorBase* iterator) 217 : StandardFrame(iterator) { 218 } 219 220 221 Address JavaScriptFrame::GetParameterSlot(int index) const { 222 int param_count = ComputeParametersCount(); 223 ASSERT(-1 <= index && index < param_count); 224 int parameter_offset = (param_count - index - 1) * kPointerSize; 225 return caller_sp() + parameter_offset; 226 } 227 228 229 Object* JavaScriptFrame::GetParameter(int index) const { 230 return Memory::Object_at(GetParameterSlot(index)); 231 } 232 233 234 inline Address JavaScriptFrame::GetOperandSlot(int index) const { 235 Address base = fp() + JavaScriptFrameConstants::kLocal0Offset; 236 ASSERT(IsAddressAligned(base, kPointerSize)); 237 ASSERT_EQ(type(), JAVA_SCRIPT); 238 ASSERT_LT(index, ComputeOperandsCount()); 239 ASSERT_LE(0, index); 240 // Operand stack grows down. 241 return base - index * kPointerSize; 242 } 243 244 245 inline Object* JavaScriptFrame::GetOperand(int index) const { 246 return Memory::Object_at(GetOperandSlot(index)); 247 } 248 249 250 inline int JavaScriptFrame::ComputeOperandsCount() const { 251 Address base = fp() + JavaScriptFrameConstants::kLocal0Offset; 252 // Base points to low address of first operand and stack grows down, so add 253 // kPointerSize to get the actual stack size. 254 intptr_t stack_size_in_bytes = (base + kPointerSize) - sp(); 255 ASSERT(IsAligned(stack_size_in_bytes, kPointerSize)); 256 ASSERT(type() == JAVA_SCRIPT); 257 ASSERT(stack_size_in_bytes >= 0); 258 return static_cast<int>(stack_size_in_bytes >> kPointerSizeLog2); 259 } 260 261 262 inline Object* JavaScriptFrame::receiver() const { 263 return GetParameter(-1); 264 } 265 266 267 inline void JavaScriptFrame::set_receiver(Object* value) { 268 Memory::Object_at(GetParameterSlot(-1)) = value; 269 } 270 271 272 inline bool JavaScriptFrame::has_adapted_arguments() const { 273 return IsArgumentsAdaptorFrame(caller_fp()); 274 } 275 276 277 inline JSFunction* JavaScriptFrame::function() const { 278 return JSFunction::cast(function_slot_object()); 279 } 280 281 282 inline StubFrame::StubFrame(StackFrameIteratorBase* iterator) 283 : StandardFrame(iterator) { 284 } 285 286 287 inline OptimizedFrame::OptimizedFrame(StackFrameIteratorBase* iterator) 288 : JavaScriptFrame(iterator) { 289 } 290 291 292 inline ArgumentsAdaptorFrame::ArgumentsAdaptorFrame( 293 StackFrameIteratorBase* iterator) : JavaScriptFrame(iterator) { 294 } 295 296 297 inline InternalFrame::InternalFrame(StackFrameIteratorBase* iterator) 298 : StandardFrame(iterator) { 299 } 300 301 302 inline StubFailureTrampolineFrame::StubFailureTrampolineFrame( 303 StackFrameIteratorBase* iterator) : StandardFrame(iterator) { 304 } 305 306 307 inline ConstructFrame::ConstructFrame(StackFrameIteratorBase* iterator) 308 : InternalFrame(iterator) { 309 } 310 311 312 inline JavaScriptFrameIterator::JavaScriptFrameIterator( 313 Isolate* isolate) 314 : iterator_(isolate) { 315 if (!done()) Advance(); 316 } 317 318 319 inline JavaScriptFrameIterator::JavaScriptFrameIterator( 320 Isolate* isolate, ThreadLocalTop* top) 321 : iterator_(isolate, top) { 322 if (!done()) Advance(); 323 } 324 325 326 inline JavaScriptFrame* JavaScriptFrameIterator::frame() const { 327 // TODO(1233797): The frame hierarchy needs to change. It's 328 // problematic that we can't use the safe-cast operator to cast to 329 // the JavaScript frame type, because we may encounter arguments 330 // adaptor frames. 331 StackFrame* frame = iterator_.frame(); 332 ASSERT(frame->is_java_script() || frame->is_arguments_adaptor()); 333 return static_cast<JavaScriptFrame*>(frame); 334 } 335 336 337 inline StackFrame* SafeStackFrameIterator::frame() const { 338 ASSERT(!done()); 339 ASSERT(frame_->is_java_script() || frame_->is_exit()); 340 return frame_; 341 } 342 343 344 } } // namespace v8::internal 345 346 #endif // V8_FRAMES_INL_H_ 347