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