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