The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / ia32 / assembler-ia32.h @ f230a1cf

History | View | Annotate | Download (40.6 KB)

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
const IntelDoubleRegister no_double_reg = { -1 };
187

    
188

    
189
struct XMMRegister : IntelDoubleRegister {
190
  static const int kNumAllocatableRegisters = 7;
191
  static const int kNumRegisters = 8;
192

    
193
  static XMMRegister from_code(int code) {
194
    STATIC_ASSERT(sizeof(XMMRegister) == sizeof(IntelDoubleRegister));
195
    XMMRegister result;
196
    result.code_ = code;
197
    return result;
198
  }
199

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

    
202
  static XMMRegister FromAllocationIndex(int index) {
203
    ASSERT(index >= 0 && index < NumAllocatableRegisters());
204
    return from_code(index + 1);
205
  }
206

    
207
  static const char* AllocationIndexToString(int index) {
208
    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
209
    const char* const names[] = {
210
      "xmm1",
211
      "xmm2",
212
      "xmm3",
213
      "xmm4",
214
      "xmm5",
215
      "xmm6",
216
      "xmm7"
217
    };
218
    return names[index];
219
  }
220
};
221

    
222

    
223
#define xmm0 (static_cast<const XMMRegister&>(double_register_0))
224
#define xmm1 (static_cast<const XMMRegister&>(double_register_1))
225
#define xmm2 (static_cast<const XMMRegister&>(double_register_2))
226
#define xmm3 (static_cast<const XMMRegister&>(double_register_3))
227
#define xmm4 (static_cast<const XMMRegister&>(double_register_4))
228
#define xmm5 (static_cast<const XMMRegister&>(double_register_5))
229
#define xmm6 (static_cast<const XMMRegister&>(double_register_6))
230
#define xmm7 (static_cast<const XMMRegister&>(double_register_7))
231
#define no_xmm_reg (static_cast<const XMMRegister&>(no_double_reg))
232

    
233

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

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

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

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

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

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

    
269

    
270
typedef IntelDoubleRegister DoubleRegister;
271

    
272

    
273
enum Condition {
274
  // any value < 0 is considered no_condition
275
  no_condition  = -1,
276

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

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

    
303

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

    
312

    
313
// Corresponds to transposing the operands of a comparison.
314
inline Condition ReverseCondition(Condition cc) {
315
  switch (cc) {
316
    case below:
317
      return above;
318
    case above:
319
      return below;
320
    case above_equal:
321
      return below_equal;
322
    case below_equal:
323
      return above_equal;
324
    case less:
325
      return greater;
326
    case greater:
327
      return less;
328
    case greater_equal:
329
      return less_equal;
330
    case less_equal:
331
      return greater_equal;
332
    default:
333
      return cc;
334
  };
335
}
336

    
337

    
338
// -----------------------------------------------------------------------------
339
// Machine instruction Immediates
340

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

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

    
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
  inline explicit Immediate(Label* value);
363

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

    
367
  friend class Assembler;
368
  friend class MacroAssembler;
369
};
370

    
371

    
372
// -----------------------------------------------------------------------------
373
// Machine instruction Operands
374

    
375
enum ScaleFactor {
376
  times_1 = 0,
377
  times_2 = 1,
378
  times_4 = 2,
379
  times_8 = 3,
380
  times_int_size = times_4,
381
  times_half_pointer_size = times_2,
382
  times_pointer_size = times_4,
383
  times_twice_pointer_size = times_8
384
};
385

    
386

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

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

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

    
400
  // [base + index*scale + disp/r]
401
  explicit Operand(Register base,
402
                   Register index,
403
                   ScaleFactor scale,
404
                   int32_t disp,
405
                   RelocInfo::Mode rmode = RelocInfo::NONE32);
406

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

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

    
418
  static Operand StaticArray(Register index,
419
                             ScaleFactor scale,
420
                             const ExternalReference& arr) {
421
    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
  // Returns true if this Operand is a wrapper for the specified register.
432
  bool is_reg(Register reg) const;
433

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

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

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

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

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

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

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

    
464

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

    
484
class Displacement BASE_EMBEDDED {
485
 public:
486
  enum Type {
487
    UNCONDITIONAL_JUMP,
488
    CODE_RELATIVE,
489
    OTHER
490
  };
491

    
492
  int data() const { return data_; }
493
  Type type() const { return TypeField::decode(data_); }
494
  void next(Label* L) const {
495
    int n = NextField::decode(data_);
496
    n > 0 ? L->link_to(n) : L->Unuse();
497
  }
498
  void link_to(Label* L) { init(L, type()); }
499

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

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

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

    
509
 private:
510
  int data_;
511

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

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

    
518

    
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
//   if (assembler->IsSupported(SSE2)) {
524
//     CpuFeatureScope fscope(assembler, SSE2);
525
//     // Generate SSE2 floating point code.
526
//   } else {
527
//     // Generate standard x87 floating point code.
528
//   }
529
class CpuFeatures : public AllStatic {
530
 public:
531
  // Detect features of the target CPU. Set safe defaults if the serializer
532
  // is enabled (snapshots must be portable).
533
  static void Probe();
534

    
535
  // Check whether a feature is supported by the target CPU.
536
  static bool IsSupported(CpuFeature f) {
537
    ASSERT(initialized_);
538
    if (Check(f, cross_compile_)) return true;
539
    if (f == SSE2 && !FLAG_enable_sse2) return false;
540
    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
    return Check(f, cross_compile_) ||
553
           (IsSupported(f) &&
554
            (!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f)));
555
  }
556

    
557
  static bool VerifyCrossCompiling() {
558
    return cross_compile_ == 0;
559
  }
560

    
561
  static bool VerifyCrossCompiling(CpuFeature f) {
562
    uint64_t mask = flag2set(f);
563
    return cross_compile_ == 0 ||
564
           (cross_compile_ & mask) == mask;
565
  }
566

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

    
572
  static uint64_t flag2set(CpuFeature f) {
573
    return static_cast<uint64_t>(1) << f;
574
  }
575

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

    
582
  static uint64_t cross_compile_;
583

    
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
  // We check before assembling an instruction that there is sufficient
593
  // space to write an instruction and its relocation information.
594
  // The relocation writer's position must be kGap bytes above the end of
595
  // the generated instructions. This leaves enough space for the
596
  // longest possible ia32 instruction, 15 bytes, and the longest possible
597
  // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
598
  // (There is a 15 byte limit on ia32 instruction length that rules out some
599
  // otherwise valid instructions.)
600
  // This allows for a single, fast space check per instruction.
601
  static const int kGap = 32;
602

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

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

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

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

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

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

    
648
  static const int kSpecialTargetSize = kPointerSize;
649

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

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

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

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

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

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

    
682

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

    
692
  // NOTE ON INTERFACE: Currently, the interface is not very consistent
693
  // in the sense that some operations (e.g. mov()) can be called in more
694
  // the one way to generate the same instruction: The Register argument
695
  // can in some cases be replaced with an Operand(Register) argument.
696
  // This should be cleaned up and made more orthogonal. The questions
697
  // is: should we always use Operands instead of Registers where an
698
  // 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
  // is obvious from the parameters to avoid hard-to-find code generation
701
  // bugs.
702

    
703
  // Insert the smallest number of nop instructions
704
  // possible to align the pc offset to a multiple
705
  // of m. m must be a power of 2.
706
  void Align(int m);
707
  void Nop(int bytes = 1);
708
  // Aligns code to something that's optimal for a jump target for the platform.
709
  void CodeTargetAlign();
710

    
711
  // Stack
712
  void pushad();
713
  void popad();
714

    
715
  void pushfd();
716
  void popfd();
717

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

    
723
  void pop(Register dst);
724
  void pop(const Operand& dst);
725

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

    
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
  void mov_b(const Operand& dst, int8_t imm8);
734
  void mov_b(const Operand& dst, Register src);
735

    
736
  void mov_w(Register dst, const Operand& src);
737
  void mov_w(const Operand& dst, Register src);
738

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

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

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

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

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

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

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

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

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

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

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

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

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

    
809
  void dec_b(Register dst);
810
  void dec_b(const Operand& dst);
811

    
812
  void dec(Register dst);
813
  void dec(const Operand& dst);
814

    
815
  void cdq();
816

    
817
  void idiv(Register src);
818

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

    
825
  void inc(Register dst);
826
  void inc(const Operand& dst);
827

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

    
830
  // Unsigned multiply instruction.
831
  void mul(Register src);                                // edx:eax = eax * reg.
832

    
833
  void neg(Register dst);
834

    
835
  void not_(Register dst);
836

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

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

    
849
  void sar(Register dst, uint8_t imm8);
850
  void sar_cl(Register dst);
851

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

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

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

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

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

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

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

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

    
887
  // Bit operations.
888
  void bt(const Operand& dst, Register src);
889
  void bts(Register dst, Register src) { bts(Operand(dst), src); }
890
  void bts(const Operand& dst, Register src);
891

    
892
  // Miscellaneous
893
  void hlt();
894
  void int3();
895
  void nop();
896
  void ret(int imm16);
897

    
898
  // Label operations & relative jumps (PPUM Appendix D)
899
  //
900
  // Takes a branch opcode (cc) and a label (L) and generates
901
  // either a backward branch or a forward branch and links it
902
  // to the label fixup chain. Usage:
903
  //
904
  // Label L;    // unbound label
905
  // j(cc, &L);  // forward branch to unbound label
906
  // bind(&L);   // bind label to the current pc
907
  // j(cc, &L);  // backward branch to bound label
908
  // bind(&L);   // illegal: a label may be bound only once
909
  //
910
  // Note: The same Label can be used for forward and backward branches
911
  // but it may be bound only once.
912

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

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

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

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

    
941
  // Floating-point operations
942
  void fld(int i);
943
  void fstp(int i);
944

    
945
  void fld1();
946
  void fldz();
947
  void fldpi();
948
  void fldln2();
949

    
950
  void fld_s(const Operand& adr);
951
  void fld_d(const Operand& adr);
952

    
953
  void fstp_s(const Operand& adr);
954
  void fst_s(const Operand& adr);
955
  void fstp_d(const Operand& adr);
956
  void fst_d(const Operand& adr);
957

    
958
  void fild_s(const Operand& adr);
959
  void fild_d(const Operand& adr);
960

    
961
  void fist_s(const Operand& adr);
962

    
963
  void fistp_s(const Operand& adr);
964
  void fistp_d(const Operand& adr);
965

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

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

    
980
  void fadd(int i);
981
  void fadd_i(int i);
982
  void fsub(int i);
983
  void fsub_i(int i);
984
  void fmul(int i);
985
  void fmul_i(int i);
986
  void fdiv(int i);
987
  void fdiv_i(int i);
988

    
989
  void fisub_s(const Operand& adr);
990

    
991
  void faddp(int i = 1);
992
  void fsubp(int i = 1);
993
  void fsubrp(int i = 1);
994
  void fmulp(int i = 1);
995
  void fdivp(int i = 1);
996
  void fprem();
997
  void fprem1();
998

    
999
  void fxch(int i = 1);
1000
  void fincstp();
1001
  void ffree(int i = 0);
1002

    
1003
  void ftst();
1004
  void fucomp(int i);
1005
  void fucompp();
1006
  void fucomi(int i);
1007
  void fucomip();
1008
  void fcompp();
1009
  void fnstsw_ax();
1010
  void fwait();
1011
  void fnclex();
1012

    
1013
  void frndint();
1014

    
1015
  void sahf();
1016
  void setcc(Condition cc, Register reg);
1017

    
1018
  void cpuid();
1019

    
1020
  // SSE instructions
1021
  void andps(XMMRegister dst, XMMRegister src);
1022
  void xorps(XMMRegister dst, XMMRegister src);
1023

    
1024
  // SSE2 instructions
1025
  void cvttss2si(Register dst, const Operand& src);
1026
  void cvttsd2si(Register dst, const Operand& src);
1027
  void cvtsd2si(Register dst, XMMRegister src);
1028

    
1029
  void cvtsi2sd(XMMRegister dst, Register src) { cvtsi2sd(dst, Operand(src)); }
1030
  void cvtsi2sd(XMMRegister dst, const Operand& src);
1031
  void cvtss2sd(XMMRegister dst, XMMRegister src);
1032
  void cvtsd2ss(XMMRegister dst, XMMRegister src);
1033

    
1034
  void addsd(XMMRegister dst, XMMRegister src);
1035
  void addsd(XMMRegister dst, const Operand& src);
1036
  void subsd(XMMRegister dst, XMMRegister src);
1037
  void mulsd(XMMRegister dst, XMMRegister src);
1038
  void mulsd(XMMRegister dst, const Operand& src);
1039
  void divsd(XMMRegister dst, XMMRegister src);
1040
  void xorpd(XMMRegister dst, XMMRegister src);
1041
  void sqrtsd(XMMRegister dst, XMMRegister src);
1042

    
1043
  void andpd(XMMRegister dst, XMMRegister src);
1044
  void orpd(XMMRegister dst, XMMRegister src);
1045

    
1046
  void ucomisd(XMMRegister dst, XMMRegister src);
1047
  void ucomisd(XMMRegister dst, const Operand& src);
1048

    
1049
  enum RoundingMode {
1050
    kRoundToNearest = 0x0,
1051
    kRoundDown      = 0x1,
1052
    kRoundUp        = 0x2,
1053
    kRoundToZero    = 0x3
1054
  };
1055

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

    
1058
  void movmskpd(Register dst, XMMRegister src);
1059
  void movmskps(Register dst, XMMRegister src);
1060

    
1061
  void cmpltsd(XMMRegister dst, XMMRegister src);
1062
  void pcmpeqd(XMMRegister dst, XMMRegister src);
1063

    
1064
  void movaps(XMMRegister dst, XMMRegister src);
1065

    
1066
  void movdqa(XMMRegister dst, const Operand& src);
1067
  void movdqa(const Operand& dst, XMMRegister src);
1068
  void movdqu(XMMRegister dst, const Operand& src);
1069
  void movdqu(const Operand& dst, XMMRegister src);
1070
  void movdq(bool aligned, XMMRegister dst, const Operand& src) {
1071
    if (aligned) {
1072
      movdqa(dst, src);
1073
    } else {
1074
      movdqu(dst, src);
1075
    }
1076
  }
1077

    
1078
  void movd(XMMRegister dst, Register src) { movd(dst, Operand(src)); }
1079
  void movd(XMMRegister dst, const Operand& src);
1080
  void movd(Register dst, XMMRegister src) { movd(Operand(dst), src); }
1081
  void movd(const Operand& dst, XMMRegister src);
1082
  void movsd(XMMRegister dst, XMMRegister src);
1083
  void movsd(XMMRegister dst, const Operand& src);
1084
  void movsd(const Operand& dst, XMMRegister src);
1085

    
1086

    
1087
  void movss(XMMRegister dst, const Operand& src);
1088
  void movss(const Operand& dst, XMMRegister src);
1089
  void movss(XMMRegister dst, XMMRegister src);
1090
  void extractps(Register dst, XMMRegister src, byte imm8);
1091

    
1092
  void pand(XMMRegister dst, XMMRegister src);
1093
  void pxor(XMMRegister dst, XMMRegister src);
1094
  void por(XMMRegister dst, XMMRegister src);
1095
  void ptest(XMMRegister dst, XMMRegister src);
1096

    
1097
  void psllq(XMMRegister reg, int8_t shift);
1098
  void psllq(XMMRegister dst, XMMRegister src);
1099
  void psrlq(XMMRegister reg, int8_t shift);
1100
  void psrlq(XMMRegister dst, XMMRegister src);
1101
  void pshufd(XMMRegister dst, XMMRegister src, uint8_t shuffle);
1102
  void pextrd(Register dst, XMMRegister src, int8_t offset) {
1103
    pextrd(Operand(dst), src, offset);
1104
  }
1105
  void pextrd(const Operand& dst, XMMRegister src, int8_t offset);
1106
  void pinsrd(XMMRegister dst, Register src, int8_t offset) {
1107
    pinsrd(dst, Operand(src), offset);
1108
  }
1109
  void pinsrd(XMMRegister dst, const Operand& src, int8_t offset);
1110

    
1111
  // Parallel XMM operations.
1112
  void movntdqa(XMMRegister dst, const Operand& src);
1113
  void movntdq(const Operand& dst, XMMRegister src);
1114
  // Prefetch src position into cache level.
1115
  // Level 1, 2 or 3 specifies CPU cache level. Level 0 specifies a
1116
  // non-temporal
1117
  void prefetch(const Operand& src, int level);
1118
  // TODO(lrn): Need SFENCE for movnt?
1119

    
1120
  // Debugging
1121
  void Print();
1122

    
1123
  // Check the code size generated from label to here.
1124
  int SizeOfCodeGeneratedSince(Label* label) {
1125
    return pc_offset() - label->pos();
1126
  }
1127

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

    
1131
  // Mark address of a debug break slot.
1132
  void RecordDebugBreakSlot();
1133

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

    
1139
  // Writes a single byte or word of data in the code stream.  Used for
1140
  // inline tables, e.g., jump-tables.
1141
  void db(uint8_t data);
1142
  void dd(uint32_t data);
1143

    
1144
  // Check if there is less than kGap bytes available in the buffer.
1145
  // If this is the case, we need to grow the buffer before emitting
1146
  // an instruction or relocation information.
1147
  inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; }
1148

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

    
1152
  static bool IsNop(Address addr);
1153

    
1154
  PositionsRecorder* positions_recorder() { return &positions_recorder_; }
1155

    
1156
  int relocation_writer_size() {
1157
    return (buffer_ + buffer_size_) - reloc_info_writer.pos();
1158
  }
1159

    
1160
  // Avoid overflows for displacements etc.
1161
  static const int kMaximalBufferSize = 512*MB;
1162

    
1163
  byte byte_at(int pos) { return buffer_[pos]; }
1164
  void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
1165

    
1166
 protected:
1167
  void emit_sse_operand(XMMRegister reg, const Operand& adr);
1168
  void emit_sse_operand(XMMRegister dst, XMMRegister src);
1169
  void emit_sse_operand(Register dst, XMMRegister src);
1170
  void emit_sse_operand(XMMRegister dst, Register src);
1171

    
1172
  byte* addr_at(int pos) { return buffer_ + pos; }
1173

    
1174

    
1175
 private:
1176
  uint32_t long_at(int pos)  {
1177
    return *reinterpret_cast<uint32_t*>(addr_at(pos));
1178
  }
1179
  void long_at_put(int pos, uint32_t x)  {
1180
    *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
1181
  }
1182

    
1183
  // code emission
1184
  void GrowBuffer();
1185
  inline void emit(uint32_t x);
1186
  inline void emit(Handle<Object> handle);
1187
  inline void emit(uint32_t x,
1188
                   RelocInfo::Mode rmode,
1189
                   TypeFeedbackId id = TypeFeedbackId::None());
1190
  inline void emit(Handle<Code> code,
1191
                   RelocInfo::Mode rmode,
1192
                   TypeFeedbackId id = TypeFeedbackId::None());
1193
  inline void emit(const Immediate& x);
1194
  inline void emit_w(const Immediate& x);
1195

    
1196
  // Emit the code-object-relative offset of the label's position
1197
  inline void emit_code_relative_offset(Label* label);
1198

    
1199
  // instruction generation
1200
  void emit_arith_b(int op1, int op2, Register dst, int imm8);
1201

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

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

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

    
1212
  // labels
1213
  void print(Label* L);
1214
  void bind_to(Label* L, int pos);
1215

    
1216
  // displacements
1217
  inline Displacement disp_at(Label* L);
1218
  inline void disp_at_put(Label* L, Displacement disp);
1219
  inline void emit_disp(Label* L, Displacement::Type type);
1220
  inline void emit_near_disp(Label* L);
1221

    
1222
  // record reloc info for current pc_
1223
  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1224

    
1225
  friend class CodePatcher;
1226
  friend class EnsureSpace;
1227

    
1228
  // code generation
1229
  RelocInfoWriter reloc_info_writer;
1230

    
1231
  PositionsRecorder positions_recorder_;
1232
  friend class PositionsRecorder;
1233
};
1234

    
1235

    
1236
// Helper class that ensures that there is enough space for generating
1237
// instructions and relocation information.  The constructor makes
1238
// sure that there is enough space and (in debug mode) the destructor
1239
// checks that we did not generate too much.
1240
class EnsureSpace BASE_EMBEDDED {
1241
 public:
1242
  explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
1243
    if (assembler_->overflow()) assembler_->GrowBuffer();
1244
#ifdef DEBUG
1245
    space_before_ = assembler_->available_space();
1246
#endif
1247
  }
1248

    
1249
#ifdef DEBUG
1250
  ~EnsureSpace() {
1251
    int bytes_generated = space_before_ - assembler_->available_space();
1252
    ASSERT(bytes_generated < assembler_->kGap);
1253
  }
1254
#endif
1255

    
1256
 private:
1257
  Assembler* assembler_;
1258
#ifdef DEBUG
1259
  int space_before_;
1260
#endif
1261
};
1262

    
1263
} }  // namespace v8::internal
1264

    
1265
#endif  // V8_IA32_ASSEMBLER_IA32_H_