Home | History | Annotate | Download | only in arm
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <limits.h>  // For LONG_MIN, LONG_MAX.
      6 
      7 #if V8_TARGET_ARCH_ARM
      8 
      9 #include "src/base/bits.h"
     10 #include "src/base/division-by-constant.h"
     11 #include "src/bootstrapper.h"
     12 #include "src/codegen.h"
     13 #include "src/debug/debug.h"
     14 #include "src/register-configuration.h"
     15 #include "src/runtime/runtime.h"
     16 
     17 #include "src/arm/macro-assembler-arm.h"
     18 
     19 namespace v8 {
     20 namespace internal {
     21 
     22 MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size,
     23                                CodeObjectRequired create_code_object)
     24     : Assembler(arg_isolate, buffer, size),
     25       generating_stub_(false),
     26       has_frame_(false) {
     27   if (create_code_object == CodeObjectRequired::kYes) {
     28     code_object_ =
     29         Handle<Object>::New(isolate()->heap()->undefined_value(), isolate());
     30   }
     31 }
     32 
     33 
     34 void MacroAssembler::Jump(Register target, Condition cond) {
     35   bx(target, cond);
     36 }
     37 
     38 
     39 void MacroAssembler::Jump(intptr_t target, RelocInfo::Mode rmode,
     40                           Condition cond) {
     41   DCHECK(RelocInfo::IsCodeTarget(rmode));
     42   mov(pc, Operand(target, rmode), LeaveCC, cond);
     43 }
     44 
     45 
     46 void MacroAssembler::Jump(Address target, RelocInfo::Mode rmode,
     47                           Condition cond) {
     48   DCHECK(!RelocInfo::IsCodeTarget(rmode));
     49   Jump(reinterpret_cast<intptr_t>(target), rmode, cond);
     50 }
     51 
     52 
     53 void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode,
     54                           Condition cond) {
     55   DCHECK(RelocInfo::IsCodeTarget(rmode));
     56   // 'code' is always generated ARM code, never THUMB code
     57   AllowDeferredHandleDereference embedding_raw_address;
     58   Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond);
     59 }
     60 
     61 
     62 int MacroAssembler::CallSize(Register target, Condition cond) {
     63   return kInstrSize;
     64 }
     65 
     66 
     67 void MacroAssembler::Call(Register target, Condition cond) {
     68   // Block constant pool for the call instruction sequence.
     69   BlockConstPoolScope block_const_pool(this);
     70   Label start;
     71   bind(&start);
     72   blx(target, cond);
     73   DCHECK_EQ(CallSize(target, cond), SizeOfCodeGeneratedSince(&start));
     74 }
     75 
     76 
     77 int MacroAssembler::CallSize(
     78     Address target, RelocInfo::Mode rmode, Condition cond) {
     79   Instr mov_instr = cond | MOV | LeaveCC;
     80   Operand mov_operand = Operand(reinterpret_cast<intptr_t>(target), rmode);
     81   return kInstrSize +
     82          mov_operand.instructions_required(this, mov_instr) * kInstrSize;
     83 }
     84 
     85 
     86 int MacroAssembler::CallStubSize(
     87     CodeStub* stub, TypeFeedbackId ast_id, Condition cond) {
     88   return CallSize(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id, cond);
     89 }
     90 
     91 
     92 void MacroAssembler::Call(Address target,
     93                           RelocInfo::Mode rmode,
     94                           Condition cond,
     95                           TargetAddressStorageMode mode) {
     96   // Block constant pool for the call instruction sequence.
     97   BlockConstPoolScope block_const_pool(this);
     98   Label start;
     99   bind(&start);
    100 
    101   bool old_predictable_code_size = predictable_code_size();
    102   if (mode == NEVER_INLINE_TARGET_ADDRESS) {
    103     set_predictable_code_size(true);
    104   }
    105 
    106 #ifdef DEBUG
    107   // Check the expected size before generating code to ensure we assume the same
    108   // constant pool availability (e.g., whether constant pool is full or not).
    109   int expected_size = CallSize(target, rmode, cond);
    110 #endif
    111 
    112   // Call sequence on V7 or later may be :
    113   //  movw  ip, #... @ call address low 16
    114   //  movt  ip, #... @ call address high 16
    115   //  blx   ip
    116   //                      @ return address
    117   // Or for pre-V7 or values that may be back-patched
    118   // to avoid ICache flushes:
    119   //  ldr   ip, [pc, #...] @ call address
    120   //  blx   ip
    121   //                      @ return address
    122 
    123   mov(ip, Operand(reinterpret_cast<int32_t>(target), rmode));
    124   blx(ip, cond);
    125 
    126   DCHECK_EQ(expected_size, SizeOfCodeGeneratedSince(&start));
    127   if (mode == NEVER_INLINE_TARGET_ADDRESS) {
    128     set_predictable_code_size(old_predictable_code_size);
    129   }
    130 }
    131 
    132 
    133 int MacroAssembler::CallSize(Handle<Code> code,
    134                              RelocInfo::Mode rmode,
    135                              TypeFeedbackId ast_id,
    136                              Condition cond) {
    137   AllowDeferredHandleDereference using_raw_address;
    138   return CallSize(reinterpret_cast<Address>(code.location()), rmode, cond);
    139 }
    140 
    141 
    142 void MacroAssembler::Call(Handle<Code> code,
    143                           RelocInfo::Mode rmode,
    144                           TypeFeedbackId ast_id,
    145                           Condition cond,
    146                           TargetAddressStorageMode mode) {
    147   Label start;
    148   bind(&start);
    149   DCHECK(RelocInfo::IsCodeTarget(rmode));
    150   if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) {
    151     SetRecordedAstId(ast_id);
    152     rmode = RelocInfo::CODE_TARGET_WITH_ID;
    153   }
    154   // 'code' is always generated ARM code, never THUMB code
    155   AllowDeferredHandleDereference embedding_raw_address;
    156   Call(reinterpret_cast<Address>(code.location()), rmode, cond, mode);
    157 }
    158 
    159 void MacroAssembler::CallDeoptimizer(Address target) {
    160   BlockConstPoolScope block_const_pool(this);
    161 
    162   uintptr_t target_raw = reinterpret_cast<uintptr_t>(target);
    163 
    164   // We use blx, like a call, but it does not return here. The link register is
    165   // used by the deoptimizer to work out what called it.
    166   if (CpuFeatures::IsSupported(ARMv7)) {
    167     CpuFeatureScope scope(this, ARMv7);
    168     movw(ip, target_raw & 0xffff);
    169     movt(ip, (target_raw >> 16) & 0xffff);
    170     blx(ip);
    171   } else {
    172     // We need to load a literal, but we can't use the usual constant pool
    173     // because we call this from a patcher, and cannot afford the guard
    174     // instruction and other administrative overhead.
    175     ldr(ip, MemOperand(pc, (2 * kInstrSize) - kPcLoadDelta));
    176     blx(ip);
    177     dd(target_raw);
    178   }
    179 }
    180 
    181 int MacroAssembler::CallDeoptimizerSize() {
    182   // ARMv7+:
    183   //    movw    ip, ...
    184   //    movt    ip, ...
    185   //    blx     ip              @ This never returns.
    186   //
    187   // ARMv6:
    188   //    ldr     ip, =address
    189   //    blx     ip              @ This never returns.
    190   //    .word   address
    191   return 3 * kInstrSize;
    192 }
    193 
    194 void MacroAssembler::Ret(Condition cond) {
    195   bx(lr, cond);
    196 }
    197 
    198 
    199 void MacroAssembler::Drop(int count, Condition cond) {
    200   if (count > 0) {
    201     add(sp, sp, Operand(count * kPointerSize), LeaveCC, cond);
    202   }
    203 }
    204 
    205 void MacroAssembler::Drop(Register count, Condition cond) {
    206   add(sp, sp, Operand(count, LSL, kPointerSizeLog2), LeaveCC, cond);
    207 }
    208 
    209 void MacroAssembler::Ret(int drop, Condition cond) {
    210   Drop(drop, cond);
    211   Ret(cond);
    212 }
    213 
    214 
    215 void MacroAssembler::Swap(Register reg1,
    216                           Register reg2,
    217                           Register scratch,
    218                           Condition cond) {
    219   if (scratch.is(no_reg)) {
    220     eor(reg1, reg1, Operand(reg2), LeaveCC, cond);
    221     eor(reg2, reg2, Operand(reg1), LeaveCC, cond);
    222     eor(reg1, reg1, Operand(reg2), LeaveCC, cond);
    223   } else {
    224     mov(scratch, reg1, LeaveCC, cond);
    225     mov(reg1, reg2, LeaveCC, cond);
    226     mov(reg2, scratch, LeaveCC, cond);
    227   }
    228 }
    229 
    230 
    231 void MacroAssembler::Call(Label* target) {
    232   bl(target);
    233 }
    234 
    235 
    236 void MacroAssembler::Push(Handle<Object> handle) {
    237   mov(ip, Operand(handle));
    238   push(ip);
    239 }
    240 
    241 
    242 void MacroAssembler::Move(Register dst, Handle<Object> value) {
    243   mov(dst, Operand(value));
    244 }
    245 
    246 
    247 void MacroAssembler::Move(Register dst, Register src, Condition cond) {
    248   if (!dst.is(src)) {
    249     mov(dst, src, LeaveCC, cond);
    250   }
    251 }
    252 
    253 void MacroAssembler::Move(SwVfpRegister dst, SwVfpRegister src,
    254                           Condition cond) {
    255   if (!dst.is(src)) {
    256     vmov(dst, src, cond);
    257   }
    258 }
    259 
    260 void MacroAssembler::Move(DwVfpRegister dst, DwVfpRegister src,
    261                           Condition cond) {
    262   if (!dst.is(src)) {
    263     vmov(dst, src, cond);
    264   }
    265 }
    266 
    267 void MacroAssembler::Move(QwNeonRegister dst, QwNeonRegister src) {
    268   if (!dst.is(src)) {
    269     vmov(dst, src);
    270   }
    271 }
    272 
    273 void MacroAssembler::Swap(DwVfpRegister srcdst0, DwVfpRegister srcdst1) {
    274   if (srcdst0.is(srcdst1)) return;  // Swapping aliased registers emits nothing.
    275 
    276   DCHECK(VfpRegisterIsAvailable(srcdst0));
    277   DCHECK(VfpRegisterIsAvailable(srcdst1));
    278 
    279   if (CpuFeatures::IsSupported(NEON)) {
    280     vswp(srcdst0, srcdst1);
    281   } else {
    282     DCHECK(!srcdst0.is(kScratchDoubleReg));
    283     DCHECK(!srcdst1.is(kScratchDoubleReg));
    284     vmov(kScratchDoubleReg, srcdst0);
    285     vmov(srcdst0, srcdst1);
    286     vmov(srcdst1, kScratchDoubleReg);
    287   }
    288 }
    289 
    290 void MacroAssembler::Swap(QwNeonRegister srcdst0, QwNeonRegister srcdst1) {
    291   if (!srcdst0.is(srcdst1)) {
    292     vswp(srcdst0, srcdst1);
    293   }
    294 }
    295 
    296 void MacroAssembler::Mls(Register dst, Register src1, Register src2,
    297                          Register srcA, Condition cond) {
    298   if (CpuFeatures::IsSupported(ARMv7)) {
    299     CpuFeatureScope scope(this, ARMv7);
    300     mls(dst, src1, src2, srcA, cond);
    301   } else {
    302     DCHECK(!srcA.is(ip));
    303     mul(ip, src1, src2, LeaveCC, cond);
    304     sub(dst, srcA, ip, LeaveCC, cond);
    305   }
    306 }
    307 
    308 
    309 void MacroAssembler::And(Register dst, Register src1, const Operand& src2,
    310                          Condition cond) {
    311   if (!src2.is_reg() &&
    312       !src2.must_output_reloc_info(this) &&
    313       src2.immediate() == 0) {
    314     mov(dst, Operand::Zero(), LeaveCC, cond);
    315   } else if (!(src2.instructions_required(this) == 1) &&
    316              !src2.must_output_reloc_info(this) &&
    317              CpuFeatures::IsSupported(ARMv7) &&
    318              base::bits::IsPowerOfTwo32(src2.immediate() + 1)) {
    319     CpuFeatureScope scope(this, ARMv7);
    320     ubfx(dst, src1, 0,
    321         WhichPowerOf2(static_cast<uint32_t>(src2.immediate()) + 1), cond);
    322   } else {
    323     and_(dst, src1, src2, LeaveCC, cond);
    324   }
    325 }
    326 
    327 
    328 void MacroAssembler::Ubfx(Register dst, Register src1, int lsb, int width,
    329                           Condition cond) {
    330   DCHECK(lsb < 32);
    331   if (!CpuFeatures::IsSupported(ARMv7) || predictable_code_size()) {
    332     int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
    333     and_(dst, src1, Operand(mask), LeaveCC, cond);
    334     if (lsb != 0) {
    335       mov(dst, Operand(dst, LSR, lsb), LeaveCC, cond);
    336     }
    337   } else {
    338     CpuFeatureScope scope(this, ARMv7);
    339     ubfx(dst, src1, lsb, width, cond);
    340   }
    341 }
    342 
    343 
    344 void MacroAssembler::Sbfx(Register dst, Register src1, int lsb, int width,
    345                           Condition cond) {
    346   DCHECK(lsb < 32);
    347   if (!CpuFeatures::IsSupported(ARMv7) || predictable_code_size()) {
    348     int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
    349     and_(dst, src1, Operand(mask), LeaveCC, cond);
    350     int shift_up = 32 - lsb - width;
    351     int shift_down = lsb + shift_up;
    352     if (shift_up != 0) {
    353       mov(dst, Operand(dst, LSL, shift_up), LeaveCC, cond);
    354     }
    355     if (shift_down != 0) {
    356       mov(dst, Operand(dst, ASR, shift_down), LeaveCC, cond);
    357     }
    358   } else {
    359     CpuFeatureScope scope(this, ARMv7);
    360     sbfx(dst, src1, lsb, width, cond);
    361   }
    362 }
    363 
    364 
    365 void MacroAssembler::Bfi(Register dst,
    366                          Register src,
    367                          Register scratch,
    368                          int lsb,
    369                          int width,
    370                          Condition cond) {
    371   DCHECK(0 <= lsb && lsb < 32);
    372   DCHECK(0 <= width && width < 32);
    373   DCHECK(lsb + width < 32);
    374   DCHECK(!scratch.is(dst));
    375   if (width == 0) return;
    376   if (!CpuFeatures::IsSupported(ARMv7) || predictable_code_size()) {
    377     int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
    378     bic(dst, dst, Operand(mask));
    379     and_(scratch, src, Operand((1 << width) - 1));
    380     mov(scratch, Operand(scratch, LSL, lsb));
    381     orr(dst, dst, scratch);
    382   } else {
    383     CpuFeatureScope scope(this, ARMv7);
    384     bfi(dst, src, lsb, width, cond);
    385   }
    386 }
    387 
    388 
    389 void MacroAssembler::Bfc(Register dst, Register src, int lsb, int width,
    390                          Condition cond) {
    391   DCHECK(lsb < 32);
    392   if (!CpuFeatures::IsSupported(ARMv7) || predictable_code_size()) {
    393     int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
    394     bic(dst, src, Operand(mask));
    395   } else {
    396     CpuFeatureScope scope(this, ARMv7);
    397     Move(dst, src, cond);
    398     bfc(dst, lsb, width, cond);
    399   }
    400 }
    401 
    402 
    403 void MacroAssembler::Load(Register dst,
    404                           const MemOperand& src,
    405                           Representation r) {
    406   DCHECK(!r.IsDouble());
    407   if (r.IsInteger8()) {
    408     ldrsb(dst, src);
    409   } else if (r.IsUInteger8()) {
    410     ldrb(dst, src);
    411   } else if (r.IsInteger16()) {
    412     ldrsh(dst, src);
    413   } else if (r.IsUInteger16()) {
    414     ldrh(dst, src);
    415   } else {
    416     ldr(dst, src);
    417   }
    418 }
    419 
    420 
    421 void MacroAssembler::Store(Register src,
    422                            const MemOperand& dst,
    423                            Representation r) {
    424   DCHECK(!r.IsDouble());
    425   if (r.IsInteger8() || r.IsUInteger8()) {
    426     strb(src, dst);
    427   } else if (r.IsInteger16() || r.IsUInteger16()) {
    428     strh(src, dst);
    429   } else {
    430     if (r.IsHeapObject()) {
    431       AssertNotSmi(src);
    432     } else if (r.IsSmi()) {
    433       AssertSmi(src);
    434     }
    435     str(src, dst);
    436   }
    437 }
    438 
    439 
    440 void MacroAssembler::LoadRoot(Register destination,
    441                               Heap::RootListIndex index,
    442                               Condition cond) {
    443   ldr(destination, MemOperand(kRootRegister, index << kPointerSizeLog2), cond);
    444 }
    445 
    446 
    447 void MacroAssembler::StoreRoot(Register source,
    448                                Heap::RootListIndex index,
    449                                Condition cond) {
    450   DCHECK(Heap::RootCanBeWrittenAfterInitialization(index));
    451   str(source, MemOperand(kRootRegister, index << kPointerSizeLog2), cond);
    452 }
    453 
    454 
    455 void MacroAssembler::InNewSpace(Register object,
    456                                 Register scratch,
    457                                 Condition cond,
    458                                 Label* branch) {
    459   DCHECK(cond == eq || cond == ne);
    460   CheckPageFlag(object, scratch, MemoryChunk::kIsInNewSpaceMask, cond, branch);
    461 }
    462 
    463 
    464 void MacroAssembler::RecordWriteField(
    465     Register object,
    466     int offset,
    467     Register value,
    468     Register dst,
    469     LinkRegisterStatus lr_status,
    470     SaveFPRegsMode save_fp,
    471     RememberedSetAction remembered_set_action,
    472     SmiCheck smi_check,
    473     PointersToHereCheck pointers_to_here_check_for_value) {
    474   // First, check if a write barrier is even needed. The tests below
    475   // catch stores of Smis.
    476   Label done;
    477 
    478   // Skip barrier if writing a smi.
    479   if (smi_check == INLINE_SMI_CHECK) {
    480     JumpIfSmi(value, &done);
    481   }
    482 
    483   // Although the object register is tagged, the offset is relative to the start
    484   // of the object, so so offset must be a multiple of kPointerSize.
    485   DCHECK(IsAligned(offset, kPointerSize));
    486 
    487   add(dst, object, Operand(offset - kHeapObjectTag));
    488   if (emit_debug_code()) {
    489     Label ok;
    490     tst(dst, Operand((1 << kPointerSizeLog2) - 1));
    491     b(eq, &ok);
    492     stop("Unaligned cell in write barrier");
    493     bind(&ok);
    494   }
    495 
    496   RecordWrite(object,
    497               dst,
    498               value,
    499               lr_status,
    500               save_fp,
    501               remembered_set_action,
    502               OMIT_SMI_CHECK,
    503               pointers_to_here_check_for_value);
    504 
    505   bind(&done);
    506 
    507   // Clobber clobbered input registers when running with the debug-code flag
    508   // turned on to provoke errors.
    509   if (emit_debug_code()) {
    510     mov(value, Operand(bit_cast<int32_t>(kZapValue + 4)));
    511     mov(dst, Operand(bit_cast<int32_t>(kZapValue + 8)));
    512   }
    513 }
    514 
    515 
    516 // Will clobber 4 registers: object, map, dst, ip.  The
    517 // register 'object' contains a heap object pointer.
    518 void MacroAssembler::RecordWriteForMap(Register object,
    519                                        Register map,
    520                                        Register dst,
    521                                        LinkRegisterStatus lr_status,
    522                                        SaveFPRegsMode fp_mode) {
    523   if (emit_debug_code()) {
    524     ldr(dst, FieldMemOperand(map, HeapObject::kMapOffset));
    525     cmp(dst, Operand(isolate()->factory()->meta_map()));
    526     Check(eq, kWrongAddressOrValuePassedToRecordWrite);
    527   }
    528 
    529   if (!FLAG_incremental_marking) {
    530     return;
    531   }
    532 
    533   if (emit_debug_code()) {
    534     ldr(ip, FieldMemOperand(object, HeapObject::kMapOffset));
    535     cmp(ip, map);
    536     Check(eq, kWrongAddressOrValuePassedToRecordWrite);
    537   }
    538 
    539   Label done;
    540 
    541   // A single check of the map's pages interesting flag suffices, since it is
    542   // only set during incremental collection, and then it's also guaranteed that
    543   // the from object's page's interesting flag is also set.  This optimization
    544   // relies on the fact that maps can never be in new space.
    545   CheckPageFlag(map,
    546                 map,  // Used as scratch.
    547                 MemoryChunk::kPointersToHereAreInterestingMask,
    548                 eq,
    549                 &done);
    550 
    551   add(dst, object, Operand(HeapObject::kMapOffset - kHeapObjectTag));
    552   if (emit_debug_code()) {
    553     Label ok;
    554     tst(dst, Operand((1 << kPointerSizeLog2) - 1));
    555     b(eq, &ok);
    556     stop("Unaligned cell in write barrier");
    557     bind(&ok);
    558   }
    559 
    560   // Record the actual write.
    561   if (lr_status == kLRHasNotBeenSaved) {
    562     push(lr);
    563   }
    564   RecordWriteStub stub(isolate(), object, map, dst, OMIT_REMEMBERED_SET,
    565                        fp_mode);
    566   CallStub(&stub);
    567   if (lr_status == kLRHasNotBeenSaved) {
    568     pop(lr);
    569   }
    570 
    571   bind(&done);
    572 
    573   // Count number of write barriers in generated code.
    574   isolate()->counters()->write_barriers_static()->Increment();
    575   IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1, ip, dst);
    576 
    577   // Clobber clobbered registers when running with the debug-code flag
    578   // turned on to provoke errors.
    579   if (emit_debug_code()) {
    580     mov(dst, Operand(bit_cast<int32_t>(kZapValue + 12)));
    581     mov(map, Operand(bit_cast<int32_t>(kZapValue + 16)));
    582   }
    583 }
    584 
    585 
    586 // Will clobber 4 registers: object, address, scratch, ip.  The
    587 // register 'object' contains a heap object pointer.  The heap object
    588 // tag is shifted away.
    589 void MacroAssembler::RecordWrite(
    590     Register object,
    591     Register address,
    592     Register value,
    593     LinkRegisterStatus lr_status,
    594     SaveFPRegsMode fp_mode,
    595     RememberedSetAction remembered_set_action,
    596     SmiCheck smi_check,
    597     PointersToHereCheck pointers_to_here_check_for_value) {
    598   DCHECK(!object.is(value));
    599   if (emit_debug_code()) {
    600     ldr(ip, MemOperand(address));
    601     cmp(ip, value);
    602     Check(eq, kWrongAddressOrValuePassedToRecordWrite);
    603   }
    604 
    605   if (remembered_set_action == OMIT_REMEMBERED_SET &&
    606       !FLAG_incremental_marking) {
    607     return;
    608   }
    609 
    610   // First, check if a write barrier is even needed. The tests below
    611   // catch stores of smis and stores into the young generation.
    612   Label done;
    613 
    614   if (smi_check == INLINE_SMI_CHECK) {
    615     JumpIfSmi(value, &done);
    616   }
    617 
    618   if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) {
    619     CheckPageFlag(value,
    620                   value,  // Used as scratch.
    621                   MemoryChunk::kPointersToHereAreInterestingMask,
    622                   eq,
    623                   &done);
    624   }
    625   CheckPageFlag(object,
    626                 value,  // Used as scratch.
    627                 MemoryChunk::kPointersFromHereAreInterestingMask,
    628                 eq,
    629                 &done);
    630 
    631   // Record the actual write.
    632   if (lr_status == kLRHasNotBeenSaved) {
    633     push(lr);
    634   }
    635   RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
    636                        fp_mode);
    637   CallStub(&stub);
    638   if (lr_status == kLRHasNotBeenSaved) {
    639     pop(lr);
    640   }
    641 
    642   bind(&done);
    643 
    644   // Count number of write barriers in generated code.
    645   isolate()->counters()->write_barriers_static()->Increment();
    646   IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1, ip,
    647                    value);
    648 
    649   // Clobber clobbered registers when running with the debug-code flag
    650   // turned on to provoke errors.
    651   if (emit_debug_code()) {
    652     mov(address, Operand(bit_cast<int32_t>(kZapValue + 12)));
    653     mov(value, Operand(bit_cast<int32_t>(kZapValue + 16)));
    654   }
    655 }
    656 
    657 void MacroAssembler::RecordWriteCodeEntryField(Register js_function,
    658                                                Register code_entry,
    659                                                Register scratch) {
    660   const int offset = JSFunction::kCodeEntryOffset;
    661 
    662   // Since a code entry (value) is always in old space, we don't need to update
    663   // remembered set. If incremental marking is off, there is nothing for us to
    664   // do.
    665   if (!FLAG_incremental_marking) return;
    666 
    667   DCHECK(js_function.is(r1));
    668   DCHECK(code_entry.is(r4));
    669   DCHECK(scratch.is(r5));
    670   AssertNotSmi(js_function);
    671 
    672   if (emit_debug_code()) {
    673     add(scratch, js_function, Operand(offset - kHeapObjectTag));
    674     ldr(ip, MemOperand(scratch));
    675     cmp(ip, code_entry);
    676     Check(eq, kWrongAddressOrValuePassedToRecordWrite);
    677   }
    678 
    679   // First, check if a write barrier is even needed. The tests below
    680   // catch stores of Smis and stores into young gen.
    681   Label done;
    682 
    683   CheckPageFlag(code_entry, scratch,
    684                 MemoryChunk::kPointersToHereAreInterestingMask, eq, &done);
    685   CheckPageFlag(js_function, scratch,
    686                 MemoryChunk::kPointersFromHereAreInterestingMask, eq, &done);
    687 
    688   const Register dst = scratch;
    689   add(dst, js_function, Operand(offset - kHeapObjectTag));
    690 
    691   push(code_entry);
    692 
    693   // Save caller-saved registers, which includes js_function.
    694   DCHECK((kCallerSaved & js_function.bit()) != 0);
    695   DCHECK_EQ(kCallerSaved & code_entry.bit(), 0u);
    696   stm(db_w, sp, (kCallerSaved | lr.bit()));
    697 
    698   int argument_count = 3;
    699   PrepareCallCFunction(argument_count, code_entry);
    700 
    701   mov(r0, js_function);
    702   mov(r1, dst);
    703   mov(r2, Operand(ExternalReference::isolate_address(isolate())));
    704 
    705   {
    706     AllowExternalCallThatCantCauseGC scope(this);
    707     CallCFunction(
    708         ExternalReference::incremental_marking_record_write_code_entry_function(
    709             isolate()),
    710         argument_count);
    711   }
    712 
    713   // Restore caller-saved registers (including js_function and code_entry).
    714   ldm(ia_w, sp, (kCallerSaved | lr.bit()));
    715 
    716   pop(code_entry);
    717 
    718   bind(&done);
    719 }
    720 
    721 void MacroAssembler::RememberedSetHelper(Register object,  // For debug tests.
    722                                          Register address,
    723                                          Register scratch,
    724                                          SaveFPRegsMode fp_mode,
    725                                          RememberedSetFinalAction and_then) {
    726   Label done;
    727   if (emit_debug_code()) {
    728     Label ok;
    729     JumpIfNotInNewSpace(object, scratch, &ok);
    730     stop("Remembered set pointer is in new space");
    731     bind(&ok);
    732   }
    733   // Load store buffer top.
    734   ExternalReference store_buffer =
    735       ExternalReference::store_buffer_top(isolate());
    736   mov(ip, Operand(store_buffer));
    737   ldr(scratch, MemOperand(ip));
    738   // Store pointer to buffer and increment buffer top.
    739   str(address, MemOperand(scratch, kPointerSize, PostIndex));
    740   // Write back new top of buffer.
    741   str(scratch, MemOperand(ip));
    742   // Call stub on end of buffer.
    743   // Check for end of buffer.
    744   tst(scratch, Operand(StoreBuffer::kStoreBufferMask));
    745   if (and_then == kFallThroughAtEnd) {
    746     b(ne, &done);
    747   } else {
    748     DCHECK(and_then == kReturnAtEnd);
    749     Ret(ne);
    750   }
    751   push(lr);
    752   StoreBufferOverflowStub store_buffer_overflow(isolate(), fp_mode);
    753   CallStub(&store_buffer_overflow);
    754   pop(lr);
    755   bind(&done);
    756   if (and_then == kReturnAtEnd) {
    757     Ret();
    758   }
    759 }
    760 
    761 void MacroAssembler::PushCommonFrame(Register marker_reg) {
    762   if (marker_reg.is_valid()) {
    763     if (FLAG_enable_embedded_constant_pool) {
    764       if (marker_reg.code() > pp.code()) {
    765         stm(db_w, sp, pp.bit() | fp.bit() | lr.bit());
    766         add(fp, sp, Operand(kPointerSize));
    767         Push(marker_reg);
    768       } else {
    769         stm(db_w, sp, marker_reg.bit() | pp.bit() | fp.bit() | lr.bit());
    770         add(fp, sp, Operand(2 * kPointerSize));
    771       }
    772     } else {
    773       if (marker_reg.code() > fp.code()) {
    774         stm(db_w, sp, fp.bit() | lr.bit());
    775         mov(fp, Operand(sp));
    776         Push(marker_reg);
    777       } else {
    778         stm(db_w, sp, marker_reg.bit() | fp.bit() | lr.bit());
    779         add(fp, sp, Operand(kPointerSize));
    780       }
    781     }
    782   } else {
    783     stm(db_w, sp, (FLAG_enable_embedded_constant_pool ? pp.bit() : 0) |
    784                       fp.bit() | lr.bit());
    785     add(fp, sp, Operand(FLAG_enable_embedded_constant_pool ? kPointerSize : 0));
    786   }
    787 }
    788 
    789 void MacroAssembler::PopCommonFrame(Register marker_reg) {
    790   if (marker_reg.is_valid()) {
    791     if (FLAG_enable_embedded_constant_pool) {
    792       if (marker_reg.code() > pp.code()) {
    793         pop(marker_reg);
    794         ldm(ia_w, sp, pp.bit() | fp.bit() | lr.bit());
    795       } else {
    796         ldm(ia_w, sp, marker_reg.bit() | pp.bit() | fp.bit() | lr.bit());
    797       }
    798     } else {
    799       if (marker_reg.code() > fp.code()) {
    800         pop(marker_reg);
    801         ldm(ia_w, sp, fp.bit() | lr.bit());
    802       } else {
    803         ldm(ia_w, sp, marker_reg.bit() | fp.bit() | lr.bit());
    804       }
    805     }
    806   } else {
    807     ldm(ia_w, sp, (FLAG_enable_embedded_constant_pool ? pp.bit() : 0) |
    808                       fp.bit() | lr.bit());
    809   }
    810 }
    811 
    812 void MacroAssembler::PushStandardFrame(Register function_reg) {
    813   DCHECK(!function_reg.is_valid() || function_reg.code() < cp.code());
    814   stm(db_w, sp, (function_reg.is_valid() ? function_reg.bit() : 0) | cp.bit() |
    815                     (FLAG_enable_embedded_constant_pool ? pp.bit() : 0) |
    816                     fp.bit() | lr.bit());
    817   int offset = -StandardFrameConstants::kContextOffset;
    818   offset += function_reg.is_valid() ? kPointerSize : 0;
    819   add(fp, sp, Operand(offset));
    820 }
    821 
    822 
    823 // Push and pop all registers that can hold pointers.
    824 void MacroAssembler::PushSafepointRegisters() {
    825   // Safepoints expect a block of contiguous register values starting with r0.
    826   // except when FLAG_enable_embedded_constant_pool, which omits pp.
    827   DCHECK(kSafepointSavedRegisters ==
    828          (FLAG_enable_embedded_constant_pool
    829               ? ((1 << (kNumSafepointSavedRegisters + 1)) - 1) & ~pp.bit()
    830               : (1 << kNumSafepointSavedRegisters) - 1));
    831   // Safepoints expect a block of kNumSafepointRegisters values on the
    832   // stack, so adjust the stack for unsaved registers.
    833   const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
    834   DCHECK(num_unsaved >= 0);
    835   sub(sp, sp, Operand(num_unsaved * kPointerSize));
    836   stm(db_w, sp, kSafepointSavedRegisters);
    837 }
    838 
    839 
    840 void MacroAssembler::PopSafepointRegisters() {
    841   const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
    842   ldm(ia_w, sp, kSafepointSavedRegisters);
    843   add(sp, sp, Operand(num_unsaved * kPointerSize));
    844 }
    845 
    846 
    847 void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) {
    848   str(src, SafepointRegisterSlot(dst));
    849 }
    850 
    851 
    852 void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
    853   ldr(dst, SafepointRegisterSlot(src));
    854 }
    855 
    856 
    857 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
    858   // The registers are pushed starting with the highest encoding,
    859   // which means that lowest encodings are closest to the stack pointer.
    860   if (FLAG_enable_embedded_constant_pool && reg_code > pp.code()) {
    861     // RegList omits pp.
    862     reg_code -= 1;
    863   }
    864   DCHECK(reg_code >= 0 && reg_code < kNumSafepointRegisters);
    865   return reg_code;
    866 }
    867 
    868 
    869 MemOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
    870   return MemOperand(sp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
    871 }
    872 
    873 
    874 MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
    875   // Number of d-regs not known at snapshot time.
    876   DCHECK(!serializer_enabled());
    877   // General purpose registers are pushed last on the stack.
    878   const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
    879   int doubles_size = config->num_allocatable_double_registers() * kDoubleSize;
    880   int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
    881   return MemOperand(sp, doubles_size + register_offset);
    882 }
    883 
    884 
    885 void MacroAssembler::Ldrd(Register dst1, Register dst2,
    886                           const MemOperand& src, Condition cond) {
    887   DCHECK(src.rm().is(no_reg));
    888   DCHECK(!dst1.is(lr));  // r14.
    889 
    890   // V8 does not use this addressing mode, so the fallback code
    891   // below doesn't support it yet.
    892   DCHECK((src.am() != PreIndex) && (src.am() != NegPreIndex));
    893 
    894   // Generate two ldr instructions if ldrd is not applicable.
    895   if ((dst1.code() % 2 == 0) && (dst1.code() + 1 == dst2.code())) {
    896     ldrd(dst1, dst2, src, cond);
    897   } else {
    898     if ((src.am() == Offset) || (src.am() == NegOffset)) {
    899       MemOperand src2(src);
    900       src2.set_offset(src2.offset() + 4);
    901       if (dst1.is(src.rn())) {
    902         ldr(dst2, src2, cond);
    903         ldr(dst1, src, cond);
    904       } else {
    905         ldr(dst1, src, cond);
    906         ldr(dst2, src2, cond);
    907       }
    908     } else {  // PostIndex or NegPostIndex.
    909       DCHECK((src.am() == PostIndex) || (src.am() == NegPostIndex));
    910       if (dst1.is(src.rn())) {
    911         ldr(dst2, MemOperand(src.rn(), 4, Offset), cond);
    912         ldr(dst1, src, cond);
    913       } else {
    914         MemOperand src2(src);
    915         src2.set_offset(src2.offset() - 4);
    916         ldr(dst1, MemOperand(src.rn(), 4, PostIndex), cond);
    917         ldr(dst2, src2, cond);
    918       }
    919     }
    920   }
    921 }
    922 
    923 
    924 void MacroAssembler::Strd(Register src1, Register src2,
    925                           const MemOperand& dst, Condition cond) {
    926   DCHECK(dst.rm().is(no_reg));
    927   DCHECK(!src1.is(lr));  // r14.
    928 
    929   // V8 does not use this addressing mode, so the fallback code
    930   // below doesn't support it yet.
    931   DCHECK((dst.am() != PreIndex) && (dst.am() != NegPreIndex));
    932 
    933   // Generate two str instructions if strd is not applicable.
    934   if ((src1.code() % 2 == 0) && (src1.code() + 1 == src2.code())) {
    935     strd(src1, src2, dst, cond);
    936   } else {
    937     MemOperand dst2(dst);
    938     if ((dst.am() == Offset) || (dst.am() == NegOffset)) {
    939       dst2.set_offset(dst2.offset() + 4);
    940       str(src1, dst, cond);
    941       str(src2, dst2, cond);
    942     } else {  // PostIndex or NegPostIndex.
    943       DCHECK((dst.am() == PostIndex) || (dst.am() == NegPostIndex));
    944       dst2.set_offset(dst2.offset() - 4);
    945       str(src1, MemOperand(dst.rn(), 4, PostIndex), cond);
    946       str(src2, dst2, cond);
    947     }
    948   }
    949 }
    950 
    951 void MacroAssembler::VFPCanonicalizeNaN(const DwVfpRegister dst,
    952                                         const DwVfpRegister src,
    953                                         const Condition cond) {
    954   // Subtracting 0.0 preserves all inputs except for signalling NaNs, which
    955   // become quiet NaNs. We use vsub rather than vadd because vsub preserves -0.0
    956   // inputs: -0.0 + 0.0 = 0.0, but -0.0 - 0.0 = -0.0.
    957   vsub(dst, src, kDoubleRegZero, cond);
    958 }
    959 
    960 
    961 void MacroAssembler::VFPCompareAndSetFlags(const SwVfpRegister src1,
    962                                            const SwVfpRegister src2,
    963                                            const Condition cond) {
    964   // Compare and move FPSCR flags to the normal condition flags.
    965   VFPCompareAndLoadFlags(src1, src2, pc, cond);
    966 }
    967 
    968 void MacroAssembler::VFPCompareAndSetFlags(const SwVfpRegister src1,
    969                                            const float src2,
    970                                            const Condition cond) {
    971   // Compare and move FPSCR flags to the normal condition flags.
    972   VFPCompareAndLoadFlags(src1, src2, pc, cond);
    973 }
    974 
    975 
    976 void MacroAssembler::VFPCompareAndSetFlags(const DwVfpRegister src1,
    977                                            const DwVfpRegister src2,
    978                                            const Condition cond) {
    979   // Compare and move FPSCR flags to the normal condition flags.
    980   VFPCompareAndLoadFlags(src1, src2, pc, cond);
    981 }
    982 
    983 void MacroAssembler::VFPCompareAndSetFlags(const DwVfpRegister src1,
    984                                            const double src2,
    985                                            const Condition cond) {
    986   // Compare and move FPSCR flags to the normal condition flags.
    987   VFPCompareAndLoadFlags(src1, src2, pc, cond);
    988 }
    989 
    990 
    991 void MacroAssembler::VFPCompareAndLoadFlags(const SwVfpRegister src1,
    992                                             const SwVfpRegister src2,
    993                                             const Register fpscr_flags,
    994                                             const Condition cond) {
    995   // Compare and load FPSCR.
    996   vcmp(src1, src2, cond);
    997   vmrs(fpscr_flags, cond);
    998 }
    999 
   1000 void MacroAssembler::VFPCompareAndLoadFlags(const SwVfpRegister src1,
   1001                                             const float src2,
   1002                                             const Register fpscr_flags,
   1003                                             const Condition cond) {
   1004   // Compare and load FPSCR.
   1005   vcmp(src1, src2, cond);
   1006   vmrs(fpscr_flags, cond);
   1007 }
   1008 
   1009 
   1010 void MacroAssembler::VFPCompareAndLoadFlags(const DwVfpRegister src1,
   1011                                             const DwVfpRegister src2,
   1012                                             const Register fpscr_flags,
   1013                                             const Condition cond) {
   1014   // Compare and load FPSCR.
   1015   vcmp(src1, src2, cond);
   1016   vmrs(fpscr_flags, cond);
   1017 }
   1018 
   1019 void MacroAssembler::VFPCompareAndLoadFlags(const DwVfpRegister src1,
   1020                                             const double src2,
   1021                                             const Register fpscr_flags,
   1022                                             const Condition cond) {
   1023   // Compare and load FPSCR.
   1024   vcmp(src1, src2, cond);
   1025   vmrs(fpscr_flags, cond);
   1026 }
   1027 
   1028 
   1029 void MacroAssembler::Vmov(const DwVfpRegister dst,
   1030                           const double imm,
   1031                           const Register scratch) {
   1032   int64_t imm_bits = bit_cast<int64_t>(imm);
   1033   // Handle special values first.
   1034   if (imm_bits == bit_cast<int64_t>(0.0)) {
   1035     vmov(dst, kDoubleRegZero);
   1036   } else if (imm_bits == bit_cast<int64_t>(-0.0)) {
   1037     vneg(dst, kDoubleRegZero);
   1038   } else {
   1039     vmov(dst, imm, scratch);
   1040   }
   1041 }
   1042 
   1043 
   1044 void MacroAssembler::VmovHigh(Register dst, DwVfpRegister src) {
   1045   if (src.code() < 16) {
   1046     const LowDwVfpRegister loc = LowDwVfpRegister::from_code(src.code());
   1047     vmov(dst, loc.high());
   1048   } else {
   1049     vmov(dst, VmovIndexHi, src);
   1050   }
   1051 }
   1052 
   1053 
   1054 void MacroAssembler::VmovHigh(DwVfpRegister dst, Register src) {
   1055   if (dst.code() < 16) {
   1056     const LowDwVfpRegister loc = LowDwVfpRegister::from_code(dst.code());
   1057     vmov(loc.high(), src);
   1058   } else {
   1059     vmov(dst, VmovIndexHi, src);
   1060   }
   1061 }
   1062 
   1063 
   1064 void MacroAssembler::VmovLow(Register dst, DwVfpRegister src) {
   1065   if (src.code() < 16) {
   1066     const LowDwVfpRegister loc = LowDwVfpRegister::from_code(src.code());
   1067     vmov(dst, loc.low());
   1068   } else {
   1069     vmov(dst, VmovIndexLo, src);
   1070   }
   1071 }
   1072 
   1073 
   1074 void MacroAssembler::VmovLow(DwVfpRegister dst, Register src) {
   1075   if (dst.code() < 16) {
   1076     const LowDwVfpRegister loc = LowDwVfpRegister::from_code(dst.code());
   1077     vmov(loc.low(), src);
   1078   } else {
   1079     vmov(dst, VmovIndexLo, src);
   1080   }
   1081 }
   1082 
   1083 void MacroAssembler::VmovExtended(Register dst, int src_code) {
   1084   DCHECK_LE(SwVfpRegister::kMaxNumRegisters, src_code);
   1085   DCHECK_GT(SwVfpRegister::kMaxNumRegisters * 2, src_code);
   1086   if (src_code & 0x1) {
   1087     VmovHigh(dst, DwVfpRegister::from_code(src_code / 2));
   1088   } else {
   1089     VmovLow(dst, DwVfpRegister::from_code(src_code / 2));
   1090   }
   1091 }
   1092 
   1093 void MacroAssembler::VmovExtended(int dst_code, Register src) {
   1094   DCHECK_LE(SwVfpRegister::kMaxNumRegisters, dst_code);
   1095   DCHECK_GT(SwVfpRegister::kMaxNumRegisters * 2, dst_code);
   1096   if (dst_code & 0x1) {
   1097     VmovHigh(DwVfpRegister::from_code(dst_code / 2), src);
   1098   } else {
   1099     VmovLow(DwVfpRegister::from_code(dst_code / 2), src);
   1100   }
   1101 }
   1102 
   1103 void MacroAssembler::VmovExtended(int dst_code, int src_code,
   1104                                   Register scratch) {
   1105   if (src_code < SwVfpRegister::kMaxNumRegisters &&
   1106       dst_code < SwVfpRegister::kMaxNumRegisters) {
   1107     // src and dst are both s-registers.
   1108     vmov(SwVfpRegister::from_code(dst_code),
   1109          SwVfpRegister::from_code(src_code));
   1110   } else if (src_code < SwVfpRegister::kMaxNumRegisters) {
   1111     // src is an s-register.
   1112     vmov(scratch, SwVfpRegister::from_code(src_code));
   1113     VmovExtended(dst_code, scratch);
   1114   } else if (dst_code < SwVfpRegister::kMaxNumRegisters) {
   1115     // dst is an s-register.
   1116     VmovExtended(scratch, src_code);
   1117     vmov(SwVfpRegister::from_code(dst_code), scratch);
   1118   } else {
   1119     // Neither src or dst are s-registers.
   1120     DCHECK_GT(SwVfpRegister::kMaxNumRegisters * 2, src_code);
   1121     DCHECK_GT(SwVfpRegister::kMaxNumRegisters * 2, dst_code);
   1122     VmovExtended(scratch, src_code);
   1123     VmovExtended(dst_code, scratch);
   1124   }
   1125 }
   1126 
   1127 void MacroAssembler::VmovExtended(int dst_code, const MemOperand& src,
   1128                                   Register scratch) {
   1129   if (dst_code >= SwVfpRegister::kMaxNumRegisters) {
   1130     ldr(scratch, src);
   1131     VmovExtended(dst_code, scratch);
   1132   } else {
   1133     vldr(SwVfpRegister::from_code(dst_code), src);
   1134   }
   1135 }
   1136 
   1137 void MacroAssembler::VmovExtended(const MemOperand& dst, int src_code,
   1138                                   Register scratch) {
   1139   if (src_code >= SwVfpRegister::kMaxNumRegisters) {
   1140     VmovExtended(scratch, src_code);
   1141     str(scratch, dst);
   1142   } else {
   1143     vstr(SwVfpRegister::from_code(src_code), dst);
   1144   }
   1145 }
   1146 
   1147 void MacroAssembler::ExtractLane(Register dst, QwNeonRegister src,
   1148                                  NeonDataType dt, int lane) {
   1149   int size = NeonSz(dt);  // 0, 1, 2
   1150   int byte = lane << size;
   1151   int double_word = byte >> kDoubleSizeLog2;
   1152   int double_byte = byte & (kDoubleSize - 1);
   1153   int double_lane = double_byte >> size;
   1154   DwVfpRegister double_source =
   1155       DwVfpRegister::from_code(src.code() * 2 + double_word);
   1156   vmov(dt, dst, double_source, double_lane);
   1157 }
   1158 
   1159 void MacroAssembler::ExtractLane(SwVfpRegister dst, QwNeonRegister src,
   1160                                  Register scratch, int lane) {
   1161   int s_code = src.code() * 4 + lane;
   1162   VmovExtended(dst.code(), s_code, scratch);
   1163 }
   1164 
   1165 void MacroAssembler::ReplaceLane(QwNeonRegister dst, QwNeonRegister src,
   1166                                  Register src_lane, NeonDataType dt, int lane) {
   1167   Move(dst, src);
   1168   int size = NeonSz(dt);  // 0, 1, 2
   1169   int byte = lane << size;
   1170   int double_word = byte >> kDoubleSizeLog2;
   1171   int double_byte = byte & (kDoubleSize - 1);
   1172   int double_lane = double_byte >> size;
   1173   DwVfpRegister double_dst =
   1174       DwVfpRegister::from_code(dst.code() * 2 + double_word);
   1175   vmov(dt, double_dst, double_lane, src_lane);
   1176 }
   1177 
   1178 void MacroAssembler::ReplaceLane(QwNeonRegister dst, QwNeonRegister src,
   1179                                  SwVfpRegister src_lane, Register scratch,
   1180                                  int lane) {
   1181   Move(dst, src);
   1182   int s_code = dst.code() * 4 + lane;
   1183   VmovExtended(s_code, src_lane.code(), scratch);
   1184 }
   1185 
   1186 void MacroAssembler::Swizzle(QwNeonRegister dst, QwNeonRegister src,
   1187                              Register scratch, NeonSize size, uint32_t lanes) {
   1188   // TODO(bbudge) Handle Int16x8, Int8x16 vectors.
   1189   DCHECK_EQ(Neon32, size);
   1190   DCHECK_IMPLIES(size == Neon32, lanes < 0xFFFFu);
   1191   if (size == Neon32) {
   1192     switch (lanes) {
   1193       // TODO(bbudge) Handle more special cases.
   1194       case 0x3210:  // Identity.
   1195         Move(dst, src);
   1196         return;
   1197       case 0x1032:  // Swap top and bottom.
   1198         vext(dst, src, src, 8);
   1199         return;
   1200       case 0x2103:  // Rotation.
   1201         vext(dst, src, src, 12);
   1202         return;
   1203       case 0x0321:  // Rotation.
   1204         vext(dst, src, src, 4);
   1205         return;
   1206       case 0x0000:  // Equivalent to vdup.
   1207       case 0x1111:
   1208       case 0x2222:
   1209       case 0x3333: {
   1210         int lane_code = src.code() * 4 + (lanes & 0xF);
   1211         if (lane_code >= SwVfpRegister::kMaxNumRegisters) {
   1212           // TODO(bbudge) use vdup (vdup.32 dst, D<src>[lane]) once implemented.
   1213           int temp_code = kScratchDoubleReg.code() * 2;
   1214           VmovExtended(temp_code, lane_code, scratch);
   1215           lane_code = temp_code;
   1216         }
   1217         vdup(dst, SwVfpRegister::from_code(lane_code));
   1218         return;
   1219       }
   1220       case 0x2301:  // Swap lanes 0, 1 and lanes 2, 3.
   1221         vrev64(Neon32, dst, src);
   1222         return;
   1223       default:  // Handle all other cases with vmovs.
   1224         int src_code = src.code() * 4;
   1225         int dst_code = dst.code() * 4;
   1226         bool in_place = src.is(dst);
   1227         if (in_place) {
   1228           vmov(kScratchQuadReg, src);
   1229           src_code = kScratchQuadReg.code() * 4;
   1230         }
   1231         for (int i = 0; i < 4; i++) {
   1232           int lane = (lanes >> (i * 4) & 0xF);
   1233           VmovExtended(dst_code + i, src_code + lane, scratch);
   1234         }
   1235         if (in_place) {
   1236           // Restore zero reg.
   1237           veor(kDoubleRegZero, kDoubleRegZero, kDoubleRegZero);
   1238         }
   1239         return;
   1240     }
   1241   }
   1242 }
   1243 
   1244 void MacroAssembler::LslPair(Register dst_low, Register dst_high,
   1245                              Register src_low, Register src_high,
   1246                              Register scratch, Register shift) {
   1247   DCHECK(!AreAliased(dst_high, src_low));
   1248   DCHECK(!AreAliased(dst_high, shift));
   1249 
   1250   Label less_than_32;
   1251   Label done;
   1252   rsb(scratch, shift, Operand(32), SetCC);
   1253   b(gt, &less_than_32);
   1254   // If shift >= 32
   1255   and_(scratch, shift, Operand(0x1f));
   1256   lsl(dst_high, src_low, Operand(scratch));
   1257   mov(dst_low, Operand(0));
   1258   jmp(&done);
   1259   bind(&less_than_32);
   1260   // If shift < 32
   1261   lsl(dst_high, src_high, Operand(shift));
   1262   orr(dst_high, dst_high, Operand(src_low, LSR, scratch));
   1263   lsl(dst_low, src_low, Operand(shift));
   1264   bind(&done);
   1265 }
   1266 
   1267 void MacroAssembler::LslPair(Register dst_low, Register dst_high,
   1268                              Register src_low, Register src_high,
   1269                              uint32_t shift) {
   1270   DCHECK(!AreAliased(dst_high, src_low));
   1271   Label less_than_32;
   1272   Label done;
   1273   if (shift == 0) {
   1274     Move(dst_high, src_high);
   1275     Move(dst_low, src_low);
   1276   } else if (shift == 32) {
   1277     Move(dst_high, src_low);
   1278     Move(dst_low, Operand(0));
   1279   } else if (shift >= 32) {
   1280     shift &= 0x1f;
   1281     lsl(dst_high, src_low, Operand(shift));
   1282     mov(dst_low, Operand(0));
   1283   } else {
   1284     lsl(dst_high, src_high, Operand(shift));
   1285     orr(dst_high, dst_high, Operand(src_low, LSR, 32 - shift));
   1286     lsl(dst_low, src_low, Operand(shift));
   1287   }
   1288 }
   1289 
   1290 void MacroAssembler::LsrPair(Register dst_low, Register dst_high,
   1291                              Register src_low, Register src_high,
   1292                              Register scratch, Register shift) {
   1293   DCHECK(!AreAliased(dst_low, src_high));
   1294   DCHECK(!AreAliased(dst_low, shift));
   1295 
   1296   Label less_than_32;
   1297   Label done;
   1298   rsb(scratch, shift, Operand(32), SetCC);
   1299   b(gt, &less_than_32);
   1300   // If shift >= 32
   1301   and_(scratch, shift, Operand(0x1f));
   1302   lsr(dst_low, src_high, Operand(scratch));
   1303   mov(dst_high, Operand(0));
   1304   jmp(&done);
   1305   bind(&less_than_32);
   1306   // If shift < 32
   1307 
   1308   lsr(dst_low, src_low, Operand(shift));
   1309   orr(dst_low, dst_low, Operand(src_high, LSL, scratch));
   1310   lsr(dst_high, src_high, Operand(shift));
   1311   bind(&done);
   1312 }
   1313 
   1314 void MacroAssembler::LsrPair(Register dst_low, Register dst_high,
   1315                              Register src_low, Register src_high,
   1316                              uint32_t shift) {
   1317   DCHECK(!AreAliased(dst_low, src_high));
   1318   Label less_than_32;
   1319   Label done;
   1320   if (shift == 32) {
   1321     mov(dst_low, src_high);
   1322     mov(dst_high, Operand(0));
   1323   } else if (shift > 32) {
   1324     shift &= 0x1f;
   1325     lsr(dst_low, src_high, Operand(shift));
   1326     mov(dst_high, Operand(0));
   1327   } else if (shift == 0) {
   1328     Move(dst_low, src_low);
   1329     Move(dst_high, src_high);
   1330   } else {
   1331     lsr(dst_low, src_low, Operand(shift));
   1332     orr(dst_low, dst_low, Operand(src_high, LSL, 32 - shift));
   1333     lsr(dst_high, src_high, Operand(shift));
   1334   }
   1335 }
   1336 
   1337 void MacroAssembler::AsrPair(Register dst_low, Register dst_high,
   1338                              Register src_low, Register src_high,
   1339                              Register scratch, Register shift) {
   1340   DCHECK(!AreAliased(dst_low, src_high));
   1341   DCHECK(!AreAliased(dst_low, shift));
   1342 
   1343   Label less_than_32;
   1344   Label done;
   1345   rsb(scratch, shift, Operand(32), SetCC);
   1346   b(gt, &less_than_32);
   1347   // If shift >= 32
   1348   and_(scratch, shift, Operand(0x1f));
   1349   asr(dst_low, src_high, Operand(scratch));
   1350   asr(dst_high, src_high, Operand(31));
   1351   jmp(&done);
   1352   bind(&less_than_32);
   1353   // If shift < 32
   1354   lsr(dst_low, src_low, Operand(shift));
   1355   orr(dst_low, dst_low, Operand(src_high, LSL, scratch));
   1356   asr(dst_high, src_high, Operand(shift));
   1357   bind(&done);
   1358 }
   1359 
   1360 void MacroAssembler::AsrPair(Register dst_low, Register dst_high,
   1361                              Register src_low, Register src_high,
   1362                              uint32_t shift) {
   1363   DCHECK(!AreAliased(dst_low, src_high));
   1364   Label less_than_32;
   1365   Label done;
   1366   if (shift == 32) {
   1367     mov(dst_low, src_high);
   1368     asr(dst_high, src_high, Operand(31));
   1369   } else if (shift > 32) {
   1370     shift &= 0x1f;
   1371     asr(dst_low, src_high, Operand(shift));
   1372     asr(dst_high, src_high, Operand(31));
   1373   } else if (shift == 0) {
   1374     Move(dst_low, src_low);
   1375     Move(dst_high, src_high);
   1376   } else {
   1377     lsr(dst_low, src_low, Operand(shift));
   1378     orr(dst_low, dst_low, Operand(src_high, LSL, 32 - shift));
   1379     asr(dst_high, src_high, Operand(shift));
   1380   }
   1381 }
   1382 
   1383 void MacroAssembler::LoadConstantPoolPointerRegisterFromCodeTargetAddress(
   1384     Register code_target_address) {
   1385   DCHECK(FLAG_enable_embedded_constant_pool);
   1386   ldr(pp, MemOperand(code_target_address,
   1387                      Code::kConstantPoolOffset - Code::kHeaderSize));
   1388   add(pp, pp, code_target_address);
   1389 }
   1390 
   1391 
   1392 void MacroAssembler::LoadConstantPoolPointerRegister() {
   1393   DCHECK(FLAG_enable_embedded_constant_pool);
   1394   int entry_offset = pc_offset() + Instruction::kPCReadOffset;
   1395   sub(ip, pc, Operand(entry_offset));
   1396   LoadConstantPoolPointerRegisterFromCodeTargetAddress(ip);
   1397 }
   1398 
   1399 void MacroAssembler::StubPrologue(StackFrame::Type type) {
   1400   mov(ip, Operand(StackFrame::TypeToMarker(type)));
   1401   PushCommonFrame(ip);
   1402   if (FLAG_enable_embedded_constant_pool) {
   1403     LoadConstantPoolPointerRegister();
   1404     set_constant_pool_available(true);
   1405   }
   1406 }
   1407 
   1408 void MacroAssembler::Prologue(bool code_pre_aging) {
   1409   { PredictableCodeSizeScope predictible_code_size_scope(
   1410         this, kNoCodeAgeSequenceLength);
   1411     // The following three instructions must remain together and unmodified
   1412     // for code aging to work properly.
   1413     if (code_pre_aging) {
   1414       // Pre-age the code.
   1415       Code* stub = Code::GetPreAgedCodeAgeStub(isolate());
   1416       add(r0, pc, Operand(-8));
   1417       ldr(pc, MemOperand(pc, -4));
   1418       emit_code_stub_address(stub);
   1419     } else {
   1420       PushStandardFrame(r1);
   1421       nop(ip.code());
   1422     }
   1423   }
   1424   if (FLAG_enable_embedded_constant_pool) {
   1425     LoadConstantPoolPointerRegister();
   1426     set_constant_pool_available(true);
   1427   }
   1428 }
   1429 
   1430 void MacroAssembler::EmitLoadFeedbackVector(Register vector) {
   1431   ldr(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
   1432   ldr(vector, FieldMemOperand(vector, JSFunction::kFeedbackVectorOffset));
   1433   ldr(vector, FieldMemOperand(vector, Cell::kValueOffset));
   1434 }
   1435 
   1436 
   1437 void MacroAssembler::EnterFrame(StackFrame::Type type,
   1438                                 bool load_constant_pool_pointer_reg) {
   1439   // r0-r3: preserved
   1440   mov(ip, Operand(StackFrame::TypeToMarker(type)));
   1441   PushCommonFrame(ip);
   1442   if (FLAG_enable_embedded_constant_pool && load_constant_pool_pointer_reg) {
   1443     LoadConstantPoolPointerRegister();
   1444   }
   1445   if (type == StackFrame::INTERNAL) {
   1446     mov(ip, Operand(CodeObject()));
   1447     push(ip);
   1448   }
   1449 }
   1450 
   1451 
   1452 int MacroAssembler::LeaveFrame(StackFrame::Type type) {
   1453   // r0: preserved
   1454   // r1: preserved
   1455   // r2: preserved
   1456 
   1457   // Drop the execution stack down to the frame pointer and restore
   1458   // the caller frame pointer, return address and constant pool pointer
   1459   // (if FLAG_enable_embedded_constant_pool).
   1460   int frame_ends;
   1461   if (FLAG_enable_embedded_constant_pool) {
   1462     add(sp, fp, Operand(StandardFrameConstants::kConstantPoolOffset));
   1463     frame_ends = pc_offset();
   1464     ldm(ia_w, sp, pp.bit() | fp.bit() | lr.bit());
   1465   } else {
   1466     mov(sp, fp);
   1467     frame_ends = pc_offset();
   1468     ldm(ia_w, sp, fp.bit() | lr.bit());
   1469   }
   1470   return frame_ends;
   1471 }
   1472 
   1473 void MacroAssembler::EnterBuiltinFrame(Register context, Register target,
   1474                                        Register argc) {
   1475   Push(lr, fp, context, target);
   1476   add(fp, sp, Operand(2 * kPointerSize));
   1477   Push(argc);
   1478 }
   1479 
   1480 void MacroAssembler::LeaveBuiltinFrame(Register context, Register target,
   1481                                        Register argc) {
   1482   Pop(argc);
   1483   Pop(lr, fp, context, target);
   1484 }
   1485 
   1486 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space,
   1487                                     StackFrame::Type frame_type) {
   1488   DCHECK(frame_type == StackFrame::EXIT ||
   1489          frame_type == StackFrame::BUILTIN_EXIT);
   1490 
   1491   // Set up the frame structure on the stack.
   1492   DCHECK_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement);
   1493   DCHECK_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset);
   1494   DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset);
   1495   mov(ip, Operand(StackFrame::TypeToMarker(frame_type)));
   1496   PushCommonFrame(ip);
   1497   // Reserve room for saved entry sp and code object.
   1498   sub(sp, fp, Operand(ExitFrameConstants::kFixedFrameSizeFromFp));
   1499   if (emit_debug_code()) {
   1500     mov(ip, Operand::Zero());
   1501     str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset));
   1502   }
   1503   if (FLAG_enable_embedded_constant_pool) {
   1504     str(pp, MemOperand(fp, ExitFrameConstants::kConstantPoolOffset));
   1505   }
   1506   mov(ip, Operand(CodeObject()));
   1507   str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset));
   1508 
   1509   // Save the frame pointer and the context in top.
   1510   mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
   1511   str(fp, MemOperand(ip));
   1512   mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
   1513   str(cp, MemOperand(ip));
   1514 
   1515   // Optionally save all double registers.
   1516   if (save_doubles) {
   1517     SaveFPRegs(sp, ip);
   1518     // Note that d0 will be accessible at
   1519     //   fp - ExitFrameConstants::kFrameSize -
   1520     //   DwVfpRegister::kMaxNumRegisters * kDoubleSize,
   1521     // since the sp slot, code slot and constant pool slot (if
   1522     // FLAG_enable_embedded_constant_pool) were pushed after the fp.
   1523   }
   1524 
   1525   // Reserve place for the return address and stack space and align the frame
   1526   // preparing for calling the runtime function.
   1527   const int frame_alignment = MacroAssembler::ActivationFrameAlignment();
   1528   sub(sp, sp, Operand((stack_space + 1) * kPointerSize));
   1529   if (frame_alignment > 0) {
   1530     DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
   1531     and_(sp, sp, Operand(-frame_alignment));
   1532   }
   1533 
   1534   // Set the exit frame sp value to point just before the return address
   1535   // location.
   1536   add(ip, sp, Operand(kPointerSize));
   1537   str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset));
   1538 }
   1539 
   1540 int MacroAssembler::ActivationFrameAlignment() {
   1541 #if V8_HOST_ARCH_ARM
   1542   // Running on the real platform. Use the alignment as mandated by the local
   1543   // environment.
   1544   // Note: This will break if we ever start generating snapshots on one ARM
   1545   // platform for another ARM platform with a different alignment.
   1546   return base::OS::ActivationFrameAlignment();
   1547 #else  // V8_HOST_ARCH_ARM
   1548   // If we are using the simulator then we should always align to the expected
   1549   // alignment. As the simulator is used to generate snapshots we do not know
   1550   // if the target platform will need alignment, so this is controlled from a
   1551   // flag.
   1552   return FLAG_sim_stack_alignment;
   1553 #endif  // V8_HOST_ARCH_ARM
   1554 }
   1555 
   1556 
   1557 void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count,
   1558                                     bool restore_context,
   1559                                     bool argument_count_is_length) {
   1560   ConstantPoolUnavailableScope constant_pool_unavailable(this);
   1561 
   1562   // Optionally restore all double registers.
   1563   if (save_doubles) {
   1564     // Calculate the stack location of the saved doubles and restore them.
   1565     const int offset = ExitFrameConstants::kFixedFrameSizeFromFp;
   1566     sub(r3, fp,
   1567         Operand(offset + DwVfpRegister::kMaxNumRegisters * kDoubleSize));
   1568     RestoreFPRegs(r3, ip);
   1569   }
   1570 
   1571   // Clear top frame.
   1572   mov(r3, Operand::Zero());
   1573   mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
   1574   str(r3, MemOperand(ip));
   1575 
   1576   // Restore current context from top and clear it in debug mode.
   1577   if (restore_context) {
   1578     mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
   1579     ldr(cp, MemOperand(ip));
   1580   }
   1581 #ifdef DEBUG
   1582   mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
   1583   str(r3, MemOperand(ip));
   1584 #endif
   1585 
   1586   // Tear down the exit frame, pop the arguments, and return.
   1587   if (FLAG_enable_embedded_constant_pool) {
   1588     ldr(pp, MemOperand(fp, ExitFrameConstants::kConstantPoolOffset));
   1589   }
   1590   mov(sp, Operand(fp));
   1591   ldm(ia_w, sp, fp.bit() | lr.bit());
   1592   if (argument_count.is_valid()) {
   1593     if (argument_count_is_length) {
   1594       add(sp, sp, argument_count);
   1595     } else {
   1596       add(sp, sp, Operand(argument_count, LSL, kPointerSizeLog2));
   1597     }
   1598   }
   1599 }
   1600 
   1601 
   1602 void MacroAssembler::MovFromFloatResult(const DwVfpRegister dst) {
   1603   if (use_eabi_hardfloat()) {
   1604     Move(dst, d0);
   1605   } else {
   1606     vmov(dst, r0, r1);
   1607   }
   1608 }
   1609 
   1610 
   1611 // On ARM this is just a synonym to make the purpose clear.
   1612 void MacroAssembler::MovFromFloatParameter(DwVfpRegister dst) {
   1613   MovFromFloatResult(dst);
   1614 }
   1615 
   1616 void MacroAssembler::PrepareForTailCall(const ParameterCount& callee_args_count,
   1617                                         Register caller_args_count_reg,
   1618                                         Register scratch0, Register scratch1) {
   1619 #if DEBUG
   1620   if (callee_args_count.is_reg()) {
   1621     DCHECK(!AreAliased(callee_args_count.reg(), caller_args_count_reg, scratch0,
   1622                        scratch1));
   1623   } else {
   1624     DCHECK(!AreAliased(caller_args_count_reg, scratch0, scratch1));
   1625   }
   1626 #endif
   1627 
   1628   // Calculate the end of destination area where we will put the arguments
   1629   // after we drop current frame. We add kPointerSize to count the receiver
   1630   // argument which is not included into formal parameters count.
   1631   Register dst_reg = scratch0;
   1632   add(dst_reg, fp, Operand(caller_args_count_reg, LSL, kPointerSizeLog2));
   1633   add(dst_reg, dst_reg,
   1634       Operand(StandardFrameConstants::kCallerSPOffset + kPointerSize));
   1635 
   1636   Register src_reg = caller_args_count_reg;
   1637   // Calculate the end of source area. +kPointerSize is for the receiver.
   1638   if (callee_args_count.is_reg()) {
   1639     add(src_reg, sp, Operand(callee_args_count.reg(), LSL, kPointerSizeLog2));
   1640     add(src_reg, src_reg, Operand(kPointerSize));
   1641   } else {
   1642     add(src_reg, sp,
   1643         Operand((callee_args_count.immediate() + 1) * kPointerSize));
   1644   }
   1645 
   1646   if (FLAG_debug_code) {
   1647     cmp(src_reg, dst_reg);
   1648     Check(lo, kStackAccessBelowStackPointer);
   1649   }
   1650 
   1651   // Restore caller's frame pointer and return address now as they will be
   1652   // overwritten by the copying loop.
   1653   ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
   1654   ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
   1655 
   1656   // Now copy callee arguments to the caller frame going backwards to avoid
   1657   // callee arguments corruption (source and destination areas could overlap).
   1658 
   1659   // Both src_reg and dst_reg are pointing to the word after the one to copy,
   1660   // so they must be pre-decremented in the loop.
   1661   Register tmp_reg = scratch1;
   1662   Label loop, entry;
   1663   b(&entry);
   1664   bind(&loop);
   1665   ldr(tmp_reg, MemOperand(src_reg, -kPointerSize, PreIndex));
   1666   str(tmp_reg, MemOperand(dst_reg, -kPointerSize, PreIndex));
   1667   bind(&entry);
   1668   cmp(sp, src_reg);
   1669   b(ne, &loop);
   1670 
   1671   // Leave current frame.
   1672   mov(sp, dst_reg);
   1673 }
   1674 
   1675 void MacroAssembler::InvokePrologue(const ParameterCount& expected,
   1676                                     const ParameterCount& actual,
   1677                                     Label* done,
   1678                                     bool* definitely_mismatches,
   1679                                     InvokeFlag flag,
   1680                                     const CallWrapper& call_wrapper) {
   1681   bool definitely_matches = false;
   1682   *definitely_mismatches = false;
   1683   Label regular_invoke;
   1684 
   1685   // Check whether the expected and actual arguments count match. If not,
   1686   // setup registers according to contract with ArgumentsAdaptorTrampoline:
   1687   //  r0: actual arguments count
   1688   //  r1: function (passed through to callee)
   1689   //  r2: expected arguments count
   1690 
   1691   // The code below is made a lot easier because the calling code already sets
   1692   // up actual and expected registers according to the contract if values are
   1693   // passed in registers.
   1694   DCHECK(actual.is_immediate() || actual.reg().is(r0));
   1695   DCHECK(expected.is_immediate() || expected.reg().is(r2));
   1696 
   1697   if (expected.is_immediate()) {
   1698     DCHECK(actual.is_immediate());
   1699     mov(r0, Operand(actual.immediate()));
   1700     if (expected.immediate() == actual.immediate()) {
   1701       definitely_matches = true;
   1702     } else {
   1703       const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
   1704       if (expected.immediate() == sentinel) {
   1705         // Don't worry about adapting arguments for builtins that
   1706         // don't want that done. Skip adaption code by making it look
   1707         // like we have a match between expected and actual number of
   1708         // arguments.
   1709         definitely_matches = true;
   1710       } else {
   1711         *definitely_mismatches = true;
   1712         mov(r2, Operand(expected.immediate()));
   1713       }
   1714     }
   1715   } else {
   1716     if (actual.is_immediate()) {
   1717       mov(r0, Operand(actual.immediate()));
   1718       cmp(expected.reg(), Operand(actual.immediate()));
   1719       b(eq, &regular_invoke);
   1720     } else {
   1721       cmp(expected.reg(), Operand(actual.reg()));
   1722       b(eq, &regular_invoke);
   1723     }
   1724   }
   1725 
   1726   if (!definitely_matches) {
   1727     Handle<Code> adaptor =
   1728         isolate()->builtins()->ArgumentsAdaptorTrampoline();
   1729     if (flag == CALL_FUNCTION) {
   1730       call_wrapper.BeforeCall(CallSize(adaptor));
   1731       Call(adaptor);
   1732       call_wrapper.AfterCall();
   1733       if (!*definitely_mismatches) {
   1734         b(done);
   1735       }
   1736     } else {
   1737       Jump(adaptor, RelocInfo::CODE_TARGET);
   1738     }
   1739     bind(&regular_invoke);
   1740   }
   1741 }
   1742 
   1743 void MacroAssembler::CheckDebugHook(Register fun, Register new_target,
   1744                                     const ParameterCount& expected,
   1745                                     const ParameterCount& actual) {
   1746   Label skip_hook;
   1747   ExternalReference debug_hook_avtive =
   1748       ExternalReference::debug_hook_on_function_call_address(isolate());
   1749   mov(r4, Operand(debug_hook_avtive));
   1750   ldrsb(r4, MemOperand(r4));
   1751   cmp(r4, Operand(0));
   1752   b(eq, &skip_hook);
   1753   {
   1754     FrameScope frame(this,
   1755                      has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
   1756     if (expected.is_reg()) {
   1757       SmiTag(expected.reg());
   1758       Push(expected.reg());
   1759     }
   1760     if (actual.is_reg()) {
   1761       SmiTag(actual.reg());
   1762       Push(actual.reg());
   1763     }
   1764     if (new_target.is_valid()) {
   1765       Push(new_target);
   1766     }
   1767     Push(fun);
   1768     Push(fun);
   1769     CallRuntime(Runtime::kDebugOnFunctionCall);
   1770     Pop(fun);
   1771     if (new_target.is_valid()) {
   1772       Pop(new_target);
   1773     }
   1774     if (actual.is_reg()) {
   1775       Pop(actual.reg());
   1776       SmiUntag(actual.reg());
   1777     }
   1778     if (expected.is_reg()) {
   1779       Pop(expected.reg());
   1780       SmiUntag(expected.reg());
   1781     }
   1782   }
   1783   bind(&skip_hook);
   1784 }
   1785 
   1786 
   1787 void MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
   1788                                         const ParameterCount& expected,
   1789                                         const ParameterCount& actual,
   1790                                         InvokeFlag flag,
   1791                                         const CallWrapper& call_wrapper) {
   1792   // You can't call a function without a valid frame.
   1793   DCHECK(flag == JUMP_FUNCTION || has_frame());
   1794   DCHECK(function.is(r1));
   1795   DCHECK_IMPLIES(new_target.is_valid(), new_target.is(r3));
   1796 
   1797   if (call_wrapper.NeedsDebugHookCheck()) {
   1798     CheckDebugHook(function, new_target, expected, actual);
   1799   }
   1800 
   1801   // Clear the new.target register if not given.
   1802   if (!new_target.is_valid()) {
   1803     LoadRoot(r3, Heap::kUndefinedValueRootIndex);
   1804   }
   1805 
   1806   Label done;
   1807   bool definitely_mismatches = false;
   1808   InvokePrologue(expected, actual, &done, &definitely_mismatches, flag,
   1809                  call_wrapper);
   1810   if (!definitely_mismatches) {
   1811     // We call indirectly through the code field in the function to
   1812     // allow recompilation to take effect without changing any of the
   1813     // call sites.
   1814     Register code = r4;
   1815     ldr(code, FieldMemOperand(function, JSFunction::kCodeEntryOffset));
   1816     if (flag == CALL_FUNCTION) {
   1817       call_wrapper.BeforeCall(CallSize(code));
   1818       Call(code);
   1819       call_wrapper.AfterCall();
   1820     } else {
   1821       DCHECK(flag == JUMP_FUNCTION);
   1822       Jump(code);
   1823     }
   1824 
   1825     // Continue here if InvokePrologue does handle the invocation due to
   1826     // mismatched parameter counts.
   1827     bind(&done);
   1828   }
   1829 }
   1830 
   1831 
   1832 void MacroAssembler::InvokeFunction(Register fun,
   1833                                     Register new_target,
   1834                                     const ParameterCount& actual,
   1835                                     InvokeFlag flag,
   1836                                     const CallWrapper& call_wrapper) {
   1837   // You can't call a function without a valid frame.
   1838   DCHECK(flag == JUMP_FUNCTION || has_frame());
   1839 
   1840   // Contract with called JS functions requires that function is passed in r1.
   1841   DCHECK(fun.is(r1));
   1842 
   1843   Register expected_reg = r2;
   1844   Register temp_reg = r4;
   1845 
   1846   ldr(temp_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
   1847   ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
   1848   ldr(expected_reg,
   1849       FieldMemOperand(temp_reg,
   1850                       SharedFunctionInfo::kFormalParameterCountOffset));
   1851   SmiUntag(expected_reg);
   1852 
   1853   ParameterCount expected(expected_reg);
   1854   InvokeFunctionCode(fun, new_target, expected, actual, flag, call_wrapper);
   1855 }
   1856 
   1857 
   1858 void MacroAssembler::InvokeFunction(Register function,
   1859                                     const ParameterCount& expected,
   1860                                     const ParameterCount& actual,
   1861                                     InvokeFlag flag,
   1862                                     const CallWrapper& call_wrapper) {
   1863   // You can't call a function without a valid frame.
   1864   DCHECK(flag == JUMP_FUNCTION || has_frame());
   1865 
   1866   // Contract with called JS functions requires that function is passed in r1.
   1867   DCHECK(function.is(r1));
   1868 
   1869   // Get the function and setup the context.
   1870   ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
   1871 
   1872   InvokeFunctionCode(r1, no_reg, expected, actual, flag, call_wrapper);
   1873 }
   1874 
   1875 
   1876 void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
   1877                                     const ParameterCount& expected,
   1878                                     const ParameterCount& actual,
   1879                                     InvokeFlag flag,
   1880                                     const CallWrapper& call_wrapper) {
   1881   Move(r1, function);
   1882   InvokeFunction(r1, expected, actual, flag, call_wrapper);
   1883 }
   1884 
   1885 
   1886 void MacroAssembler::IsObjectJSStringType(Register object,
   1887                                           Register scratch,
   1888                                           Label* fail) {
   1889   DCHECK(kNotStringTag != 0);
   1890 
   1891   ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
   1892   ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
   1893   tst(scratch, Operand(kIsNotStringMask));
   1894   b(ne, fail);
   1895 }
   1896 
   1897 
   1898 void MacroAssembler::IsObjectNameType(Register object,
   1899                                       Register scratch,
   1900                                       Label* fail) {
   1901   ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
   1902   ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
   1903   cmp(scratch, Operand(LAST_NAME_TYPE));
   1904   b(hi, fail);
   1905 }
   1906 
   1907 void MacroAssembler::MaybeDropFrames() {
   1908   // Check whether we need to drop frames to restart a function on the stack.
   1909   ExternalReference restart_fp =
   1910       ExternalReference::debug_restart_fp_address(isolate());
   1911   mov(r1, Operand(restart_fp));
   1912   ldr(r1, MemOperand(r1));
   1913   tst(r1, r1);
   1914   Jump(isolate()->builtins()->FrameDropperTrampoline(), RelocInfo::CODE_TARGET,
   1915        ne);
   1916 }
   1917 
   1918 void MacroAssembler::PushStackHandler() {
   1919   // Adjust this code if not the case.
   1920   STATIC_ASSERT(StackHandlerConstants::kSize == 1 * kPointerSize);
   1921   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
   1922 
   1923   // Link the current handler as the next handler.
   1924   mov(r6, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
   1925   ldr(r5, MemOperand(r6));
   1926   push(r5);
   1927 
   1928   // Set this new handler as the current one.
   1929   str(sp, MemOperand(r6));
   1930 }
   1931 
   1932 
   1933 void MacroAssembler::PopStackHandler() {
   1934   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
   1935   pop(r1);
   1936   mov(ip, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
   1937   add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
   1938   str(r1, MemOperand(ip));
   1939 }
   1940 
   1941 
   1942 // Compute the hash code from the untagged key.  This must be kept in sync with
   1943 // ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
   1944 // code-stub-hydrogen.cc
   1945 void MacroAssembler::GetNumberHash(Register t0, Register scratch) {
   1946   // First of all we assign the hash seed to scratch.
   1947   LoadRoot(scratch, Heap::kHashSeedRootIndex);
   1948   SmiUntag(scratch);
   1949 
   1950   // Xor original key with a seed.
   1951   eor(t0, t0, Operand(scratch));
   1952 
   1953   // Compute the hash code from the untagged key.  This must be kept in sync
   1954   // with ComputeIntegerHash in utils.h.
   1955   //
   1956   // hash = ~hash + (hash << 15);
   1957   mvn(scratch, Operand(t0));
   1958   add(t0, scratch, Operand(t0, LSL, 15));
   1959   // hash = hash ^ (hash >> 12);
   1960   eor(t0, t0, Operand(t0, LSR, 12));
   1961   // hash = hash + (hash << 2);
   1962   add(t0, t0, Operand(t0, LSL, 2));
   1963   // hash = hash ^ (hash >> 4);
   1964   eor(t0, t0, Operand(t0, LSR, 4));
   1965   // hash = hash * 2057;
   1966   mov(scratch, Operand(t0, LSL, 11));
   1967   add(t0, t0, Operand(t0, LSL, 3));
   1968   add(t0, t0, scratch);
   1969   // hash = hash ^ (hash >> 16);
   1970   eor(t0, t0, Operand(t0, LSR, 16));
   1971   bic(t0, t0, Operand(0xc0000000u));
   1972 }
   1973 
   1974 void MacroAssembler::Allocate(int object_size,
   1975                               Register result,
   1976                               Register scratch1,
   1977                               Register scratch2,
   1978                               Label* gc_required,
   1979                               AllocationFlags flags) {
   1980   DCHECK(object_size <= kMaxRegularHeapObjectSize);
   1981   DCHECK((flags & ALLOCATION_FOLDED) == 0);
   1982   if (!FLAG_inline_new) {
   1983     if (emit_debug_code()) {
   1984       // Trash the registers to simulate an allocation failure.
   1985       mov(result, Operand(0x7091));
   1986       mov(scratch1, Operand(0x7191));
   1987       mov(scratch2, Operand(0x7291));
   1988     }
   1989     jmp(gc_required);
   1990     return;
   1991   }
   1992 
   1993   DCHECK(!AreAliased(result, scratch1, scratch2, ip));
   1994 
   1995   // Make object size into bytes.
   1996   if ((flags & SIZE_IN_WORDS) != 0) {
   1997     object_size *= kPointerSize;
   1998   }
   1999   DCHECK_EQ(0, object_size & kObjectAlignmentMask);
   2000 
   2001   // Check relative positions of allocation top and limit addresses.
   2002   // The values must be adjacent in memory to allow the use of LDM.
   2003   // Also, assert that the registers are numbered such that the values
   2004   // are loaded in the correct order.
   2005   ExternalReference allocation_top =
   2006       AllocationUtils::GetAllocationTopReference(isolate(), flags);
   2007   ExternalReference allocation_limit =
   2008       AllocationUtils::GetAllocationLimitReference(isolate(), flags);
   2009 
   2010   intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address());
   2011   intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address());
   2012   DCHECK((limit - top) == kPointerSize);
   2013   DCHECK(result.code() < ip.code());
   2014 
   2015   // Set up allocation top address register.
   2016   Register top_address = scratch1;
   2017   // This code stores a temporary value in ip. This is OK, as the code below
   2018   // does not need ip for implicit literal generation.
   2019   Register alloc_limit = ip;
   2020   Register result_end = scratch2;
   2021   mov(top_address, Operand(allocation_top));
   2022 
   2023   if ((flags & RESULT_CONTAINS_TOP) == 0) {
   2024     // Load allocation top into result and allocation limit into alloc_limit.
   2025     ldm(ia, top_address, result.bit() | alloc_limit.bit());
   2026   } else {
   2027     if (emit_debug_code()) {
   2028       // Assert that result actually contains top on entry.
   2029       ldr(alloc_limit, MemOperand(top_address));
   2030       cmp(result, alloc_limit);
   2031       Check(eq, kUnexpectedAllocationTop);
   2032     }
   2033     // Load allocation limit. Result already contains allocation top.
   2034     ldr(alloc_limit, MemOperand(top_address, limit - top));
   2035   }
   2036 
   2037   if ((flags & DOUBLE_ALIGNMENT) != 0) {
   2038     // Align the next allocation. Storing the filler map without checking top is
   2039     // safe in new-space because the limit of the heap is aligned there.
   2040     STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
   2041     and_(result_end, result, Operand(kDoubleAlignmentMask), SetCC);
   2042     Label aligned;
   2043     b(eq, &aligned);
   2044     if ((flags & PRETENURE) != 0) {
   2045       cmp(result, Operand(alloc_limit));
   2046       b(hs, gc_required);
   2047     }
   2048     mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
   2049     str(result_end, MemOperand(result, kDoubleSize / 2, PostIndex));
   2050     bind(&aligned);
   2051   }
   2052 
   2053   // Calculate new top and bail out if new space is exhausted. Use result
   2054   // to calculate the new top. We must preserve the ip register at this
   2055   // point, so we cannot just use add().
   2056   DCHECK(object_size > 0);
   2057   Register source = result;
   2058   int shift = 0;
   2059   while (object_size != 0) {
   2060     if (((object_size >> shift) & 0x03) == 0) {
   2061       shift += 2;
   2062     } else {
   2063       int bits = object_size & (0xff << shift);
   2064       object_size -= bits;
   2065       shift += 8;
   2066       Operand bits_operand(bits);
   2067       DCHECK(bits_operand.instructions_required(this) == 1);
   2068       add(result_end, source, bits_operand);
   2069       source = result_end;
   2070     }
   2071   }
   2072 
   2073   cmp(result_end, Operand(alloc_limit));
   2074   b(hi, gc_required);
   2075 
   2076   if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
   2077     // The top pointer is not updated for allocation folding dominators.
   2078     str(result_end, MemOperand(top_address));
   2079   }
   2080 
   2081   // Tag object.
   2082   add(result, result, Operand(kHeapObjectTag));
   2083 }
   2084 
   2085 
   2086 void MacroAssembler::Allocate(Register object_size, Register result,
   2087                               Register result_end, Register scratch,
   2088                               Label* gc_required, AllocationFlags flags) {
   2089   DCHECK((flags & ALLOCATION_FOLDED) == 0);
   2090   if (!FLAG_inline_new) {
   2091     if (emit_debug_code()) {
   2092       // Trash the registers to simulate an allocation failure.
   2093       mov(result, Operand(0x7091));
   2094       mov(scratch, Operand(0x7191));
   2095       mov(result_end, Operand(0x7291));
   2096     }
   2097     jmp(gc_required);
   2098     return;
   2099   }
   2100 
   2101   // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag
   2102   // is not specified. Other registers must not overlap.
   2103   DCHECK(!AreAliased(object_size, result, scratch, ip));
   2104   DCHECK(!AreAliased(result_end, result, scratch, ip));
   2105   DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end));
   2106 
   2107   // Check relative positions of allocation top and limit addresses.
   2108   // The values must be adjacent in memory to allow the use of LDM.
   2109   // Also, assert that the registers are numbered such that the values
   2110   // are loaded in the correct order.
   2111   ExternalReference allocation_top =
   2112       AllocationUtils::GetAllocationTopReference(isolate(), flags);
   2113   ExternalReference allocation_limit =
   2114       AllocationUtils::GetAllocationLimitReference(isolate(), flags);
   2115   intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address());
   2116   intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address());
   2117   DCHECK((limit - top) == kPointerSize);
   2118   DCHECK(result.code() < ip.code());
   2119 
   2120   // Set up allocation top address and allocation limit registers.
   2121   Register top_address = scratch;
   2122   // This code stores a temporary value in ip. This is OK, as the code below
   2123   // does not need ip for implicit literal generation.
   2124   Register alloc_limit = ip;
   2125   mov(top_address, Operand(allocation_top));
   2126 
   2127   if ((flags & RESULT_CONTAINS_TOP) == 0) {
   2128     // Load allocation top into result and allocation limit into alloc_limit.
   2129     ldm(ia, top_address, result.bit() | alloc_limit.bit());
   2130   } else {
   2131     if (emit_debug_code()) {
   2132       // Assert that result actually contains top on entry.
   2133       ldr(alloc_limit, MemOperand(top_address));
   2134       cmp(result, alloc_limit);
   2135       Check(eq, kUnexpectedAllocationTop);
   2136     }
   2137     // Load allocation limit. Result already contains allocation top.
   2138     ldr(alloc_limit, MemOperand(top_address, limit - top));
   2139   }
   2140 
   2141   if ((flags & DOUBLE_ALIGNMENT) != 0) {
   2142     // Align the next allocation. Storing the filler map without checking top is
   2143     // safe in new-space because the limit of the heap is aligned there.
   2144     DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
   2145     and_(result_end, result, Operand(kDoubleAlignmentMask), SetCC);
   2146     Label aligned;
   2147     b(eq, &aligned);
   2148     if ((flags & PRETENURE) != 0) {
   2149       cmp(result, Operand(alloc_limit));
   2150       b(hs, gc_required);
   2151     }
   2152     mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
   2153     str(result_end, MemOperand(result, kDoubleSize / 2, PostIndex));
   2154     bind(&aligned);
   2155   }
   2156 
   2157   // Calculate new top and bail out if new space is exhausted. Use result
   2158   // to calculate the new top. Object size may be in words so a shift is
   2159   // required to get the number of bytes.
   2160   if ((flags & SIZE_IN_WORDS) != 0) {
   2161     add(result_end, result, Operand(object_size, LSL, kPointerSizeLog2), SetCC);
   2162   } else {
   2163     add(result_end, result, Operand(object_size), SetCC);
   2164   }
   2165 
   2166   cmp(result_end, Operand(alloc_limit));
   2167   b(hi, gc_required);
   2168 
   2169   // Update allocation top. result temporarily holds the new top.
   2170   if (emit_debug_code()) {
   2171     tst(result_end, Operand(kObjectAlignmentMask));
   2172     Check(eq, kUnalignedAllocationInNewSpace);
   2173   }
   2174   if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
   2175     // The top pointer is not updated for allocation folding dominators.
   2176     str(result_end, MemOperand(top_address));
   2177   }
   2178 
   2179   // Tag object.
   2180   add(result, result, Operand(kHeapObjectTag));
   2181 }
   2182 
   2183 void MacroAssembler::FastAllocate(Register object_size, Register result,
   2184                                   Register result_end, Register scratch,
   2185                                   AllocationFlags flags) {
   2186   // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag
   2187   // is not specified. Other registers must not overlap.
   2188   DCHECK(!AreAliased(object_size, result, scratch, ip));
   2189   DCHECK(!AreAliased(result_end, result, scratch, ip));
   2190   DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end));
   2191 
   2192   ExternalReference allocation_top =
   2193       AllocationUtils::GetAllocationTopReference(isolate(), flags);
   2194 
   2195   Register top_address = scratch;
   2196   mov(top_address, Operand(allocation_top));
   2197   ldr(result, MemOperand(top_address));
   2198 
   2199   if ((flags & DOUBLE_ALIGNMENT) != 0) {
   2200     // Align the next allocation. Storing the filler map without checking top is
   2201     // safe in new-space because the limit of the heap is aligned there.
   2202     DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
   2203     and_(result_end, result, Operand(kDoubleAlignmentMask), SetCC);
   2204     Label aligned;
   2205     b(eq, &aligned);
   2206     mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
   2207     str(result_end, MemOperand(result, kDoubleSize / 2, PostIndex));
   2208     bind(&aligned);
   2209   }
   2210 
   2211   // Calculate new top using result. Object size may be in words so a shift is
   2212   // required to get the number of bytes.
   2213   if ((flags & SIZE_IN_WORDS) != 0) {
   2214     add(result_end, result, Operand(object_size, LSL, kPointerSizeLog2), SetCC);
   2215   } else {
   2216     add(result_end, result, Operand(object_size), SetCC);
   2217   }
   2218 
   2219   // Update allocation top. result temporarily holds the new top.
   2220   if (emit_debug_code()) {
   2221     tst(result_end, Operand(kObjectAlignmentMask));
   2222     Check(eq, kUnalignedAllocationInNewSpace);
   2223   }
   2224   // The top pointer is not updated for allocation folding dominators.
   2225   str(result_end, MemOperand(top_address));
   2226 
   2227   add(result, result, Operand(kHeapObjectTag));
   2228 }
   2229 
   2230 void MacroAssembler::FastAllocate(int object_size, Register result,
   2231                                   Register scratch1, Register scratch2,
   2232                                   AllocationFlags flags) {
   2233   DCHECK(object_size <= kMaxRegularHeapObjectSize);
   2234   DCHECK(!AreAliased(result, scratch1, scratch2, ip));
   2235 
   2236   // Make object size into bytes.
   2237   if ((flags & SIZE_IN_WORDS) != 0) {
   2238     object_size *= kPointerSize;
   2239   }
   2240   DCHECK_EQ(0, object_size & kObjectAlignmentMask);
   2241 
   2242   ExternalReference allocation_top =
   2243       AllocationUtils::GetAllocationTopReference(isolate(), flags);
   2244 
   2245   // Set up allocation top address register.
   2246   Register top_address = scratch1;
   2247   Register result_end = scratch2;
   2248   mov(top_address, Operand(allocation_top));
   2249   ldr(result, MemOperand(top_address));
   2250 
   2251   if ((flags & DOUBLE_ALIGNMENT) != 0) {
   2252     // Align the next allocation. Storing the filler map without checking top is
   2253     // safe in new-space because the limit of the heap is aligned there.
   2254     STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
   2255     and_(result_end, result, Operand(kDoubleAlignmentMask), SetCC);
   2256     Label aligned;
   2257     b(eq, &aligned);
   2258     mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
   2259     str(result_end, MemOperand(result, kDoubleSize / 2, PostIndex));
   2260     bind(&aligned);
   2261   }
   2262 
   2263   // Calculate new top using result. Object size may be in words so a shift is
   2264   // required to get the number of bytes. We must preserve the ip register at
   2265   // this point, so we cannot just use add().
   2266   DCHECK(object_size > 0);
   2267   Register source = result;
   2268   int shift = 0;
   2269   while (object_size != 0) {
   2270     if (((object_size >> shift) & 0x03) == 0) {
   2271       shift += 2;
   2272     } else {
   2273       int bits = object_size & (0xff << shift);
   2274       object_size -= bits;
   2275       shift += 8;
   2276       Operand bits_operand(bits);
   2277       DCHECK(bits_operand.instructions_required(this) == 1);
   2278       add(result_end, source, bits_operand);
   2279       source = result_end;
   2280     }
   2281   }
   2282 
   2283   // The top pointer is not updated for allocation folding dominators.
   2284   str(result_end, MemOperand(top_address));
   2285 
   2286   add(result, result, Operand(kHeapObjectTag));
   2287 }
   2288 
   2289 void MacroAssembler::CompareObjectType(Register object,
   2290                                        Register map,
   2291                                        Register type_reg,
   2292                                        InstanceType type) {
   2293   const Register temp = type_reg.is(no_reg) ? ip : type_reg;
   2294 
   2295   ldr(map, FieldMemOperand(object, HeapObject::kMapOffset));
   2296   CompareInstanceType(map, temp, type);
   2297 }
   2298 
   2299 
   2300 void MacroAssembler::CompareInstanceType(Register map,
   2301                                          Register type_reg,
   2302                                          InstanceType type) {
   2303   // Registers map and type_reg can be ip. These two lines assert
   2304   // that ip can be used with the two instructions (the constants
   2305   // will never need ip).
   2306   STATIC_ASSERT(Map::kInstanceTypeOffset < 4096);
   2307   STATIC_ASSERT(LAST_TYPE < 256);
   2308   ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
   2309   cmp(type_reg, Operand(type));
   2310 }
   2311 
   2312 
   2313 void MacroAssembler::CompareRoot(Register obj,
   2314                                  Heap::RootListIndex index) {
   2315   DCHECK(!obj.is(ip));
   2316   LoadRoot(ip, index);
   2317   cmp(obj, ip);
   2318 }
   2319 
   2320 void MacroAssembler::CompareMap(Register obj,
   2321                                 Register scratch,
   2322                                 Handle<Map> map,
   2323                                 Label* early_success) {
   2324   ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
   2325   CompareMap(scratch, map, early_success);
   2326 }
   2327 
   2328 
   2329 void MacroAssembler::CompareMap(Register obj_map,
   2330                                 Handle<Map> map,
   2331                                 Label* early_success) {
   2332   cmp(obj_map, Operand(map));
   2333 }
   2334 
   2335 
   2336 void MacroAssembler::CheckMap(Register obj,
   2337                               Register scratch,
   2338                               Handle<Map> map,
   2339                               Label* fail,
   2340                               SmiCheckType smi_check_type) {
   2341   if (smi_check_type == DO_SMI_CHECK) {
   2342     JumpIfSmi(obj, fail);
   2343   }
   2344 
   2345   Label success;
   2346   CompareMap(obj, scratch, map, &success);
   2347   b(ne, fail);
   2348   bind(&success);
   2349 }
   2350 
   2351 
   2352 void MacroAssembler::CheckMap(Register obj,
   2353                               Register scratch,
   2354                               Heap::RootListIndex index,
   2355                               Label* fail,
   2356                               SmiCheckType smi_check_type) {
   2357   if (smi_check_type == DO_SMI_CHECK) {
   2358     JumpIfSmi(obj, fail);
   2359   }
   2360   ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
   2361   LoadRoot(ip, index);
   2362   cmp(scratch, ip);
   2363   b(ne, fail);
   2364 }
   2365 
   2366 
   2367 void MacroAssembler::DispatchWeakMap(Register obj, Register scratch1,
   2368                                      Register scratch2, Handle<WeakCell> cell,
   2369                                      Handle<Code> success,
   2370                                      SmiCheckType smi_check_type) {
   2371   Label fail;
   2372   if (smi_check_type == DO_SMI_CHECK) {
   2373     JumpIfSmi(obj, &fail);
   2374   }
   2375   ldr(scratch1, FieldMemOperand(obj, HeapObject::kMapOffset));
   2376   CmpWeakValue(scratch1, cell, scratch2);
   2377   Jump(success, RelocInfo::CODE_TARGET, eq);
   2378   bind(&fail);
   2379 }
   2380 
   2381 
   2382 void MacroAssembler::CmpWeakValue(Register value, Handle<WeakCell> cell,
   2383                                   Register scratch) {
   2384   mov(scratch, Operand(cell));
   2385   ldr(scratch, FieldMemOperand(scratch, WeakCell::kValueOffset));
   2386   cmp(value, scratch);
   2387 }
   2388 
   2389 
   2390 void MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) {
   2391   mov(value, Operand(cell));
   2392   ldr(value, FieldMemOperand(value, WeakCell::kValueOffset));
   2393 }
   2394 
   2395 
   2396 void MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell,
   2397                                    Label* miss) {
   2398   GetWeakValue(value, cell);
   2399   JumpIfSmi(value, miss);
   2400 }
   2401 
   2402 
   2403 void MacroAssembler::GetMapConstructor(Register result, Register map,
   2404                                        Register temp, Register temp2) {
   2405   Label done, loop;
   2406   ldr(result, FieldMemOperand(map, Map::kConstructorOrBackPointerOffset));
   2407   bind(&loop);
   2408   JumpIfSmi(result, &done);
   2409   CompareObjectType(result, temp, temp2, MAP_TYPE);
   2410   b(ne, &done);
   2411   ldr(result, FieldMemOperand(result, Map::kConstructorOrBackPointerOffset));
   2412   b(&loop);
   2413   bind(&done);
   2414 }
   2415 
   2416 void MacroAssembler::CallStub(CodeStub* stub,
   2417                               TypeFeedbackId ast_id,
   2418                               Condition cond) {
   2419   DCHECK(AllowThisStubCall(stub));  // Stub calls are not allowed in some stubs.
   2420   Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id, cond);
   2421 }
   2422 
   2423 
   2424 void MacroAssembler::TailCallStub(CodeStub* stub, Condition cond) {
   2425   Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond);
   2426 }
   2427 
   2428 
   2429 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
   2430   return has_frame_ || !stub->SometimesSetsUpAFrame();
   2431 }
   2432 
   2433 void MacroAssembler::SmiToDouble(LowDwVfpRegister value, Register smi) {
   2434   if (CpuFeatures::IsSupported(VFPv3)) {
   2435     CpuFeatureScope scope(this, VFPv3);
   2436     vmov(value.low(), smi);
   2437     vcvt_f64_s32(value, 1);
   2438   } else {
   2439     SmiUntag(ip, smi);
   2440     vmov(value.low(), ip);
   2441     vcvt_f64_s32(value, value.low());
   2442   }
   2443 }
   2444 
   2445 
   2446 void MacroAssembler::TestDoubleIsInt32(DwVfpRegister double_input,
   2447                                        LowDwVfpRegister double_scratch) {
   2448   DCHECK(!double_input.is(double_scratch));
   2449   vcvt_s32_f64(double_scratch.low(), double_input);
   2450   vcvt_f64_s32(double_scratch, double_scratch.low());
   2451   VFPCompareAndSetFlags(double_input, double_scratch);
   2452 }
   2453 
   2454 
   2455 void MacroAssembler::TryDoubleToInt32Exact(Register result,
   2456                                            DwVfpRegister double_input,
   2457                                            LowDwVfpRegister double_scratch) {
   2458   DCHECK(!double_input.is(double_scratch));
   2459   vcvt_s32_f64(double_scratch.low(), double_input);
   2460   vmov(result, double_scratch.low());
   2461   vcvt_f64_s32(double_scratch, double_scratch.low());
   2462   VFPCompareAndSetFlags(double_input, double_scratch);
   2463 }
   2464 
   2465 
   2466 void MacroAssembler::TryInt32Floor(Register result,
   2467                                    DwVfpRegister double_input,
   2468                                    Register input_high,
   2469                                    LowDwVfpRegister double_scratch,
   2470                                    Label* done,
   2471                                    Label* exact) {
   2472   DCHECK(!result.is(input_high));
   2473   DCHECK(!double_input.is(double_scratch));
   2474   Label negative, exception;
   2475 
   2476   VmovHigh(input_high, double_input);
   2477 
   2478   // Test for NaN and infinities.
   2479   Sbfx(result, input_high,
   2480        HeapNumber::kExponentShift, HeapNumber::kExponentBits);
   2481   cmp(result, Operand(-1));
   2482   b(eq, &exception);
   2483   // Test for values that can be exactly represented as a
   2484   // signed 32-bit integer.
   2485   TryDoubleToInt32Exact(result, double_input, double_scratch);
   2486   // If exact, return (result already fetched).
   2487   b(eq, exact);
   2488   cmp(input_high, Operand::Zero());
   2489   b(mi, &negative);
   2490 
   2491   // Input is in ]+0, +inf[.
   2492   // If result equals 0x7fffffff input was out of range or
   2493   // in ]0x7fffffff, 0x80000000[. We ignore this last case which
   2494   // could fits into an int32, that means we always think input was
   2495   // out of range and always go to exception.
   2496   // If result < 0x7fffffff, go to done, result fetched.
   2497   cmn(result, Operand(1));
   2498   b(mi, &exception);
   2499   b(done);
   2500 
   2501   // Input is in ]-inf, -0[.
   2502   // If x is a non integer negative number,
   2503   // floor(x) <=> round_to_zero(x) - 1.
   2504   bind(&negative);
   2505   sub(result, result, Operand(1), SetCC);
   2506   // If result is still negative, go to done, result fetched.
   2507   // Else, we had an overflow and we fall through exception.
   2508   b(mi, done);
   2509   bind(&exception);
   2510 }
   2511 
   2512 void MacroAssembler::TryInlineTruncateDoubleToI(Register result,
   2513                                                 DwVfpRegister double_input,
   2514                                                 Label* done) {
   2515   LowDwVfpRegister double_scratch = kScratchDoubleReg;
   2516   vcvt_s32_f64(double_scratch.low(), double_input);
   2517   vmov(result, double_scratch.low());
   2518 
   2519   // If result is not saturated (0x7fffffff or 0x80000000), we are done.
   2520   sub(ip, result, Operand(1));
   2521   cmp(ip, Operand(0x7ffffffe));
   2522   b(lt, done);
   2523 }
   2524 
   2525 
   2526 void MacroAssembler::TruncateDoubleToI(Register result,
   2527                                        DwVfpRegister double_input) {
   2528   Label done;
   2529 
   2530   TryInlineTruncateDoubleToI(result, double_input, &done);
   2531 
   2532   // If we fell through then inline version didn't succeed - call stub instead.
   2533   push(lr);
   2534   sub(sp, sp, Operand(kDoubleSize));  // Put input on stack.
   2535   vstr(double_input, MemOperand(sp, 0));
   2536 
   2537   DoubleToIStub stub(isolate(), sp, result, 0, true, true);
   2538   CallStub(&stub);
   2539 
   2540   add(sp, sp, Operand(kDoubleSize));
   2541   pop(lr);
   2542 
   2543   bind(&done);
   2544 }
   2545 
   2546 
   2547 void MacroAssembler::TruncateHeapNumberToI(Register result,
   2548                                            Register object) {
   2549   Label done;
   2550   LowDwVfpRegister double_scratch = kScratchDoubleReg;
   2551   DCHECK(!result.is(object));
   2552 
   2553   vldr(double_scratch,
   2554        MemOperand(object, HeapNumber::kValueOffset - kHeapObjectTag));
   2555   TryInlineTruncateDoubleToI(result, double_scratch, &done);
   2556 
   2557   // If we fell through then inline version didn't succeed - call stub instead.
   2558   push(lr);
   2559   DoubleToIStub stub(isolate(),
   2560                      object,
   2561                      result,
   2562                      HeapNumber::kValueOffset - kHeapObjectTag,
   2563                      true,
   2564                      true);
   2565   CallStub(&stub);
   2566   pop(lr);
   2567 
   2568   bind(&done);
   2569 }
   2570 
   2571 
   2572 void MacroAssembler::TruncateNumberToI(Register object,
   2573                                        Register result,
   2574                                        Register heap_number_map,
   2575                                        Register scratch1,
   2576                                        Label* not_number) {
   2577   Label done;
   2578   DCHECK(!result.is(object));
   2579 
   2580   UntagAndJumpIfSmi(result, object, &done);
   2581   JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number);
   2582   TruncateHeapNumberToI(result, object);
   2583 
   2584   bind(&done);
   2585 }
   2586 
   2587 
   2588 void MacroAssembler::GetLeastBitsFromSmi(Register dst,
   2589                                          Register src,
   2590                                          int num_least_bits) {
   2591   if (CpuFeatures::IsSupported(ARMv7) && !predictable_code_size()) {
   2592     CpuFeatureScope scope(this, ARMv7);
   2593     ubfx(dst, src, kSmiTagSize, num_least_bits);
   2594   } else {
   2595     SmiUntag(dst, src);
   2596     and_(dst, dst, Operand((1 << num_least_bits) - 1));
   2597   }
   2598 }
   2599 
   2600 
   2601 void MacroAssembler::GetLeastBitsFromInt32(Register dst,
   2602                                            Register src,
   2603                                            int num_least_bits) {
   2604   and_(dst, src, Operand((1 << num_least_bits) - 1));
   2605 }
   2606 
   2607 
   2608 void MacroAssembler::CallRuntime(const Runtime::Function* f,
   2609                                  int num_arguments,
   2610                                  SaveFPRegsMode save_doubles) {
   2611   // All parameters are on the stack.  r0 has the return value after call.
   2612 
   2613   // If the expected number of arguments of the runtime function is
   2614   // constant, we check that the actual number of arguments match the
   2615   // expectation.
   2616   CHECK(f->nargs < 0 || f->nargs == num_arguments);
   2617 
   2618   // TODO(1236192): Most runtime routines don't need the number of
   2619   // arguments passed in because it is constant. At some point we
   2620   // should remove this need and make the runtime routine entry code
   2621   // smarter.
   2622   mov(r0, Operand(num_arguments));
   2623   mov(r1, Operand(ExternalReference(f, isolate())));
   2624   CEntryStub stub(isolate(), 1, save_doubles);
   2625   CallStub(&stub);
   2626 }
   2627 
   2628 
   2629 void MacroAssembler::CallExternalReference(const ExternalReference& ext,
   2630                                            int num_arguments) {
   2631   mov(r0, Operand(num_arguments));
   2632   mov(r1, Operand(ext));
   2633 
   2634   CEntryStub stub(isolate(), 1);
   2635   CallStub(&stub);
   2636 }
   2637 
   2638 
   2639 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) {
   2640   const Runtime::Function* function = Runtime::FunctionForId(fid);
   2641   DCHECK_EQ(1, function->result_size);
   2642   if (function->nargs >= 0) {
   2643     // TODO(1236192): Most runtime routines don't need the number of
   2644     // arguments passed in because it is constant. At some point we
   2645     // should remove this need and make the runtime routine entry code
   2646     // smarter.
   2647     mov(r0, Operand(function->nargs));
   2648   }
   2649   JumpToExternalReference(ExternalReference(fid, isolate()));
   2650 }
   2651 
   2652 void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin,
   2653                                              bool builtin_exit_frame) {
   2654 #if defined(__thumb__)
   2655   // Thumb mode builtin.
   2656   DCHECK((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1);
   2657 #endif
   2658   mov(r1, Operand(builtin));
   2659   CEntryStub stub(isolate(), 1, kDontSaveFPRegs, kArgvOnStack,
   2660                   builtin_exit_frame);
   2661   Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
   2662 }
   2663 
   2664 void MacroAssembler::SetCounter(StatsCounter* counter, int value,
   2665                                 Register scratch1, Register scratch2) {
   2666   if (FLAG_native_code_counters && counter->Enabled()) {
   2667     mov(scratch1, Operand(value));
   2668     mov(scratch2, Operand(ExternalReference(counter)));
   2669     str(scratch1, MemOperand(scratch2));
   2670   }
   2671 }
   2672 
   2673 
   2674 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value,
   2675                                       Register scratch1, Register scratch2) {
   2676   DCHECK(value > 0);
   2677   if (FLAG_native_code_counters && counter->Enabled()) {
   2678     mov(scratch2, Operand(ExternalReference(counter)));
   2679     ldr(scratch1, MemOperand(scratch2));
   2680     add(scratch1, scratch1, Operand(value));
   2681     str(scratch1, MemOperand(scratch2));
   2682   }
   2683 }
   2684 
   2685 
   2686 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
   2687                                       Register scratch1, Register scratch2) {
   2688   DCHECK(value > 0);
   2689   if (FLAG_native_code_counters && counter->Enabled()) {
   2690     mov(scratch2, Operand(ExternalReference(counter)));
   2691     ldr(scratch1, MemOperand(scratch2));
   2692     sub(scratch1, scratch1, Operand(value));
   2693     str(scratch1, MemOperand(scratch2));
   2694   }
   2695 }
   2696 
   2697 
   2698 void MacroAssembler::Assert(Condition cond, BailoutReason reason) {
   2699   if (emit_debug_code())
   2700     Check(cond, reason);
   2701 }
   2702 
   2703 
   2704 void MacroAssembler::AssertFastElements(Register elements) {
   2705   if (emit_debug_code()) {
   2706     DCHECK(!elements.is(ip));
   2707     Label ok;
   2708     push(elements);
   2709     ldr(elements, FieldMemOperand(elements, HeapObject::kMapOffset));
   2710     LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
   2711     cmp(elements, ip);
   2712     b(eq, &ok);
   2713     LoadRoot(ip, Heap::kFixedDoubleArrayMapRootIndex);
   2714     cmp(elements, ip);
   2715     b(eq, &ok);
   2716     LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
   2717     cmp(elements, ip);
   2718     b(eq, &ok);
   2719     Abort(kJSObjectWithFastElementsMapHasSlowElements);
   2720     bind(&ok);
   2721     pop(elements);
   2722   }
   2723 }
   2724 
   2725 
   2726 void MacroAssembler::Check(Condition cond, BailoutReason reason) {
   2727   Label L;
   2728   b(cond, &L);
   2729   Abort(reason);
   2730   // will not return here
   2731   bind(&L);
   2732 }
   2733 
   2734 
   2735 void MacroAssembler::Abort(BailoutReason reason) {
   2736   Label abort_start;
   2737   bind(&abort_start);
   2738 #ifdef DEBUG
   2739   const char* msg = GetBailoutReason(reason);
   2740   if (msg != NULL) {
   2741     RecordComment("Abort message: ");
   2742     RecordComment(msg);
   2743   }
   2744 
   2745   if (FLAG_trap_on_abort) {
   2746     stop(msg);
   2747     return;
   2748   }
   2749 #endif
   2750 
   2751   // Check if Abort() has already been initialized.
   2752   DCHECK(isolate()->builtins()->Abort()->IsHeapObject());
   2753 
   2754   Move(r1, Smi::FromInt(static_cast<int>(reason)));
   2755 
   2756   // Disable stub call restrictions to always allow calls to abort.
   2757   if (!has_frame_) {
   2758     // We don't actually want to generate a pile of code for this, so just
   2759     // claim there is a stack frame, without generating one.
   2760     FrameScope scope(this, StackFrame::NONE);
   2761     Call(isolate()->builtins()->Abort(), RelocInfo::CODE_TARGET);
   2762   } else {
   2763     Call(isolate()->builtins()->Abort(), RelocInfo::CODE_TARGET);
   2764   }
   2765   // will not return here
   2766   if (is_const_pool_blocked()) {
   2767     // If the calling code cares about the exact number of
   2768     // instructions generated, we insert padding here to keep the size
   2769     // of the Abort macro constant.
   2770     static const int kExpectedAbortInstructions = 7;
   2771     int abort_instructions = InstructionsGeneratedSince(&abort_start);
   2772     DCHECK(abort_instructions <= kExpectedAbortInstructions);
   2773     while (abort_instructions++ < kExpectedAbortInstructions) {
   2774       nop();
   2775     }
   2776   }
   2777 }
   2778 
   2779 
   2780 void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
   2781   if (context_chain_length > 0) {
   2782     // Move up the chain of contexts to the context containing the slot.
   2783     ldr(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX)));
   2784     for (int i = 1; i < context_chain_length; i++) {
   2785       ldr(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
   2786     }
   2787   } else {
   2788     // Slot is in the current function context.  Move it into the
   2789     // destination register in case we store into it (the write barrier
   2790     // cannot be allowed to destroy the context in esi).
   2791     mov(dst, cp);
   2792   }
   2793 }
   2794 
   2795 void MacroAssembler::LoadNativeContextSlot(int index, Register dst) {
   2796   ldr(dst, NativeContextMemOperand());
   2797   ldr(dst, ContextMemOperand(dst, index));
   2798 }
   2799 
   2800 
   2801 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
   2802                                                   Register map,
   2803                                                   Register scratch) {
   2804   // Load the initial map. The global functions all have initial maps.
   2805   ldr(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
   2806   if (emit_debug_code()) {
   2807     Label ok, fail;
   2808     CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK);
   2809     b(&ok);
   2810     bind(&fail);
   2811     Abort(kGlobalFunctionsMustHaveInitialMap);
   2812     bind(&ok);
   2813   }
   2814 }
   2815 
   2816 
   2817 void MacroAssembler::JumpIfNotPowerOfTwoOrZero(
   2818     Register reg,
   2819     Register scratch,
   2820     Label* not_power_of_two_or_zero) {
   2821   sub(scratch, reg, Operand(1), SetCC);
   2822   b(mi, not_power_of_two_or_zero);
   2823   tst(scratch, reg);
   2824   b(ne, not_power_of_two_or_zero);
   2825 }
   2826 
   2827 
   2828 void MacroAssembler::JumpIfNotPowerOfTwoOrZeroAndNeg(
   2829     Register reg,
   2830     Register scratch,
   2831     Label* zero_and_neg,
   2832     Label* not_power_of_two) {
   2833   sub(scratch, reg, Operand(1), SetCC);
   2834   b(mi, zero_and_neg);
   2835   tst(scratch, reg);
   2836   b(ne, not_power_of_two);
   2837 }
   2838 
   2839 
   2840 void MacroAssembler::JumpIfNotBothSmi(Register reg1,
   2841                                       Register reg2,
   2842                                       Label* on_not_both_smi) {
   2843   STATIC_ASSERT(kSmiTag == 0);
   2844   tst(reg1, Operand(kSmiTagMask));
   2845   tst(reg2, Operand(kSmiTagMask), eq);
   2846   b(ne, on_not_both_smi);
   2847 }
   2848 
   2849 
   2850 void MacroAssembler::UntagAndJumpIfSmi(
   2851     Register dst, Register src, Label* smi_case) {
   2852   STATIC_ASSERT(kSmiTag == 0);
   2853   SmiUntag(dst, src, SetCC);
   2854   b(cc, smi_case);  // Shifter carry is not set for a smi.
   2855 }
   2856 
   2857 void MacroAssembler::JumpIfEitherSmi(Register reg1,
   2858                                      Register reg2,
   2859                                      Label* on_either_smi) {
   2860   STATIC_ASSERT(kSmiTag == 0);
   2861   tst(reg1, Operand(kSmiTagMask));
   2862   tst(reg2, Operand(kSmiTagMask), ne);
   2863   b(eq, on_either_smi);
   2864 }
   2865 
   2866 void MacroAssembler::AssertNotNumber(Register object) {
   2867   if (emit_debug_code()) {
   2868     STATIC_ASSERT(kSmiTag == 0);
   2869     tst(object, Operand(kSmiTagMask));
   2870     Check(ne, kOperandIsANumber);
   2871     push(object);
   2872     CompareObjectType(object, object, object, HEAP_NUMBER_TYPE);
   2873     pop(object);
   2874     Check(ne, kOperandIsANumber);
   2875   }
   2876 }
   2877 
   2878 void MacroAssembler::AssertNotSmi(Register object) {
   2879   if (emit_debug_code()) {
   2880     STATIC_ASSERT(kSmiTag == 0);
   2881     tst(object, Operand(kSmiTagMask));
   2882     Check(ne, kOperandIsASmi);
   2883   }
   2884 }
   2885 
   2886 
   2887 void MacroAssembler::AssertSmi(Register object) {
   2888   if (emit_debug_code()) {
   2889     STATIC_ASSERT(kSmiTag == 0);
   2890     tst(object, Operand(kSmiTagMask));
   2891     Check(eq, kOperandIsNotSmi);
   2892   }
   2893 }
   2894 
   2895 
   2896 void MacroAssembler::AssertString(Register object) {
   2897   if (emit_debug_code()) {
   2898     STATIC_ASSERT(kSmiTag == 0);
   2899     tst(object, Operand(kSmiTagMask));
   2900     Check(ne, kOperandIsASmiAndNotAString);
   2901     push(object);
   2902     ldr(object, FieldMemOperand(object, HeapObject::kMapOffset));
   2903     CompareInstanceType(object, object, FIRST_NONSTRING_TYPE);
   2904     pop(object);
   2905     Check(lo, kOperandIsNotAString);
   2906   }
   2907 }
   2908 
   2909 
   2910 void MacroAssembler::AssertName(Register object) {
   2911   if (emit_debug_code()) {
   2912     STATIC_ASSERT(kSmiTag == 0);
   2913     tst(object, Operand(kSmiTagMask));
   2914     Check(ne, kOperandIsASmiAndNotAName);
   2915     push(object);
   2916     ldr(object, FieldMemOperand(object, HeapObject::kMapOffset));
   2917     CompareInstanceType(object, object, LAST_NAME_TYPE);
   2918     pop(object);
   2919     Check(le, kOperandIsNotAName);
   2920   }
   2921 }
   2922 
   2923 
   2924 void MacroAssembler::AssertFunction(Register object) {
   2925   if (emit_debug_code()) {
   2926     STATIC_ASSERT(kSmiTag == 0);
   2927     tst(object, Operand(kSmiTagMask));
   2928     Check(ne, kOperandIsASmiAndNotAFunction);
   2929     push(object);
   2930     CompareObjectType(object, object, object, JS_FUNCTION_TYPE);
   2931     pop(object);
   2932     Check(eq, kOperandIsNotAFunction);
   2933   }
   2934 }
   2935 
   2936 
   2937 void MacroAssembler::AssertBoundFunction(Register object) {
   2938   if (emit_debug_code()) {
   2939     STATIC_ASSERT(kSmiTag == 0);
   2940     tst(object, Operand(kSmiTagMask));
   2941     Check(ne, kOperandIsASmiAndNotABoundFunction);
   2942     push(object);
   2943     CompareObjectType(object, object, object, JS_BOUND_FUNCTION_TYPE);
   2944     pop(object);
   2945     Check(eq, kOperandIsNotABoundFunction);
   2946   }
   2947 }
   2948 
   2949 void MacroAssembler::AssertGeneratorObject(Register object) {
   2950   if (emit_debug_code()) {
   2951     STATIC_ASSERT(kSmiTag == 0);
   2952     tst(object, Operand(kSmiTagMask));
   2953     Check(ne, kOperandIsASmiAndNotAGeneratorObject);
   2954     push(object);
   2955     CompareObjectType(object, object, object, JS_GENERATOR_OBJECT_TYPE);
   2956     pop(object);
   2957     Check(eq, kOperandIsNotAGeneratorObject);
   2958   }
   2959 }
   2960 
   2961 void MacroAssembler::AssertReceiver(Register object) {
   2962   if (emit_debug_code()) {
   2963     STATIC_ASSERT(kSmiTag == 0);
   2964     tst(object, Operand(kSmiTagMask));
   2965     Check(ne, kOperandIsASmiAndNotAReceiver);
   2966     push(object);
   2967     STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
   2968     CompareObjectType(object, object, object, FIRST_JS_RECEIVER_TYPE);
   2969     pop(object);
   2970     Check(hs, kOperandIsNotAReceiver);
   2971   }
   2972 }
   2973 
   2974 
   2975 void MacroAssembler::AssertUndefinedOrAllocationSite(Register object,
   2976                                                      Register scratch) {
   2977   if (emit_debug_code()) {
   2978     Label done_checking;
   2979     AssertNotSmi(object);
   2980     CompareRoot(object, Heap::kUndefinedValueRootIndex);
   2981     b(eq, &done_checking);
   2982     ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
   2983     CompareRoot(scratch, Heap::kAllocationSiteMapRootIndex);
   2984     Assert(eq, kExpectedUndefinedOrCell);
   2985     bind(&done_checking);
   2986   }
   2987 }
   2988 
   2989 
   2990 void MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) {
   2991   if (emit_debug_code()) {
   2992     CompareRoot(reg, index);
   2993     Check(eq, kHeapNumberMapRegisterClobbered);
   2994   }
   2995 }
   2996 
   2997 
   2998 void MacroAssembler::JumpIfNotHeapNumber(Register object,
   2999                                          Register heap_number_map,
   3000                                          Register scratch,
   3001                                          Label* on_not_heap_number) {
   3002   ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
   3003   AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
   3004   cmp(scratch, heap_number_map);
   3005   b(ne, on_not_heap_number);
   3006 }
   3007 
   3008 
   3009 void MacroAssembler::JumpIfNonSmisNotBothSequentialOneByteStrings(
   3010     Register first, Register second, Register scratch1, Register scratch2,
   3011     Label* failure) {
   3012   // Test that both first and second are sequential one-byte strings.
   3013   // Assume that they are non-smis.
   3014   ldr(scratch1, FieldMemOperand(first, HeapObject::kMapOffset));
   3015   ldr(scratch2, FieldMemOperand(second, HeapObject::kMapOffset));
   3016   ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
   3017   ldrb(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset));
   3018 
   3019   JumpIfBothInstanceTypesAreNotSequentialOneByte(scratch1, scratch2, scratch1,
   3020                                                  scratch2, failure);
   3021 }
   3022 
   3023 void MacroAssembler::JumpIfNotBothSequentialOneByteStrings(Register first,
   3024                                                            Register second,
   3025                                                            Register scratch1,
   3026                                                            Register scratch2,
   3027                                                            Label* failure) {
   3028   // Check that neither is a smi.
   3029   and_(scratch1, first, Operand(second));
   3030   JumpIfSmi(scratch1, failure);
   3031   JumpIfNonSmisNotBothSequentialOneByteStrings(first, second, scratch1,
   3032                                                scratch2, failure);
   3033 }
   3034 
   3035 
   3036 void MacroAssembler::JumpIfNotUniqueNameInstanceType(Register reg,
   3037                                                      Label* not_unique_name) {
   3038   STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
   3039   Label succeed;
   3040   tst(reg, Operand(kIsNotStringMask | kIsNotInternalizedMask));
   3041   b(eq, &succeed);
   3042   cmp(reg, Operand(SYMBOL_TYPE));
   3043   b(ne, not_unique_name);
   3044 
   3045   bind(&succeed);
   3046 }
   3047 
   3048 
   3049 // Allocates a heap number or jumps to the need_gc label if the young space
   3050 // is full and a scavenge is needed.
   3051 void MacroAssembler::AllocateHeapNumber(Register result,
   3052                                         Register scratch1,
   3053                                         Register scratch2,
   3054                                         Register heap_number_map,
   3055                                         Label* gc_required,
   3056                                         MutableMode mode) {
   3057   // Allocate an object in the heap for the heap number and tag it as a heap
   3058   // object.
   3059   Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
   3060            NO_ALLOCATION_FLAGS);
   3061 
   3062   Heap::RootListIndex map_index = mode == MUTABLE
   3063       ? Heap::kMutableHeapNumberMapRootIndex
   3064       : Heap::kHeapNumberMapRootIndex;
   3065   AssertIsRoot(heap_number_map, map_index);
   3066 
   3067   // Store heap number map in the allocated object.
   3068   str(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
   3069 }
   3070 
   3071 
   3072 void MacroAssembler::AllocateHeapNumberWithValue(Register result,
   3073                                                  DwVfpRegister value,
   3074                                                  Register scratch1,
   3075                                                  Register scratch2,
   3076                                                  Register heap_number_map,
   3077                                                  Label* gc_required) {
   3078   AllocateHeapNumber(result, scratch1, scratch2, heap_number_map, gc_required);
   3079   sub(scratch1, result, Operand(kHeapObjectTag));
   3080   vstr(value, scratch1, HeapNumber::kValueOffset);
   3081 }
   3082 
   3083 
   3084 void MacroAssembler::AllocateJSValue(Register result, Register constructor,
   3085                                      Register value, Register scratch1,
   3086                                      Register scratch2, Label* gc_required) {
   3087   DCHECK(!result.is(constructor));
   3088   DCHECK(!result.is(scratch1));
   3089   DCHECK(!result.is(scratch2));
   3090   DCHECK(!result.is(value));
   3091 
   3092   // Allocate JSValue in new space.
   3093   Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required,
   3094            NO_ALLOCATION_FLAGS);
   3095 
   3096   // Initialize the JSValue.
   3097   LoadGlobalFunctionInitialMap(constructor, scratch1, scratch2);
   3098   str(scratch1, FieldMemOperand(result, HeapObject::kMapOffset));
   3099   LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
   3100   str(scratch1, FieldMemOperand(result, JSObject::kPropertiesOffset));
   3101   str(scratch1, FieldMemOperand(result, JSObject::kElementsOffset));
   3102   str(value, FieldMemOperand(result, JSValue::kValueOffset));
   3103   STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
   3104 }
   3105 
   3106 void MacroAssembler::InitializeFieldsWithFiller(Register current_address,
   3107                                                 Register end_address,
   3108                                                 Register filler) {
   3109   Label loop, entry;
   3110   b(&entry);
   3111   bind(&loop);
   3112   str(filler, MemOperand(current_address, kPointerSize, PostIndex));
   3113   bind(&entry);
   3114   cmp(current_address, end_address);
   3115   b(lo, &loop);
   3116 }
   3117 
   3118 
   3119 void MacroAssembler::CheckFor32DRegs(Register scratch) {
   3120   mov(scratch, Operand(ExternalReference::cpu_features()));
   3121   ldr(scratch, MemOperand(scratch));
   3122   tst(scratch, Operand(1u << VFP32DREGS));
   3123 }
   3124 
   3125 
   3126 void MacroAssembler::SaveFPRegs(Register location, Register scratch) {
   3127   CpuFeatureScope scope(this, VFP32DREGS, CpuFeatureScope::kDontCheckSupported);
   3128   CheckFor32DRegs(scratch);
   3129   vstm(db_w, location, d16, d31, ne);
   3130   sub(location, location, Operand(16 * kDoubleSize), LeaveCC, eq);
   3131   vstm(db_w, location, d0, d15);
   3132 }
   3133 
   3134 
   3135 void MacroAssembler::RestoreFPRegs(Register location, Register scratch) {
   3136   CpuFeatureScope scope(this, VFP32DREGS, CpuFeatureScope::kDontCheckSupported);
   3137   CheckFor32DRegs(scratch);
   3138   vldm(ia_w, location, d0, d15);
   3139   vldm(ia_w, location, d16, d31, ne);
   3140   add(location, location, Operand(16 * kDoubleSize), LeaveCC, eq);
   3141 }
   3142 
   3143 template <typename T>
   3144 void MacroAssembler::FloatMaxHelper(T result, T left, T right,
   3145                                     Label* out_of_line) {
   3146   // This trivial case is caught sooner, so that the out-of-line code can be
   3147   // completely avoided.
   3148   DCHECK(!left.is(right));
   3149 
   3150   if (CpuFeatures::IsSupported(ARMv8)) {
   3151     CpuFeatureScope scope(this, ARMv8);
   3152     VFPCompareAndSetFlags(left, right);
   3153     b(vs, out_of_line);
   3154     vmaxnm(result, left, right);
   3155   } else {
   3156     Label done;
   3157     VFPCompareAndSetFlags(left, right);
   3158     b(vs, out_of_line);
   3159     // Avoid a conditional instruction if the result register is unique.
   3160     bool aliased_result_reg = result.is(left) || result.is(right);
   3161     Move(result, right, aliased_result_reg ? mi : al);
   3162     Move(result, left, gt);
   3163     b(ne, &done);
   3164     // Left and right are equal, but check for +/-0.
   3165     VFPCompareAndSetFlags(left, 0.0);
   3166     b(eq, out_of_line);
   3167     // The arguments are equal and not zero, so it doesn't matter which input we
   3168     // pick. We have already moved one input into the result (if it didn't
   3169     // already alias) so there's nothing more to do.
   3170     bind(&done);
   3171   }
   3172 }
   3173 
   3174 template <typename T>
   3175 void MacroAssembler::FloatMaxOutOfLineHelper(T result, T left, T right) {
   3176   DCHECK(!left.is(right));
   3177 
   3178   // ARMv8: At least one of left and right is a NaN.
   3179   // Anything else: At least one of left and right is a NaN, or both left and
   3180   // right are zeroes with unknown sign.
   3181 
   3182   // If left and right are +/-0, select the one with the most positive sign.
   3183   // If left or right are NaN, vadd propagates the appropriate one.
   3184   vadd(result, left, right);
   3185 }
   3186 
   3187 template <typename T>
   3188 void MacroAssembler::FloatMinHelper(T result, T left, T right,
   3189                                     Label* out_of_line) {
   3190   // This trivial case is caught sooner, so that the out-of-line code can be
   3191   // completely avoided.
   3192   DCHECK(!left.is(right));
   3193 
   3194   if (CpuFeatures::IsSupported(ARMv8)) {
   3195     CpuFeatureScope scope(this, ARMv8);
   3196     VFPCompareAndSetFlags(left, right);
   3197     b(vs, out_of_line);
   3198     vminnm(result, left, right);
   3199   } else {
   3200     Label done;
   3201     VFPCompareAndSetFlags(left, right);
   3202     b(vs, out_of_line);
   3203     // Avoid a conditional instruction if the result register is unique.
   3204     bool aliased_result_reg = result.is(left) || result.is(right);
   3205     Move(result, left, aliased_result_reg ? mi : al);
   3206     Move(result, right, gt);
   3207     b(ne, &done);
   3208     // Left and right are equal, but check for +/-0.
   3209     VFPCompareAndSetFlags(left, 0.0);
   3210     // If the arguments are equal and not zero, it doesn't matter which input we
   3211     // pick. We have already moved one input into the result (if it didn't
   3212     // already alias) so there's nothing more to do.
   3213     b(ne, &done);
   3214     // At this point, both left and right are either 0 or -0.
   3215     // We could use a single 'vorr' instruction here if we had NEON support.
   3216     // The algorithm used is -((-L) + (-R)), which is most efficiently expressed
   3217     // as -((-L) - R).
   3218     if (left.is(result)) {
   3219       DCHECK(!right.is(result));
   3220       vneg(result, left);
   3221       vsub(result, result, right);
   3222       vneg(result, result);
   3223     } else {
   3224       DCHECK(!left.is(result));
   3225       vneg(result, right);
   3226       vsub(result, result, left);
   3227       vneg(result, result);
   3228     }
   3229     bind(&done);
   3230   }
   3231 }
   3232 
   3233 template <typename T>
   3234 void MacroAssembler::FloatMinOutOfLineHelper(T result, T left, T right) {
   3235   DCHECK(!left.is(right));
   3236 
   3237   // At least one of left and right is a NaN. Use vadd to propagate the NaN
   3238   // appropriately. +/-0 is handled inline.
   3239   vadd(result, left, right);
   3240 }
   3241 
   3242 void MacroAssembler::FloatMax(SwVfpRegister result, SwVfpRegister left,
   3243                               SwVfpRegister right, Label* out_of_line) {
   3244   FloatMaxHelper(result, left, right, out_of_line);
   3245 }
   3246 
   3247 void MacroAssembler::FloatMin(SwVfpRegister result, SwVfpRegister left,
   3248                               SwVfpRegister right, Label* out_of_line) {
   3249   FloatMinHelper(result, left, right, out_of_line);
   3250 }
   3251 
   3252 void MacroAssembler::FloatMax(DwVfpRegister result, DwVfpRegister left,
   3253                               DwVfpRegister right, Label* out_of_line) {
   3254   FloatMaxHelper(result, left, right, out_of_line);
   3255 }
   3256 
   3257 void MacroAssembler::FloatMin(DwVfpRegister result, DwVfpRegister left,
   3258                               DwVfpRegister right, Label* out_of_line) {
   3259   FloatMinHelper(result, left, right, out_of_line);
   3260 }
   3261 
   3262 void MacroAssembler::FloatMaxOutOfLine(SwVfpRegister result, SwVfpRegister left,
   3263                                        SwVfpRegister right) {
   3264   FloatMaxOutOfLineHelper(result, left, right);
   3265 }
   3266 
   3267 void MacroAssembler::FloatMinOutOfLine(SwVfpRegister result, SwVfpRegister left,
   3268                                        SwVfpRegister right) {
   3269   FloatMinOutOfLineHelper(result, left, right);
   3270 }
   3271 
   3272 void MacroAssembler::FloatMaxOutOfLine(DwVfpRegister result, DwVfpRegister left,
   3273                                        DwVfpRegister right) {
   3274   FloatMaxOutOfLineHelper(result, left, right);
   3275 }
   3276 
   3277 void MacroAssembler::FloatMinOutOfLine(DwVfpRegister result, DwVfpRegister left,
   3278                                        DwVfpRegister right) {
   3279   FloatMinOutOfLineHelper(result, left, right);
   3280 }
   3281 
   3282 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte(
   3283     Register first, Register second, Register scratch1, Register scratch2,
   3284     Label* failure) {
   3285   const int kFlatOneByteStringMask =
   3286       kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
   3287   const int kFlatOneByteStringTag =
   3288       kStringTag | kOneByteStringTag | kSeqStringTag;
   3289   and_(scratch1, first, Operand(kFlatOneByteStringMask));
   3290   and_(scratch2, second, Operand(kFlatOneByteStringMask));
   3291   cmp(scratch1, Operand(kFlatOneByteStringTag));
   3292   // Ignore second test if first test failed.
   3293   cmp(scratch2, Operand(kFlatOneByteStringTag), eq);
   3294   b(ne, failure);
   3295 }
   3296 
   3297 static const int kRegisterPassedArguments = 4;
   3298 
   3299 
   3300 int MacroAssembler::CalculateStackPassedWords(int num_reg_arguments,
   3301                                               int num_double_arguments) {
   3302   int stack_passed_words = 0;
   3303   if (use_eabi_hardfloat()) {
   3304     // In the hard floating point calling convention, we can use
   3305     // all double registers to pass doubles.
   3306     if (num_double_arguments > DoubleRegister::NumRegisters()) {
   3307       stack_passed_words +=
   3308           2 * (num_double_arguments - DoubleRegister::NumRegisters());
   3309     }
   3310   } else {
   3311     // In the soft floating point calling convention, every double
   3312     // argument is passed using two registers.
   3313     num_reg_arguments += 2 * num_double_arguments;
   3314   }
   3315   // Up to four simple arguments are passed in registers r0..r3.
   3316   if (num_reg_arguments > kRegisterPassedArguments) {
   3317     stack_passed_words += num_reg_arguments - kRegisterPassedArguments;
   3318   }
   3319   return stack_passed_words;
   3320 }
   3321 
   3322 
   3323 void MacroAssembler::EmitSeqStringSetCharCheck(Register string,
   3324                                                Register index,
   3325                                                Register value,
   3326                                                uint32_t encoding_mask) {
   3327   Label is_object;
   3328   SmiTst(string);
   3329   Check(ne, kNonObject);
   3330 
   3331   ldr(ip, FieldMemOperand(string, HeapObject::kMapOffset));
   3332   ldrb(ip, FieldMemOperand(ip, Map::kInstanceTypeOffset));
   3333 
   3334   and_(ip, ip, Operand(kStringRepresentationMask | kStringEncodingMask));
   3335   cmp(ip, Operand(encoding_mask));
   3336   Check(eq, kUnexpectedStringType);
   3337 
   3338   // The index is assumed to be untagged coming in, tag it to compare with the
   3339   // string length without using a temp register, it is restored at the end of
   3340   // this function.
   3341   Label index_tag_ok, index_tag_bad;
   3342   TrySmiTag(index, index, &index_tag_bad);
   3343   b(&index_tag_ok);
   3344   bind(&index_tag_bad);
   3345   Abort(kIndexIsTooLarge);
   3346   bind(&index_tag_ok);
   3347 
   3348   ldr(ip, FieldMemOperand(string, String::kLengthOffset));
   3349   cmp(index, ip);
   3350   Check(lt, kIndexIsTooLarge);
   3351 
   3352   cmp(index, Operand(Smi::kZero));
   3353   Check(ge, kIndexIsNegative);
   3354 
   3355   SmiUntag(index, index);
   3356 }
   3357 
   3358 
   3359 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
   3360                                           int num_double_arguments,
   3361                                           Register scratch) {
   3362   int frame_alignment = ActivationFrameAlignment();
   3363   int stack_passed_arguments = CalculateStackPassedWords(
   3364       num_reg_arguments, num_double_arguments);
   3365   if (frame_alignment > kPointerSize) {
   3366     // Make stack end at alignment and make room for num_arguments - 4 words
   3367     // and the original value of sp.
   3368     mov(scratch, sp);
   3369     sub(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize));
   3370     DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
   3371     and_(sp, sp, Operand(-frame_alignment));
   3372     str(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize));
   3373   } else {
   3374     sub(sp, sp, Operand(stack_passed_arguments * kPointerSize));
   3375   }
   3376 }
   3377 
   3378 
   3379 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
   3380                                           Register scratch) {
   3381   PrepareCallCFunction(num_reg_arguments, 0, scratch);
   3382 }
   3383 
   3384 
   3385 void MacroAssembler::MovToFloatParameter(DwVfpRegister src) {
   3386   DCHECK(src.is(d0));
   3387   if (!use_eabi_hardfloat()) {
   3388     vmov(r0, r1, src);
   3389   }
   3390 }
   3391 
   3392 
   3393 // On ARM this is just a synonym to make the purpose clear.
   3394 void MacroAssembler::MovToFloatResult(DwVfpRegister src) {
   3395   MovToFloatParameter(src);
   3396 }
   3397 
   3398 
   3399 void MacroAssembler::MovToFloatParameters(DwVfpRegister src1,
   3400                                           DwVfpRegister src2) {
   3401   DCHECK(src1.is(d0));
   3402   DCHECK(src2.is(d1));
   3403   if (!use_eabi_hardfloat()) {
   3404     vmov(r0, r1, src1);
   3405     vmov(r2, r3, src2);
   3406   }
   3407 }
   3408 
   3409 
   3410 void MacroAssembler::CallCFunction(ExternalReference function,
   3411                                    int num_reg_arguments,
   3412                                    int num_double_arguments) {
   3413   mov(ip, Operand(function));
   3414   CallCFunctionHelper(ip, num_reg_arguments, num_double_arguments);
   3415 }
   3416 
   3417 
   3418 void MacroAssembler::CallCFunction(Register function,
   3419                                    int num_reg_arguments,
   3420                                    int num_double_arguments) {
   3421   CallCFunctionHelper(function, num_reg_arguments, num_double_arguments);
   3422 }
   3423 
   3424 
   3425 void MacroAssembler::CallCFunction(ExternalReference function,
   3426                                    int num_arguments) {
   3427   CallCFunction(function, num_arguments, 0);
   3428 }
   3429 
   3430 
   3431 void MacroAssembler::CallCFunction(Register function,
   3432                                    int num_arguments) {
   3433   CallCFunction(function, num_arguments, 0);
   3434 }
   3435 
   3436 
   3437 void MacroAssembler::CallCFunctionHelper(Register function,
   3438                                          int num_reg_arguments,
   3439                                          int num_double_arguments) {
   3440   DCHECK(has_frame());
   3441   // Make sure that the stack is aligned before calling a C function unless
   3442   // running in the simulator. The simulator has its own alignment check which
   3443   // provides more information.
   3444 #if V8_HOST_ARCH_ARM
   3445   if (emit_debug_code()) {
   3446     int frame_alignment = base::OS::ActivationFrameAlignment();
   3447     int frame_alignment_mask = frame_alignment - 1;
   3448     if (frame_alignment > kPointerSize) {
   3449       DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
   3450       Label alignment_as_expected;
   3451       tst(sp, Operand(frame_alignment_mask));
   3452       b(eq, &alignment_as_expected);
   3453       // Don't use Check here, as it will call Runtime_Abort possibly
   3454       // re-entering here.
   3455       stop("Unexpected alignment");
   3456       bind(&alignment_as_expected);
   3457     }
   3458   }
   3459 #endif
   3460 
   3461   // Just call directly. The function called cannot cause a GC, or
   3462   // allow preemption, so the return address in the link register
   3463   // stays correct.
   3464   Call(function);
   3465   int stack_passed_arguments = CalculateStackPassedWords(
   3466       num_reg_arguments, num_double_arguments);
   3467   if (ActivationFrameAlignment() > kPointerSize) {
   3468     ldr(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
   3469   } else {
   3470     add(sp, sp, Operand(stack_passed_arguments * kPointerSize));
   3471   }
   3472 }
   3473 
   3474 
   3475 void MacroAssembler::CheckPageFlag(
   3476     Register object,
   3477     Register scratch,
   3478     int mask,
   3479     Condition cc,
   3480     Label* condition_met) {
   3481   DCHECK(cc == eq || cc == ne);
   3482   Bfc(scratch, object, 0, kPageSizeBits);
   3483   ldr(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset));
   3484   tst(scratch, Operand(mask));
   3485   b(cc, condition_met);
   3486 }
   3487 
   3488 
   3489 void MacroAssembler::JumpIfBlack(Register object,
   3490                                  Register scratch0,
   3491                                  Register scratch1,
   3492                                  Label* on_black) {
   3493   HasColor(object, scratch0, scratch1, on_black, 1, 1);  // kBlackBitPattern.
   3494   DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
   3495 }
   3496 
   3497 
   3498 void MacroAssembler::HasColor(Register object,
   3499                               Register bitmap_scratch,
   3500                               Register mask_scratch,
   3501                               Label* has_color,
   3502                               int first_bit,
   3503                               int second_bit) {
   3504   DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, no_reg));
   3505 
   3506   GetMarkBits(object, bitmap_scratch, mask_scratch);
   3507 
   3508   Label other_color, word_boundary;
   3509   ldr(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
   3510   tst(ip, Operand(mask_scratch));
   3511   b(first_bit == 1 ? eq : ne, &other_color);
   3512   // Shift left 1 by adding.
   3513   add(mask_scratch, mask_scratch, Operand(mask_scratch), SetCC);
   3514   b(eq, &word_boundary);
   3515   tst(ip, Operand(mask_scratch));
   3516   b(second_bit == 1 ? ne : eq, has_color);
   3517   jmp(&other_color);
   3518 
   3519   bind(&word_boundary);
   3520   ldr(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize));
   3521   tst(ip, Operand(1));
   3522   b(second_bit == 1 ? ne : eq, has_color);
   3523   bind(&other_color);
   3524 }
   3525 
   3526 
   3527 void MacroAssembler::GetMarkBits(Register addr_reg,
   3528                                  Register bitmap_reg,
   3529                                  Register mask_reg) {
   3530   DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg));
   3531   and_(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask));
   3532   Ubfx(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2);
   3533   const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2;
   3534   Ubfx(ip, addr_reg, kLowBits, kPageSizeBits - kLowBits);
   3535   add(bitmap_reg, bitmap_reg, Operand(ip, LSL, kPointerSizeLog2));
   3536   mov(ip, Operand(1));
   3537   mov(mask_reg, Operand(ip, LSL, mask_reg));
   3538 }
   3539 
   3540 
   3541 void MacroAssembler::JumpIfWhite(Register value, Register bitmap_scratch,
   3542                                  Register mask_scratch, Register load_scratch,
   3543                                  Label* value_is_white) {
   3544   DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, ip));
   3545   GetMarkBits(value, bitmap_scratch, mask_scratch);
   3546 
   3547   // If the value is black or grey we don't need to do anything.
   3548   DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
   3549   DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0);
   3550   DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0);
   3551   DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
   3552 
   3553   // Since both black and grey have a 1 in the first position and white does
   3554   // not have a 1 there we only need to check one bit.
   3555   ldr(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
   3556   tst(mask_scratch, load_scratch);
   3557   b(eq, value_is_white);
   3558 }
   3559 
   3560 
   3561 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) {
   3562   usat(output_reg, 8, Operand(input_reg));
   3563 }
   3564 
   3565 
   3566 void MacroAssembler::ClampDoubleToUint8(Register result_reg,
   3567                                         DwVfpRegister input_reg,
   3568                                         LowDwVfpRegister double_scratch) {
   3569   Label done;
   3570 
   3571   // Handle inputs >= 255 (including +infinity).
   3572   Vmov(double_scratch, 255.0, result_reg);
   3573   mov(result_reg, Operand(255));
   3574   VFPCompareAndSetFlags(input_reg, double_scratch);
   3575   b(ge, &done);
   3576 
   3577   // For inputs < 255 (including negative) vcvt_u32_f64 with round-to-nearest
   3578   // rounding mode will provide the correct result.
   3579   vcvt_u32_f64(double_scratch.low(), input_reg, kFPSCRRounding);
   3580   vmov(result_reg, double_scratch.low());
   3581 
   3582   bind(&done);
   3583 }
   3584 
   3585 
   3586 void MacroAssembler::LoadInstanceDescriptors(Register map,
   3587                                              Register descriptors) {
   3588   ldr(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset));
   3589 }
   3590 
   3591 
   3592 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
   3593   ldr(dst, FieldMemOperand(map, Map::kBitField3Offset));
   3594   DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
   3595 }
   3596 
   3597 
   3598 void MacroAssembler::EnumLength(Register dst, Register map) {
   3599   STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
   3600   ldr(dst, FieldMemOperand(map, Map::kBitField3Offset));
   3601   and_(dst, dst, Operand(Map::EnumLengthBits::kMask));
   3602   SmiTag(dst);
   3603 }
   3604 
   3605 
   3606 void MacroAssembler::LoadAccessor(Register dst, Register holder,
   3607                                   int accessor_index,
   3608                                   AccessorComponent accessor) {
   3609   ldr(dst, FieldMemOperand(holder, HeapObject::kMapOffset));
   3610   LoadInstanceDescriptors(dst, dst);
   3611   ldr(dst,
   3612       FieldMemOperand(dst, DescriptorArray::GetValueOffset(accessor_index)));
   3613   int offset = accessor == ACCESSOR_GETTER ? AccessorPair::kGetterOffset
   3614                                            : AccessorPair::kSetterOffset;
   3615   ldr(dst, FieldMemOperand(dst, offset));
   3616 }
   3617 
   3618 
   3619 void MacroAssembler::CheckEnumCache(Label* call_runtime) {
   3620   Register null_value = r5;
   3621   Register  empty_fixed_array_value = r6;
   3622   LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
   3623   Label next, start;
   3624   mov(r2, r0);
   3625 
   3626   // Check if the enum length field is properly initialized, indicating that
   3627   // there is an enum cache.
   3628   ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset));
   3629 
   3630   EnumLength(r3, r1);
   3631   cmp(r3, Operand(Smi::FromInt(kInvalidEnumCacheSentinel)));
   3632   b(eq, call_runtime);
   3633 
   3634   LoadRoot(null_value, Heap::kNullValueRootIndex);
   3635   jmp(&start);
   3636 
   3637   bind(&next);
   3638   ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset));
   3639 
   3640   // For all objects but the receiver, check that the cache is empty.
   3641   EnumLength(r3, r1);
   3642   cmp(r3, Operand(Smi::kZero));
   3643   b(ne, call_runtime);
   3644 
   3645   bind(&start);
   3646 
   3647   // Check that there are no elements. Register r2 contains the current JS
   3648   // object we've reached through the prototype chain.
   3649   Label no_elements;
   3650   ldr(r2, FieldMemOperand(r2, JSObject::kElementsOffset));
   3651   cmp(r2, empty_fixed_array_value);
   3652   b(eq, &no_elements);
   3653 
   3654   // Second chance, the object may be using the empty slow element dictionary.
   3655   CompareRoot(r2, Heap::kEmptySlowElementDictionaryRootIndex);
   3656   b(ne, call_runtime);
   3657 
   3658   bind(&no_elements);
   3659   ldr(r2, FieldMemOperand(r1, Map::kPrototypeOffset));
   3660   cmp(r2, null_value);
   3661   b(ne, &next);
   3662 }
   3663 
   3664 void MacroAssembler::TestJSArrayForAllocationMemento(
   3665     Register receiver_reg,
   3666     Register scratch_reg,
   3667     Label* no_memento_found) {
   3668   Label map_check;
   3669   Label top_check;
   3670   ExternalReference new_space_allocation_top_adr =
   3671       ExternalReference::new_space_allocation_top_address(isolate());
   3672   const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag;
   3673   const int kMementoLastWordOffset =
   3674       kMementoMapOffset + AllocationMemento::kSize - kPointerSize;
   3675 
   3676   // Bail out if the object is not in new space.
   3677   JumpIfNotInNewSpace(receiver_reg, scratch_reg, no_memento_found);
   3678   // If the object is in new space, we need to check whether it is on the same
   3679   // page as the current top.
   3680   add(scratch_reg, receiver_reg, Operand(kMementoLastWordOffset));
   3681   mov(ip, Operand(new_space_allocation_top_adr));
   3682   ldr(ip, MemOperand(ip));
   3683   eor(scratch_reg, scratch_reg, Operand(ip));
   3684   tst(scratch_reg, Operand(~Page::kPageAlignmentMask));
   3685   b(eq, &top_check);
   3686   // The object is on a different page than allocation top. Bail out if the
   3687   // object sits on the page boundary as no memento can follow and we cannot
   3688   // touch the memory following it.
   3689   add(scratch_reg, receiver_reg, Operand(kMementoLastWordOffset));
   3690   eor(scratch_reg, scratch_reg, Operand(receiver_reg));
   3691   tst(scratch_reg, Operand(~Page::kPageAlignmentMask));
   3692   b(ne, no_memento_found);
   3693   // Continue with the actual map check.
   3694   jmp(&map_check);
   3695   // If top is on the same page as the current object, we need to check whether
   3696   // we are below top.
   3697   bind(&top_check);
   3698   add(scratch_reg, receiver_reg, Operand(kMementoLastWordOffset));
   3699   mov(ip, Operand(new_space_allocation_top_adr));
   3700   ldr(ip, MemOperand(ip));
   3701   cmp(scratch_reg, ip);
   3702   b(ge, no_memento_found);
   3703   // Memento map check.
   3704   bind(&map_check);
   3705   ldr(scratch_reg, MemOperand(receiver_reg, kMementoMapOffset));
   3706   cmp(scratch_reg, Operand(isolate()->factory()->allocation_memento_map()));
   3707 }
   3708 
   3709 Register GetRegisterThatIsNotOneOf(Register reg1,
   3710                                    Register reg2,
   3711                                    Register reg3,
   3712                                    Register reg4,
   3713                                    Register reg5,
   3714                                    Register reg6) {
   3715   RegList regs = 0;
   3716   if (reg1.is_valid()) regs |= reg1.bit();
   3717   if (reg2.is_valid()) regs |= reg2.bit();
   3718   if (reg3.is_valid()) regs |= reg3.bit();
   3719   if (reg4.is_valid()) regs |= reg4.bit();
   3720   if (reg5.is_valid()) regs |= reg5.bit();
   3721   if (reg6.is_valid()) regs |= reg6.bit();
   3722 
   3723   const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   3724   for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
   3725     int code = config->GetAllocatableGeneralCode(i);
   3726     Register candidate = Register::from_code(code);
   3727     if (regs & candidate.bit()) continue;
   3728     return candidate;
   3729   }
   3730   UNREACHABLE();
   3731   return no_reg;
   3732 }
   3733 
   3734 #ifdef DEBUG
   3735 bool AreAliased(Register reg1,
   3736                 Register reg2,
   3737                 Register reg3,
   3738                 Register reg4,
   3739                 Register reg5,
   3740                 Register reg6,
   3741                 Register reg7,
   3742                 Register reg8) {
   3743   int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() +
   3744       reg3.is_valid() + reg4.is_valid() + reg5.is_valid() + reg6.is_valid() +
   3745       reg7.is_valid() + reg8.is_valid();
   3746 
   3747   RegList regs = 0;
   3748   if (reg1.is_valid()) regs |= reg1.bit();
   3749   if (reg2.is_valid()) regs |= reg2.bit();
   3750   if (reg3.is_valid()) regs |= reg3.bit();
   3751   if (reg4.is_valid()) regs |= reg4.bit();
   3752   if (reg5.is_valid()) regs |= reg5.bit();
   3753   if (reg6.is_valid()) regs |= reg6.bit();
   3754   if (reg7.is_valid()) regs |= reg7.bit();
   3755   if (reg8.is_valid()) regs |= reg8.bit();
   3756   int n_of_non_aliasing_regs = NumRegs(regs);
   3757 
   3758   return n_of_valid_regs != n_of_non_aliasing_regs;
   3759 }
   3760 #endif
   3761 
   3762 
   3763 CodePatcher::CodePatcher(Isolate* isolate, byte* address, int instructions,
   3764                          FlushICache flush_cache)
   3765     : address_(address),
   3766       size_(instructions * Assembler::kInstrSize),
   3767       masm_(isolate, address, size_ + Assembler::kGap, CodeObjectRequired::kNo),
   3768       flush_cache_(flush_cache) {
   3769   // Create a new macro assembler pointing to the address of the code to patch.
   3770   // The size is adjusted with kGap on order for the assembler to generate size
   3771   // bytes of instructions without failing with buffer size constraints.
   3772   DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
   3773 }
   3774 
   3775 
   3776 CodePatcher::~CodePatcher() {
   3777   // Indicate that code has changed.
   3778   if (flush_cache_ == FLUSH) {
   3779     Assembler::FlushICache(masm_.isolate(), address_, size_);
   3780   }
   3781 
   3782   // Check that we don't have any pending constant pools.
   3783   DCHECK(masm_.pending_32_bit_constants_.empty());
   3784   DCHECK(masm_.pending_64_bit_constants_.empty());
   3785 
   3786   // Check that the code was patched as expected.
   3787   DCHECK(masm_.pc_ == address_ + size_);
   3788   DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
   3789 }
   3790 
   3791 
   3792 void CodePatcher::Emit(Instr instr) {
   3793   masm()->emit(instr);
   3794 }
   3795 
   3796 
   3797 void CodePatcher::Emit(Address addr) {
   3798   masm()->emit(reinterpret_cast<Instr>(addr));
   3799 }
   3800 
   3801 
   3802 void CodePatcher::EmitCondition(Condition cond) {
   3803   Instr instr = Assembler::instr_at(masm_.pc_);
   3804   instr = (instr & ~kCondMask) | cond;
   3805   masm_.emit(instr);
   3806 }
   3807 
   3808 
   3809 void MacroAssembler::TruncatingDiv(Register result,
   3810                                    Register dividend,
   3811                                    int32_t divisor) {
   3812   DCHECK(!dividend.is(result));
   3813   DCHECK(!dividend.is(ip));
   3814   DCHECK(!result.is(ip));
   3815   base::MagicNumbersForDivision<uint32_t> mag =
   3816       base::SignedDivisionByConstant(bit_cast<uint32_t>(divisor));
   3817   mov(ip, Operand(mag.multiplier));
   3818   bool neg = (mag.multiplier & (1U << 31)) != 0;
   3819   if (divisor > 0 && neg) {
   3820     smmla(result, dividend, ip, dividend);
   3821   } else {
   3822     smmul(result, dividend, ip);
   3823     if (divisor < 0 && !neg && mag.multiplier > 0) {
   3824       sub(result, result, Operand(dividend));
   3825     }
   3826   }
   3827   if (mag.shift > 0) mov(result, Operand(result, ASR, mag.shift));
   3828   add(result, result, Operand(dividend, LSR, 31));
   3829 }
   3830 
   3831 }  // namespace internal
   3832 }  // namespace v8
   3833 
   3834 #endif  // V8_TARGET_ARCH_ARM
   3835