assembler-ia32.h 41.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
// Copyright (c) 1994-2006 Sun Microsystems Inc.
// All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// - Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// - Redistribution in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// - Neither the name of Sun Microsystems or the names of contributors may
// be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// The original source code covered by the above license above has been
// modified significantly by Google Inc.
33
// Copyright 2011 the V8 project authors. All rights reserved.
34 35 36

// A light-weight IA32 Assembler.

37 38
#ifndef V8_IA32_ASSEMBLER_IA32_H_
#define V8_IA32_ASSEMBLER_IA32_H_
39

40
#include "isolate.h"
41 42
#include "serialize.h"

43 44
namespace v8 {
namespace internal {
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67

// CPU Registers.
//
// 1) We would prefer to use an enum, but enum values are assignment-
// compatible with int, which has caused code-generation bugs.
//
// 2) We would prefer to use a class instead of a struct but we don't like
// the register initialization to depend on the particular initialization
// order (which appears to be different on OS X, Linux, and Windows for the
// installed versions of C++ we tried). Using a struct permits C-style
// "initialization". Also, the Register objects cannot be const as this
// forces initialization stubs in MSVC, making us dependent on initialization
// order.
//
// 3) By not using an enum, we are possibly preventing the compiler from
// doing certain constant folds, which may significantly reduce the
// code generated for some assembly instructions (because they boil down
// to a few constants). If this is a problem, we could change the code
// such that we use an enum in optimized mode, and the struct in debug
// mode. This way we get the compile-time error checking in debug mode
// and best performance in optimized code.
//
struct Register {
68 69 70 71
  static const int kMaxNumAllocatableRegisters = 6;
  static int NumAllocatableRegisters() {
    return kMaxNumAllocatableRegisters;
  }
72 73
  static const int kNumRegisters = 8;

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 82
    ASSERT(code >= 0);
    ASSERT(code < kNumRegisters);
83 84 85 86
    Register r = { code };
    return r;
  }
  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 90
  bool is_byte_register() const { return code_ <= 3; }
  int code() const {
91 92 93
    ASSERT(is_valid());
    return code_;
  }
94
  int bit() const {
95 96 97 98
    ASSERT(is_valid());
    return 1 << code_;
  }

99
  // Unfortunately we can't make this private in a struct.
100 101 102
  int code_;
};

103 104 105 106 107 108 109 110 111
const int kRegister_eax_Code = 0;
const int kRegister_ecx_Code = 1;
const int kRegister_edx_Code = 2;
const int kRegister_ebx_Code = 3;
const int kRegister_esp_Code = 4;
const int kRegister_ebp_Code = 5;
const int kRegister_esi_Code = 6;
const int kRegister_edi_Code = 7;
const int kRegister_no_reg_Code = -1;
112

113 114 115 116 117 118 119 120 121
const Register eax = { kRegister_eax_Code };
const Register ecx = { kRegister_ecx_Code };
const Register edx = { kRegister_edx_Code };
const Register ebx = { kRegister_ebx_Code };
const Register esp = { kRegister_esp_Code };
const Register ebp = { kRegister_ebp_Code };
const Register esi = { kRegister_esi_Code };
const Register edi = { kRegister_edi_Code };
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 127 128 129 130 131 132 133 134 135 136 137 138
  // This is the mapping of allocation indices to registers.
  const char* const kNames[] = { "eax", "ecx", "edx", "ebx", "esi", "edi" };
  return kNames[index];
}


inline int Register::ToAllocationIndex(Register reg) {
  ASSERT(reg.is_valid() && !reg.is(esp) && !reg.is(ebp));
  return (reg.code() >= 6) ? reg.code() - 2 : reg.code();
}


inline Register Register::FromAllocationIndex(int index)  {
139
  ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
140 141 142 143
  return (index >= 4) ? from_code(index + 2) : from_code(index);
}


144
struct IntelDoubleRegister {
145
  static const int kMaxNumRegisters = 8;
146 147 148 149
  static const int kMaxNumAllocatableRegisters = 7;
  static int NumAllocatableRegisters();
  static int NumRegisters();
  static const char* AllocationIndexToString(int index);
150

151
  static int ToAllocationIndex(IntelDoubleRegister reg) {
152 153
    ASSERT(reg.code() != 0);
    return reg.code() - 1;
154 155
  }

156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
  static IntelDoubleRegister FromAllocationIndex(int index) {
    ASSERT(index >= 0 && index < NumAllocatableRegisters());
    return from_code(index + 1);
  }

  static IntelDoubleRegister from_code(int code) {
    IntelDoubleRegister result = { code };
    return result;
  }

  bool is_valid() const {
    return 0 <= code_ && code_ < NumRegisters();
  }
  int code() const {
    ASSERT(is_valid());
    return code_;
  }

  int code_;
};


const IntelDoubleRegister double_register_0 = { 0 };
const IntelDoubleRegister double_register_1 = { 1 };
const IntelDoubleRegister double_register_2 = { 2 };
const IntelDoubleRegister double_register_3 = { 3 };
const IntelDoubleRegister double_register_4 = { 4 };
const IntelDoubleRegister double_register_5 = { 5 };
const IntelDoubleRegister double_register_6 = { 6 };
const IntelDoubleRegister double_register_7 = { 7 };
186
const IntelDoubleRegister no_double_reg = { -1 };
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201


struct XMMRegister : IntelDoubleRegister {
  static const int kNumAllocatableRegisters = 7;
  static const int kNumRegisters = 8;

  static XMMRegister from_code(int code) {
    STATIC_ASSERT(sizeof(XMMRegister) == sizeof(IntelDoubleRegister));
    XMMRegister result;
    result.code_ = code;
    return result;
  }

  bool is(XMMRegister reg) const { return code_ == reg.code_; }

202
  static XMMRegister FromAllocationIndex(int index) {
203
    ASSERT(index >= 0 && index < NumAllocatableRegisters());
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
    return from_code(index + 1);
  }

  static const char* AllocationIndexToString(int index) {
    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
    const char* const names[] = {
      "xmm1",
      "xmm2",
      "xmm3",
      "xmm4",
      "xmm5",
      "xmm6",
      "xmm7"
    };
    return names[index];
  }
220
};
221

222 223 224 225 226 227 228 229 230

#define xmm0 (static_cast<const XMMRegister&>(double_register_0))
#define xmm1 (static_cast<const XMMRegister&>(double_register_1))
#define xmm2 (static_cast<const XMMRegister&>(double_register_2))
#define xmm3 (static_cast<const XMMRegister&>(double_register_3))
#define xmm4 (static_cast<const XMMRegister&>(double_register_4))
#define xmm5 (static_cast<const XMMRegister&>(double_register_5))
#define xmm6 (static_cast<const XMMRegister&>(double_register_6))
#define xmm7 (static_cast<const XMMRegister&>(double_register_7))
231
#define no_xmm_reg (static_cast<const XMMRegister&>(no_double_reg))
232 233


234 235 236
struct X87Register : IntelDoubleRegister {
  static const int kNumAllocatableRegisters = 5;
  static const int kNumRegisters = 5;
237

238
  bool is(X87Register reg) const {
239
    return code_ == reg.code_;
240 241
  }

242 243 244
  static const char* AllocationIndexToString(int index) {
    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
    const char* const names[] = {
245
      "stX_0", "stX_1", "stX_2", "stX_3", "stX_4"
246 247
    };
    return names[index];
248 249
  }

250 251 252 253 254 255 256 257 258 259
  static X87Register FromAllocationIndex(int index) {
    STATIC_ASSERT(sizeof(X87Register) == sizeof(IntelDoubleRegister));
    ASSERT(index >= 0 && index < NumAllocatableRegisters());
    X87Register result;
    result.code_ = index;
    return result;
  }

  static int ToAllocationIndex(X87Register reg) {
    return reg.code_;
260
  }
261 262
};

263 264 265 266 267
#define stX_0 static_cast<const X87Register&>(double_register_0)
#define stX_1 static_cast<const X87Register&>(double_register_1)
#define stX_2 static_cast<const X87Register&>(double_register_2)
#define stX_3 static_cast<const X87Register&>(double_register_3)
#define stX_4 static_cast<const X87Register&>(double_register_4)
268 269


270
typedef IntelDoubleRegister DoubleRegister;
271 272


273 274 275 276 277 278 279 280 281 282 283 284
enum Condition {
  // any value < 0 is considered no_condition
  no_condition  = -1,

  overflow      =  0,
  no_overflow   =  1,
  below         =  2,
  above_equal   =  3,
  equal         =  4,
  not_equal     =  5,
  below_equal   =  6,
  above         =  7,
285 286
  negative      =  8,
  positive      =  9,
287 288 289 290 291 292 293 294
  parity_even   = 10,
  parity_odd    = 11,
  less          = 12,
  greater_equal = 13,
  less_equal    = 14,
  greater       = 15,

  // aliases
295 296
  carry         = below,
  not_carry     = above_equal,
297 298
  zero          = equal,
  not_zero      = not_equal,
299 300
  sign          = negative,
  not_sign      = positive
301 302 303 304 305 306 307
};


// Returns the equivalent of !cc.
// Negation of the default no_condition (-1) results in a non-default
// no_condition value (-2). As long as tests for no_condition check
// for condition < 0, this will work as expected.
308 309 310 311
inline Condition NegateCondition(Condition cc) {
  return static_cast<Condition>(cc ^ 1);
}

312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336

// Corresponds to transposing the operands of a comparison.
inline Condition ReverseCondition(Condition cc) {
  switch (cc) {
    case below:
      return above;
    case above:
      return below;
    case above_equal:
      return below_equal;
    case below_equal:
      return above_equal;
    case less:
      return greater;
    case greater:
      return less;
    case greater_equal:
      return less_equal;
    case less_equal:
      return greater_equal;
    default:
      return cc;
  };
}

337

338 339 340 341 342 343 344 345 346
// -----------------------------------------------------------------------------
// Machine instruction Immediates

class Immediate BASE_EMBEDDED {
 public:
  inline explicit Immediate(int x);
  inline explicit Immediate(const ExternalReference& ext);
  inline explicit Immediate(Handle<Object> handle);
  inline explicit Immediate(Smi* value);
347
  inline explicit Immediate(Address addr);
348

349 350 351 352
  static Immediate CodeRelativeOffset(Label* label) {
    return Immediate(label);
  }

353
  bool is_zero() const { return x_ == 0 && RelocInfo::IsNone(rmode_); }
354
  bool is_int8() const {
355
    return -128 <= x_ && x_ < 128 && RelocInfo::IsNone(rmode_);
356
  }
357
  bool is_int16() const {
358
    return -32768 <= x_ && x_ < 32768 && RelocInfo::IsNone(rmode_);
359
  }
360 361

 private:
362 363
  inline explicit Immediate(Label* value);

364
  int x_;
365
  RelocInfo::Mode rmode_;
366 367

  friend class Assembler;
368
  friend class MacroAssembler;
369 370 371 372 373 374 375 376 377 378
};


// -----------------------------------------------------------------------------
// Machine instruction Operands

enum ScaleFactor {
  times_1 = 0,
  times_2 = 1,
  times_4 = 2,
379
  times_8 = 3,
380 381
  times_int_size = times_4,
  times_half_pointer_size = times_2,
382 383
  times_pointer_size = times_4,
  times_twice_pointer_size = times_8
384 385 386 387 388
};


class Operand BASE_EMBEDDED {
 public:
389 390 391
  // XMM reg
  INLINE(explicit Operand(XMMRegister xmm_reg));

392
  // [disp/r]
393
  INLINE(explicit Operand(int32_t disp, RelocInfo::Mode rmode));
394 395 396
  // disp only must always be relocated

  // [base + disp/r]
397
  explicit Operand(Register base, int32_t disp,
398
                   RelocInfo::Mode rmode = RelocInfo::NONE32);
399 400 401 402 403 404

  // [base + index*scale + disp/r]
  explicit Operand(Register base,
                   Register index,
                   ScaleFactor scale,
                   int32_t disp,
405
                   RelocInfo::Mode rmode = RelocInfo::NONE32);
406 407 408 409 410

  // [index*scale + disp/r]
  explicit Operand(Register index,
                   ScaleFactor scale,
                   int32_t disp,
411
                   RelocInfo::Mode rmode = RelocInfo::NONE32);
412 413 414

  static Operand StaticVariable(const ExternalReference& ext) {
    return Operand(reinterpret_cast<int32_t>(ext.address()),
415
                   RelocInfo::EXTERNAL_REFERENCE);
416 417 418 419 420 421
  }

  static Operand StaticArray(Register index,
                             ScaleFactor scale,
                             const ExternalReference& arr) {
    return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()),
422
                   RelocInfo::EXTERNAL_REFERENCE);
423 424
  }

425
  static Operand ForCell(Handle<Cell> cell) {
426
    AllowDeferredHandleDereference embedding_raw_address;
427
    return Operand(reinterpret_cast<int32_t>(cell.location()),
428
                   RelocInfo::CELL);
429 430
  }

431 432 433
  // Returns true if this Operand is a wrapper for the specified register.
  bool is_reg(Register reg) const;

434 435 436 437 438 439 440
  // Returns true if this Operand is a wrapper for one register.
  bool is_reg_only() const;

  // Asserts that this Operand is a wrapper for one register and returns the
  // register.
  Register reg() const;

441
 private:
442 443
  // reg
  INLINE(explicit Operand(Register reg));
444

445 446 447 448
  // Set the ModRM byte without an encoded 'reg' register. The
  // register is encoded later as part of the emit_operand operation.
  inline void set_modrm(int mod, Register rm);

449 450
  inline void set_sib(ScaleFactor scale, Register index, Register base);
  inline void set_disp8(int8_t disp);
451
  inline void set_dispr(int32_t disp, RelocInfo::Mode rmode);
452

453 454 455 456 457 458
  byte buf_[6];
  // The number of bytes in buf_.
  unsigned int len_;
  // Only valid if len_ > 4.
  RelocInfo::Mode rmode_;

459
  friend class Assembler;
460 461
  friend class MacroAssembler;
  friend class LCodeGen;
462 463 464
};


465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
// -----------------------------------------------------------------------------
// A Displacement describes the 32bit immediate field of an instruction which
// may be used together with a Label in order to refer to a yet unknown code
// position. Displacements stored in the instruction stream are used to describe
// the instruction and to chain a list of instructions using the same Label.
// A Displacement contains 2 different fields:
//
// next field: position of next displacement in the chain (0 = end of list)
// type field: instruction type
//
// A next value of null (0) indicates the end of a chain (note that there can
// be no displacement at position zero, because there is always at least one
// instruction byte before the displacement).
//
// Displacement _data field layout
//
481
// |31.....2|1......0|
482 483 484 485 486 487
// [  next  |  type  |

class Displacement BASE_EMBEDDED {
 public:
  enum Type {
    UNCONDITIONAL_JUMP,
488
    CODE_RELATIVE,
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
    OTHER
  };

  int data() const { return data_; }
  Type type() const { return TypeField::decode(data_); }
  void next(Label* L) const {
    int n = NextField::decode(data_);
    n > 0 ? L->link_to(n) : L->Unuse();
  }
  void link_to(Label* L) { init(L, type()); }

  explicit Displacement(int data) { data_ = data; }

  Displacement(Label* L, Type type) { init(L, type); }

  void print() {
    PrintF("%s (%x) ", (type() == UNCONDITIONAL_JUMP ? "jmp" : "[other]"),
                       NextField::decode(data_));
  }

 private:
  int data_;

512 513
  class TypeField: public BitField<Type, 0, 2> {};
  class NextField: public BitField<int,  2, 32-2> {};
514 515 516 517 518

  void init(Label* L, Type type);
};


519

520
// CpuFeatures keeps track of which features are supported by the target CPU.
521
// Supported features must be enabled by a CpuFeatureScope before use.
522
// Example:
523 524
//   if (assembler->IsSupported(SSE2)) {
//     CpuFeatureScope fscope(assembler, SSE2);
525 526 527 528
//     // Generate SSE2 floating point code.
//   } else {
//     // Generate standard x87 floating point code.
//   }
529
class CpuFeatures : public AllStatic {
530
 public:
531 532 533
  // Detect features of the target CPU. Set safe defaults if the serializer
  // is enabled (snapshots must be portable).
  static void Probe();
534

535
  // Check whether a feature is supported by the target CPU.
536 537
  static bool IsSupported(CpuFeature f) {
    ASSERT(initialized_);
538
    if (Check(f, cross_compile_)) return true;
539 540
    if (f == SSE2 && !FLAG_enable_sse2) return false;
    if (f == SSE3 && !FLAG_enable_sse3) return false;
541
    if (f == SSE4_1 && !FLAG_enable_sse4_1) return false;
542
    if (f == CMOV && !FLAG_enable_cmov) return false;
543
    return Check(f, supported_);
544
  }
545

546
  static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
547
    ASSERT(initialized_);
548
    return Check(f, found_by_runtime_probing_only_);
549
  }
550

551
  static bool IsSafeForSnapshot(CpuFeature f) {
552 553
    return Check(f, cross_compile_) ||
           (IsSupported(f) &&
554 555
            (!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f)));
  }
556

557 558 559 560 561 562 563 564 565 566
  static bool VerifyCrossCompiling() {
    return cross_compile_ == 0;
  }

  static bool VerifyCrossCompiling(CpuFeature f) {
    uint64_t mask = flag2set(f);
    return cross_compile_ == 0 ||
           (cross_compile_ & mask) == mask;
  }

567
 private:
568 569 570 571 572 573 574 575
  static bool Check(CpuFeature f, uint64_t set) {
    return (set & flag2set(f)) != 0;
  }

  static uint64_t flag2set(CpuFeature f) {
    return static_cast<uint64_t>(1) << f;
  }

576 577 578 579
#ifdef DEBUG
  static bool initialized_;
#endif
  static uint64_t supported_;
580
  static uint64_t found_by_runtime_probing_only_;
581

582 583
  static uint64_t cross_compile_;

584
  friend class ExternalReference;
585
  friend class PlatformFeatureScope;
586
  DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
587 588 589
};


590
class Assembler : public AssemblerBase {
591
 private:
592 593 594
  // We check before assembling an instruction that there is sufficient
  // space to write an instruction and its relocation information.
  // The relocation writer's position must be kGap bytes above the end of
595
  // the generated instructions. This leaves enough space for the
596 597 598 599 600
  // longest possible ia32 instruction, 15 bytes, and the longest possible
  // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
  // (There is a 15 byte limit on ia32 instruction length that rules out some
  // otherwise valid instructions.)
  // This allows for a single, fast space check per instruction.
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
  static const int kGap = 32;

 public:
  // Create an assembler. Instructions and relocation information are emitted
  // into a buffer, with the instructions starting from the beginning and the
  // relocation information starting from the end of the buffer. See CodeDesc
  // for a detailed comment on the layout (globals.h).
  //
  // If the provided buffer is NULL, the assembler allocates and grows its own
  // buffer, and buffer_size determines the initial buffer size. The buffer is
  // owned by the assembler and deallocated upon destruction of the assembler.
  //
  // If the provided buffer is not NULL, the assembler uses the provided buffer
  // for code generation and assumes its size to be buffer_size. If the buffer
  // is too small, a fatal error occurs. No deallocation of the buffer is done
  // upon destruction of the assembler.
617 618
  // TODO(vitalyr): the assembler does not need an isolate.
  Assembler(Isolate* isolate, void* buffer, int buffer_size);
619
  virtual ~Assembler() { }
620 621 622

  // GetCode emits any pending (non-emitted) code and fills the descriptor
  // desc. GetCode() is idempotent; it returns the same result if no other
623
  // Assembler functions are invoked in between GetCode() calls.
624 625 626 627 628 629
  void GetCode(CodeDesc* desc);

  // Read/Modify the code target in the branch/call instruction at pc.
  inline static Address target_address_at(Address pc);
  inline static void set_target_address_at(Address pc, Address target);

630 631 632 633
  // Return the code target address at a call site from the return address
  // of that call in the instruction stream.
  inline static Address target_address_from_return_address(Address pc);

634
  // This sets the branch destination (which is in the instruction on x86).
635
  // This is for calls and branches within generated code.
636 637
  inline static void deserialization_set_special_target_at(
      Address instruction_payload, Address target) {
638 639 640
    set_target_address_at(instruction_payload, target);
  }

641 642 643 644 645 646 647
  // This sets the branch destination (which is in the instruction on x86).
  // This is for calls and branches to runtime code.
  inline static void set_external_target_at(Address instruction_payload,
                                            Address target) {
    set_target_address_at(instruction_payload, target);
  }

648
  static const int kSpecialTargetSize = kPointerSize;
649

650 651
  // Distance between the address of the code target in the call instruction
  // and the return address
652
  static const int kCallTargetAddressOffset = kPointerSize;
653 654 655
  // Distance between start of patched return sequence and the emitted address
  // to jump to.
  static const int kPatchReturnSequenceAddressOffset = 1;  // JMP imm32.
656

657 658 659 660
  // Distance between start of patched debug break slot and the emitted address
  // to jump to.
  static const int kPatchDebugBreakSlotAddressOffset = 1;  // JMP imm32.

661
  static const int kCallInstructionLength = 5;
662
  static const int kPatchDebugBreakSlotReturnOffset = kPointerSize;
663
  static const int kJSReturnSequenceLength = 6;
664

665 666 667
  // The debug break slot must be able to contain a call instruction.
  static const int kDebugBreakSlotLength = kCallInstructionLength;

668 669
  // One byte opcode for test al, 0xXX.
  static const byte kTestAlByte = 0xA8;
670 671 672 673 674 675 676 677 678
  // One byte opcode for nop.
  static const byte kNopByte = 0x90;

  // One byte opcode for a short unconditional jump.
  static const byte kJmpShortOpcode = 0xEB;
  // One byte prefix for a short conditional jump.
  static const byte kJccShortPrefix = 0x70;
  static const byte kJncShortOpcode = kJccShortPrefix | not_carry;
  static const byte kJcShortOpcode = kJccShortPrefix | carry;
679 680 681
  static const byte kJnzShortOpcode = kJccShortPrefix | not_zero;
  static const byte kJzShortOpcode = kJccShortPrefix | zero;

682

683 684 685 686 687 688 689 690 691 692 693 694 695
  // ---------------------------------------------------------------------------
  // Code generation
  //
  // - function names correspond one-to-one to ia32 instruction mnemonics
  // - unless specified otherwise, instructions operate on 32bit operands
  // - instructions on 8bit (byte) operands/registers have a trailing '_b'
  // - instructions on 16bit (word) operands/registers have a trailing '_w'
  // - naming conflicts with C++ keywords are resolved via a trailing '_'

  // NOTE ON INTERFACE: Currently, the interface is not very consistent
  // in the sense that some operations (e.g. mov()) can be called in more
  // the one way to generate the same instruction: The Register argument
  // can in some cases be replaced with an Operand(Register) argument.
696
  // This should be cleaned up and made more orthogonal. The questions
697 698
  // is: should we always use Operands instead of Registers where an
  // Operand is possible, or should we have a Register (overloaded) form
699
  // instead? We must be careful to make sure that the selected instruction
700 701 702 703 704 705 706
  // is obvious from the parameters to avoid hard-to-find code generation
  // bugs.

  // Insert the smallest number of nop instructions
  // possible to align the pc offset to a multiple
  // of m. m must be a power of 2.
  void Align(int m);
707
  void Nop(int bytes = 1);
708 709
  // Aligns code to something that's optimal for a jump target for the platform.
  void CodeTargetAlign();
710 711 712 713 714 715 716 717 718

  // Stack
  void pushad();
  void popad();

  void pushfd();
  void popfd();

  void push(const Immediate& x);
719
  void push_imm32(int32_t imm32);
720 721 722 723 724 725
  void push(Register src);
  void push(const Operand& src);

  void pop(Register dst);
  void pop(const Operand& dst);

726 727 728
  void enter(const Immediate& size);
  void leave();

729
  // Moves
730
  void mov_b(Register dst, Register src) { mov_b(dst, Operand(src)); }
731
  void mov_b(Register dst, const Operand& src);
732
  void mov_b(Register dst, int8_t imm8) { mov_b(Operand(dst), imm8); }
733 734 735 736 737
  void mov_b(const Operand& dst, int8_t imm8);
  void mov_b(const Operand& dst, Register src);

  void mov_w(Register dst, const Operand& src);
  void mov_w(const Operand& dst, Register src);
738
  void mov_w(const Operand& dst, int16_t imm16);
739 740

  void mov(Register dst, int32_t imm32);
741
  void mov(Register dst, const Immediate& x);
742 743
  void mov(Register dst, Handle<Object> handle);
  void mov(Register dst, const Operand& src);
744
  void mov(Register dst, Register src);
745 746 747 748
  void mov(const Operand& dst, const Immediate& x);
  void mov(const Operand& dst, Handle<Object> handle);
  void mov(const Operand& dst, Register src);

749
  void movsx_b(Register dst, Register src) { movsx_b(dst, Operand(src)); }
750 751
  void movsx_b(Register dst, const Operand& src);

752
  void movsx_w(Register dst, Register src) { movsx_w(dst, Operand(src)); }
753 754
  void movsx_w(Register dst, const Operand& src);

755
  void movzx_b(Register dst, Register src) { movzx_b(dst, Operand(src)); }
756 757
  void movzx_b(Register dst, const Operand& src);

758
  void movzx_w(Register dst, Register src) { movzx_w(dst, Operand(src)); }
759 760 761
  void movzx_w(Register dst, const Operand& src);

  // Conditional moves
762 763 764
  void cmov(Condition cc, Register dst, Register src) {
    cmov(cc, dst, Operand(src));
  }
765 766
  void cmov(Condition cc, Register dst, const Operand& src);

767 768 769
  // Flag management.
  void cld();

770
  // Repetitive string instructions.
771
  void rep_movs();
772
  void rep_stos();
773
  void stos();
774

775 776 777
  // Exchange two registers
  void xchg(Register dst, Register src);

778 779 780 781
  // Arithmetics
  void adc(Register dst, int32_t imm32);
  void adc(Register dst, const Operand& src);

782
  void add(Register dst, Register src) { add(dst, Operand(src)); }
783
  void add(Register dst, const Operand& src);
784
  void add(const Operand& dst, Register src);
785
  void add(Register dst, const Immediate& imm) { add(Operand(dst), imm); }
786 787 788
  void add(const Operand& dst, const Immediate& x);

  void and_(Register dst, int32_t imm32);
789
  void and_(Register dst, const Immediate& x);
790
  void and_(Register dst, Register src) { and_(dst, Operand(src)); }
791
  void and_(Register dst, const Operand& src);
792
  void and_(const Operand& dst, Register src);
793 794
  void and_(const Operand& dst, const Immediate& x);

795
  void cmpb(Register reg, int8_t imm8) { cmpb(Operand(reg), imm8); }
796
  void cmpb(const Operand& op, int8_t imm8);
797 798
  void cmpb(Register reg, const Operand& op);
  void cmpb(const Operand& op, Register reg);
799 800
  void cmpb_al(const Operand& op);
  void cmpw_ax(const Operand& op);
801
  void cmpw(const Operand& op, Immediate imm16);
802 803
  void cmp(Register reg, int32_t imm32);
  void cmp(Register reg, Handle<Object> handle);
804
  void cmp(Register reg0, Register reg1) { cmp(reg0, Operand(reg1)); }
805
  void cmp(Register reg, const Operand& op);
806
  void cmp(Register reg, const Immediate& imm) { cmp(Operand(reg), imm); }
807
  void cmp(const Operand& op, const Immediate& imm);
808
  void cmp(const Operand& op, Handle<Object> handle);
809 810

  void dec_b(Register dst);
811
  void dec_b(const Operand& dst);
812 813 814 815 816 817 818 819

  void dec(Register dst);
  void dec(const Operand& dst);

  void cdq();

  void idiv(Register src);

820 821
  // Signed multiply instructions.
  void imul(Register src);                               // edx:eax = eax * src.
822
  void imul(Register dst, Register src) { imul(dst, Operand(src)); }
823 824
  void imul(Register dst, const Operand& src);           // dst = dst * src.
  void imul(Register dst, Register src, int32_t imm32);  // dst = src * imm32.
825 826 827 828 829 830

  void inc(Register dst);
  void inc(const Operand& dst);

  void lea(Register dst, const Operand& src);

831 832
  // Unsigned multiply instruction.
  void mul(Register src);                                // edx:eax = eax * reg.
833 834 835 836 837 838

  void neg(Register dst);

  void not_(Register dst);

  void or_(Register dst, int32_t imm32);
839
  void or_(Register dst, Register src) { or_(dst, Operand(src)); }
840 841
  void or_(Register dst, const Operand& src);
  void or_(const Operand& dst, Register src);
842
  void or_(Register dst, const Immediate& imm) { or_(Operand(dst), imm); }
843 844 845
  void or_(const Operand& dst, const Immediate& x);

  void rcl(Register dst, uint8_t imm8);
846
  void rcr(Register dst, uint8_t imm8);
847 848
  void ror(Register dst, uint8_t imm8);
  void ror_cl(Register dst);
849 850

  void sar(Register dst, uint8_t imm8);
851
  void sar_cl(Register dst);
852 853 854

  void sbb(Register dst, const Operand& src);

855
  void shld(Register dst, Register src) { shld(dst, Operand(src)); }
856 857 858
  void shld(Register dst, const Operand& src);

  void shl(Register dst, uint8_t imm8);
859
  void shl_cl(Register dst);
860

861
  void shrd(Register dst, Register src) { shrd(dst, Operand(src)); }
862 863 864
  void shrd(Register dst, const Operand& src);

  void shr(Register dst, uint8_t imm8);
865
  void shr_cl(Register dst);
866

867
  void sub(Register dst, const Immediate& imm) { sub(Operand(dst), imm); }
868
  void sub(const Operand& dst, const Immediate& x);
869
  void sub(Register dst, Register src) { sub(dst, Operand(src)); }
870 871 872 873
  void sub(Register dst, const Operand& src);
  void sub(const Operand& dst, Register src);

  void test(Register reg, const Immediate& imm);
874
  void test(Register reg0, Register reg1) { test(reg0, Operand(reg1)); }
875
  void test(Register reg, const Operand& op);
876
  void test_b(Register reg, const Operand& op);
877
  void test(const Operand& op, const Immediate& imm);
878
  void test_b(Register reg, uint8_t imm8);
879
  void test_b(const Operand& op, uint8_t imm8);
880 881

  void xor_(Register dst, int32_t imm32);
882
  void xor_(Register dst, Register src) { xor_(dst, Operand(src)); }
883
  void xor_(Register dst, const Operand& src);
884 885
  void xor_(const Operand& dst, Register src);
  void xor_(Register dst, const Immediate& imm) { xor_(Operand(dst), imm); }
886 887 888
  void xor_(const Operand& dst, const Immediate& x);

  // Bit operations.
889
  void bt(const Operand& dst, Register src);
890
  void bts(Register dst, Register src) { bts(Operand(dst), src); }
891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917
  void bts(const Operand& dst, Register src);

  // Miscellaneous
  void hlt();
  void int3();
  void nop();
  void ret(int imm16);

  // Label operations & relative jumps (PPUM Appendix D)
  //
  // Takes a branch opcode (cc) and a label (L) and generates
  // either a backward branch or a forward branch and links it
  // to the label fixup chain. Usage:
  //
  // Label L;    // unbound label
  // j(cc, &L);  // forward branch to unbound label
  // bind(&L);   // bind label to the current pc
  // j(cc, &L);  // backward branch to bound label
  // bind(&L);   // illegal: a label may be bound only once
  //
  // Note: The same Label can be used for forward and backward branches
  // but it may be bound only once.

  void bind(Label* L);  // binds an unbound label L to the current code position

  // Calls
  void call(Label* L);
918
  void call(byte* entry, RelocInfo::Mode rmode);
919
  int CallSize(const Operand& adr);
920
  void call(Register reg) { call(Operand(reg)); }
921
  void call(const Operand& adr);
922
  int CallSize(Handle<Code> code, RelocInfo::Mode mode);
923
  void call(Handle<Code> code,
924 925
            RelocInfo::Mode rmode,
            TypeFeedbackId id = TypeFeedbackId::None());
926 927

  // Jumps
928 929
  // unconditional jump to L
  void jmp(Label* L, Label::Distance distance = Label::kFar);
930
  void jmp(byte* entry, RelocInfo::Mode rmode);
931
  void jmp(Register reg) { jmp(Operand(reg)); }
932
  void jmp(const Operand& adr);
933
  void jmp(Handle<Code> code, RelocInfo::Mode rmode);
934 935

  // Conditional jumps
936 937 938
  void j(Condition cc,
         Label* L,
         Label::Distance distance = Label::kFar);
939 940
  void j(Condition cc, byte* entry, RelocInfo::Mode rmode);
  void j(Condition cc, Handle<Code> code);
941 942 943

  // Floating-point operations
  void fld(int i);
944
  void fstp(int i);
945 946 947

  void fld1();
  void fldz();
948
  void fldpi();
949
  void fldln2();
950 951 952 953 954

  void fld_s(const Operand& adr);
  void fld_d(const Operand& adr);

  void fstp_s(const Operand& adr);
955
  void fst_s(const Operand& adr);
956
  void fstp_d(const Operand& adr);
957
  void fst_d(const Operand& adr);
958 959 960 961 962 963 964 965 966

  void fild_s(const Operand& adr);
  void fild_d(const Operand& adr);

  void fist_s(const Operand& adr);

  void fistp_s(const Operand& adr);
  void fistp_d(const Operand& adr);

967
  // The fisttp instructions require SSE3.
968
  void fisttp_s(const Operand& adr);
969
  void fisttp_d(const Operand& adr);
970

971 972
  void fabs();
  void fchs();
973 974
  void fcos();
  void fsin();
975
  void fptan();
976
  void fyl2x();
977 978 979
  void f2xm1();
  void fscale();
  void fninit();
980 981

  void fadd(int i);
982
  void fadd_i(int i);
983
  void fsub(int i);
984
  void fsub_i(int i);
985
  void fmul(int i);
986
  void fmul_i(int i);
987
  void fdiv(int i);
988
  void fdiv_i(int i);
989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006

  void fisub_s(const Operand& adr);

  void faddp(int i = 1);
  void fsubp(int i = 1);
  void fsubrp(int i = 1);
  void fmulp(int i = 1);
  void fdivp(int i = 1);
  void fprem();
  void fprem1();

  void fxch(int i = 1);
  void fincstp();
  void ffree(int i = 0);

  void ftst();
  void fucomp(int i);
  void fucompp();
1007
  void fucomi(int i);
1008
  void fucomip();
1009 1010 1011
  void fcompp();
  void fnstsw_ax();
  void fwait();
1012
  void fnclex();
1013 1014 1015 1016

  void frndint();

  void sahf();
1017
  void setcc(Condition cc, Register reg);
1018 1019 1020

  void cpuid();

1021
  // SSE instructions
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
  void movaps(XMMRegister dst, XMMRegister src);
  void shufps(XMMRegister dst, XMMRegister src, byte imm8);

  void andps(XMMRegister dst, const Operand& src);
  void andps(XMMRegister dst, XMMRegister src) { andps(dst, Operand(src)); }
  void xorps(XMMRegister dst, const Operand& src);
  void xorps(XMMRegister dst, XMMRegister src) { xorps(dst, Operand(src)); }
  void orps(XMMRegister dst, const Operand& src);
  void orps(XMMRegister dst, XMMRegister src) { orps(dst, Operand(src)); }

  void addps(XMMRegister dst, const Operand& src);
  void addps(XMMRegister dst, XMMRegister src) { addps(dst, Operand(src)); }
  void subps(XMMRegister dst, const Operand& src);
  void subps(XMMRegister dst, XMMRegister src) { subps(dst, Operand(src)); }
  void mulps(XMMRegister dst, const Operand& src);
  void mulps(XMMRegister dst, XMMRegister src) { mulps(dst, Operand(src)); }
  void divps(XMMRegister dst, const Operand& src);
  void divps(XMMRegister dst, XMMRegister src) { divps(dst, Operand(src)); }
1040

1041 1042
  // SSE2 instructions
  void cvttss2si(Register dst, const Operand& src);
1043 1044 1045
  void cvttss2si(Register dst, XMMRegister src) {
    cvttss2si(dst, Operand(src));
  }
1046
  void cvttsd2si(Register dst, const Operand& src);
1047
  void cvtsd2si(Register dst, XMMRegister src);
1048

1049
  void cvtsi2sd(XMMRegister dst, Register src) { cvtsi2sd(dst, Operand(src)); }
1050
  void cvtsi2sd(XMMRegister dst, const Operand& src);
1051
  void cvtss2sd(XMMRegister dst, XMMRegister src);
1052
  void cvtsd2ss(XMMRegister dst, XMMRegister src);
1053 1054

  void addsd(XMMRegister dst, XMMRegister src);
1055
  void addsd(XMMRegister dst, const Operand& src);
1056 1057
  void subsd(XMMRegister dst, XMMRegister src);
  void mulsd(XMMRegister dst, XMMRegister src);
1058
  void mulsd(XMMRegister dst, const Operand& src);
1059
  void divsd(XMMRegister dst, XMMRegister src);
1060
  void xorpd(XMMRegister dst, XMMRegister src);
1061
  void sqrtsd(XMMRegister dst, XMMRegister src);
1062

1063
  void andpd(XMMRegister dst, XMMRegister src);
1064
  void orpd(XMMRegister dst, XMMRegister src);
1065

1066
  void ucomisd(XMMRegister dst, XMMRegister src) { ucomisd(dst, Operand(src)); }
1067
  void ucomisd(XMMRegister dst, const Operand& src);
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077

  enum RoundingMode {
    kRoundToNearest = 0x0,
    kRoundDown      = 0x1,
    kRoundUp        = 0x2,
    kRoundToZero    = 0x3
  };

  void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode);

1078
  void movmskpd(Register dst, XMMRegister src);
1079
  void movmskps(Register dst, XMMRegister src);
1080

1081
  void cmpltsd(XMMRegister dst, XMMRegister src);
1082
  void pcmpeqd(XMMRegister dst, XMMRegister src);
1083

1084 1085 1086 1087
  void movdqa(XMMRegister dst, const Operand& src);
  void movdqa(const Operand& dst, XMMRegister src);
  void movdqu(XMMRegister dst, const Operand& src);
  void movdqu(const Operand& dst, XMMRegister src);
1088 1089 1090 1091 1092 1093 1094
  void movdq(bool aligned, XMMRegister dst, const Operand& src) {
    if (aligned) {
      movdqa(dst, src);
    } else {
      movdqu(dst, src);
    }
  }
1095

1096
  void movd(XMMRegister dst, Register src) { movd(dst, Operand(src)); }
1097
  void movd(XMMRegister dst, const Operand& src);
1098 1099
  void movd(Register dst, XMMRegister src) { movd(Operand(dst), src); }
  void movd(const Operand& dst, XMMRegister src);
1100
  void movsd(XMMRegister dst, XMMRegister src) { movsd(dst, Operand(src)); }
1101 1102 1103
  void movsd(XMMRegister dst, const Operand& src);
  void movsd(const Operand& dst, XMMRegister src);

1104

1105
  void movss(XMMRegister dst, const Operand& src);
1106
  void movss(const Operand& dst, XMMRegister src);
1107
  void movss(XMMRegister dst, XMMRegister src) { movss(dst, Operand(src)); }
1108
  void extractps(Register dst, XMMRegister src, byte imm8);
1109

1110
  void pand(XMMRegister dst, XMMRegister src);
1111
  void pxor(XMMRegister dst, XMMRegister src);
1112
  void por(XMMRegister dst, XMMRegister src);
1113 1114
  void ptest(XMMRegister dst, XMMRegister src);

1115
  void psllq(XMMRegister reg, int8_t shift);
1116 1117 1118
  void psllq(XMMRegister dst, XMMRegister src);
  void psrlq(XMMRegister reg, int8_t shift);
  void psrlq(XMMRegister dst, XMMRegister src);
1119
  void pshufd(XMMRegister dst, XMMRegister src, uint8_t shuffle);
1120 1121 1122
  void pextrd(Register dst, XMMRegister src, int8_t offset) {
    pextrd(Operand(dst), src, offset);
  }
1123
  void pextrd(const Operand& dst, XMMRegister src, int8_t offset);
1124 1125 1126
  void pinsrd(XMMRegister dst, Register src, int8_t offset) {
    pinsrd(dst, Operand(src), offset);
  }
1127
  void pinsrd(XMMRegister dst, const Operand& src, int8_t offset);
1128

1129
  // Parallel XMM operations.
1130
  void movntdqa(XMMRegister dst, const Operand& src);
1131 1132 1133 1134 1135 1136 1137
  void movntdq(const Operand& dst, XMMRegister src);
  // Prefetch src position into cache level.
  // Level 1, 2 or 3 specifies CPU cache level. Level 0 specifies a
  // non-temporal
  void prefetch(const Operand& src, int level);
  // TODO(lrn): Need SFENCE for movnt?

1138 1139 1140 1141
  // Debugging
  void Print();

  // Check the code size generated from label to here.
1142 1143 1144
  int SizeOfCodeGeneratedSince(Label* label) {
    return pc_offset() - label->pos();
  }
1145 1146 1147 1148

  // Mark address of the ExitJSFrame code.
  void RecordJSReturn();

1149 1150 1151
  // Mark address of a debug break slot.
  void RecordDebugBreakSlot();

1152
  // Record a comment relocation entry that can be used by a disassembler.
1153 1154 1155
  // Use --code-comments to enable, or provide "force = true" flag to always
  // write a comment.
  void RecordComment(const char* msg, bool force = false);
1156

1157 1158 1159 1160
  // Writes a single byte or word of data in the code stream.  Used for
  // inline tables, e.g., jump-tables.
  void db(uint8_t data);
  void dd(uint32_t data);
1161

1162 1163 1164 1165 1166 1167 1168 1169
  // Check if there is less than kGap bytes available in the buffer.
  // If this is the case, we need to grow the buffer before emitting
  // an instruction or relocation information.
  inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; }

  // Get the number of bytes available in the buffer.
  inline int available_space() const { return reloc_info_writer.pos() - pc_; }

1170
  static bool IsNop(Address addr);
1171

1172 1173
  PositionsRecorder* positions_recorder() { return &positions_recorder_; }

1174 1175 1176 1177
  int relocation_writer_size() {
    return (buffer_ + buffer_size_) - reloc_info_writer.pos();
  }

1178 1179 1180
  // Avoid overflows for displacements etc.
  static const int kMaximalBufferSize = 512*MB;

1181
  byte byte_at(int pos) { return buffer_[pos]; }
1182 1183
  void set_byte_at(int pos, byte value) { buffer_[pos] = value; }

1184 1185 1186
 protected:
  void emit_sse_operand(XMMRegister reg, const Operand& adr);
  void emit_sse_operand(XMMRegister dst, XMMRegister src);
1187
  void emit_sse_operand(Register dst, XMMRegister src);
1188
  void emit_sse_operand(XMMRegister dst, Register src);
1189

1190 1191
  byte* addr_at(int pos) { return buffer_ + pos; }

1192

1193
 private:
1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204
  uint32_t long_at(int pos)  {
    return *reinterpret_cast<uint32_t*>(addr_at(pos));
  }
  void long_at_put(int pos, uint32_t x)  {
    *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
  }

  // code emission
  void GrowBuffer();
  inline void emit(uint32_t x);
  inline void emit(Handle<Object> handle);
1205 1206
  inline void emit(uint32_t x,
                   RelocInfo::Mode rmode,
1207
                   TypeFeedbackId id = TypeFeedbackId::None());
1208 1209 1210
  inline void emit(Handle<Code> code,
                   RelocInfo::Mode rmode,
                   TypeFeedbackId id = TypeFeedbackId::None());
1211
  inline void emit(const Immediate& x);
1212
  inline void emit_w(const Immediate& x);
1213

1214 1215 1216
  // Emit the code-object-relative offset of the label's position
  inline void emit_code_relative_offset(Label* label);

1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233
  // instruction generation
  void emit_arith_b(int op1, int op2, Register dst, int imm8);

  // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81)
  // with a given destination expression and an immediate operand.  It attempts
  // to use the shortest encoding possible.
  // sel specifies the /n in the modrm byte (see the Intel PRM).
  void emit_arith(int sel, Operand dst, const Immediate& x);

  void emit_operand(Register reg, const Operand& adr);

  void emit_farith(int b1, int b2, int i);

  // labels
  void print(Label* L);
  void bind_to(Label* L, int pos);

1234 1235 1236 1237
  // displacements
  inline Displacement disp_at(Label* L);
  inline void disp_at_put(Label* L, Displacement disp);
  inline void emit_disp(Label* L, Displacement::Type type);
1238
  inline void emit_near_disp(Label* L);
1239

1240
  // record reloc info for current pc_
1241
  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1242 1243 1244

  friend class CodePatcher;
  friend class EnsureSpace;
1245 1246 1247 1248

  // code generation
  RelocInfoWriter reloc_info_writer;

1249 1250
  PositionsRecorder positions_recorder_;
  friend class PositionsRecorder;
1251 1252 1253 1254 1255 1256 1257 1258 1259 1260
};


// Helper class that ensures that there is enough space for generating
// instructions and relocation information.  The constructor makes
// sure that there is enough space and (in debug mode) the destructor
// checks that we did not generate too much.
class EnsureSpace BASE_EMBEDDED {
 public:
  explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
ager@chromium.org's avatar
ager@chromium.org committed
1261
    if (assembler_->overflow()) assembler_->GrowBuffer();
1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282
#ifdef DEBUG
    space_before_ = assembler_->available_space();
#endif
  }

#ifdef DEBUG
  ~EnsureSpace() {
    int bytes_generated = space_before_ - assembler_->available_space();
    ASSERT(bytes_generated < assembler_->kGap);
  }
#endif

 private:
  Assembler* assembler_;
#ifdef DEBUG
  int space_before_;
#endif
};

} }  // namespace v8::internal

1283
#endif  // V8_IA32_ASSEMBLER_IA32_H_