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 2006-2009 the V8 project authors. All rights reserved. 34 35 // A lightweight X64 Assembler. 36 37 #ifndef V8_X64_ASSEMBLER_X64_H_ 38 #define V8_X64_ASSEMBLER_X64_H_ 39 40 #include "serialize.h" 41 42 namespace v8 { 43 namespace internal { 44 45 // Utility functions 46 47 // Test whether a 64-bit value is in a specific range. 48 static inline bool is_uint32(int64_t x) { 49 static const int64_t kUInt32Mask = V8_INT64_C(0xffffffff); 50 return x == (x & kUInt32Mask); 51 } 52 53 static inline bool is_int32(int64_t x) { 54 static const int64_t kMinIntValue = V8_INT64_C(-0x80000000); 55 return is_uint32(x - kMinIntValue); 56 } 57 58 static inline bool uint_is_int32(uint64_t x) { 59 static const uint64_t kMaxIntValue = V8_UINT64_C(0x80000000); 60 return x < kMaxIntValue; 61 } 62 63 static inline bool is_uint32(uint64_t x) { 64 static const uint64_t kMaxUIntValue = V8_UINT64_C(0x100000000); 65 return x < kMaxUIntValue; 66 } 67 68 // CPU Registers. 69 // 70 // 1) We would prefer to use an enum, but enum values are assignment- 71 // compatible with int, which has caused code-generation bugs. 72 // 73 // 2) We would prefer to use a class instead of a struct but we don't like 74 // the register initialization to depend on the particular initialization 75 // order (which appears to be different on OS X, Linux, and Windows for the 76 // installed versions of C++ we tried). Using a struct permits C-style 77 // "initialization". Also, the Register objects cannot be const as this 78 // forces initialization stubs in MSVC, making us dependent on initialization 79 // order. 80 // 81 // 3) By not using an enum, we are possibly preventing the compiler from 82 // doing certain constant folds, which may significantly reduce the 83 // code generated for some assembly instructions (because they boil down 84 // to a few constants). If this is a problem, we could change the code 85 // such that we use an enum in optimized mode, and the struct in debug 86 // mode. This way we get the compile-time error checking in debug mode 87 // and best performance in optimized code. 88 // 89 90 struct Register { 91 static Register toRegister(int code) { 92 Register r = { code }; 93 return r; 94 } 95 bool is_valid() const { return 0 <= code_ && code_ < 16; } 96 bool is(Register reg) const { return code_ == reg.code_; } 97 int code() const { 98 ASSERT(is_valid()); 99 return code_; 100 } 101 int bit() const { 102 return 1 << code_; 103 } 104 105 // Return the high bit of the register code as a 0 or 1. Used often 106 // when constructing the REX prefix byte. 107 int high_bit() const { 108 return code_ >> 3; 109 } 110 // Return the 3 low bits of the register code. Used when encoding registers 111 // in modR/M, SIB, and opcode bytes. 112 int low_bits() const { 113 return code_ & 0x7; 114 } 115 116 // Unfortunately we can't make this private in a struct when initializing 117 // by assignment. 118 int code_; 119 }; 120 121 const Register rax = { 0 }; 122 const Register rcx = { 1 }; 123 const Register rdx = { 2 }; 124 const Register rbx = { 3 }; 125 const Register rsp = { 4 }; 126 const Register rbp = { 5 }; 127 const Register rsi = { 6 }; 128 const Register rdi = { 7 }; 129 const Register r8 = { 8 }; 130 const Register r9 = { 9 }; 131 const Register r10 = { 10 }; 132 const Register r11 = { 11 }; 133 const Register r12 = { 12 }; 134 const Register r13 = { 13 }; 135 const Register r14 = { 14 }; 136 const Register r15 = { 15 }; 137 const Register no_reg = { -1 }; 138 139 140 struct XMMRegister { 141 bool is_valid() const { return 0 <= code_ && code_ < 16; } 142 int code() const { 143 ASSERT(is_valid()); 144 return code_; 145 } 146 147 // Return the high bit of the register code as a 0 or 1. Used often 148 // when constructing the REX prefix byte. 149 int high_bit() const { 150 return code_ >> 3; 151 } 152 // Return the 3 low bits of the register code. Used when encoding registers 153 // in modR/M, SIB, and opcode bytes. 154 int low_bits() const { 155 return code_ & 0x7; 156 } 157 158 int code_; 159 }; 160 161 const XMMRegister xmm0 = { 0 }; 162 const XMMRegister xmm1 = { 1 }; 163 const XMMRegister xmm2 = { 2 }; 164 const XMMRegister xmm3 = { 3 }; 165 const XMMRegister xmm4 = { 4 }; 166 const XMMRegister xmm5 = { 5 }; 167 const XMMRegister xmm6 = { 6 }; 168 const XMMRegister xmm7 = { 7 }; 169 const XMMRegister xmm8 = { 8 }; 170 const XMMRegister xmm9 = { 9 }; 171 const XMMRegister xmm10 = { 10 }; 172 const XMMRegister xmm11 = { 11 }; 173 const XMMRegister xmm12 = { 12 }; 174 const XMMRegister xmm13 = { 13 }; 175 const XMMRegister xmm14 = { 14 }; 176 const XMMRegister xmm15 = { 15 }; 177 178 enum Condition { 179 // any value < 0 is considered no_condition 180 no_condition = -1, 181 182 overflow = 0, 183 no_overflow = 1, 184 below = 2, 185 above_equal = 3, 186 equal = 4, 187 not_equal = 5, 188 below_equal = 6, 189 above = 7, 190 negative = 8, 191 positive = 9, 192 parity_even = 10, 193 parity_odd = 11, 194 less = 12, 195 greater_equal = 13, 196 less_equal = 14, 197 greater = 15, 198 199 // Fake conditions that are handled by the 200 // opcodes using them. 201 always = 16, 202 never = 17, 203 // aliases 204 carry = below, 205 not_carry = above_equal, 206 zero = equal, 207 not_zero = not_equal, 208 sign = negative, 209 not_sign = positive, 210 last_condition = greater 211 }; 212 213 214 // Returns the equivalent of !cc. 215 // Negation of the default no_condition (-1) results in a non-default 216 // no_condition value (-2). As long as tests for no_condition check 217 // for condition < 0, this will work as expected. 218 inline Condition NegateCondition(Condition cc); 219 220 // Corresponds to transposing the operands of a comparison. 221 inline Condition ReverseCondition(Condition cc) { 222 switch (cc) { 223 case below: 224 return above; 225 case above: 226 return below; 227 case above_equal: 228 return below_equal; 229 case below_equal: 230 return above_equal; 231 case less: 232 return greater; 233 case greater: 234 return less; 235 case greater_equal: 236 return less_equal; 237 case less_equal: 238 return greater_equal; 239 default: 240 return cc; 241 }; 242 } 243 244 enum Hint { 245 no_hint = 0, 246 not_taken = 0x2e, 247 taken = 0x3e 248 }; 249 250 // The result of negating a hint is as if the corresponding condition 251 // were negated by NegateCondition. That is, no_hint is mapped to 252 // itself and not_taken and taken are mapped to each other. 253 inline Hint NegateHint(Hint hint) { 254 return (hint == no_hint) 255 ? no_hint 256 : ((hint == not_taken) ? taken : not_taken); 257 } 258 259 260 // ----------------------------------------------------------------------------- 261 // Machine instruction Immediates 262 263 class Immediate BASE_EMBEDDED { 264 public: 265 explicit Immediate(int32_t value) : value_(value) {} 266 267 private: 268 int32_t value_; 269 270 friend class Assembler; 271 }; 272 273 274 // ----------------------------------------------------------------------------- 275 // Machine instruction Operands 276 277 enum ScaleFactor { 278 times_1 = 0, 279 times_2 = 1, 280 times_4 = 2, 281 times_8 = 3, 282 times_int_size = times_4, 283 times_pointer_size = times_8 284 }; 285 286 287 class Operand BASE_EMBEDDED { 288 public: 289 // [base + disp/r] 290 Operand(Register base, int32_t disp); 291 292 // [base + index*scale + disp/r] 293 Operand(Register base, 294 Register index, 295 ScaleFactor scale, 296 int32_t disp); 297 298 // [index*scale + disp/r] 299 Operand(Register index, 300 ScaleFactor scale, 301 int32_t disp); 302 303 private: 304 byte rex_; 305 byte buf_[10]; 306 // The number of bytes in buf_. 307 unsigned int len_; 308 RelocInfo::Mode rmode_; 309 310 // Set the ModR/M byte without an encoded 'reg' register. The 311 // register is encoded later as part of the emit_operand operation. 312 // set_modrm can be called before or after set_sib and set_disp*. 313 inline void set_modrm(int mod, Register rm); 314 315 // Set the SIB byte if one is needed. Sets the length to 2 rather than 1. 316 inline void set_sib(ScaleFactor scale, Register index, Register base); 317 318 // Adds operand displacement fields (offsets added to the memory address). 319 // Needs to be called after set_sib, not before it. 320 inline void set_disp8(int disp); 321 inline void set_disp32(int disp); 322 323 friend class Assembler; 324 }; 325 326 327 // CpuFeatures keeps track of which features are supported by the target CPU. 328 // Supported features must be enabled by a Scope before use. 329 // Example: 330 // if (CpuFeatures::IsSupported(SSE3)) { 331 // CpuFeatures::Scope fscope(SSE3); 332 // // Generate SSE3 floating point code. 333 // } else { 334 // // Generate standard x87 or SSE2 floating point code. 335 // } 336 class CpuFeatures : public AllStatic { 337 public: 338 // Detect features of the target CPU. Set safe defaults if the serializer 339 // is enabled (snapshots must be portable). 340 static void Probe(); 341 // Check whether a feature is supported by the target CPU. 342 static bool IsSupported(CpuFeature f) { 343 if (f == SSE2 && !FLAG_enable_sse2) return false; 344 if (f == SSE3 && !FLAG_enable_sse3) return false; 345 if (f == CMOV && !FLAG_enable_cmov) return false; 346 if (f == RDTSC && !FLAG_enable_rdtsc) return false; 347 if (f == SAHF && !FLAG_enable_sahf) return false; 348 return (supported_ & (V8_UINT64_C(1) << f)) != 0; 349 } 350 // Check whether a feature is currently enabled. 351 static bool IsEnabled(CpuFeature f) { 352 return (enabled_ & (V8_UINT64_C(1) << f)) != 0; 353 } 354 // Enable a specified feature within a scope. 355 class Scope BASE_EMBEDDED { 356 #ifdef DEBUG 357 public: 358 explicit Scope(CpuFeature f) { 359 uint64_t mask = (V8_UINT64_C(1) << f); 360 ASSERT(CpuFeatures::IsSupported(f)); 361 ASSERT(!Serializer::enabled() || (found_by_runtime_probing_ & mask) == 0); 362 old_enabled_ = CpuFeatures::enabled_; 363 CpuFeatures::enabled_ |= mask; 364 } 365 ~Scope() { CpuFeatures::enabled_ = old_enabled_; } 366 private: 367 uint64_t old_enabled_; 368 #else 369 public: 370 explicit Scope(CpuFeature f) {} 371 #endif 372 }; 373 private: 374 // Safe defaults include SSE2 and CMOV for X64. It is always available, if 375 // anyone checks, but they shouldn't need to check. 376 static const uint64_t kDefaultCpuFeatures = (1 << SSE2 | 1 << CMOV); 377 static uint64_t supported_; 378 static uint64_t enabled_; 379 static uint64_t found_by_runtime_probing_; 380 }; 381 382 383 class Assembler : public Malloced { 384 private: 385 // We check before assembling an instruction that there is sufficient 386 // space to write an instruction and its relocation information. 387 // The relocation writer's position must be kGap bytes above the end of 388 // the generated instructions. This leaves enough space for the 389 // longest possible x64 instruction, 15 bytes, and the longest possible 390 // relocation information encoding, RelocInfoWriter::kMaxLength == 16. 391 // (There is a 15 byte limit on x64 instruction length that rules out some 392 // otherwise valid instructions.) 393 // This allows for a single, fast space check per instruction. 394 static const int kGap = 32; 395 396 public: 397 // Create an assembler. Instructions and relocation information are emitted 398 // into a buffer, with the instructions starting from the beginning and the 399 // relocation information starting from the end of the buffer. See CodeDesc 400 // for a detailed comment on the layout (globals.h). 401 // 402 // If the provided buffer is NULL, the assembler allocates and grows its own 403 // buffer, and buffer_size determines the initial buffer size. The buffer is 404 // owned by the assembler and deallocated upon destruction of the assembler. 405 // 406 // If the provided buffer is not NULL, the assembler uses the provided buffer 407 // for code generation and assumes its size to be buffer_size. If the buffer 408 // is too small, a fatal error occurs. No deallocation of the buffer is done 409 // upon destruction of the assembler. 410 Assembler(void* buffer, int buffer_size); 411 ~Assembler(); 412 413 // GetCode emits any pending (non-emitted) code and fills the descriptor 414 // desc. GetCode() is idempotent; it returns the same result if no other 415 // Assembler functions are invoked in between GetCode() calls. 416 void GetCode(CodeDesc* desc); 417 418 // Read/Modify the code target in the relative branch/call instruction at pc. 419 // On the x64 architecture, we use relative jumps with a 32-bit displacement 420 // to jump to other Code objects in the Code space in the heap. 421 // Jumps to C functions are done indirectly through a 64-bit register holding 422 // the absolute address of the target. 423 // These functions convert between absolute Addresses of Code objects and 424 // the relative displacements stored in the code. 425 static inline Address target_address_at(Address pc); 426 static inline void set_target_address_at(Address pc, Address target); 427 428 // This sets the branch destination (which is in the instruction on x64). 429 // This is for calls and branches within generated code. 430 inline static void set_target_at(Address instruction_payload, 431 Address target) { 432 set_target_address_at(instruction_payload, target); 433 } 434 435 // This sets the branch destination (which is a load instruction on x64). 436 // This is for calls and branches to runtime code. 437 inline static void set_external_target_at(Address instruction_payload, 438 Address target) { 439 *reinterpret_cast<Address*>(instruction_payload) = target; 440 } 441 442 inline Handle<Object> code_target_object_handle_at(Address pc); 443 // Number of bytes taken up by the branch target in the code. 444 static const int kCallTargetSize = 4; // Use 32-bit displacement. 445 static const int kExternalTargetSize = 8; // Use 64-bit absolute. 446 // Distance between the address of the code target in the call instruction 447 // and the return address pushed on the stack. 448 static const int kCallTargetAddressOffset = 4; // Use 32-bit displacement. 449 // Distance between the start of the JS return sequence and where the 450 // 32-bit displacement of a near call would be, relative to the pushed 451 // return address. TODO: Use return sequence length instead. 452 // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset; 453 static const int kPatchReturnSequenceAddressOffset = 13 - 4; 454 // TODO(X64): Rename this, removing the "Real", after changing the above. 455 static const int kRealPatchReturnSequenceAddressOffset = 2; 456 457 // The x64 JS return sequence is padded with int3 to make it large 458 // enough to hold a call instruction when the debugger patches it. 459 static const int kCallInstructionLength = 13; 460 static const int kJSReturnSequenceLength = 13; 461 462 // --------------------------------------------------------------------------- 463 // Code generation 464 // 465 // Function names correspond one-to-one to x64 instruction mnemonics. 466 // Unless specified otherwise, instructions operate on 64-bit operands. 467 // 468 // If we need versions of an assembly instruction that operate on different 469 // width arguments, we add a single-letter suffix specifying the width. 470 // This is done for the following instructions: mov, cmp, inc, dec, 471 // add, sub, and test. 472 // There are no versions of these instructions without the suffix. 473 // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'. 474 // - Instructions on 16-bit (word) operands/registers have a trailing 'w'. 475 // - Instructions on 32-bit (doubleword) operands/registers use 'l'. 476 // - Instructions on 64-bit (quadword) operands/registers use 'q'. 477 // 478 // Some mnemonics, such as "and", are the same as C++ keywords. 479 // Naming conflicts with C++ keywords are resolved by adding a trailing '_'. 480 481 // Insert the smallest number of nop instructions 482 // possible to align the pc offset to a multiple 483 // of m. m must be a power of 2. 484 void Align(int m); 485 486 // Stack 487 void pushfq(); 488 void popfq(); 489 490 void push(Immediate value); 491 void push(Register src); 492 void push(const Operand& src); 493 void push(Label* label, RelocInfo::Mode relocation_mode); 494 495 void pop(Register dst); 496 void pop(const Operand& dst); 497 498 void enter(Immediate size); 499 void leave(); 500 501 // Moves 502 void movb(Register dst, const Operand& src); 503 void movb(Register dst, Immediate imm); 504 void movb(const Operand& dst, Register src); 505 506 // Move the low 16 bits of a 64-bit register value to a 16-bit 507 // memory location. 508 void movw(const Operand& dst, Register src); 509 510 void movl(Register dst, Register src); 511 void movl(Register dst, const Operand& src); 512 void movl(const Operand& dst, Register src); 513 void movl(const Operand& dst, Immediate imm); 514 // Load a 32-bit immediate value, zero-extended to 64 bits. 515 void movl(Register dst, Immediate imm32); 516 517 // Move 64 bit register value to 64-bit memory location. 518 void movq(const Operand& dst, Register src); 519 // Move 64 bit memory location to 64-bit register value. 520 void movq(Register dst, const Operand& src); 521 void movq(Register dst, Register src); 522 // Sign extends immediate 32-bit value to 64 bits. 523 void movq(Register dst, Immediate x); 524 // Move the offset of the label location relative to the current 525 // position (after the move) to the destination. 526 void movl(const Operand& dst, Label* src); 527 528 // Move sign extended immediate to memory location. 529 void movq(const Operand& dst, Immediate value); 530 // New x64 instructions to load a 64-bit immediate into a register. 531 // All 64-bit immediates must have a relocation mode. 532 void movq(Register dst, void* ptr, RelocInfo::Mode rmode); 533 void movq(Register dst, int64_t value, RelocInfo::Mode rmode); 534 void movq(Register dst, const char* s, RelocInfo::Mode rmode); 535 // Moves the address of the external reference into the register. 536 void movq(Register dst, ExternalReference ext); 537 void movq(Register dst, Handle<Object> handle, RelocInfo::Mode rmode); 538 539 void movsxbq(Register dst, const Operand& src); 540 void movsxwq(Register dst, const Operand& src); 541 void movsxlq(Register dst, Register src); 542 void movsxlq(Register dst, const Operand& src); 543 void movzxbq(Register dst, const Operand& src); 544 void movzxbl(Register dst, const Operand& src); 545 void movzxwq(Register dst, const Operand& src); 546 void movzxwl(Register dst, const Operand& src); 547 548 // Repeated moves. 549 550 void repmovsb(); 551 void repmovsw(); 552 void repmovsl(); 553 void repmovsq(); 554 555 // New x64 instruction to load from an immediate 64-bit pointer into RAX. 556 void load_rax(void* ptr, RelocInfo::Mode rmode); 557 void load_rax(ExternalReference ext); 558 559 // Conditional moves. 560 void cmovq(Condition cc, Register dst, Register src); 561 void cmovq(Condition cc, Register dst, const Operand& src); 562 void cmovl(Condition cc, Register dst, Register src); 563 void cmovl(Condition cc, Register dst, const Operand& src); 564 565 // Exchange two registers 566 void xchg(Register dst, Register src); 567 568 // Arithmetics 569 void addl(Register dst, Register src) { 570 if (dst.low_bits() == 4) { // Forces SIB byte. 571 arithmetic_op_32(0x01, src, dst); 572 } else { 573 arithmetic_op_32(0x03, dst, src); 574 } 575 } 576 577 void addl(Register dst, Immediate src) { 578 immediate_arithmetic_op_32(0x0, dst, src); 579 } 580 581 void addl(Register dst, const Operand& src) { 582 arithmetic_op_32(0x03, dst, src); 583 } 584 585 void addl(const Operand& dst, Immediate src) { 586 immediate_arithmetic_op_32(0x0, dst, src); 587 } 588 589 void addq(Register dst, Register src) { 590 arithmetic_op(0x03, dst, src); 591 } 592 593 void addq(Register dst, const Operand& src) { 594 arithmetic_op(0x03, dst, src); 595 } 596 597 void addq(const Operand& dst, Register src) { 598 arithmetic_op(0x01, src, dst); 599 } 600 601 void addq(Register dst, Immediate src) { 602 immediate_arithmetic_op(0x0, dst, src); 603 } 604 605 void addq(const Operand& dst, Immediate src) { 606 immediate_arithmetic_op(0x0, dst, src); 607 } 608 609 void cmpb(Register dst, Immediate src) { 610 immediate_arithmetic_op_8(0x7, dst, src); 611 } 612 613 void cmpb_al(Immediate src); 614 615 void cmpb(Register dst, Register src) { 616 arithmetic_op(0x3A, dst, src); 617 } 618 619 void cmpb(Register dst, const Operand& src) { 620 arithmetic_op(0x3A, dst, src); 621 } 622 623 void cmpb(const Operand& dst, Register src) { 624 arithmetic_op(0x38, src, dst); 625 } 626 627 void cmpb(const Operand& dst, Immediate src) { 628 immediate_arithmetic_op_8(0x7, dst, src); 629 } 630 631 void cmpw(const Operand& dst, Immediate src) { 632 immediate_arithmetic_op_16(0x7, dst, src); 633 } 634 635 void cmpw(Register dst, Immediate src) { 636 immediate_arithmetic_op_16(0x7, dst, src); 637 } 638 639 void cmpw(Register dst, const Operand& src) { 640 arithmetic_op_16(0x3B, dst, src); 641 } 642 643 void cmpw(Register dst, Register src) { 644 arithmetic_op_16(0x3B, dst, src); 645 } 646 647 void cmpw(const Operand& dst, Register src) { 648 arithmetic_op_16(0x39, src, dst); 649 } 650 651 void cmpl(Register dst, Register src) { 652 arithmetic_op_32(0x3B, dst, src); 653 } 654 655 void cmpl(Register dst, const Operand& src) { 656 arithmetic_op_32(0x3B, dst, src); 657 } 658 659 void cmpl(const Operand& dst, Register src) { 660 arithmetic_op_32(0x39, src, dst); 661 } 662 663 void cmpl(Register dst, Immediate src) { 664 immediate_arithmetic_op_32(0x7, dst, src); 665 } 666 667 void cmpl(const Operand& dst, Immediate src) { 668 immediate_arithmetic_op_32(0x7, dst, src); 669 } 670 671 void cmpq(Register dst, Register src) { 672 arithmetic_op(0x3B, dst, src); 673 } 674 675 void cmpq(Register dst, const Operand& src) { 676 arithmetic_op(0x3B, dst, src); 677 } 678 679 void cmpq(const Operand& dst, Register src) { 680 arithmetic_op(0x39, src, dst); 681 } 682 683 void cmpq(Register dst, Immediate src) { 684 immediate_arithmetic_op(0x7, dst, src); 685 } 686 687 void cmpq(const Operand& dst, Immediate src) { 688 immediate_arithmetic_op(0x7, dst, src); 689 } 690 691 void and_(Register dst, Register src) { 692 arithmetic_op(0x23, dst, src); 693 } 694 695 void and_(Register dst, const Operand& src) { 696 arithmetic_op(0x23, dst, src); 697 } 698 699 void and_(const Operand& dst, Register src) { 700 arithmetic_op(0x21, src, dst); 701 } 702 703 void and_(Register dst, Immediate src) { 704 immediate_arithmetic_op(0x4, dst, src); 705 } 706 707 void and_(const Operand& dst, Immediate src) { 708 immediate_arithmetic_op(0x4, dst, src); 709 } 710 711 void andl(Register dst, Immediate src) { 712 immediate_arithmetic_op_32(0x4, dst, src); 713 } 714 715 void andl(Register dst, Register src) { 716 arithmetic_op_32(0x23, dst, src); 717 } 718 719 void andb(Register dst, Immediate src) { 720 immediate_arithmetic_op_8(0x4, dst, src); 721 } 722 723 void decq(Register dst); 724 void decq(const Operand& dst); 725 void decl(Register dst); 726 void decl(const Operand& dst); 727 void decb(Register dst); 728 void decb(const Operand& dst); 729 730 // Sign-extends rax into rdx:rax. 731 void cqo(); 732 // Sign-extends eax into edx:eax. 733 void cdq(); 734 735 // Divide rdx:rax by src. Quotient in rax, remainder in rdx. 736 void idivq(Register src); 737 // Divide edx:eax by lower 32 bits of src. Quotient in eax, rem. in edx. 738 void idivl(Register src); 739 740 // Signed multiply instructions. 741 void imul(Register src); // rdx:rax = rax * src. 742 void imul(Register dst, Register src); // dst = dst * src. 743 void imul(Register dst, const Operand& src); // dst = dst * src. 744 void imul(Register dst, Register src, Immediate imm); // dst = src * imm. 745 // Multiply 32 bit registers 746 void imull(Register dst, Register src); // dst = dst * src. 747 748 void incq(Register dst); 749 void incq(const Operand& dst); 750 void incl(const Operand& dst); 751 752 void lea(Register dst, const Operand& src); 753 754 // Multiply rax by src, put the result in rdx:rax. 755 void mul(Register src); 756 757 void neg(Register dst); 758 void neg(const Operand& dst); 759 void negl(Register dst); 760 761 void not_(Register dst); 762 void not_(const Operand& dst); 763 764 void or_(Register dst, Register src) { 765 arithmetic_op(0x0B, dst, src); 766 } 767 768 void orl(Register dst, Register src) { 769 arithmetic_op_32(0x0B, dst, src); 770 } 771 772 void or_(Register dst, const Operand& src) { 773 arithmetic_op(0x0B, dst, src); 774 } 775 776 void or_(const Operand& dst, Register src) { 777 arithmetic_op(0x09, src, dst); 778 } 779 780 void or_(Register dst, Immediate src) { 781 immediate_arithmetic_op(0x1, dst, src); 782 } 783 784 void orl(Register dst, Immediate src) { 785 immediate_arithmetic_op_32(0x1, dst, src); 786 } 787 788 void or_(const Operand& dst, Immediate src) { 789 immediate_arithmetic_op(0x1, dst, src); 790 } 791 792 void orl(const Operand& dst, Immediate src) { 793 immediate_arithmetic_op_32(0x1, dst, src); 794 } 795 796 797 void rcl(Register dst, Immediate imm8) { 798 shift(dst, imm8, 0x2); 799 } 800 801 void rol(Register dst, Immediate imm8) { 802 shift(dst, imm8, 0x0); 803 } 804 805 void rcr(Register dst, Immediate imm8) { 806 shift(dst, imm8, 0x3); 807 } 808 809 void ror(Register dst, Immediate imm8) { 810 shift(dst, imm8, 0x1); 811 } 812 813 // Shifts dst:src left by cl bits, affecting only dst. 814 void shld(Register dst, Register src); 815 816 // Shifts src:dst right by cl bits, affecting only dst. 817 void shrd(Register dst, Register src); 818 819 // Shifts dst right, duplicating sign bit, by shift_amount bits. 820 // Shifting by 1 is handled efficiently. 821 void sar(Register dst, Immediate shift_amount) { 822 shift(dst, shift_amount, 0x7); 823 } 824 825 // Shifts dst right, duplicating sign bit, by shift_amount bits. 826 // Shifting by 1 is handled efficiently. 827 void sarl(Register dst, Immediate shift_amount) { 828 shift_32(dst, shift_amount, 0x7); 829 } 830 831 // Shifts dst right, duplicating sign bit, by cl % 64 bits. 832 void sar_cl(Register dst) { 833 shift(dst, 0x7); 834 } 835 836 // Shifts dst right, duplicating sign bit, by cl % 64 bits. 837 void sarl_cl(Register dst) { 838 shift_32(dst, 0x7); 839 } 840 841 void shl(Register dst, Immediate shift_amount) { 842 shift(dst, shift_amount, 0x4); 843 } 844 845 void shl_cl(Register dst) { 846 shift(dst, 0x4); 847 } 848 849 void shll_cl(Register dst) { 850 shift_32(dst, 0x4); 851 } 852 853 void shll(Register dst, Immediate shift_amount) { 854 shift_32(dst, shift_amount, 0x4); 855 } 856 857 void shr(Register dst, Immediate shift_amount) { 858 shift(dst, shift_amount, 0x5); 859 } 860 861 void shr_cl(Register dst) { 862 shift(dst, 0x5); 863 } 864 865 void shrl_cl(Register dst) { 866 shift_32(dst, 0x5); 867 } 868 869 void shrl(Register dst, Immediate shift_amount) { 870 shift_32(dst, shift_amount, 0x5); 871 } 872 873 void store_rax(void* dst, RelocInfo::Mode mode); 874 void store_rax(ExternalReference ref); 875 876 void subq(Register dst, Register src) { 877 arithmetic_op(0x2B, dst, src); 878 } 879 880 void subq(Register dst, const Operand& src) { 881 arithmetic_op(0x2B, dst, src); 882 } 883 884 void subq(const Operand& dst, Register src) { 885 arithmetic_op(0x29, src, dst); 886 } 887 888 void subq(Register dst, Immediate src) { 889 immediate_arithmetic_op(0x5, dst, src); 890 } 891 892 void subq(const Operand& dst, Immediate src) { 893 immediate_arithmetic_op(0x5, dst, src); 894 } 895 896 void subl(Register dst, Register src) { 897 arithmetic_op_32(0x2B, dst, src); 898 } 899 900 void subl(Register dst, const Operand& src) { 901 arithmetic_op_32(0x2B, dst, src); 902 } 903 904 void subl(const Operand& dst, Immediate src) { 905 immediate_arithmetic_op_32(0x5, dst, src); 906 } 907 908 void subl(Register dst, Immediate src) { 909 immediate_arithmetic_op_32(0x5, dst, src); 910 } 911 912 void subb(Register dst, Immediate src) { 913 immediate_arithmetic_op_8(0x5, dst, src); 914 } 915 916 void testb(Register dst, Register src); 917 void testb(Register reg, Immediate mask); 918 void testb(const Operand& op, Immediate mask); 919 void testb(const Operand& op, Register reg); 920 void testl(Register dst, Register src); 921 void testl(Register reg, Immediate mask); 922 void testl(const Operand& op, Immediate mask); 923 void testq(const Operand& op, Register reg); 924 void testq(Register dst, Register src); 925 void testq(Register dst, Immediate mask); 926 927 void xor_(Register dst, Register src) { 928 if (dst.code() == src.code()) { 929 arithmetic_op_32(0x33, dst, src); 930 } else { 931 arithmetic_op(0x33, dst, src); 932 } 933 } 934 935 void xorl(Register dst, Register src) { 936 arithmetic_op_32(0x33, dst, src); 937 } 938 939 void xor_(Register dst, const Operand& src) { 940 arithmetic_op(0x33, dst, src); 941 } 942 943 void xor_(const Operand& dst, Register src) { 944 arithmetic_op(0x31, src, dst); 945 } 946 947 void xor_(Register dst, Immediate src) { 948 immediate_arithmetic_op(0x6, dst, src); 949 } 950 951 void xor_(const Operand& dst, Immediate src) { 952 immediate_arithmetic_op(0x6, dst, src); 953 } 954 955 // Bit operations. 956 void bt(const Operand& dst, Register src); 957 void bts(const Operand& dst, Register src); 958 959 // Miscellaneous 960 void clc(); 961 void cpuid(); 962 void hlt(); 963 void int3(); 964 void nop(); 965 void nop(int n); 966 void rdtsc(); 967 void ret(int imm16); 968 void setcc(Condition cc, Register reg); 969 970 // Label operations & relative jumps (PPUM Appendix D) 971 // 972 // Takes a branch opcode (cc) and a label (L) and generates 973 // either a backward branch or a forward branch and links it 974 // to the label fixup chain. Usage: 975 // 976 // Label L; // unbound label 977 // j(cc, &L); // forward branch to unbound label 978 // bind(&L); // bind label to the current pc 979 // j(cc, &L); // backward branch to bound label 980 // bind(&L); // illegal: a label may be bound only once 981 // 982 // Note: The same Label can be used for forward and backward branches 983 // but it may be bound only once. 984 985 void bind(Label* L); // binds an unbound label L to the current code position 986 987 // Calls 988 // Call near relative 32-bit displacement, relative to next instruction. 989 void call(Label* L); 990 void call(Handle<Code> target, RelocInfo::Mode rmode); 991 992 // Call near absolute indirect, address in register 993 void call(Register adr); 994 995 // Call near indirect 996 void call(const Operand& operand); 997 998 // Jumps 999 // Jump short or near relative. 1000 // Use a 32-bit signed displacement. 1001 void jmp(Label* L); // unconditional jump to L 1002 void jmp(Handle<Code> target, RelocInfo::Mode rmode); 1003 1004 // Jump near absolute indirect (r64) 1005 void jmp(Register adr); 1006 1007 // Jump near absolute indirect (m64) 1008 void jmp(const Operand& src); 1009 1010 // Conditional jumps 1011 void j(Condition cc, Label* L); 1012 void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode); 1013 1014 // Floating-point operations 1015 void fld(int i); 1016 1017 void fld1(); 1018 void fldz(); 1019 1020 void fld_s(const Operand& adr); 1021 void fld_d(const Operand& adr); 1022 1023 void fstp_s(const Operand& adr); 1024 void fstp_d(const Operand& adr); 1025 void fstp(int index); 1026 1027 void fild_s(const Operand& adr); 1028 void fild_d(const Operand& adr); 1029 1030 void fist_s(const Operand& adr); 1031 1032 void fistp_s(const Operand& adr); 1033 void fistp_d(const Operand& adr); 1034 1035 void fisttp_s(const Operand& adr); 1036 void fisttp_d(const Operand& adr); 1037 1038 void fabs(); 1039 void fchs(); 1040 1041 void fadd(int i); 1042 void fsub(int i); 1043 void fmul(int i); 1044 void fdiv(int i); 1045 1046 void fisub_s(const Operand& adr); 1047 1048 void faddp(int i = 1); 1049 void fsubp(int i = 1); 1050 void fsubrp(int i = 1); 1051 void fmulp(int i = 1); 1052 void fdivp(int i = 1); 1053 void fprem(); 1054 void fprem1(); 1055 1056 void fxch(int i = 1); 1057 void fincstp(); 1058 void ffree(int i = 0); 1059 1060 void ftst(); 1061 void fucomp(int i); 1062 void fucompp(); 1063 void fucomi(int i); 1064 void fucomip(); 1065 1066 void fcompp(); 1067 void fnstsw_ax(); 1068 void fwait(); 1069 void fnclex(); 1070 1071 void fsin(); 1072 void fcos(); 1073 1074 void frndint(); 1075 1076 void sahf(); 1077 1078 // SSE2 instructions 1079 void movsd(const Operand& dst, XMMRegister src); 1080 void movsd(XMMRegister src, XMMRegister dst); 1081 void movsd(XMMRegister src, const Operand& dst); 1082 1083 void cvttss2si(Register dst, const Operand& src); 1084 void cvttsd2si(Register dst, const Operand& src); 1085 1086 void cvtlsi2sd(XMMRegister dst, const Operand& src); 1087 void cvtlsi2sd(XMMRegister dst, Register src); 1088 void cvtqsi2sd(XMMRegister dst, const Operand& src); 1089 void cvtqsi2sd(XMMRegister dst, Register src); 1090 1091 void addsd(XMMRegister dst, XMMRegister src); 1092 void subsd(XMMRegister dst, XMMRegister src); 1093 void mulsd(XMMRegister dst, XMMRegister src); 1094 void divsd(XMMRegister dst, XMMRegister src); 1095 1096 void xorpd(XMMRegister dst, XMMRegister src); 1097 1098 void comisd(XMMRegister dst, XMMRegister src); 1099 void ucomisd(XMMRegister dst, XMMRegister src); 1100 1101 void emit_sse_operand(XMMRegister dst, XMMRegister src); 1102 void emit_sse_operand(XMMRegister reg, const Operand& adr); 1103 void emit_sse_operand(XMMRegister dst, Register src); 1104 1105 // Use either movsd or movlpd. 1106 // void movdbl(XMMRegister dst, const Operand& src); 1107 // void movdbl(const Operand& dst, XMMRegister src); 1108 1109 // Debugging 1110 void Print(); 1111 1112 // Check the code size generated from label to here. 1113 int SizeOfCodeGeneratedSince(Label* l) { return pc_offset() - l->pos(); } 1114 1115 // Mark address of the ExitJSFrame code. 1116 void RecordJSReturn(); 1117 1118 // Record a comment relocation entry that can be used by a disassembler. 1119 // Use --debug_code to enable. 1120 void RecordComment(const char* msg); 1121 1122 void RecordPosition(int pos); 1123 void RecordStatementPosition(int pos); 1124 void WriteRecordedPositions(); 1125 1126 int pc_offset() const { return static_cast<int>(pc_ - buffer_); } 1127 int current_statement_position() const { return current_statement_position_; } 1128 int current_position() const { return current_position_; } 1129 1130 // Check if there is less than kGap bytes available in the buffer. 1131 // If this is the case, we need to grow the buffer before emitting 1132 // an instruction or relocation information. 1133 inline bool buffer_overflow() const { 1134 return pc_ >= reloc_info_writer.pos() - kGap; 1135 } 1136 1137 // Get the number of bytes available in the buffer. 1138 inline int available_space() const { 1139 return static_cast<int>(reloc_info_writer.pos() - pc_); 1140 } 1141 1142 // Avoid overflows for displacements etc. 1143 static const int kMaximalBufferSize = 512*MB; 1144 static const int kMinimalBufferSize = 4*KB; 1145 1146 private: 1147 byte* addr_at(int pos) { return buffer_ + pos; } 1148 byte byte_at(int pos) { return buffer_[pos]; } 1149 uint32_t long_at(int pos) { 1150 return *reinterpret_cast<uint32_t*>(addr_at(pos)); 1151 } 1152 void long_at_put(int pos, uint32_t x) { 1153 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x; 1154 } 1155 1156 // code emission 1157 void GrowBuffer(); 1158 1159 void emit(byte x) { *pc_++ = x; } 1160 inline void emitl(uint32_t x); 1161 inline void emitq(uint64_t x, RelocInfo::Mode rmode); 1162 inline void emitw(uint16_t x); 1163 inline void emit_code_target(Handle<Code> target, RelocInfo::Mode rmode); 1164 void emit(Immediate x) { emitl(x.value_); } 1165 1166 // Emits a REX prefix that encodes a 64-bit operand size and 1167 // the top bit of both register codes. 1168 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B. 1169 // REX.W is set. 1170 inline void emit_rex_64(Register reg, Register rm_reg); 1171 inline void emit_rex_64(XMMRegister reg, Register rm_reg); 1172 1173 // Emits a REX prefix that encodes a 64-bit operand size and 1174 // the top bit of the destination, index, and base register codes. 1175 // The high bit of reg is used for REX.R, the high bit of op's base 1176 // register is used for REX.B, and the high bit of op's index register 1177 // is used for REX.X. REX.W is set. 1178 inline void emit_rex_64(Register reg, const Operand& op); 1179 inline void emit_rex_64(XMMRegister reg, const Operand& op); 1180 1181 // Emits a REX prefix that encodes a 64-bit operand size and 1182 // the top bit of the register code. 1183 // The high bit of register is used for REX.B. 1184 // REX.W is set and REX.R and REX.X are clear. 1185 inline void emit_rex_64(Register rm_reg); 1186 1187 // Emits a REX prefix that encodes a 64-bit operand size and 1188 // the top bit of the index and base register codes. 1189 // The high bit of op's base register is used for REX.B, and the high 1190 // bit of op's index register is used for REX.X. 1191 // REX.W is set and REX.R clear. 1192 inline void emit_rex_64(const Operand& op); 1193 1194 // Emit a REX prefix that only sets REX.W to choose a 64-bit operand size. 1195 void emit_rex_64() { emit(0x48); } 1196 1197 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B. 1198 // REX.W is clear. 1199 inline void emit_rex_32(Register reg, Register rm_reg); 1200 1201 // The high bit of reg is used for REX.R, the high bit of op's base 1202 // register is used for REX.B, and the high bit of op's index register 1203 // is used for REX.X. REX.W is cleared. 1204 inline void emit_rex_32(Register reg, const Operand& op); 1205 1206 // High bit of rm_reg goes to REX.B. 1207 // REX.W, REX.R and REX.X are clear. 1208 inline void emit_rex_32(Register rm_reg); 1209 1210 // High bit of base goes to REX.B and high bit of index to REX.X. 1211 // REX.W and REX.R are clear. 1212 inline void emit_rex_32(const Operand& op); 1213 1214 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B. 1215 // REX.W is cleared. If no REX bits are set, no byte is emitted. 1216 inline void emit_optional_rex_32(Register reg, Register rm_reg); 1217 1218 // The high bit of reg is used for REX.R, the high bit of op's base 1219 // register is used for REX.B, and the high bit of op's index register 1220 // is used for REX.X. REX.W is cleared. If no REX bits are set, nothing 1221 // is emitted. 1222 inline void emit_optional_rex_32(Register reg, const Operand& op); 1223 1224 // As for emit_optional_rex_32(Register, Register), except that 1225 // the registers are XMM registers. 1226 inline void emit_optional_rex_32(XMMRegister reg, XMMRegister base); 1227 1228 // As for emit_optional_rex_32(Register, Register), except that 1229 // the registers are XMM registers. 1230 inline void emit_optional_rex_32(XMMRegister reg, Register base); 1231 1232 // As for emit_optional_rex_32(Register, const Operand&), except that 1233 // the register is an XMM register. 1234 inline void emit_optional_rex_32(XMMRegister reg, const Operand& op); 1235 1236 // Optionally do as emit_rex_32(Register) if the register number has 1237 // the high bit set. 1238 inline void emit_optional_rex_32(Register rm_reg); 1239 1240 // Optionally do as emit_rex_32(const Operand&) if the operand register 1241 // numbers have a high bit set. 1242 inline void emit_optional_rex_32(const Operand& op); 1243 1244 1245 // Emit the ModR/M byte, and optionally the SIB byte and 1246 // 1- or 4-byte offset for a memory operand. Also encodes 1247 // the second operand of the operation, a register or operation 1248 // subcode, into the reg field of the ModR/M byte. 1249 void emit_operand(Register reg, const Operand& adr) { 1250 emit_operand(reg.low_bits(), adr); 1251 } 1252 1253 // Emit the ModR/M byte, and optionally the SIB byte and 1254 // 1- or 4-byte offset for a memory operand. Also used to encode 1255 // a three-bit opcode extension into the ModR/M byte. 1256 void emit_operand(int rm, const Operand& adr); 1257 1258 // Emit a ModR/M byte with registers coded in the reg and rm_reg fields. 1259 void emit_modrm(Register reg, Register rm_reg) { 1260 emit(0xC0 | reg.low_bits() << 3 | rm_reg.low_bits()); 1261 } 1262 1263 // Emit a ModR/M byte with an operation subcode in the reg field and 1264 // a register in the rm_reg field. 1265 void emit_modrm(int code, Register rm_reg) { 1266 ASSERT(is_uint3(code)); 1267 emit(0xC0 | code << 3 | rm_reg.low_bits()); 1268 } 1269 1270 // Emit the code-object-relative offset of the label's position 1271 inline void emit_code_relative_offset(Label* label); 1272 1273 // Emit machine code for one of the operations ADD, ADC, SUB, SBC, 1274 // AND, OR, XOR, or CMP. The encodings of these operations are all 1275 // similar, differing just in the opcode or in the reg field of the 1276 // ModR/M byte. 1277 void arithmetic_op_16(byte opcode, Register reg, Register rm_reg); 1278 void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg); 1279 void arithmetic_op_32(byte opcode, Register reg, Register rm_reg); 1280 void arithmetic_op_32(byte opcode, Register reg, const Operand& rm_reg); 1281 void arithmetic_op(byte opcode, Register reg, Register rm_reg); 1282 void arithmetic_op(byte opcode, Register reg, const Operand& rm_reg); 1283 void immediate_arithmetic_op(byte subcode, Register dst, Immediate src); 1284 void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate src); 1285 // Operate on a byte in memory or register. 1286 void immediate_arithmetic_op_8(byte subcode, 1287 Register dst, 1288 Immediate src); 1289 void immediate_arithmetic_op_8(byte subcode, 1290 const Operand& dst, 1291 Immediate src); 1292 // Operate on a word in memory or register. 1293 void immediate_arithmetic_op_16(byte subcode, 1294 Register dst, 1295 Immediate src); 1296 void immediate_arithmetic_op_16(byte subcode, 1297 const Operand& dst, 1298 Immediate src); 1299 // Operate on a 32-bit word in memory or register. 1300 void immediate_arithmetic_op_32(byte subcode, 1301 Register dst, 1302 Immediate src); 1303 void immediate_arithmetic_op_32(byte subcode, 1304 const Operand& dst, 1305 Immediate src); 1306 1307 // Emit machine code for a shift operation. 1308 void shift(Register dst, Immediate shift_amount, int subcode); 1309 void shift_32(Register dst, Immediate shift_amount, int subcode); 1310 // Shift dst by cl % 64 bits. 1311 void shift(Register dst, int subcode); 1312 void shift_32(Register dst, int subcode); 1313 1314 void emit_farith(int b1, int b2, int i); 1315 1316 // labels 1317 // void print(Label* L); 1318 void bind_to(Label* L, int pos); 1319 void link_to(Label* L, Label* appendix); 1320 1321 // record reloc info for current pc_ 1322 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); 1323 1324 friend class CodePatcher; 1325 friend class EnsureSpace; 1326 friend class RegExpMacroAssemblerX64; 1327 1328 // Code buffer: 1329 // The buffer into which code and relocation info are generated. 1330 byte* buffer_; 1331 int buffer_size_; 1332 // True if the assembler owns the buffer, false if buffer is external. 1333 bool own_buffer_; 1334 // A previously allocated buffer of kMinimalBufferSize bytes, or NULL. 1335 static byte* spare_buffer_; 1336 1337 // code generation 1338 byte* pc_; // the program counter; moves forward 1339 RelocInfoWriter reloc_info_writer; 1340 1341 List< Handle<Code> > code_targets_; 1342 // push-pop elimination 1343 byte* last_pc_; 1344 1345 // source position information 1346 int current_statement_position_; 1347 int current_position_; 1348 int written_statement_position_; 1349 int written_position_; 1350 }; 1351 1352 1353 // Helper class that ensures that there is enough space for generating 1354 // instructions and relocation information. The constructor makes 1355 // sure that there is enough space and (in debug mode) the destructor 1356 // checks that we did not generate too much. 1357 class EnsureSpace BASE_EMBEDDED { 1358 public: 1359 explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) { 1360 if (assembler_->buffer_overflow()) assembler_->GrowBuffer(); 1361 #ifdef DEBUG 1362 space_before_ = assembler_->available_space(); 1363 #endif 1364 } 1365 1366 #ifdef DEBUG 1367 ~EnsureSpace() { 1368 int bytes_generated = space_before_ - assembler_->available_space(); 1369 ASSERT(bytes_generated < assembler_->kGap); 1370 } 1371 #endif 1372 1373 private: 1374 Assembler* assembler_; 1375 #ifdef DEBUG 1376 int space_before_; 1377 #endif 1378 }; 1379 1380 } } // namespace v8::internal 1381 1382 #endif // V8_X64_ASSEMBLER_X64_H_ 1383