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