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 Object** StackHandler::context_address() const { 102 const int offset = StackHandlerConstants::kContextOffset; 103 return reinterpret_cast<Object**>(address() + offset); 104 } 105 106 107 inline Object** StackHandler::code_address() const { 108 const int offset = StackHandlerConstants::kCodeOffset; 109 return reinterpret_cast<Object**>(address() + offset); 110 } 111 112 113 inline StackFrame::StackFrame(StackFrameIterator* iterator) 114 : iterator_(iterator), isolate_(iterator_->isolate()) { 115 } 116 117 118 inline StackHandler* StackFrame::top_handler() const { 119 return iterator_->handler(); 120 } 121 122 123 inline Code* StackFrame::LookupCode() const { 124 return GetContainingCode(isolate(), pc()); 125 } 126 127 128 inline Code* StackFrame::GetContainingCode(Isolate* isolate, Address pc) { 129 return isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code; 130 } 131 132 133 inline EntryFrame::EntryFrame(StackFrameIterator* iterator) 134 : StackFrame(iterator) { 135 } 136 137 138 inline EntryConstructFrame::EntryConstructFrame(StackFrameIterator* iterator) 139 : EntryFrame(iterator) { 140 } 141 142 143 inline ExitFrame::ExitFrame(StackFrameIterator* iterator) 144 : StackFrame(iterator) { 145 } 146 147 148 inline StandardFrame::StandardFrame(StackFrameIterator* iterator) 149 : StackFrame(iterator) { 150 } 151 152 153 inline Object* StandardFrame::GetExpression(int index) const { 154 return Memory::Object_at(GetExpressionAddress(index)); 155 } 156 157 158 inline void StandardFrame::SetExpression(int index, Object* value) { 159 Memory::Object_at(GetExpressionAddress(index)) = value; 160 } 161 162 163 inline Object* StandardFrame::context() const { 164 const int offset = StandardFrameConstants::kContextOffset; 165 return Memory::Object_at(fp() + offset); 166 } 167 168 169 inline Address StandardFrame::caller_fp() const { 170 return Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset); 171 } 172 173 174 inline Address StandardFrame::caller_pc() const { 175 return Memory::Address_at(ComputePCAddress(fp())); 176 } 177 178 179 inline Address StandardFrame::ComputePCAddress(Address fp) { 180 return fp + StandardFrameConstants::kCallerPCOffset; 181 } 182 183 184 inline bool StandardFrame::IsArgumentsAdaptorFrame(Address fp) { 185 Object* marker = 186 Memory::Object_at(fp + StandardFrameConstants::kContextOffset); 187 return marker == Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR); 188 } 189 190 191 inline bool StandardFrame::IsConstructFrame(Address fp) { 192 Object* marker = 193 Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset); 194 return marker == Smi::FromInt(StackFrame::CONSTRUCT); 195 } 196 197 198 inline JavaScriptFrame::JavaScriptFrame(StackFrameIterator* iterator) 199 : StandardFrame(iterator) { 200 } 201 202 203 Address JavaScriptFrame::GetParameterSlot(int index) const { 204 int param_count = ComputeParametersCount(); 205 ASSERT(-1 <= index && index < param_count); 206 int parameter_offset = (param_count - index - 1) * kPointerSize; 207 return caller_sp() + parameter_offset; 208 } 209 210 211 Object* JavaScriptFrame::GetParameter(int index) const { 212 return Memory::Object_at(GetParameterSlot(index)); 213 } 214 215 216 inline Object* JavaScriptFrame::receiver() const { 217 return GetParameter(-1); 218 } 219 220 221 inline void JavaScriptFrame::set_receiver(Object* value) { 222 Memory::Object_at(GetParameterSlot(-1)) = value; 223 } 224 225 226 inline bool JavaScriptFrame::has_adapted_arguments() const { 227 return IsArgumentsAdaptorFrame(caller_fp()); 228 } 229 230 231 inline Object* JavaScriptFrame::function() const { 232 Object* result = function_slot_object(); 233 ASSERT(result->IsJSFunction()); 234 return result; 235 } 236 237 238 inline OptimizedFrame::OptimizedFrame(StackFrameIterator* iterator) 239 : JavaScriptFrame(iterator) { 240 } 241 242 243 inline ArgumentsAdaptorFrame::ArgumentsAdaptorFrame( 244 StackFrameIterator* iterator) : JavaScriptFrame(iterator) { 245 } 246 247 248 inline InternalFrame::InternalFrame(StackFrameIterator* iterator) 249 : StandardFrame(iterator) { 250 } 251 252 253 inline ConstructFrame::ConstructFrame(StackFrameIterator* iterator) 254 : InternalFrame(iterator) { 255 } 256 257 258 template<typename Iterator> 259 inline JavaScriptFrameIteratorTemp<Iterator>::JavaScriptFrameIteratorTemp( 260 Isolate* isolate) 261 : iterator_(isolate) { 262 if (!done()) Advance(); 263 } 264 265 266 template<typename Iterator> 267 inline JavaScriptFrameIteratorTemp<Iterator>::JavaScriptFrameIteratorTemp( 268 Isolate* isolate, ThreadLocalTop* top) 269 : iterator_(isolate, top) { 270 if (!done()) Advance(); 271 } 272 273 274 template<typename Iterator> 275 inline JavaScriptFrame* JavaScriptFrameIteratorTemp<Iterator>::frame() const { 276 // TODO(1233797): The frame hierarchy needs to change. It's 277 // problematic that we can't use the safe-cast operator to cast to 278 // the JavaScript frame type, because we may encounter arguments 279 // adaptor frames. 280 StackFrame* frame = iterator_.frame(); 281 ASSERT(frame->is_java_script() || frame->is_arguments_adaptor()); 282 return static_cast<JavaScriptFrame*>(frame); 283 } 284 285 286 template<typename Iterator> 287 JavaScriptFrameIteratorTemp<Iterator>::JavaScriptFrameIteratorTemp( 288 Isolate* isolate, StackFrame::Id id) 289 : iterator_(isolate) { 290 AdvanceToId(id); 291 } 292 293 294 template<typename Iterator> 295 void JavaScriptFrameIteratorTemp<Iterator>::Advance() { 296 do { 297 iterator_.Advance(); 298 } while (!iterator_.done() && !iterator_.frame()->is_java_script()); 299 } 300 301 302 template<typename Iterator> 303 void JavaScriptFrameIteratorTemp<Iterator>::AdvanceToArgumentsFrame() { 304 if (!frame()->has_adapted_arguments()) return; 305 iterator_.Advance(); 306 ASSERT(iterator_.frame()->is_arguments_adaptor()); 307 } 308 309 310 template<typename Iterator> 311 void JavaScriptFrameIteratorTemp<Iterator>::AdvanceToId(StackFrame::Id id) { 312 while (!done()) { 313 Advance(); 314 if (frame()->id() == id) return; 315 } 316 } 317 318 319 template<typename Iterator> 320 void JavaScriptFrameIteratorTemp<Iterator>::Reset() { 321 iterator_.Reset(); 322 if (!done()) Advance(); 323 } 324 325 326 } } // namespace v8::internal 327 328 #endif // V8_FRAMES_INL_H_ 329