Home | History | Annotate | Download | only in src
      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