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