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 47namespace v8 { 48namespace internal { 49 50 51inline Address StackHandler::address() const { 52 return reinterpret_cast<Address>(const_cast<StackHandler*>(this)); 53} 54 55 56inline StackHandler* StackHandler::next() const { 57 const int offset = StackHandlerConstants::kNextOffset; 58 return FromAddress(Memory::Address_at(address() + offset)); 59} 60 61 62inline 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 69inline void StackHandler::Iterate(ObjectVisitor* v, Code* holder) const { 70 v->VisitPointer(context_address()); 71 v->VisitPointer(code_address()); 72} 73 74 75inline StackHandler* StackHandler::FromAddress(Address address) { 76 return reinterpret_cast<StackHandler*>(address); 77} 78 79 80inline bool StackHandler::is_js_entry() const { 81 return kind() == JS_ENTRY; 82} 83 84 85inline bool StackHandler::is_catch() const { 86 return kind() == CATCH; 87} 88 89 90inline bool StackHandler::is_finally() const { 91 return kind() == FINALLY; 92} 93 94 95inline StackHandler::Kind StackHandler::kind() const { 96 const int offset = StackHandlerConstants::kStateOffset; 97 return KindField::decode(Memory::unsigned_at(address() + offset)); 98} 99 100 101inline Object** StackHandler::context_address() const { 102 const int offset = StackHandlerConstants::kContextOffset; 103 return reinterpret_cast<Object**>(address() + offset); 104} 105 106 107inline Object** StackHandler::code_address() const { 108 const int offset = StackHandlerConstants::kCodeOffset; 109 return reinterpret_cast<Object**>(address() + offset); 110} 111 112 113inline StackFrame::StackFrame(StackFrameIterator* iterator) 114 : iterator_(iterator), isolate_(iterator_->isolate()) { 115} 116 117 118inline StackHandler* StackFrame::top_handler() const { 119 return iterator_->handler(); 120} 121 122 123inline Code* StackFrame::LookupCode() const { 124 return GetContainingCode(isolate(), pc()); 125} 126 127 128inline Code* StackFrame::GetContainingCode(Isolate* isolate, Address pc) { 129 return isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code; 130} 131 132 133inline EntryFrame::EntryFrame(StackFrameIterator* iterator) 134 : StackFrame(iterator) { 135} 136 137 138inline EntryConstructFrame::EntryConstructFrame(StackFrameIterator* iterator) 139 : EntryFrame(iterator) { 140} 141 142 143inline ExitFrame::ExitFrame(StackFrameIterator* iterator) 144 : StackFrame(iterator) { 145} 146 147 148inline StandardFrame::StandardFrame(StackFrameIterator* iterator) 149 : StackFrame(iterator) { 150} 151 152 153inline Object* StandardFrame::GetExpression(int index) const { 154 return Memory::Object_at(GetExpressionAddress(index)); 155} 156 157 158inline void StandardFrame::SetExpression(int index, Object* value) { 159 Memory::Object_at(GetExpressionAddress(index)) = value; 160} 161 162 163inline Object* StandardFrame::context() const { 164 const int offset = StandardFrameConstants::kContextOffset; 165 return Memory::Object_at(fp() + offset); 166} 167 168 169inline Address StandardFrame::caller_fp() const { 170 return Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset); 171} 172 173 174inline Address StandardFrame::caller_pc() const { 175 return Memory::Address_at(ComputePCAddress(fp())); 176} 177 178 179inline Address StandardFrame::ComputePCAddress(Address fp) { 180 return fp + StandardFrameConstants::kCallerPCOffset; 181} 182 183 184inline 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 191inline 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 198inline JavaScriptFrame::JavaScriptFrame(StackFrameIterator* iterator) 199 : StandardFrame(iterator) { 200} 201 202 203Address 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 211Object* JavaScriptFrame::GetParameter(int index) const { 212 return Memory::Object_at(GetParameterSlot(index)); 213} 214 215 216inline Object* JavaScriptFrame::receiver() const { 217 return GetParameter(-1); 218} 219 220 221inline void JavaScriptFrame::set_receiver(Object* value) { 222 Memory::Object_at(GetParameterSlot(-1)) = value; 223} 224 225 226inline bool JavaScriptFrame::has_adapted_arguments() const { 227 return IsArgumentsAdaptorFrame(caller_fp()); 228} 229 230 231inline Object* JavaScriptFrame::function() const { 232 Object* result = function_slot_object(); 233 ASSERT(result->IsJSFunction()); 234 return result; 235} 236 237 238inline OptimizedFrame::OptimizedFrame(StackFrameIterator* iterator) 239 : JavaScriptFrame(iterator) { 240} 241 242 243inline ArgumentsAdaptorFrame::ArgumentsAdaptorFrame( 244 StackFrameIterator* iterator) : JavaScriptFrame(iterator) { 245} 246 247 248inline InternalFrame::InternalFrame(StackFrameIterator* iterator) 249 : StandardFrame(iterator) { 250} 251 252 253inline ConstructFrame::ConstructFrame(StackFrameIterator* iterator) 254 : InternalFrame(iterator) { 255} 256 257 258template<typename Iterator> 259inline JavaScriptFrameIteratorTemp<Iterator>::JavaScriptFrameIteratorTemp( 260 Isolate* isolate) 261 : iterator_(isolate) { 262 if (!done()) Advance(); 263} 264 265 266template<typename Iterator> 267inline JavaScriptFrameIteratorTemp<Iterator>::JavaScriptFrameIteratorTemp( 268 Isolate* isolate, ThreadLocalTop* top) 269 : iterator_(isolate, top) { 270 if (!done()) Advance(); 271} 272 273 274template<typename Iterator> 275inline 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 286template<typename Iterator> 287JavaScriptFrameIteratorTemp<Iterator>::JavaScriptFrameIteratorTemp( 288 Isolate* isolate, StackFrame::Id id) 289 : iterator_(isolate) { 290 AdvanceToId(id); 291} 292 293 294template<typename Iterator> 295void JavaScriptFrameIteratorTemp<Iterator>::Advance() { 296 do { 297 iterator_.Advance(); 298 } while (!iterator_.done() && !iterator_.frame()->is_java_script()); 299} 300 301 302template<typename Iterator> 303void JavaScriptFrameIteratorTemp<Iterator>::AdvanceToArgumentsFrame() { 304 if (!frame()->has_adapted_arguments()) return; 305 iterator_.Advance(); 306 ASSERT(iterator_.frame()->is_arguments_adaptor()); 307} 308 309 310template<typename Iterator> 311void JavaScriptFrameIteratorTemp<Iterator>::AdvanceToId(StackFrame::Id id) { 312 while (!done()) { 313 Advance(); 314 if (frame()->id() == id) return; 315 } 316} 317 318 319template<typename Iterator> 320void 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