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_MACRO_ASSEMBLER_H_
      6 #define V8_MACRO_ASSEMBLER_H_
      7 
      8 #include "src/assembler.h"
      9 #include "src/frames.h"
     10 #include "src/heap/heap.h"
     11 
     12 // Helper types to make boolean flag easier to read at call-site.
     13 enum InvokeFlag {
     14   CALL_FUNCTION,
     15   JUMP_FUNCTION
     16 };
     17 
     18 
     19 // Flags used for the AllocateInNewSpace functions.
     20 enum AllocationFlags {
     21   // No special flags.
     22   NO_ALLOCATION_FLAGS = 0,
     23   // The content of the result register already contains the allocation top in
     24   // new space.
     25   RESULT_CONTAINS_TOP = 1 << 0,
     26   // Specify that the requested size of the space to allocate is specified in
     27   // words instead of bytes.
     28   SIZE_IN_WORDS = 1 << 1,
     29   // Align the allocation to a multiple of kDoubleSize
     30   DOUBLE_ALIGNMENT = 1 << 2,
     31   // Directly allocate in old space
     32   PRETENURE = 1 << 3,
     33 };
     34 
     35 #if V8_TARGET_ARCH_IA32
     36 #include "src/ia32/macro-assembler-ia32.h"
     37 #elif V8_TARGET_ARCH_X64
     38 #include "src/x64/macro-assembler-x64.h"
     39 #elif V8_TARGET_ARCH_ARM64
     40 #include "src/arm64/constants-arm64.h"
     41 #include "src/arm64/macro-assembler-arm64.h"
     42 #elif V8_TARGET_ARCH_ARM
     43 #include "src/arm/constants-arm.h"
     44 #include "src/arm/macro-assembler-arm.h"
     45 #elif V8_TARGET_ARCH_PPC
     46 #include "src/ppc/constants-ppc.h"
     47 #include "src/ppc/macro-assembler-ppc.h"
     48 #elif V8_TARGET_ARCH_MIPS
     49 #include "src/mips/constants-mips.h"
     50 #include "src/mips/macro-assembler-mips.h"
     51 #elif V8_TARGET_ARCH_MIPS64
     52 #include "src/mips64/constants-mips64.h"
     53 #include "src/mips64/macro-assembler-mips64.h"
     54 #elif V8_TARGET_ARCH_S390
     55 #include "src/s390/constants-s390.h"
     56 #include "src/s390/macro-assembler-s390.h"
     57 #else
     58 #error Unsupported target architecture.
     59 #endif
     60 
     61 namespace v8 {
     62 namespace internal {
     63 
     64 // Simulators only support C calls with up to kMaxCParameters parameters.
     65 static constexpr int kMaxCParameters = 9;
     66 
     67 class FrameScope {
     68  public:
     69   explicit FrameScope(TurboAssembler* tasm, StackFrame::Type type)
     70       : tasm_(tasm), type_(type), old_has_frame_(tasm->has_frame()) {
     71     tasm->set_has_frame(true);
     72     if (type != StackFrame::MANUAL && type_ != StackFrame::NONE) {
     73       tasm->EnterFrame(type);
     74     }
     75   }
     76 
     77   ~FrameScope() {
     78     if (type_ != StackFrame::MANUAL && type_ != StackFrame::NONE) {
     79       tasm_->LeaveFrame(type_);
     80     }
     81     tasm_->set_has_frame(old_has_frame_);
     82   }
     83 
     84   // Normally we generate the leave-frame code when this object goes
     85   // out of scope.  Sometimes we may need to generate the code somewhere else
     86   // in addition.  Calling this will achieve that, but the object stays in
     87   // scope, the MacroAssembler is still marked as being in a frame scope, and
     88   // the code will be generated again when it goes out of scope.
     89   void GenerateLeaveFrame() {
     90     DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
     91     tasm_->LeaveFrame(type_);
     92   }
     93 
     94  private:
     95   TurboAssembler* tasm_;
     96   StackFrame::Type type_;
     97   bool old_has_frame_;
     98 };
     99 
    100 class FrameAndConstantPoolScope {
    101  public:
    102   FrameAndConstantPoolScope(MacroAssembler* masm, StackFrame::Type type)
    103       : masm_(masm),
    104         type_(type),
    105         old_has_frame_(masm->has_frame()),
    106         old_constant_pool_available_(FLAG_enable_embedded_constant_pool &&
    107                                      masm->is_constant_pool_available()) {
    108     masm->set_has_frame(true);
    109     if (FLAG_enable_embedded_constant_pool) {
    110       masm->set_constant_pool_available(true);
    111     }
    112     if (type_ != StackFrame::MANUAL && type_ != StackFrame::NONE) {
    113       masm->EnterFrame(type, !old_constant_pool_available_);
    114     }
    115   }
    116 
    117   ~FrameAndConstantPoolScope() {
    118     masm_->LeaveFrame(type_);
    119     masm_->set_has_frame(old_has_frame_);
    120     if (FLAG_enable_embedded_constant_pool) {
    121       masm_->set_constant_pool_available(old_constant_pool_available_);
    122     }
    123   }
    124 
    125   // Normally we generate the leave-frame code when this object goes
    126   // out of scope.  Sometimes we may need to generate the code somewhere else
    127   // in addition.  Calling this will achieve that, but the object stays in
    128   // scope, the MacroAssembler is still marked as being in a frame scope, and
    129   // the code will be generated again when it goes out of scope.
    130   void GenerateLeaveFrame() {
    131     DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
    132     masm_->LeaveFrame(type_);
    133   }
    134 
    135  private:
    136   MacroAssembler* masm_;
    137   StackFrame::Type type_;
    138   bool old_has_frame_;
    139   bool old_constant_pool_available_;
    140 
    141   DISALLOW_IMPLICIT_CONSTRUCTORS(FrameAndConstantPoolScope);
    142 };
    143 
    144 // Class for scoping the the unavailability of constant pool access.
    145 class ConstantPoolUnavailableScope {
    146  public:
    147   explicit ConstantPoolUnavailableScope(Assembler* assembler)
    148       : assembler_(assembler),
    149         old_constant_pool_available_(FLAG_enable_embedded_constant_pool &&
    150                                      assembler->is_constant_pool_available()) {
    151     if (FLAG_enable_embedded_constant_pool) {
    152       assembler->set_constant_pool_available(false);
    153     }
    154   }
    155   ~ConstantPoolUnavailableScope() {
    156     if (FLAG_enable_embedded_constant_pool) {
    157       assembler_->set_constant_pool_available(old_constant_pool_available_);
    158     }
    159   }
    160 
    161  private:
    162   Assembler* assembler_;
    163   int old_constant_pool_available_;
    164 
    165   DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolUnavailableScope);
    166 };
    167 
    168 
    169 class AllowExternalCallThatCantCauseGC: public FrameScope {
    170  public:
    171   explicit AllowExternalCallThatCantCauseGC(MacroAssembler* masm)
    172       : FrameScope(masm, StackFrame::NONE) { }
    173 };
    174 
    175 
    176 class NoCurrentFrameScope {
    177  public:
    178   explicit NoCurrentFrameScope(MacroAssembler* masm)
    179       : masm_(masm), saved_(masm->has_frame()) {
    180     masm->set_has_frame(false);
    181   }
    182 
    183   ~NoCurrentFrameScope() {
    184     masm_->set_has_frame(saved_);
    185   }
    186 
    187  private:
    188   MacroAssembler* masm_;
    189   bool saved_;
    190 };
    191 
    192 // Prevent the use of the RootArray during the lifetime of this
    193 // scope object.
    194 class NoRootArrayScope {
    195  public:
    196   explicit NoRootArrayScope(MacroAssembler* masm)
    197       : masm_(masm), old_value_(masm->root_array_available()) {
    198     masm->set_root_array_available(false);
    199   }
    200 
    201   ~NoRootArrayScope() { masm_->set_root_array_available(old_value_); }
    202 
    203  private:
    204   MacroAssembler* masm_;
    205   bool old_value_;
    206 };
    207 
    208 // Wrapper class for passing expected and actual parameter counts as
    209 // either registers or immediate values. Used to make sure that the
    210 // caller provides exactly the expected number of parameters to the
    211 // callee.
    212 class ParameterCount BASE_EMBEDDED {
    213  public:
    214   explicit ParameterCount(Register reg) : reg_(reg), immediate_(0) {}
    215   explicit ParameterCount(uint16_t imm) : reg_(no_reg), immediate_(imm) {}
    216 
    217   bool is_reg() const { return reg_.is_valid(); }
    218   bool is_immediate() const { return !is_reg(); }
    219 
    220   Register reg() const {
    221     DCHECK(is_reg());
    222     return reg_;
    223   }
    224   uint16_t immediate() const {
    225     DCHECK(is_immediate());
    226     return immediate_;
    227   }
    228 
    229  private:
    230   const Register reg_;
    231   const uint16_t immediate_;
    232 
    233   DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterCount);
    234 };
    235 
    236 }  // namespace internal
    237 }  // namespace v8
    238 
    239 #endif  // V8_MACRO_ASSEMBLER_H_
    240