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