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