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