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