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