Home | History | Annotate | Download | only in x64
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/v8.h"
      6 
      7 #if V8_TARGET_ARCH_X64
      8 
      9 #include "src/base/bits.h"
     10 #include "src/base/division-by-constant.h"
     11 #include "src/bootstrapper.h"
     12 #include "src/codegen.h"
     13 #include "src/cpu-profiler.h"
     14 #include "src/debug.h"
     15 #include "src/heap/heap.h"
     16 #include "src/isolate-inl.h"
     17 #include "src/serialize.h"
     18 #include "src/x64/assembler-x64.h"
     19 #include "src/x64/macro-assembler-x64.h"
     20 
     21 namespace v8 {
     22 namespace internal {
     23 
     24 MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size)
     25     : Assembler(arg_isolate, buffer, size),
     26       generating_stub_(false),
     27       has_frame_(false),
     28       root_array_available_(true) {
     29   if (isolate() != NULL) {
     30     code_object_ = Handle<Object>(isolate()->heap()->undefined_value(),
     31                                   isolate());
     32   }
     33 }
     34 
     35 
     36 static const int64_t kInvalidRootRegisterDelta = -1;
     37 
     38 
     39 int64_t MacroAssembler::RootRegisterDelta(ExternalReference other) {
     40   if (predictable_code_size() &&
     41       (other.address() < reinterpret_cast<Address>(isolate()) ||
     42        other.address() >= reinterpret_cast<Address>(isolate() + 1))) {
     43     return kInvalidRootRegisterDelta;
     44   }
     45   Address roots_register_value = kRootRegisterBias +
     46       reinterpret_cast<Address>(isolate()->heap()->roots_array_start());
     47 
     48   int64_t delta = kInvalidRootRegisterDelta;  // Bogus initialization.
     49   if (kPointerSize == kInt64Size) {
     50     delta = other.address() - roots_register_value;
     51   } else {
     52     // For x32, zero extend the address to 64-bit and calculate the delta.
     53     uint64_t o = static_cast<uint32_t>(
     54         reinterpret_cast<intptr_t>(other.address()));
     55     uint64_t r = static_cast<uint32_t>(
     56         reinterpret_cast<intptr_t>(roots_register_value));
     57     delta = o - r;
     58   }
     59   return delta;
     60 }
     61 
     62 
     63 Operand MacroAssembler::ExternalOperand(ExternalReference target,
     64                                         Register scratch) {
     65   if (root_array_available_ && !serializer_enabled()) {
     66     int64_t delta = RootRegisterDelta(target);
     67     if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
     68       return Operand(kRootRegister, static_cast<int32_t>(delta));
     69     }
     70   }
     71   Move(scratch, target);
     72   return Operand(scratch, 0);
     73 }
     74 
     75 
     76 void MacroAssembler::Load(Register destination, ExternalReference source) {
     77   if (root_array_available_ && !serializer_enabled()) {
     78     int64_t delta = RootRegisterDelta(source);
     79     if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
     80       movp(destination, Operand(kRootRegister, static_cast<int32_t>(delta)));
     81       return;
     82     }
     83   }
     84   // Safe code.
     85   if (destination.is(rax)) {
     86     load_rax(source);
     87   } else {
     88     Move(kScratchRegister, source);
     89     movp(destination, Operand(kScratchRegister, 0));
     90   }
     91 }
     92 
     93 
     94 void MacroAssembler::Store(ExternalReference destination, Register source) {
     95   if (root_array_available_ && !serializer_enabled()) {
     96     int64_t delta = RootRegisterDelta(destination);
     97     if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
     98       movp(Operand(kRootRegister, static_cast<int32_t>(delta)), source);
     99       return;
    100     }
    101   }
    102   // Safe code.
    103   if (source.is(rax)) {
    104     store_rax(destination);
    105   } else {
    106     Move(kScratchRegister, destination);
    107     movp(Operand(kScratchRegister, 0), source);
    108   }
    109 }
    110 
    111 
    112 void MacroAssembler::LoadAddress(Register destination,
    113                                  ExternalReference source) {
    114   if (root_array_available_ && !serializer_enabled()) {
    115     int64_t delta = RootRegisterDelta(source);
    116     if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
    117       leap(destination, Operand(kRootRegister, static_cast<int32_t>(delta)));
    118       return;
    119     }
    120   }
    121   // Safe code.
    122   Move(destination, source);
    123 }
    124 
    125 
    126 int MacroAssembler::LoadAddressSize(ExternalReference source) {
    127   if (root_array_available_ && !serializer_enabled()) {
    128     // This calculation depends on the internals of LoadAddress.
    129     // It's correctness is ensured by the asserts in the Call
    130     // instruction below.
    131     int64_t delta = RootRegisterDelta(source);
    132     if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
    133       // Operand is leap(scratch, Operand(kRootRegister, delta));
    134       // Opcodes : REX.W 8D ModRM Disp8/Disp32  - 4 or 7.
    135       int size = 4;
    136       if (!is_int8(static_cast<int32_t>(delta))) {
    137         size += 3;  // Need full four-byte displacement in lea.
    138       }
    139       return size;
    140     }
    141   }
    142   // Size of movp(destination, src);
    143   return Assembler::kMoveAddressIntoScratchRegisterInstructionLength;
    144 }
    145 
    146 
    147 void MacroAssembler::PushAddress(ExternalReference source) {
    148   int64_t address = reinterpret_cast<int64_t>(source.address());
    149   if (is_int32(address) && !serializer_enabled()) {
    150     if (emit_debug_code()) {
    151       Move(kScratchRegister, kZapValue, Assembler::RelocInfoNone());
    152     }
    153     Push(Immediate(static_cast<int32_t>(address)));
    154     return;
    155   }
    156   LoadAddress(kScratchRegister, source);
    157   Push(kScratchRegister);
    158 }
    159 
    160 
    161 void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
    162   DCHECK(root_array_available_);
    163   movp(destination, Operand(kRootRegister,
    164                             (index << kPointerSizeLog2) - kRootRegisterBias));
    165 }
    166 
    167 
    168 void MacroAssembler::LoadRootIndexed(Register destination,
    169                                      Register variable_offset,
    170                                      int fixed_offset) {
    171   DCHECK(root_array_available_);
    172   movp(destination,
    173        Operand(kRootRegister,
    174                variable_offset, times_pointer_size,
    175                (fixed_offset << kPointerSizeLog2) - kRootRegisterBias));
    176 }
    177 
    178 
    179 void MacroAssembler::StoreRoot(Register source, Heap::RootListIndex index) {
    180   DCHECK(root_array_available_);
    181   movp(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias),
    182        source);
    183 }
    184 
    185 
    186 void MacroAssembler::PushRoot(Heap::RootListIndex index) {
    187   DCHECK(root_array_available_);
    188   Push(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias));
    189 }
    190 
    191 
    192 void MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) {
    193   DCHECK(root_array_available_);
    194   cmpp(with, Operand(kRootRegister,
    195                      (index << kPointerSizeLog2) - kRootRegisterBias));
    196 }
    197 
    198 
    199 void MacroAssembler::CompareRoot(const Operand& with,
    200                                  Heap::RootListIndex index) {
    201   DCHECK(root_array_available_);
    202   DCHECK(!with.AddressUsesRegister(kScratchRegister));
    203   LoadRoot(kScratchRegister, index);
    204   cmpp(with, kScratchRegister);
    205 }
    206 
    207 
    208 void MacroAssembler::RememberedSetHelper(Register object,  // For debug tests.
    209                                          Register addr,
    210                                          Register scratch,
    211                                          SaveFPRegsMode save_fp,
    212                                          RememberedSetFinalAction and_then) {
    213   if (emit_debug_code()) {
    214     Label ok;
    215     JumpIfNotInNewSpace(object, scratch, &ok, Label::kNear);
    216     int3();
    217     bind(&ok);
    218   }
    219   // Load store buffer top.
    220   LoadRoot(scratch, Heap::kStoreBufferTopRootIndex);
    221   // Store pointer to buffer.
    222   movp(Operand(scratch, 0), addr);
    223   // Increment buffer top.
    224   addp(scratch, Immediate(kPointerSize));
    225   // Write back new top of buffer.
    226   StoreRoot(scratch, Heap::kStoreBufferTopRootIndex);
    227   // Call stub on end of buffer.
    228   Label done;
    229   // Check for end of buffer.
    230   testp(scratch, Immediate(StoreBuffer::kStoreBufferOverflowBit));
    231   if (and_then == kReturnAtEnd) {
    232     Label buffer_overflowed;
    233     j(not_equal, &buffer_overflowed, Label::kNear);
    234     ret(0);
    235     bind(&buffer_overflowed);
    236   } else {
    237     DCHECK(and_then == kFallThroughAtEnd);
    238     j(equal, &done, Label::kNear);
    239   }
    240   StoreBufferOverflowStub store_buffer_overflow(isolate(), save_fp);
    241   CallStub(&store_buffer_overflow);
    242   if (and_then == kReturnAtEnd) {
    243     ret(0);
    244   } else {
    245     DCHECK(and_then == kFallThroughAtEnd);
    246     bind(&done);
    247   }
    248 }
    249 
    250 
    251 void MacroAssembler::InNewSpace(Register object,
    252                                 Register scratch,
    253                                 Condition cc,
    254                                 Label* branch,
    255                                 Label::Distance distance) {
    256   if (serializer_enabled()) {
    257     // Can't do arithmetic on external references if it might get serialized.
    258     // The mask isn't really an address.  We load it as an external reference in
    259     // case the size of the new space is different between the snapshot maker
    260     // and the running system.
    261     if (scratch.is(object)) {
    262       Move(kScratchRegister, ExternalReference::new_space_mask(isolate()));
    263       andp(scratch, kScratchRegister);
    264     } else {
    265       Move(scratch, ExternalReference::new_space_mask(isolate()));
    266       andp(scratch, object);
    267     }
    268     Move(kScratchRegister, ExternalReference::new_space_start(isolate()));
    269     cmpp(scratch, kScratchRegister);
    270     j(cc, branch, distance);
    271   } else {
    272     DCHECK(kPointerSize == kInt64Size
    273         ? is_int32(static_cast<int64_t>(isolate()->heap()->NewSpaceMask()))
    274         : kPointerSize == kInt32Size);
    275     intptr_t new_space_start =
    276         reinterpret_cast<intptr_t>(isolate()->heap()->NewSpaceStart());
    277     Move(kScratchRegister, reinterpret_cast<Address>(-new_space_start),
    278          Assembler::RelocInfoNone());
    279     if (scratch.is(object)) {
    280       addp(scratch, kScratchRegister);
    281     } else {
    282       leap(scratch, Operand(object, kScratchRegister, times_1, 0));
    283     }
    284     andp(scratch,
    285          Immediate(static_cast<int32_t>(isolate()->heap()->NewSpaceMask())));
    286     j(cc, branch, distance);
    287   }
    288 }
    289 
    290 
    291 void MacroAssembler::RecordWriteField(
    292     Register object,
    293     int offset,
    294     Register value,
    295     Register dst,
    296     SaveFPRegsMode save_fp,
    297     RememberedSetAction remembered_set_action,
    298     SmiCheck smi_check,
    299     PointersToHereCheck pointers_to_here_check_for_value) {
    300   // First, check if a write barrier is even needed. The tests below
    301   // catch stores of Smis.
    302   Label done;
    303 
    304   // Skip barrier if writing a smi.
    305   if (smi_check == INLINE_SMI_CHECK) {
    306     JumpIfSmi(value, &done);
    307   }
    308 
    309   // Although the object register is tagged, the offset is relative to the start
    310   // of the object, so so offset must be a multiple of kPointerSize.
    311   DCHECK(IsAligned(offset, kPointerSize));
    312 
    313   leap(dst, FieldOperand(object, offset));
    314   if (emit_debug_code()) {
    315     Label ok;
    316     testb(dst, Immediate((1 << kPointerSizeLog2) - 1));
    317     j(zero, &ok, Label::kNear);
    318     int3();
    319     bind(&ok);
    320   }
    321 
    322   RecordWrite(object, dst, value, save_fp, remembered_set_action,
    323               OMIT_SMI_CHECK, pointers_to_here_check_for_value);
    324 
    325   bind(&done);
    326 
    327   // Clobber clobbered input registers when running with the debug-code flag
    328   // turned on to provoke errors.
    329   if (emit_debug_code()) {
    330     Move(value, kZapValue, Assembler::RelocInfoNone());
    331     Move(dst, kZapValue, Assembler::RelocInfoNone());
    332   }
    333 }
    334 
    335 
    336 void MacroAssembler::RecordWriteArray(
    337     Register object,
    338     Register value,
    339     Register index,
    340     SaveFPRegsMode save_fp,
    341     RememberedSetAction remembered_set_action,
    342     SmiCheck smi_check,
    343     PointersToHereCheck pointers_to_here_check_for_value) {
    344   // First, check if a write barrier is even needed. The tests below
    345   // catch stores of Smis.
    346   Label done;
    347 
    348   // Skip barrier if writing a smi.
    349   if (smi_check == INLINE_SMI_CHECK) {
    350     JumpIfSmi(value, &done);
    351   }
    352 
    353   // Array access: calculate the destination address. Index is not a smi.
    354   Register dst = index;
    355   leap(dst, Operand(object, index, times_pointer_size,
    356                    FixedArray::kHeaderSize - kHeapObjectTag));
    357 
    358   RecordWrite(object, dst, value, save_fp, remembered_set_action,
    359               OMIT_SMI_CHECK, pointers_to_here_check_for_value);
    360 
    361   bind(&done);
    362 
    363   // Clobber clobbered input registers when running with the debug-code flag
    364   // turned on to provoke errors.
    365   if (emit_debug_code()) {
    366     Move(value, kZapValue, Assembler::RelocInfoNone());
    367     Move(index, kZapValue, Assembler::RelocInfoNone());
    368   }
    369 }
    370 
    371 
    372 void MacroAssembler::RecordWriteForMap(Register object,
    373                                        Register map,
    374                                        Register dst,
    375                                        SaveFPRegsMode fp_mode) {
    376   DCHECK(!object.is(kScratchRegister));
    377   DCHECK(!object.is(map));
    378   DCHECK(!object.is(dst));
    379   DCHECK(!map.is(dst));
    380   AssertNotSmi(object);
    381 
    382   if (emit_debug_code()) {
    383     Label ok;
    384     if (map.is(kScratchRegister)) pushq(map);
    385     CompareMap(map, isolate()->factory()->meta_map());
    386     if (map.is(kScratchRegister)) popq(map);
    387     j(equal, &ok, Label::kNear);
    388     int3();
    389     bind(&ok);
    390   }
    391 
    392   if (!FLAG_incremental_marking) {
    393     return;
    394   }
    395 
    396   if (emit_debug_code()) {
    397     Label ok;
    398     if (map.is(kScratchRegister)) pushq(map);
    399     cmpp(map, FieldOperand(object, HeapObject::kMapOffset));
    400     if (map.is(kScratchRegister)) popq(map);
    401     j(equal, &ok, Label::kNear);
    402     int3();
    403     bind(&ok);
    404   }
    405 
    406   // Compute the address.
    407   leap(dst, FieldOperand(object, HeapObject::kMapOffset));
    408 
    409   // First, check if a write barrier is even needed. The tests below
    410   // catch stores of smis and stores into the young generation.
    411   Label done;
    412 
    413   // A single check of the map's pages interesting flag suffices, since it is
    414   // only set during incremental collection, and then it's also guaranteed that
    415   // the from object's page's interesting flag is also set.  This optimization
    416   // relies on the fact that maps can never be in new space.
    417   CheckPageFlag(map,
    418                 map,  // Used as scratch.
    419                 MemoryChunk::kPointersToHereAreInterestingMask,
    420                 zero,
    421                 &done,
    422                 Label::kNear);
    423 
    424   RecordWriteStub stub(isolate(), object, map, dst, OMIT_REMEMBERED_SET,
    425                        fp_mode);
    426   CallStub(&stub);
    427 
    428   bind(&done);
    429 
    430   // Count number of write barriers in generated code.
    431   isolate()->counters()->write_barriers_static()->Increment();
    432   IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
    433 
    434   // Clobber clobbered registers when running with the debug-code flag
    435   // turned on to provoke errors.
    436   if (emit_debug_code()) {
    437     Move(dst, kZapValue, Assembler::RelocInfoNone());
    438     Move(map, kZapValue, Assembler::RelocInfoNone());
    439   }
    440 }
    441 
    442 
    443 void MacroAssembler::RecordWrite(
    444     Register object,
    445     Register address,
    446     Register value,
    447     SaveFPRegsMode fp_mode,
    448     RememberedSetAction remembered_set_action,
    449     SmiCheck smi_check,
    450     PointersToHereCheck pointers_to_here_check_for_value) {
    451   DCHECK(!object.is(value));
    452   DCHECK(!object.is(address));
    453   DCHECK(!value.is(address));
    454   AssertNotSmi(object);
    455 
    456   if (remembered_set_action == OMIT_REMEMBERED_SET &&
    457       !FLAG_incremental_marking) {
    458     return;
    459   }
    460 
    461   if (emit_debug_code()) {
    462     Label ok;
    463     cmpp(value, Operand(address, 0));
    464     j(equal, &ok, Label::kNear);
    465     int3();
    466     bind(&ok);
    467   }
    468 
    469   // First, check if a write barrier is even needed. The tests below
    470   // catch stores of smis and stores into the young generation.
    471   Label done;
    472 
    473   if (smi_check == INLINE_SMI_CHECK) {
    474     // Skip barrier if writing a smi.
    475     JumpIfSmi(value, &done);
    476   }
    477 
    478   if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) {
    479     CheckPageFlag(value,
    480                   value,  // Used as scratch.
    481                   MemoryChunk::kPointersToHereAreInterestingMask,
    482                   zero,
    483                   &done,
    484                   Label::kNear);
    485   }
    486 
    487   CheckPageFlag(object,
    488                 value,  // Used as scratch.
    489                 MemoryChunk::kPointersFromHereAreInterestingMask,
    490                 zero,
    491                 &done,
    492                 Label::kNear);
    493 
    494   RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
    495                        fp_mode);
    496   CallStub(&stub);
    497 
    498   bind(&done);
    499 
    500   // Count number of write barriers in generated code.
    501   isolate()->counters()->write_barriers_static()->Increment();
    502   IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
    503 
    504   // Clobber clobbered registers when running with the debug-code flag
    505   // turned on to provoke errors.
    506   if (emit_debug_code()) {
    507     Move(address, kZapValue, Assembler::RelocInfoNone());
    508     Move(value, kZapValue, Assembler::RelocInfoNone());
    509   }
    510 }
    511 
    512 
    513 void MacroAssembler::Assert(Condition cc, BailoutReason reason) {
    514   if (emit_debug_code()) Check(cc, reason);
    515 }
    516 
    517 
    518 void MacroAssembler::AssertFastElements(Register elements) {
    519   if (emit_debug_code()) {
    520     Label ok;
    521     CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
    522                 Heap::kFixedArrayMapRootIndex);
    523     j(equal, &ok, Label::kNear);
    524     CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
    525                 Heap::kFixedDoubleArrayMapRootIndex);
    526     j(equal, &ok, Label::kNear);
    527     CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
    528                 Heap::kFixedCOWArrayMapRootIndex);
    529     j(equal, &ok, Label::kNear);
    530     Abort(kJSObjectWithFastElementsMapHasSlowElements);
    531     bind(&ok);
    532   }
    533 }
    534 
    535 
    536 void MacroAssembler::Check(Condition cc, BailoutReason reason) {
    537   Label L;
    538   j(cc, &L, Label::kNear);
    539   Abort(reason);
    540   // Control will not return here.
    541   bind(&L);
    542 }
    543 
    544 
    545 void MacroAssembler::CheckStackAlignment() {
    546   int frame_alignment = base::OS::ActivationFrameAlignment();
    547   int frame_alignment_mask = frame_alignment - 1;
    548   if (frame_alignment > kPointerSize) {
    549     DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
    550     Label alignment_as_expected;
    551     testp(rsp, Immediate(frame_alignment_mask));
    552     j(zero, &alignment_as_expected, Label::kNear);
    553     // Abort if stack is not aligned.
    554     int3();
    555     bind(&alignment_as_expected);
    556   }
    557 }
    558 
    559 
    560 void MacroAssembler::NegativeZeroTest(Register result,
    561                                       Register op,
    562                                       Label* then_label) {
    563   Label ok;
    564   testl(result, result);
    565   j(not_zero, &ok, Label::kNear);
    566   testl(op, op);
    567   j(sign, then_label);
    568   bind(&ok);
    569 }
    570 
    571 
    572 void MacroAssembler::Abort(BailoutReason reason) {
    573 #ifdef DEBUG
    574   const char* msg = GetBailoutReason(reason);
    575   if (msg != NULL) {
    576     RecordComment("Abort message: ");
    577     RecordComment(msg);
    578   }
    579 
    580   if (FLAG_trap_on_abort) {
    581     int3();
    582     return;
    583   }
    584 #endif
    585 
    586   Move(kScratchRegister, Smi::FromInt(static_cast<int>(reason)),
    587        Assembler::RelocInfoNone());
    588   Push(kScratchRegister);
    589 
    590   if (!has_frame_) {
    591     // We don't actually want to generate a pile of code for this, so just
    592     // claim there is a stack frame, without generating one.
    593     FrameScope scope(this, StackFrame::NONE);
    594     CallRuntime(Runtime::kAbort, 1);
    595   } else {
    596     CallRuntime(Runtime::kAbort, 1);
    597   }
    598   // Control will not return here.
    599   int3();
    600 }
    601 
    602 
    603 void MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) {
    604   DCHECK(AllowThisStubCall(stub));  // Calls are not allowed in some stubs
    605   Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id);
    606 }
    607 
    608 
    609 void MacroAssembler::TailCallStub(CodeStub* stub) {
    610   Jump(stub->GetCode(), RelocInfo::CODE_TARGET);
    611 }
    612 
    613 
    614 void MacroAssembler::StubReturn(int argc) {
    615   DCHECK(argc >= 1 && generating_stub());
    616   ret((argc - 1) * kPointerSize);
    617 }
    618 
    619 
    620 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
    621   return has_frame_ || !stub->SometimesSetsUpAFrame();
    622 }
    623 
    624 
    625 void MacroAssembler::IndexFromHash(Register hash, Register index) {
    626   // The assert checks that the constants for the maximum number of digits
    627   // for an array index cached in the hash field and the number of bits
    628   // reserved for it does not conflict.
    629   DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
    630          (1 << String::kArrayIndexValueBits));
    631   if (!hash.is(index)) {
    632     movl(index, hash);
    633   }
    634   DecodeFieldToSmi<String::ArrayIndexValueBits>(index);
    635 }
    636 
    637 
    638 void MacroAssembler::CallRuntime(const Runtime::Function* f,
    639                                  int num_arguments,
    640                                  SaveFPRegsMode save_doubles) {
    641   // If the expected number of arguments of the runtime function is
    642   // constant, we check that the actual number of arguments match the
    643   // expectation.
    644   CHECK(f->nargs < 0 || f->nargs == num_arguments);
    645 
    646   // TODO(1236192): Most runtime routines don't need the number of
    647   // arguments passed in because it is constant. At some point we
    648   // should remove this need and make the runtime routine entry code
    649   // smarter.
    650   Set(rax, num_arguments);
    651   LoadAddress(rbx, ExternalReference(f, isolate()));
    652   CEntryStub ces(isolate(), f->result_size, save_doubles);
    653   CallStub(&ces);
    654 }
    655 
    656 
    657 void MacroAssembler::CallExternalReference(const ExternalReference& ext,
    658                                            int num_arguments) {
    659   Set(rax, num_arguments);
    660   LoadAddress(rbx, ext);
    661 
    662   CEntryStub stub(isolate(), 1);
    663   CallStub(&stub);
    664 }
    665 
    666 
    667 void MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
    668                                                int num_arguments,
    669                                                int result_size) {
    670   // ----------- S t a t e -------------
    671   //  -- rsp[0]                 : return address
    672   //  -- rsp[8]                 : argument num_arguments - 1
    673   //  ...
    674   //  -- rsp[8 * num_arguments] : argument 0 (receiver)
    675   // -----------------------------------
    676 
    677   // TODO(1236192): Most runtime routines don't need the number of
    678   // arguments passed in because it is constant. At some point we
    679   // should remove this need and make the runtime routine entry code
    680   // smarter.
    681   Set(rax, num_arguments);
    682   JumpToExternalReference(ext, result_size);
    683 }
    684 
    685 
    686 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
    687                                      int num_arguments,
    688                                      int result_size) {
    689   TailCallExternalReference(ExternalReference(fid, isolate()),
    690                             num_arguments,
    691                             result_size);
    692 }
    693 
    694 
    695 static int Offset(ExternalReference ref0, ExternalReference ref1) {
    696   int64_t offset = (ref0.address() - ref1.address());
    697   // Check that fits into int.
    698   DCHECK(static_cast<int>(offset) == offset);
    699   return static_cast<int>(offset);
    700 }
    701 
    702 
    703 void MacroAssembler::PrepareCallApiFunction(int arg_stack_space) {
    704   EnterApiExitFrame(arg_stack_space);
    705 }
    706 
    707 
    708 void MacroAssembler::CallApiFunctionAndReturn(
    709     Register function_address,
    710     ExternalReference thunk_ref,
    711     Register thunk_last_arg,
    712     int stack_space,
    713     Operand return_value_operand,
    714     Operand* context_restore_operand) {
    715   Label prologue;
    716   Label promote_scheduled_exception;
    717   Label exception_handled;
    718   Label delete_allocated_handles;
    719   Label leave_exit_frame;
    720   Label write_back;
    721 
    722   Factory* factory = isolate()->factory();
    723   ExternalReference next_address =
    724       ExternalReference::handle_scope_next_address(isolate());
    725   const int kNextOffset = 0;
    726   const int kLimitOffset = Offset(
    727       ExternalReference::handle_scope_limit_address(isolate()),
    728       next_address);
    729   const int kLevelOffset = Offset(
    730       ExternalReference::handle_scope_level_address(isolate()),
    731       next_address);
    732   ExternalReference scheduled_exception_address =
    733       ExternalReference::scheduled_exception_address(isolate());
    734 
    735   DCHECK(rdx.is(function_address) || r8.is(function_address));
    736   // Allocate HandleScope in callee-save registers.
    737   Register prev_next_address_reg = r14;
    738   Register prev_limit_reg = rbx;
    739   Register base_reg = r15;
    740   Move(base_reg, next_address);
    741   movp(prev_next_address_reg, Operand(base_reg, kNextOffset));
    742   movp(prev_limit_reg, Operand(base_reg, kLimitOffset));
    743   addl(Operand(base_reg, kLevelOffset), Immediate(1));
    744 
    745   if (FLAG_log_timer_events) {
    746     FrameScope frame(this, StackFrame::MANUAL);
    747     PushSafepointRegisters();
    748     PrepareCallCFunction(1);
    749     LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate()));
    750     CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1);
    751     PopSafepointRegisters();
    752   }
    753 
    754 
    755   Label profiler_disabled;
    756   Label end_profiler_check;
    757   Move(rax, ExternalReference::is_profiling_address(isolate()));
    758   cmpb(Operand(rax, 0), Immediate(0));
    759   j(zero, &profiler_disabled);
    760 
    761   // Third parameter is the address of the actual getter function.
    762   Move(thunk_last_arg, function_address);
    763   Move(rax, thunk_ref);
    764   jmp(&end_profiler_check);
    765 
    766   bind(&profiler_disabled);
    767   // Call the api function!
    768   Move(rax, function_address);
    769 
    770   bind(&end_profiler_check);
    771 
    772   // Call the api function!
    773   call(rax);
    774 
    775   if (FLAG_log_timer_events) {
    776     FrameScope frame(this, StackFrame::MANUAL);
    777     PushSafepointRegisters();
    778     PrepareCallCFunction(1);
    779     LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate()));
    780     CallCFunction(ExternalReference::log_leave_external_function(isolate()), 1);
    781     PopSafepointRegisters();
    782   }
    783 
    784   // Load the value from ReturnValue
    785   movp(rax, return_value_operand);
    786   bind(&prologue);
    787 
    788   // No more valid handles (the result handle was the last one). Restore
    789   // previous handle scope.
    790   subl(Operand(base_reg, kLevelOffset), Immediate(1));
    791   movp(Operand(base_reg, kNextOffset), prev_next_address_reg);
    792   cmpp(prev_limit_reg, Operand(base_reg, kLimitOffset));
    793   j(not_equal, &delete_allocated_handles);
    794   bind(&leave_exit_frame);
    795 
    796   // Check if the function scheduled an exception.
    797   Move(rsi, scheduled_exception_address);
    798   Cmp(Operand(rsi, 0), factory->the_hole_value());
    799   j(not_equal, &promote_scheduled_exception);
    800   bind(&exception_handled);
    801 
    802 #if ENABLE_EXTRA_CHECKS
    803   // Check if the function returned a valid JavaScript value.
    804   Label ok;
    805   Register return_value = rax;
    806   Register map = rcx;
    807 
    808   JumpIfSmi(return_value, &ok, Label::kNear);
    809   movp(map, FieldOperand(return_value, HeapObject::kMapOffset));
    810 
    811   CmpInstanceType(map, FIRST_NONSTRING_TYPE);
    812   j(below, &ok, Label::kNear);
    813 
    814   CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
    815   j(above_equal, &ok, Label::kNear);
    816 
    817   CompareRoot(map, Heap::kHeapNumberMapRootIndex);
    818   j(equal, &ok, Label::kNear);
    819 
    820   CompareRoot(return_value, Heap::kUndefinedValueRootIndex);
    821   j(equal, &ok, Label::kNear);
    822 
    823   CompareRoot(return_value, Heap::kTrueValueRootIndex);
    824   j(equal, &ok, Label::kNear);
    825 
    826   CompareRoot(return_value, Heap::kFalseValueRootIndex);
    827   j(equal, &ok, Label::kNear);
    828 
    829   CompareRoot(return_value, Heap::kNullValueRootIndex);
    830   j(equal, &ok, Label::kNear);
    831 
    832   Abort(kAPICallReturnedInvalidObject);
    833 
    834   bind(&ok);
    835 #endif
    836 
    837   bool restore_context = context_restore_operand != NULL;
    838   if (restore_context) {
    839     movp(rsi, *context_restore_operand);
    840   }
    841   LeaveApiExitFrame(!restore_context);
    842   ret(stack_space * kPointerSize);
    843 
    844   bind(&promote_scheduled_exception);
    845   {
    846     FrameScope frame(this, StackFrame::INTERNAL);
    847     CallRuntime(Runtime::kPromoteScheduledException, 0);
    848   }
    849   jmp(&exception_handled);
    850 
    851   // HandleScope limit has changed. Delete allocated extensions.
    852   bind(&delete_allocated_handles);
    853   movp(Operand(base_reg, kLimitOffset), prev_limit_reg);
    854   movp(prev_limit_reg, rax);
    855   LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate()));
    856   LoadAddress(rax,
    857               ExternalReference::delete_handle_scope_extensions(isolate()));
    858   call(rax);
    859   movp(rax, prev_limit_reg);
    860   jmp(&leave_exit_frame);
    861 }
    862 
    863 
    864 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext,
    865                                              int result_size) {
    866   // Set the entry point and jump to the C entry runtime stub.
    867   LoadAddress(rbx, ext);
    868   CEntryStub ces(isolate(), result_size);
    869   jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
    870 }
    871 
    872 
    873 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
    874                                    InvokeFlag flag,
    875                                    const CallWrapper& call_wrapper) {
    876   // You can't call a builtin without a valid frame.
    877   DCHECK(flag == JUMP_FUNCTION || has_frame());
    878 
    879   // Rely on the assertion to check that the number of provided
    880   // arguments match the expected number of arguments. Fake a
    881   // parameter count to avoid emitting code to do the check.
    882   ParameterCount expected(0);
    883   GetBuiltinEntry(rdx, id);
    884   InvokeCode(rdx, expected, expected, flag, call_wrapper);
    885 }
    886 
    887 
    888 void MacroAssembler::GetBuiltinFunction(Register target,
    889                                         Builtins::JavaScript id) {
    890   // Load the builtins object into target register.
    891   movp(target, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
    892   movp(target, FieldOperand(target, GlobalObject::kBuiltinsOffset));
    893   movp(target, FieldOperand(target,
    894                             JSBuiltinsObject::OffsetOfFunctionWithId(id)));
    895 }
    896 
    897 
    898 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
    899   DCHECK(!target.is(rdi));
    900   // Load the JavaScript builtin function from the builtins object.
    901   GetBuiltinFunction(rdi, id);
    902   movp(target, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
    903 }
    904 
    905 
    906 #define REG(Name) { kRegister_ ## Name ## _Code }
    907 
    908 static const Register saved_regs[] = {
    909   REG(rax), REG(rcx), REG(rdx), REG(rbx), REG(rbp), REG(rsi), REG(rdi), REG(r8),
    910   REG(r9), REG(r10), REG(r11)
    911 };
    912 
    913 #undef REG
    914 
    915 static const int kNumberOfSavedRegs = sizeof(saved_regs) / sizeof(Register);
    916 
    917 
    918 void MacroAssembler::PushCallerSaved(SaveFPRegsMode fp_mode,
    919                                      Register exclusion1,
    920                                      Register exclusion2,
    921                                      Register exclusion3) {
    922   // We don't allow a GC during a store buffer overflow so there is no need to
    923   // store the registers in any particular way, but we do have to store and
    924   // restore them.
    925   for (int i = 0; i < kNumberOfSavedRegs; i++) {
    926     Register reg = saved_regs[i];
    927     if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) {
    928       pushq(reg);
    929     }
    930   }
    931   // R12 to r15 are callee save on all platforms.
    932   if (fp_mode == kSaveFPRegs) {
    933     subp(rsp, Immediate(kDoubleSize * XMMRegister::kMaxNumRegisters));
    934     for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
    935       XMMRegister reg = XMMRegister::from_code(i);
    936       movsd(Operand(rsp, i * kDoubleSize), reg);
    937     }
    938   }
    939 }
    940 
    941 
    942 void MacroAssembler::PopCallerSaved(SaveFPRegsMode fp_mode,
    943                                     Register exclusion1,
    944                                     Register exclusion2,
    945                                     Register exclusion3) {
    946   if (fp_mode == kSaveFPRegs) {
    947     for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
    948       XMMRegister reg = XMMRegister::from_code(i);
    949       movsd(reg, Operand(rsp, i * kDoubleSize));
    950     }
    951     addp(rsp, Immediate(kDoubleSize * XMMRegister::kMaxNumRegisters));
    952   }
    953   for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) {
    954     Register reg = saved_regs[i];
    955     if (!reg.is(exclusion1) && !reg.is(exclusion2) && !reg.is(exclusion3)) {
    956       popq(reg);
    957     }
    958   }
    959 }
    960 
    961 
    962 void MacroAssembler::Cvtlsi2sd(XMMRegister dst, Register src) {
    963   xorps(dst, dst);
    964   cvtlsi2sd(dst, src);
    965 }
    966 
    967 
    968 void MacroAssembler::Cvtlsi2sd(XMMRegister dst, const Operand& src) {
    969   xorps(dst, dst);
    970   cvtlsi2sd(dst, src);
    971 }
    972 
    973 
    974 void MacroAssembler::Load(Register dst, const Operand& src, Representation r) {
    975   DCHECK(!r.IsDouble());
    976   if (r.IsInteger8()) {
    977     movsxbq(dst, src);
    978   } else if (r.IsUInteger8()) {
    979     movzxbl(dst, src);
    980   } else if (r.IsInteger16()) {
    981     movsxwq(dst, src);
    982   } else if (r.IsUInteger16()) {
    983     movzxwl(dst, src);
    984   } else if (r.IsInteger32()) {
    985     movl(dst, src);
    986   } else {
    987     movp(dst, src);
    988   }
    989 }
    990 
    991 
    992 void MacroAssembler::Store(const Operand& dst, Register src, Representation r) {
    993   DCHECK(!r.IsDouble());
    994   if (r.IsInteger8() || r.IsUInteger8()) {
    995     movb(dst, src);
    996   } else if (r.IsInteger16() || r.IsUInteger16()) {
    997     movw(dst, src);
    998   } else if (r.IsInteger32()) {
    999     movl(dst, src);
   1000   } else {
   1001     if (r.IsHeapObject()) {
   1002       AssertNotSmi(src);
   1003     } else if (r.IsSmi()) {
   1004       AssertSmi(src);
   1005     }
   1006     movp(dst, src);
   1007   }
   1008 }
   1009 
   1010 
   1011 void MacroAssembler::Set(Register dst, int64_t x) {
   1012   if (x == 0) {
   1013     xorl(dst, dst);
   1014   } else if (is_uint32(x)) {
   1015     movl(dst, Immediate(static_cast<uint32_t>(x)));
   1016   } else if (is_int32(x)) {
   1017     movq(dst, Immediate(static_cast<int32_t>(x)));
   1018   } else {
   1019     movq(dst, x);
   1020   }
   1021 }
   1022 
   1023 
   1024 void MacroAssembler::Set(const Operand& dst, intptr_t x) {
   1025   if (kPointerSize == kInt64Size) {
   1026     if (is_int32(x)) {
   1027       movp(dst, Immediate(static_cast<int32_t>(x)));
   1028     } else {
   1029       Set(kScratchRegister, x);
   1030       movp(dst, kScratchRegister);
   1031     }
   1032   } else {
   1033     movp(dst, Immediate(static_cast<int32_t>(x)));
   1034   }
   1035 }
   1036 
   1037 
   1038 // ----------------------------------------------------------------------------
   1039 // Smi tagging, untagging and tag detection.
   1040 
   1041 bool MacroAssembler::IsUnsafeInt(const int32_t x) {
   1042   static const int kMaxBits = 17;
   1043   return !is_intn(x, kMaxBits);
   1044 }
   1045 
   1046 
   1047 void MacroAssembler::SafeMove(Register dst, Smi* src) {
   1048   DCHECK(!dst.is(kScratchRegister));
   1049   if (IsUnsafeInt(src->value()) && jit_cookie() != 0) {
   1050     if (SmiValuesAre32Bits()) {
   1051       // JIT cookie can be converted to Smi.
   1052       Move(dst, Smi::FromInt(src->value() ^ jit_cookie()));
   1053       Move(kScratchRegister, Smi::FromInt(jit_cookie()));
   1054       xorp(dst, kScratchRegister);
   1055     } else {
   1056       DCHECK(SmiValuesAre31Bits());
   1057       int32_t value = static_cast<int32_t>(reinterpret_cast<intptr_t>(src));
   1058       movp(dst, Immediate(value ^ jit_cookie()));
   1059       xorp(dst, Immediate(jit_cookie()));
   1060     }
   1061   } else {
   1062     Move(dst, src);
   1063   }
   1064 }
   1065 
   1066 
   1067 void MacroAssembler::SafePush(Smi* src) {
   1068   if (IsUnsafeInt(src->value()) && jit_cookie() != 0) {
   1069     if (SmiValuesAre32Bits()) {
   1070       // JIT cookie can be converted to Smi.
   1071       Push(Smi::FromInt(src->value() ^ jit_cookie()));
   1072       Move(kScratchRegister, Smi::FromInt(jit_cookie()));
   1073       xorp(Operand(rsp, 0), kScratchRegister);
   1074     } else {
   1075       DCHECK(SmiValuesAre31Bits());
   1076       int32_t value = static_cast<int32_t>(reinterpret_cast<intptr_t>(src));
   1077       Push(Immediate(value ^ jit_cookie()));
   1078       xorp(Operand(rsp, 0), Immediate(jit_cookie()));
   1079     }
   1080   } else {
   1081     Push(src);
   1082   }
   1083 }
   1084 
   1085 
   1086 Register MacroAssembler::GetSmiConstant(Smi* source) {
   1087   int value = source->value();
   1088   if (value == 0) {
   1089     xorl(kScratchRegister, kScratchRegister);
   1090     return kScratchRegister;
   1091   }
   1092   if (value == 1) {
   1093     return kSmiConstantRegister;
   1094   }
   1095   LoadSmiConstant(kScratchRegister, source);
   1096   return kScratchRegister;
   1097 }
   1098 
   1099 
   1100 void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) {
   1101   if (emit_debug_code()) {
   1102     Move(dst, Smi::FromInt(kSmiConstantRegisterValue),
   1103          Assembler::RelocInfoNone());
   1104     cmpp(dst, kSmiConstantRegister);
   1105     Assert(equal, kUninitializedKSmiConstantRegister);
   1106   }
   1107   int value = source->value();
   1108   if (value == 0) {
   1109     xorl(dst, dst);
   1110     return;
   1111   }
   1112   bool negative = value < 0;
   1113   unsigned int uvalue = negative ? -value : value;
   1114 
   1115   switch (uvalue) {
   1116     case 9:
   1117       leap(dst,
   1118            Operand(kSmiConstantRegister, kSmiConstantRegister, times_8, 0));
   1119       break;
   1120     case 8:
   1121       xorl(dst, dst);
   1122       leap(dst, Operand(dst, kSmiConstantRegister, times_8, 0));
   1123       break;
   1124     case 4:
   1125       xorl(dst, dst);
   1126       leap(dst, Operand(dst, kSmiConstantRegister, times_4, 0));
   1127       break;
   1128     case 5:
   1129       leap(dst,
   1130            Operand(kSmiConstantRegister, kSmiConstantRegister, times_4, 0));
   1131       break;
   1132     case 3:
   1133       leap(dst,
   1134            Operand(kSmiConstantRegister, kSmiConstantRegister, times_2, 0));
   1135       break;
   1136     case 2:
   1137       leap(dst,
   1138            Operand(kSmiConstantRegister, kSmiConstantRegister, times_1, 0));
   1139       break;
   1140     case 1:
   1141       movp(dst, kSmiConstantRegister);
   1142       break;
   1143     case 0:
   1144       UNREACHABLE();
   1145       return;
   1146     default:
   1147       Move(dst, source, Assembler::RelocInfoNone());
   1148       return;
   1149   }
   1150   if (negative) {
   1151     negp(dst);
   1152   }
   1153 }
   1154 
   1155 
   1156 void MacroAssembler::Integer32ToSmi(Register dst, Register src) {
   1157   STATIC_ASSERT(kSmiTag == 0);
   1158   if (!dst.is(src)) {
   1159     movl(dst, src);
   1160   }
   1161   shlp(dst, Immediate(kSmiShift));
   1162 }
   1163 
   1164 
   1165 void MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) {
   1166   if (emit_debug_code()) {
   1167     testb(dst, Immediate(0x01));
   1168     Label ok;
   1169     j(zero, &ok, Label::kNear);
   1170     Abort(kInteger32ToSmiFieldWritingToNonSmiLocation);
   1171     bind(&ok);
   1172   }
   1173 
   1174   if (SmiValuesAre32Bits()) {
   1175     DCHECK(kSmiShift % kBitsPerByte == 0);
   1176     movl(Operand(dst, kSmiShift / kBitsPerByte), src);
   1177   } else {
   1178     DCHECK(SmiValuesAre31Bits());
   1179     Integer32ToSmi(kScratchRegister, src);
   1180     movp(dst, kScratchRegister);
   1181   }
   1182 }
   1183 
   1184 
   1185 void MacroAssembler::Integer64PlusConstantToSmi(Register dst,
   1186                                                 Register src,
   1187                                                 int constant) {
   1188   if (dst.is(src)) {
   1189     addl(dst, Immediate(constant));
   1190   } else {
   1191     leal(dst, Operand(src, constant));
   1192   }
   1193   shlp(dst, Immediate(kSmiShift));
   1194 }
   1195 
   1196 
   1197 void MacroAssembler::SmiToInteger32(Register dst, Register src) {
   1198   STATIC_ASSERT(kSmiTag == 0);
   1199   if (!dst.is(src)) {
   1200     movp(dst, src);
   1201   }
   1202 
   1203   if (SmiValuesAre32Bits()) {
   1204     shrp(dst, Immediate(kSmiShift));
   1205   } else {
   1206     DCHECK(SmiValuesAre31Bits());
   1207     sarl(dst, Immediate(kSmiShift));
   1208   }
   1209 }
   1210 
   1211 
   1212 void MacroAssembler::SmiToInteger32(Register dst, const Operand& src) {
   1213   if (SmiValuesAre32Bits()) {
   1214     movl(dst, Operand(src, kSmiShift / kBitsPerByte));
   1215   } else {
   1216     DCHECK(SmiValuesAre31Bits());
   1217     movl(dst, src);
   1218     sarl(dst, Immediate(kSmiShift));
   1219   }
   1220 }
   1221 
   1222 
   1223 void MacroAssembler::SmiToInteger64(Register dst, Register src) {
   1224   STATIC_ASSERT(kSmiTag == 0);
   1225   if (!dst.is(src)) {
   1226     movp(dst, src);
   1227   }
   1228   sarp(dst, Immediate(kSmiShift));
   1229   if (kPointerSize == kInt32Size) {
   1230     // Sign extend to 64-bit.
   1231     movsxlq(dst, dst);
   1232   }
   1233 }
   1234 
   1235 
   1236 void MacroAssembler::SmiToInteger64(Register dst, const Operand& src) {
   1237   if (SmiValuesAre32Bits()) {
   1238     movsxlq(dst, Operand(src, kSmiShift / kBitsPerByte));
   1239   } else {
   1240     DCHECK(SmiValuesAre31Bits());
   1241     movp(dst, src);
   1242     SmiToInteger64(dst, dst);
   1243   }
   1244 }
   1245 
   1246 
   1247 void MacroAssembler::SmiTest(Register src) {
   1248   AssertSmi(src);
   1249   testp(src, src);
   1250 }
   1251 
   1252 
   1253 void MacroAssembler::SmiCompare(Register smi1, Register smi2) {
   1254   AssertSmi(smi1);
   1255   AssertSmi(smi2);
   1256   cmpp(smi1, smi2);
   1257 }
   1258 
   1259 
   1260 void MacroAssembler::SmiCompare(Register dst, Smi* src) {
   1261   AssertSmi(dst);
   1262   Cmp(dst, src);
   1263 }
   1264 
   1265 
   1266 void MacroAssembler::Cmp(Register dst, Smi* src) {
   1267   DCHECK(!dst.is(kScratchRegister));
   1268   if (src->value() == 0) {
   1269     testp(dst, dst);
   1270   } else {
   1271     Register constant_reg = GetSmiConstant(src);
   1272     cmpp(dst, constant_reg);
   1273   }
   1274 }
   1275 
   1276 
   1277 void MacroAssembler::SmiCompare(Register dst, const Operand& src) {
   1278   AssertSmi(dst);
   1279   AssertSmi(src);
   1280   cmpp(dst, src);
   1281 }
   1282 
   1283 
   1284 void MacroAssembler::SmiCompare(const Operand& dst, Register src) {
   1285   AssertSmi(dst);
   1286   AssertSmi(src);
   1287   cmpp(dst, src);
   1288 }
   1289 
   1290 
   1291 void MacroAssembler::SmiCompare(const Operand& dst, Smi* src) {
   1292   AssertSmi(dst);
   1293   if (SmiValuesAre32Bits()) {
   1294     cmpl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(src->value()));
   1295   } else {
   1296     DCHECK(SmiValuesAre31Bits());
   1297     cmpl(dst, Immediate(src));
   1298   }
   1299 }
   1300 
   1301 
   1302 void MacroAssembler::Cmp(const Operand& dst, Smi* src) {
   1303   // The Operand cannot use the smi register.
   1304   Register smi_reg = GetSmiConstant(src);
   1305   DCHECK(!dst.AddressUsesRegister(smi_reg));
   1306   cmpp(dst, smi_reg);
   1307 }
   1308 
   1309 
   1310 void MacroAssembler::SmiCompareInteger32(const Operand& dst, Register src) {
   1311   if (SmiValuesAre32Bits()) {
   1312     cmpl(Operand(dst, kSmiShift / kBitsPerByte), src);
   1313   } else {
   1314     DCHECK(SmiValuesAre31Bits());
   1315     SmiToInteger32(kScratchRegister, dst);
   1316     cmpl(kScratchRegister, src);
   1317   }
   1318 }
   1319 
   1320 
   1321 void MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst,
   1322                                                            Register src,
   1323                                                            int power) {
   1324   DCHECK(power >= 0);
   1325   DCHECK(power < 64);
   1326   if (power == 0) {
   1327     SmiToInteger64(dst, src);
   1328     return;
   1329   }
   1330   if (!dst.is(src)) {
   1331     movp(dst, src);
   1332   }
   1333   if (power < kSmiShift) {
   1334     sarp(dst, Immediate(kSmiShift - power));
   1335   } else if (power > kSmiShift) {
   1336     shlp(dst, Immediate(power - kSmiShift));
   1337   }
   1338 }
   1339 
   1340 
   1341 void MacroAssembler::PositiveSmiDivPowerOfTwoToInteger32(Register dst,
   1342                                                          Register src,
   1343                                                          int power) {
   1344   DCHECK((0 <= power) && (power < 32));
   1345   if (dst.is(src)) {
   1346     shrp(dst, Immediate(power + kSmiShift));
   1347   } else {
   1348     UNIMPLEMENTED();  // Not used.
   1349   }
   1350 }
   1351 
   1352 
   1353 void MacroAssembler::SmiOrIfSmis(Register dst, Register src1, Register src2,
   1354                                  Label* on_not_smis,
   1355                                  Label::Distance near_jump) {
   1356   if (dst.is(src1) || dst.is(src2)) {
   1357     DCHECK(!src1.is(kScratchRegister));
   1358     DCHECK(!src2.is(kScratchRegister));
   1359     movp(kScratchRegister, src1);
   1360     orp(kScratchRegister, src2);
   1361     JumpIfNotSmi(kScratchRegister, on_not_smis, near_jump);
   1362     movp(dst, kScratchRegister);
   1363   } else {
   1364     movp(dst, src1);
   1365     orp(dst, src2);
   1366     JumpIfNotSmi(dst, on_not_smis, near_jump);
   1367   }
   1368 }
   1369 
   1370 
   1371 Condition MacroAssembler::CheckSmi(Register src) {
   1372   STATIC_ASSERT(kSmiTag == 0);
   1373   testb(src, Immediate(kSmiTagMask));
   1374   return zero;
   1375 }
   1376 
   1377 
   1378 Condition MacroAssembler::CheckSmi(const Operand& src) {
   1379   STATIC_ASSERT(kSmiTag == 0);
   1380   testb(src, Immediate(kSmiTagMask));
   1381   return zero;
   1382 }
   1383 
   1384 
   1385 Condition MacroAssembler::CheckNonNegativeSmi(Register src) {
   1386   STATIC_ASSERT(kSmiTag == 0);
   1387   // Test that both bits of the mask 0x8000000000000001 are zero.
   1388   movp(kScratchRegister, src);
   1389   rolp(kScratchRegister, Immediate(1));
   1390   testb(kScratchRegister, Immediate(3));
   1391   return zero;
   1392 }
   1393 
   1394 
   1395 Condition MacroAssembler::CheckBothSmi(Register first, Register second) {
   1396   if (first.is(second)) {
   1397     return CheckSmi(first);
   1398   }
   1399   STATIC_ASSERT(kSmiTag == 0 && kHeapObjectTag == 1 && kHeapObjectTagMask == 3);
   1400   if (SmiValuesAre32Bits()) {
   1401     leal(kScratchRegister, Operand(first, second, times_1, 0));
   1402     testb(kScratchRegister, Immediate(0x03));
   1403   } else {
   1404     DCHECK(SmiValuesAre31Bits());
   1405     movl(kScratchRegister, first);
   1406     orl(kScratchRegister, second);
   1407     testb(kScratchRegister, Immediate(kSmiTagMask));
   1408   }
   1409   return zero;
   1410 }
   1411 
   1412 
   1413 Condition MacroAssembler::CheckBothNonNegativeSmi(Register first,
   1414                                                   Register second) {
   1415   if (first.is(second)) {
   1416     return CheckNonNegativeSmi(first);
   1417   }
   1418   movp(kScratchRegister, first);
   1419   orp(kScratchRegister, second);
   1420   rolp(kScratchRegister, Immediate(1));
   1421   testl(kScratchRegister, Immediate(3));
   1422   return zero;
   1423 }
   1424 
   1425 
   1426 Condition MacroAssembler::CheckEitherSmi(Register first,
   1427                                          Register second,
   1428                                          Register scratch) {
   1429   if (first.is(second)) {
   1430     return CheckSmi(first);
   1431   }
   1432   if (scratch.is(second)) {
   1433     andl(scratch, first);
   1434   } else {
   1435     if (!scratch.is(first)) {
   1436       movl(scratch, first);
   1437     }
   1438     andl(scratch, second);
   1439   }
   1440   testb(scratch, Immediate(kSmiTagMask));
   1441   return zero;
   1442 }
   1443 
   1444 
   1445 Condition MacroAssembler::CheckIsMinSmi(Register src) {
   1446   DCHECK(!src.is(kScratchRegister));
   1447   // If we overflow by subtracting one, it's the minimal smi value.
   1448   cmpp(src, kSmiConstantRegister);
   1449   return overflow;
   1450 }
   1451 
   1452 
   1453 Condition MacroAssembler::CheckInteger32ValidSmiValue(Register src) {
   1454   if (SmiValuesAre32Bits()) {
   1455     // A 32-bit integer value can always be converted to a smi.
   1456     return always;
   1457   } else {
   1458     DCHECK(SmiValuesAre31Bits());
   1459     cmpl(src, Immediate(0xc0000000));
   1460     return positive;
   1461   }
   1462 }
   1463 
   1464 
   1465 Condition MacroAssembler::CheckUInteger32ValidSmiValue(Register src) {
   1466   if (SmiValuesAre32Bits()) {
   1467     // An unsigned 32-bit integer value is valid as long as the high bit
   1468     // is not set.
   1469     testl(src, src);
   1470     return positive;
   1471   } else {
   1472     DCHECK(SmiValuesAre31Bits());
   1473     testl(src, Immediate(0xc0000000));
   1474     return zero;
   1475   }
   1476 }
   1477 
   1478 
   1479 void MacroAssembler::CheckSmiToIndicator(Register dst, Register src) {
   1480   if (dst.is(src)) {
   1481     andl(dst, Immediate(kSmiTagMask));
   1482   } else {
   1483     movl(dst, Immediate(kSmiTagMask));
   1484     andl(dst, src);
   1485   }
   1486 }
   1487 
   1488 
   1489 void MacroAssembler::CheckSmiToIndicator(Register dst, const Operand& src) {
   1490   if (!(src.AddressUsesRegister(dst))) {
   1491     movl(dst, Immediate(kSmiTagMask));
   1492     andl(dst, src);
   1493   } else {
   1494     movl(dst, src);
   1495     andl(dst, Immediate(kSmiTagMask));
   1496   }
   1497 }
   1498 
   1499 
   1500 void MacroAssembler::JumpIfValidSmiValue(Register src,
   1501                                          Label* on_valid,
   1502                                          Label::Distance near_jump) {
   1503   Condition is_valid = CheckInteger32ValidSmiValue(src);
   1504   j(is_valid, on_valid, near_jump);
   1505 }
   1506 
   1507 
   1508 void MacroAssembler::JumpIfNotValidSmiValue(Register src,
   1509                                             Label* on_invalid,
   1510                                             Label::Distance near_jump) {
   1511   Condition is_valid = CheckInteger32ValidSmiValue(src);
   1512   j(NegateCondition(is_valid), on_invalid, near_jump);
   1513 }
   1514 
   1515 
   1516 void MacroAssembler::JumpIfUIntValidSmiValue(Register src,
   1517                                              Label* on_valid,
   1518                                              Label::Distance near_jump) {
   1519   Condition is_valid = CheckUInteger32ValidSmiValue(src);
   1520   j(is_valid, on_valid, near_jump);
   1521 }
   1522 
   1523 
   1524 void MacroAssembler::JumpIfUIntNotValidSmiValue(Register src,
   1525                                                 Label* on_invalid,
   1526                                                 Label::Distance near_jump) {
   1527   Condition is_valid = CheckUInteger32ValidSmiValue(src);
   1528   j(NegateCondition(is_valid), on_invalid, near_jump);
   1529 }
   1530 
   1531 
   1532 void MacroAssembler::JumpIfSmi(Register src,
   1533                                Label* on_smi,
   1534                                Label::Distance near_jump) {
   1535   Condition smi = CheckSmi(src);
   1536   j(smi, on_smi, near_jump);
   1537 }
   1538 
   1539 
   1540 void MacroAssembler::JumpIfNotSmi(Register src,
   1541                                   Label* on_not_smi,
   1542                                   Label::Distance near_jump) {
   1543   Condition smi = CheckSmi(src);
   1544   j(NegateCondition(smi), on_not_smi, near_jump);
   1545 }
   1546 
   1547 
   1548 void MacroAssembler::JumpUnlessNonNegativeSmi(
   1549     Register src, Label* on_not_smi_or_negative,
   1550     Label::Distance near_jump) {
   1551   Condition non_negative_smi = CheckNonNegativeSmi(src);
   1552   j(NegateCondition(non_negative_smi), on_not_smi_or_negative, near_jump);
   1553 }
   1554 
   1555 
   1556 void MacroAssembler::JumpIfSmiEqualsConstant(Register src,
   1557                                              Smi* constant,
   1558                                              Label* on_equals,
   1559                                              Label::Distance near_jump) {
   1560   SmiCompare(src, constant);
   1561   j(equal, on_equals, near_jump);
   1562 }
   1563 
   1564 
   1565 void MacroAssembler::JumpIfNotBothSmi(Register src1,
   1566                                       Register src2,
   1567                                       Label* on_not_both_smi,
   1568                                       Label::Distance near_jump) {
   1569   Condition both_smi = CheckBothSmi(src1, src2);
   1570   j(NegateCondition(both_smi), on_not_both_smi, near_jump);
   1571 }
   1572 
   1573 
   1574 void MacroAssembler::JumpUnlessBothNonNegativeSmi(Register src1,
   1575                                                   Register src2,
   1576                                                   Label* on_not_both_smi,
   1577                                                   Label::Distance near_jump) {
   1578   Condition both_smi = CheckBothNonNegativeSmi(src1, src2);
   1579   j(NegateCondition(both_smi), on_not_both_smi, near_jump);
   1580 }
   1581 
   1582 
   1583 void MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant) {
   1584   if (constant->value() == 0) {
   1585     if (!dst.is(src)) {
   1586       movp(dst, src);
   1587     }
   1588     return;
   1589   } else if (dst.is(src)) {
   1590     DCHECK(!dst.is(kScratchRegister));
   1591     switch (constant->value()) {
   1592       case 1:
   1593         addp(dst, kSmiConstantRegister);
   1594         return;
   1595       case 2:
   1596         leap(dst, Operand(src, kSmiConstantRegister, times_2, 0));
   1597         return;
   1598       case 4:
   1599         leap(dst, Operand(src, kSmiConstantRegister, times_4, 0));
   1600         return;
   1601       case 8:
   1602         leap(dst, Operand(src, kSmiConstantRegister, times_8, 0));
   1603         return;
   1604       default:
   1605         Register constant_reg = GetSmiConstant(constant);
   1606         addp(dst, constant_reg);
   1607         return;
   1608     }
   1609   } else {
   1610     switch (constant->value()) {
   1611       case 1:
   1612         leap(dst, Operand(src, kSmiConstantRegister, times_1, 0));
   1613         return;
   1614       case 2:
   1615         leap(dst, Operand(src, kSmiConstantRegister, times_2, 0));
   1616         return;
   1617       case 4:
   1618         leap(dst, Operand(src, kSmiConstantRegister, times_4, 0));
   1619         return;
   1620       case 8:
   1621         leap(dst, Operand(src, kSmiConstantRegister, times_8, 0));
   1622         return;
   1623       default:
   1624         LoadSmiConstant(dst, constant);
   1625         addp(dst, src);
   1626         return;
   1627     }
   1628   }
   1629 }
   1630 
   1631 
   1632 void MacroAssembler::SmiAddConstant(const Operand& dst, Smi* constant) {
   1633   if (constant->value() != 0) {
   1634     if (SmiValuesAre32Bits()) {
   1635       addl(Operand(dst, kSmiShift / kBitsPerByte),
   1636            Immediate(constant->value()));
   1637     } else {
   1638       DCHECK(SmiValuesAre31Bits());
   1639       addp(dst, Immediate(constant));
   1640     }
   1641   }
   1642 }
   1643 
   1644 
   1645 void MacroAssembler::SmiAddConstant(Register dst,
   1646                                     Register src,
   1647                                     Smi* constant,
   1648                                     SmiOperationExecutionMode mode,
   1649                                     Label* bailout_label,
   1650                                     Label::Distance near_jump) {
   1651   if (constant->value() == 0) {
   1652     if (!dst.is(src)) {
   1653       movp(dst, src);
   1654     }
   1655   } else if (dst.is(src)) {
   1656     DCHECK(!dst.is(kScratchRegister));
   1657     LoadSmiConstant(kScratchRegister, constant);
   1658     addp(dst, kScratchRegister);
   1659     if (mode.Contains(BAILOUT_ON_NO_OVERFLOW)) {
   1660       j(no_overflow, bailout_label, near_jump);
   1661       DCHECK(mode.Contains(PRESERVE_SOURCE_REGISTER));
   1662       subp(dst, kScratchRegister);
   1663     } else if (mode.Contains(BAILOUT_ON_OVERFLOW)) {
   1664       if (mode.Contains(PRESERVE_SOURCE_REGISTER)) {
   1665         Label done;
   1666         j(no_overflow, &done, Label::kNear);
   1667         subp(dst, kScratchRegister);
   1668         jmp(bailout_label, near_jump);
   1669         bind(&done);
   1670       } else {
   1671         // Bailout if overflow without reserving src.
   1672         j(overflow, bailout_label, near_jump);
   1673       }
   1674     } else {
   1675       CHECK(mode.IsEmpty());
   1676     }
   1677   } else {
   1678     DCHECK(mode.Contains(PRESERVE_SOURCE_REGISTER));
   1679     DCHECK(mode.Contains(BAILOUT_ON_OVERFLOW));
   1680     LoadSmiConstant(dst, constant);
   1681     addp(dst, src);
   1682     j(overflow, bailout_label, near_jump);
   1683   }
   1684 }
   1685 
   1686 
   1687 void MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant) {
   1688   if (constant->value() == 0) {
   1689     if (!dst.is(src)) {
   1690       movp(dst, src);
   1691     }
   1692   } else if (dst.is(src)) {
   1693     DCHECK(!dst.is(kScratchRegister));
   1694     Register constant_reg = GetSmiConstant(constant);
   1695     subp(dst, constant_reg);
   1696   } else {
   1697     if (constant->value() == Smi::kMinValue) {
   1698       LoadSmiConstant(dst, constant);
   1699       // Adding and subtracting the min-value gives the same result, it only
   1700       // differs on the overflow bit, which we don't check here.
   1701       addp(dst, src);
   1702     } else {
   1703       // Subtract by adding the negation.
   1704       LoadSmiConstant(dst, Smi::FromInt(-constant->value()));
   1705       addp(dst, src);
   1706     }
   1707   }
   1708 }
   1709 
   1710 
   1711 void MacroAssembler::SmiSubConstant(Register dst,
   1712                                     Register src,
   1713                                     Smi* constant,
   1714                                     SmiOperationExecutionMode mode,
   1715                                     Label* bailout_label,
   1716                                     Label::Distance near_jump) {
   1717   if (constant->value() == 0) {
   1718     if (!dst.is(src)) {
   1719       movp(dst, src);
   1720     }
   1721   } else if (dst.is(src)) {
   1722     DCHECK(!dst.is(kScratchRegister));
   1723     LoadSmiConstant(kScratchRegister, constant);
   1724     subp(dst, kScratchRegister);
   1725     if (mode.Contains(BAILOUT_ON_NO_OVERFLOW)) {
   1726       j(no_overflow, bailout_label, near_jump);
   1727       DCHECK(mode.Contains(PRESERVE_SOURCE_REGISTER));
   1728       addp(dst, kScratchRegister);
   1729     } else if (mode.Contains(BAILOUT_ON_OVERFLOW)) {
   1730       if (mode.Contains(PRESERVE_SOURCE_REGISTER)) {
   1731         Label done;
   1732         j(no_overflow, &done, Label::kNear);
   1733         addp(dst, kScratchRegister);
   1734         jmp(bailout_label, near_jump);
   1735         bind(&done);
   1736       } else {
   1737         // Bailout if overflow without reserving src.
   1738         j(overflow, bailout_label, near_jump);
   1739       }
   1740     } else {
   1741       CHECK(mode.IsEmpty());
   1742     }
   1743   } else {
   1744     DCHECK(mode.Contains(PRESERVE_SOURCE_REGISTER));
   1745     DCHECK(mode.Contains(BAILOUT_ON_OVERFLOW));
   1746     if (constant->value() == Smi::kMinValue) {
   1747       DCHECK(!dst.is(kScratchRegister));
   1748       movp(dst, src);
   1749       LoadSmiConstant(kScratchRegister, constant);
   1750       subp(dst, kScratchRegister);
   1751       j(overflow, bailout_label, near_jump);
   1752     } else {
   1753       // Subtract by adding the negation.
   1754       LoadSmiConstant(dst, Smi::FromInt(-(constant->value())));
   1755       addp(dst, src);
   1756       j(overflow, bailout_label, near_jump);
   1757     }
   1758   }
   1759 }
   1760 
   1761 
   1762 void MacroAssembler::SmiNeg(Register dst,
   1763                             Register src,
   1764                             Label* on_smi_result,
   1765                             Label::Distance near_jump) {
   1766   if (dst.is(src)) {
   1767     DCHECK(!dst.is(kScratchRegister));
   1768     movp(kScratchRegister, src);
   1769     negp(dst);  // Low 32 bits are retained as zero by negation.
   1770     // Test if result is zero or Smi::kMinValue.
   1771     cmpp(dst, kScratchRegister);
   1772     j(not_equal, on_smi_result, near_jump);
   1773     movp(src, kScratchRegister);
   1774   } else {
   1775     movp(dst, src);
   1776     negp(dst);
   1777     cmpp(dst, src);
   1778     // If the result is zero or Smi::kMinValue, negation failed to create a smi.
   1779     j(not_equal, on_smi_result, near_jump);
   1780   }
   1781 }
   1782 
   1783 
   1784 template<class T>
   1785 static void SmiAddHelper(MacroAssembler* masm,
   1786                          Register dst,
   1787                          Register src1,
   1788                          T src2,
   1789                          Label* on_not_smi_result,
   1790                          Label::Distance near_jump) {
   1791   if (dst.is(src1)) {
   1792     Label done;
   1793     masm->addp(dst, src2);
   1794     masm->j(no_overflow, &done, Label::kNear);
   1795     // Restore src1.
   1796     masm->subp(dst, src2);
   1797     masm->jmp(on_not_smi_result, near_jump);
   1798     masm->bind(&done);
   1799   } else {
   1800     masm->movp(dst, src1);
   1801     masm->addp(dst, src2);
   1802     masm->j(overflow, on_not_smi_result, near_jump);
   1803   }
   1804 }
   1805 
   1806 
   1807 void MacroAssembler::SmiAdd(Register dst,
   1808                             Register src1,
   1809                             Register src2,
   1810                             Label* on_not_smi_result,
   1811                             Label::Distance near_jump) {
   1812   DCHECK_NOT_NULL(on_not_smi_result);
   1813   DCHECK(!dst.is(src2));
   1814   SmiAddHelper<Register>(this, dst, src1, src2, on_not_smi_result, near_jump);
   1815 }
   1816 
   1817 
   1818 void MacroAssembler::SmiAdd(Register dst,
   1819                             Register src1,
   1820                             const Operand& src2,
   1821                             Label* on_not_smi_result,
   1822                             Label::Distance near_jump) {
   1823   DCHECK_NOT_NULL(on_not_smi_result);
   1824   DCHECK(!src2.AddressUsesRegister(dst));
   1825   SmiAddHelper<Operand>(this, dst, src1, src2, on_not_smi_result, near_jump);
   1826 }
   1827 
   1828 
   1829 void MacroAssembler::SmiAdd(Register dst,
   1830                             Register src1,
   1831                             Register src2) {
   1832   // No overflow checking. Use only when it's known that
   1833   // overflowing is impossible.
   1834   if (!dst.is(src1)) {
   1835     if (emit_debug_code()) {
   1836       movp(kScratchRegister, src1);
   1837       addp(kScratchRegister, src2);
   1838       Check(no_overflow, kSmiAdditionOverflow);
   1839     }
   1840     leap(dst, Operand(src1, src2, times_1, 0));
   1841   } else {
   1842     addp(dst, src2);
   1843     Assert(no_overflow, kSmiAdditionOverflow);
   1844   }
   1845 }
   1846 
   1847 
   1848 template<class T>
   1849 static void SmiSubHelper(MacroAssembler* masm,
   1850                          Register dst,
   1851                          Register src1,
   1852                          T src2,
   1853                          Label* on_not_smi_result,
   1854                          Label::Distance near_jump) {
   1855   if (dst.is(src1)) {
   1856     Label done;
   1857     masm->subp(dst, src2);
   1858     masm->j(no_overflow, &done, Label::kNear);
   1859     // Restore src1.
   1860     masm->addp(dst, src2);
   1861     masm->jmp(on_not_smi_result, near_jump);
   1862     masm->bind(&done);
   1863   } else {
   1864     masm->movp(dst, src1);
   1865     masm->subp(dst, src2);
   1866     masm->j(overflow, on_not_smi_result, near_jump);
   1867   }
   1868 }
   1869 
   1870 
   1871 void MacroAssembler::SmiSub(Register dst,
   1872                             Register src1,
   1873                             Register src2,
   1874                             Label* on_not_smi_result,
   1875                             Label::Distance near_jump) {
   1876   DCHECK_NOT_NULL(on_not_smi_result);
   1877   DCHECK(!dst.is(src2));
   1878   SmiSubHelper<Register>(this, dst, src1, src2, on_not_smi_result, near_jump);
   1879 }
   1880 
   1881 
   1882 void MacroAssembler::SmiSub(Register dst,
   1883                             Register src1,
   1884                             const Operand& src2,
   1885                             Label* on_not_smi_result,
   1886                             Label::Distance near_jump) {
   1887   DCHECK_NOT_NULL(on_not_smi_result);
   1888   DCHECK(!src2.AddressUsesRegister(dst));
   1889   SmiSubHelper<Operand>(this, dst, src1, src2, on_not_smi_result, near_jump);
   1890 }
   1891 
   1892 
   1893 template<class T>
   1894 static void SmiSubNoOverflowHelper(MacroAssembler* masm,
   1895                                    Register dst,
   1896                                    Register src1,
   1897                                    T src2) {
   1898   // No overflow checking. Use only when it's known that
   1899   // overflowing is impossible (e.g., subtracting two positive smis).
   1900   if (!dst.is(src1)) {
   1901     masm->movp(dst, src1);
   1902   }
   1903   masm->subp(dst, src2);
   1904   masm->Assert(no_overflow, kSmiSubtractionOverflow);
   1905 }
   1906 
   1907 
   1908 void MacroAssembler::SmiSub(Register dst, Register src1, Register src2) {
   1909   DCHECK(!dst.is(src2));
   1910   SmiSubNoOverflowHelper<Register>(this, dst, src1, src2);
   1911 }
   1912 
   1913 
   1914 void MacroAssembler::SmiSub(Register dst,
   1915                             Register src1,
   1916                             const Operand& src2) {
   1917   SmiSubNoOverflowHelper<Operand>(this, dst, src1, src2);
   1918 }
   1919 
   1920 
   1921 void MacroAssembler::SmiMul(Register dst,
   1922                             Register src1,
   1923                             Register src2,
   1924                             Label* on_not_smi_result,
   1925                             Label::Distance near_jump) {
   1926   DCHECK(!dst.is(src2));
   1927   DCHECK(!dst.is(kScratchRegister));
   1928   DCHECK(!src1.is(kScratchRegister));
   1929   DCHECK(!src2.is(kScratchRegister));
   1930 
   1931   if (dst.is(src1)) {
   1932     Label failure, zero_correct_result;
   1933     movp(kScratchRegister, src1);  // Create backup for later testing.
   1934     SmiToInteger64(dst, src1);
   1935     imulp(dst, src2);
   1936     j(overflow, &failure, Label::kNear);
   1937 
   1938     // Check for negative zero result.  If product is zero, and one
   1939     // argument is negative, go to slow case.
   1940     Label correct_result;
   1941     testp(dst, dst);
   1942     j(not_zero, &correct_result, Label::kNear);
   1943 
   1944     movp(dst, kScratchRegister);
   1945     xorp(dst, src2);
   1946     // Result was positive zero.
   1947     j(positive, &zero_correct_result, Label::kNear);
   1948 
   1949     bind(&failure);  // Reused failure exit, restores src1.
   1950     movp(src1, kScratchRegister);
   1951     jmp(on_not_smi_result, near_jump);
   1952 
   1953     bind(&zero_correct_result);
   1954     Set(dst, 0);
   1955 
   1956     bind(&correct_result);
   1957   } else {
   1958     SmiToInteger64(dst, src1);
   1959     imulp(dst, src2);
   1960     j(overflow, on_not_smi_result, near_jump);
   1961     // Check for negative zero result.  If product is zero, and one
   1962     // argument is negative, go to slow case.
   1963     Label correct_result;
   1964     testp(dst, dst);
   1965     j(not_zero, &correct_result, Label::kNear);
   1966     // One of src1 and src2 is zero, the check whether the other is
   1967     // negative.
   1968     movp(kScratchRegister, src1);
   1969     xorp(kScratchRegister, src2);
   1970     j(negative, on_not_smi_result, near_jump);
   1971     bind(&correct_result);
   1972   }
   1973 }
   1974 
   1975 
   1976 void MacroAssembler::SmiDiv(Register dst,
   1977                             Register src1,
   1978                             Register src2,
   1979                             Label* on_not_smi_result,
   1980                             Label::Distance near_jump) {
   1981   DCHECK(!src1.is(kScratchRegister));
   1982   DCHECK(!src2.is(kScratchRegister));
   1983   DCHECK(!dst.is(kScratchRegister));
   1984   DCHECK(!src2.is(rax));
   1985   DCHECK(!src2.is(rdx));
   1986   DCHECK(!src1.is(rdx));
   1987 
   1988   // Check for 0 divisor (result is +/-Infinity).
   1989   testp(src2, src2);
   1990   j(zero, on_not_smi_result, near_jump);
   1991 
   1992   if (src1.is(rax)) {
   1993     movp(kScratchRegister, src1);
   1994   }
   1995   SmiToInteger32(rax, src1);
   1996   // We need to rule out dividing Smi::kMinValue by -1, since that would
   1997   // overflow in idiv and raise an exception.
   1998   // We combine this with negative zero test (negative zero only happens
   1999   // when dividing zero by a negative number).
   2000 
   2001   // We overshoot a little and go to slow case if we divide min-value
   2002   // by any negative value, not just -1.
   2003   Label safe_div;
   2004   testl(rax, Immediate(~Smi::kMinValue));
   2005   j(not_zero, &safe_div, Label::kNear);
   2006   testp(src2, src2);
   2007   if (src1.is(rax)) {
   2008     j(positive, &safe_div, Label::kNear);
   2009     movp(src1, kScratchRegister);
   2010     jmp(on_not_smi_result, near_jump);
   2011   } else {
   2012     j(negative, on_not_smi_result, near_jump);
   2013   }
   2014   bind(&safe_div);
   2015 
   2016   SmiToInteger32(src2, src2);
   2017   // Sign extend src1 into edx:eax.
   2018   cdq();
   2019   idivl(src2);
   2020   Integer32ToSmi(src2, src2);
   2021   // Check that the remainder is zero.
   2022   testl(rdx, rdx);
   2023   if (src1.is(rax)) {
   2024     Label smi_result;
   2025     j(zero, &smi_result, Label::kNear);
   2026     movp(src1, kScratchRegister);
   2027     jmp(on_not_smi_result, near_jump);
   2028     bind(&smi_result);
   2029   } else {
   2030     j(not_zero, on_not_smi_result, near_jump);
   2031   }
   2032   if (!dst.is(src1) && src1.is(rax)) {
   2033     movp(src1, kScratchRegister);
   2034   }
   2035   Integer32ToSmi(dst, rax);
   2036 }
   2037 
   2038 
   2039 void MacroAssembler::SmiMod(Register dst,
   2040                             Register src1,
   2041                             Register src2,
   2042                             Label* on_not_smi_result,
   2043                             Label::Distance near_jump) {
   2044   DCHECK(!dst.is(kScratchRegister));
   2045   DCHECK(!src1.is(kScratchRegister));
   2046   DCHECK(!src2.is(kScratchRegister));
   2047   DCHECK(!src2.is(rax));
   2048   DCHECK(!src2.is(rdx));
   2049   DCHECK(!src1.is(rdx));
   2050   DCHECK(!src1.is(src2));
   2051 
   2052   testp(src2, src2);
   2053   j(zero, on_not_smi_result, near_jump);
   2054 
   2055   if (src1.is(rax)) {
   2056     movp(kScratchRegister, src1);
   2057   }
   2058   SmiToInteger32(rax, src1);
   2059   SmiToInteger32(src2, src2);
   2060 
   2061   // Test for the edge case of dividing Smi::kMinValue by -1 (will overflow).
   2062   Label safe_div;
   2063   cmpl(rax, Immediate(Smi::kMinValue));
   2064   j(not_equal, &safe_div, Label::kNear);
   2065   cmpl(src2, Immediate(-1));
   2066   j(not_equal, &safe_div, Label::kNear);
   2067   // Retag inputs and go slow case.
   2068   Integer32ToSmi(src2, src2);
   2069   if (src1.is(rax)) {
   2070     movp(src1, kScratchRegister);
   2071   }
   2072   jmp(on_not_smi_result, near_jump);
   2073   bind(&safe_div);
   2074 
   2075   // Sign extend eax into edx:eax.
   2076   cdq();
   2077   idivl(src2);
   2078   // Restore smi tags on inputs.
   2079   Integer32ToSmi(src2, src2);
   2080   if (src1.is(rax)) {
   2081     movp(src1, kScratchRegister);
   2082   }
   2083   // Check for a negative zero result.  If the result is zero, and the
   2084   // dividend is negative, go slow to return a floating point negative zero.
   2085   Label smi_result;
   2086   testl(rdx, rdx);
   2087   j(not_zero, &smi_result, Label::kNear);
   2088   testp(src1, src1);
   2089   j(negative, on_not_smi_result, near_jump);
   2090   bind(&smi_result);
   2091   Integer32ToSmi(dst, rdx);
   2092 }
   2093 
   2094 
   2095 void MacroAssembler::SmiNot(Register dst, Register src) {
   2096   DCHECK(!dst.is(kScratchRegister));
   2097   DCHECK(!src.is(kScratchRegister));
   2098   if (SmiValuesAre32Bits()) {
   2099     // Set tag and padding bits before negating, so that they are zero
   2100     // afterwards.
   2101     movl(kScratchRegister, Immediate(~0));
   2102   } else {
   2103     DCHECK(SmiValuesAre31Bits());
   2104     movl(kScratchRegister, Immediate(1));
   2105   }
   2106   if (dst.is(src)) {
   2107     xorp(dst, kScratchRegister);
   2108   } else {
   2109     leap(dst, Operand(src, kScratchRegister, times_1, 0));
   2110   }
   2111   notp(dst);
   2112 }
   2113 
   2114 
   2115 void MacroAssembler::SmiAnd(Register dst, Register src1, Register src2) {
   2116   DCHECK(!dst.is(src2));
   2117   if (!dst.is(src1)) {
   2118     movp(dst, src1);
   2119   }
   2120   andp(dst, src2);
   2121 }
   2122 
   2123 
   2124 void MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) {
   2125   if (constant->value() == 0) {
   2126     Set(dst, 0);
   2127   } else if (dst.is(src)) {
   2128     DCHECK(!dst.is(kScratchRegister));
   2129     Register constant_reg = GetSmiConstant(constant);
   2130     andp(dst, constant_reg);
   2131   } else {
   2132     LoadSmiConstant(dst, constant);
   2133     andp(dst, src);
   2134   }
   2135 }
   2136 
   2137 
   2138 void MacroAssembler::SmiOr(Register dst, Register src1, Register src2) {
   2139   if (!dst.is(src1)) {
   2140     DCHECK(!src1.is(src2));
   2141     movp(dst, src1);
   2142   }
   2143   orp(dst, src2);
   2144 }
   2145 
   2146 
   2147 void MacroAssembler::SmiOrConstant(Register dst, Register src, Smi* constant) {
   2148   if (dst.is(src)) {
   2149     DCHECK(!dst.is(kScratchRegister));
   2150     Register constant_reg = GetSmiConstant(constant);
   2151     orp(dst, constant_reg);
   2152   } else {
   2153     LoadSmiConstant(dst, constant);
   2154     orp(dst, src);
   2155   }
   2156 }
   2157 
   2158 
   2159 void MacroAssembler::SmiXor(Register dst, Register src1, Register src2) {
   2160   if (!dst.is(src1)) {
   2161     DCHECK(!src1.is(src2));
   2162     movp(dst, src1);
   2163   }
   2164   xorp(dst, src2);
   2165 }
   2166 
   2167 
   2168 void MacroAssembler::SmiXorConstant(Register dst, Register src, Smi* constant) {
   2169   if (dst.is(src)) {
   2170     DCHECK(!dst.is(kScratchRegister));
   2171     Register constant_reg = GetSmiConstant(constant);
   2172     xorp(dst, constant_reg);
   2173   } else {
   2174     LoadSmiConstant(dst, constant);
   2175     xorp(dst, src);
   2176   }
   2177 }
   2178 
   2179 
   2180 void MacroAssembler::SmiShiftArithmeticRightConstant(Register dst,
   2181                                                      Register src,
   2182                                                      int shift_value) {
   2183   DCHECK(is_uint5(shift_value));
   2184   if (shift_value > 0) {
   2185     if (dst.is(src)) {
   2186       sarp(dst, Immediate(shift_value + kSmiShift));
   2187       shlp(dst, Immediate(kSmiShift));
   2188     } else {
   2189       UNIMPLEMENTED();  // Not used.
   2190     }
   2191   }
   2192 }
   2193 
   2194 
   2195 void MacroAssembler::SmiShiftLeftConstant(Register dst,
   2196                                           Register src,
   2197                                           int shift_value,
   2198                                           Label* on_not_smi_result,
   2199                                           Label::Distance near_jump) {
   2200   if (SmiValuesAre32Bits()) {
   2201     if (!dst.is(src)) {
   2202       movp(dst, src);
   2203     }
   2204     if (shift_value > 0) {
   2205       // Shift amount specified by lower 5 bits, not six as the shl opcode.
   2206       shlq(dst, Immediate(shift_value & 0x1f));
   2207     }
   2208   } else {
   2209     DCHECK(SmiValuesAre31Bits());
   2210     if (dst.is(src)) {
   2211       UNIMPLEMENTED();  // Not used.
   2212     } else {
   2213       SmiToInteger32(dst, src);
   2214       shll(dst, Immediate(shift_value));
   2215       JumpIfNotValidSmiValue(dst, on_not_smi_result, near_jump);
   2216       Integer32ToSmi(dst, dst);
   2217     }
   2218   }
   2219 }
   2220 
   2221 
   2222 void MacroAssembler::SmiShiftLogicalRightConstant(
   2223     Register dst, Register src, int shift_value,
   2224     Label* on_not_smi_result, Label::Distance near_jump) {
   2225   // Logic right shift interprets its result as an *unsigned* number.
   2226   if (dst.is(src)) {
   2227     UNIMPLEMENTED();  // Not used.
   2228   } else {
   2229     if (shift_value == 0) {
   2230       testp(src, src);
   2231       j(negative, on_not_smi_result, near_jump);
   2232     }
   2233     if (SmiValuesAre32Bits()) {
   2234       movp(dst, src);
   2235       shrp(dst, Immediate(shift_value + kSmiShift));
   2236       shlp(dst, Immediate(kSmiShift));
   2237     } else {
   2238       DCHECK(SmiValuesAre31Bits());
   2239       SmiToInteger32(dst, src);
   2240       shrp(dst, Immediate(shift_value));
   2241       JumpIfUIntNotValidSmiValue(dst, on_not_smi_result, near_jump);
   2242       Integer32ToSmi(dst, dst);
   2243     }
   2244   }
   2245 }
   2246 
   2247 
   2248 void MacroAssembler::SmiShiftLeft(Register dst,
   2249                                   Register src1,
   2250                                   Register src2,
   2251                                   Label* on_not_smi_result,
   2252                                   Label::Distance near_jump) {
   2253   if (SmiValuesAre32Bits()) {
   2254     DCHECK(!dst.is(rcx));
   2255     if (!dst.is(src1)) {
   2256       movp(dst, src1);
   2257     }
   2258     // Untag shift amount.
   2259     SmiToInteger32(rcx, src2);
   2260     // Shift amount specified by lower 5 bits, not six as the shl opcode.
   2261     andp(rcx, Immediate(0x1f));
   2262     shlq_cl(dst);
   2263   } else {
   2264     DCHECK(SmiValuesAre31Bits());
   2265     DCHECK(!dst.is(kScratchRegister));
   2266     DCHECK(!src1.is(kScratchRegister));
   2267     DCHECK(!src2.is(kScratchRegister));
   2268     DCHECK(!dst.is(src2));
   2269     DCHECK(!dst.is(rcx));
   2270 
   2271     if (src1.is(rcx) || src2.is(rcx)) {
   2272       movq(kScratchRegister, rcx);
   2273     }
   2274     if (dst.is(src1)) {
   2275       UNIMPLEMENTED();  // Not used.
   2276     } else {
   2277       Label valid_result;
   2278       SmiToInteger32(dst, src1);
   2279       SmiToInteger32(rcx, src2);
   2280       shll_cl(dst);
   2281       JumpIfValidSmiValue(dst, &valid_result, Label::kNear);
   2282       // As src1 or src2 could not be dst, we do not need to restore them for
   2283       // clobbering dst.
   2284       if (src1.is(rcx) || src2.is(rcx)) {
   2285         if (src1.is(rcx)) {
   2286           movq(src1, kScratchRegister);
   2287         } else {
   2288           movq(src2, kScratchRegister);
   2289         }
   2290       }
   2291       jmp(on_not_smi_result, near_jump);
   2292       bind(&valid_result);
   2293       Integer32ToSmi(dst, dst);
   2294     }
   2295   }
   2296 }
   2297 
   2298 
   2299 void MacroAssembler::SmiShiftLogicalRight(Register dst,
   2300                                           Register src1,
   2301                                           Register src2,
   2302                                           Label* on_not_smi_result,
   2303                                           Label::Distance near_jump) {
   2304   DCHECK(!dst.is(kScratchRegister));
   2305   DCHECK(!src1.is(kScratchRegister));
   2306   DCHECK(!src2.is(kScratchRegister));
   2307   DCHECK(!dst.is(src2));
   2308   DCHECK(!dst.is(rcx));
   2309   if (src1.is(rcx) || src2.is(rcx)) {
   2310     movq(kScratchRegister, rcx);
   2311   }
   2312   if (dst.is(src1)) {
   2313     UNIMPLEMENTED();  // Not used.
   2314   } else {
   2315     Label valid_result;
   2316     SmiToInteger32(dst, src1);
   2317     SmiToInteger32(rcx, src2);
   2318     shrl_cl(dst);
   2319     JumpIfUIntValidSmiValue(dst, &valid_result, Label::kNear);
   2320     // As src1 or src2 could not be dst, we do not need to restore them for
   2321     // clobbering dst.
   2322     if (src1.is(rcx) || src2.is(rcx)) {
   2323       if (src1.is(rcx)) {
   2324         movq(src1, kScratchRegister);
   2325       } else {
   2326         movq(src2, kScratchRegister);
   2327       }
   2328      }
   2329     jmp(on_not_smi_result, near_jump);
   2330     bind(&valid_result);
   2331     Integer32ToSmi(dst, dst);
   2332   }
   2333 }
   2334 
   2335 
   2336 void MacroAssembler::SmiShiftArithmeticRight(Register dst,
   2337                                              Register src1,
   2338                                              Register src2) {
   2339   DCHECK(!dst.is(kScratchRegister));
   2340   DCHECK(!src1.is(kScratchRegister));
   2341   DCHECK(!src2.is(kScratchRegister));
   2342   DCHECK(!dst.is(rcx));
   2343 
   2344   SmiToInteger32(rcx, src2);
   2345   if (!dst.is(src1)) {
   2346     movp(dst, src1);
   2347   }
   2348   SmiToInteger32(dst, dst);
   2349   sarl_cl(dst);
   2350   Integer32ToSmi(dst, dst);
   2351 }
   2352 
   2353 
   2354 void MacroAssembler::SelectNonSmi(Register dst,
   2355                                   Register src1,
   2356                                   Register src2,
   2357                                   Label* on_not_smis,
   2358                                   Label::Distance near_jump) {
   2359   DCHECK(!dst.is(kScratchRegister));
   2360   DCHECK(!src1.is(kScratchRegister));
   2361   DCHECK(!src2.is(kScratchRegister));
   2362   DCHECK(!dst.is(src1));
   2363   DCHECK(!dst.is(src2));
   2364   // Both operands must not be smis.
   2365 #ifdef DEBUG
   2366   Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2));
   2367   Check(not_both_smis, kBothRegistersWereSmisInSelectNonSmi);
   2368 #endif
   2369   STATIC_ASSERT(kSmiTag == 0);
   2370   DCHECK_EQ(0, Smi::FromInt(0));
   2371   movl(kScratchRegister, Immediate(kSmiTagMask));
   2372   andp(kScratchRegister, src1);
   2373   testl(kScratchRegister, src2);
   2374   // If non-zero then both are smis.
   2375   j(not_zero, on_not_smis, near_jump);
   2376 
   2377   // Exactly one operand is a smi.
   2378   DCHECK_EQ(1, static_cast<int>(kSmiTagMask));
   2379   // kScratchRegister still holds src1 & kSmiTag, which is either zero or one.
   2380   subp(kScratchRegister, Immediate(1));
   2381   // If src1 is a smi, then scratch register all 1s, else it is all 0s.
   2382   movp(dst, src1);
   2383   xorp(dst, src2);
   2384   andp(dst, kScratchRegister);
   2385   // If src1 is a smi, dst holds src1 ^ src2, else it is zero.
   2386   xorp(dst, src1);
   2387   // If src1 is a smi, dst is src2, else it is src1, i.e., the non-smi.
   2388 }
   2389 
   2390 
   2391 SmiIndex MacroAssembler::SmiToIndex(Register dst,
   2392                                     Register src,
   2393                                     int shift) {
   2394   if (SmiValuesAre32Bits()) {
   2395     DCHECK(is_uint6(shift));
   2396     // There is a possible optimization if shift is in the range 60-63, but that
   2397     // will (and must) never happen.
   2398     if (!dst.is(src)) {
   2399       movp(dst, src);
   2400     }
   2401     if (shift < kSmiShift) {
   2402       sarp(dst, Immediate(kSmiShift - shift));
   2403     } else {
   2404       shlp(dst, Immediate(shift - kSmiShift));
   2405     }
   2406     return SmiIndex(dst, times_1);
   2407   } else {
   2408     DCHECK(SmiValuesAre31Bits());
   2409     DCHECK(shift >= times_1 && shift <= (static_cast<int>(times_8) + 1));
   2410     if (!dst.is(src)) {
   2411       movp(dst, src);
   2412     }
   2413     // We have to sign extend the index register to 64-bit as the SMI might
   2414     // be negative.
   2415     movsxlq(dst, dst);
   2416     if (shift == times_1) {
   2417       sarq(dst, Immediate(kSmiShift));
   2418       return SmiIndex(dst, times_1);
   2419     }
   2420     return SmiIndex(dst, static_cast<ScaleFactor>(shift - 1));
   2421   }
   2422 }
   2423 
   2424 
   2425 SmiIndex MacroAssembler::SmiToNegativeIndex(Register dst,
   2426                                             Register src,
   2427                                             int shift) {
   2428   if (SmiValuesAre32Bits()) {
   2429     // Register src holds a positive smi.
   2430     DCHECK(is_uint6(shift));
   2431     if (!dst.is(src)) {
   2432       movp(dst, src);
   2433     }
   2434     negp(dst);
   2435     if (shift < kSmiShift) {
   2436       sarp(dst, Immediate(kSmiShift - shift));
   2437     } else {
   2438       shlp(dst, Immediate(shift - kSmiShift));
   2439     }
   2440     return SmiIndex(dst, times_1);
   2441   } else {
   2442     DCHECK(SmiValuesAre31Bits());
   2443     DCHECK(shift >= times_1 && shift <= (static_cast<int>(times_8) + 1));
   2444     if (!dst.is(src)) {
   2445       movp(dst, src);
   2446     }
   2447     negq(dst);
   2448     if (shift == times_1) {
   2449       sarq(dst, Immediate(kSmiShift));
   2450       return SmiIndex(dst, times_1);
   2451     }
   2452     return SmiIndex(dst, static_cast<ScaleFactor>(shift - 1));
   2453   }
   2454 }
   2455 
   2456 
   2457 void MacroAssembler::AddSmiField(Register dst, const Operand& src) {
   2458   if (SmiValuesAre32Bits()) {
   2459     DCHECK_EQ(0, kSmiShift % kBitsPerByte);
   2460     addl(dst, Operand(src, kSmiShift / kBitsPerByte));
   2461   } else {
   2462     DCHECK(SmiValuesAre31Bits());
   2463     SmiToInteger32(kScratchRegister, src);
   2464     addl(dst, kScratchRegister);
   2465   }
   2466 }
   2467 
   2468 
   2469 void MacroAssembler::Push(Smi* source) {
   2470   intptr_t smi = reinterpret_cast<intptr_t>(source);
   2471   if (is_int32(smi)) {
   2472     Push(Immediate(static_cast<int32_t>(smi)));
   2473   } else {
   2474     Register constant = GetSmiConstant(source);
   2475     Push(constant);
   2476   }
   2477 }
   2478 
   2479 
   2480 void MacroAssembler::PushRegisterAsTwoSmis(Register src, Register scratch) {
   2481   DCHECK(!src.is(scratch));
   2482   movp(scratch, src);
   2483   // High bits.
   2484   shrp(src, Immediate(kPointerSize * kBitsPerByte - kSmiShift));
   2485   shlp(src, Immediate(kSmiShift));
   2486   Push(src);
   2487   // Low bits.
   2488   shlp(scratch, Immediate(kSmiShift));
   2489   Push(scratch);
   2490 }
   2491 
   2492 
   2493 void MacroAssembler::PopRegisterAsTwoSmis(Register dst, Register scratch) {
   2494   DCHECK(!dst.is(scratch));
   2495   Pop(scratch);
   2496   // Low bits.
   2497   shrp(scratch, Immediate(kSmiShift));
   2498   Pop(dst);
   2499   shrp(dst, Immediate(kSmiShift));
   2500   // High bits.
   2501   shlp(dst, Immediate(kPointerSize * kBitsPerByte - kSmiShift));
   2502   orp(dst, scratch);
   2503 }
   2504 
   2505 
   2506 void MacroAssembler::Test(const Operand& src, Smi* source) {
   2507   if (SmiValuesAre32Bits()) {
   2508     testl(Operand(src, kIntSize), Immediate(source->value()));
   2509   } else {
   2510     DCHECK(SmiValuesAre31Bits());
   2511     testl(src, Immediate(source));
   2512   }
   2513 }
   2514 
   2515 
   2516 // ----------------------------------------------------------------------------
   2517 
   2518 
   2519 void MacroAssembler::LookupNumberStringCache(Register object,
   2520                                              Register result,
   2521                                              Register scratch1,
   2522                                              Register scratch2,
   2523                                              Label* not_found) {
   2524   // Use of registers. Register result is used as a temporary.
   2525   Register number_string_cache = result;
   2526   Register mask = scratch1;
   2527   Register scratch = scratch2;
   2528 
   2529   // Load the number string cache.
   2530   LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
   2531 
   2532   // Make the hash mask from the length of the number string cache. It
   2533   // contains two elements (number and string) for each cache entry.
   2534   SmiToInteger32(
   2535       mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset));
   2536   shrl(mask, Immediate(1));
   2537   subp(mask, Immediate(1));  // Make mask.
   2538 
   2539   // Calculate the entry in the number string cache. The hash value in the
   2540   // number string cache for smis is just the smi value, and the hash for
   2541   // doubles is the xor of the upper and lower words. See
   2542   // Heap::GetNumberStringCache.
   2543   Label is_smi;
   2544   Label load_result_from_cache;
   2545   JumpIfSmi(object, &is_smi);
   2546   CheckMap(object,
   2547            isolate()->factory()->heap_number_map(),
   2548            not_found,
   2549            DONT_DO_SMI_CHECK);
   2550 
   2551   STATIC_ASSERT(8 == kDoubleSize);
   2552   movl(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4));
   2553   xorp(scratch, FieldOperand(object, HeapNumber::kValueOffset));
   2554   andp(scratch, mask);
   2555   // Each entry in string cache consists of two pointer sized fields,
   2556   // but times_twice_pointer_size (multiplication by 16) scale factor
   2557   // is not supported by addrmode on x64 platform.
   2558   // So we have to premultiply entry index before lookup.
   2559   shlp(scratch, Immediate(kPointerSizeLog2 + 1));
   2560 
   2561   Register index = scratch;
   2562   Register probe = mask;
   2563   movp(probe,
   2564        FieldOperand(number_string_cache,
   2565                     index,
   2566                     times_1,
   2567                     FixedArray::kHeaderSize));
   2568   JumpIfSmi(probe, not_found);
   2569   movsd(xmm0, FieldOperand(object, HeapNumber::kValueOffset));
   2570   ucomisd(xmm0, FieldOperand(probe, HeapNumber::kValueOffset));
   2571   j(parity_even, not_found);  // Bail out if NaN is involved.
   2572   j(not_equal, not_found);  // The cache did not contain this value.
   2573   jmp(&load_result_from_cache);
   2574 
   2575   bind(&is_smi);
   2576   SmiToInteger32(scratch, object);
   2577   andp(scratch, mask);
   2578   // Each entry in string cache consists of two pointer sized fields,
   2579   // but times_twice_pointer_size (multiplication by 16) scale factor
   2580   // is not supported by addrmode on x64 platform.
   2581   // So we have to premultiply entry index before lookup.
   2582   shlp(scratch, Immediate(kPointerSizeLog2 + 1));
   2583 
   2584   // Check if the entry is the smi we are looking for.
   2585   cmpp(object,
   2586        FieldOperand(number_string_cache,
   2587                     index,
   2588                     times_1,
   2589                     FixedArray::kHeaderSize));
   2590   j(not_equal, not_found);
   2591 
   2592   // Get the result from the cache.
   2593   bind(&load_result_from_cache);
   2594   movp(result,
   2595        FieldOperand(number_string_cache,
   2596                     index,
   2597                     times_1,
   2598                     FixedArray::kHeaderSize + kPointerSize));
   2599   IncrementCounter(isolate()->counters()->number_to_string_native(), 1);
   2600 }
   2601 
   2602 
   2603 void MacroAssembler::JumpIfNotString(Register object,
   2604                                      Register object_map,
   2605                                      Label* not_string,
   2606                                      Label::Distance near_jump) {
   2607   Condition is_smi = CheckSmi(object);
   2608   j(is_smi, not_string, near_jump);
   2609   CmpObjectType(object, FIRST_NONSTRING_TYPE, object_map);
   2610   j(above_equal, not_string, near_jump);
   2611 }
   2612 
   2613 
   2614 void MacroAssembler::JumpIfNotBothSequentialOneByteStrings(
   2615     Register first_object, Register second_object, Register scratch1,
   2616     Register scratch2, Label* on_fail, Label::Distance near_jump) {
   2617   // Check that both objects are not smis.
   2618   Condition either_smi = CheckEitherSmi(first_object, second_object);
   2619   j(either_smi, on_fail, near_jump);
   2620 
   2621   // Load instance type for both strings.
   2622   movp(scratch1, FieldOperand(first_object, HeapObject::kMapOffset));
   2623   movp(scratch2, FieldOperand(second_object, HeapObject::kMapOffset));
   2624   movzxbl(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
   2625   movzxbl(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
   2626 
   2627   // Check that both are flat one-byte strings.
   2628   DCHECK(kNotStringTag != 0);
   2629   const int kFlatOneByteStringMask =
   2630       kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
   2631   const int kFlatOneByteStringTag =
   2632       kStringTag | kOneByteStringTag | kSeqStringTag;
   2633 
   2634   andl(scratch1, Immediate(kFlatOneByteStringMask));
   2635   andl(scratch2, Immediate(kFlatOneByteStringMask));
   2636   // Interleave the bits to check both scratch1 and scratch2 in one test.
   2637   DCHECK_EQ(0, kFlatOneByteStringMask & (kFlatOneByteStringMask << 3));
   2638   leap(scratch1, Operand(scratch1, scratch2, times_8, 0));
   2639   cmpl(scratch1,
   2640        Immediate(kFlatOneByteStringTag + (kFlatOneByteStringTag << 3)));
   2641   j(not_equal, on_fail, near_jump);
   2642 }
   2643 
   2644 
   2645 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialOneByte(
   2646     Register instance_type, Register scratch, Label* failure,
   2647     Label::Distance near_jump) {
   2648   if (!scratch.is(instance_type)) {
   2649     movl(scratch, instance_type);
   2650   }
   2651 
   2652   const int kFlatOneByteStringMask =
   2653       kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
   2654 
   2655   andl(scratch, Immediate(kFlatOneByteStringMask));
   2656   cmpl(scratch, Immediate(kStringTag | kSeqStringTag | kOneByteStringTag));
   2657   j(not_equal, failure, near_jump);
   2658 }
   2659 
   2660 
   2661 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte(
   2662     Register first_object_instance_type, Register second_object_instance_type,
   2663     Register scratch1, Register scratch2, Label* on_fail,
   2664     Label::Distance near_jump) {
   2665   // Load instance type for both strings.
   2666   movp(scratch1, first_object_instance_type);
   2667   movp(scratch2, second_object_instance_type);
   2668 
   2669   // Check that both are flat one-byte strings.
   2670   DCHECK(kNotStringTag != 0);
   2671   const int kFlatOneByteStringMask =
   2672       kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
   2673   const int kFlatOneByteStringTag =
   2674       kStringTag | kOneByteStringTag | kSeqStringTag;
   2675 
   2676   andl(scratch1, Immediate(kFlatOneByteStringMask));
   2677   andl(scratch2, Immediate(kFlatOneByteStringMask));
   2678   // Interleave the bits to check both scratch1 and scratch2 in one test.
   2679   DCHECK_EQ(0, kFlatOneByteStringMask & (kFlatOneByteStringMask << 3));
   2680   leap(scratch1, Operand(scratch1, scratch2, times_8, 0));
   2681   cmpl(scratch1,
   2682        Immediate(kFlatOneByteStringTag + (kFlatOneByteStringTag << 3)));
   2683   j(not_equal, on_fail, near_jump);
   2684 }
   2685 
   2686 
   2687 template<class T>
   2688 static void JumpIfNotUniqueNameHelper(MacroAssembler* masm,
   2689                                       T operand_or_register,
   2690                                       Label* not_unique_name,
   2691                                       Label::Distance distance) {
   2692   STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
   2693   Label succeed;
   2694   masm->testb(operand_or_register,
   2695               Immediate(kIsNotStringMask | kIsNotInternalizedMask));
   2696   masm->j(zero, &succeed, Label::kNear);
   2697   masm->cmpb(operand_or_register, Immediate(static_cast<uint8_t>(SYMBOL_TYPE)));
   2698   masm->j(not_equal, not_unique_name, distance);
   2699 
   2700   masm->bind(&succeed);
   2701 }
   2702 
   2703 
   2704 void MacroAssembler::JumpIfNotUniqueNameInstanceType(Operand operand,
   2705                                                      Label* not_unique_name,
   2706                                                      Label::Distance distance) {
   2707   JumpIfNotUniqueNameHelper<Operand>(this, operand, not_unique_name, distance);
   2708 }
   2709 
   2710 
   2711 void MacroAssembler::JumpIfNotUniqueNameInstanceType(Register reg,
   2712                                                      Label* not_unique_name,
   2713                                                      Label::Distance distance) {
   2714   JumpIfNotUniqueNameHelper<Register>(this, reg, not_unique_name, distance);
   2715 }
   2716 
   2717 
   2718 void MacroAssembler::Move(Register dst, Register src) {
   2719   if (!dst.is(src)) {
   2720     movp(dst, src);
   2721   }
   2722 }
   2723 
   2724 
   2725 void MacroAssembler::Move(Register dst, Handle<Object> source) {
   2726   AllowDeferredHandleDereference smi_check;
   2727   if (source->IsSmi()) {
   2728     Move(dst, Smi::cast(*source));
   2729   } else {
   2730     MoveHeapObject(dst, source);
   2731   }
   2732 }
   2733 
   2734 
   2735 void MacroAssembler::Move(const Operand& dst, Handle<Object> source) {
   2736   AllowDeferredHandleDereference smi_check;
   2737   if (source->IsSmi()) {
   2738     Move(dst, Smi::cast(*source));
   2739   } else {
   2740     MoveHeapObject(kScratchRegister, source);
   2741     movp(dst, kScratchRegister);
   2742   }
   2743 }
   2744 
   2745 
   2746 void MacroAssembler::Cmp(Register dst, Handle<Object> source) {
   2747   AllowDeferredHandleDereference smi_check;
   2748   if (source->IsSmi()) {
   2749     Cmp(dst, Smi::cast(*source));
   2750   } else {
   2751     MoveHeapObject(kScratchRegister, source);
   2752     cmpp(dst, kScratchRegister);
   2753   }
   2754 }
   2755 
   2756 
   2757 void MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) {
   2758   AllowDeferredHandleDereference smi_check;
   2759   if (source->IsSmi()) {
   2760     Cmp(dst, Smi::cast(*source));
   2761   } else {
   2762     MoveHeapObject(kScratchRegister, source);
   2763     cmpp(dst, kScratchRegister);
   2764   }
   2765 }
   2766 
   2767 
   2768 void MacroAssembler::Push(Handle<Object> source) {
   2769   AllowDeferredHandleDereference smi_check;
   2770   if (source->IsSmi()) {
   2771     Push(Smi::cast(*source));
   2772   } else {
   2773     MoveHeapObject(kScratchRegister, source);
   2774     Push(kScratchRegister);
   2775   }
   2776 }
   2777 
   2778 
   2779 void MacroAssembler::MoveHeapObject(Register result,
   2780                                     Handle<Object> object) {
   2781   AllowDeferredHandleDereference using_raw_address;
   2782   DCHECK(object->IsHeapObject());
   2783   if (isolate()->heap()->InNewSpace(*object)) {
   2784     Handle<Cell> cell = isolate()->factory()->NewCell(object);
   2785     Move(result, cell, RelocInfo::CELL);
   2786     movp(result, Operand(result, 0));
   2787   } else {
   2788     Move(result, object, RelocInfo::EMBEDDED_OBJECT);
   2789   }
   2790 }
   2791 
   2792 
   2793 void MacroAssembler::LoadGlobalCell(Register dst, Handle<Cell> cell) {
   2794   if (dst.is(rax)) {
   2795     AllowDeferredHandleDereference embedding_raw_address;
   2796     load_rax(cell.location(), RelocInfo::CELL);
   2797   } else {
   2798     Move(dst, cell, RelocInfo::CELL);
   2799     movp(dst, Operand(dst, 0));
   2800   }
   2801 }
   2802 
   2803 
   2804 void MacroAssembler::Drop(int stack_elements) {
   2805   if (stack_elements > 0) {
   2806     addp(rsp, Immediate(stack_elements * kPointerSize));
   2807   }
   2808 }
   2809 
   2810 
   2811 void MacroAssembler::DropUnderReturnAddress(int stack_elements,
   2812                                             Register scratch) {
   2813   DCHECK(stack_elements > 0);
   2814   if (kPointerSize == kInt64Size && stack_elements == 1) {
   2815     popq(MemOperand(rsp, 0));
   2816     return;
   2817   }
   2818 
   2819   PopReturnAddressTo(scratch);
   2820   Drop(stack_elements);
   2821   PushReturnAddressFrom(scratch);
   2822 }
   2823 
   2824 
   2825 void MacroAssembler::Push(Register src) {
   2826   if (kPointerSize == kInt64Size) {
   2827     pushq(src);
   2828   } else {
   2829     // x32 uses 64-bit push for rbp in the prologue.
   2830     DCHECK(src.code() != rbp.code());
   2831     leal(rsp, Operand(rsp, -4));
   2832     movp(Operand(rsp, 0), src);
   2833   }
   2834 }
   2835 
   2836 
   2837 void MacroAssembler::Push(const Operand& src) {
   2838   if (kPointerSize == kInt64Size) {
   2839     pushq(src);
   2840   } else {
   2841     movp(kScratchRegister, src);
   2842     leal(rsp, Operand(rsp, -4));
   2843     movp(Operand(rsp, 0), kScratchRegister);
   2844   }
   2845 }
   2846 
   2847 
   2848 void MacroAssembler::PushQuad(const Operand& src) {
   2849   if (kPointerSize == kInt64Size) {
   2850     pushq(src);
   2851   } else {
   2852     movp(kScratchRegister, src);
   2853     pushq(kScratchRegister);
   2854   }
   2855 }
   2856 
   2857 
   2858 void MacroAssembler::Push(Immediate value) {
   2859   if (kPointerSize == kInt64Size) {
   2860     pushq(value);
   2861   } else {
   2862     leal(rsp, Operand(rsp, -4));
   2863     movp(Operand(rsp, 0), value);
   2864   }
   2865 }
   2866 
   2867 
   2868 void MacroAssembler::PushImm32(int32_t imm32) {
   2869   if (kPointerSize == kInt64Size) {
   2870     pushq_imm32(imm32);
   2871   } else {
   2872     leal(rsp, Operand(rsp, -4));
   2873     movp(Operand(rsp, 0), Immediate(imm32));
   2874   }
   2875 }
   2876 
   2877 
   2878 void MacroAssembler::Pop(Register dst) {
   2879   if (kPointerSize == kInt64Size) {
   2880     popq(dst);
   2881   } else {
   2882     // x32 uses 64-bit pop for rbp in the epilogue.
   2883     DCHECK(dst.code() != rbp.code());
   2884     movp(dst, Operand(rsp, 0));
   2885     leal(rsp, Operand(rsp, 4));
   2886   }
   2887 }
   2888 
   2889 
   2890 void MacroAssembler::Pop(const Operand& dst) {
   2891   if (kPointerSize == kInt64Size) {
   2892     popq(dst);
   2893   } else {
   2894     Register scratch = dst.AddressUsesRegister(kScratchRegister)
   2895         ? kSmiConstantRegister : kScratchRegister;
   2896     movp(scratch, Operand(rsp, 0));
   2897     movp(dst, scratch);
   2898     leal(rsp, Operand(rsp, 4));
   2899     if (scratch.is(kSmiConstantRegister)) {
   2900       // Restore kSmiConstantRegister.
   2901       movp(kSmiConstantRegister,
   2902            reinterpret_cast<void*>(Smi::FromInt(kSmiConstantRegisterValue)),
   2903            Assembler::RelocInfoNone());
   2904     }
   2905   }
   2906 }
   2907 
   2908 
   2909 void MacroAssembler::PopQuad(const Operand& dst) {
   2910   if (kPointerSize == kInt64Size) {
   2911     popq(dst);
   2912   } else {
   2913     popq(kScratchRegister);
   2914     movp(dst, kScratchRegister);
   2915   }
   2916 }
   2917 
   2918 
   2919 void MacroAssembler::LoadSharedFunctionInfoSpecialField(Register dst,
   2920                                                         Register base,
   2921                                                         int offset) {
   2922   DCHECK(offset > SharedFunctionInfo::kLengthOffset &&
   2923          offset <= SharedFunctionInfo::kSize &&
   2924          (((offset - SharedFunctionInfo::kLengthOffset) / kIntSize) % 2 == 1));
   2925   if (kPointerSize == kInt64Size) {
   2926     movsxlq(dst, FieldOperand(base, offset));
   2927   } else {
   2928     movp(dst, FieldOperand(base, offset));
   2929     SmiToInteger32(dst, dst);
   2930   }
   2931 }
   2932 
   2933 
   2934 void MacroAssembler::TestBitSharedFunctionInfoSpecialField(Register base,
   2935                                                            int offset,
   2936                                                            int bits) {
   2937   DCHECK(offset > SharedFunctionInfo::kLengthOffset &&
   2938          offset <= SharedFunctionInfo::kSize &&
   2939          (((offset - SharedFunctionInfo::kLengthOffset) / kIntSize) % 2 == 1));
   2940   if (kPointerSize == kInt32Size) {
   2941     // On x32, this field is represented by SMI.
   2942     bits += kSmiShift;
   2943   }
   2944   int byte_offset = bits / kBitsPerByte;
   2945   int bit_in_byte = bits & (kBitsPerByte - 1);
   2946   testb(FieldOperand(base, offset + byte_offset), Immediate(1 << bit_in_byte));
   2947 }
   2948 
   2949 
   2950 void MacroAssembler::Jump(ExternalReference ext) {
   2951   LoadAddress(kScratchRegister, ext);
   2952   jmp(kScratchRegister);
   2953 }
   2954 
   2955 
   2956 void MacroAssembler::Jump(const Operand& op) {
   2957   if (kPointerSize == kInt64Size) {
   2958     jmp(op);
   2959   } else {
   2960     movp(kScratchRegister, op);
   2961     jmp(kScratchRegister);
   2962   }
   2963 }
   2964 
   2965 
   2966 void MacroAssembler::Jump(Address destination, RelocInfo::Mode rmode) {
   2967   Move(kScratchRegister, destination, rmode);
   2968   jmp(kScratchRegister);
   2969 }
   2970 
   2971 
   2972 void MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) {
   2973   // TODO(X64): Inline this
   2974   jmp(code_object, rmode);
   2975 }
   2976 
   2977 
   2978 int MacroAssembler::CallSize(ExternalReference ext) {
   2979   // Opcode for call kScratchRegister is: Rex.B FF D4 (three bytes).
   2980   return LoadAddressSize(ext) +
   2981          Assembler::kCallScratchRegisterInstructionLength;
   2982 }
   2983 
   2984 
   2985 void MacroAssembler::Call(ExternalReference ext) {
   2986 #ifdef DEBUG
   2987   int end_position = pc_offset() + CallSize(ext);
   2988 #endif
   2989   LoadAddress(kScratchRegister, ext);
   2990   call(kScratchRegister);
   2991 #ifdef DEBUG
   2992   CHECK_EQ(end_position, pc_offset());
   2993 #endif
   2994 }
   2995 
   2996 
   2997 void MacroAssembler::Call(const Operand& op) {
   2998   if (kPointerSize == kInt64Size) {
   2999     call(op);
   3000   } else {
   3001     movp(kScratchRegister, op);
   3002     call(kScratchRegister);
   3003   }
   3004 }
   3005 
   3006 
   3007 void MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) {
   3008 #ifdef DEBUG
   3009   int end_position = pc_offset() + CallSize(destination);
   3010 #endif
   3011   Move(kScratchRegister, destination, rmode);
   3012   call(kScratchRegister);
   3013 #ifdef DEBUG
   3014   CHECK_EQ(pc_offset(), end_position);
   3015 #endif
   3016 }
   3017 
   3018 
   3019 void MacroAssembler::Call(Handle<Code> code_object,
   3020                           RelocInfo::Mode rmode,
   3021                           TypeFeedbackId ast_id) {
   3022 #ifdef DEBUG
   3023   int end_position = pc_offset() + CallSize(code_object);
   3024 #endif
   3025   DCHECK(RelocInfo::IsCodeTarget(rmode) ||
   3026       rmode == RelocInfo::CODE_AGE_SEQUENCE);
   3027   call(code_object, rmode, ast_id);
   3028 #ifdef DEBUG
   3029   CHECK_EQ(end_position, pc_offset());
   3030 #endif
   3031 }
   3032 
   3033 
   3034 void MacroAssembler::Pushad() {
   3035   Push(rax);
   3036   Push(rcx);
   3037   Push(rdx);
   3038   Push(rbx);
   3039   // Not pushing rsp or rbp.
   3040   Push(rsi);
   3041   Push(rdi);
   3042   Push(r8);
   3043   Push(r9);
   3044   // r10 is kScratchRegister.
   3045   Push(r11);
   3046   // r12 is kSmiConstantRegister.
   3047   // r13 is kRootRegister.
   3048   Push(r14);
   3049   Push(r15);
   3050   STATIC_ASSERT(11 == kNumSafepointSavedRegisters);
   3051   // Use lea for symmetry with Popad.
   3052   int sp_delta =
   3053       (kNumSafepointRegisters - kNumSafepointSavedRegisters) * kPointerSize;
   3054   leap(rsp, Operand(rsp, -sp_delta));
   3055 }
   3056 
   3057 
   3058 void MacroAssembler::Popad() {
   3059   // Popad must not change the flags, so use lea instead of addq.
   3060   int sp_delta =
   3061       (kNumSafepointRegisters - kNumSafepointSavedRegisters) * kPointerSize;
   3062   leap(rsp, Operand(rsp, sp_delta));
   3063   Pop(r15);
   3064   Pop(r14);
   3065   Pop(r11);
   3066   Pop(r9);
   3067   Pop(r8);
   3068   Pop(rdi);
   3069   Pop(rsi);
   3070   Pop(rbx);
   3071   Pop(rdx);
   3072   Pop(rcx);
   3073   Pop(rax);
   3074 }
   3075 
   3076 
   3077 void MacroAssembler::Dropad() {
   3078   addp(rsp, Immediate(kNumSafepointRegisters * kPointerSize));
   3079 }
   3080 
   3081 
   3082 // Order general registers are pushed by Pushad:
   3083 // rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r14, r15.
   3084 const int
   3085 MacroAssembler::kSafepointPushRegisterIndices[Register::kNumRegisters] = {
   3086     0,
   3087     1,
   3088     2,
   3089     3,
   3090     -1,
   3091     -1,
   3092     4,
   3093     5,
   3094     6,
   3095     7,
   3096     -1,
   3097     8,
   3098     -1,
   3099     -1,
   3100     9,
   3101     10
   3102 };
   3103 
   3104 
   3105 void MacroAssembler::StoreToSafepointRegisterSlot(Register dst,
   3106                                                   const Immediate& imm) {
   3107   movp(SafepointRegisterSlot(dst), imm);
   3108 }
   3109 
   3110 
   3111 void MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) {
   3112   movp(SafepointRegisterSlot(dst), src);
   3113 }
   3114 
   3115 
   3116 void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
   3117   movp(dst, SafepointRegisterSlot(src));
   3118 }
   3119 
   3120 
   3121 Operand MacroAssembler::SafepointRegisterSlot(Register reg) {
   3122   return Operand(rsp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
   3123 }
   3124 
   3125 
   3126 void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
   3127                                     int handler_index) {
   3128   // Adjust this code if not the case.
   3129   STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize +
   3130                                                 kFPOnStackSize);
   3131   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
   3132   STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
   3133   STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
   3134   STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
   3135   STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
   3136 
   3137   // We will build up the handler from the bottom by pushing on the stack.
   3138   // First push the frame pointer and context.
   3139   if (kind == StackHandler::JS_ENTRY) {
   3140     // The frame pointer does not point to a JS frame so we save NULL for
   3141     // rbp. We expect the code throwing an exception to check rbp before
   3142     // dereferencing it to restore the context.
   3143     pushq(Immediate(0));  // NULL frame pointer.
   3144     Push(Smi::FromInt(0));  // No context.
   3145   } else {
   3146     pushq(rbp);
   3147     Push(rsi);
   3148   }
   3149 
   3150   // Push the state and the code object.
   3151   unsigned state =
   3152       StackHandler::IndexField::encode(handler_index) |
   3153       StackHandler::KindField::encode(kind);
   3154   Push(Immediate(state));
   3155   Push(CodeObject());
   3156 
   3157   // Link the current handler as the next handler.
   3158   ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
   3159   Push(ExternalOperand(handler_address));
   3160   // Set this new handler as the current one.
   3161   movp(ExternalOperand(handler_address), rsp);
   3162 }
   3163 
   3164 
   3165 void MacroAssembler::PopTryHandler() {
   3166   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
   3167   ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
   3168   Pop(ExternalOperand(handler_address));
   3169   addp(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize));
   3170 }
   3171 
   3172 
   3173 void MacroAssembler::JumpToHandlerEntry() {
   3174   // Compute the handler entry address and jump to it.  The handler table is
   3175   // a fixed array of (smi-tagged) code offsets.
   3176   // rax = exception, rdi = code object, rdx = state.
   3177   movp(rbx, FieldOperand(rdi, Code::kHandlerTableOffset));
   3178   shrp(rdx, Immediate(StackHandler::kKindWidth));
   3179   movp(rdx,
   3180        FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize));
   3181   SmiToInteger64(rdx, rdx);
   3182   leap(rdi, FieldOperand(rdi, rdx, times_1, Code::kHeaderSize));
   3183   jmp(rdi);
   3184 }
   3185 
   3186 
   3187 void MacroAssembler::Throw(Register value) {
   3188   // Adjust this code if not the case.
   3189   STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize +
   3190                                                 kFPOnStackSize);
   3191   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
   3192   STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
   3193   STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
   3194   STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
   3195   STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
   3196 
   3197   // The exception is expected in rax.
   3198   if (!value.is(rax)) {
   3199     movp(rax, value);
   3200   }
   3201   // Drop the stack pointer to the top of the top handler.
   3202   ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
   3203   movp(rsp, ExternalOperand(handler_address));
   3204   // Restore the next handler.
   3205   Pop(ExternalOperand(handler_address));
   3206 
   3207   // Remove the code object and state, compute the handler address in rdi.
   3208   Pop(rdi);  // Code object.
   3209   Pop(rdx);  // Offset and state.
   3210 
   3211   // Restore the context and frame pointer.
   3212   Pop(rsi);  // Context.
   3213   popq(rbp);  // Frame pointer.
   3214 
   3215   // If the handler is a JS frame, restore the context to the frame.
   3216   // (kind == ENTRY) == (rbp == 0) == (rsi == 0), so we could test either
   3217   // rbp or rsi.
   3218   Label skip;
   3219   testp(rsi, rsi);
   3220   j(zero, &skip, Label::kNear);
   3221   movp(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
   3222   bind(&skip);
   3223 
   3224   JumpToHandlerEntry();
   3225 }
   3226 
   3227 
   3228 void MacroAssembler::ThrowUncatchable(Register value) {
   3229   // Adjust this code if not the case.
   3230   STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize +
   3231                                                 kFPOnStackSize);
   3232   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
   3233   STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
   3234   STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
   3235   STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
   3236   STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
   3237 
   3238   // The exception is expected in rax.
   3239   if (!value.is(rax)) {
   3240     movp(rax, value);
   3241   }
   3242   // Drop the stack pointer to the top of the top stack handler.
   3243   ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
   3244   Load(rsp, handler_address);
   3245 
   3246   // Unwind the handlers until the top ENTRY handler is found.
   3247   Label fetch_next, check_kind;
   3248   jmp(&check_kind, Label::kNear);
   3249   bind(&fetch_next);
   3250   movp(rsp, Operand(rsp, StackHandlerConstants::kNextOffset));
   3251 
   3252   bind(&check_kind);
   3253   STATIC_ASSERT(StackHandler::JS_ENTRY == 0);
   3254   testl(Operand(rsp, StackHandlerConstants::kStateOffset),
   3255         Immediate(StackHandler::KindField::kMask));
   3256   j(not_zero, &fetch_next);
   3257 
   3258   // Set the top handler address to next handler past the top ENTRY handler.
   3259   Pop(ExternalOperand(handler_address));
   3260 
   3261   // Remove the code object and state, compute the handler address in rdi.
   3262   Pop(rdi);  // Code object.
   3263   Pop(rdx);  // Offset and state.
   3264 
   3265   // Clear the context pointer and frame pointer (0 was saved in the handler).
   3266   Pop(rsi);
   3267   popq(rbp);
   3268 
   3269   JumpToHandlerEntry();
   3270 }
   3271 
   3272 
   3273 void MacroAssembler::Ret() {
   3274   ret(0);
   3275 }
   3276 
   3277 
   3278 void MacroAssembler::Ret(int bytes_dropped, Register scratch) {
   3279   if (is_uint16(bytes_dropped)) {
   3280     ret(bytes_dropped);
   3281   } else {
   3282     PopReturnAddressTo(scratch);
   3283     addp(rsp, Immediate(bytes_dropped));
   3284     PushReturnAddressFrom(scratch);
   3285     ret(0);
   3286   }
   3287 }
   3288 
   3289 
   3290 void MacroAssembler::FCmp() {
   3291   fucomip();
   3292   fstp(0);
   3293 }
   3294 
   3295 
   3296 void MacroAssembler::CmpObjectType(Register heap_object,
   3297                                    InstanceType type,
   3298                                    Register map) {
   3299   movp(map, FieldOperand(heap_object, HeapObject::kMapOffset));
   3300   CmpInstanceType(map, type);
   3301 }
   3302 
   3303 
   3304 void MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
   3305   cmpb(FieldOperand(map, Map::kInstanceTypeOffset),
   3306        Immediate(static_cast<int8_t>(type)));
   3307 }
   3308 
   3309 
   3310 void MacroAssembler::CheckFastElements(Register map,
   3311                                        Label* fail,
   3312                                        Label::Distance distance) {
   3313   STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
   3314   STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
   3315   STATIC_ASSERT(FAST_ELEMENTS == 2);
   3316   STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
   3317   cmpb(FieldOperand(map, Map::kBitField2Offset),
   3318        Immediate(Map::kMaximumBitField2FastHoleyElementValue));
   3319   j(above, fail, distance);
   3320 }
   3321 
   3322 
   3323 void MacroAssembler::CheckFastObjectElements(Register map,
   3324                                              Label* fail,
   3325                                              Label::Distance distance) {
   3326   STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
   3327   STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
   3328   STATIC_ASSERT(FAST_ELEMENTS == 2);
   3329   STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
   3330   cmpb(FieldOperand(map, Map::kBitField2Offset),
   3331        Immediate(Map::kMaximumBitField2FastHoleySmiElementValue));
   3332   j(below_equal, fail, distance);
   3333   cmpb(FieldOperand(map, Map::kBitField2Offset),
   3334        Immediate(Map::kMaximumBitField2FastHoleyElementValue));
   3335   j(above, fail, distance);
   3336 }
   3337 
   3338 
   3339 void MacroAssembler::CheckFastSmiElements(Register map,
   3340                                           Label* fail,
   3341                                           Label::Distance distance) {
   3342   STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
   3343   STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
   3344   cmpb(FieldOperand(map, Map::kBitField2Offset),
   3345        Immediate(Map::kMaximumBitField2FastHoleySmiElementValue));
   3346   j(above, fail, distance);
   3347 }
   3348 
   3349 
   3350 void MacroAssembler::StoreNumberToDoubleElements(
   3351     Register maybe_number,
   3352     Register elements,
   3353     Register index,
   3354     XMMRegister xmm_scratch,
   3355     Label* fail,
   3356     int elements_offset) {
   3357   Label smi_value, is_nan, maybe_nan, not_nan, have_double_value, done;
   3358 
   3359   JumpIfSmi(maybe_number, &smi_value, Label::kNear);
   3360 
   3361   CheckMap(maybe_number,
   3362            isolate()->factory()->heap_number_map(),
   3363            fail,
   3364            DONT_DO_SMI_CHECK);
   3365 
   3366   // Double value, canonicalize NaN.
   3367   uint32_t offset = HeapNumber::kValueOffset + sizeof(kHoleNanLower32);
   3368   cmpl(FieldOperand(maybe_number, offset),
   3369        Immediate(kNaNOrInfinityLowerBoundUpper32));
   3370   j(greater_equal, &maybe_nan, Label::kNear);
   3371 
   3372   bind(&not_nan);
   3373   movsd(xmm_scratch, FieldOperand(maybe_number, HeapNumber::kValueOffset));
   3374   bind(&have_double_value);
   3375   movsd(FieldOperand(elements, index, times_8,
   3376                      FixedDoubleArray::kHeaderSize - elements_offset),
   3377         xmm_scratch);
   3378   jmp(&done);
   3379 
   3380   bind(&maybe_nan);
   3381   // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
   3382   // it's an Infinity, and the non-NaN code path applies.
   3383   j(greater, &is_nan, Label::kNear);
   3384   cmpl(FieldOperand(maybe_number, HeapNumber::kValueOffset), Immediate(0));
   3385   j(zero, &not_nan);
   3386   bind(&is_nan);
   3387   // Convert all NaNs to the same canonical NaN value when they are stored in
   3388   // the double array.
   3389   Set(kScratchRegister,
   3390       bit_cast<uint64_t>(
   3391           FixedDoubleArray::canonical_not_the_hole_nan_as_double()));
   3392   movq(xmm_scratch, kScratchRegister);
   3393   jmp(&have_double_value, Label::kNear);
   3394 
   3395   bind(&smi_value);
   3396   // Value is a smi. convert to a double and store.
   3397   // Preserve original value.
   3398   SmiToInteger32(kScratchRegister, maybe_number);
   3399   Cvtlsi2sd(xmm_scratch, kScratchRegister);
   3400   movsd(FieldOperand(elements, index, times_8,
   3401                      FixedDoubleArray::kHeaderSize - elements_offset),
   3402         xmm_scratch);
   3403   bind(&done);
   3404 }
   3405 
   3406 
   3407 void MacroAssembler::CompareMap(Register obj, Handle<Map> map) {
   3408   Cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
   3409 }
   3410 
   3411 
   3412 void MacroAssembler::CheckMap(Register obj,
   3413                               Handle<Map> map,
   3414                               Label* fail,
   3415                               SmiCheckType smi_check_type) {
   3416   if (smi_check_type == DO_SMI_CHECK) {
   3417     JumpIfSmi(obj, fail);
   3418   }
   3419 
   3420   CompareMap(obj, map);
   3421   j(not_equal, fail);
   3422 }
   3423 
   3424 
   3425 void MacroAssembler::ClampUint8(Register reg) {
   3426   Label done;
   3427   testl(reg, Immediate(0xFFFFFF00));
   3428   j(zero, &done, Label::kNear);
   3429   setcc(negative, reg);  // 1 if negative, 0 if positive.
   3430   decb(reg);  // 0 if negative, 255 if positive.
   3431   bind(&done);
   3432 }
   3433 
   3434 
   3435 void MacroAssembler::ClampDoubleToUint8(XMMRegister input_reg,
   3436                                         XMMRegister temp_xmm_reg,
   3437                                         Register result_reg) {
   3438   Label done;
   3439   Label conv_failure;
   3440   xorps(temp_xmm_reg, temp_xmm_reg);
   3441   cvtsd2si(result_reg, input_reg);
   3442   testl(result_reg, Immediate(0xFFFFFF00));
   3443   j(zero, &done, Label::kNear);
   3444   cmpl(result_reg, Immediate(1));
   3445   j(overflow, &conv_failure, Label::kNear);
   3446   movl(result_reg, Immediate(0));
   3447   setcc(sign, result_reg);
   3448   subl(result_reg, Immediate(1));
   3449   andl(result_reg, Immediate(255));
   3450   jmp(&done, Label::kNear);
   3451   bind(&conv_failure);
   3452   Set(result_reg, 0);
   3453   ucomisd(input_reg, temp_xmm_reg);
   3454   j(below, &done, Label::kNear);
   3455   Set(result_reg, 255);
   3456   bind(&done);
   3457 }
   3458 
   3459 
   3460 void MacroAssembler::LoadUint32(XMMRegister dst,
   3461                                 Register src) {
   3462   if (FLAG_debug_code) {
   3463     cmpq(src, Immediate(0xffffffff));
   3464     Assert(below_equal, kInputGPRIsExpectedToHaveUpper32Cleared);
   3465   }
   3466   cvtqsi2sd(dst, src);
   3467 }
   3468 
   3469 
   3470 void MacroAssembler::SlowTruncateToI(Register result_reg,
   3471                                      Register input_reg,
   3472                                      int offset) {
   3473   DoubleToIStub stub(isolate(), input_reg, result_reg, offset, true);
   3474   call(stub.GetCode(), RelocInfo::CODE_TARGET);
   3475 }
   3476 
   3477 
   3478 void MacroAssembler::TruncateHeapNumberToI(Register result_reg,
   3479                                            Register input_reg) {
   3480   Label done;
   3481   movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
   3482   cvttsd2siq(result_reg, xmm0);
   3483   cmpq(result_reg, Immediate(1));
   3484   j(no_overflow, &done, Label::kNear);
   3485 
   3486   // Slow case.
   3487   if (input_reg.is(result_reg)) {
   3488     subp(rsp, Immediate(kDoubleSize));
   3489     movsd(MemOperand(rsp, 0), xmm0);
   3490     SlowTruncateToI(result_reg, rsp, 0);
   3491     addp(rsp, Immediate(kDoubleSize));
   3492   } else {
   3493     SlowTruncateToI(result_reg, input_reg);
   3494   }
   3495 
   3496   bind(&done);
   3497   // Keep our invariant that the upper 32 bits are zero.
   3498   movl(result_reg, result_reg);
   3499 }
   3500 
   3501 
   3502 void MacroAssembler::TruncateDoubleToI(Register result_reg,
   3503                                        XMMRegister input_reg) {
   3504   Label done;
   3505   cvttsd2siq(result_reg, input_reg);
   3506   cmpq(result_reg, Immediate(1));
   3507   j(no_overflow, &done, Label::kNear);
   3508 
   3509   subp(rsp, Immediate(kDoubleSize));
   3510   movsd(MemOperand(rsp, 0), input_reg);
   3511   SlowTruncateToI(result_reg, rsp, 0);
   3512   addp(rsp, Immediate(kDoubleSize));
   3513 
   3514   bind(&done);
   3515   // Keep our invariant that the upper 32 bits are zero.
   3516   movl(result_reg, result_reg);
   3517 }
   3518 
   3519 
   3520 void MacroAssembler::DoubleToI(Register result_reg, XMMRegister input_reg,
   3521                                XMMRegister scratch,
   3522                                MinusZeroMode minus_zero_mode,
   3523                                Label* lost_precision, Label* is_nan,
   3524                                Label* minus_zero, Label::Distance dst) {
   3525   cvttsd2si(result_reg, input_reg);
   3526   Cvtlsi2sd(xmm0, result_reg);
   3527   ucomisd(xmm0, input_reg);
   3528   j(not_equal, lost_precision, dst);
   3529   j(parity_even, is_nan, dst);  // NaN.
   3530   if (minus_zero_mode == FAIL_ON_MINUS_ZERO) {
   3531     Label done;
   3532     // The integer converted back is equal to the original. We
   3533     // only have to test if we got -0 as an input.
   3534     testl(result_reg, result_reg);
   3535     j(not_zero, &done, Label::kNear);
   3536     movmskpd(result_reg, input_reg);
   3537     // Bit 0 contains the sign of the double in input_reg.
   3538     // If input was positive, we are ok and return 0, otherwise
   3539     // jump to minus_zero.
   3540     andl(result_reg, Immediate(1));
   3541     j(not_zero, minus_zero, dst);
   3542     bind(&done);
   3543   }
   3544 }
   3545 
   3546 
   3547 void MacroAssembler::LoadInstanceDescriptors(Register map,
   3548                                              Register descriptors) {
   3549   movp(descriptors, FieldOperand(map, Map::kDescriptorsOffset));
   3550 }
   3551 
   3552 
   3553 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
   3554   movl(dst, FieldOperand(map, Map::kBitField3Offset));
   3555   DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
   3556 }
   3557 
   3558 
   3559 void MacroAssembler::EnumLength(Register dst, Register map) {
   3560   STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
   3561   movl(dst, FieldOperand(map, Map::kBitField3Offset));
   3562   andl(dst, Immediate(Map::EnumLengthBits::kMask));
   3563   Integer32ToSmi(dst, dst);
   3564 }
   3565 
   3566 
   3567 void MacroAssembler::DispatchMap(Register obj,
   3568                                  Register unused,
   3569                                  Handle<Map> map,
   3570                                  Handle<Code> success,
   3571                                  SmiCheckType smi_check_type) {
   3572   Label fail;
   3573   if (smi_check_type == DO_SMI_CHECK) {
   3574     JumpIfSmi(obj, &fail);
   3575   }
   3576   Cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
   3577   j(equal, success, RelocInfo::CODE_TARGET);
   3578 
   3579   bind(&fail);
   3580 }
   3581 
   3582 
   3583 void MacroAssembler::AssertNumber(Register object) {
   3584   if (emit_debug_code()) {
   3585     Label ok;
   3586     Condition is_smi = CheckSmi(object);
   3587     j(is_smi, &ok, Label::kNear);
   3588     Cmp(FieldOperand(object, HeapObject::kMapOffset),
   3589         isolate()->factory()->heap_number_map());
   3590     Check(equal, kOperandIsNotANumber);
   3591     bind(&ok);
   3592   }
   3593 }
   3594 
   3595 
   3596 void MacroAssembler::AssertNotSmi(Register object) {
   3597   if (emit_debug_code()) {
   3598     Condition is_smi = CheckSmi(object);
   3599     Check(NegateCondition(is_smi), kOperandIsASmi);
   3600   }
   3601 }
   3602 
   3603 
   3604 void MacroAssembler::AssertSmi(Register object) {
   3605   if (emit_debug_code()) {
   3606     Condition is_smi = CheckSmi(object);
   3607     Check(is_smi, kOperandIsNotASmi);
   3608   }
   3609 }
   3610 
   3611 
   3612 void MacroAssembler::AssertSmi(const Operand& object) {
   3613   if (emit_debug_code()) {
   3614     Condition is_smi = CheckSmi(object);
   3615     Check(is_smi, kOperandIsNotASmi);
   3616   }
   3617 }
   3618 
   3619 
   3620 void MacroAssembler::AssertZeroExtended(Register int32_register) {
   3621   if (emit_debug_code()) {
   3622     DCHECK(!int32_register.is(kScratchRegister));
   3623     movq(kScratchRegister, V8_INT64_C(0x0000000100000000));
   3624     cmpq(kScratchRegister, int32_register);
   3625     Check(above_equal, k32BitValueInRegisterIsNotZeroExtended);
   3626   }
   3627 }
   3628 
   3629 
   3630 void MacroAssembler::AssertString(Register object) {
   3631   if (emit_debug_code()) {
   3632     testb(object, Immediate(kSmiTagMask));
   3633     Check(not_equal, kOperandIsASmiAndNotAString);
   3634     Push(object);
   3635     movp(object, FieldOperand(object, HeapObject::kMapOffset));
   3636     CmpInstanceType(object, FIRST_NONSTRING_TYPE);
   3637     Pop(object);
   3638     Check(below, kOperandIsNotAString);
   3639   }
   3640 }
   3641 
   3642 
   3643 void MacroAssembler::AssertName(Register object) {
   3644   if (emit_debug_code()) {
   3645     testb(object, Immediate(kSmiTagMask));
   3646     Check(not_equal, kOperandIsASmiAndNotAName);
   3647     Push(object);
   3648     movp(object, FieldOperand(object, HeapObject::kMapOffset));
   3649     CmpInstanceType(object, LAST_NAME_TYPE);
   3650     Pop(object);
   3651     Check(below_equal, kOperandIsNotAName);
   3652   }
   3653 }
   3654 
   3655 
   3656 void MacroAssembler::AssertUndefinedOrAllocationSite(Register object) {
   3657   if (emit_debug_code()) {
   3658     Label done_checking;
   3659     AssertNotSmi(object);
   3660     Cmp(object, isolate()->factory()->undefined_value());
   3661     j(equal, &done_checking);
   3662     Cmp(FieldOperand(object, 0), isolate()->factory()->allocation_site_map());
   3663     Assert(equal, kExpectedUndefinedOrCell);
   3664     bind(&done_checking);
   3665   }
   3666 }
   3667 
   3668 
   3669 void MacroAssembler::AssertRootValue(Register src,
   3670                                      Heap::RootListIndex root_value_index,
   3671                                      BailoutReason reason) {
   3672   if (emit_debug_code()) {
   3673     DCHECK(!src.is(kScratchRegister));
   3674     LoadRoot(kScratchRegister, root_value_index);
   3675     cmpp(src, kScratchRegister);
   3676     Check(equal, reason);
   3677   }
   3678 }
   3679 
   3680 
   3681 
   3682 Condition MacroAssembler::IsObjectStringType(Register heap_object,
   3683                                              Register map,
   3684                                              Register instance_type) {
   3685   movp(map, FieldOperand(heap_object, HeapObject::kMapOffset));
   3686   movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
   3687   STATIC_ASSERT(kNotStringTag != 0);
   3688   testb(instance_type, Immediate(kIsNotStringMask));
   3689   return zero;
   3690 }
   3691 
   3692 
   3693 Condition MacroAssembler::IsObjectNameType(Register heap_object,
   3694                                            Register map,
   3695                                            Register instance_type) {
   3696   movp(map, FieldOperand(heap_object, HeapObject::kMapOffset));
   3697   movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
   3698   cmpb(instance_type, Immediate(static_cast<uint8_t>(LAST_NAME_TYPE)));
   3699   return below_equal;
   3700 }
   3701 
   3702 
   3703 void MacroAssembler::TryGetFunctionPrototype(Register function,
   3704                                              Register result,
   3705                                              Label* miss,
   3706                                              bool miss_on_bound_function) {
   3707   Label non_instance;
   3708   if (miss_on_bound_function) {
   3709     // Check that the receiver isn't a smi.
   3710     testl(function, Immediate(kSmiTagMask));
   3711     j(zero, miss);
   3712 
   3713     // Check that the function really is a function.
   3714     CmpObjectType(function, JS_FUNCTION_TYPE, result);
   3715     j(not_equal, miss);
   3716 
   3717     movp(kScratchRegister,
   3718          FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
   3719     // It's not smi-tagged (stored in the top half of a smi-tagged 8-byte
   3720     // field).
   3721     TestBitSharedFunctionInfoSpecialField(kScratchRegister,
   3722         SharedFunctionInfo::kCompilerHintsOffset,
   3723         SharedFunctionInfo::kBoundFunction);
   3724     j(not_zero, miss);
   3725 
   3726     // Make sure that the function has an instance prototype.
   3727     testb(FieldOperand(result, Map::kBitFieldOffset),
   3728           Immediate(1 << Map::kHasNonInstancePrototype));
   3729     j(not_zero, &non_instance, Label::kNear);
   3730   }
   3731 
   3732   // Get the prototype or initial map from the function.
   3733   movp(result,
   3734        FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
   3735 
   3736   // If the prototype or initial map is the hole, don't return it and
   3737   // simply miss the cache instead. This will allow us to allocate a
   3738   // prototype object on-demand in the runtime system.
   3739   CompareRoot(result, Heap::kTheHoleValueRootIndex);
   3740   j(equal, miss);
   3741 
   3742   // If the function does not have an initial map, we're done.
   3743   Label done;
   3744   CmpObjectType(result, MAP_TYPE, kScratchRegister);
   3745   j(not_equal, &done, Label::kNear);
   3746 
   3747   // Get the prototype from the initial map.
   3748   movp(result, FieldOperand(result, Map::kPrototypeOffset));
   3749 
   3750   if (miss_on_bound_function) {
   3751     jmp(&done, Label::kNear);
   3752 
   3753     // Non-instance prototype: Fetch prototype from constructor field
   3754     // in initial map.
   3755     bind(&non_instance);
   3756     movp(result, FieldOperand(result, Map::kConstructorOffset));
   3757   }
   3758 
   3759   // All done.
   3760   bind(&done);
   3761 }
   3762 
   3763 
   3764 void MacroAssembler::SetCounter(StatsCounter* counter, int value) {
   3765   if (FLAG_native_code_counters && counter->Enabled()) {
   3766     Operand counter_operand = ExternalOperand(ExternalReference(counter));
   3767     movl(counter_operand, Immediate(value));
   3768   }
   3769 }
   3770 
   3771 
   3772 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
   3773   DCHECK(value > 0);
   3774   if (FLAG_native_code_counters && counter->Enabled()) {
   3775     Operand counter_operand = ExternalOperand(ExternalReference(counter));
   3776     if (value == 1) {
   3777       incl(counter_operand);
   3778     } else {
   3779       addl(counter_operand, Immediate(value));
   3780     }
   3781   }
   3782 }
   3783 
   3784 
   3785 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
   3786   DCHECK(value > 0);
   3787   if (FLAG_native_code_counters && counter->Enabled()) {
   3788     Operand counter_operand = ExternalOperand(ExternalReference(counter));
   3789     if (value == 1) {
   3790       decl(counter_operand);
   3791     } else {
   3792       subl(counter_operand, Immediate(value));
   3793     }
   3794   }
   3795 }
   3796 
   3797 
   3798 void MacroAssembler::DebugBreak() {
   3799   Set(rax, 0);  // No arguments.
   3800   LoadAddress(rbx, ExternalReference(Runtime::kDebugBreak, isolate()));
   3801   CEntryStub ces(isolate(), 1);
   3802   DCHECK(AllowThisStubCall(&ces));
   3803   Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
   3804 }
   3805 
   3806 
   3807 void MacroAssembler::InvokeCode(Register code,
   3808                                 const ParameterCount& expected,
   3809                                 const ParameterCount& actual,
   3810                                 InvokeFlag flag,
   3811                                 const CallWrapper& call_wrapper) {
   3812   // You can't call a function without a valid frame.
   3813   DCHECK(flag == JUMP_FUNCTION || has_frame());
   3814 
   3815   Label done;
   3816   bool definitely_mismatches = false;
   3817   InvokePrologue(expected,
   3818                  actual,
   3819                  Handle<Code>::null(),
   3820                  code,
   3821                  &done,
   3822                  &definitely_mismatches,
   3823                  flag,
   3824                  Label::kNear,
   3825                  call_wrapper);
   3826   if (!definitely_mismatches) {
   3827     if (flag == CALL_FUNCTION) {
   3828       call_wrapper.BeforeCall(CallSize(code));
   3829       call(code);
   3830       call_wrapper.AfterCall();
   3831     } else {
   3832       DCHECK(flag == JUMP_FUNCTION);
   3833       jmp(code);
   3834     }
   3835     bind(&done);
   3836   }
   3837 }
   3838 
   3839 
   3840 void MacroAssembler::InvokeFunction(Register function,
   3841                                     const ParameterCount& actual,
   3842                                     InvokeFlag flag,
   3843                                     const CallWrapper& call_wrapper) {
   3844   // You can't call a function without a valid frame.
   3845   DCHECK(flag == JUMP_FUNCTION || has_frame());
   3846 
   3847   DCHECK(function.is(rdi));
   3848   movp(rdx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
   3849   movp(rsi, FieldOperand(function, JSFunction::kContextOffset));
   3850   LoadSharedFunctionInfoSpecialField(rbx, rdx,
   3851       SharedFunctionInfo::kFormalParameterCountOffset);
   3852   // Advances rdx to the end of the Code object header, to the start of
   3853   // the executable code.
   3854   movp(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
   3855 
   3856   ParameterCount expected(rbx);
   3857   InvokeCode(rdx, expected, actual, flag, call_wrapper);
   3858 }
   3859 
   3860 
   3861 void MacroAssembler::InvokeFunction(Register function,
   3862                                     const ParameterCount& expected,
   3863                                     const ParameterCount& actual,
   3864                                     InvokeFlag flag,
   3865                                     const CallWrapper& call_wrapper) {
   3866   // You can't call a function without a valid frame.
   3867   DCHECK(flag == JUMP_FUNCTION || has_frame());
   3868 
   3869   DCHECK(function.is(rdi));
   3870   movp(rsi, FieldOperand(function, JSFunction::kContextOffset));
   3871   // Advances rdx to the end of the Code object header, to the start of
   3872   // the executable code.
   3873   movp(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
   3874 
   3875   InvokeCode(rdx, expected, actual, flag, call_wrapper);
   3876 }
   3877 
   3878 
   3879 void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
   3880                                     const ParameterCount& expected,
   3881                                     const ParameterCount& actual,
   3882                                     InvokeFlag flag,
   3883                                     const CallWrapper& call_wrapper) {
   3884   Move(rdi, function);
   3885   InvokeFunction(rdi, expected, actual, flag, call_wrapper);
   3886 }
   3887 
   3888 
   3889 void MacroAssembler::InvokePrologue(const ParameterCount& expected,
   3890                                     const ParameterCount& actual,
   3891                                     Handle<Code> code_constant,
   3892                                     Register code_register,
   3893                                     Label* done,
   3894                                     bool* definitely_mismatches,
   3895                                     InvokeFlag flag,
   3896                                     Label::Distance near_jump,
   3897                                     const CallWrapper& call_wrapper) {
   3898   bool definitely_matches = false;
   3899   *definitely_mismatches = false;
   3900   Label invoke;
   3901   if (expected.is_immediate()) {
   3902     DCHECK(actual.is_immediate());
   3903     if (expected.immediate() == actual.immediate()) {
   3904       definitely_matches = true;
   3905     } else {
   3906       Set(rax, actual.immediate());
   3907       if (expected.immediate() ==
   3908               SharedFunctionInfo::kDontAdaptArgumentsSentinel) {
   3909         // Don't worry about adapting arguments for built-ins that
   3910         // don't want that done. Skip adaption code by making it look
   3911         // like we have a match between expected and actual number of
   3912         // arguments.
   3913         definitely_matches = true;
   3914       } else {
   3915         *definitely_mismatches = true;
   3916         Set(rbx, expected.immediate());
   3917       }
   3918     }
   3919   } else {
   3920     if (actual.is_immediate()) {
   3921       // Expected is in register, actual is immediate. This is the
   3922       // case when we invoke function values without going through the
   3923       // IC mechanism.
   3924       cmpp(expected.reg(), Immediate(actual.immediate()));
   3925       j(equal, &invoke, Label::kNear);
   3926       DCHECK(expected.reg().is(rbx));
   3927       Set(rax, actual.immediate());
   3928     } else if (!expected.reg().is(actual.reg())) {
   3929       // Both expected and actual are in (different) registers. This
   3930       // is the case when we invoke functions using call and apply.
   3931       cmpp(expected.reg(), actual.reg());
   3932       j(equal, &invoke, Label::kNear);
   3933       DCHECK(actual.reg().is(rax));
   3934       DCHECK(expected.reg().is(rbx));
   3935     }
   3936   }
   3937 
   3938   if (!definitely_matches) {
   3939     Handle<Code> adaptor = isolate()->builtins()->ArgumentsAdaptorTrampoline();
   3940     if (!code_constant.is_null()) {
   3941       Move(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT);
   3942       addp(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag));
   3943     } else if (!code_register.is(rdx)) {
   3944       movp(rdx, code_register);
   3945     }
   3946 
   3947     if (flag == CALL_FUNCTION) {
   3948       call_wrapper.BeforeCall(CallSize(adaptor));
   3949       Call(adaptor, RelocInfo::CODE_TARGET);
   3950       call_wrapper.AfterCall();
   3951       if (!*definitely_mismatches) {
   3952         jmp(done, near_jump);
   3953       }
   3954     } else {
   3955       Jump(adaptor, RelocInfo::CODE_TARGET);
   3956     }
   3957     bind(&invoke);
   3958   }
   3959 }
   3960 
   3961 
   3962 void MacroAssembler::StubPrologue() {
   3963     pushq(rbp);  // Caller's frame pointer.
   3964     movp(rbp, rsp);
   3965     Push(rsi);  // Callee's context.
   3966     Push(Smi::FromInt(StackFrame::STUB));
   3967 }
   3968 
   3969 
   3970 void MacroAssembler::Prologue(bool code_pre_aging) {
   3971   PredictableCodeSizeScope predictible_code_size_scope(this,
   3972       kNoCodeAgeSequenceLength);
   3973   if (code_pre_aging) {
   3974       // Pre-age the code.
   3975     Call(isolate()->builtins()->MarkCodeAsExecutedOnce(),
   3976          RelocInfo::CODE_AGE_SEQUENCE);
   3977     Nop(kNoCodeAgeSequenceLength - Assembler::kShortCallInstructionLength);
   3978   } else {
   3979     pushq(rbp);  // Caller's frame pointer.
   3980     movp(rbp, rsp);
   3981     Push(rsi);  // Callee's context.
   3982     Push(rdi);  // Callee's JS function.
   3983   }
   3984 }
   3985 
   3986 
   3987 void MacroAssembler::EnterFrame(StackFrame::Type type) {
   3988   pushq(rbp);
   3989   movp(rbp, rsp);
   3990   Push(rsi);  // Context.
   3991   Push(Smi::FromInt(type));
   3992   Move(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
   3993   Push(kScratchRegister);
   3994   if (emit_debug_code()) {
   3995     Move(kScratchRegister,
   3996          isolate()->factory()->undefined_value(),
   3997          RelocInfo::EMBEDDED_OBJECT);
   3998     cmpp(Operand(rsp, 0), kScratchRegister);
   3999     Check(not_equal, kCodeObjectNotProperlyPatched);
   4000   }
   4001 }
   4002 
   4003 
   4004 void MacroAssembler::LeaveFrame(StackFrame::Type type) {
   4005   if (emit_debug_code()) {
   4006     Move(kScratchRegister, Smi::FromInt(type));
   4007     cmpp(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister);
   4008     Check(equal, kStackFrameTypesMustMatch);
   4009   }
   4010   movp(rsp, rbp);
   4011   popq(rbp);
   4012 }
   4013 
   4014 
   4015 void MacroAssembler::EnterExitFramePrologue(bool save_rax) {
   4016   // Set up the frame structure on the stack.
   4017   // All constants are relative to the frame pointer of the exit frame.
   4018   DCHECK(ExitFrameConstants::kCallerSPDisplacement ==
   4019          kFPOnStackSize + kPCOnStackSize);
   4020   DCHECK(ExitFrameConstants::kCallerPCOffset == kFPOnStackSize);
   4021   DCHECK(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize);
   4022   pushq(rbp);
   4023   movp(rbp, rsp);
   4024 
   4025   // Reserve room for entry stack pointer and push the code object.
   4026   DCHECK(ExitFrameConstants::kSPOffset == -1 * kPointerSize);
   4027   Push(Immediate(0));  // Saved entry sp, patched before call.
   4028   Move(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
   4029   Push(kScratchRegister);  // Accessed from EditFrame::code_slot.
   4030 
   4031   // Save the frame pointer and the context in top.
   4032   if (save_rax) {
   4033     movp(r14, rax);  // Backup rax in callee-save register.
   4034   }
   4035 
   4036   Store(ExternalReference(Isolate::kCEntryFPAddress, isolate()), rbp);
   4037   Store(ExternalReference(Isolate::kContextAddress, isolate()), rsi);
   4038 }
   4039 
   4040 
   4041 void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space,
   4042                                             bool save_doubles) {
   4043 #ifdef _WIN64
   4044   const int kShadowSpace = 4;
   4045   arg_stack_space += kShadowSpace;
   4046 #endif
   4047   // Optionally save all XMM registers.
   4048   if (save_doubles) {
   4049     int space = XMMRegister::kMaxNumAllocatableRegisters * kDoubleSize +
   4050         arg_stack_space * kRegisterSize;
   4051     subp(rsp, Immediate(space));
   4052     int offset = -2 * kPointerSize;
   4053     for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); i++) {
   4054       XMMRegister reg = XMMRegister::FromAllocationIndex(i);
   4055       movsd(Operand(rbp, offset - ((i + 1) * kDoubleSize)), reg);
   4056     }
   4057   } else if (arg_stack_space > 0) {
   4058     subp(rsp, Immediate(arg_stack_space * kRegisterSize));
   4059   }
   4060 
   4061   // Get the required frame alignment for the OS.
   4062   const int kFrameAlignment = base::OS::ActivationFrameAlignment();
   4063   if (kFrameAlignment > 0) {
   4064     DCHECK(base::bits::IsPowerOfTwo32(kFrameAlignment));
   4065     DCHECK(is_int8(kFrameAlignment));
   4066     andp(rsp, Immediate(-kFrameAlignment));
   4067   }
   4068 
   4069   // Patch the saved entry sp.
   4070   movp(Operand(rbp, ExitFrameConstants::kSPOffset), rsp);
   4071 }
   4072 
   4073 
   4074 void MacroAssembler::EnterExitFrame(int arg_stack_space, bool save_doubles) {
   4075   EnterExitFramePrologue(true);
   4076 
   4077   // Set up argv in callee-saved register r15. It is reused in LeaveExitFrame,
   4078   // so it must be retained across the C-call.
   4079   int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
   4080   leap(r15, Operand(rbp, r14, times_pointer_size, offset));
   4081 
   4082   EnterExitFrameEpilogue(arg_stack_space, save_doubles);
   4083 }
   4084 
   4085 
   4086 void MacroAssembler::EnterApiExitFrame(int arg_stack_space) {
   4087   EnterExitFramePrologue(false);
   4088   EnterExitFrameEpilogue(arg_stack_space, false);
   4089 }
   4090 
   4091 
   4092 void MacroAssembler::LeaveExitFrame(bool save_doubles) {
   4093   // Registers:
   4094   // r15 : argv
   4095   if (save_doubles) {
   4096     int offset = -2 * kPointerSize;
   4097     for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); i++) {
   4098       XMMRegister reg = XMMRegister::FromAllocationIndex(i);
   4099       movsd(reg, Operand(rbp, offset - ((i + 1) * kDoubleSize)));
   4100     }
   4101   }
   4102   // Get the return address from the stack and restore the frame pointer.
   4103   movp(rcx, Operand(rbp, kFPOnStackSize));
   4104   movp(rbp, Operand(rbp, 0 * kPointerSize));
   4105 
   4106   // Drop everything up to and including the arguments and the receiver
   4107   // from the caller stack.
   4108   leap(rsp, Operand(r15, 1 * kPointerSize));
   4109 
   4110   PushReturnAddressFrom(rcx);
   4111 
   4112   LeaveExitFrameEpilogue(true);
   4113 }
   4114 
   4115 
   4116 void MacroAssembler::LeaveApiExitFrame(bool restore_context) {
   4117   movp(rsp, rbp);
   4118   popq(rbp);
   4119 
   4120   LeaveExitFrameEpilogue(restore_context);
   4121 }
   4122 
   4123 
   4124 void MacroAssembler::LeaveExitFrameEpilogue(bool restore_context) {
   4125   // Restore current context from top and clear it in debug mode.
   4126   ExternalReference context_address(Isolate::kContextAddress, isolate());
   4127   Operand context_operand = ExternalOperand(context_address);
   4128   if (restore_context) {
   4129     movp(rsi, context_operand);
   4130   }
   4131 #ifdef DEBUG
   4132   movp(context_operand, Immediate(0));
   4133 #endif
   4134 
   4135   // Clear the top frame.
   4136   ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress,
   4137                                        isolate());
   4138   Operand c_entry_fp_operand = ExternalOperand(c_entry_fp_address);
   4139   movp(c_entry_fp_operand, Immediate(0));
   4140 }
   4141 
   4142 
   4143 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
   4144                                             Register scratch,
   4145                                             Label* miss) {
   4146   Label same_contexts;
   4147 
   4148   DCHECK(!holder_reg.is(scratch));
   4149   DCHECK(!scratch.is(kScratchRegister));
   4150   // Load current lexical context from the stack frame.
   4151   movp(scratch, Operand(rbp, StandardFrameConstants::kContextOffset));
   4152 
   4153   // When generating debug code, make sure the lexical context is set.
   4154   if (emit_debug_code()) {
   4155     cmpp(scratch, Immediate(0));
   4156     Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext);
   4157   }
   4158   // Load the native context of the current context.
   4159   int offset =
   4160       Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
   4161   movp(scratch, FieldOperand(scratch, offset));
   4162   movp(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset));
   4163 
   4164   // Check the context is a native context.
   4165   if (emit_debug_code()) {
   4166     Cmp(FieldOperand(scratch, HeapObject::kMapOffset),
   4167         isolate()->factory()->native_context_map());
   4168     Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
   4169   }
   4170 
   4171   // Check if both contexts are the same.
   4172   cmpp(scratch, FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
   4173   j(equal, &same_contexts);
   4174 
   4175   // Compare security tokens.
   4176   // Check that the security token in the calling global object is
   4177   // compatible with the security token in the receiving global
   4178   // object.
   4179 
   4180   // Check the context is a native context.
   4181   if (emit_debug_code()) {
   4182     // Preserve original value of holder_reg.
   4183     Push(holder_reg);
   4184     movp(holder_reg,
   4185          FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
   4186     CompareRoot(holder_reg, Heap::kNullValueRootIndex);
   4187     Check(not_equal, kJSGlobalProxyContextShouldNotBeNull);
   4188 
   4189     // Read the first word and compare to native_context_map(),
   4190     movp(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset));
   4191     CompareRoot(holder_reg, Heap::kNativeContextMapRootIndex);
   4192     Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
   4193     Pop(holder_reg);
   4194   }
   4195 
   4196   movp(kScratchRegister,
   4197        FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
   4198   int token_offset =
   4199       Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize;
   4200   movp(scratch, FieldOperand(scratch, token_offset));
   4201   cmpp(scratch, FieldOperand(kScratchRegister, token_offset));
   4202   j(not_equal, miss);
   4203 
   4204   bind(&same_contexts);
   4205 }
   4206 
   4207 
   4208 // Compute the hash code from the untagged key.  This must be kept in sync with
   4209 // ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
   4210 // code-stub-hydrogen.cc
   4211 void MacroAssembler::GetNumberHash(Register r0, Register scratch) {
   4212   // First of all we assign the hash seed to scratch.
   4213   LoadRoot(scratch, Heap::kHashSeedRootIndex);
   4214   SmiToInteger32(scratch, scratch);
   4215 
   4216   // Xor original key with a seed.
   4217   xorl(r0, scratch);
   4218 
   4219   // Compute the hash code from the untagged key.  This must be kept in sync
   4220   // with ComputeIntegerHash in utils.h.
   4221   //
   4222   // hash = ~hash + (hash << 15);
   4223   movl(scratch, r0);
   4224   notl(r0);
   4225   shll(scratch, Immediate(15));
   4226   addl(r0, scratch);
   4227   // hash = hash ^ (hash >> 12);
   4228   movl(scratch, r0);
   4229   shrl(scratch, Immediate(12));
   4230   xorl(r0, scratch);
   4231   // hash = hash + (hash << 2);
   4232   leal(r0, Operand(r0, r0, times_4, 0));
   4233   // hash = hash ^ (hash >> 4);
   4234   movl(scratch, r0);
   4235   shrl(scratch, Immediate(4));
   4236   xorl(r0, scratch);
   4237   // hash = hash * 2057;
   4238   imull(r0, r0, Immediate(2057));
   4239   // hash = hash ^ (hash >> 16);
   4240   movl(scratch, r0);
   4241   shrl(scratch, Immediate(16));
   4242   xorl(r0, scratch);
   4243 }
   4244 
   4245 
   4246 
   4247 void MacroAssembler::LoadFromNumberDictionary(Label* miss,
   4248                                               Register elements,
   4249                                               Register key,
   4250                                               Register r0,
   4251                                               Register r1,
   4252                                               Register r2,
   4253                                               Register result) {
   4254   // Register use:
   4255   //
   4256   // elements - holds the slow-case elements of the receiver on entry.
   4257   //            Unchanged unless 'result' is the same register.
   4258   //
   4259   // key      - holds the smi key on entry.
   4260   //            Unchanged unless 'result' is the same register.
   4261   //
   4262   // Scratch registers:
   4263   //
   4264   // r0 - holds the untagged key on entry and holds the hash once computed.
   4265   //
   4266   // r1 - used to hold the capacity mask of the dictionary
   4267   //
   4268   // r2 - used for the index into the dictionary.
   4269   //
   4270   // result - holds the result on exit if the load succeeded.
   4271   //          Allowed to be the same as 'key' or 'result'.
   4272   //          Unchanged on bailout so 'key' or 'result' can be used
   4273   //          in further computation.
   4274 
   4275   Label done;
   4276 
   4277   GetNumberHash(r0, r1);
   4278 
   4279   // Compute capacity mask.
   4280   SmiToInteger32(r1, FieldOperand(elements,
   4281                                   SeededNumberDictionary::kCapacityOffset));
   4282   decl(r1);
   4283 
   4284   // Generate an unrolled loop that performs a few probes before giving up.
   4285   for (int i = 0; i < kNumberDictionaryProbes; i++) {
   4286     // Use r2 for index calculations and keep the hash intact in r0.
   4287     movp(r2, r0);
   4288     // Compute the masked index: (hash + i + i * i) & mask.
   4289     if (i > 0) {
   4290       addl(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i)));
   4291     }
   4292     andp(r2, r1);
   4293 
   4294     // Scale the index by multiplying by the entry size.
   4295     DCHECK(SeededNumberDictionary::kEntrySize == 3);
   4296     leap(r2, Operand(r2, r2, times_2, 0));  // r2 = r2 * 3
   4297 
   4298     // Check if the key matches.
   4299     cmpp(key, FieldOperand(elements,
   4300                            r2,
   4301                            times_pointer_size,
   4302                            SeededNumberDictionary::kElementsStartOffset));
   4303     if (i != (kNumberDictionaryProbes - 1)) {
   4304       j(equal, &done);
   4305     } else {
   4306       j(not_equal, miss);
   4307     }
   4308   }
   4309 
   4310   bind(&done);
   4311   // Check that the value is a normal propety.
   4312   const int kDetailsOffset =
   4313       SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
   4314   DCHECK_EQ(NORMAL, 0);
   4315   Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
   4316        Smi::FromInt(PropertyDetails::TypeField::kMask));
   4317   j(not_zero, miss);
   4318 
   4319   // Get the value at the masked, scaled index.
   4320   const int kValueOffset =
   4321       SeededNumberDictionary::kElementsStartOffset + kPointerSize;
   4322   movp(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
   4323 }
   4324 
   4325 
   4326 void MacroAssembler::LoadAllocationTopHelper(Register result,
   4327                                              Register scratch,
   4328                                              AllocationFlags flags) {
   4329   ExternalReference allocation_top =
   4330       AllocationUtils::GetAllocationTopReference(isolate(), flags);
   4331 
   4332   // Just return if allocation top is already known.
   4333   if ((flags & RESULT_CONTAINS_TOP) != 0) {
   4334     // No use of scratch if allocation top is provided.
   4335     DCHECK(!scratch.is_valid());
   4336 #ifdef DEBUG
   4337     // Assert that result actually contains top on entry.
   4338     Operand top_operand = ExternalOperand(allocation_top);
   4339     cmpp(result, top_operand);
   4340     Check(equal, kUnexpectedAllocationTop);
   4341 #endif
   4342     return;
   4343   }
   4344 
   4345   // Move address of new object to result. Use scratch register if available,
   4346   // and keep address in scratch until call to UpdateAllocationTopHelper.
   4347   if (scratch.is_valid()) {
   4348     LoadAddress(scratch, allocation_top);
   4349     movp(result, Operand(scratch, 0));
   4350   } else {
   4351     Load(result, allocation_top);
   4352   }
   4353 }
   4354 
   4355 
   4356 void MacroAssembler::MakeSureDoubleAlignedHelper(Register result,
   4357                                                  Register scratch,
   4358                                                  Label* gc_required,
   4359                                                  AllocationFlags flags) {
   4360   if (kPointerSize == kDoubleSize) {
   4361     if (FLAG_debug_code) {
   4362       testl(result, Immediate(kDoubleAlignmentMask));
   4363       Check(zero, kAllocationIsNotDoubleAligned);
   4364     }
   4365   } else {
   4366     // Align the next allocation. Storing the filler map without checking top
   4367     // is safe in new-space because the limit of the heap is aligned there.
   4368     DCHECK(kPointerSize * 2 == kDoubleSize);
   4369     DCHECK((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
   4370     DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
   4371     // Make sure scratch is not clobbered by this function as it might be
   4372     // used in UpdateAllocationTopHelper later.
   4373     DCHECK(!scratch.is(kScratchRegister));
   4374     Label aligned;
   4375     testl(result, Immediate(kDoubleAlignmentMask));
   4376     j(zero, &aligned, Label::kNear);
   4377     if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) {
   4378       ExternalReference allocation_limit =
   4379           AllocationUtils::GetAllocationLimitReference(isolate(), flags);
   4380       cmpp(result, ExternalOperand(allocation_limit));
   4381       j(above_equal, gc_required);
   4382     }
   4383     LoadRoot(kScratchRegister, Heap::kOnePointerFillerMapRootIndex);
   4384     movp(Operand(result, 0), kScratchRegister);
   4385     addp(result, Immediate(kDoubleSize / 2));
   4386     bind(&aligned);
   4387   }
   4388 }
   4389 
   4390 
   4391 void MacroAssembler::UpdateAllocationTopHelper(Register result_end,
   4392                                                Register scratch,
   4393                                                AllocationFlags flags) {
   4394   if (emit_debug_code()) {
   4395     testp(result_end, Immediate(kObjectAlignmentMask));
   4396     Check(zero, kUnalignedAllocationInNewSpace);
   4397   }
   4398 
   4399   ExternalReference allocation_top =
   4400       AllocationUtils::GetAllocationTopReference(isolate(), flags);
   4401 
   4402   // Update new top.
   4403   if (scratch.is_valid()) {
   4404     // Scratch already contains address of allocation top.
   4405     movp(Operand(scratch, 0), result_end);
   4406   } else {
   4407     Store(allocation_top, result_end);
   4408   }
   4409 }
   4410 
   4411 
   4412 void MacroAssembler::Allocate(int object_size,
   4413                               Register result,
   4414                               Register result_end,
   4415                               Register scratch,
   4416                               Label* gc_required,
   4417                               AllocationFlags flags) {
   4418   DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
   4419   DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
   4420   if (!FLAG_inline_new) {
   4421     if (emit_debug_code()) {
   4422       // Trash the registers to simulate an allocation failure.
   4423       movl(result, Immediate(0x7091));
   4424       if (result_end.is_valid()) {
   4425         movl(result_end, Immediate(0x7191));
   4426       }
   4427       if (scratch.is_valid()) {
   4428         movl(scratch, Immediate(0x7291));
   4429       }
   4430     }
   4431     jmp(gc_required);
   4432     return;
   4433   }
   4434   DCHECK(!result.is(result_end));
   4435 
   4436   // Load address of new object into result.
   4437   LoadAllocationTopHelper(result, scratch, flags);
   4438 
   4439   if ((flags & DOUBLE_ALIGNMENT) != 0) {
   4440     MakeSureDoubleAlignedHelper(result, scratch, gc_required, flags);
   4441   }
   4442 
   4443   // Calculate new top and bail out if new space is exhausted.
   4444   ExternalReference allocation_limit =
   4445       AllocationUtils::GetAllocationLimitReference(isolate(), flags);
   4446 
   4447   Register top_reg = result_end.is_valid() ? result_end : result;
   4448 
   4449   if (!top_reg.is(result)) {
   4450     movp(top_reg, result);
   4451   }
   4452   addp(top_reg, Immediate(object_size));
   4453   j(carry, gc_required);
   4454   Operand limit_operand = ExternalOperand(allocation_limit);
   4455   cmpp(top_reg, limit_operand);
   4456   j(above, gc_required);
   4457 
   4458   // Update allocation top.
   4459   UpdateAllocationTopHelper(top_reg, scratch, flags);
   4460 
   4461   bool tag_result = (flags & TAG_OBJECT) != 0;
   4462   if (top_reg.is(result)) {
   4463     if (tag_result) {
   4464       subp(result, Immediate(object_size - kHeapObjectTag));
   4465     } else {
   4466       subp(result, Immediate(object_size));
   4467     }
   4468   } else if (tag_result) {
   4469     // Tag the result if requested.
   4470     DCHECK(kHeapObjectTag == 1);
   4471     incp(result);
   4472   }
   4473 }
   4474 
   4475 
   4476 void MacroAssembler::Allocate(int header_size,
   4477                               ScaleFactor element_size,
   4478                               Register element_count,
   4479                               Register result,
   4480                               Register result_end,
   4481                               Register scratch,
   4482                               Label* gc_required,
   4483                               AllocationFlags flags) {
   4484   DCHECK((flags & SIZE_IN_WORDS) == 0);
   4485   leap(result_end, Operand(element_count, element_size, header_size));
   4486   Allocate(result_end, result, result_end, scratch, gc_required, flags);
   4487 }
   4488 
   4489 
   4490 void MacroAssembler::Allocate(Register object_size,
   4491                               Register result,
   4492                               Register result_end,
   4493                               Register scratch,
   4494                               Label* gc_required,
   4495                               AllocationFlags flags) {
   4496   DCHECK((flags & SIZE_IN_WORDS) == 0);
   4497   if (!FLAG_inline_new) {
   4498     if (emit_debug_code()) {
   4499       // Trash the registers to simulate an allocation failure.
   4500       movl(result, Immediate(0x7091));
   4501       movl(result_end, Immediate(0x7191));
   4502       if (scratch.is_valid()) {
   4503         movl(scratch, Immediate(0x7291));
   4504       }
   4505       // object_size is left unchanged by this function.
   4506     }
   4507     jmp(gc_required);
   4508     return;
   4509   }
   4510   DCHECK(!result.is(result_end));
   4511 
   4512   // Load address of new object into result.
   4513   LoadAllocationTopHelper(result, scratch, flags);
   4514 
   4515   if ((flags & DOUBLE_ALIGNMENT) != 0) {
   4516     MakeSureDoubleAlignedHelper(result, scratch, gc_required, flags);
   4517   }
   4518 
   4519   // Calculate new top and bail out if new space is exhausted.
   4520   ExternalReference allocation_limit =
   4521       AllocationUtils::GetAllocationLimitReference(isolate(), flags);
   4522   if (!object_size.is(result_end)) {
   4523     movp(result_end, object_size);
   4524   }
   4525   addp(result_end, result);
   4526   j(carry, gc_required);
   4527   Operand limit_operand = ExternalOperand(allocation_limit);
   4528   cmpp(result_end, limit_operand);
   4529   j(above, gc_required);
   4530 
   4531   // Update allocation top.
   4532   UpdateAllocationTopHelper(result_end, scratch, flags);
   4533 
   4534   // Tag the result if requested.
   4535   if ((flags & TAG_OBJECT) != 0) {
   4536     addp(result, Immediate(kHeapObjectTag));
   4537   }
   4538 }
   4539 
   4540 
   4541 void MacroAssembler::UndoAllocationInNewSpace(Register object) {
   4542   ExternalReference new_space_allocation_top =
   4543       ExternalReference::new_space_allocation_top_address(isolate());
   4544 
   4545   // Make sure the object has no tag before resetting top.
   4546   andp(object, Immediate(~kHeapObjectTagMask));
   4547   Operand top_operand = ExternalOperand(new_space_allocation_top);
   4548 #ifdef DEBUG
   4549   cmpp(object, top_operand);
   4550   Check(below, kUndoAllocationOfNonAllocatedMemory);
   4551 #endif
   4552   movp(top_operand, object);
   4553 }
   4554 
   4555 
   4556 void MacroAssembler::AllocateHeapNumber(Register result,
   4557                                         Register scratch,
   4558                                         Label* gc_required,
   4559                                         MutableMode mode) {
   4560   // Allocate heap number in new space.
   4561   Allocate(HeapNumber::kSize, result, scratch, no_reg, gc_required, TAG_OBJECT);
   4562 
   4563   Heap::RootListIndex map_index = mode == MUTABLE
   4564       ? Heap::kMutableHeapNumberMapRootIndex
   4565       : Heap::kHeapNumberMapRootIndex;
   4566 
   4567   // Set the map.
   4568   LoadRoot(kScratchRegister, map_index);
   4569   movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
   4570 }
   4571 
   4572 
   4573 void MacroAssembler::AllocateTwoByteString(Register result,
   4574                                            Register length,
   4575                                            Register scratch1,
   4576                                            Register scratch2,
   4577                                            Register scratch3,
   4578                                            Label* gc_required) {
   4579   // Calculate the number of bytes needed for the characters in the string while
   4580   // observing object alignment.
   4581   const int kHeaderAlignment = SeqTwoByteString::kHeaderSize &
   4582                                kObjectAlignmentMask;
   4583   DCHECK(kShortSize == 2);
   4584   // scratch1 = length * 2 + kObjectAlignmentMask.
   4585   leap(scratch1, Operand(length, length, times_1, kObjectAlignmentMask +
   4586                 kHeaderAlignment));
   4587   andp(scratch1, Immediate(~kObjectAlignmentMask));
   4588   if (kHeaderAlignment > 0) {
   4589     subp(scratch1, Immediate(kHeaderAlignment));
   4590   }
   4591 
   4592   // Allocate two byte string in new space.
   4593   Allocate(SeqTwoByteString::kHeaderSize,
   4594            times_1,
   4595            scratch1,
   4596            result,
   4597            scratch2,
   4598            scratch3,
   4599            gc_required,
   4600            TAG_OBJECT);
   4601 
   4602   // Set the map, length and hash field.
   4603   LoadRoot(kScratchRegister, Heap::kStringMapRootIndex);
   4604   movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
   4605   Integer32ToSmi(scratch1, length);
   4606   movp(FieldOperand(result, String::kLengthOffset), scratch1);
   4607   movp(FieldOperand(result, String::kHashFieldOffset),
   4608        Immediate(String::kEmptyHashField));
   4609 }
   4610 
   4611 
   4612 void MacroAssembler::AllocateOneByteString(Register result, Register length,
   4613                                            Register scratch1, Register scratch2,
   4614                                            Register scratch3,
   4615                                            Label* gc_required) {
   4616   // Calculate the number of bytes needed for the characters in the string while
   4617   // observing object alignment.
   4618   const int kHeaderAlignment = SeqOneByteString::kHeaderSize &
   4619                                kObjectAlignmentMask;
   4620   movl(scratch1, length);
   4621   DCHECK(kCharSize == 1);
   4622   addp(scratch1, Immediate(kObjectAlignmentMask + kHeaderAlignment));
   4623   andp(scratch1, Immediate(~kObjectAlignmentMask));
   4624   if (kHeaderAlignment > 0) {
   4625     subp(scratch1, Immediate(kHeaderAlignment));
   4626   }
   4627 
   4628   // Allocate one-byte string in new space.
   4629   Allocate(SeqOneByteString::kHeaderSize,
   4630            times_1,
   4631            scratch1,
   4632            result,
   4633            scratch2,
   4634            scratch3,
   4635            gc_required,
   4636            TAG_OBJECT);
   4637 
   4638   // Set the map, length and hash field.
   4639   LoadRoot(kScratchRegister, Heap::kOneByteStringMapRootIndex);
   4640   movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
   4641   Integer32ToSmi(scratch1, length);
   4642   movp(FieldOperand(result, String::kLengthOffset), scratch1);
   4643   movp(FieldOperand(result, String::kHashFieldOffset),
   4644        Immediate(String::kEmptyHashField));
   4645 }
   4646 
   4647 
   4648 void MacroAssembler::AllocateTwoByteConsString(Register result,
   4649                                         Register scratch1,
   4650                                         Register scratch2,
   4651                                         Label* gc_required) {
   4652   // Allocate heap number in new space.
   4653   Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
   4654            TAG_OBJECT);
   4655 
   4656   // Set the map. The other fields are left uninitialized.
   4657   LoadRoot(kScratchRegister, Heap::kConsStringMapRootIndex);
   4658   movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
   4659 }
   4660 
   4661 
   4662 void MacroAssembler::AllocateOneByteConsString(Register result,
   4663                                                Register scratch1,
   4664                                                Register scratch2,
   4665                                                Label* gc_required) {
   4666   Allocate(ConsString::kSize,
   4667            result,
   4668            scratch1,
   4669            scratch2,
   4670            gc_required,
   4671            TAG_OBJECT);
   4672 
   4673   // Set the map. The other fields are left uninitialized.
   4674   LoadRoot(kScratchRegister, Heap::kConsOneByteStringMapRootIndex);
   4675   movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
   4676 }
   4677 
   4678 
   4679 void MacroAssembler::AllocateTwoByteSlicedString(Register result,
   4680                                           Register scratch1,
   4681                                           Register scratch2,
   4682                                           Label* gc_required) {
   4683   // Allocate heap number in new space.
   4684   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
   4685            TAG_OBJECT);
   4686 
   4687   // Set the map. The other fields are left uninitialized.
   4688   LoadRoot(kScratchRegister, Heap::kSlicedStringMapRootIndex);
   4689   movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
   4690 }
   4691 
   4692 
   4693 void MacroAssembler::AllocateOneByteSlicedString(Register result,
   4694                                                  Register scratch1,
   4695                                                  Register scratch2,
   4696                                                  Label* gc_required) {
   4697   // Allocate heap number in new space.
   4698   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
   4699            TAG_OBJECT);
   4700 
   4701   // Set the map. The other fields are left uninitialized.
   4702   LoadRoot(kScratchRegister, Heap::kSlicedOneByteStringMapRootIndex);
   4703   movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
   4704 }
   4705 
   4706 
   4707 // Copy memory, byte-by-byte, from source to destination.  Not optimized for
   4708 // long or aligned copies.  The contents of scratch and length are destroyed.
   4709 // Destination is incremented by length, source, length and scratch are
   4710 // clobbered.
   4711 // A simpler loop is faster on small copies, but slower on large ones.
   4712 // The cld() instruction must have been emitted, to set the direction flag(),
   4713 // before calling this function.
   4714 void MacroAssembler::CopyBytes(Register destination,
   4715                                Register source,
   4716                                Register length,
   4717                                int min_length,
   4718                                Register scratch) {
   4719   DCHECK(min_length >= 0);
   4720   if (emit_debug_code()) {
   4721     cmpl(length, Immediate(min_length));
   4722     Assert(greater_equal, kInvalidMinLength);
   4723   }
   4724   Label short_loop, len8, len16, len24, done, short_string;
   4725 
   4726   const int kLongStringLimit = 4 * kPointerSize;
   4727   if (min_length <= kLongStringLimit) {
   4728     cmpl(length, Immediate(kPointerSize));
   4729     j(below, &short_string, Label::kNear);
   4730   }
   4731 
   4732   DCHECK(source.is(rsi));
   4733   DCHECK(destination.is(rdi));
   4734   DCHECK(length.is(rcx));
   4735 
   4736   if (min_length <= kLongStringLimit) {
   4737     cmpl(length, Immediate(2 * kPointerSize));
   4738     j(below_equal, &len8, Label::kNear);
   4739     cmpl(length, Immediate(3 * kPointerSize));
   4740     j(below_equal, &len16, Label::kNear);
   4741     cmpl(length, Immediate(4 * kPointerSize));
   4742     j(below_equal, &len24, Label::kNear);
   4743   }
   4744 
   4745   // Because source is 8-byte aligned in our uses of this function,
   4746   // we keep source aligned for the rep movs operation by copying the odd bytes
   4747   // at the end of the ranges.
   4748   movp(scratch, length);
   4749   shrl(length, Immediate(kPointerSizeLog2));
   4750   repmovsp();
   4751   // Move remaining bytes of length.
   4752   andl(scratch, Immediate(kPointerSize - 1));
   4753   movp(length, Operand(source, scratch, times_1, -kPointerSize));
   4754   movp(Operand(destination, scratch, times_1, -kPointerSize), length);
   4755   addp(destination, scratch);
   4756 
   4757   if (min_length <= kLongStringLimit) {
   4758     jmp(&done, Label::kNear);
   4759     bind(&len24);
   4760     movp(scratch, Operand(source, 2 * kPointerSize));
   4761     movp(Operand(destination, 2 * kPointerSize), scratch);
   4762     bind(&len16);
   4763     movp(scratch, Operand(source, kPointerSize));
   4764     movp(Operand(destination, kPointerSize), scratch);
   4765     bind(&len8);
   4766     movp(scratch, Operand(source, 0));
   4767     movp(Operand(destination, 0), scratch);
   4768     // Move remaining bytes of length.
   4769     movp(scratch, Operand(source, length, times_1, -kPointerSize));
   4770     movp(Operand(destination, length, times_1, -kPointerSize), scratch);
   4771     addp(destination, length);
   4772     jmp(&done, Label::kNear);
   4773 
   4774     bind(&short_string);
   4775     if (min_length == 0) {
   4776       testl(length, length);
   4777       j(zero, &done, Label::kNear);
   4778     }
   4779 
   4780     bind(&short_loop);
   4781     movb(scratch, Operand(source, 0));
   4782     movb(Operand(destination, 0), scratch);
   4783     incp(source);
   4784     incp(destination);
   4785     decl(length);
   4786     j(not_zero, &short_loop);
   4787   }
   4788 
   4789   bind(&done);
   4790 }
   4791 
   4792 
   4793 void MacroAssembler::InitializeFieldsWithFiller(Register start_offset,
   4794                                                 Register end_offset,
   4795                                                 Register filler) {
   4796   Label loop, entry;
   4797   jmp(&entry);
   4798   bind(&loop);
   4799   movp(Operand(start_offset, 0), filler);
   4800   addp(start_offset, Immediate(kPointerSize));
   4801   bind(&entry);
   4802   cmpp(start_offset, end_offset);
   4803   j(less, &loop);
   4804 }
   4805 
   4806 
   4807 void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
   4808   if (context_chain_length > 0) {
   4809     // Move up the chain of contexts to the context containing the slot.
   4810     movp(dst, Operand(rsi, Context::SlotOffset(Context::PREVIOUS_INDEX)));
   4811     for (int i = 1; i < context_chain_length; i++) {
   4812       movp(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
   4813     }
   4814   } else {
   4815     // Slot is in the current function context.  Move it into the
   4816     // destination register in case we store into it (the write barrier
   4817     // cannot be allowed to destroy the context in rsi).
   4818     movp(dst, rsi);
   4819   }
   4820 
   4821   // We should not have found a with context by walking the context
   4822   // chain (i.e., the static scope chain and runtime context chain do
   4823   // not agree).  A variable occurring in such a scope should have
   4824   // slot type LOOKUP and not CONTEXT.
   4825   if (emit_debug_code()) {
   4826     CompareRoot(FieldOperand(dst, HeapObject::kMapOffset),
   4827                 Heap::kWithContextMapRootIndex);
   4828     Check(not_equal, kVariableResolvedToWithContext);
   4829   }
   4830 }
   4831 
   4832 
   4833 void MacroAssembler::LoadTransitionedArrayMapConditional(
   4834     ElementsKind expected_kind,
   4835     ElementsKind transitioned_kind,
   4836     Register map_in_out,
   4837     Register scratch,
   4838     Label* no_map_match) {
   4839   // Load the global or builtins object from the current context.
   4840   movp(scratch,
   4841        Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
   4842   movp(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset));
   4843 
   4844   // Check that the function's map is the same as the expected cached map.
   4845   movp(scratch, Operand(scratch,
   4846                         Context::SlotOffset(Context::JS_ARRAY_MAPS_INDEX)));
   4847 
   4848   int offset = expected_kind * kPointerSize +
   4849       FixedArrayBase::kHeaderSize;
   4850   cmpp(map_in_out, FieldOperand(scratch, offset));
   4851   j(not_equal, no_map_match);
   4852 
   4853   // Use the transitioned cached map.
   4854   offset = transitioned_kind * kPointerSize +
   4855       FixedArrayBase::kHeaderSize;
   4856   movp(map_in_out, FieldOperand(scratch, offset));
   4857 }
   4858 
   4859 
   4860 #ifdef _WIN64
   4861 static const int kRegisterPassedArguments = 4;
   4862 #else
   4863 static const int kRegisterPassedArguments = 6;
   4864 #endif
   4865 
   4866 void MacroAssembler::LoadGlobalFunction(int index, Register function) {
   4867   // Load the global or builtins object from the current context.
   4868   movp(function,
   4869        Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
   4870   // Load the native context from the global or builtins object.
   4871   movp(function, FieldOperand(function, GlobalObject::kNativeContextOffset));
   4872   // Load the function from the native context.
   4873   movp(function, Operand(function, Context::SlotOffset(index)));
   4874 }
   4875 
   4876 
   4877 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
   4878                                                   Register map) {
   4879   // Load the initial map.  The global functions all have initial maps.
   4880   movp(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
   4881   if (emit_debug_code()) {
   4882     Label ok, fail;
   4883     CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK);
   4884     jmp(&ok);
   4885     bind(&fail);
   4886     Abort(kGlobalFunctionsMustHaveInitialMap);
   4887     bind(&ok);
   4888   }
   4889 }
   4890 
   4891 
   4892 int MacroAssembler::ArgumentStackSlotsForCFunctionCall(int num_arguments) {
   4893   // On Windows 64 stack slots are reserved by the caller for all arguments
   4894   // including the ones passed in registers, and space is always allocated for
   4895   // the four register arguments even if the function takes fewer than four
   4896   // arguments.
   4897   // On AMD64 ABI (Linux/Mac) the first six arguments are passed in registers
   4898   // and the caller does not reserve stack slots for them.
   4899   DCHECK(num_arguments >= 0);
   4900 #ifdef _WIN64
   4901   const int kMinimumStackSlots = kRegisterPassedArguments;
   4902   if (num_arguments < kMinimumStackSlots) return kMinimumStackSlots;
   4903   return num_arguments;
   4904 #else
   4905   if (num_arguments < kRegisterPassedArguments) return 0;
   4906   return num_arguments - kRegisterPassedArguments;
   4907 #endif
   4908 }
   4909 
   4910 
   4911 void MacroAssembler::EmitSeqStringSetCharCheck(Register string,
   4912                                                Register index,
   4913                                                Register value,
   4914                                                uint32_t encoding_mask) {
   4915   Label is_object;
   4916   JumpIfNotSmi(string, &is_object);
   4917   Abort(kNonObject);
   4918   bind(&is_object);
   4919 
   4920   Push(value);
   4921   movp(value, FieldOperand(string, HeapObject::kMapOffset));
   4922   movzxbp(value, FieldOperand(value, Map::kInstanceTypeOffset));
   4923 
   4924   andb(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
   4925   cmpp(value, Immediate(encoding_mask));
   4926   Pop(value);
   4927   Check(equal, kUnexpectedStringType);
   4928 
   4929   // The index is assumed to be untagged coming in, tag it to compare with the
   4930   // string length without using a temp register, it is restored at the end of
   4931   // this function.
   4932   Integer32ToSmi(index, index);
   4933   SmiCompare(index, FieldOperand(string, String::kLengthOffset));
   4934   Check(less, kIndexIsTooLarge);
   4935 
   4936   SmiCompare(index, Smi::FromInt(0));
   4937   Check(greater_equal, kIndexIsNegative);
   4938 
   4939   // Restore the index
   4940   SmiToInteger32(index, index);
   4941 }
   4942 
   4943 
   4944 void MacroAssembler::PrepareCallCFunction(int num_arguments) {
   4945   int frame_alignment = base::OS::ActivationFrameAlignment();
   4946   DCHECK(frame_alignment != 0);
   4947   DCHECK(num_arguments >= 0);
   4948 
   4949   // Make stack end at alignment and allocate space for arguments and old rsp.
   4950   movp(kScratchRegister, rsp);
   4951   DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
   4952   int argument_slots_on_stack =
   4953       ArgumentStackSlotsForCFunctionCall(num_arguments);
   4954   subp(rsp, Immediate((argument_slots_on_stack + 1) * kRegisterSize));
   4955   andp(rsp, Immediate(-frame_alignment));
   4956   movp(Operand(rsp, argument_slots_on_stack * kRegisterSize), kScratchRegister);
   4957 }
   4958 
   4959 
   4960 void MacroAssembler::CallCFunction(ExternalReference function,
   4961                                    int num_arguments) {
   4962   LoadAddress(rax, function);
   4963   CallCFunction(rax, num_arguments);
   4964 }
   4965 
   4966 
   4967 void MacroAssembler::CallCFunction(Register function, int num_arguments) {
   4968   DCHECK(has_frame());
   4969   // Check stack alignment.
   4970   if (emit_debug_code()) {
   4971     CheckStackAlignment();
   4972   }
   4973 
   4974   call(function);
   4975   DCHECK(base::OS::ActivationFrameAlignment() != 0);
   4976   DCHECK(num_arguments >= 0);
   4977   int argument_slots_on_stack =
   4978       ArgumentStackSlotsForCFunctionCall(num_arguments);
   4979   movp(rsp, Operand(rsp, argument_slots_on_stack * kRegisterSize));
   4980 }
   4981 
   4982 
   4983 #ifdef DEBUG
   4984 bool AreAliased(Register reg1,
   4985                 Register reg2,
   4986                 Register reg3,
   4987                 Register reg4,
   4988                 Register reg5,
   4989                 Register reg6,
   4990                 Register reg7,
   4991                 Register reg8) {
   4992   int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() +
   4993       reg3.is_valid() + reg4.is_valid() + reg5.is_valid() + reg6.is_valid() +
   4994       reg7.is_valid() + reg8.is_valid();
   4995 
   4996   RegList regs = 0;
   4997   if (reg1.is_valid()) regs |= reg1.bit();
   4998   if (reg2.is_valid()) regs |= reg2.bit();
   4999   if (reg3.is_valid()) regs |= reg3.bit();
   5000   if (reg4.is_valid()) regs |= reg4.bit();
   5001   if (reg5.is_valid()) regs |= reg5.bit();
   5002   if (reg6.is_valid()) regs |= reg6.bit();
   5003   if (reg7.is_valid()) regs |= reg7.bit();
   5004   if (reg8.is_valid()) regs |= reg8.bit();
   5005   int n_of_non_aliasing_regs = NumRegs(regs);
   5006 
   5007   return n_of_valid_regs != n_of_non_aliasing_regs;
   5008 }
   5009 #endif
   5010 
   5011 
   5012 CodePatcher::CodePatcher(byte* address, int size)
   5013     : address_(address),
   5014       size_(size),
   5015       masm_(NULL, address, size + Assembler::kGap) {
   5016   // Create a new macro assembler pointing to the address of the code to patch.
   5017   // The size is adjusted with kGap on order for the assembler to generate size
   5018   // bytes of instructions without failing with buffer size constraints.
   5019   DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
   5020 }
   5021 
   5022 
   5023 CodePatcher::~CodePatcher() {
   5024   // Indicate that code has changed.
   5025   CpuFeatures::FlushICache(address_, size_);
   5026 
   5027   // Check that the code was patched as expected.
   5028   DCHECK(masm_.pc_ == address_ + size_);
   5029   DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
   5030 }
   5031 
   5032 
   5033 void MacroAssembler::CheckPageFlag(
   5034     Register object,
   5035     Register scratch,
   5036     int mask,
   5037     Condition cc,
   5038     Label* condition_met,
   5039     Label::Distance condition_met_distance) {
   5040   DCHECK(cc == zero || cc == not_zero);
   5041   if (scratch.is(object)) {
   5042     andp(scratch, Immediate(~Page::kPageAlignmentMask));
   5043   } else {
   5044     movp(scratch, Immediate(~Page::kPageAlignmentMask));
   5045     andp(scratch, object);
   5046   }
   5047   if (mask < (1 << kBitsPerByte)) {
   5048     testb(Operand(scratch, MemoryChunk::kFlagsOffset),
   5049           Immediate(static_cast<uint8_t>(mask)));
   5050   } else {
   5051     testl(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
   5052   }
   5053   j(cc, condition_met, condition_met_distance);
   5054 }
   5055 
   5056 
   5057 void MacroAssembler::CheckMapDeprecated(Handle<Map> map,
   5058                                         Register scratch,
   5059                                         Label* if_deprecated) {
   5060   if (map->CanBeDeprecated()) {
   5061     Move(scratch, map);
   5062     movl(scratch, FieldOperand(scratch, Map::kBitField3Offset));
   5063     andl(scratch, Immediate(Map::Deprecated::kMask));
   5064     j(not_zero, if_deprecated);
   5065   }
   5066 }
   5067 
   5068 
   5069 void MacroAssembler::JumpIfBlack(Register object,
   5070                                  Register bitmap_scratch,
   5071                                  Register mask_scratch,
   5072                                  Label* on_black,
   5073                                  Label::Distance on_black_distance) {
   5074   DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, rcx));
   5075   GetMarkBits(object, bitmap_scratch, mask_scratch);
   5076 
   5077   DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0);
   5078   // The mask_scratch register contains a 1 at the position of the first bit
   5079   // and a 0 at all other positions, including the position of the second bit.
   5080   movp(rcx, mask_scratch);
   5081   // Make rcx into a mask that covers both marking bits using the operation
   5082   // rcx = mask | (mask << 1).
   5083   leap(rcx, Operand(mask_scratch, mask_scratch, times_2, 0));
   5084   // Note that we are using a 4-byte aligned 8-byte load.
   5085   andp(rcx, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
   5086   cmpp(mask_scratch, rcx);
   5087   j(equal, on_black, on_black_distance);
   5088 }
   5089 
   5090 
   5091 // Detect some, but not all, common pointer-free objects.  This is used by the
   5092 // incremental write barrier which doesn't care about oddballs (they are always
   5093 // marked black immediately so this code is not hit).
   5094 void MacroAssembler::JumpIfDataObject(
   5095     Register value,
   5096     Register scratch,
   5097     Label* not_data_object,
   5098     Label::Distance not_data_object_distance) {
   5099   Label is_data_object;
   5100   movp(scratch, FieldOperand(value, HeapObject::kMapOffset));
   5101   CompareRoot(scratch, Heap::kHeapNumberMapRootIndex);
   5102   j(equal, &is_data_object, Label::kNear);
   5103   DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
   5104   DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
   5105   // If it's a string and it's not a cons string then it's an object containing
   5106   // no GC pointers.
   5107   testb(FieldOperand(scratch, Map::kInstanceTypeOffset),
   5108         Immediate(kIsIndirectStringMask | kIsNotStringMask));
   5109   j(not_zero, not_data_object, not_data_object_distance);
   5110   bind(&is_data_object);
   5111 }
   5112 
   5113 
   5114 void MacroAssembler::GetMarkBits(Register addr_reg,
   5115                                  Register bitmap_reg,
   5116                                  Register mask_reg) {
   5117   DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, rcx));
   5118   movp(bitmap_reg, addr_reg);
   5119   // Sign extended 32 bit immediate.
   5120   andp(bitmap_reg, Immediate(~Page::kPageAlignmentMask));
   5121   movp(rcx, addr_reg);
   5122   int shift =
   5123       Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2;
   5124   shrl(rcx, Immediate(shift));
   5125   andp(rcx,
   5126        Immediate((Page::kPageAlignmentMask >> shift) &
   5127                  ~(Bitmap::kBytesPerCell - 1)));
   5128 
   5129   addp(bitmap_reg, rcx);
   5130   movp(rcx, addr_reg);
   5131   shrl(rcx, Immediate(kPointerSizeLog2));
   5132   andp(rcx, Immediate((1 << Bitmap::kBitsPerCellLog2) - 1));
   5133   movl(mask_reg, Immediate(1));
   5134   shlp_cl(mask_reg);
   5135 }
   5136 
   5137 
   5138 void MacroAssembler::EnsureNotWhite(
   5139     Register value,
   5140     Register bitmap_scratch,
   5141     Register mask_scratch,
   5142     Label* value_is_white_and_not_data,
   5143     Label::Distance distance) {
   5144   DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, rcx));
   5145   GetMarkBits(value, bitmap_scratch, mask_scratch);
   5146 
   5147   // If the value is black or grey we don't need to do anything.
   5148   DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
   5149   DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0);
   5150   DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0);
   5151   DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
   5152 
   5153   Label done;
   5154 
   5155   // Since both black and grey have a 1 in the first position and white does
   5156   // not have a 1 there we only need to check one bit.
   5157   testp(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch);
   5158   j(not_zero, &done, Label::kNear);
   5159 
   5160   if (emit_debug_code()) {
   5161     // Check for impossible bit pattern.
   5162     Label ok;
   5163     Push(mask_scratch);
   5164     // shl.  May overflow making the check conservative.
   5165     addp(mask_scratch, mask_scratch);
   5166     testp(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch);
   5167     j(zero, &ok, Label::kNear);
   5168     int3();
   5169     bind(&ok);
   5170     Pop(mask_scratch);
   5171   }
   5172 
   5173   // Value is white.  We check whether it is data that doesn't need scanning.
   5174   // Currently only checks for HeapNumber and non-cons strings.
   5175   Register map = rcx;  // Holds map while checking type.
   5176   Register length = rcx;  // Holds length of object after checking type.
   5177   Label not_heap_number;
   5178   Label is_data_object;
   5179 
   5180   // Check for heap-number
   5181   movp(map, FieldOperand(value, HeapObject::kMapOffset));
   5182   CompareRoot(map, Heap::kHeapNumberMapRootIndex);
   5183   j(not_equal, &not_heap_number, Label::kNear);
   5184   movp(length, Immediate(HeapNumber::kSize));
   5185   jmp(&is_data_object, Label::kNear);
   5186 
   5187   bind(&not_heap_number);
   5188   // Check for strings.
   5189   DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
   5190   DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
   5191   // If it's a string and it's not a cons string then it's an object containing
   5192   // no GC pointers.
   5193   Register instance_type = rcx;
   5194   movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
   5195   testb(instance_type, Immediate(kIsIndirectStringMask | kIsNotStringMask));
   5196   j(not_zero, value_is_white_and_not_data);
   5197   // It's a non-indirect (non-cons and non-slice) string.
   5198   // If it's external, the length is just ExternalString::kSize.
   5199   // Otherwise it's String::kHeaderSize + string->length() * (1 or 2).
   5200   Label not_external;
   5201   // External strings are the only ones with the kExternalStringTag bit
   5202   // set.
   5203   DCHECK_EQ(0, kSeqStringTag & kExternalStringTag);
   5204   DCHECK_EQ(0, kConsStringTag & kExternalStringTag);
   5205   testb(instance_type, Immediate(kExternalStringTag));
   5206   j(zero, &not_external, Label::kNear);
   5207   movp(length, Immediate(ExternalString::kSize));
   5208   jmp(&is_data_object, Label::kNear);
   5209 
   5210   bind(&not_external);
   5211   // Sequential string, either Latin1 or UC16.
   5212   DCHECK(kOneByteStringTag == 0x04);
   5213   andp(length, Immediate(kStringEncodingMask));
   5214   xorp(length, Immediate(kStringEncodingMask));
   5215   addp(length, Immediate(0x04));
   5216   // Value now either 4 (if Latin1) or 8 (if UC16), i.e. char-size shifted by 2.
   5217   imulp(length, FieldOperand(value, String::kLengthOffset));
   5218   shrp(length, Immediate(2 + kSmiTagSize + kSmiShiftSize));
   5219   addp(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask));
   5220   andp(length, Immediate(~kObjectAlignmentMask));
   5221 
   5222   bind(&is_data_object);
   5223   // Value is a data object, and it is white.  Mark it black.  Since we know
   5224   // that the object is white we can make it black by flipping one bit.
   5225   orp(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch);
   5226 
   5227   andp(bitmap_scratch, Immediate(~Page::kPageAlignmentMask));
   5228   addl(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset), length);
   5229 
   5230   bind(&done);
   5231 }
   5232 
   5233 
   5234 void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) {
   5235   Label next, start;
   5236   Register empty_fixed_array_value = r8;
   5237   LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
   5238   movp(rcx, rax);
   5239 
   5240   // Check if the enum length field is properly initialized, indicating that
   5241   // there is an enum cache.
   5242   movp(rbx, FieldOperand(rcx, HeapObject::kMapOffset));
   5243 
   5244   EnumLength(rdx, rbx);
   5245   Cmp(rdx, Smi::FromInt(kInvalidEnumCacheSentinel));
   5246   j(equal, call_runtime);
   5247 
   5248   jmp(&start);
   5249 
   5250   bind(&next);
   5251 
   5252   movp(rbx, FieldOperand(rcx, HeapObject::kMapOffset));
   5253 
   5254   // For all objects but the receiver, check that the cache is empty.
   5255   EnumLength(rdx, rbx);
   5256   Cmp(rdx, Smi::FromInt(0));
   5257   j(not_equal, call_runtime);
   5258 
   5259   bind(&start);
   5260 
   5261   // Check that there are no elements. Register rcx contains the current JS
   5262   // object we've reached through the prototype chain.
   5263   Label no_elements;
   5264   cmpp(empty_fixed_array_value,
   5265        FieldOperand(rcx, JSObject::kElementsOffset));
   5266   j(equal, &no_elements);
   5267 
   5268   // Second chance, the object may be using the empty slow element dictionary.
   5269   LoadRoot(kScratchRegister, Heap::kEmptySlowElementDictionaryRootIndex);
   5270   cmpp(kScratchRegister, FieldOperand(rcx, JSObject::kElementsOffset));
   5271   j(not_equal, call_runtime);
   5272 
   5273   bind(&no_elements);
   5274   movp(rcx, FieldOperand(rbx, Map::kPrototypeOffset));
   5275   cmpp(rcx, null_value);
   5276   j(not_equal, &next);
   5277 }
   5278 
   5279 void MacroAssembler::TestJSArrayForAllocationMemento(
   5280     Register receiver_reg,
   5281     Register scratch_reg,
   5282     Label* no_memento_found) {
   5283   ExternalReference new_space_start =
   5284       ExternalReference::new_space_start(isolate());
   5285   ExternalReference new_space_allocation_top =
   5286       ExternalReference::new_space_allocation_top_address(isolate());
   5287 
   5288   leap(scratch_reg, Operand(receiver_reg,
   5289       JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag));
   5290   Move(kScratchRegister, new_space_start);
   5291   cmpp(scratch_reg, kScratchRegister);
   5292   j(less, no_memento_found);
   5293   cmpp(scratch_reg, ExternalOperand(new_space_allocation_top));
   5294   j(greater, no_memento_found);
   5295   CompareRoot(MemOperand(scratch_reg, -AllocationMemento::kSize),
   5296               Heap::kAllocationMementoMapRootIndex);
   5297 }
   5298 
   5299 
   5300 void MacroAssembler::JumpIfDictionaryInPrototypeChain(
   5301     Register object,
   5302     Register scratch0,
   5303     Register scratch1,
   5304     Label* found) {
   5305   DCHECK(!(scratch0.is(kScratchRegister) && scratch1.is(kScratchRegister)));
   5306   DCHECK(!scratch1.is(scratch0));
   5307   Register current = scratch0;
   5308   Label loop_again;
   5309 
   5310   movp(current, object);
   5311 
   5312   // Loop based on the map going up the prototype chain.
   5313   bind(&loop_again);
   5314   movp(current, FieldOperand(current, HeapObject::kMapOffset));
   5315   movp(scratch1, FieldOperand(current, Map::kBitField2Offset));
   5316   DecodeField<Map::ElementsKindBits>(scratch1);
   5317   cmpp(scratch1, Immediate(DICTIONARY_ELEMENTS));
   5318   j(equal, found);
   5319   movp(current, FieldOperand(current, Map::kPrototypeOffset));
   5320   CompareRoot(current, Heap::kNullValueRootIndex);
   5321   j(not_equal, &loop_again);
   5322 }
   5323 
   5324 
   5325 void MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) {
   5326   DCHECK(!dividend.is(rax));
   5327   DCHECK(!dividend.is(rdx));
   5328   base::MagicNumbersForDivision<uint32_t> mag =
   5329       base::SignedDivisionByConstant(static_cast<uint32_t>(divisor));
   5330   movl(rax, Immediate(mag.multiplier));
   5331   imull(dividend);
   5332   bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0;
   5333   if (divisor > 0 && neg) addl(rdx, dividend);
   5334   if (divisor < 0 && !neg && mag.multiplier > 0) subl(rdx, dividend);
   5335   if (mag.shift > 0) sarl(rdx, Immediate(mag.shift));
   5336   movl(rax, dividend);
   5337   shrl(rax, Immediate(31));
   5338   addl(rdx, rax);
   5339 }
   5340 
   5341 
   5342 } }  // namespace v8::internal
   5343 
   5344 #endif  // V8_TARGET_ARCH_X64
   5345