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