Home | History | Annotate | Download | only in ia32
      1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
      2 // All Rights Reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 // - Redistributions of source code must retain the above copyright notice,
      9 // this list of conditions and the following disclaimer.
     10 //
     11 // - Redistribution in binary form must reproduce the above copyright
     12 // notice, this list of conditions and the following disclaimer in the
     13 // documentation and/or other materials provided with the distribution.
     14 //
     15 // - Neither the name of Sun Microsystems or the names of contributors may
     16 // be used to endorse or promote products derived from this software without
     17 // specific prior written permission.
     18 //
     19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
     20 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     21 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     23 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     24 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     26 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     27 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 
     31 // The original source code covered by the above license above has been
     32 // modified significantly by Google Inc.
     33 // Copyright 2011 the V8 project authors. All rights reserved.
     34 
     35 // A light-weight IA32 Assembler.
     36 
     37 #ifndef V8_IA32_ASSEMBLER_IA32_H_
     38 #define V8_IA32_ASSEMBLER_IA32_H_
     39 
     40 #include "isolate.h"
     41 #include "serialize.h"
     42 
     43 namespace v8 {
     44 namespace internal {
     45 
     46 // CPU Registers.
     47 //
     48 // 1) We would prefer to use an enum, but enum values are assignment-
     49 // compatible with int, which has caused code-generation bugs.
     50 //
     51 // 2) We would prefer to use a class instead of a struct but we don't like
     52 // the register initialization to depend on the particular initialization
     53 // order (which appears to be different on OS X, Linux, and Windows for the
     54 // installed versions of C++ we tried). Using a struct permits C-style
     55 // "initialization". Also, the Register objects cannot be const as this
     56 // forces initialization stubs in MSVC, making us dependent on initialization
     57 // order.
     58 //
     59 // 3) By not using an enum, we are possibly preventing the compiler from
     60 // doing certain constant folds, which may significantly reduce the
     61 // code generated for some assembly instructions (because they boil down
     62 // to a few constants). If this is a problem, we could change the code
     63 // such that we use an enum in optimized mode, and the struct in debug
     64 // mode. This way we get the compile-time error checking in debug mode
     65 // and best performance in optimized code.
     66 //
     67 struct Register {
     68   static const int kMaxNumAllocatableRegisters = 6;
     69   static int NumAllocatableRegisters() {
     70     return kMaxNumAllocatableRegisters;
     71   }
     72   static const int kNumRegisters = 8;
     73 
     74   static inline const char* AllocationIndexToString(int index);
     75 
     76   static inline int ToAllocationIndex(Register reg);
     77 
     78   static inline Register FromAllocationIndex(int index);
     79 
     80   static Register from_code(int code) {
     81     ASSERT(code >= 0);
     82     ASSERT(code < kNumRegisters);
     83     Register r = { code };
     84     return r;
     85   }
     86   bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
     87   bool is(Register reg) const { return code_ == reg.code_; }
     88   // eax, ebx, ecx and edx are byte registers, the rest are not.
     89   bool is_byte_register() const { return code_ <= 3; }
     90   int code() const {
     91     ASSERT(is_valid());
     92     return code_;
     93   }
     94   int bit() const {
     95     ASSERT(is_valid());
     96     return 1 << code_;
     97   }
     98 
     99   // Unfortunately we can't make this private in a struct.
    100   int code_;
    101 };
    102 
    103 const int kRegister_eax_Code = 0;
    104 const int kRegister_ecx_Code = 1;
    105 const int kRegister_edx_Code = 2;
    106 const int kRegister_ebx_Code = 3;
    107 const int kRegister_esp_Code = 4;
    108 const int kRegister_ebp_Code = 5;
    109 const int kRegister_esi_Code = 6;
    110 const int kRegister_edi_Code = 7;
    111 const int kRegister_no_reg_Code = -1;
    112 
    113 const Register eax = { kRegister_eax_Code };
    114 const Register ecx = { kRegister_ecx_Code };
    115 const Register edx = { kRegister_edx_Code };
    116 const Register ebx = { kRegister_ebx_Code };
    117 const Register esp = { kRegister_esp_Code };
    118 const Register ebp = { kRegister_ebp_Code };
    119 const Register esi = { kRegister_esi_Code };
    120 const Register edi = { kRegister_edi_Code };
    121 const Register no_reg = { kRegister_no_reg_Code };
    122 
    123 
    124 inline const char* Register::AllocationIndexToString(int index) {
    125   ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
    126   // This is the mapping of allocation indices to registers.
    127   const char* const kNames[] = { "eax", "ecx", "edx", "ebx", "esi", "edi" };
    128   return kNames[index];
    129 }
    130 
    131 
    132 inline int Register::ToAllocationIndex(Register reg) {
    133   ASSERT(reg.is_valid() && !reg.is(esp) && !reg.is(ebp));
    134   return (reg.code() >= 6) ? reg.code() - 2 : reg.code();
    135 }
    136 
    137 
    138 inline Register Register::FromAllocationIndex(int index)  {
    139   ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
    140   return (index >= 4) ? from_code(index + 2) : from_code(index);
    141 }
    142 
    143 
    144 struct IntelDoubleRegister {
    145   static const int kMaxNumRegisters = 8;
    146   static const int kMaxNumAllocatableRegisters = 7;
    147   static int NumAllocatableRegisters();
    148   static int NumRegisters();
    149   static const char* AllocationIndexToString(int index);
    150 
    151   static int ToAllocationIndex(IntelDoubleRegister reg) {
    152     ASSERT(reg.code() != 0);
    153     return reg.code() - 1;
    154   }
    155 
    156   static IntelDoubleRegister FromAllocationIndex(int index) {
    157     ASSERT(index >= 0 && index < NumAllocatableRegisters());
    158     return from_code(index + 1);
    159   }
    160 
    161   static IntelDoubleRegister from_code(int code) {
    162     IntelDoubleRegister result = { code };
    163     return result;
    164   }
    165 
    166   bool is_valid() const {
    167     return 0 <= code_ && code_ < NumRegisters();
    168   }
    169   int code() const {
    170     ASSERT(is_valid());
    171     return code_;
    172   }
    173 
    174   int code_;
    175 };
    176 
    177 
    178 const IntelDoubleRegister double_register_0 = { 0 };
    179 const IntelDoubleRegister double_register_1 = { 1 };
    180 const IntelDoubleRegister double_register_2 = { 2 };
    181 const IntelDoubleRegister double_register_3 = { 3 };
    182 const IntelDoubleRegister double_register_4 = { 4 };
    183 const IntelDoubleRegister double_register_5 = { 5 };
    184 const IntelDoubleRegister double_register_6 = { 6 };
    185 const IntelDoubleRegister double_register_7 = { 7 };
    186 
    187 
    188 struct XMMRegister : IntelDoubleRegister {
    189   static const int kNumAllocatableRegisters = 7;
    190   static const int kNumRegisters = 8;
    191 
    192   static XMMRegister from_code(int code) {
    193     STATIC_ASSERT(sizeof(XMMRegister) == sizeof(IntelDoubleRegister));
    194     XMMRegister result;
    195     result.code_ = code;
    196     return result;
    197   }
    198 
    199   bool is(XMMRegister reg) const { return code_ == reg.code_; }
    200 
    201   static XMMRegister FromAllocationIndex(int index) {
    202     ASSERT(index >= 0 && index < NumAllocatableRegisters());
    203     return from_code(index + 1);
    204   }
    205 
    206   static const char* AllocationIndexToString(int index) {
    207     ASSERT(index >= 0 && index < kNumAllocatableRegisters);
    208     const char* const names[] = {
    209       "xmm1",
    210       "xmm2",
    211       "xmm3",
    212       "xmm4",
    213       "xmm5",
    214       "xmm6",
    215       "xmm7"
    216     };
    217     return names[index];
    218   }
    219 };
    220 
    221 
    222 #define xmm0 (static_cast<const XMMRegister&>(double_register_0))
    223 #define xmm1 (static_cast<const XMMRegister&>(double_register_1))
    224 #define xmm2 (static_cast<const XMMRegister&>(double_register_2))
    225 #define xmm3 (static_cast<const XMMRegister&>(double_register_3))
    226 #define xmm4 (static_cast<const XMMRegister&>(double_register_4))
    227 #define xmm5 (static_cast<const XMMRegister&>(double_register_5))
    228 #define xmm6 (static_cast<const XMMRegister&>(double_register_6))
    229 #define xmm7 (static_cast<const XMMRegister&>(double_register_7))
    230 
    231 
    232 struct X87Register : IntelDoubleRegister {
    233   static const int kNumAllocatableRegisters = 5;
    234   static const int kNumRegisters = 5;
    235 
    236   bool is(X87Register reg) const {
    237     return code_ == reg.code_;
    238   }
    239 
    240   static const char* AllocationIndexToString(int index) {
    241     ASSERT(index >= 0 && index < kNumAllocatableRegisters);
    242     const char* const names[] = {
    243       "stX_0", "stX_1", "stX_2", "stX_3", "stX_4"
    244     };
    245     return names[index];
    246   }
    247 
    248   static X87Register FromAllocationIndex(int index) {
    249     STATIC_ASSERT(sizeof(X87Register) == sizeof(IntelDoubleRegister));
    250     ASSERT(index >= 0 && index < NumAllocatableRegisters());
    251     X87Register result;
    252     result.code_ = index;
    253     return result;
    254   }
    255 
    256   static int ToAllocationIndex(X87Register reg) {
    257     return reg.code_;
    258   }
    259 };
    260 
    261 #define stX_0 static_cast<const X87Register&>(double_register_0)
    262 #define stX_1 static_cast<const X87Register&>(double_register_1)
    263 #define stX_2 static_cast<const X87Register&>(double_register_2)
    264 #define stX_3 static_cast<const X87Register&>(double_register_3)
    265 #define stX_4 static_cast<const X87Register&>(double_register_4)
    266 
    267 
    268 typedef IntelDoubleRegister DoubleRegister;
    269 
    270 
    271 enum Condition {
    272   // any value < 0 is considered no_condition
    273   no_condition  = -1,
    274 
    275   overflow      =  0,
    276   no_overflow   =  1,
    277   below         =  2,
    278   above_equal   =  3,
    279   equal         =  4,
    280   not_equal     =  5,
    281   below_equal   =  6,
    282   above         =  7,
    283   negative      =  8,
    284   positive      =  9,
    285   parity_even   = 10,
    286   parity_odd    = 11,
    287   less          = 12,
    288   greater_equal = 13,
    289   less_equal    = 14,
    290   greater       = 15,
    291 
    292   // aliases
    293   carry         = below,
    294   not_carry     = above_equal,
    295   zero          = equal,
    296   not_zero      = not_equal,
    297   sign          = negative,
    298   not_sign      = positive
    299 };
    300 
    301 
    302 // Returns the equivalent of !cc.
    303 // Negation of the default no_condition (-1) results in a non-default
    304 // no_condition value (-2). As long as tests for no_condition check
    305 // for condition < 0, this will work as expected.
    306 inline Condition NegateCondition(Condition cc) {
    307   return static_cast<Condition>(cc ^ 1);
    308 }
    309 
    310 
    311 // Corresponds to transposing the operands of a comparison.
    312 inline Condition ReverseCondition(Condition cc) {
    313   switch (cc) {
    314     case below:
    315       return above;
    316     case above:
    317       return below;
    318     case above_equal:
    319       return below_equal;
    320     case below_equal:
    321       return above_equal;
    322     case less:
    323       return greater;
    324     case greater:
    325       return less;
    326     case greater_equal:
    327       return less_equal;
    328     case less_equal:
    329       return greater_equal;
    330     default:
    331       return cc;
    332   };
    333 }
    334 
    335 
    336 // -----------------------------------------------------------------------------
    337 // Machine instruction Immediates
    338 
    339 class Immediate BASE_EMBEDDED {
    340  public:
    341   inline explicit Immediate(int x);
    342   inline explicit Immediate(const ExternalReference& ext);
    343   inline explicit Immediate(Handle<Object> handle);
    344   inline explicit Immediate(Smi* value);
    345   inline explicit Immediate(Address addr);
    346 
    347   static Immediate CodeRelativeOffset(Label* label) {
    348     return Immediate(label);
    349   }
    350 
    351   bool is_zero() const { return x_ == 0 && RelocInfo::IsNone(rmode_); }
    352   bool is_int8() const {
    353     return -128 <= x_ && x_ < 128 && RelocInfo::IsNone(rmode_);
    354   }
    355   bool is_int16() const {
    356     return -32768 <= x_ && x_ < 32768 && RelocInfo::IsNone(rmode_);
    357   }
    358 
    359  private:
    360   inline explicit Immediate(Label* value);
    361 
    362   int x_;
    363   RelocInfo::Mode rmode_;
    364 
    365   friend class Assembler;
    366   friend class MacroAssembler;
    367 };
    368 
    369 
    370 // -----------------------------------------------------------------------------
    371 // Machine instruction Operands
    372 
    373 enum ScaleFactor {
    374   times_1 = 0,
    375   times_2 = 1,
    376   times_4 = 2,
    377   times_8 = 3,
    378   times_int_size = times_4,
    379   times_half_pointer_size = times_2,
    380   times_pointer_size = times_4,
    381   times_twice_pointer_size = times_8
    382 };
    383 
    384 
    385 class Operand BASE_EMBEDDED {
    386  public:
    387   // XMM reg
    388   INLINE(explicit Operand(XMMRegister xmm_reg));
    389 
    390   // [disp/r]
    391   INLINE(explicit Operand(int32_t disp, RelocInfo::Mode rmode));
    392   // disp only must always be relocated
    393 
    394   // [base + disp/r]
    395   explicit Operand(Register base, int32_t disp,
    396                    RelocInfo::Mode rmode = RelocInfo::NONE32);
    397 
    398   // [base + index*scale + disp/r]
    399   explicit Operand(Register base,
    400                    Register index,
    401                    ScaleFactor scale,
    402                    int32_t disp,
    403                    RelocInfo::Mode rmode = RelocInfo::NONE32);
    404 
    405   // [index*scale + disp/r]
    406   explicit Operand(Register index,
    407                    ScaleFactor scale,
    408                    int32_t disp,
    409                    RelocInfo::Mode rmode = RelocInfo::NONE32);
    410 
    411   static Operand StaticVariable(const ExternalReference& ext) {
    412     return Operand(reinterpret_cast<int32_t>(ext.address()),
    413                    RelocInfo::EXTERNAL_REFERENCE);
    414   }
    415 
    416   static Operand StaticArray(Register index,
    417                              ScaleFactor scale,
    418                              const ExternalReference& arr) {
    419     return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()),
    420                    RelocInfo::EXTERNAL_REFERENCE);
    421   }
    422 
    423   static Operand ForCell(Handle<Cell> cell) {
    424     AllowDeferredHandleDereference embedding_raw_address;
    425     return Operand(reinterpret_cast<int32_t>(cell.location()),
    426                    RelocInfo::CELL);
    427   }
    428 
    429   // Returns true if this Operand is a wrapper for the specified register.
    430   bool is_reg(Register reg) const;
    431 
    432   // Returns true if this Operand is a wrapper for one register.
    433   bool is_reg_only() const;
    434 
    435   // Asserts that this Operand is a wrapper for one register and returns the
    436   // register.
    437   Register reg() const;
    438 
    439  private:
    440   // reg
    441   INLINE(explicit Operand(Register reg));
    442 
    443   // Set the ModRM byte without an encoded 'reg' register. The
    444   // register is encoded later as part of the emit_operand operation.
    445   inline void set_modrm(int mod, Register rm);
    446 
    447   inline void set_sib(ScaleFactor scale, Register index, Register base);
    448   inline void set_disp8(int8_t disp);
    449   inline void set_dispr(int32_t disp, RelocInfo::Mode rmode);
    450 
    451   byte buf_[6];
    452   // The number of bytes in buf_.
    453   unsigned int len_;
    454   // Only valid if len_ > 4.
    455   RelocInfo::Mode rmode_;
    456 
    457   friend class Assembler;
    458   friend class MacroAssembler;
    459   friend class LCodeGen;
    460 };
    461 
    462 
    463 // -----------------------------------------------------------------------------
    464 // A Displacement describes the 32bit immediate field of an instruction which
    465 // may be used together with a Label in order to refer to a yet unknown code
    466 // position. Displacements stored in the instruction stream are used to describe
    467 // the instruction and to chain a list of instructions using the same Label.
    468 // A Displacement contains 2 different fields:
    469 //
    470 // next field: position of next displacement in the chain (0 = end of list)
    471 // type field: instruction type
    472 //
    473 // A next value of null (0) indicates the end of a chain (note that there can
    474 // be no displacement at position zero, because there is always at least one
    475 // instruction byte before the displacement).
    476 //
    477 // Displacement _data field layout
    478 //
    479 // |31.....2|1......0|
    480 // [  next  |  type  |
    481 
    482 class Displacement BASE_EMBEDDED {
    483  public:
    484   enum Type {
    485     UNCONDITIONAL_JUMP,
    486     CODE_RELATIVE,
    487     OTHER
    488   };
    489 
    490   int data() const { return data_; }
    491   Type type() const { return TypeField::decode(data_); }
    492   void next(Label* L) const {
    493     int n = NextField::decode(data_);
    494     n > 0 ? L->link_to(n) : L->Unuse();
    495   }
    496   void link_to(Label* L) { init(L, type()); }
    497 
    498   explicit Displacement(int data) { data_ = data; }
    499 
    500   Displacement(Label* L, Type type) { init(L, type); }
    501 
    502   void print() {
    503     PrintF("%s (%x) ", (type() == UNCONDITIONAL_JUMP ? "jmp" : "[other]"),
    504                        NextField::decode(data_));
    505   }
    506 
    507  private:
    508   int data_;
    509 
    510   class TypeField: public BitField<Type, 0, 2> {};
    511   class NextField: public BitField<int,  2, 32-2> {};
    512 
    513   void init(Label* L, Type type);
    514 };
    515 
    516 
    517 
    518 // CpuFeatures keeps track of which features are supported by the target CPU.
    519 // Supported features must be enabled by a CpuFeatureScope before use.
    520 // Example:
    521 //   if (assembler->IsSupported(SSE2)) {
    522 //     CpuFeatureScope fscope(assembler, SSE2);
    523 //     // Generate SSE2 floating point code.
    524 //   } else {
    525 //     // Generate standard x87 floating point code.
    526 //   }
    527 class CpuFeatures : public AllStatic {
    528  public:
    529   // Detect features of the target CPU. Set safe defaults if the serializer
    530   // is enabled (snapshots must be portable).
    531   static void Probe();
    532 
    533   // Check whether a feature is supported by the target CPU.
    534   static bool IsSupported(CpuFeature f) {
    535     ASSERT(initialized_);
    536     if (f == SSE2 && !FLAG_enable_sse2) return false;
    537     if (f == SSE3 && !FLAG_enable_sse3) return false;
    538     if (f == SSE4_1 && !FLAG_enable_sse4_1) return false;
    539     if (f == CMOV && !FLAG_enable_cmov) return false;
    540     if (f == RDTSC && !FLAG_enable_rdtsc) return false;
    541     return (supported_ & (static_cast<uint64_t>(1) << f)) != 0;
    542   }
    543 
    544   static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
    545     ASSERT(initialized_);
    546     return (found_by_runtime_probing_only_ &
    547             (static_cast<uint64_t>(1) << f)) != 0;
    548   }
    549 
    550   static bool IsSafeForSnapshot(CpuFeature f) {
    551     return (IsSupported(f) &&
    552             (!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f)));
    553   }
    554 
    555  private:
    556 #ifdef DEBUG
    557   static bool initialized_;
    558 #endif
    559   static uint64_t supported_;
    560   static uint64_t found_by_runtime_probing_only_;
    561 
    562   friend class ExternalReference;
    563   DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
    564 };
    565 
    566 
    567 class Assembler : public AssemblerBase {
    568  private:
    569   // We check before assembling an instruction that there is sufficient
    570   // space to write an instruction and its relocation information.
    571   // The relocation writer's position must be kGap bytes above the end of
    572   // the generated instructions. This leaves enough space for the
    573   // longest possible ia32 instruction, 15 bytes, and the longest possible
    574   // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
    575   // (There is a 15 byte limit on ia32 instruction length that rules out some
    576   // otherwise valid instructions.)
    577   // This allows for a single, fast space check per instruction.
    578   static const int kGap = 32;
    579 
    580  public:
    581   // Create an assembler. Instructions and relocation information are emitted
    582   // into a buffer, with the instructions starting from the beginning and the
    583   // relocation information starting from the end of the buffer. See CodeDesc
    584   // for a detailed comment on the layout (globals.h).
    585   //
    586   // If the provided buffer is NULL, the assembler allocates and grows its own
    587   // buffer, and buffer_size determines the initial buffer size. The buffer is
    588   // owned by the assembler and deallocated upon destruction of the assembler.
    589   //
    590   // If the provided buffer is not NULL, the assembler uses the provided buffer
    591   // for code generation and assumes its size to be buffer_size. If the buffer
    592   // is too small, a fatal error occurs. No deallocation of the buffer is done
    593   // upon destruction of the assembler.
    594   // TODO(vitalyr): the assembler does not need an isolate.
    595   Assembler(Isolate* isolate, void* buffer, int buffer_size);
    596   virtual ~Assembler() { }
    597 
    598   // GetCode emits any pending (non-emitted) code and fills the descriptor
    599   // desc. GetCode() is idempotent; it returns the same result if no other
    600   // Assembler functions are invoked in between GetCode() calls.
    601   void GetCode(CodeDesc* desc);
    602 
    603   // Read/Modify the code target in the branch/call instruction at pc.
    604   inline static Address target_address_at(Address pc);
    605   inline static void set_target_address_at(Address pc, Address target);
    606 
    607   // Return the code target address at a call site from the return address
    608   // of that call in the instruction stream.
    609   inline static Address target_address_from_return_address(Address pc);
    610 
    611   // This sets the branch destination (which is in the instruction on x86).
    612   // This is for calls and branches within generated code.
    613   inline static void deserialization_set_special_target_at(
    614       Address instruction_payload, Address target) {
    615     set_target_address_at(instruction_payload, target);
    616   }
    617 
    618   // This sets the branch destination (which is in the instruction on x86).
    619   // This is for calls and branches to runtime code.
    620   inline static void set_external_target_at(Address instruction_payload,
    621                                             Address target) {
    622     set_target_address_at(instruction_payload, target);
    623   }
    624 
    625   static const int kSpecialTargetSize = kPointerSize;
    626 
    627   // Distance between the address of the code target in the call instruction
    628   // and the return address
    629   static const int kCallTargetAddressOffset = kPointerSize;
    630   // Distance between start of patched return sequence and the emitted address
    631   // to jump to.
    632   static const int kPatchReturnSequenceAddressOffset = 1;  // JMP imm32.
    633 
    634   // Distance between start of patched debug break slot and the emitted address
    635   // to jump to.
    636   static const int kPatchDebugBreakSlotAddressOffset = 1;  // JMP imm32.
    637 
    638   static const int kCallInstructionLength = 5;
    639   static const int kPatchDebugBreakSlotReturnOffset = kPointerSize;
    640   static const int kJSReturnSequenceLength = 6;
    641 
    642   // The debug break slot must be able to contain a call instruction.
    643   static const int kDebugBreakSlotLength = kCallInstructionLength;
    644 
    645   // One byte opcode for test al, 0xXX.
    646   static const byte kTestAlByte = 0xA8;
    647   // One byte opcode for nop.
    648   static const byte kNopByte = 0x90;
    649 
    650   // One byte opcode for a short unconditional jump.
    651   static const byte kJmpShortOpcode = 0xEB;
    652   // One byte prefix for a short conditional jump.
    653   static const byte kJccShortPrefix = 0x70;
    654   static const byte kJncShortOpcode = kJccShortPrefix | not_carry;
    655   static const byte kJcShortOpcode = kJccShortPrefix | carry;
    656   static const byte kJnzShortOpcode = kJccShortPrefix | not_zero;
    657   static const byte kJzShortOpcode = kJccShortPrefix | zero;
    658 
    659 
    660   // ---------------------------------------------------------------------------
    661   // Code generation
    662   //
    663   // - function names correspond one-to-one to ia32 instruction mnemonics
    664   // - unless specified otherwise, instructions operate on 32bit operands
    665   // - instructions on 8bit (byte) operands/registers have a trailing '_b'
    666   // - instructions on 16bit (word) operands/registers have a trailing '_w'
    667   // - naming conflicts with C++ keywords are resolved via a trailing '_'
    668 
    669   // NOTE ON INTERFACE: Currently, the interface is not very consistent
    670   // in the sense that some operations (e.g. mov()) can be called in more
    671   // the one way to generate the same instruction: The Register argument
    672   // can in some cases be replaced with an Operand(Register) argument.
    673   // This should be cleaned up and made more orthogonal. The questions
    674   // is: should we always use Operands instead of Registers where an
    675   // Operand is possible, or should we have a Register (overloaded) form
    676   // instead? We must be careful to make sure that the selected instruction
    677   // is obvious from the parameters to avoid hard-to-find code generation
    678   // bugs.
    679 
    680   // Insert the smallest number of nop instructions
    681   // possible to align the pc offset to a multiple
    682   // of m. m must be a power of 2.
    683   void Align(int m);
    684   void Nop(int bytes = 1);
    685   // Aligns code to something that's optimal for a jump target for the platform.
    686   void CodeTargetAlign();
    687 
    688   // Stack
    689   void pushad();
    690   void popad();
    691 
    692   void pushfd();
    693   void popfd();
    694 
    695   void push(const Immediate& x);
    696   void push_imm32(int32_t imm32);
    697   void push(Register src);
    698   void push(const Operand& src);
    699 
    700   void pop(Register dst);
    701   void pop(const Operand& dst);
    702 
    703   void enter(const Immediate& size);
    704   void leave();
    705 
    706   // Moves
    707   void mov_b(Register dst, Register src) { mov_b(dst, Operand(src)); }
    708   void mov_b(Register dst, const Operand& src);
    709   void mov_b(Register dst, int8_t imm8) { mov_b(Operand(dst), imm8); }
    710   void mov_b(const Operand& dst, int8_t imm8);
    711   void mov_b(const Operand& dst, Register src);
    712 
    713   void mov_w(Register dst, const Operand& src);
    714   void mov_w(const Operand& dst, Register src);
    715 
    716   void mov(Register dst, int32_t imm32);
    717   void mov(Register dst, const Immediate& x);
    718   void mov(Register dst, Handle<Object> handle);
    719   void mov(Register dst, const Operand& src);
    720   void mov(Register dst, Register src);
    721   void mov(const Operand& dst, const Immediate& x);
    722   void mov(const Operand& dst, Handle<Object> handle);
    723   void mov(const Operand& dst, Register src);
    724 
    725   void movsx_b(Register dst, Register src) { movsx_b(dst, Operand(src)); }
    726   void movsx_b(Register dst, const Operand& src);
    727 
    728   void movsx_w(Register dst, Register src) { movsx_w(dst, Operand(src)); }
    729   void movsx_w(Register dst, const Operand& src);
    730 
    731   void movzx_b(Register dst, Register src) { movzx_b(dst, Operand(src)); }
    732   void movzx_b(Register dst, const Operand& src);
    733 
    734   void movzx_w(Register dst, Register src) { movzx_w(dst, Operand(src)); }
    735   void movzx_w(Register dst, const Operand& src);
    736 
    737   // Conditional moves
    738   void cmov(Condition cc, Register dst, Register src) {
    739     cmov(cc, dst, Operand(src));
    740   }
    741   void cmov(Condition cc, Register dst, const Operand& src);
    742 
    743   // Flag management.
    744   void cld();
    745 
    746   // Repetitive string instructions.
    747   void rep_movs();
    748   void rep_stos();
    749   void stos();
    750 
    751   // Exchange two registers
    752   void xchg(Register dst, Register src);
    753 
    754   // Arithmetics
    755   void adc(Register dst, int32_t imm32);
    756   void adc(Register dst, const Operand& src);
    757 
    758   void add(Register dst, Register src) { add(dst, Operand(src)); }
    759   void add(Register dst, const Operand& src);
    760   void add(const Operand& dst, Register src);
    761   void add(Register dst, const Immediate& imm) { add(Operand(dst), imm); }
    762   void add(const Operand& dst, const Immediate& x);
    763 
    764   void and_(Register dst, int32_t imm32);
    765   void and_(Register dst, const Immediate& x);
    766   void and_(Register dst, Register src) { and_(dst, Operand(src)); }
    767   void and_(Register dst, const Operand& src);
    768   void and_(const Operand& dst, Register src);
    769   void and_(const Operand& dst, const Immediate& x);
    770 
    771   void cmpb(Register reg, int8_t imm8) { cmpb(Operand(reg), imm8); }
    772   void cmpb(const Operand& op, int8_t imm8);
    773   void cmpb(Register reg, const Operand& op);
    774   void cmpb(const Operand& op, Register reg);
    775   void cmpb_al(const Operand& op);
    776   void cmpw_ax(const Operand& op);
    777   void cmpw(const Operand& op, Immediate imm16);
    778   void cmp(Register reg, int32_t imm32);
    779   void cmp(Register reg, Handle<Object> handle);
    780   void cmp(Register reg0, Register reg1) { cmp(reg0, Operand(reg1)); }
    781   void cmp(Register reg, const Operand& op);
    782   void cmp(Register reg, const Immediate& imm) { cmp(Operand(reg), imm); }
    783   void cmp(const Operand& op, const Immediate& imm);
    784   void cmp(const Operand& op, Handle<Object> handle);
    785 
    786   void dec_b(Register dst);
    787   void dec_b(const Operand& dst);
    788 
    789   void dec(Register dst);
    790   void dec(const Operand& dst);
    791 
    792   void cdq();
    793 
    794   void idiv(Register src);
    795 
    796   // Signed multiply instructions.
    797   void imul(Register src);                               // edx:eax = eax * src.
    798   void imul(Register dst, Register src) { imul(dst, Operand(src)); }
    799   void imul(Register dst, const Operand& src);           // dst = dst * src.
    800   void imul(Register dst, Register src, int32_t imm32);  // dst = src * imm32.
    801 
    802   void inc(Register dst);
    803   void inc(const Operand& dst);
    804 
    805   void lea(Register dst, const Operand& src);
    806 
    807   // Unsigned multiply instruction.
    808   void mul(Register src);                                // edx:eax = eax * reg.
    809 
    810   void neg(Register dst);
    811 
    812   void not_(Register dst);
    813 
    814   void or_(Register dst, int32_t imm32);
    815   void or_(Register dst, Register src) { or_(dst, Operand(src)); }
    816   void or_(Register dst, const Operand& src);
    817   void or_(const Operand& dst, Register src);
    818   void or_(Register dst, const Immediate& imm) { or_(Operand(dst), imm); }
    819   void or_(const Operand& dst, const Immediate& x);
    820 
    821   void rcl(Register dst, uint8_t imm8);
    822   void rcr(Register dst, uint8_t imm8);
    823   void ror(Register dst, uint8_t imm8);
    824   void ror_cl(Register dst);
    825 
    826   void sar(Register dst, uint8_t imm8);
    827   void sar_cl(Register dst);
    828 
    829   void sbb(Register dst, const Operand& src);
    830 
    831   void shld(Register dst, Register src) { shld(dst, Operand(src)); }
    832   void shld(Register dst, const Operand& src);
    833 
    834   void shl(Register dst, uint8_t imm8);
    835   void shl_cl(Register dst);
    836 
    837   void shrd(Register dst, Register src) { shrd(dst, Operand(src)); }
    838   void shrd(Register dst, const Operand& src);
    839 
    840   void shr(Register dst, uint8_t imm8);
    841   void shr_cl(Register dst);
    842 
    843   void sub(Register dst, const Immediate& imm) { sub(Operand(dst), imm); }
    844   void sub(const Operand& dst, const Immediate& x);
    845   void sub(Register dst, Register src) { sub(dst, Operand(src)); }
    846   void sub(Register dst, const Operand& src);
    847   void sub(const Operand& dst, Register src);
    848 
    849   void test(Register reg, const Immediate& imm);
    850   void test(Register reg0, Register reg1) { test(reg0, Operand(reg1)); }
    851   void test(Register reg, const Operand& op);
    852   void test_b(Register reg, const Operand& op);
    853   void test(const Operand& op, const Immediate& imm);
    854   void test_b(Register reg, uint8_t imm8) { test_b(Operand(reg), imm8); }
    855   void test_b(const Operand& op, uint8_t imm8);
    856 
    857   void xor_(Register dst, int32_t imm32);
    858   void xor_(Register dst, Register src) { xor_(dst, Operand(src)); }
    859   void xor_(Register dst, const Operand& src);
    860   void xor_(const Operand& dst, Register src);
    861   void xor_(Register dst, const Immediate& imm) { xor_(Operand(dst), imm); }
    862   void xor_(const Operand& dst, const Immediate& x);
    863 
    864   // Bit operations.
    865   void bt(const Operand& dst, Register src);
    866   void bts(Register dst, Register src) { bts(Operand(dst), src); }
    867   void bts(const Operand& dst, Register src);
    868 
    869   // Miscellaneous
    870   void hlt();
    871   void int3();
    872   void nop();
    873   void rdtsc();
    874   void ret(int imm16);
    875 
    876   // Label operations & relative jumps (PPUM Appendix D)
    877   //
    878   // Takes a branch opcode (cc) and a label (L) and generates
    879   // either a backward branch or a forward branch and links it
    880   // to the label fixup chain. Usage:
    881   //
    882   // Label L;    // unbound label
    883   // j(cc, &L);  // forward branch to unbound label
    884   // bind(&L);   // bind label to the current pc
    885   // j(cc, &L);  // backward branch to bound label
    886   // bind(&L);   // illegal: a label may be bound only once
    887   //
    888   // Note: The same Label can be used for forward and backward branches
    889   // but it may be bound only once.
    890 
    891   void bind(Label* L);  // binds an unbound label L to the current code position
    892 
    893   // Calls
    894   void call(Label* L);
    895   void call(byte* entry, RelocInfo::Mode rmode);
    896   int CallSize(const Operand& adr);
    897   void call(Register reg) { call(Operand(reg)); }
    898   void call(const Operand& adr);
    899   int CallSize(Handle<Code> code, RelocInfo::Mode mode);
    900   void call(Handle<Code> code,
    901             RelocInfo::Mode rmode,
    902             TypeFeedbackId id = TypeFeedbackId::None());
    903 
    904   // Jumps
    905   // unconditional jump to L
    906   void jmp(Label* L, Label::Distance distance = Label::kFar);
    907   void jmp(byte* entry, RelocInfo::Mode rmode);
    908   void jmp(Register reg) { jmp(Operand(reg)); }
    909   void jmp(const Operand& adr);
    910   void jmp(Handle<Code> code, RelocInfo::Mode rmode);
    911 
    912   // Conditional jumps
    913   void j(Condition cc,
    914          Label* L,
    915          Label::Distance distance = Label::kFar);
    916   void j(Condition cc, byte* entry, RelocInfo::Mode rmode);
    917   void j(Condition cc, Handle<Code> code);
    918 
    919   // Floating-point operations
    920   void fld(int i);
    921   void fstp(int i);
    922 
    923   void fld1();
    924   void fldz();
    925   void fldpi();
    926   void fldln2();
    927 
    928   void fld_s(const Operand& adr);
    929   void fld_d(const Operand& adr);
    930 
    931   void fstp_s(const Operand& adr);
    932   void fstp_d(const Operand& adr);
    933   void fst_d(const Operand& adr);
    934 
    935   void fild_s(const Operand& adr);
    936   void fild_d(const Operand& adr);
    937 
    938   void fist_s(const Operand& adr);
    939 
    940   void fistp_s(const Operand& adr);
    941   void fistp_d(const Operand& adr);
    942 
    943   // The fisttp instructions require SSE3.
    944   void fisttp_s(const Operand& adr);
    945   void fisttp_d(const Operand& adr);
    946 
    947   void fabs();
    948   void fchs();
    949   void fcos();
    950   void fsin();
    951   void fptan();
    952   void fyl2x();
    953   void f2xm1();
    954   void fscale();
    955   void fninit();
    956 
    957   void fadd(int i);
    958   void fsub(int i);
    959   void fmul(int i);
    960   void fmul_i(int i);
    961   void fdiv(int i);
    962 
    963   void fisub_s(const Operand& adr);
    964 
    965   void faddp(int i = 1);
    966   void fsubp(int i = 1);
    967   void fsubrp(int i = 1);
    968   void fmulp(int i = 1);
    969   void fdivp(int i = 1);
    970   void fprem();
    971   void fprem1();
    972 
    973   void fxch(int i = 1);
    974   void fincstp();
    975   void ffree(int i = 0);
    976 
    977   void ftst();
    978   void fucomp(int i);
    979   void fucompp();
    980   void fucomi(int i);
    981   void fucomip();
    982   void fcompp();
    983   void fnstsw_ax();
    984   void fwait();
    985   void fnclex();
    986 
    987   void frndint();
    988 
    989   void sahf();
    990   void setcc(Condition cc, Register reg);
    991 
    992   void cpuid();
    993 
    994   // SSE2 instructions
    995   void cvttss2si(Register dst, const Operand& src);
    996   void cvttsd2si(Register dst, const Operand& src);
    997   void cvtsd2si(Register dst, XMMRegister src);
    998 
    999   void cvtsi2sd(XMMRegister dst, Register src) { cvtsi2sd(dst, Operand(src)); }
   1000   void cvtsi2sd(XMMRegister dst, const Operand& src);
   1001   void cvtss2sd(XMMRegister dst, XMMRegister src);
   1002   void cvtsd2ss(XMMRegister dst, XMMRegister src);
   1003 
   1004   void addsd(XMMRegister dst, XMMRegister src);
   1005   void addsd(XMMRegister dst, const Operand& src);
   1006   void subsd(XMMRegister dst, XMMRegister src);
   1007   void mulsd(XMMRegister dst, XMMRegister src);
   1008   void mulsd(XMMRegister dst, const Operand& src);
   1009   void divsd(XMMRegister dst, XMMRegister src);
   1010   void xorpd(XMMRegister dst, XMMRegister src);
   1011   void xorps(XMMRegister dst, XMMRegister src);
   1012   void sqrtsd(XMMRegister dst, XMMRegister src);
   1013 
   1014   void andpd(XMMRegister dst, XMMRegister src);
   1015   void orpd(XMMRegister dst, XMMRegister src);
   1016 
   1017   void ucomisd(XMMRegister dst, XMMRegister src);
   1018   void ucomisd(XMMRegister dst, const Operand& src);
   1019 
   1020   enum RoundingMode {
   1021     kRoundToNearest = 0x0,
   1022     kRoundDown      = 0x1,
   1023     kRoundUp        = 0x2,
   1024     kRoundToZero    = 0x3
   1025   };
   1026 
   1027   void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode);
   1028 
   1029   void movmskpd(Register dst, XMMRegister src);
   1030   void movmskps(Register dst, XMMRegister src);
   1031 
   1032   void cmpltsd(XMMRegister dst, XMMRegister src);
   1033   void pcmpeqd(XMMRegister dst, XMMRegister src);
   1034 
   1035   void movaps(XMMRegister dst, XMMRegister src);
   1036 
   1037   void movdqa(XMMRegister dst, const Operand& src);
   1038   void movdqa(const Operand& dst, XMMRegister src);
   1039   void movdqu(XMMRegister dst, const Operand& src);
   1040   void movdqu(const Operand& dst, XMMRegister src);
   1041   void movdq(bool aligned, XMMRegister dst, const Operand& src) {
   1042     if (aligned) {
   1043       movdqa(dst, src);
   1044     } else {
   1045       movdqu(dst, src);
   1046     }
   1047   }
   1048 
   1049   // Use either movsd or movlpd.
   1050   void movdbl(XMMRegister dst, const Operand& src);
   1051   void movdbl(const Operand& dst, XMMRegister src);
   1052 
   1053   void movd(XMMRegister dst, Register src) { movd(dst, Operand(src)); }
   1054   void movd(XMMRegister dst, const Operand& src);
   1055   void movd(Register dst, XMMRegister src) { movd(Operand(dst), src); }
   1056   void movd(const Operand& dst, XMMRegister src);
   1057   void movsd(XMMRegister dst, XMMRegister src);
   1058 
   1059   void movss(XMMRegister dst, const Operand& src);
   1060   void movss(const Operand& dst, XMMRegister src);
   1061   void movss(XMMRegister dst, XMMRegister src);
   1062   void extractps(Register dst, XMMRegister src, byte imm8);
   1063 
   1064   void pand(XMMRegister dst, XMMRegister src);
   1065   void pxor(XMMRegister dst, XMMRegister src);
   1066   void por(XMMRegister dst, XMMRegister src);
   1067   void ptest(XMMRegister dst, XMMRegister src);
   1068 
   1069   void psllq(XMMRegister reg, int8_t shift);
   1070   void psllq(XMMRegister dst, XMMRegister src);
   1071   void psrlq(XMMRegister reg, int8_t shift);
   1072   void psrlq(XMMRegister dst, XMMRegister src);
   1073   void pshufd(XMMRegister dst, XMMRegister src, uint8_t shuffle);
   1074   void pextrd(Register dst, XMMRegister src, int8_t offset) {
   1075     pextrd(Operand(dst), src, offset);
   1076   }
   1077   void pextrd(const Operand& dst, XMMRegister src, int8_t offset);
   1078   void pinsrd(XMMRegister dst, Register src, int8_t offset) {
   1079     pinsrd(dst, Operand(src), offset);
   1080   }
   1081   void pinsrd(XMMRegister dst, const Operand& src, int8_t offset);
   1082 
   1083   // Parallel XMM operations.
   1084   void movntdqa(XMMRegister dst, const Operand& src);
   1085   void movntdq(const Operand& dst, XMMRegister src);
   1086   // Prefetch src position into cache level.
   1087   // Level 1, 2 or 3 specifies CPU cache level. Level 0 specifies a
   1088   // non-temporal
   1089   void prefetch(const Operand& src, int level);
   1090   // TODO(lrn): Need SFENCE for movnt?
   1091 
   1092   // Debugging
   1093   void Print();
   1094 
   1095   // Check the code size generated from label to here.
   1096   int SizeOfCodeGeneratedSince(Label* label) {
   1097     return pc_offset() - label->pos();
   1098   }
   1099 
   1100   // Mark address of the ExitJSFrame code.
   1101   void RecordJSReturn();
   1102 
   1103   // Mark address of a debug break slot.
   1104   void RecordDebugBreakSlot();
   1105 
   1106   // Record a comment relocation entry that can be used by a disassembler.
   1107   // Use --code-comments to enable, or provide "force = true" flag to always
   1108   // write a comment.
   1109   void RecordComment(const char* msg, bool force = false);
   1110 
   1111   // Writes a single byte or word of data in the code stream.  Used for
   1112   // inline tables, e.g., jump-tables.
   1113   void db(uint8_t data);
   1114   void dd(uint32_t data);
   1115 
   1116   // Check if there is less than kGap bytes available in the buffer.
   1117   // If this is the case, we need to grow the buffer before emitting
   1118   // an instruction or relocation information.
   1119   inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; }
   1120 
   1121   // Get the number of bytes available in the buffer.
   1122   inline int available_space() const { return reloc_info_writer.pos() - pc_; }
   1123 
   1124   static bool IsNop(Address addr);
   1125 
   1126   PositionsRecorder* positions_recorder() { return &positions_recorder_; }
   1127 
   1128   int relocation_writer_size() {
   1129     return (buffer_ + buffer_size_) - reloc_info_writer.pos();
   1130   }
   1131 
   1132   // Avoid overflows for displacements etc.
   1133   static const int kMaximalBufferSize = 512*MB;
   1134 
   1135   byte byte_at(int pos)  { return buffer_[pos]; }
   1136   void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
   1137 
   1138  protected:
   1139   void movsd(XMMRegister dst, const Operand& src);
   1140   void movsd(const Operand& dst, XMMRegister src);
   1141 
   1142   void emit_sse_operand(XMMRegister reg, const Operand& adr);
   1143   void emit_sse_operand(XMMRegister dst, XMMRegister src);
   1144   void emit_sse_operand(Register dst, XMMRegister src);
   1145 
   1146   byte* addr_at(int pos) { return buffer_ + pos; }
   1147 
   1148 
   1149  private:
   1150   uint32_t long_at(int pos)  {
   1151     return *reinterpret_cast<uint32_t*>(addr_at(pos));
   1152   }
   1153   void long_at_put(int pos, uint32_t x)  {
   1154     *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
   1155   }
   1156 
   1157   // code emission
   1158   void GrowBuffer();
   1159   inline void emit(uint32_t x);
   1160   inline void emit(Handle<Object> handle);
   1161   inline void emit(uint32_t x,
   1162                    RelocInfo::Mode rmode,
   1163                    TypeFeedbackId id = TypeFeedbackId::None());
   1164   inline void emit(Handle<Code> code,
   1165                    RelocInfo::Mode rmode,
   1166                    TypeFeedbackId id = TypeFeedbackId::None());
   1167   inline void emit(const Immediate& x);
   1168   inline void emit_w(const Immediate& x);
   1169 
   1170   // Emit the code-object-relative offset of the label's position
   1171   inline void emit_code_relative_offset(Label* label);
   1172 
   1173   // instruction generation
   1174   void emit_arith_b(int op1, int op2, Register dst, int imm8);
   1175 
   1176   // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81)
   1177   // with a given destination expression and an immediate operand.  It attempts
   1178   // to use the shortest encoding possible.
   1179   // sel specifies the /n in the modrm byte (see the Intel PRM).
   1180   void emit_arith(int sel, Operand dst, const Immediate& x);
   1181 
   1182   void emit_operand(Register reg, const Operand& adr);
   1183 
   1184   void emit_farith(int b1, int b2, int i);
   1185 
   1186   // labels
   1187   void print(Label* L);
   1188   void bind_to(Label* L, int pos);
   1189 
   1190   // displacements
   1191   inline Displacement disp_at(Label* L);
   1192   inline void disp_at_put(Label* L, Displacement disp);
   1193   inline void emit_disp(Label* L, Displacement::Type type);
   1194   inline void emit_near_disp(Label* L);
   1195 
   1196   // record reloc info for current pc_
   1197   void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
   1198 
   1199   friend class CodePatcher;
   1200   friend class EnsureSpace;
   1201 
   1202   // code generation
   1203   RelocInfoWriter reloc_info_writer;
   1204 
   1205   PositionsRecorder positions_recorder_;
   1206   friend class PositionsRecorder;
   1207 };
   1208 
   1209 
   1210 // Helper class that ensures that there is enough space for generating
   1211 // instructions and relocation information.  The constructor makes
   1212 // sure that there is enough space and (in debug mode) the destructor
   1213 // checks that we did not generate too much.
   1214 class EnsureSpace BASE_EMBEDDED {
   1215  public:
   1216   explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
   1217     if (assembler_->overflow()) assembler_->GrowBuffer();
   1218 #ifdef DEBUG
   1219     space_before_ = assembler_->available_space();
   1220 #endif
   1221   }
   1222 
   1223 #ifdef DEBUG
   1224   ~EnsureSpace() {
   1225     int bytes_generated = space_before_ - assembler_->available_space();
   1226     ASSERT(bytes_generated < assembler_->kGap);
   1227   }
   1228 #endif
   1229 
   1230  private:
   1231   Assembler* assembler_;
   1232 #ifdef DEBUG
   1233   int space_before_;
   1234 #endif
   1235 };
   1236 
   1237 } }  // namespace v8::internal
   1238 
   1239 #endif  // V8_IA32_ASSEMBLER_IA32_H_
   1240