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