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