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