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