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