Home | History | Annotate | Download | only in ia32
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/v8.h"
      6 
      7 #if V8_TARGET_ARCH_IA32
      8 
      9 #include "src/bootstrapper.h"
     10 #include "src/codegen.h"
     11 #include "src/cpu-profiler.h"
     12 #include "src/debug.h"
     13 #include "src/isolate-inl.h"
     14 #include "src/runtime.h"
     15 #include "src/serialize.h"
     16 
     17 namespace v8 {
     18 namespace internal {
     19 
     20 // -------------------------------------------------------------------------
     21 // MacroAssembler implementation.
     22 
     23 MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size)
     24     : Assembler(arg_isolate, buffer, size),
     25       generating_stub_(false),
     26       has_frame_(false) {
     27   if (isolate() != NULL) {
     28     // TODO(titzer): should we just use a null handle here instead?
     29     code_object_ = Handle<Object>(isolate()->heap()->undefined_value(),
     30                                   isolate());
     31   }
     32 }
     33 
     34 
     35 void MacroAssembler::Load(Register dst, const Operand& src, Representation r) {
     36   ASSERT(!r.IsDouble());
     37   if (r.IsInteger8()) {
     38     movsx_b(dst, src);
     39   } else if (r.IsUInteger8()) {
     40     movzx_b(dst, src);
     41   } else if (r.IsInteger16()) {
     42     movsx_w(dst, src);
     43   } else if (r.IsUInteger16()) {
     44     movzx_w(dst, src);
     45   } else {
     46     mov(dst, src);
     47   }
     48 }
     49 
     50 
     51 void MacroAssembler::Store(Register src, const Operand& dst, Representation r) {
     52   ASSERT(!r.IsDouble());
     53   if (r.IsInteger8() || r.IsUInteger8()) {
     54     mov_b(dst, src);
     55   } else if (r.IsInteger16() || r.IsUInteger16()) {
     56     mov_w(dst, src);
     57   } else {
     58     if (r.IsHeapObject()) {
     59       AssertNotSmi(src);
     60     } else if (r.IsSmi()) {
     61       AssertSmi(src);
     62     }
     63     mov(dst, src);
     64   }
     65 }
     66 
     67 
     68 void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
     69   if (isolate()->heap()->RootCanBeTreatedAsConstant(index)) {
     70     Handle<Object> value(&isolate()->heap()->roots_array_start()[index]);
     71     mov(destination, value);
     72     return;
     73   }
     74   ExternalReference roots_array_start =
     75       ExternalReference::roots_array_start(isolate());
     76   mov(destination, Immediate(index));
     77   mov(destination, Operand::StaticArray(destination,
     78                                         times_pointer_size,
     79                                         roots_array_start));
     80 }
     81 
     82 
     83 void MacroAssembler::StoreRoot(Register source,
     84                                Register scratch,
     85                                Heap::RootListIndex index) {
     86   ASSERT(Heap::RootCanBeWrittenAfterInitialization(index));
     87   ExternalReference roots_array_start =
     88       ExternalReference::roots_array_start(isolate());
     89   mov(scratch, Immediate(index));
     90   mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start),
     91       source);
     92 }
     93 
     94 
     95 void MacroAssembler::CompareRoot(Register with,
     96                                  Register scratch,
     97                                  Heap::RootListIndex index) {
     98   ExternalReference roots_array_start =
     99       ExternalReference::roots_array_start(isolate());
    100   mov(scratch, Immediate(index));
    101   cmp(with, Operand::StaticArray(scratch,
    102                                 times_pointer_size,
    103                                 roots_array_start));
    104 }
    105 
    106 
    107 void MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) {
    108   ASSERT(isolate()->heap()->RootCanBeTreatedAsConstant(index));
    109   Handle<Object> value(&isolate()->heap()->roots_array_start()[index]);
    110   cmp(with, value);
    111 }
    112 
    113 
    114 void MacroAssembler::CompareRoot(const Operand& with,
    115                                  Heap::RootListIndex index) {
    116   ASSERT(isolate()->heap()->RootCanBeTreatedAsConstant(index));
    117   Handle<Object> value(&isolate()->heap()->roots_array_start()[index]);
    118   cmp(with, value);
    119 }
    120 
    121 
    122 void MacroAssembler::InNewSpace(
    123     Register object,
    124     Register scratch,
    125     Condition cc,
    126     Label* condition_met,
    127     Label::Distance condition_met_distance) {
    128   ASSERT(cc == equal || cc == not_equal);
    129   if (scratch.is(object)) {
    130     and_(scratch, Immediate(~Page::kPageAlignmentMask));
    131   } else {
    132     mov(scratch, Immediate(~Page::kPageAlignmentMask));
    133     and_(scratch, object);
    134   }
    135   // Check that we can use a test_b.
    136   ASSERT(MemoryChunk::IN_FROM_SPACE < 8);
    137   ASSERT(MemoryChunk::IN_TO_SPACE < 8);
    138   int mask = (1 << MemoryChunk::IN_FROM_SPACE)
    139            | (1 << MemoryChunk::IN_TO_SPACE);
    140   // If non-zero, the page belongs to new-space.
    141   test_b(Operand(scratch, MemoryChunk::kFlagsOffset),
    142          static_cast<uint8_t>(mask));
    143   j(cc, condition_met, condition_met_distance);
    144 }
    145 
    146 
    147 void MacroAssembler::RememberedSetHelper(
    148     Register object,  // Only used for debug checks.
    149     Register addr,
    150     Register scratch,
    151     SaveFPRegsMode save_fp,
    152     MacroAssembler::RememberedSetFinalAction and_then) {
    153   Label done;
    154   if (emit_debug_code()) {
    155     Label ok;
    156     JumpIfNotInNewSpace(object, scratch, &ok, Label::kNear);
    157     int3();
    158     bind(&ok);
    159   }
    160   // Load store buffer top.
    161   ExternalReference store_buffer =
    162       ExternalReference::store_buffer_top(isolate());
    163   mov(scratch, Operand::StaticVariable(store_buffer));
    164   // Store pointer to buffer.
    165   mov(Operand(scratch, 0), addr);
    166   // Increment buffer top.
    167   add(scratch, Immediate(kPointerSize));
    168   // Write back new top of buffer.
    169   mov(Operand::StaticVariable(store_buffer), scratch);
    170   // Call stub on end of buffer.
    171   // Check for end of buffer.
    172   test(scratch, Immediate(StoreBuffer::kStoreBufferOverflowBit));
    173   if (and_then == kReturnAtEnd) {
    174     Label buffer_overflowed;
    175     j(not_equal, &buffer_overflowed, Label::kNear);
    176     ret(0);
    177     bind(&buffer_overflowed);
    178   } else {
    179     ASSERT(and_then == kFallThroughAtEnd);
    180     j(equal, &done, Label::kNear);
    181   }
    182   StoreBufferOverflowStub store_buffer_overflow =
    183       StoreBufferOverflowStub(isolate(), save_fp);
    184   CallStub(&store_buffer_overflow);
    185   if (and_then == kReturnAtEnd) {
    186     ret(0);
    187   } else {
    188     ASSERT(and_then == kFallThroughAtEnd);
    189     bind(&done);
    190   }
    191 }
    192 
    193 
    194 void MacroAssembler::ClampDoubleToUint8(XMMRegister input_reg,
    195                                         XMMRegister scratch_reg,
    196                                         Register result_reg) {
    197   Label done;
    198   Label conv_failure;
    199   xorps(scratch_reg, scratch_reg);
    200   cvtsd2si(result_reg, input_reg);
    201   test(result_reg, Immediate(0xFFFFFF00));
    202   j(zero, &done, Label::kNear);
    203   cmp(result_reg, Immediate(0x1));
    204   j(overflow, &conv_failure, Label::kNear);
    205   mov(result_reg, Immediate(0));
    206   setcc(sign, result_reg);
    207   sub(result_reg, Immediate(1));
    208   and_(result_reg, Immediate(255));
    209   jmp(&done, Label::kNear);
    210   bind(&conv_failure);
    211   Move(result_reg, Immediate(0));
    212   ucomisd(input_reg, scratch_reg);
    213   j(below, &done, Label::kNear);
    214   Move(result_reg, Immediate(255));
    215   bind(&done);
    216 }
    217 
    218 
    219 void MacroAssembler::ClampUint8(Register reg) {
    220   Label done;
    221   test(reg, Immediate(0xFFFFFF00));
    222   j(zero, &done, Label::kNear);
    223   setcc(negative, reg);  // 1 if negative, 0 if positive.
    224   dec_b(reg);  // 0 if negative, 255 if positive.
    225   bind(&done);
    226 }
    227 
    228 
    229 void MacroAssembler::SlowTruncateToI(Register result_reg,
    230                                      Register input_reg,
    231                                      int offset) {
    232   DoubleToIStub stub(isolate(), input_reg, result_reg, offset, true);
    233   call(stub.GetCode(), RelocInfo::CODE_TARGET);
    234 }
    235 
    236 
    237 void MacroAssembler::TruncateDoubleToI(Register result_reg,
    238                                        XMMRegister input_reg) {
    239   Label done;
    240   cvttsd2si(result_reg, Operand(input_reg));
    241   cmp(result_reg, 0x1);
    242   j(no_overflow, &done, Label::kNear);
    243 
    244   sub(esp, Immediate(kDoubleSize));
    245   movsd(MemOperand(esp, 0), input_reg);
    246   SlowTruncateToI(result_reg, esp, 0);
    247   add(esp, Immediate(kDoubleSize));
    248   bind(&done);
    249 }
    250 
    251 
    252 void MacroAssembler::DoubleToI(Register result_reg,
    253                                XMMRegister input_reg,
    254                                XMMRegister scratch,
    255                                MinusZeroMode minus_zero_mode,
    256                                Label* conversion_failed,
    257                                Label::Distance dst) {
    258   ASSERT(!input_reg.is(scratch));
    259   cvttsd2si(result_reg, Operand(input_reg));
    260   Cvtsi2sd(scratch, Operand(result_reg));
    261   ucomisd(scratch, input_reg);
    262   j(not_equal, conversion_failed, dst);
    263   j(parity_even, conversion_failed, dst);  // NaN.
    264   if (minus_zero_mode == FAIL_ON_MINUS_ZERO) {
    265     Label done;
    266     // The integer converted back is equal to the original. We
    267     // only have to test if we got -0 as an input.
    268     test(result_reg, Operand(result_reg));
    269     j(not_zero, &done, Label::kNear);
    270     movmskpd(result_reg, input_reg);
    271     // Bit 0 contains the sign of the double in input_reg.
    272     // If input was positive, we are ok and return 0, otherwise
    273     // jump to conversion_failed.
    274     and_(result_reg, 1);
    275     j(not_zero, conversion_failed, dst);
    276     bind(&done);
    277   }
    278 }
    279 
    280 
    281 void MacroAssembler::TruncateHeapNumberToI(Register result_reg,
    282                                            Register input_reg) {
    283   Label done, slow_case;
    284 
    285   if (CpuFeatures::IsSupported(SSE3)) {
    286     CpuFeatureScope scope(this, SSE3);
    287     Label convert;
    288     // Use more powerful conversion when sse3 is available.
    289     // Load x87 register with heap number.
    290     fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
    291     // Get exponent alone and check for too-big exponent.
    292     mov(result_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset));
    293     and_(result_reg, HeapNumber::kExponentMask);
    294     const uint32_t kTooBigExponent =
    295         (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift;
    296     cmp(Operand(result_reg), Immediate(kTooBigExponent));
    297     j(greater_equal, &slow_case, Label::kNear);
    298 
    299     // Reserve space for 64 bit answer.
    300     sub(Operand(esp), Immediate(kDoubleSize));
    301     // Do conversion, which cannot fail because we checked the exponent.
    302     fisttp_d(Operand(esp, 0));
    303     mov(result_reg, Operand(esp, 0));  // Low word of answer is the result.
    304     add(Operand(esp), Immediate(kDoubleSize));
    305     jmp(&done, Label::kNear);
    306 
    307     // Slow case.
    308     bind(&slow_case);
    309     if (input_reg.is(result_reg)) {
    310       // Input is clobbered. Restore number from fpu stack
    311       sub(Operand(esp), Immediate(kDoubleSize));
    312       fstp_d(Operand(esp, 0));
    313       SlowTruncateToI(result_reg, esp, 0);
    314       add(esp, Immediate(kDoubleSize));
    315     } else {
    316       fstp(0);
    317       SlowTruncateToI(result_reg, input_reg);
    318     }
    319   } else {
    320     movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
    321     cvttsd2si(result_reg, Operand(xmm0));
    322     cmp(result_reg, 0x1);
    323     j(no_overflow, &done, Label::kNear);
    324     // Check if the input was 0x8000000 (kMinInt).
    325     // If no, then we got an overflow and we deoptimize.
    326     ExternalReference min_int = ExternalReference::address_of_min_int();
    327     ucomisd(xmm0, Operand::StaticVariable(min_int));
    328     j(not_equal, &slow_case, Label::kNear);
    329     j(parity_even, &slow_case, Label::kNear);  // NaN.
    330     jmp(&done, Label::kNear);
    331 
    332     // Slow case.
    333     bind(&slow_case);
    334     if (input_reg.is(result_reg)) {
    335       // Input is clobbered. Restore number from double scratch.
    336       sub(esp, Immediate(kDoubleSize));
    337       movsd(MemOperand(esp, 0), xmm0);
    338       SlowTruncateToI(result_reg, esp, 0);
    339       add(esp, Immediate(kDoubleSize));
    340     } else {
    341       SlowTruncateToI(result_reg, input_reg);
    342     }
    343   }
    344   bind(&done);
    345 }
    346 
    347 
    348 void MacroAssembler::TaggedToI(Register result_reg,
    349                                Register input_reg,
    350                                XMMRegister temp,
    351                                MinusZeroMode minus_zero_mode,
    352                                Label* lost_precision) {
    353   Label done;
    354   ASSERT(!temp.is(xmm0));
    355 
    356   cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
    357       isolate()->factory()->heap_number_map());
    358   j(not_equal, lost_precision, Label::kNear);
    359 
    360   ASSERT(!temp.is(no_xmm_reg));
    361 
    362   movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
    363   cvttsd2si(result_reg, Operand(xmm0));
    364   Cvtsi2sd(temp, Operand(result_reg));
    365   ucomisd(xmm0, temp);
    366   RecordComment("Deferred TaggedToI: lost precision");
    367   j(not_equal, lost_precision, Label::kNear);
    368   RecordComment("Deferred TaggedToI: NaN");
    369   j(parity_even, lost_precision, Label::kNear);
    370   if (minus_zero_mode == FAIL_ON_MINUS_ZERO) {
    371     test(result_reg, Operand(result_reg));
    372     j(not_zero, &done, Label::kNear);
    373     movmskpd(result_reg, xmm0);
    374     and_(result_reg, 1);
    375     RecordComment("Deferred TaggedToI: minus zero");
    376     j(not_zero, lost_precision, Label::kNear);
    377   }
    378   bind(&done);
    379 }
    380 
    381 
    382 void MacroAssembler::LoadUint32(XMMRegister dst,
    383                                 Register src) {
    384   Label done;
    385   cmp(src, Immediate(0));
    386   ExternalReference uint32_bias =
    387         ExternalReference::address_of_uint32_bias();
    388   Cvtsi2sd(dst, src);
    389   j(not_sign, &done, Label::kNear);
    390   addsd(dst, Operand::StaticVariable(uint32_bias));
    391   bind(&done);
    392 }
    393 
    394 
    395 void MacroAssembler::RecordWriteArray(
    396     Register object,
    397     Register value,
    398     Register index,
    399     SaveFPRegsMode save_fp,
    400     RememberedSetAction remembered_set_action,
    401     SmiCheck smi_check,
    402     PointersToHereCheck pointers_to_here_check_for_value) {
    403   // First, check if a write barrier is even needed. The tests below
    404   // catch stores of Smis.
    405   Label done;
    406 
    407   // Skip barrier if writing a smi.
    408   if (smi_check == INLINE_SMI_CHECK) {
    409     ASSERT_EQ(0, kSmiTag);
    410     test(value, Immediate(kSmiTagMask));
    411     j(zero, &done);
    412   }
    413 
    414   // Array access: calculate the destination address in the same manner as
    415   // KeyedStoreIC::GenerateGeneric.  Multiply a smi by 2 to get an offset
    416   // into an array of words.
    417   Register dst = index;
    418   lea(dst, Operand(object, index, times_half_pointer_size,
    419                    FixedArray::kHeaderSize - kHeapObjectTag));
    420 
    421   RecordWrite(object, dst, value, save_fp, remembered_set_action,
    422               OMIT_SMI_CHECK, pointers_to_here_check_for_value);
    423 
    424   bind(&done);
    425 
    426   // Clobber clobbered input registers when running with the debug-code flag
    427   // turned on to provoke errors.
    428   if (emit_debug_code()) {
    429     mov(value, Immediate(BitCast<int32_t>(kZapValue)));
    430     mov(index, Immediate(BitCast<int32_t>(kZapValue)));
    431   }
    432 }
    433 
    434 
    435 void MacroAssembler::RecordWriteField(
    436     Register object,
    437     int offset,
    438     Register value,
    439     Register dst,
    440     SaveFPRegsMode save_fp,
    441     RememberedSetAction remembered_set_action,
    442     SmiCheck smi_check,
    443     PointersToHereCheck pointers_to_here_check_for_value) {
    444   // First, check if a write barrier is even needed. The tests below
    445   // catch stores of Smis.
    446   Label done;
    447 
    448   // Skip barrier if writing a smi.
    449   if (smi_check == INLINE_SMI_CHECK) {
    450     JumpIfSmi(value, &done, Label::kNear);
    451   }
    452 
    453   // Although the object register is tagged, the offset is relative to the start
    454   // of the object, so so offset must be a multiple of kPointerSize.
    455   ASSERT(IsAligned(offset, kPointerSize));
    456 
    457   lea(dst, FieldOperand(object, offset));
    458   if (emit_debug_code()) {
    459     Label ok;
    460     test_b(dst, (1 << kPointerSizeLog2) - 1);
    461     j(zero, &ok, Label::kNear);
    462     int3();
    463     bind(&ok);
    464   }
    465 
    466   RecordWrite(object, dst, value, save_fp, remembered_set_action,
    467               OMIT_SMI_CHECK, pointers_to_here_check_for_value);
    468 
    469   bind(&done);
    470 
    471   // Clobber clobbered input registers when running with the debug-code flag
    472   // turned on to provoke errors.
    473   if (emit_debug_code()) {
    474     mov(value, Immediate(BitCast<int32_t>(kZapValue)));
    475     mov(dst, Immediate(BitCast<int32_t>(kZapValue)));
    476   }
    477 }
    478 
    479 
    480 void MacroAssembler::RecordWriteForMap(
    481     Register object,
    482     Handle<Map> map,
    483     Register scratch1,
    484     Register scratch2,
    485     SaveFPRegsMode save_fp) {
    486   Label done;
    487 
    488   Register address = scratch1;
    489   Register value = scratch2;
    490   if (emit_debug_code()) {
    491     Label ok;
    492     lea(address, FieldOperand(object, HeapObject::kMapOffset));
    493     test_b(address, (1 << kPointerSizeLog2) - 1);
    494     j(zero, &ok, Label::kNear);
    495     int3();
    496     bind(&ok);
    497   }
    498 
    499   ASSERT(!object.is(value));
    500   ASSERT(!object.is(address));
    501   ASSERT(!value.is(address));
    502   AssertNotSmi(object);
    503 
    504   if (!FLAG_incremental_marking) {
    505     return;
    506   }
    507 
    508   // Compute the address.
    509   lea(address, FieldOperand(object, HeapObject::kMapOffset));
    510 
    511   // Count number of write barriers in generated code.
    512   isolate()->counters()->write_barriers_static()->Increment();
    513   IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
    514 
    515   // A single check of the map's pages interesting flag suffices, since it is
    516   // only set during incremental collection, and then it's also guaranteed that
    517   // the from object's page's interesting flag is also set.  This optimization
    518   // relies on the fact that maps can never be in new space.
    519   ASSERT(!isolate()->heap()->InNewSpace(*map));
    520   CheckPageFlagForMap(map,
    521                       MemoryChunk::kPointersToHereAreInterestingMask,
    522                       zero,
    523                       &done,
    524                       Label::kNear);
    525 
    526   RecordWriteStub stub(isolate(), object, value, address, OMIT_REMEMBERED_SET,
    527                        save_fp);
    528   CallStub(&stub);
    529 
    530   bind(&done);
    531 
    532   // Clobber clobbered input registers when running with the debug-code flag
    533   // turned on to provoke errors.
    534   if (emit_debug_code()) {
    535     mov(value, Immediate(BitCast<int32_t>(kZapValue)));
    536     mov(scratch1, Immediate(BitCast<int32_t>(kZapValue)));
    537     mov(scratch2, Immediate(BitCast<int32_t>(kZapValue)));
    538   }
    539 }
    540 
    541 
    542 void MacroAssembler::RecordWrite(
    543     Register object,
    544     Register address,
    545     Register value,
    546     SaveFPRegsMode fp_mode,
    547     RememberedSetAction remembered_set_action,
    548     SmiCheck smi_check,
    549     PointersToHereCheck pointers_to_here_check_for_value) {
    550   ASSERT(!object.is(value));
    551   ASSERT(!object.is(address));
    552   ASSERT(!value.is(address));
    553   AssertNotSmi(object);
    554 
    555   if (remembered_set_action == OMIT_REMEMBERED_SET &&
    556       !FLAG_incremental_marking) {
    557     return;
    558   }
    559 
    560   if (emit_debug_code()) {
    561     Label ok;
    562     cmp(value, Operand(address, 0));
    563     j(equal, &ok, Label::kNear);
    564     int3();
    565     bind(&ok);
    566   }
    567 
    568   // Count number of write barriers in generated code.
    569   isolate()->counters()->write_barriers_static()->Increment();
    570   IncrementCounter(isolate()->counters()->write_barriers_dynamic(), 1);
    571 
    572   // First, check if a write barrier is even needed. The tests below
    573   // catch stores of Smis and stores into young gen.
    574   Label done;
    575 
    576   if (smi_check == INLINE_SMI_CHECK) {
    577     // Skip barrier if writing a smi.
    578     JumpIfSmi(value, &done, Label::kNear);
    579   }
    580 
    581   if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) {
    582     CheckPageFlag(value,
    583                   value,  // Used as scratch.
    584                   MemoryChunk::kPointersToHereAreInterestingMask,
    585                   zero,
    586                   &done,
    587                   Label::kNear);
    588   }
    589   CheckPageFlag(object,
    590                 value,  // Used as scratch.
    591                 MemoryChunk::kPointersFromHereAreInterestingMask,
    592                 zero,
    593                 &done,
    594                 Label::kNear);
    595 
    596   RecordWriteStub stub(isolate(), object, value, address, remembered_set_action,
    597                        fp_mode);
    598   CallStub(&stub);
    599 
    600   bind(&done);
    601 
    602   // Clobber clobbered registers when running with the debug-code flag
    603   // turned on to provoke errors.
    604   if (emit_debug_code()) {
    605     mov(address, Immediate(BitCast<int32_t>(kZapValue)));
    606     mov(value, Immediate(BitCast<int32_t>(kZapValue)));
    607   }
    608 }
    609 
    610 
    611 void MacroAssembler::DebugBreak() {
    612   Move(eax, Immediate(0));
    613   mov(ebx, Immediate(ExternalReference(Runtime::kDebugBreak, isolate())));
    614   CEntryStub ces(isolate(), 1);
    615   call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
    616 }
    617 
    618 
    619 void MacroAssembler::Cvtsi2sd(XMMRegister dst, const Operand& src) {
    620   xorps(dst, dst);
    621   cvtsi2sd(dst, src);
    622 }
    623 
    624 
    625 bool MacroAssembler::IsUnsafeImmediate(const Immediate& x) {
    626   static const int kMaxImmediateBits = 17;
    627   if (!RelocInfo::IsNone(x.rmode_)) return false;
    628   return !is_intn(x.x_, kMaxImmediateBits);
    629 }
    630 
    631 
    632 void MacroAssembler::SafeMove(Register dst, const Immediate& x) {
    633   if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
    634     Move(dst, Immediate(x.x_ ^ jit_cookie()));
    635     xor_(dst, jit_cookie());
    636   } else {
    637     Move(dst, x);
    638   }
    639 }
    640 
    641 
    642 void MacroAssembler::SafePush(const Immediate& x) {
    643   if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
    644     push(Immediate(x.x_ ^ jit_cookie()));
    645     xor_(Operand(esp, 0), Immediate(jit_cookie()));
    646   } else {
    647     push(x);
    648   }
    649 }
    650 
    651 
    652 void MacroAssembler::CmpObjectType(Register heap_object,
    653                                    InstanceType type,
    654                                    Register map) {
    655   mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
    656   CmpInstanceType(map, type);
    657 }
    658 
    659 
    660 void MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
    661   cmpb(FieldOperand(map, Map::kInstanceTypeOffset),
    662        static_cast<int8_t>(type));
    663 }
    664 
    665 
    666 void MacroAssembler::CheckFastElements(Register map,
    667                                        Label* fail,
    668                                        Label::Distance distance) {
    669   STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
    670   STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
    671   STATIC_ASSERT(FAST_ELEMENTS == 2);
    672   STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
    673   cmpb(FieldOperand(map, Map::kBitField2Offset),
    674        Map::kMaximumBitField2FastHoleyElementValue);
    675   j(above, fail, distance);
    676 }
    677 
    678 
    679 void MacroAssembler::CheckFastObjectElements(Register map,
    680                                              Label* fail,
    681                                              Label::Distance distance) {
    682   STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
    683   STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
    684   STATIC_ASSERT(FAST_ELEMENTS == 2);
    685   STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
    686   cmpb(FieldOperand(map, Map::kBitField2Offset),
    687        Map::kMaximumBitField2FastHoleySmiElementValue);
    688   j(below_equal, fail, distance);
    689   cmpb(FieldOperand(map, Map::kBitField2Offset),
    690        Map::kMaximumBitField2FastHoleyElementValue);
    691   j(above, fail, distance);
    692 }
    693 
    694 
    695 void MacroAssembler::CheckFastSmiElements(Register map,
    696                                           Label* fail,
    697                                           Label::Distance distance) {
    698   STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
    699   STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
    700   cmpb(FieldOperand(map, Map::kBitField2Offset),
    701        Map::kMaximumBitField2FastHoleySmiElementValue);
    702   j(above, fail, distance);
    703 }
    704 
    705 
    706 void MacroAssembler::StoreNumberToDoubleElements(
    707     Register maybe_number,
    708     Register elements,
    709     Register key,
    710     Register scratch1,
    711     XMMRegister scratch2,
    712     Label* fail,
    713     int elements_offset) {
    714   Label smi_value, done, maybe_nan, not_nan, is_nan, have_double_value;
    715   JumpIfSmi(maybe_number, &smi_value, Label::kNear);
    716 
    717   CheckMap(maybe_number,
    718            isolate()->factory()->heap_number_map(),
    719            fail,
    720            DONT_DO_SMI_CHECK);
    721 
    722   // Double value, canonicalize NaN.
    723   uint32_t offset = HeapNumber::kValueOffset + sizeof(kHoleNanLower32);
    724   cmp(FieldOperand(maybe_number, offset),
    725       Immediate(kNaNOrInfinityLowerBoundUpper32));
    726   j(greater_equal, &maybe_nan, Label::kNear);
    727 
    728   bind(&not_nan);
    729   ExternalReference canonical_nan_reference =
    730       ExternalReference::address_of_canonical_non_hole_nan();
    731   movsd(scratch2, FieldOperand(maybe_number, HeapNumber::kValueOffset));
    732   bind(&have_double_value);
    733   movsd(FieldOperand(elements, key, times_4,
    734                      FixedDoubleArray::kHeaderSize - elements_offset),
    735         scratch2);
    736   jmp(&done);
    737 
    738   bind(&maybe_nan);
    739   // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
    740   // it's an Infinity, and the non-NaN code path applies.
    741   j(greater, &is_nan, Label::kNear);
    742   cmp(FieldOperand(maybe_number, HeapNumber::kValueOffset), Immediate(0));
    743   j(zero, &not_nan);
    744   bind(&is_nan);
    745   movsd(scratch2, Operand::StaticVariable(canonical_nan_reference));
    746   jmp(&have_double_value, Label::kNear);
    747 
    748   bind(&smi_value);
    749   // Value is a smi. Convert to a double and store.
    750   // Preserve original value.
    751   mov(scratch1, maybe_number);
    752   SmiUntag(scratch1);
    753   Cvtsi2sd(scratch2, scratch1);
    754   movsd(FieldOperand(elements, key, times_4,
    755                      FixedDoubleArray::kHeaderSize - elements_offset),
    756         scratch2);
    757   bind(&done);
    758 }
    759 
    760 
    761 void MacroAssembler::CompareMap(Register obj, Handle<Map> map) {
    762   cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
    763 }
    764 
    765 
    766 void MacroAssembler::CheckMap(Register obj,
    767                               Handle<Map> map,
    768                               Label* fail,
    769                               SmiCheckType smi_check_type) {
    770   if (smi_check_type == DO_SMI_CHECK) {
    771     JumpIfSmi(obj, fail);
    772   }
    773 
    774   CompareMap(obj, map);
    775   j(not_equal, fail);
    776 }
    777 
    778 
    779 void MacroAssembler::DispatchMap(Register obj,
    780                                  Register unused,
    781                                  Handle<Map> map,
    782                                  Handle<Code> success,
    783                                  SmiCheckType smi_check_type) {
    784   Label fail;
    785   if (smi_check_type == DO_SMI_CHECK) {
    786     JumpIfSmi(obj, &fail);
    787   }
    788   cmp(FieldOperand(obj, HeapObject::kMapOffset), Immediate(map));
    789   j(equal, success);
    790 
    791   bind(&fail);
    792 }
    793 
    794 
    795 Condition MacroAssembler::IsObjectStringType(Register heap_object,
    796                                              Register map,
    797                                              Register instance_type) {
    798   mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
    799   movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
    800   STATIC_ASSERT(kNotStringTag != 0);
    801   test(instance_type, Immediate(kIsNotStringMask));
    802   return zero;
    803 }
    804 
    805 
    806 Condition MacroAssembler::IsObjectNameType(Register heap_object,
    807                                            Register map,
    808                                            Register instance_type) {
    809   mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
    810   movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
    811   cmpb(instance_type, static_cast<uint8_t>(LAST_NAME_TYPE));
    812   return below_equal;
    813 }
    814 
    815 
    816 void MacroAssembler::IsObjectJSObjectType(Register heap_object,
    817                                           Register map,
    818                                           Register scratch,
    819                                           Label* fail) {
    820   mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
    821   IsInstanceJSObjectType(map, scratch, fail);
    822 }
    823 
    824 
    825 void MacroAssembler::IsInstanceJSObjectType(Register map,
    826                                             Register scratch,
    827                                             Label* fail) {
    828   movzx_b(scratch, FieldOperand(map, Map::kInstanceTypeOffset));
    829   sub(scratch, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
    830   cmp(scratch,
    831       LAST_NONCALLABLE_SPEC_OBJECT_TYPE - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
    832   j(above, fail);
    833 }
    834 
    835 
    836 void MacroAssembler::FCmp() {
    837   fucomip();
    838   fstp(0);
    839 }
    840 
    841 
    842 void MacroAssembler::AssertNumber(Register object) {
    843   if (emit_debug_code()) {
    844     Label ok;
    845     JumpIfSmi(object, &ok);
    846     cmp(FieldOperand(object, HeapObject::kMapOffset),
    847         isolate()->factory()->heap_number_map());
    848     Check(equal, kOperandNotANumber);
    849     bind(&ok);
    850   }
    851 }
    852 
    853 
    854 void MacroAssembler::AssertSmi(Register object) {
    855   if (emit_debug_code()) {
    856     test(object, Immediate(kSmiTagMask));
    857     Check(equal, kOperandIsNotASmi);
    858   }
    859 }
    860 
    861 
    862 void MacroAssembler::AssertString(Register object) {
    863   if (emit_debug_code()) {
    864     test(object, Immediate(kSmiTagMask));
    865     Check(not_equal, kOperandIsASmiAndNotAString);
    866     push(object);
    867     mov(object, FieldOperand(object, HeapObject::kMapOffset));
    868     CmpInstanceType(object, FIRST_NONSTRING_TYPE);
    869     pop(object);
    870     Check(below, kOperandIsNotAString);
    871   }
    872 }
    873 
    874 
    875 void MacroAssembler::AssertName(Register object) {
    876   if (emit_debug_code()) {
    877     test(object, Immediate(kSmiTagMask));
    878     Check(not_equal, kOperandIsASmiAndNotAName);
    879     push(object);
    880     mov(object, FieldOperand(object, HeapObject::kMapOffset));
    881     CmpInstanceType(object, LAST_NAME_TYPE);
    882     pop(object);
    883     Check(below_equal, kOperandIsNotAName);
    884   }
    885 }
    886 
    887 
    888 void MacroAssembler::AssertUndefinedOrAllocationSite(Register object) {
    889   if (emit_debug_code()) {
    890     Label done_checking;
    891     AssertNotSmi(object);
    892     cmp(object, isolate()->factory()->undefined_value());
    893     j(equal, &done_checking);
    894     cmp(FieldOperand(object, 0),
    895         Immediate(isolate()->factory()->allocation_site_map()));
    896     Assert(equal, kExpectedUndefinedOrCell);
    897     bind(&done_checking);
    898   }
    899 }
    900 
    901 
    902 void MacroAssembler::AssertNotSmi(Register object) {
    903   if (emit_debug_code()) {
    904     test(object, Immediate(kSmiTagMask));
    905     Check(not_equal, kOperandIsASmi);
    906   }
    907 }
    908 
    909 
    910 void MacroAssembler::StubPrologue() {
    911   push(ebp);  // Caller's frame pointer.
    912   mov(ebp, esp);
    913   push(esi);  // Callee's context.
    914   push(Immediate(Smi::FromInt(StackFrame::STUB)));
    915 }
    916 
    917 
    918 void MacroAssembler::Prologue(bool code_pre_aging) {
    919   PredictableCodeSizeScope predictible_code_size_scope(this,
    920       kNoCodeAgeSequenceLength);
    921   if (code_pre_aging) {
    922       // Pre-age the code.
    923     call(isolate()->builtins()->MarkCodeAsExecutedOnce(),
    924         RelocInfo::CODE_AGE_SEQUENCE);
    925     Nop(kNoCodeAgeSequenceLength - Assembler::kCallInstructionLength);
    926   } else {
    927     push(ebp);  // Caller's frame pointer.
    928     mov(ebp, esp);
    929     push(esi);  // Callee's context.
    930     push(edi);  // Callee's JS function.
    931   }
    932 }
    933 
    934 
    935 void MacroAssembler::EnterFrame(StackFrame::Type type) {
    936   push(ebp);
    937   mov(ebp, esp);
    938   push(esi);
    939   push(Immediate(Smi::FromInt(type)));
    940   push(Immediate(CodeObject()));
    941   if (emit_debug_code()) {
    942     cmp(Operand(esp, 0), Immediate(isolate()->factory()->undefined_value()));
    943     Check(not_equal, kCodeObjectNotProperlyPatched);
    944   }
    945 }
    946 
    947 
    948 void MacroAssembler::LeaveFrame(StackFrame::Type type) {
    949   if (emit_debug_code()) {
    950     cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset),
    951         Immediate(Smi::FromInt(type)));
    952     Check(equal, kStackFrameTypesMustMatch);
    953   }
    954   leave();
    955 }
    956 
    957 
    958 void MacroAssembler::EnterExitFramePrologue() {
    959   // Set up the frame structure on the stack.
    960   ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize);
    961   ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize);
    962   ASSERT(ExitFrameConstants::kCallerFPOffset ==  0 * kPointerSize);
    963   push(ebp);
    964   mov(ebp, esp);
    965 
    966   // Reserve room for entry stack pointer and push the code object.
    967   ASSERT(ExitFrameConstants::kSPOffset  == -1 * kPointerSize);
    968   push(Immediate(0));  // Saved entry sp, patched before call.
    969   push(Immediate(CodeObject()));  // Accessed from ExitFrame::code_slot.
    970 
    971   // Save the frame pointer and the context in top.
    972   ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate());
    973   ExternalReference context_address(Isolate::kContextAddress, isolate());
    974   mov(Operand::StaticVariable(c_entry_fp_address), ebp);
    975   mov(Operand::StaticVariable(context_address), esi);
    976 }
    977 
    978 
    979 void MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) {
    980   // Optionally save all XMM registers.
    981   if (save_doubles) {
    982     int space = XMMRegister::kMaxNumRegisters * kDoubleSize +
    983                 argc * kPointerSize;
    984     sub(esp, Immediate(space));
    985     const int offset = -2 * kPointerSize;
    986     for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
    987       XMMRegister reg = XMMRegister::from_code(i);
    988       movsd(Operand(ebp, offset - ((i + 1) * kDoubleSize)), reg);
    989     }
    990   } else {
    991     sub(esp, Immediate(argc * kPointerSize));
    992   }
    993 
    994   // Get the required frame alignment for the OS.
    995   const int kFrameAlignment = OS::ActivationFrameAlignment();
    996   if (kFrameAlignment > 0) {
    997     ASSERT(IsPowerOf2(kFrameAlignment));
    998     and_(esp, -kFrameAlignment);
    999   }
   1000 
   1001   // Patch the saved entry sp.
   1002   mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp);
   1003 }
   1004 
   1005 
   1006 void MacroAssembler::EnterExitFrame(bool save_doubles) {
   1007   EnterExitFramePrologue();
   1008 
   1009   // Set up argc and argv in callee-saved registers.
   1010   int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
   1011   mov(edi, eax);
   1012   lea(esi, Operand(ebp, eax, times_4, offset));
   1013 
   1014   // Reserve space for argc, argv and isolate.
   1015   EnterExitFrameEpilogue(3, save_doubles);
   1016 }
   1017 
   1018 
   1019 void MacroAssembler::EnterApiExitFrame(int argc) {
   1020   EnterExitFramePrologue();
   1021   EnterExitFrameEpilogue(argc, false);
   1022 }
   1023 
   1024 
   1025 void MacroAssembler::LeaveExitFrame(bool save_doubles) {
   1026   // Optionally restore all XMM registers.
   1027   if (save_doubles) {
   1028     const int offset = -2 * kPointerSize;
   1029     for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
   1030       XMMRegister reg = XMMRegister::from_code(i);
   1031       movsd(reg, Operand(ebp, offset - ((i + 1) * kDoubleSize)));
   1032     }
   1033   }
   1034 
   1035   // Get the return address from the stack and restore the frame pointer.
   1036   mov(ecx, Operand(ebp, 1 * kPointerSize));
   1037   mov(ebp, Operand(ebp, 0 * kPointerSize));
   1038 
   1039   // Pop the arguments and the receiver from the caller stack.
   1040   lea(esp, Operand(esi, 1 * kPointerSize));
   1041 
   1042   // Push the return address to get ready to return.
   1043   push(ecx);
   1044 
   1045   LeaveExitFrameEpilogue(true);
   1046 }
   1047 
   1048 
   1049 void MacroAssembler::LeaveExitFrameEpilogue(bool restore_context) {
   1050   // Restore current context from top and clear it in debug mode.
   1051   ExternalReference context_address(Isolate::kContextAddress, isolate());
   1052   if (restore_context) {
   1053     mov(esi, Operand::StaticVariable(context_address));
   1054   }
   1055 #ifdef DEBUG
   1056   mov(Operand::StaticVariable(context_address), Immediate(0));
   1057 #endif
   1058 
   1059   // Clear the top frame.
   1060   ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress,
   1061                                        isolate());
   1062   mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0));
   1063 }
   1064 
   1065 
   1066 void MacroAssembler::LeaveApiExitFrame(bool restore_context) {
   1067   mov(esp, ebp);
   1068   pop(ebp);
   1069 
   1070   LeaveExitFrameEpilogue(restore_context);
   1071 }
   1072 
   1073 
   1074 void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
   1075                                     int handler_index) {
   1076   // Adjust this code if not the case.
   1077   STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
   1078   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
   1079   STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
   1080   STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
   1081   STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
   1082   STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
   1083 
   1084   // We will build up the handler from the bottom by pushing on the stack.
   1085   // First push the frame pointer and context.
   1086   if (kind == StackHandler::JS_ENTRY) {
   1087     // The frame pointer does not point to a JS frame so we save NULL for
   1088     // ebp. We expect the code throwing an exception to check ebp before
   1089     // dereferencing it to restore the context.
   1090     push(Immediate(0));  // NULL frame pointer.
   1091     push(Immediate(Smi::FromInt(0)));  // No context.
   1092   } else {
   1093     push(ebp);
   1094     push(esi);
   1095   }
   1096   // Push the state and the code object.
   1097   unsigned state =
   1098       StackHandler::IndexField::encode(handler_index) |
   1099       StackHandler::KindField::encode(kind);
   1100   push(Immediate(state));
   1101   Push(CodeObject());
   1102 
   1103   // Link the current handler as the next handler.
   1104   ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
   1105   push(Operand::StaticVariable(handler_address));
   1106   // Set this new handler as the current one.
   1107   mov(Operand::StaticVariable(handler_address), esp);
   1108 }
   1109 
   1110 
   1111 void MacroAssembler::PopTryHandler() {
   1112   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
   1113   ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
   1114   pop(Operand::StaticVariable(handler_address));
   1115   add(esp, Immediate(StackHandlerConstants::kSize - kPointerSize));
   1116 }
   1117 
   1118 
   1119 void MacroAssembler::JumpToHandlerEntry() {
   1120   // Compute the handler entry address and jump to it.  The handler table is
   1121   // a fixed array of (smi-tagged) code offsets.
   1122   // eax = exception, edi = code object, edx = state.
   1123   mov(ebx, FieldOperand(edi, Code::kHandlerTableOffset));
   1124   shr(edx, StackHandler::kKindWidth);
   1125   mov(edx, FieldOperand(ebx, edx, times_4, FixedArray::kHeaderSize));
   1126   SmiUntag(edx);
   1127   lea(edi, FieldOperand(edi, edx, times_1, Code::kHeaderSize));
   1128   jmp(edi);
   1129 }
   1130 
   1131 
   1132 void MacroAssembler::Throw(Register value) {
   1133   // Adjust this code if not the case.
   1134   STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
   1135   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
   1136   STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
   1137   STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
   1138   STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
   1139   STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
   1140 
   1141   // The exception is expected in eax.
   1142   if (!value.is(eax)) {
   1143     mov(eax, value);
   1144   }
   1145   // Drop the stack pointer to the top of the top handler.
   1146   ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
   1147   mov(esp, Operand::StaticVariable(handler_address));
   1148   // Restore the next handler.
   1149   pop(Operand::StaticVariable(handler_address));
   1150 
   1151   // Remove the code object and state, compute the handler address in edi.
   1152   pop(edi);  // Code object.
   1153   pop(edx);  // Index and state.
   1154 
   1155   // Restore the context and frame pointer.
   1156   pop(esi);  // Context.
   1157   pop(ebp);  // Frame pointer.
   1158 
   1159   // If the handler is a JS frame, restore the context to the frame.
   1160   // (kind == ENTRY) == (ebp == 0) == (esi == 0), so we could test either
   1161   // ebp or esi.
   1162   Label skip;
   1163   test(esi, esi);
   1164   j(zero, &skip, Label::kNear);
   1165   mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
   1166   bind(&skip);
   1167 
   1168   JumpToHandlerEntry();
   1169 }
   1170 
   1171 
   1172 void MacroAssembler::ThrowUncatchable(Register value) {
   1173   // Adjust this code if not the case.
   1174   STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
   1175   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
   1176   STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
   1177   STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
   1178   STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
   1179   STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
   1180 
   1181   // The exception is expected in eax.
   1182   if (!value.is(eax)) {
   1183     mov(eax, value);
   1184   }
   1185   // Drop the stack pointer to the top of the top stack handler.
   1186   ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
   1187   mov(esp, Operand::StaticVariable(handler_address));
   1188 
   1189   // Unwind the handlers until the top ENTRY handler is found.
   1190   Label fetch_next, check_kind;
   1191   jmp(&check_kind, Label::kNear);
   1192   bind(&fetch_next);
   1193   mov(esp, Operand(esp, StackHandlerConstants::kNextOffset));
   1194 
   1195   bind(&check_kind);
   1196   STATIC_ASSERT(StackHandler::JS_ENTRY == 0);
   1197   test(Operand(esp, StackHandlerConstants::kStateOffset),
   1198        Immediate(StackHandler::KindField::kMask));
   1199   j(not_zero, &fetch_next);
   1200 
   1201   // Set the top handler address to next handler past the top ENTRY handler.
   1202   pop(Operand::StaticVariable(handler_address));
   1203 
   1204   // Remove the code object and state, compute the handler address in edi.
   1205   pop(edi);  // Code object.
   1206   pop(edx);  // Index and state.
   1207 
   1208   // Clear the context pointer and frame pointer (0 was saved in the handler).
   1209   pop(esi);
   1210   pop(ebp);
   1211 
   1212   JumpToHandlerEntry();
   1213 }
   1214 
   1215 
   1216 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
   1217                                             Register scratch1,
   1218                                             Register scratch2,
   1219                                             Label* miss) {
   1220   Label same_contexts;
   1221 
   1222   ASSERT(!holder_reg.is(scratch1));
   1223   ASSERT(!holder_reg.is(scratch2));
   1224   ASSERT(!scratch1.is(scratch2));
   1225 
   1226   // Load current lexical context from the stack frame.
   1227   mov(scratch1, Operand(ebp, StandardFrameConstants::kContextOffset));
   1228 
   1229   // When generating debug code, make sure the lexical context is set.
   1230   if (emit_debug_code()) {
   1231     cmp(scratch1, Immediate(0));
   1232     Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext);
   1233   }
   1234   // Load the native context of the current context.
   1235   int offset =
   1236       Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
   1237   mov(scratch1, FieldOperand(scratch1, offset));
   1238   mov(scratch1, FieldOperand(scratch1, GlobalObject::kNativeContextOffset));
   1239 
   1240   // Check the context is a native context.
   1241   if (emit_debug_code()) {
   1242     // Read the first word and compare to native_context_map.
   1243     cmp(FieldOperand(scratch1, HeapObject::kMapOffset),
   1244         isolate()->factory()->native_context_map());
   1245     Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
   1246   }
   1247 
   1248   // Check if both contexts are the same.
   1249   cmp(scratch1, FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
   1250   j(equal, &same_contexts);
   1251 
   1252   // Compare security tokens, save holder_reg on the stack so we can use it
   1253   // as a temporary register.
   1254   //
   1255   // Check that the security token in the calling global object is
   1256   // compatible with the security token in the receiving global
   1257   // object.
   1258   mov(scratch2,
   1259       FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
   1260 
   1261   // Check the context is a native context.
   1262   if (emit_debug_code()) {
   1263     cmp(scratch2, isolate()->factory()->null_value());
   1264     Check(not_equal, kJSGlobalProxyContextShouldNotBeNull);
   1265 
   1266     // Read the first word and compare to native_context_map(),
   1267     cmp(FieldOperand(scratch2, HeapObject::kMapOffset),
   1268         isolate()->factory()->native_context_map());
   1269     Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
   1270   }
   1271 
   1272   int token_offset = Context::kHeaderSize +
   1273                      Context::SECURITY_TOKEN_INDEX * kPointerSize;
   1274   mov(scratch1, FieldOperand(scratch1, token_offset));
   1275   cmp(scratch1, FieldOperand(scratch2, token_offset));
   1276   j(not_equal, miss);
   1277 
   1278   bind(&same_contexts);
   1279 }
   1280 
   1281 
   1282 // Compute the hash code from the untagged key.  This must be kept in sync with
   1283 // ComputeIntegerHash in utils.h and KeyedLoadGenericElementStub in
   1284 // code-stub-hydrogen.cc
   1285 //
   1286 // Note: r0 will contain hash code
   1287 void MacroAssembler::GetNumberHash(Register r0, Register scratch) {
   1288   // Xor original key with a seed.
   1289   if (serializer_enabled()) {
   1290     ExternalReference roots_array_start =
   1291         ExternalReference::roots_array_start(isolate());
   1292     mov(scratch, Immediate(Heap::kHashSeedRootIndex));
   1293     mov(scratch,
   1294         Operand::StaticArray(scratch, times_pointer_size, roots_array_start));
   1295     SmiUntag(scratch);
   1296     xor_(r0, scratch);
   1297   } else {
   1298     int32_t seed = isolate()->heap()->HashSeed();
   1299     xor_(r0, Immediate(seed));
   1300   }
   1301 
   1302   // hash = ~hash + (hash << 15);
   1303   mov(scratch, r0);
   1304   not_(r0);
   1305   shl(scratch, 15);
   1306   add(r0, scratch);
   1307   // hash = hash ^ (hash >> 12);
   1308   mov(scratch, r0);
   1309   shr(scratch, 12);
   1310   xor_(r0, scratch);
   1311   // hash = hash + (hash << 2);
   1312   lea(r0, Operand(r0, r0, times_4, 0));
   1313   // hash = hash ^ (hash >> 4);
   1314   mov(scratch, r0);
   1315   shr(scratch, 4);
   1316   xor_(r0, scratch);
   1317   // hash = hash * 2057;
   1318   imul(r0, r0, 2057);
   1319   // hash = hash ^ (hash >> 16);
   1320   mov(scratch, r0);
   1321   shr(scratch, 16);
   1322   xor_(r0, scratch);
   1323 }
   1324 
   1325 
   1326 
   1327 void MacroAssembler::LoadFromNumberDictionary(Label* miss,
   1328                                               Register elements,
   1329                                               Register key,
   1330                                               Register r0,
   1331                                               Register r1,
   1332                                               Register r2,
   1333                                               Register result) {
   1334   // Register use:
   1335   //
   1336   // elements - holds the slow-case elements of the receiver and is unchanged.
   1337   //
   1338   // key      - holds the smi key on entry and is unchanged.
   1339   //
   1340   // Scratch registers:
   1341   //
   1342   // r0 - holds the untagged key on entry and holds the hash once computed.
   1343   //
   1344   // r1 - used to hold the capacity mask of the dictionary
   1345   //
   1346   // r2 - used for the index into the dictionary.
   1347   //
   1348   // result - holds the result on exit if the load succeeds and we fall through.
   1349 
   1350   Label done;
   1351 
   1352   GetNumberHash(r0, r1);
   1353 
   1354   // Compute capacity mask.
   1355   mov(r1, FieldOperand(elements, SeededNumberDictionary::kCapacityOffset));
   1356   shr(r1, kSmiTagSize);  // convert smi to int
   1357   dec(r1);
   1358 
   1359   // Generate an unrolled loop that performs a few probes before giving up.
   1360   for (int i = 0; i < kNumberDictionaryProbes; i++) {
   1361     // Use r2 for index calculations and keep the hash intact in r0.
   1362     mov(r2, r0);
   1363     // Compute the masked index: (hash + i + i * i) & mask.
   1364     if (i > 0) {
   1365       add(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i)));
   1366     }
   1367     and_(r2, r1);
   1368 
   1369     // Scale the index by multiplying by the entry size.
   1370     ASSERT(SeededNumberDictionary::kEntrySize == 3);
   1371     lea(r2, Operand(r2, r2, times_2, 0));  // r2 = r2 * 3
   1372 
   1373     // Check if the key matches.
   1374     cmp(key, FieldOperand(elements,
   1375                           r2,
   1376                           times_pointer_size,
   1377                           SeededNumberDictionary::kElementsStartOffset));
   1378     if (i != (kNumberDictionaryProbes - 1)) {
   1379       j(equal, &done);
   1380     } else {
   1381       j(not_equal, miss);
   1382     }
   1383   }
   1384 
   1385   bind(&done);
   1386   // Check that the value is a normal propety.
   1387   const int kDetailsOffset =
   1388       SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
   1389   ASSERT_EQ(NORMAL, 0);
   1390   test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
   1391        Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize));
   1392   j(not_zero, miss);
   1393 
   1394   // Get the value at the masked, scaled index.
   1395   const int kValueOffset =
   1396       SeededNumberDictionary::kElementsStartOffset + kPointerSize;
   1397   mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
   1398 }
   1399 
   1400 
   1401 void MacroAssembler::LoadAllocationTopHelper(Register result,
   1402                                              Register scratch,
   1403                                              AllocationFlags flags) {
   1404   ExternalReference allocation_top =
   1405       AllocationUtils::GetAllocationTopReference(isolate(), flags);
   1406 
   1407   // Just return if allocation top is already known.
   1408   if ((flags & RESULT_CONTAINS_TOP) != 0) {
   1409     // No use of scratch if allocation top is provided.
   1410     ASSERT(scratch.is(no_reg));
   1411 #ifdef DEBUG
   1412     // Assert that result actually contains top on entry.
   1413     cmp(result, Operand::StaticVariable(allocation_top));
   1414     Check(equal, kUnexpectedAllocationTop);
   1415 #endif
   1416     return;
   1417   }
   1418 
   1419   // Move address of new object to result. Use scratch register if available.
   1420   if (scratch.is(no_reg)) {
   1421     mov(result, Operand::StaticVariable(allocation_top));
   1422   } else {
   1423     mov(scratch, Immediate(allocation_top));
   1424     mov(result, Operand(scratch, 0));
   1425   }
   1426 }
   1427 
   1428 
   1429 void MacroAssembler::UpdateAllocationTopHelper(Register result_end,
   1430                                                Register scratch,
   1431                                                AllocationFlags flags) {
   1432   if (emit_debug_code()) {
   1433     test(result_end, Immediate(kObjectAlignmentMask));
   1434     Check(zero, kUnalignedAllocationInNewSpace);
   1435   }
   1436 
   1437   ExternalReference allocation_top =
   1438       AllocationUtils::GetAllocationTopReference(isolate(), flags);
   1439 
   1440   // Update new top. Use scratch if available.
   1441   if (scratch.is(no_reg)) {
   1442     mov(Operand::StaticVariable(allocation_top), result_end);
   1443   } else {
   1444     mov(Operand(scratch, 0), result_end);
   1445   }
   1446 }
   1447 
   1448 
   1449 void MacroAssembler::Allocate(int object_size,
   1450                               Register result,
   1451                               Register result_end,
   1452                               Register scratch,
   1453                               Label* gc_required,
   1454                               AllocationFlags flags) {
   1455   ASSERT((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
   1456   ASSERT(object_size <= Page::kMaxRegularHeapObjectSize);
   1457   if (!FLAG_inline_new) {
   1458     if (emit_debug_code()) {
   1459       // Trash the registers to simulate an allocation failure.
   1460       mov(result, Immediate(0x7091));
   1461       if (result_end.is_valid()) {
   1462         mov(result_end, Immediate(0x7191));
   1463       }
   1464       if (scratch.is_valid()) {
   1465         mov(scratch, Immediate(0x7291));
   1466       }
   1467     }
   1468     jmp(gc_required);
   1469     return;
   1470   }
   1471   ASSERT(!result.is(result_end));
   1472 
   1473   // Load address of new object into result.
   1474   LoadAllocationTopHelper(result, scratch, flags);
   1475 
   1476   ExternalReference allocation_limit =
   1477       AllocationUtils::GetAllocationLimitReference(isolate(), flags);
   1478 
   1479   // Align the next allocation. Storing the filler map without checking top is
   1480   // safe in new-space because the limit of the heap is aligned there.
   1481   if ((flags & DOUBLE_ALIGNMENT) != 0) {
   1482     ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
   1483     ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
   1484     Label aligned;
   1485     test(result, Immediate(kDoubleAlignmentMask));
   1486     j(zero, &aligned, Label::kNear);
   1487     if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) {
   1488       cmp(result, Operand::StaticVariable(allocation_limit));
   1489       j(above_equal, gc_required);
   1490     }
   1491     mov(Operand(result, 0),
   1492         Immediate(isolate()->factory()->one_pointer_filler_map()));
   1493     add(result, Immediate(kDoubleSize / 2));
   1494     bind(&aligned);
   1495   }
   1496 
   1497   // Calculate new top and bail out if space is exhausted.
   1498   Register top_reg = result_end.is_valid() ? result_end : result;
   1499   if (!top_reg.is(result)) {
   1500     mov(top_reg, result);
   1501   }
   1502   add(top_reg, Immediate(object_size));
   1503   j(carry, gc_required);
   1504   cmp(top_reg, Operand::StaticVariable(allocation_limit));
   1505   j(above, gc_required);
   1506 
   1507   // Update allocation top.
   1508   UpdateAllocationTopHelper(top_reg, scratch, flags);
   1509 
   1510   // Tag result if requested.
   1511   bool tag_result = (flags & TAG_OBJECT) != 0;
   1512   if (top_reg.is(result)) {
   1513     if (tag_result) {
   1514       sub(result, Immediate(object_size - kHeapObjectTag));
   1515     } else {
   1516       sub(result, Immediate(object_size));
   1517     }
   1518   } else if (tag_result) {
   1519     ASSERT(kHeapObjectTag == 1);
   1520     inc(result);
   1521   }
   1522 }
   1523 
   1524 
   1525 void MacroAssembler::Allocate(int header_size,
   1526                               ScaleFactor element_size,
   1527                               Register element_count,
   1528                               RegisterValueType element_count_type,
   1529                               Register result,
   1530                               Register result_end,
   1531                               Register scratch,
   1532                               Label* gc_required,
   1533                               AllocationFlags flags) {
   1534   ASSERT((flags & SIZE_IN_WORDS) == 0);
   1535   if (!FLAG_inline_new) {
   1536     if (emit_debug_code()) {
   1537       // Trash the registers to simulate an allocation failure.
   1538       mov(result, Immediate(0x7091));
   1539       mov(result_end, Immediate(0x7191));
   1540       if (scratch.is_valid()) {
   1541         mov(scratch, Immediate(0x7291));
   1542       }
   1543       // Register element_count is not modified by the function.
   1544     }
   1545     jmp(gc_required);
   1546     return;
   1547   }
   1548   ASSERT(!result.is(result_end));
   1549 
   1550   // Load address of new object into result.
   1551   LoadAllocationTopHelper(result, scratch, flags);
   1552 
   1553   ExternalReference allocation_limit =
   1554       AllocationUtils::GetAllocationLimitReference(isolate(), flags);
   1555 
   1556   // Align the next allocation. Storing the filler map without checking top is
   1557   // safe in new-space because the limit of the heap is aligned there.
   1558   if ((flags & DOUBLE_ALIGNMENT) != 0) {
   1559     ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
   1560     ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
   1561     Label aligned;
   1562     test(result, Immediate(kDoubleAlignmentMask));
   1563     j(zero, &aligned, Label::kNear);
   1564     if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) {
   1565       cmp(result, Operand::StaticVariable(allocation_limit));
   1566       j(above_equal, gc_required);
   1567     }
   1568     mov(Operand(result, 0),
   1569         Immediate(isolate()->factory()->one_pointer_filler_map()));
   1570     add(result, Immediate(kDoubleSize / 2));
   1571     bind(&aligned);
   1572   }
   1573 
   1574   // Calculate new top and bail out if space is exhausted.
   1575   // We assume that element_count*element_size + header_size does not
   1576   // overflow.
   1577   if (element_count_type == REGISTER_VALUE_IS_SMI) {
   1578     STATIC_ASSERT(static_cast<ScaleFactor>(times_2 - 1) == times_1);
   1579     STATIC_ASSERT(static_cast<ScaleFactor>(times_4 - 1) == times_2);
   1580     STATIC_ASSERT(static_cast<ScaleFactor>(times_8 - 1) == times_4);
   1581     ASSERT(element_size >= times_2);
   1582     ASSERT(kSmiTagSize == 1);
   1583     element_size = static_cast<ScaleFactor>(element_size - 1);
   1584   } else {
   1585     ASSERT(element_count_type == REGISTER_VALUE_IS_INT32);
   1586   }
   1587   lea(result_end, Operand(element_count, element_size, header_size));
   1588   add(result_end, result);
   1589   j(carry, gc_required);
   1590   cmp(result_end, Operand::StaticVariable(allocation_limit));
   1591   j(above, gc_required);
   1592 
   1593   if ((flags & TAG_OBJECT) != 0) {
   1594     ASSERT(kHeapObjectTag == 1);
   1595     inc(result);
   1596   }
   1597 
   1598   // Update allocation top.
   1599   UpdateAllocationTopHelper(result_end, scratch, flags);
   1600 }
   1601 
   1602 
   1603 void MacroAssembler::Allocate(Register object_size,
   1604                               Register result,
   1605                               Register result_end,
   1606                               Register scratch,
   1607                               Label* gc_required,
   1608                               AllocationFlags flags) {
   1609   ASSERT((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
   1610   if (!FLAG_inline_new) {
   1611     if (emit_debug_code()) {
   1612       // Trash the registers to simulate an allocation failure.
   1613       mov(result, Immediate(0x7091));
   1614       mov(result_end, Immediate(0x7191));
   1615       if (scratch.is_valid()) {
   1616         mov(scratch, Immediate(0x7291));
   1617       }
   1618       // object_size is left unchanged by this function.
   1619     }
   1620     jmp(gc_required);
   1621     return;
   1622   }
   1623   ASSERT(!result.is(result_end));
   1624 
   1625   // Load address of new object into result.
   1626   LoadAllocationTopHelper(result, scratch, flags);
   1627 
   1628   ExternalReference allocation_limit =
   1629       AllocationUtils::GetAllocationLimitReference(isolate(), flags);
   1630 
   1631   // Align the next allocation. Storing the filler map without checking top is
   1632   // safe in new-space because the limit of the heap is aligned there.
   1633   if ((flags & DOUBLE_ALIGNMENT) != 0) {
   1634     ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
   1635     ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
   1636     Label aligned;
   1637     test(result, Immediate(kDoubleAlignmentMask));
   1638     j(zero, &aligned, Label::kNear);
   1639     if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) {
   1640       cmp(result, Operand::StaticVariable(allocation_limit));
   1641       j(above_equal, gc_required);
   1642     }
   1643     mov(Operand(result, 0),
   1644         Immediate(isolate()->factory()->one_pointer_filler_map()));
   1645     add(result, Immediate(kDoubleSize / 2));
   1646     bind(&aligned);
   1647   }
   1648 
   1649   // Calculate new top and bail out if space is exhausted.
   1650   if (!object_size.is(result_end)) {
   1651     mov(result_end, object_size);
   1652   }
   1653   add(result_end, result);
   1654   j(carry, gc_required);
   1655   cmp(result_end, Operand::StaticVariable(allocation_limit));
   1656   j(above, gc_required);
   1657 
   1658   // Tag result if requested.
   1659   if ((flags & TAG_OBJECT) != 0) {
   1660     ASSERT(kHeapObjectTag == 1);
   1661     inc(result);
   1662   }
   1663 
   1664   // Update allocation top.
   1665   UpdateAllocationTopHelper(result_end, scratch, flags);
   1666 }
   1667 
   1668 
   1669 void MacroAssembler::UndoAllocationInNewSpace(Register object) {
   1670   ExternalReference new_space_allocation_top =
   1671       ExternalReference::new_space_allocation_top_address(isolate());
   1672 
   1673   // Make sure the object has no tag before resetting top.
   1674   and_(object, Immediate(~kHeapObjectTagMask));
   1675 #ifdef DEBUG
   1676   cmp(object, Operand::StaticVariable(new_space_allocation_top));
   1677   Check(below, kUndoAllocationOfNonAllocatedMemory);
   1678 #endif
   1679   mov(Operand::StaticVariable(new_space_allocation_top), object);
   1680 }
   1681 
   1682 
   1683 void MacroAssembler::AllocateHeapNumber(Register result,
   1684                                         Register scratch1,
   1685                                         Register scratch2,
   1686                                         Label* gc_required) {
   1687   // Allocate heap number in new space.
   1688   Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
   1689            TAG_OBJECT);
   1690 
   1691   // Set the map.
   1692   mov(FieldOperand(result, HeapObject::kMapOffset),
   1693       Immediate(isolate()->factory()->heap_number_map()));
   1694 }
   1695 
   1696 
   1697 void MacroAssembler::AllocateTwoByteString(Register result,
   1698                                            Register length,
   1699                                            Register scratch1,
   1700                                            Register scratch2,
   1701                                            Register scratch3,
   1702                                            Label* gc_required) {
   1703   // Calculate the number of bytes needed for the characters in the string while
   1704   // observing object alignment.
   1705   ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
   1706   ASSERT(kShortSize == 2);
   1707   // scratch1 = length * 2 + kObjectAlignmentMask.
   1708   lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask));
   1709   and_(scratch1, Immediate(~kObjectAlignmentMask));
   1710 
   1711   // Allocate two byte string in new space.
   1712   Allocate(SeqTwoByteString::kHeaderSize,
   1713            times_1,
   1714            scratch1,
   1715            REGISTER_VALUE_IS_INT32,
   1716            result,
   1717            scratch2,
   1718            scratch3,
   1719            gc_required,
   1720            TAG_OBJECT);
   1721 
   1722   // Set the map, length and hash field.
   1723   mov(FieldOperand(result, HeapObject::kMapOffset),
   1724       Immediate(isolate()->factory()->string_map()));
   1725   mov(scratch1, length);
   1726   SmiTag(scratch1);
   1727   mov(FieldOperand(result, String::kLengthOffset), scratch1);
   1728   mov(FieldOperand(result, String::kHashFieldOffset),
   1729       Immediate(String::kEmptyHashField));
   1730 }
   1731 
   1732 
   1733 void MacroAssembler::AllocateAsciiString(Register result,
   1734                                          Register length,
   1735                                          Register scratch1,
   1736                                          Register scratch2,
   1737                                          Register scratch3,
   1738                                          Label* gc_required) {
   1739   // Calculate the number of bytes needed for the characters in the string while
   1740   // observing object alignment.
   1741   ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
   1742   mov(scratch1, length);
   1743   ASSERT(kCharSize == 1);
   1744   add(scratch1, Immediate(kObjectAlignmentMask));
   1745   and_(scratch1, Immediate(~kObjectAlignmentMask));
   1746 
   1747   // Allocate ASCII string in new space.
   1748   Allocate(SeqOneByteString::kHeaderSize,
   1749            times_1,
   1750            scratch1,
   1751            REGISTER_VALUE_IS_INT32,
   1752            result,
   1753            scratch2,
   1754            scratch3,
   1755            gc_required,
   1756            TAG_OBJECT);
   1757 
   1758   // Set the map, length and hash field.
   1759   mov(FieldOperand(result, HeapObject::kMapOffset),
   1760       Immediate(isolate()->factory()->ascii_string_map()));
   1761   mov(scratch1, length);
   1762   SmiTag(scratch1);
   1763   mov(FieldOperand(result, String::kLengthOffset), scratch1);
   1764   mov(FieldOperand(result, String::kHashFieldOffset),
   1765       Immediate(String::kEmptyHashField));
   1766 }
   1767 
   1768 
   1769 void MacroAssembler::AllocateAsciiString(Register result,
   1770                                          int length,
   1771                                          Register scratch1,
   1772                                          Register scratch2,
   1773                                          Label* gc_required) {
   1774   ASSERT(length > 0);
   1775 
   1776   // Allocate ASCII string in new space.
   1777   Allocate(SeqOneByteString::SizeFor(length), result, scratch1, scratch2,
   1778            gc_required, TAG_OBJECT);
   1779 
   1780   // Set the map, length and hash field.
   1781   mov(FieldOperand(result, HeapObject::kMapOffset),
   1782       Immediate(isolate()->factory()->ascii_string_map()));
   1783   mov(FieldOperand(result, String::kLengthOffset),
   1784       Immediate(Smi::FromInt(length)));
   1785   mov(FieldOperand(result, String::kHashFieldOffset),
   1786       Immediate(String::kEmptyHashField));
   1787 }
   1788 
   1789 
   1790 void MacroAssembler::AllocateTwoByteConsString(Register result,
   1791                                         Register scratch1,
   1792                                         Register scratch2,
   1793                                         Label* gc_required) {
   1794   // Allocate heap number in new space.
   1795   Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
   1796            TAG_OBJECT);
   1797 
   1798   // Set the map. The other fields are left uninitialized.
   1799   mov(FieldOperand(result, HeapObject::kMapOffset),
   1800       Immediate(isolate()->factory()->cons_string_map()));
   1801 }
   1802 
   1803 
   1804 void MacroAssembler::AllocateAsciiConsString(Register result,
   1805                                              Register scratch1,
   1806                                              Register scratch2,
   1807                                              Label* gc_required) {
   1808   Allocate(ConsString::kSize,
   1809            result,
   1810            scratch1,
   1811            scratch2,
   1812            gc_required,
   1813            TAG_OBJECT);
   1814 
   1815   // Set the map. The other fields are left uninitialized.
   1816   mov(FieldOperand(result, HeapObject::kMapOffset),
   1817       Immediate(isolate()->factory()->cons_ascii_string_map()));
   1818 }
   1819 
   1820 
   1821 void MacroAssembler::AllocateTwoByteSlicedString(Register result,
   1822                                           Register scratch1,
   1823                                           Register scratch2,
   1824                                           Label* gc_required) {
   1825   // Allocate heap number in new space.
   1826   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
   1827            TAG_OBJECT);
   1828 
   1829   // Set the map. The other fields are left uninitialized.
   1830   mov(FieldOperand(result, HeapObject::kMapOffset),
   1831       Immediate(isolate()->factory()->sliced_string_map()));
   1832 }
   1833 
   1834 
   1835 void MacroAssembler::AllocateAsciiSlicedString(Register result,
   1836                                                Register scratch1,
   1837                                                Register scratch2,
   1838                                                Label* gc_required) {
   1839   // Allocate heap number in new space.
   1840   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
   1841            TAG_OBJECT);
   1842 
   1843   // Set the map. The other fields are left uninitialized.
   1844   mov(FieldOperand(result, HeapObject::kMapOffset),
   1845       Immediate(isolate()->factory()->sliced_ascii_string_map()));
   1846 }
   1847 
   1848 
   1849 // Copy memory, byte-by-byte, from source to destination.  Not optimized for
   1850 // long or aligned copies.  The contents of scratch and length are destroyed.
   1851 // Source and destination are incremented by length.
   1852 // Many variants of movsb, loop unrolling, word moves, and indexed operands
   1853 // have been tried here already, and this is fastest.
   1854 // A simpler loop is faster on small copies, but 30% slower on large ones.
   1855 // The cld() instruction must have been emitted, to set the direction flag(),
   1856 // before calling this function.
   1857 void MacroAssembler::CopyBytes(Register source,
   1858                                Register destination,
   1859                                Register length,
   1860                                Register scratch) {
   1861   Label short_loop, len4, len8, len12, done, short_string;
   1862   ASSERT(source.is(esi));
   1863   ASSERT(destination.is(edi));
   1864   ASSERT(length.is(ecx));
   1865   cmp(length, Immediate(4));
   1866   j(below, &short_string, Label::kNear);
   1867 
   1868   // Because source is 4-byte aligned in our uses of this function,
   1869   // we keep source aligned for the rep_movs call by copying the odd bytes
   1870   // at the end of the ranges.
   1871   mov(scratch, Operand(source, length, times_1, -4));
   1872   mov(Operand(destination, length, times_1, -4), scratch);
   1873 
   1874   cmp(length, Immediate(8));
   1875   j(below_equal, &len4, Label::kNear);
   1876   cmp(length, Immediate(12));
   1877   j(below_equal, &len8, Label::kNear);
   1878   cmp(length, Immediate(16));
   1879   j(below_equal, &len12, Label::kNear);
   1880 
   1881   mov(scratch, ecx);
   1882   shr(ecx, 2);
   1883   rep_movs();
   1884   and_(scratch, Immediate(0x3));
   1885   add(destination, scratch);
   1886   jmp(&done, Label::kNear);
   1887 
   1888   bind(&len12);
   1889   mov(scratch, Operand(source, 8));
   1890   mov(Operand(destination, 8), scratch);
   1891   bind(&len8);
   1892   mov(scratch, Operand(source, 4));
   1893   mov(Operand(destination, 4), scratch);
   1894   bind(&len4);
   1895   mov(scratch, Operand(source, 0));
   1896   mov(Operand(destination, 0), scratch);
   1897   add(destination, length);
   1898   jmp(&done, Label::kNear);
   1899 
   1900   bind(&short_string);
   1901   test(length, length);
   1902   j(zero, &done, Label::kNear);
   1903 
   1904   bind(&short_loop);
   1905   mov_b(scratch, Operand(source, 0));
   1906   mov_b(Operand(destination, 0), scratch);
   1907   inc(source);
   1908   inc(destination);
   1909   dec(length);
   1910   j(not_zero, &short_loop);
   1911 
   1912   bind(&done);
   1913 }
   1914 
   1915 
   1916 void MacroAssembler::InitializeFieldsWithFiller(Register start_offset,
   1917                                                 Register end_offset,
   1918                                                 Register filler) {
   1919   Label loop, entry;
   1920   jmp(&entry);
   1921   bind(&loop);
   1922   mov(Operand(start_offset, 0), filler);
   1923   add(start_offset, Immediate(kPointerSize));
   1924   bind(&entry);
   1925   cmp(start_offset, end_offset);
   1926   j(less, &loop);
   1927 }
   1928 
   1929 
   1930 void MacroAssembler::BooleanBitTest(Register object,
   1931                                     int field_offset,
   1932                                     int bit_index) {
   1933   bit_index += kSmiTagSize + kSmiShiftSize;
   1934   ASSERT(IsPowerOf2(kBitsPerByte));
   1935   int byte_index = bit_index / kBitsPerByte;
   1936   int byte_bit_index = bit_index & (kBitsPerByte - 1);
   1937   test_b(FieldOperand(object, field_offset + byte_index),
   1938          static_cast<byte>(1 << byte_bit_index));
   1939 }
   1940 
   1941 
   1942 
   1943 void MacroAssembler::NegativeZeroTest(Register result,
   1944                                       Register op,
   1945                                       Label* then_label) {
   1946   Label ok;
   1947   test(result, result);
   1948   j(not_zero, &ok);
   1949   test(op, op);
   1950   j(sign, then_label);
   1951   bind(&ok);
   1952 }
   1953 
   1954 
   1955 void MacroAssembler::NegativeZeroTest(Register result,
   1956                                       Register op1,
   1957                                       Register op2,
   1958                                       Register scratch,
   1959                                       Label* then_label) {
   1960   Label ok;
   1961   test(result, result);
   1962   j(not_zero, &ok);
   1963   mov(scratch, op1);
   1964   or_(scratch, op2);
   1965   j(sign, then_label);
   1966   bind(&ok);
   1967 }
   1968 
   1969 
   1970 void MacroAssembler::TryGetFunctionPrototype(Register function,
   1971                                              Register result,
   1972                                              Register scratch,
   1973                                              Label* miss,
   1974                                              bool miss_on_bound_function) {
   1975   // Check that the receiver isn't a smi.
   1976   JumpIfSmi(function, miss);
   1977 
   1978   // Check that the function really is a function.
   1979   CmpObjectType(function, JS_FUNCTION_TYPE, result);
   1980   j(not_equal, miss);
   1981 
   1982   if (miss_on_bound_function) {
   1983     // If a bound function, go to miss label.
   1984     mov(scratch,
   1985         FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
   1986     BooleanBitTest(scratch, SharedFunctionInfo::kCompilerHintsOffset,
   1987                    SharedFunctionInfo::kBoundFunction);
   1988     j(not_zero, miss);
   1989   }
   1990 
   1991   // Make sure that the function has an instance prototype.
   1992   Label non_instance;
   1993   movzx_b(scratch, FieldOperand(result, Map::kBitFieldOffset));
   1994   test(scratch, Immediate(1 << Map::kHasNonInstancePrototype));
   1995   j(not_zero, &non_instance);
   1996 
   1997   // Get the prototype or initial map from the function.
   1998   mov(result,
   1999       FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
   2000 
   2001   // If the prototype or initial map is the hole, don't return it and
   2002   // simply miss the cache instead. This will allow us to allocate a
   2003   // prototype object on-demand in the runtime system.
   2004   cmp(result, Immediate(isolate()->factory()->the_hole_value()));
   2005   j(equal, miss);
   2006 
   2007   // If the function does not have an initial map, we're done.
   2008   Label done;
   2009   CmpObjectType(result, MAP_TYPE, scratch);
   2010   j(not_equal, &done);
   2011 
   2012   // Get the prototype from the initial map.
   2013   mov(result, FieldOperand(result, Map::kPrototypeOffset));
   2014   jmp(&done);
   2015 
   2016   // Non-instance prototype: Fetch prototype from constructor field
   2017   // in initial map.
   2018   bind(&non_instance);
   2019   mov(result, FieldOperand(result, Map::kConstructorOffset));
   2020 
   2021   // All done.
   2022   bind(&done);
   2023 }
   2024 
   2025 
   2026 void MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) {
   2027   ASSERT(AllowThisStubCall(stub));  // Calls are not allowed in some stubs.
   2028   call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id);
   2029 }
   2030 
   2031 
   2032 void MacroAssembler::TailCallStub(CodeStub* stub) {
   2033   jmp(stub->GetCode(), RelocInfo::CODE_TARGET);
   2034 }
   2035 
   2036 
   2037 void MacroAssembler::StubReturn(int argc) {
   2038   ASSERT(argc >= 1 && generating_stub());
   2039   ret((argc - 1) * kPointerSize);
   2040 }
   2041 
   2042 
   2043 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
   2044   return has_frame_ || !stub->SometimesSetsUpAFrame();
   2045 }
   2046 
   2047 
   2048 void MacroAssembler::IndexFromHash(Register hash, Register index) {
   2049   // The assert checks that the constants for the maximum number of digits
   2050   // for an array index cached in the hash field and the number of bits
   2051   // reserved for it does not conflict.
   2052   ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
   2053          (1 << String::kArrayIndexValueBits));
   2054   if (!index.is(hash)) {
   2055     mov(index, hash);
   2056   }
   2057   DecodeFieldToSmi<String::ArrayIndexValueBits>(index);
   2058 }
   2059 
   2060 
   2061 void MacroAssembler::CallRuntime(const Runtime::Function* f,
   2062                                  int num_arguments,
   2063                                  SaveFPRegsMode save_doubles) {
   2064   // If the expected number of arguments of the runtime function is
   2065   // constant, we check that the actual number of arguments match the
   2066   // expectation.
   2067   CHECK(f->nargs < 0 || f->nargs == num_arguments);
   2068 
   2069   // TODO(1236192): Most runtime routines don't need the number of
   2070   // arguments passed in because it is constant. At some point we
   2071   // should remove this need and make the runtime routine entry code
   2072   // smarter.
   2073   Move(eax, Immediate(num_arguments));
   2074   mov(ebx, Immediate(ExternalReference(f, isolate())));
   2075   CEntryStub ces(isolate(), 1, save_doubles);
   2076   CallStub(&ces);
   2077 }
   2078 
   2079 
   2080 void MacroAssembler::CallExternalReference(ExternalReference ref,
   2081                                            int num_arguments) {
   2082   mov(eax, Immediate(num_arguments));
   2083   mov(ebx, Immediate(ref));
   2084 
   2085   CEntryStub stub(isolate(), 1);
   2086   CallStub(&stub);
   2087 }
   2088 
   2089 
   2090 void MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
   2091                                                int num_arguments,
   2092                                                int result_size) {
   2093   // TODO(1236192): Most runtime routines don't need the number of
   2094   // arguments passed in because it is constant. At some point we
   2095   // should remove this need and make the runtime routine entry code
   2096   // smarter.
   2097   Move(eax, Immediate(num_arguments));
   2098   JumpToExternalReference(ext);
   2099 }
   2100 
   2101 
   2102 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
   2103                                      int num_arguments,
   2104                                      int result_size) {
   2105   TailCallExternalReference(ExternalReference(fid, isolate()),
   2106                             num_arguments,
   2107                             result_size);
   2108 }
   2109 
   2110 
   2111 Operand ApiParameterOperand(int index) {
   2112   return Operand(esp, index * kPointerSize);
   2113 }
   2114 
   2115 
   2116 void MacroAssembler::PrepareCallApiFunction(int argc) {
   2117   EnterApiExitFrame(argc);
   2118   if (emit_debug_code()) {
   2119     mov(esi, Immediate(BitCast<int32_t>(kZapValue)));
   2120   }
   2121 }
   2122 
   2123 
   2124 void MacroAssembler::CallApiFunctionAndReturn(
   2125     Register function_address,
   2126     ExternalReference thunk_ref,
   2127     Operand thunk_last_arg,
   2128     int stack_space,
   2129     Operand return_value_operand,
   2130     Operand* context_restore_operand) {
   2131   ExternalReference next_address =
   2132       ExternalReference::handle_scope_next_address(isolate());
   2133   ExternalReference limit_address =
   2134       ExternalReference::handle_scope_limit_address(isolate());
   2135   ExternalReference level_address =
   2136       ExternalReference::handle_scope_level_address(isolate());
   2137 
   2138   ASSERT(edx.is(function_address));
   2139   // Allocate HandleScope in callee-save registers.
   2140   mov(ebx, Operand::StaticVariable(next_address));
   2141   mov(edi, Operand::StaticVariable(limit_address));
   2142   add(Operand::StaticVariable(level_address), Immediate(1));
   2143 
   2144   if (FLAG_log_timer_events) {
   2145     FrameScope frame(this, StackFrame::MANUAL);
   2146     PushSafepointRegisters();
   2147     PrepareCallCFunction(1, eax);
   2148     mov(Operand(esp, 0),
   2149         Immediate(ExternalReference::isolate_address(isolate())));
   2150     CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1);
   2151     PopSafepointRegisters();
   2152   }
   2153 
   2154 
   2155   Label profiler_disabled;
   2156   Label end_profiler_check;
   2157   mov(eax, Immediate(ExternalReference::is_profiling_address(isolate())));
   2158   cmpb(Operand(eax, 0), 0);
   2159   j(zero, &profiler_disabled);
   2160 
   2161   // Additional parameter is the address of the actual getter function.
   2162   mov(thunk_last_arg, function_address);
   2163   // Call the api function.
   2164   mov(eax, Immediate(thunk_ref));
   2165   call(eax);
   2166   jmp(&end_profiler_check);
   2167 
   2168   bind(&profiler_disabled);
   2169   // Call the api function.
   2170   call(function_address);
   2171   bind(&end_profiler_check);
   2172 
   2173   if (FLAG_log_timer_events) {
   2174     FrameScope frame(this, StackFrame::MANUAL);
   2175     PushSafepointRegisters();
   2176     PrepareCallCFunction(1, eax);
   2177     mov(Operand(esp, 0),
   2178         Immediate(ExternalReference::isolate_address(isolate())));
   2179     CallCFunction(ExternalReference::log_leave_external_function(isolate()), 1);
   2180     PopSafepointRegisters();
   2181   }
   2182 
   2183   Label prologue;
   2184   // Load the value from ReturnValue
   2185   mov(eax, return_value_operand);
   2186 
   2187   Label promote_scheduled_exception;
   2188   Label exception_handled;
   2189   Label delete_allocated_handles;
   2190   Label leave_exit_frame;
   2191 
   2192   bind(&prologue);
   2193   // No more valid handles (the result handle was the last one). Restore
   2194   // previous handle scope.
   2195   mov(Operand::StaticVariable(next_address), ebx);
   2196   sub(Operand::StaticVariable(level_address), Immediate(1));
   2197   Assert(above_equal, kInvalidHandleScopeLevel);
   2198   cmp(edi, Operand::StaticVariable(limit_address));
   2199   j(not_equal, &delete_allocated_handles);
   2200   bind(&leave_exit_frame);
   2201 
   2202   // Check if the function scheduled an exception.
   2203   ExternalReference scheduled_exception_address =
   2204       ExternalReference::scheduled_exception_address(isolate());
   2205   cmp(Operand::StaticVariable(scheduled_exception_address),
   2206       Immediate(isolate()->factory()->the_hole_value()));
   2207   j(not_equal, &promote_scheduled_exception);
   2208   bind(&exception_handled);
   2209 
   2210 #if ENABLE_EXTRA_CHECKS
   2211   // Check if the function returned a valid JavaScript value.
   2212   Label ok;
   2213   Register return_value = eax;
   2214   Register map = ecx;
   2215 
   2216   JumpIfSmi(return_value, &ok, Label::kNear);
   2217   mov(map, FieldOperand(return_value, HeapObject::kMapOffset));
   2218 
   2219   CmpInstanceType(map, FIRST_NONSTRING_TYPE);
   2220   j(below, &ok, Label::kNear);
   2221 
   2222   CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
   2223   j(above_equal, &ok, Label::kNear);
   2224 
   2225   cmp(map, isolate()->factory()->heap_number_map());
   2226   j(equal, &ok, Label::kNear);
   2227 
   2228   cmp(return_value, isolate()->factory()->undefined_value());
   2229   j(equal, &ok, Label::kNear);
   2230 
   2231   cmp(return_value, isolate()->factory()->true_value());
   2232   j(equal, &ok, Label::kNear);
   2233 
   2234   cmp(return_value, isolate()->factory()->false_value());
   2235   j(equal, &ok, Label::kNear);
   2236 
   2237   cmp(return_value, isolate()->factory()->null_value());
   2238   j(equal, &ok, Label::kNear);
   2239 
   2240   Abort(kAPICallReturnedInvalidObject);
   2241 
   2242   bind(&ok);
   2243 #endif
   2244 
   2245   bool restore_context = context_restore_operand != NULL;
   2246   if (restore_context) {
   2247     mov(esi, *context_restore_operand);
   2248   }
   2249   LeaveApiExitFrame(!restore_context);
   2250   ret(stack_space * kPointerSize);
   2251 
   2252   bind(&promote_scheduled_exception);
   2253   {
   2254     FrameScope frame(this, StackFrame::INTERNAL);
   2255     CallRuntime(Runtime::kHiddenPromoteScheduledException, 0);
   2256   }
   2257   jmp(&exception_handled);
   2258 
   2259   // HandleScope limit has changed. Delete allocated extensions.
   2260   ExternalReference delete_extensions =
   2261       ExternalReference::delete_handle_scope_extensions(isolate());
   2262   bind(&delete_allocated_handles);
   2263   mov(Operand::StaticVariable(limit_address), edi);
   2264   mov(edi, eax);
   2265   mov(Operand(esp, 0),
   2266       Immediate(ExternalReference::isolate_address(isolate())));
   2267   mov(eax, Immediate(delete_extensions));
   2268   call(eax);
   2269   mov(eax, edi);
   2270   jmp(&leave_exit_frame);
   2271 }
   2272 
   2273 
   2274 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext) {
   2275   // Set the entry point and jump to the C entry runtime stub.
   2276   mov(ebx, Immediate(ext));
   2277   CEntryStub ces(isolate(), 1);
   2278   jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
   2279 }
   2280 
   2281 
   2282 void MacroAssembler::InvokePrologue(const ParameterCount& expected,
   2283                                     const ParameterCount& actual,
   2284                                     Handle<Code> code_constant,
   2285                                     const Operand& code_operand,
   2286                                     Label* done,
   2287                                     bool* definitely_mismatches,
   2288                                     InvokeFlag flag,
   2289                                     Label::Distance done_near,
   2290                                     const CallWrapper& call_wrapper) {
   2291   bool definitely_matches = false;
   2292   *definitely_mismatches = false;
   2293   Label invoke;
   2294   if (expected.is_immediate()) {
   2295     ASSERT(actual.is_immediate());
   2296     if (expected.immediate() == actual.immediate()) {
   2297       definitely_matches = true;
   2298     } else {
   2299       mov(eax, actual.immediate());
   2300       const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
   2301       if (expected.immediate() == sentinel) {
   2302         // Don't worry about adapting arguments for builtins that
   2303         // don't want that done. Skip adaption code by making it look
   2304         // like we have a match between expected and actual number of
   2305         // arguments.
   2306         definitely_matches = true;
   2307       } else {
   2308         *definitely_mismatches = true;
   2309         mov(ebx, expected.immediate());
   2310       }
   2311     }
   2312   } else {
   2313     if (actual.is_immediate()) {
   2314       // Expected is in register, actual is immediate. This is the
   2315       // case when we invoke function values without going through the
   2316       // IC mechanism.
   2317       cmp(expected.reg(), actual.immediate());
   2318       j(equal, &invoke);
   2319       ASSERT(expected.reg().is(ebx));
   2320       mov(eax, actual.immediate());
   2321     } else if (!expected.reg().is(actual.reg())) {
   2322       // Both expected and actual are in (different) registers. This
   2323       // is the case when we invoke functions using call and apply.
   2324       cmp(expected.reg(), actual.reg());
   2325       j(equal, &invoke);
   2326       ASSERT(actual.reg().is(eax));
   2327       ASSERT(expected.reg().is(ebx));
   2328     }
   2329   }
   2330 
   2331   if (!definitely_matches) {
   2332     Handle<Code> adaptor =
   2333         isolate()->builtins()->ArgumentsAdaptorTrampoline();
   2334     if (!code_constant.is_null()) {
   2335       mov(edx, Immediate(code_constant));
   2336       add(edx, Immediate(Code::kHeaderSize - kHeapObjectTag));
   2337     } else if (!code_operand.is_reg(edx)) {
   2338       mov(edx, code_operand);
   2339     }
   2340 
   2341     if (flag == CALL_FUNCTION) {
   2342       call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET));
   2343       call(adaptor, RelocInfo::CODE_TARGET);
   2344       call_wrapper.AfterCall();
   2345       if (!*definitely_mismatches) {
   2346         jmp(done, done_near);
   2347       }
   2348     } else {
   2349       jmp(adaptor, RelocInfo::CODE_TARGET);
   2350     }
   2351     bind(&invoke);
   2352   }
   2353 }
   2354 
   2355 
   2356 void MacroAssembler::InvokeCode(const Operand& code,
   2357                                 const ParameterCount& expected,
   2358                                 const ParameterCount& actual,
   2359                                 InvokeFlag flag,
   2360                                 const CallWrapper& call_wrapper) {
   2361   // You can't call a function without a valid frame.
   2362   ASSERT(flag == JUMP_FUNCTION || has_frame());
   2363 
   2364   Label done;
   2365   bool definitely_mismatches = false;
   2366   InvokePrologue(expected, actual, Handle<Code>::null(), code,
   2367                  &done, &definitely_mismatches, flag, Label::kNear,
   2368                  call_wrapper);
   2369   if (!definitely_mismatches) {
   2370     if (flag == CALL_FUNCTION) {
   2371       call_wrapper.BeforeCall(CallSize(code));
   2372       call(code);
   2373       call_wrapper.AfterCall();
   2374     } else {
   2375       ASSERT(flag == JUMP_FUNCTION);
   2376       jmp(code);
   2377     }
   2378     bind(&done);
   2379   }
   2380 }
   2381 
   2382 
   2383 void MacroAssembler::InvokeFunction(Register fun,
   2384                                     const ParameterCount& actual,
   2385                                     InvokeFlag flag,
   2386                                     const CallWrapper& call_wrapper) {
   2387   // You can't call a function without a valid frame.
   2388   ASSERT(flag == JUMP_FUNCTION || has_frame());
   2389 
   2390   ASSERT(fun.is(edi));
   2391   mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
   2392   mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
   2393   mov(ebx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
   2394   SmiUntag(ebx);
   2395 
   2396   ParameterCount expected(ebx);
   2397   InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
   2398              expected, actual, flag, call_wrapper);
   2399 }
   2400 
   2401 
   2402 void MacroAssembler::InvokeFunction(Register fun,
   2403                                     const ParameterCount& expected,
   2404                                     const ParameterCount& actual,
   2405                                     InvokeFlag flag,
   2406                                     const CallWrapper& call_wrapper) {
   2407   // You can't call a function without a valid frame.
   2408   ASSERT(flag == JUMP_FUNCTION || has_frame());
   2409 
   2410   ASSERT(fun.is(edi));
   2411   mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
   2412 
   2413   InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
   2414              expected, actual, flag, call_wrapper);
   2415 }
   2416 
   2417 
   2418 void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
   2419                                     const ParameterCount& expected,
   2420                                     const ParameterCount& actual,
   2421                                     InvokeFlag flag,
   2422                                     const CallWrapper& call_wrapper) {
   2423   LoadHeapObject(edi, function);
   2424   InvokeFunction(edi, expected, actual, flag, call_wrapper);
   2425 }
   2426 
   2427 
   2428 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
   2429                                    InvokeFlag flag,
   2430                                    const CallWrapper& call_wrapper) {
   2431   // You can't call a builtin without a valid frame.
   2432   ASSERT(flag == JUMP_FUNCTION || has_frame());
   2433 
   2434   // Rely on the assertion to check that the number of provided
   2435   // arguments match the expected number of arguments. Fake a
   2436   // parameter count to avoid emitting code to do the check.
   2437   ParameterCount expected(0);
   2438   GetBuiltinFunction(edi, id);
   2439   InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
   2440              expected, expected, flag, call_wrapper);
   2441 }
   2442 
   2443 
   2444 void MacroAssembler::GetBuiltinFunction(Register target,
   2445                                         Builtins::JavaScript id) {
   2446   // Load the JavaScript builtin function from the builtins object.
   2447   mov(target, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
   2448   mov(target, FieldOperand(target, GlobalObject::kBuiltinsOffset));
   2449   mov(target, FieldOperand(target,
   2450                            JSBuiltinsObject::OffsetOfFunctionWithId(id)));
   2451 }
   2452 
   2453 
   2454 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
   2455   ASSERT(!target.is(edi));
   2456   // Load the JavaScript builtin function from the builtins object.
   2457   GetBuiltinFunction(edi, id);
   2458   // Load the code entry point from the function into the target register.
   2459   mov(target, FieldOperand(edi, JSFunction::kCodeEntryOffset));
   2460 }
   2461 
   2462 
   2463 void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
   2464   if (context_chain_length > 0) {
   2465     // Move up the chain of contexts to the context containing the slot.
   2466     mov(dst, Operand(esi, Context::SlotOffset(Context::PREVIOUS_INDEX)));
   2467     for (int i = 1; i < context_chain_length; i++) {
   2468       mov(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
   2469     }
   2470   } else {
   2471     // Slot is in the current function context.  Move it into the
   2472     // destination register in case we store into it (the write barrier
   2473     // cannot be allowed to destroy the context in esi).
   2474     mov(dst, esi);
   2475   }
   2476 
   2477   // We should not have found a with context by walking the context chain
   2478   // (i.e., the static scope chain and runtime context chain do not agree).
   2479   // A variable occurring in such a scope should have slot type LOOKUP and
   2480   // not CONTEXT.
   2481   if (emit_debug_code()) {
   2482     cmp(FieldOperand(dst, HeapObject::kMapOffset),
   2483         isolate()->factory()->with_context_map());
   2484     Check(not_equal, kVariableResolvedToWithContext);
   2485   }
   2486 }
   2487 
   2488 
   2489 void MacroAssembler::LoadTransitionedArrayMapConditional(
   2490     ElementsKind expected_kind,
   2491     ElementsKind transitioned_kind,
   2492     Register map_in_out,
   2493     Register scratch,
   2494     Label* no_map_match) {
   2495   // Load the global or builtins object from the current context.
   2496   mov(scratch, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
   2497   mov(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset));
   2498 
   2499   // Check that the function's map is the same as the expected cached map.
   2500   mov(scratch, Operand(scratch,
   2501                        Context::SlotOffset(Context::JS_ARRAY_MAPS_INDEX)));
   2502 
   2503   size_t offset = expected_kind * kPointerSize +
   2504       FixedArrayBase::kHeaderSize;
   2505   cmp(map_in_out, FieldOperand(scratch, offset));
   2506   j(not_equal, no_map_match);
   2507 
   2508   // Use the transitioned cached map.
   2509   offset = transitioned_kind * kPointerSize +
   2510       FixedArrayBase::kHeaderSize;
   2511   mov(map_in_out, FieldOperand(scratch, offset));
   2512 }
   2513 
   2514 
   2515 void MacroAssembler::LoadGlobalFunction(int index, Register function) {
   2516   // Load the global or builtins object from the current context.
   2517   mov(function,
   2518       Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
   2519   // Load the native context from the global or builtins object.
   2520   mov(function,
   2521       FieldOperand(function, GlobalObject::kNativeContextOffset));
   2522   // Load the function from the native context.
   2523   mov(function, Operand(function, Context::SlotOffset(index)));
   2524 }
   2525 
   2526 
   2527 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
   2528                                                   Register map) {
   2529   // Load the initial map.  The global functions all have initial maps.
   2530   mov(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
   2531   if (emit_debug_code()) {
   2532     Label ok, fail;
   2533     CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK);
   2534     jmp(&ok);
   2535     bind(&fail);
   2536     Abort(kGlobalFunctionsMustHaveInitialMap);
   2537     bind(&ok);
   2538   }
   2539 }
   2540 
   2541 
   2542 // Store the value in register src in the safepoint register stack
   2543 // slot for register dst.
   2544 void MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) {
   2545   mov(SafepointRegisterSlot(dst), src);
   2546 }
   2547 
   2548 
   2549 void MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Immediate src) {
   2550   mov(SafepointRegisterSlot(dst), src);
   2551 }
   2552 
   2553 
   2554 void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
   2555   mov(dst, SafepointRegisterSlot(src));
   2556 }
   2557 
   2558 
   2559 Operand MacroAssembler::SafepointRegisterSlot(Register reg) {
   2560   return Operand(esp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
   2561 }
   2562 
   2563 
   2564 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
   2565   // The registers are pushed starting with the lowest encoding,
   2566   // which means that lowest encodings are furthest away from
   2567   // the stack pointer.
   2568   ASSERT(reg_code >= 0 && reg_code < kNumSafepointRegisters);
   2569   return kNumSafepointRegisters - reg_code - 1;
   2570 }
   2571 
   2572 
   2573 void MacroAssembler::LoadHeapObject(Register result,
   2574                                     Handle<HeapObject> object) {
   2575   AllowDeferredHandleDereference embedding_raw_address;
   2576   if (isolate()->heap()->InNewSpace(*object)) {
   2577     Handle<Cell> cell = isolate()->factory()->NewCell(object);
   2578     mov(result, Operand::ForCell(cell));
   2579   } else {
   2580     mov(result, object);
   2581   }
   2582 }
   2583 
   2584 
   2585 void MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) {
   2586   AllowDeferredHandleDereference using_raw_address;
   2587   if (isolate()->heap()->InNewSpace(*object)) {
   2588     Handle<Cell> cell = isolate()->factory()->NewCell(object);
   2589     cmp(reg, Operand::ForCell(cell));
   2590   } else {
   2591     cmp(reg, object);
   2592   }
   2593 }
   2594 
   2595 
   2596 void MacroAssembler::PushHeapObject(Handle<HeapObject> object) {
   2597   AllowDeferredHandleDereference using_raw_address;
   2598   if (isolate()->heap()->InNewSpace(*object)) {
   2599     Handle<Cell> cell = isolate()->factory()->NewCell(object);
   2600     push(Operand::ForCell(cell));
   2601   } else {
   2602     Push(object);
   2603   }
   2604 }
   2605 
   2606 
   2607 void MacroAssembler::Ret() {
   2608   ret(0);
   2609 }
   2610 
   2611 
   2612 void MacroAssembler::Ret(int bytes_dropped, Register scratch) {
   2613   if (is_uint16(bytes_dropped)) {
   2614     ret(bytes_dropped);
   2615   } else {
   2616     pop(scratch);
   2617     add(esp, Immediate(bytes_dropped));
   2618     push(scratch);
   2619     ret(0);
   2620   }
   2621 }
   2622 
   2623 
   2624 void MacroAssembler::Drop(int stack_elements) {
   2625   if (stack_elements > 0) {
   2626     add(esp, Immediate(stack_elements * kPointerSize));
   2627   }
   2628 }
   2629 
   2630 
   2631 void MacroAssembler::Move(Register dst, Register src) {
   2632   if (!dst.is(src)) {
   2633     mov(dst, src);
   2634   }
   2635 }
   2636 
   2637 
   2638 void MacroAssembler::Move(Register dst, const Immediate& x) {
   2639   if (x.is_zero()) {
   2640     xor_(dst, dst);  // Shorter than mov of 32-bit immediate 0.
   2641   } else {
   2642     mov(dst, x);
   2643   }
   2644 }
   2645 
   2646 
   2647 void MacroAssembler::Move(const Operand& dst, const Immediate& x) {
   2648   mov(dst, x);
   2649 }
   2650 
   2651 
   2652 void MacroAssembler::Move(XMMRegister dst, double val) {
   2653   // TODO(titzer): recognize double constants with ExternalReferences.
   2654   uint64_t int_val = BitCast<uint64_t, double>(val);
   2655   if (int_val == 0) {
   2656     xorps(dst, dst);
   2657   } else {
   2658     int32_t lower = static_cast<int32_t>(int_val);
   2659     int32_t upper = static_cast<int32_t>(int_val >> kBitsPerInt);
   2660     push(Immediate(upper));
   2661     push(Immediate(lower));
   2662     movsd(dst, Operand(esp, 0));
   2663     add(esp, Immediate(kDoubleSize));
   2664   }
   2665 }
   2666 
   2667 
   2668 void MacroAssembler::SetCounter(StatsCounter* counter, int value) {
   2669   if (FLAG_native_code_counters && counter->Enabled()) {
   2670     mov(Operand::StaticVariable(ExternalReference(counter)), Immediate(value));
   2671   }
   2672 }
   2673 
   2674 
   2675 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
   2676   ASSERT(value > 0);
   2677   if (FLAG_native_code_counters && counter->Enabled()) {
   2678     Operand operand = Operand::StaticVariable(ExternalReference(counter));
   2679     if (value == 1) {
   2680       inc(operand);
   2681     } else {
   2682       add(operand, Immediate(value));
   2683     }
   2684   }
   2685 }
   2686 
   2687 
   2688 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
   2689   ASSERT(value > 0);
   2690   if (FLAG_native_code_counters && counter->Enabled()) {
   2691     Operand operand = Operand::StaticVariable(ExternalReference(counter));
   2692     if (value == 1) {
   2693       dec(operand);
   2694     } else {
   2695       sub(operand, Immediate(value));
   2696     }
   2697   }
   2698 }
   2699 
   2700 
   2701 void MacroAssembler::IncrementCounter(Condition cc,
   2702                                       StatsCounter* counter,
   2703                                       int value) {
   2704   ASSERT(value > 0);
   2705   if (FLAG_native_code_counters && counter->Enabled()) {
   2706     Label skip;
   2707     j(NegateCondition(cc), &skip);
   2708     pushfd();
   2709     IncrementCounter(counter, value);
   2710     popfd();
   2711     bind(&skip);
   2712   }
   2713 }
   2714 
   2715 
   2716 void MacroAssembler::DecrementCounter(Condition cc,
   2717                                       StatsCounter* counter,
   2718                                       int value) {
   2719   ASSERT(value > 0);
   2720   if (FLAG_native_code_counters && counter->Enabled()) {
   2721     Label skip;
   2722     j(NegateCondition(cc), &skip);
   2723     pushfd();
   2724     DecrementCounter(counter, value);
   2725     popfd();
   2726     bind(&skip);
   2727   }
   2728 }
   2729 
   2730 
   2731 void MacroAssembler::Assert(Condition cc, BailoutReason reason) {
   2732   if (emit_debug_code()) Check(cc, reason);
   2733 }
   2734 
   2735 
   2736 void MacroAssembler::AssertFastElements(Register elements) {
   2737   if (emit_debug_code()) {
   2738     Factory* factory = isolate()->factory();
   2739     Label ok;
   2740     cmp(FieldOperand(elements, HeapObject::kMapOffset),
   2741         Immediate(factory->fixed_array_map()));
   2742     j(equal, &ok);
   2743     cmp(FieldOperand(elements, HeapObject::kMapOffset),
   2744         Immediate(factory->fixed_double_array_map()));
   2745     j(equal, &ok);
   2746     cmp(FieldOperand(elements, HeapObject::kMapOffset),
   2747         Immediate(factory->fixed_cow_array_map()));
   2748     j(equal, &ok);
   2749     Abort(kJSObjectWithFastElementsMapHasSlowElements);
   2750     bind(&ok);
   2751   }
   2752 }
   2753 
   2754 
   2755 void MacroAssembler::Check(Condition cc, BailoutReason reason) {
   2756   Label L;
   2757   j(cc, &L);
   2758   Abort(reason);
   2759   // will not return here
   2760   bind(&L);
   2761 }
   2762 
   2763 
   2764 void MacroAssembler::CheckStackAlignment() {
   2765   int frame_alignment = OS::ActivationFrameAlignment();
   2766   int frame_alignment_mask = frame_alignment - 1;
   2767   if (frame_alignment > kPointerSize) {
   2768     ASSERT(IsPowerOf2(frame_alignment));
   2769     Label alignment_as_expected;
   2770     test(esp, Immediate(frame_alignment_mask));
   2771     j(zero, &alignment_as_expected);
   2772     // Abort if stack is not aligned.
   2773     int3();
   2774     bind(&alignment_as_expected);
   2775   }
   2776 }
   2777 
   2778 
   2779 void MacroAssembler::Abort(BailoutReason reason) {
   2780 #ifdef DEBUG
   2781   const char* msg = GetBailoutReason(reason);
   2782   if (msg != NULL) {
   2783     RecordComment("Abort message: ");
   2784     RecordComment(msg);
   2785   }
   2786 
   2787   if (FLAG_trap_on_abort) {
   2788     int3();
   2789     return;
   2790   }
   2791 #endif
   2792 
   2793   push(Immediate(reinterpret_cast<intptr_t>(Smi::FromInt(reason))));
   2794   // Disable stub call restrictions to always allow calls to abort.
   2795   if (!has_frame_) {
   2796     // We don't actually want to generate a pile of code for this, so just
   2797     // claim there is a stack frame, without generating one.
   2798     FrameScope scope(this, StackFrame::NONE);
   2799     CallRuntime(Runtime::kAbort, 1);
   2800   } else {
   2801     CallRuntime(Runtime::kAbort, 1);
   2802   }
   2803   // will not return here
   2804   int3();
   2805 }
   2806 
   2807 
   2808 void MacroAssembler::LoadInstanceDescriptors(Register map,
   2809                                              Register descriptors) {
   2810   mov(descriptors, FieldOperand(map, Map::kDescriptorsOffset));
   2811 }
   2812 
   2813 
   2814 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
   2815   mov(dst, FieldOperand(map, Map::kBitField3Offset));
   2816   DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
   2817 }
   2818 
   2819 
   2820 void MacroAssembler::LoadPowerOf2(XMMRegister dst,
   2821                                   Register scratch,
   2822                                   int power) {
   2823   ASSERT(is_uintn(power + HeapNumber::kExponentBias,
   2824                   HeapNumber::kExponentBits));
   2825   mov(scratch, Immediate(power + HeapNumber::kExponentBias));
   2826   movd(dst, scratch);
   2827   psllq(dst, HeapNumber::kMantissaBits);
   2828 }
   2829 
   2830 
   2831 void MacroAssembler::LookupNumberStringCache(Register object,
   2832                                              Register result,
   2833                                              Register scratch1,
   2834                                              Register scratch2,
   2835                                              Label* not_found) {
   2836   // Use of registers. Register result is used as a temporary.
   2837   Register number_string_cache = result;
   2838   Register mask = scratch1;
   2839   Register scratch = scratch2;
   2840 
   2841   // Load the number string cache.
   2842   LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
   2843   // Make the hash mask from the length of the number string cache. It
   2844   // contains two elements (number and string) for each cache entry.
   2845   mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset));
   2846   shr(mask, kSmiTagSize + 1);  // Untag length and divide it by two.
   2847   sub(mask, Immediate(1));  // Make mask.
   2848 
   2849   // Calculate the entry in the number string cache. The hash value in the
   2850   // number string cache for smis is just the smi value, and the hash for
   2851   // doubles is the xor of the upper and lower words. See
   2852   // Heap::GetNumberStringCache.
   2853   Label smi_hash_calculated;
   2854   Label load_result_from_cache;
   2855   Label not_smi;
   2856   STATIC_ASSERT(kSmiTag == 0);
   2857   JumpIfNotSmi(object, &not_smi, Label::kNear);
   2858   mov(scratch, object);
   2859   SmiUntag(scratch);
   2860   jmp(&smi_hash_calculated, Label::kNear);
   2861   bind(&not_smi);
   2862   cmp(FieldOperand(object, HeapObject::kMapOffset),
   2863       isolate()->factory()->heap_number_map());
   2864   j(not_equal, not_found);
   2865   STATIC_ASSERT(8 == kDoubleSize);
   2866   mov(scratch, FieldOperand(object, HeapNumber::kValueOffset));
   2867   xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4));
   2868   // Object is heap number and hash is now in scratch. Calculate cache index.
   2869   and_(scratch, mask);
   2870   Register index = scratch;
   2871   Register probe = mask;
   2872   mov(probe,
   2873       FieldOperand(number_string_cache,
   2874                    index,
   2875                    times_twice_pointer_size,
   2876                    FixedArray::kHeaderSize));
   2877   JumpIfSmi(probe, not_found);
   2878   movsd(xmm0, FieldOperand(object, HeapNumber::kValueOffset));
   2879   ucomisd(xmm0, FieldOperand(probe, HeapNumber::kValueOffset));
   2880   j(parity_even, not_found);  // Bail out if NaN is involved.
   2881   j(not_equal, not_found);  // The cache did not contain this value.
   2882   jmp(&load_result_from_cache, Label::kNear);
   2883 
   2884   bind(&smi_hash_calculated);
   2885   // Object is smi and hash is now in scratch. Calculate cache index.
   2886   and_(scratch, mask);
   2887   // Check if the entry is the smi we are looking for.
   2888   cmp(object,
   2889       FieldOperand(number_string_cache,
   2890                    index,
   2891                    times_twice_pointer_size,
   2892                    FixedArray::kHeaderSize));
   2893   j(not_equal, not_found);
   2894 
   2895   // Get the result from the cache.
   2896   bind(&load_result_from_cache);
   2897   mov(result,
   2898       FieldOperand(number_string_cache,
   2899                    index,
   2900                    times_twice_pointer_size,
   2901                    FixedArray::kHeaderSize + kPointerSize));
   2902   IncrementCounter(isolate()->counters()->number_to_string_native(), 1);
   2903 }
   2904 
   2905 
   2906 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(
   2907     Register instance_type,
   2908     Register scratch,
   2909     Label* failure) {
   2910   if (!scratch.is(instance_type)) {
   2911     mov(scratch, instance_type);
   2912   }
   2913   and_(scratch,
   2914        kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask);
   2915   cmp(scratch, kStringTag | kSeqStringTag | kOneByteStringTag);
   2916   j(not_equal, failure);
   2917 }
   2918 
   2919 
   2920 void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register object1,
   2921                                                          Register object2,
   2922                                                          Register scratch1,
   2923                                                          Register scratch2,
   2924                                                          Label* failure) {
   2925   // Check that both objects are not smis.
   2926   STATIC_ASSERT(kSmiTag == 0);
   2927   mov(scratch1, object1);
   2928   and_(scratch1, object2);
   2929   JumpIfSmi(scratch1, failure);
   2930 
   2931   // Load instance type for both strings.
   2932   mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset));
   2933   mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset));
   2934   movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
   2935   movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
   2936 
   2937   // Check that both are flat ASCII strings.
   2938   const int kFlatAsciiStringMask =
   2939       kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
   2940   const int kFlatAsciiStringTag =
   2941       kStringTag | kOneByteStringTag | kSeqStringTag;
   2942   // Interleave bits from both instance types and compare them in one check.
   2943   ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3));
   2944   and_(scratch1, kFlatAsciiStringMask);
   2945   and_(scratch2, kFlatAsciiStringMask);
   2946   lea(scratch1, Operand(scratch1, scratch2, times_8, 0));
   2947   cmp(scratch1, kFlatAsciiStringTag | (kFlatAsciiStringTag << 3));
   2948   j(not_equal, failure);
   2949 }
   2950 
   2951 
   2952 void MacroAssembler::JumpIfNotUniqueName(Operand operand,
   2953                                          Label* not_unique_name,
   2954                                          Label::Distance distance) {
   2955   STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
   2956   Label succeed;
   2957   test(operand, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
   2958   j(zero, &succeed);
   2959   cmpb(operand, static_cast<uint8_t>(SYMBOL_TYPE));
   2960   j(not_equal, not_unique_name, distance);
   2961 
   2962   bind(&succeed);
   2963 }
   2964 
   2965 
   2966 void MacroAssembler::EmitSeqStringSetCharCheck(Register string,
   2967                                                Register index,
   2968                                                Register value,
   2969                                                uint32_t encoding_mask) {
   2970   Label is_object;
   2971   JumpIfNotSmi(string, &is_object, Label::kNear);
   2972   Abort(kNonObject);
   2973   bind(&is_object);
   2974 
   2975   push(value);
   2976   mov(value, FieldOperand(string, HeapObject::kMapOffset));
   2977   movzx_b(value, FieldOperand(value, Map::kInstanceTypeOffset));
   2978 
   2979   and_(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
   2980   cmp(value, Immediate(encoding_mask));
   2981   pop(value);
   2982   Check(equal, kUnexpectedStringType);
   2983 
   2984   // The index is assumed to be untagged coming in, tag it to compare with the
   2985   // string length without using a temp register, it is restored at the end of
   2986   // this function.
   2987   SmiTag(index);
   2988   Check(no_overflow, kIndexIsTooLarge);
   2989 
   2990   cmp(index, FieldOperand(string, String::kLengthOffset));
   2991   Check(less, kIndexIsTooLarge);
   2992 
   2993   cmp(index, Immediate(Smi::FromInt(0)));
   2994   Check(greater_equal, kIndexIsNegative);
   2995 
   2996   // Restore the index
   2997   SmiUntag(index);
   2998 }
   2999 
   3000 
   3001 void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
   3002   int frame_alignment = OS::ActivationFrameAlignment();
   3003   if (frame_alignment != 0) {
   3004     // Make stack end at alignment and make room for num_arguments words
   3005     // and the original value of esp.
   3006     mov(scratch, esp);
   3007     sub(esp, Immediate((num_arguments + 1) * kPointerSize));
   3008     ASSERT(IsPowerOf2(frame_alignment));
   3009     and_(esp, -frame_alignment);
   3010     mov(Operand(esp, num_arguments * kPointerSize), scratch);
   3011   } else {
   3012     sub(esp, Immediate(num_arguments * kPointerSize));
   3013   }
   3014 }
   3015 
   3016 
   3017 void MacroAssembler::CallCFunction(ExternalReference function,
   3018                                    int num_arguments) {
   3019   // Trashing eax is ok as it will be the return value.
   3020   mov(eax, Immediate(function));
   3021   CallCFunction(eax, num_arguments);
   3022 }
   3023 
   3024 
   3025 void MacroAssembler::CallCFunction(Register function,
   3026                                    int num_arguments) {
   3027   ASSERT(has_frame());
   3028   // Check stack alignment.
   3029   if (emit_debug_code()) {
   3030     CheckStackAlignment();
   3031   }
   3032 
   3033   call(function);
   3034   if (OS::ActivationFrameAlignment() != 0) {
   3035     mov(esp, Operand(esp, num_arguments * kPointerSize));
   3036   } else {
   3037     add(esp, Immediate(num_arguments * kPointerSize));
   3038   }
   3039 }
   3040 
   3041 
   3042 bool AreAliased(Register r1, Register r2, Register r3, Register r4) {
   3043   if (r1.is(r2)) return true;
   3044   if (r1.is(r3)) return true;
   3045   if (r1.is(r4)) return true;
   3046   if (r2.is(r3)) return true;
   3047   if (r2.is(r4)) return true;
   3048   if (r3.is(r4)) return true;
   3049   return false;
   3050 }
   3051 
   3052 
   3053 CodePatcher::CodePatcher(byte* address, int size)
   3054     : address_(address),
   3055       size_(size),
   3056       masm_(NULL, address, size + Assembler::kGap) {
   3057   // Create a new macro assembler pointing to the address of the code to patch.
   3058   // The size is adjusted with kGap on order for the assembler to generate size
   3059   // bytes of instructions without failing with buffer size constraints.
   3060   ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
   3061 }
   3062 
   3063 
   3064 CodePatcher::~CodePatcher() {
   3065   // Indicate that code has changed.
   3066   CPU::FlushICache(address_, size_);
   3067 
   3068   // Check that the code was patched as expected.
   3069   ASSERT(masm_.pc_ == address_ + size_);
   3070   ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
   3071 }
   3072 
   3073 
   3074 void MacroAssembler::CheckPageFlag(
   3075     Register object,
   3076     Register scratch,
   3077     int mask,
   3078     Condition cc,
   3079     Label* condition_met,
   3080     Label::Distance condition_met_distance) {
   3081   ASSERT(cc == zero || cc == not_zero);
   3082   if (scratch.is(object)) {
   3083     and_(scratch, Immediate(~Page::kPageAlignmentMask));
   3084   } else {
   3085     mov(scratch, Immediate(~Page::kPageAlignmentMask));
   3086     and_(scratch, object);
   3087   }
   3088   if (mask < (1 << kBitsPerByte)) {
   3089     test_b(Operand(scratch, MemoryChunk::kFlagsOffset),
   3090            static_cast<uint8_t>(mask));
   3091   } else {
   3092     test(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
   3093   }
   3094   j(cc, condition_met, condition_met_distance);
   3095 }
   3096 
   3097 
   3098 void MacroAssembler::CheckPageFlagForMap(
   3099     Handle<Map> map,
   3100     int mask,
   3101     Condition cc,
   3102     Label* condition_met,
   3103     Label::Distance condition_met_distance) {
   3104   ASSERT(cc == zero || cc == not_zero);
   3105   Page* page = Page::FromAddress(map->address());
   3106   ExternalReference reference(ExternalReference::page_flags(page));
   3107   // The inlined static address check of the page's flags relies
   3108   // on maps never being compacted.
   3109   ASSERT(!isolate()->heap()->mark_compact_collector()->
   3110          IsOnEvacuationCandidate(*map));
   3111   if (mask < (1 << kBitsPerByte)) {
   3112     test_b(Operand::StaticVariable(reference), static_cast<uint8_t>(mask));
   3113   } else {
   3114     test(Operand::StaticVariable(reference), Immediate(mask));
   3115   }
   3116   j(cc, condition_met, condition_met_distance);
   3117 }
   3118 
   3119 
   3120 void MacroAssembler::CheckMapDeprecated(Handle<Map> map,
   3121                                         Register scratch,
   3122                                         Label* if_deprecated) {
   3123   if (map->CanBeDeprecated()) {
   3124     mov(scratch, map);
   3125     mov(scratch, FieldOperand(scratch, Map::kBitField3Offset));
   3126     and_(scratch, Immediate(Map::Deprecated::kMask));
   3127     j(not_zero, if_deprecated);
   3128   }
   3129 }
   3130 
   3131 
   3132 void MacroAssembler::JumpIfBlack(Register object,
   3133                                  Register scratch0,
   3134                                  Register scratch1,
   3135                                  Label* on_black,
   3136                                  Label::Distance on_black_near) {
   3137   HasColor(object, scratch0, scratch1,
   3138            on_black, on_black_near,
   3139            1, 0);  // kBlackBitPattern.
   3140   ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0);
   3141 }
   3142 
   3143 
   3144 void MacroAssembler::HasColor(Register object,
   3145                               Register bitmap_scratch,
   3146                               Register mask_scratch,
   3147                               Label* has_color,
   3148                               Label::Distance has_color_distance,
   3149                               int first_bit,
   3150                               int second_bit) {
   3151   ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, ecx));
   3152 
   3153   GetMarkBits(object, bitmap_scratch, mask_scratch);
   3154 
   3155   Label other_color, word_boundary;
   3156   test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
   3157   j(first_bit == 1 ? zero : not_zero, &other_color, Label::kNear);
   3158   add(mask_scratch, mask_scratch);  // Shift left 1 by adding.
   3159   j(zero, &word_boundary, Label::kNear);
   3160   test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
   3161   j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
   3162   jmp(&other_color, Label::kNear);
   3163 
   3164   bind(&word_boundary);
   3165   test_b(Operand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize), 1);
   3166 
   3167   j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
   3168   bind(&other_color);
   3169 }
   3170 
   3171 
   3172 void MacroAssembler::GetMarkBits(Register addr_reg,
   3173                                  Register bitmap_reg,
   3174                                  Register mask_reg) {
   3175   ASSERT(!AreAliased(addr_reg, mask_reg, bitmap_reg, ecx));
   3176   mov(bitmap_reg, Immediate(~Page::kPageAlignmentMask));
   3177   and_(bitmap_reg, addr_reg);
   3178   mov(ecx, addr_reg);
   3179   int shift =
   3180       Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2;
   3181   shr(ecx, shift);
   3182   and_(ecx,
   3183        (Page::kPageAlignmentMask >> shift) & ~(Bitmap::kBytesPerCell - 1));
   3184 
   3185   add(bitmap_reg, ecx);
   3186   mov(ecx, addr_reg);
   3187   shr(ecx, kPointerSizeLog2);
   3188   and_(ecx, (1 << Bitmap::kBitsPerCellLog2) - 1);
   3189   mov(mask_reg, Immediate(1));
   3190   shl_cl(mask_reg);
   3191 }
   3192 
   3193 
   3194 void MacroAssembler::EnsureNotWhite(
   3195     Register value,
   3196     Register bitmap_scratch,
   3197     Register mask_scratch,
   3198     Label* value_is_white_and_not_data,
   3199     Label::Distance distance) {
   3200   ASSERT(!AreAliased(value, bitmap_scratch, mask_scratch, ecx));
   3201   GetMarkBits(value, bitmap_scratch, mask_scratch);
   3202 
   3203   // If the value is black or grey we don't need to do anything.
   3204   ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0);
   3205   ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0);
   3206   ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0);
   3207   ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
   3208 
   3209   Label done;
   3210 
   3211   // Since both black and grey have a 1 in the first position and white does
   3212   // not have a 1 there we only need to check one bit.
   3213   test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
   3214   j(not_zero, &done, Label::kNear);
   3215 
   3216   if (emit_debug_code()) {
   3217     // Check for impossible bit pattern.
   3218     Label ok;
   3219     push(mask_scratch);
   3220     // shl.  May overflow making the check conservative.
   3221     add(mask_scratch, mask_scratch);
   3222     test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
   3223     j(zero, &ok, Label::kNear);
   3224     int3();
   3225     bind(&ok);
   3226     pop(mask_scratch);
   3227   }
   3228 
   3229   // Value is white.  We check whether it is data that doesn't need scanning.
   3230   // Currently only checks for HeapNumber and non-cons strings.
   3231   Register map = ecx;  // Holds map while checking type.
   3232   Register length = ecx;  // Holds length of object after checking type.
   3233   Label not_heap_number;
   3234   Label is_data_object;
   3235 
   3236   // Check for heap-number
   3237   mov(map, FieldOperand(value, HeapObject::kMapOffset));
   3238   cmp(map, isolate()->factory()->heap_number_map());
   3239   j(not_equal, &not_heap_number, Label::kNear);
   3240   mov(length, Immediate(HeapNumber::kSize));
   3241   jmp(&is_data_object, Label::kNear);
   3242 
   3243   bind(&not_heap_number);
   3244   // Check for strings.
   3245   ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
   3246   ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
   3247   // If it's a string and it's not a cons string then it's an object containing
   3248   // no GC pointers.
   3249   Register instance_type = ecx;
   3250   movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
   3251   test_b(instance_type, kIsIndirectStringMask | kIsNotStringMask);
   3252   j(not_zero, value_is_white_and_not_data);
   3253   // It's a non-indirect (non-cons and non-slice) string.
   3254   // If it's external, the length is just ExternalString::kSize.
   3255   // Otherwise it's String::kHeaderSize + string->length() * (1 or 2).
   3256   Label not_external;
   3257   // External strings are the only ones with the kExternalStringTag bit
   3258   // set.
   3259   ASSERT_EQ(0, kSeqStringTag & kExternalStringTag);
   3260   ASSERT_EQ(0, kConsStringTag & kExternalStringTag);
   3261   test_b(instance_type, kExternalStringTag);
   3262   j(zero, &not_external, Label::kNear);
   3263   mov(length, Immediate(ExternalString::kSize));
   3264   jmp(&is_data_object, Label::kNear);
   3265 
   3266   bind(&not_external);
   3267   // Sequential string, either ASCII or UC16.
   3268   ASSERT(kOneByteStringTag == 0x04);
   3269   and_(length, Immediate(kStringEncodingMask));
   3270   xor_(length, Immediate(kStringEncodingMask));
   3271   add(length, Immediate(0x04));
   3272   // Value now either 4 (if ASCII) or 8 (if UC16), i.e., char-size shifted
   3273   // by 2. If we multiply the string length as smi by this, it still
   3274   // won't overflow a 32-bit value.
   3275   ASSERT_EQ(SeqOneByteString::kMaxSize, SeqTwoByteString::kMaxSize);
   3276   ASSERT(SeqOneByteString::kMaxSize <=
   3277          static_cast<int>(0xffffffffu >> (2 + kSmiTagSize)));
   3278   imul(length, FieldOperand(value, String::kLengthOffset));
   3279   shr(length, 2 + kSmiTagSize + kSmiShiftSize);
   3280   add(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask));
   3281   and_(length, Immediate(~kObjectAlignmentMask));
   3282 
   3283   bind(&is_data_object);
   3284   // Value is a data object, and it is white.  Mark it black.  Since we know
   3285   // that the object is white we can make it black by flipping one bit.
   3286   or_(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch);
   3287 
   3288   and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask));
   3289   add(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset),
   3290       length);
   3291   if (emit_debug_code()) {
   3292     mov(length, Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
   3293     cmp(length, Operand(bitmap_scratch, MemoryChunk::kSizeOffset));
   3294     Check(less_equal, kLiveBytesCountOverflowChunkSize);
   3295   }
   3296 
   3297   bind(&done);
   3298 }
   3299 
   3300 
   3301 void MacroAssembler::EnumLength(Register dst, Register map) {
   3302   STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
   3303   mov(dst, FieldOperand(map, Map::kBitField3Offset));
   3304   and_(dst, Immediate(Map::EnumLengthBits::kMask));
   3305   SmiTag(dst);
   3306 }
   3307 
   3308 
   3309 void MacroAssembler::CheckEnumCache(Label* call_runtime) {
   3310   Label next, start;
   3311   mov(ecx, eax);
   3312 
   3313   // Check if the enum length field is properly initialized, indicating that
   3314   // there is an enum cache.
   3315   mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
   3316 
   3317   EnumLength(edx, ebx);
   3318   cmp(edx, Immediate(Smi::FromInt(kInvalidEnumCacheSentinel)));
   3319   j(equal, call_runtime);
   3320 
   3321   jmp(&start);
   3322 
   3323   bind(&next);
   3324   mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
   3325 
   3326   // For all objects but the receiver, check that the cache is empty.
   3327   EnumLength(edx, ebx);
   3328   cmp(edx, Immediate(Smi::FromInt(0)));
   3329   j(not_equal, call_runtime);
   3330 
   3331   bind(&start);
   3332 
   3333   // Check that there are no elements. Register rcx contains the current JS
   3334   // object we've reached through the prototype chain.
   3335   Label no_elements;
   3336   mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
   3337   cmp(ecx, isolate()->factory()->empty_fixed_array());
   3338   j(equal, &no_elements);
   3339 
   3340   // Second chance, the object may be using the empty slow element dictionary.
   3341   cmp(ecx, isolate()->factory()->empty_slow_element_dictionary());
   3342   j(not_equal, call_runtime);
   3343 
   3344   bind(&no_elements);
   3345   mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
   3346   cmp(ecx, isolate()->factory()->null_value());
   3347   j(not_equal, &next);
   3348 }
   3349 
   3350 
   3351 void MacroAssembler::TestJSArrayForAllocationMemento(
   3352     Register receiver_reg,
   3353     Register scratch_reg,
   3354     Label* no_memento_found) {
   3355   ExternalReference new_space_start =
   3356       ExternalReference::new_space_start(isolate());
   3357   ExternalReference new_space_allocation_top =
   3358       ExternalReference::new_space_allocation_top_address(isolate());
   3359 
   3360   lea(scratch_reg, Operand(receiver_reg,
   3361       JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag));
   3362   cmp(scratch_reg, Immediate(new_space_start));
   3363   j(less, no_memento_found);
   3364   cmp(scratch_reg, Operand::StaticVariable(new_space_allocation_top));
   3365   j(greater, no_memento_found);
   3366   cmp(MemOperand(scratch_reg, -AllocationMemento::kSize),
   3367       Immediate(isolate()->factory()->allocation_memento_map()));
   3368 }
   3369 
   3370 
   3371 void MacroAssembler::JumpIfDictionaryInPrototypeChain(
   3372     Register object,
   3373     Register scratch0,
   3374     Register scratch1,
   3375     Label* found) {
   3376   ASSERT(!scratch1.is(scratch0));
   3377   Factory* factory = isolate()->factory();
   3378   Register current = scratch0;
   3379   Label loop_again;
   3380 
   3381   // scratch contained elements pointer.
   3382   mov(current, object);
   3383 
   3384   // Loop based on the map going up the prototype chain.
   3385   bind(&loop_again);
   3386   mov(current, FieldOperand(current, HeapObject::kMapOffset));
   3387   mov(scratch1, FieldOperand(current, Map::kBitField2Offset));
   3388   DecodeField<Map::ElementsKindBits>(scratch1);
   3389   cmp(scratch1, Immediate(DICTIONARY_ELEMENTS));
   3390   j(equal, found);
   3391   mov(current, FieldOperand(current, Map::kPrototypeOffset));
   3392   cmp(current, Immediate(factory->null_value()));
   3393   j(not_equal, &loop_again);
   3394 }
   3395 
   3396 
   3397 void MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) {
   3398   ASSERT(!dividend.is(eax));
   3399   ASSERT(!dividend.is(edx));
   3400   MultiplierAndShift ms(divisor);
   3401   mov(eax, Immediate(ms.multiplier()));
   3402   imul(dividend);
   3403   if (divisor > 0 && ms.multiplier() < 0) add(edx, dividend);
   3404   if (divisor < 0 && ms.multiplier() > 0) sub(edx, dividend);
   3405   if (ms.shift() > 0) sar(edx, ms.shift());
   3406   mov(eax, dividend);
   3407   shr(eax, 31);
   3408   add(edx, eax);
   3409 }
   3410 
   3411 
   3412 } }  // namespace v8::internal
   3413 
   3414 #endif  // V8_TARGET_ARCH_IA32
   3415