Home | History | Annotate | Download | only in src
      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/frames.h"
      9 #include "src/isolate.h"
     10 #include "src/objects-inl.h"
     11 #include "src/v8memory.h"
     12 
     13 #if V8_TARGET_ARCH_IA32
     14 #include "src/ia32/frames-ia32.h"  // NOLINT
     15 #elif V8_TARGET_ARCH_X64
     16 #include "src/x64/frames-x64.h"  // NOLINT
     17 #elif V8_TARGET_ARCH_ARM64
     18 #include "src/arm64/frames-arm64.h"  // NOLINT
     19 #elif V8_TARGET_ARCH_ARM
     20 #include "src/arm/frames-arm.h"  // NOLINT
     21 #elif V8_TARGET_ARCH_PPC
     22 #include "src/ppc/frames-ppc.h"  // NOLINT
     23 #elif V8_TARGET_ARCH_MIPS
     24 #include "src/mips/frames-mips.h"  // NOLINT
     25 #elif V8_TARGET_ARCH_MIPS64
     26 #include "src/mips64/frames-mips64.h"  // NOLINT
     27 #elif V8_TARGET_ARCH_S390
     28 #include "src/s390/frames-s390.h"  // NOLINT
     29 #elif V8_TARGET_ARCH_X87
     30 #include "src/x87/frames-x87.h"  // NOLINT
     31 #else
     32 #error Unsupported target architecture.
     33 #endif
     34 
     35 namespace v8 {
     36 namespace internal {
     37 
     38 
     39 inline Address StackHandler::address() const {
     40   return reinterpret_cast<Address>(const_cast<StackHandler*>(this));
     41 }
     42 
     43 
     44 inline StackHandler* StackHandler::next() const {
     45   const int offset = StackHandlerConstants::kNextOffset;
     46   return FromAddress(Memory::Address_at(address() + offset));
     47 }
     48 
     49 
     50 inline StackHandler* StackHandler::FromAddress(Address address) {
     51   return reinterpret_cast<StackHandler*>(address);
     52 }
     53 
     54 
     55 inline StackFrame::StackFrame(StackFrameIteratorBase* iterator)
     56     : iterator_(iterator), isolate_(iterator_->isolate()) {
     57 }
     58 
     59 
     60 inline StackHandler* StackFrame::top_handler() const {
     61   return iterator_->handler();
     62 }
     63 
     64 
     65 inline Code* StackFrame::LookupCode() const {
     66   // TODO(jgruber): This should really check that pc is within the returned
     67   // code's instruction range [instruction_start(), instruction_end()[.
     68   return GetContainingCode(isolate(), pc());
     69 }
     70 
     71 
     72 inline Code* StackFrame::GetContainingCode(Isolate* isolate, Address pc) {
     73   return isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code;
     74 }
     75 
     76 
     77 inline Address* StackFrame::ResolveReturnAddressLocation(Address* pc_address) {
     78   if (return_address_location_resolver_ == NULL) {
     79     return pc_address;
     80   } else {
     81     return reinterpret_cast<Address*>(
     82         return_address_location_resolver_(
     83             reinterpret_cast<uintptr_t>(pc_address)));
     84   }
     85 }
     86 
     87 
     88 inline EntryFrame::EntryFrame(StackFrameIteratorBase* iterator)
     89     : StackFrame(iterator) {
     90 }
     91 
     92 
     93 inline EntryConstructFrame::EntryConstructFrame(
     94     StackFrameIteratorBase* iterator)
     95     : EntryFrame(iterator) {
     96 }
     97 
     98 
     99 inline ExitFrame::ExitFrame(StackFrameIteratorBase* iterator)
    100     : StackFrame(iterator) {
    101 }
    102 
    103 inline BuiltinExitFrame::BuiltinExitFrame(StackFrameIteratorBase* iterator)
    104     : ExitFrame(iterator) {}
    105 
    106 inline Object* BuiltinExitFrame::receiver_slot_object() const {
    107   // The receiver is the first argument on the frame.
    108   // fp[1]: return address.
    109   // fp[2]: the last argument (new target).
    110   // fp[4]: argc.
    111   // fp[2 + argc - 1]: receiver.
    112   Object* argc_slot = argc_slot_object();
    113   DCHECK(argc_slot->IsSmi());
    114   int argc = Smi::cast(argc_slot)->value();
    115 
    116   const int receiverOffset =
    117       BuiltinExitFrameConstants::kNewTargetOffset + (argc - 1) * kPointerSize;
    118   return Memory::Object_at(fp() + receiverOffset);
    119 }
    120 
    121 inline Object* BuiltinExitFrame::argc_slot_object() const {
    122   return Memory::Object_at(fp() + BuiltinExitFrameConstants::kArgcOffset);
    123 }
    124 
    125 inline Object* BuiltinExitFrame::target_slot_object() const {
    126   return Memory::Object_at(fp() + BuiltinExitFrameConstants::kTargetOffset);
    127 }
    128 
    129 inline Object* BuiltinExitFrame::new_target_slot_object() const {
    130   return Memory::Object_at(fp() + BuiltinExitFrameConstants::kNewTargetOffset);
    131 }
    132 
    133 inline StandardFrame::StandardFrame(StackFrameIteratorBase* iterator)
    134     : StackFrame(iterator) {
    135 }
    136 
    137 
    138 inline Object* StandardFrame::GetExpression(int index) const {
    139   return Memory::Object_at(GetExpressionAddress(index));
    140 }
    141 
    142 
    143 inline void StandardFrame::SetExpression(int index, Object* value) {
    144   Memory::Object_at(GetExpressionAddress(index)) = value;
    145 }
    146 
    147 
    148 inline Address StandardFrame::caller_fp() const {
    149   return Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset);
    150 }
    151 
    152 
    153 inline Address StandardFrame::caller_pc() const {
    154   return Memory::Address_at(ComputePCAddress(fp()));
    155 }
    156 
    157 
    158 inline Address StandardFrame::ComputePCAddress(Address fp) {
    159   return fp + StandardFrameConstants::kCallerPCOffset;
    160 }
    161 
    162 
    163 inline Address StandardFrame::ComputeConstantPoolAddress(Address fp) {
    164   return fp + StandardFrameConstants::kConstantPoolOffset;
    165 }
    166 
    167 
    168 inline bool StandardFrame::IsArgumentsAdaptorFrame(Address fp) {
    169   intptr_t frame_type =
    170       Memory::intptr_at(fp + TypedFrameConstants::kFrameTypeOffset);
    171   return frame_type == StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR);
    172 }
    173 
    174 
    175 inline bool StandardFrame::IsConstructFrame(Address fp) {
    176   intptr_t frame_type =
    177       Memory::intptr_at(fp + TypedFrameConstants::kFrameTypeOffset);
    178   return frame_type == StackFrame::TypeToMarker(StackFrame::CONSTRUCT);
    179 }
    180 
    181 inline JavaScriptFrame::JavaScriptFrame(StackFrameIteratorBase* iterator)
    182     : StandardFrame(iterator) {}
    183 
    184 Address JavaScriptFrame::GetParameterSlot(int index) const {
    185   int param_count = ComputeParametersCount();
    186   DCHECK(-1 <= index && index < param_count);
    187   int parameter_offset = (param_count - index - 1) * kPointerSize;
    188   return caller_sp() + parameter_offset;
    189 }
    190 
    191 inline Address JavaScriptFrame::GetOperandSlot(int index) const {
    192   Address base = fp() + JavaScriptFrameConstants::kLocal0Offset;
    193   DCHECK(IsAddressAligned(base, kPointerSize));
    194   DCHECK_EQ(type(), JAVA_SCRIPT);
    195   DCHECK_LT(index, ComputeOperandsCount());
    196   DCHECK_LE(0, index);
    197   // Operand stack grows down.
    198   return base - index * kPointerSize;
    199 }
    200 
    201 
    202 inline Object* JavaScriptFrame::GetOperand(int index) const {
    203   return Memory::Object_at(GetOperandSlot(index));
    204 }
    205 
    206 
    207 inline int JavaScriptFrame::ComputeOperandsCount() const {
    208   Address base = fp() + JavaScriptFrameConstants::kLocal0Offset;
    209   // Base points to low address of first operand and stack grows down, so add
    210   // kPointerSize to get the actual stack size.
    211   intptr_t stack_size_in_bytes = (base + kPointerSize) - sp();
    212   DCHECK(IsAligned(stack_size_in_bytes, kPointerSize));
    213   DCHECK(type() == JAVA_SCRIPT);
    214   DCHECK(stack_size_in_bytes >= 0);
    215   return static_cast<int>(stack_size_in_bytes >> kPointerSizeLog2);
    216 }
    217 
    218 
    219 inline void JavaScriptFrame::set_receiver(Object* value) {
    220   Memory::Object_at(GetParameterSlot(-1)) = value;
    221 }
    222 
    223 
    224 inline bool JavaScriptFrame::has_adapted_arguments() const {
    225   return IsArgumentsAdaptorFrame(caller_fp());
    226 }
    227 
    228 
    229 inline Object* JavaScriptFrame::function_slot_object() const {
    230   const int offset = JavaScriptFrameConstants::kFunctionOffset;
    231   return Memory::Object_at(fp() + offset);
    232 }
    233 
    234 inline StubFrame::StubFrame(StackFrameIteratorBase* iterator)
    235     : StandardFrame(iterator) {
    236 }
    237 
    238 
    239 inline OptimizedFrame::OptimizedFrame(StackFrameIteratorBase* iterator)
    240     : JavaScriptFrame(iterator) {
    241 }
    242 
    243 
    244 inline InterpretedFrame::InterpretedFrame(StackFrameIteratorBase* iterator)
    245     : JavaScriptFrame(iterator) {}
    246 
    247 
    248 inline ArgumentsAdaptorFrame::ArgumentsAdaptorFrame(
    249     StackFrameIteratorBase* iterator) : JavaScriptFrame(iterator) {
    250 }
    251 
    252 inline BuiltinFrame::BuiltinFrame(StackFrameIteratorBase* iterator)
    253     : JavaScriptFrame(iterator) {}
    254 
    255 inline WasmCompiledFrame::WasmCompiledFrame(StackFrameIteratorBase* iterator)
    256     : StandardFrame(iterator) {}
    257 
    258 inline WasmInterpreterEntryFrame::WasmInterpreterEntryFrame(
    259     StackFrameIteratorBase* iterator)
    260     : StandardFrame(iterator) {}
    261 
    262 inline WasmToJsFrame::WasmToJsFrame(StackFrameIteratorBase* iterator)
    263     : StubFrame(iterator) {}
    264 
    265 inline JsToWasmFrame::JsToWasmFrame(StackFrameIteratorBase* iterator)
    266     : StubFrame(iterator) {}
    267 
    268 inline InternalFrame::InternalFrame(StackFrameIteratorBase* iterator)
    269     : StandardFrame(iterator) {
    270 }
    271 
    272 
    273 inline StubFailureTrampolineFrame::StubFailureTrampolineFrame(
    274     StackFrameIteratorBase* iterator) : StandardFrame(iterator) {
    275 }
    276 
    277 
    278 inline ConstructFrame::ConstructFrame(StackFrameIteratorBase* iterator)
    279     : InternalFrame(iterator) {
    280 }
    281 
    282 inline JavaScriptFrameIterator::JavaScriptFrameIterator(
    283     Isolate* isolate)
    284     : iterator_(isolate) {
    285   if (!done()) Advance();
    286 }
    287 
    288 inline JavaScriptFrameIterator::JavaScriptFrameIterator(
    289     Isolate* isolate, ThreadLocalTop* top)
    290     : iterator_(isolate, top) {
    291   if (!done()) Advance();
    292 }
    293 
    294 inline JavaScriptFrame* JavaScriptFrameIterator::frame() const {
    295   // TODO(1233797): The frame hierarchy needs to change. It's
    296   // problematic that we can't use the safe-cast operator to cast to
    297   // the JavaScript frame type, because we may encounter arguments
    298   // adaptor frames.
    299   StackFrame* frame = iterator_.frame();
    300   DCHECK(frame->is_java_script() || frame->is_arguments_adaptor());
    301   return static_cast<JavaScriptFrame*>(frame);
    302 }
    303 
    304 inline StandardFrame* StackTraceFrameIterator::frame() const {
    305   StackFrame* frame = iterator_.frame();
    306   DCHECK(frame->is_java_script() || frame->is_arguments_adaptor() ||
    307          frame->is_wasm());
    308   return static_cast<StandardFrame*>(frame);
    309 }
    310 
    311 bool StackTraceFrameIterator::is_javascript() const {
    312   return frame()->is_java_script();
    313 }
    314 
    315 bool StackTraceFrameIterator::is_wasm() const { return frame()->is_wasm(); }
    316 
    317 JavaScriptFrame* StackTraceFrameIterator::javascript_frame() const {
    318   return JavaScriptFrame::cast(frame());
    319 }
    320 
    321 inline StackFrame* SafeStackFrameIterator::frame() const {
    322   DCHECK(!done());
    323   DCHECK(frame_->is_java_script() || frame_->is_exit() ||
    324          frame_->is_builtin_exit());
    325   return frame_;
    326 }
    327 
    328 
    329 }  // namespace internal
    330 }  // namespace v8
    331 
    332 #endif  // V8_FRAMES_INL_H_
    333